root/chrome/browser/notifications/sync_notifier/synced_notification_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. UseRichNotifications
  2. SetUp
  3. TearDown
  4. AddButtonBitmaps
  5. notification_manager
  6. TEST_F
  7. TEST_F
  8. TEST_F
  9. TEST_F
  10. TEST_F
  11. TEST_F
  12. TEST_F
  13. TEST_F
  14. TEST_F
  15. TEST_F
  16. TEST_F
  17. TEST_F
  18. TEST_F
  19. TEST_F
  20. TEST_F
  21. TEST_F
  22. TEST_F
  23. TEST_F
  24. TEST_F
  25. TEST_F
  26. TEST_F
  27. TEST_F
  28. TEST_F

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_test_util.h"
#include "chrome/browser/notifications/notification_ui_manager.h"
#include "chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h"
#include "chrome/browser/notifications/sync_notifier/synced_notification.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/message_center/message_center_util.h"
#include "ui/message_center/notification_types.h"

using syncer::SyncData;
using notifier::SyncedNotification;
using sync_pb::EntitySpecifics;
using sync_pb::SyncedNotificationSpecifics;

namespace {
const int kNotificationPriority = static_cast<int>(
    message_center::LOW_PRIORITY);

bool UseRichNotifications() {
  return message_center::IsRichNotificationEnabled();
}

}  // namespace

namespace notifier {

class SyncedNotificationTest : public testing::Test {
 public:
  SyncedNotificationTest()
      : ui_thread_(content::BrowserThread::UI, &message_loop_) {}
  virtual ~SyncedNotificationTest() {}

  // Methods from testing::Test.

  virtual void SetUp() OVERRIDE {
    notification_manager_.reset(new StubNotificationUIManager(GURL(
        kSyncedNotificationsWelcomeOrigin)));

    sync_data1_ = CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
                                 kAppId1, kKey1, kUnread);
    sync_data2_ = CreateSyncData(kTitle2, kText2, kIconUrl2, kImageUrl2,
                                 kAppId2, kKey2, kUnread);
    // Notification 3 will have the same ID as notification1, but different
    // data inside.
    sync_data3_ = CreateSyncData(kTitle3, kText3, kIconUrl3, kImageUrl3,
                                 kAppId1, kKey1, kUnread);
    // Notification 4 will be the same as 1, but the read state will be 'read'.
    sync_data4_ = CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
                                 kAppId1, kKey1, kDismissed);

    notification1_.reset(new SyncedNotification(
        sync_data1_, NULL, notification_manager_.get()));
    notification2_.reset(new SyncedNotification(
        sync_data2_, NULL, notification_manager_.get()));
    notification3_.reset(new SyncedNotification(
        sync_data3_, NULL, notification_manager_.get()));
    notification4_.reset(new SyncedNotification(
        sync_data4_, NULL, notification_manager_.get()));

  }

  virtual void TearDown() OVERRIDE {
    notification_manager_.reset();
  }

  virtual void AddButtonBitmaps(SyncedNotification* notification,
                                unsigned int how_many) {
    for (unsigned int i = 0; i < how_many; ++i) {
      notification->button_bitmaps_.push_back(gfx::Image());
      notification->button_bitmaps_fetch_pending_.push_back(true);
    }
  }

  StubNotificationUIManager* notification_manager() {
    return notification_manager_.get();
  }

  scoped_ptr<SyncedNotification> notification1_;
  scoped_ptr<SyncedNotification> notification2_;
  scoped_ptr<SyncedNotification> notification3_;
  scoped_ptr<SyncedNotification> notification4_;
  syncer::SyncData sync_data1_;
  syncer::SyncData sync_data2_;
  syncer::SyncData sync_data3_;
  syncer::SyncData sync_data4_;

 private:
  base::MessageLoopForIO message_loop_;
  content::TestBrowserThread ui_thread_;
  scoped_ptr<StubNotificationUIManager> notification_manager_;

  DISALLOW_COPY_AND_ASSIGN(SyncedNotificationTest);
};

// test simple accessors

TEST_F(SyncedNotificationTest, GetAppIdTest) {
  std::string found_app_id = notification1_->GetAppId();
  std::string expected_app_id(kAppId1);

  EXPECT_EQ(found_app_id, expected_app_id);
}

TEST_F(SyncedNotificationTest, GetKeyTest) {
  std::string found_key = notification1_->GetKey();
  std::string expected_key(kKey1);

  EXPECT_EQ(expected_key, found_key);
}

TEST_F(SyncedNotificationTest, GetTitleTest) {
  std::string found_title = notification1_->GetTitle();
  std::string expected_title(kTitle1);

  EXPECT_EQ(expected_title, found_title);
}

TEST_F(SyncedNotificationTest, GetIconURLTest) {
  std::string found_icon_url = notification1_->GetAppIconUrl().spec();
  std::string expected_icon_url(kIconUrl1);

  EXPECT_EQ(expected_icon_url, found_icon_url);
}

TEST_F(SyncedNotificationTest, GetReadStateTest) {
  SyncedNotification::ReadState found_state1 =
      notification1_->GetReadState();
  SyncedNotification::ReadState expected_state1(SyncedNotification::kUnread);

  EXPECT_EQ(expected_state1, found_state1);

  SyncedNotification::ReadState found_state2 =
      notification4_->GetReadState();
  SyncedNotification::ReadState expected_state2(SyncedNotification::kDismissed);

  EXPECT_EQ(expected_state2, found_state2);
}

// TODO(petewil): Improve ctor to pass in an image and type so this test can
// pass on actual data.
TEST_F(SyncedNotificationTest, GetImageURLTest) {
  GURL found_image_url = notification1_->GetImageUrl();
  GURL expected_image_url = GURL(kImageUrl1);

  EXPECT_EQ(expected_image_url, found_image_url);
}

TEST_F(SyncedNotificationTest, GetTextTest) {
  std::string found_text = notification1_->GetText();
  std::string expected_text(kText1);

  EXPECT_EQ(expected_text, found_text);
}

TEST_F(SyncedNotificationTest, GetCreationTimeTest) {
  uint64 found_time = notification1_->GetCreationTime();
  EXPECT_EQ(kFakeCreationTime, found_time);
}

TEST_F(SyncedNotificationTest, GetPriorityTest) {
  double found_priority = notification1_->GetPriority();
  EXPECT_EQ(static_cast<double>(kNotificationPriority), found_priority);
}

TEST_F(SyncedNotificationTest, GetButtonCountTest) {
  int found_button_count = notification1_->GetButtonCount();
  EXPECT_EQ(2, found_button_count);
}

TEST_F(SyncedNotificationTest, GetNotificationCountTest) {
  int found_notification_count = notification1_->GetNotificationCount();
  EXPECT_EQ(3, found_notification_count);
}

TEST_F(SyncedNotificationTest, GetDefaultDestinationDataTest) {
    std::string default_destination_title =
        notification1_->GetDefaultDestinationTitle();
    GURL default_destination_icon_url =
        notification1_->GetDefaultDestinationIconUrl();
    GURL default_destination_url =
        notification1_->GetDefaultDestinationUrl();
    EXPECT_EQ(std::string(kDefaultDestinationTitle), default_destination_title);
    EXPECT_EQ(GURL(kDefaultDestinationIconUrl),
              default_destination_icon_url);
    EXPECT_EQ(GURL(kDefaultDestinationUrl), default_destination_url);
}

TEST_F(SyncedNotificationTest, GetButtonDataTest) {
    std::string button_one_title = notification1_->GetButtonTitle(0);
    GURL button_one_icon_url = notification1_->GetButtonIconUrl(0);
    GURL button_one_url = notification1_->GetButtonUrl(0);
    std::string button_two_title = notification1_->GetButtonTitle(1);
    GURL button_two_icon_url = notification1_->GetButtonIconUrl(1);
    GURL button_two_url = notification1_->GetButtonUrl(1);
    EXPECT_EQ(std::string(kButtonOneTitle), button_one_title);
    EXPECT_EQ(GURL(kButtonOneIconUrl), button_one_icon_url);
    EXPECT_EQ(GURL(kButtonOneUrl), button_one_url);
    EXPECT_EQ(std::string(kButtonTwoTitle), button_two_title);
    EXPECT_EQ(GURL(kButtonTwoIconUrl), button_two_icon_url);
    EXPECT_EQ(GURL(kButtonTwoUrl), button_two_url);
}

TEST_F(SyncedNotificationTest, ContainedNotificationTest) {
  std::string notification_title1 =
      notification1_->GetContainedNotificationTitle(0);
  std::string notification_title2 =
      notification1_->GetContainedNotificationTitle(1);
  std::string notification_title3 =
      notification1_->GetContainedNotificationTitle(2);
  std::string notification_message1 =
      notification1_->GetContainedNotificationMessage(0);
  std::string notification_message2 =
      notification1_->GetContainedNotificationMessage(1);
  std::string notification_message3 =
      notification1_->GetContainedNotificationMessage(2);

  EXPECT_EQ(std::string(kContainedTitle1), notification_title1);
  EXPECT_EQ(std::string(kContainedTitle2), notification_title2);
  EXPECT_EQ(std::string(kContainedTitle3), notification_title3);
  EXPECT_EQ(std::string(kContainedMessage1), notification_message1);
  EXPECT_EQ(std::string(kContainedMessage2), notification_message2);
  EXPECT_EQ(std::string(kContainedMessage3), notification_message3);
}

// test that EqualsIgnoringReadState works as we expect
TEST_F(SyncedNotificationTest, EqualsIgnoringReadStateTest) {
  EXPECT_TRUE(notification1_->EqualsIgnoringReadState(*notification1_));
  EXPECT_TRUE(notification2_->EqualsIgnoringReadState(*notification2_));
  EXPECT_FALSE(notification1_->EqualsIgnoringReadState(*notification2_));
  EXPECT_FALSE(notification1_->EqualsIgnoringReadState(*notification3_));
  EXPECT_TRUE(notification1_->EqualsIgnoringReadState(*notification4_));
}

TEST_F(SyncedNotificationTest, UpdateTest) {
  scoped_ptr<SyncedNotification> notification5;
  notification5.reset(new SyncedNotification(
      sync_data1_, NULL, notification_manager()));

  // update with the sync data from notification2, and ensure they are equal.
  notification5->Update(sync_data2_);
  EXPECT_TRUE(notification5->EqualsIgnoringReadState(*notification2_));
  EXPECT_EQ(notification5->GetReadState(), notification2_->GetReadState());
  EXPECT_FALSE(notification5->EqualsIgnoringReadState(*notification1_));
}

TEST_F(SyncedNotificationTest, ShowTest) {

  if (!UseRichNotifications())
    return;

  // Call the method under test using the pre-populated data.
  notification1_->Show(NULL);

  const Notification notification = notification_manager()->notification();

  // Check the base fields of the notification.
  EXPECT_EQ(message_center::NOTIFICATION_TYPE_IMAGE, notification.type());
  EXPECT_EQ(std::string(kTitle1), base::UTF16ToUTF8(notification.title()));
  EXPECT_EQ(std::string(kText1), base::UTF16ToUTF8(notification.message()));
  EXPECT_EQ(std::string(kExpectedOriginUrl), notification.origin_url().spec());
  EXPECT_EQ(std::string(kKey1), base::UTF16ToUTF8(notification.replace_id()));

  EXPECT_EQ(kFakeCreationTime, notification.timestamp().ToDoubleT());
  EXPECT_EQ(kNotificationPriority, notification.priority());
}

TEST_F(SyncedNotificationTest, DismissTest) {

  if (!UseRichNotifications())
    return;

  // Call the method under test using a dismissed notification.
  notification4_->Show(NULL);

  EXPECT_EQ(std::string(kKey1), notification_manager()->dismissed_id());
}

TEST_F(SyncedNotificationTest, CreateBitmapFetcherTest) {
  scoped_ptr<SyncedNotification> notification6;
  notification6.reset(new SyncedNotification(
      sync_data1_, NULL, notification_manager()));

  // Add two bitmaps to the queue.
  notification6->CreateBitmapFetcher(GURL(kIconUrl1));
  notification6->CreateBitmapFetcher(GURL(kIconUrl2));

  EXPECT_EQ(GURL(kIconUrl1), notification6->fetchers_[0]->url());
  EXPECT_EQ(GURL(kIconUrl2), notification6->fetchers_[1]->url());

  notification6->CreateBitmapFetcher(GURL(kIconUrl2));
}

TEST_F(SyncedNotificationTest, OnFetchCompleteTest) {
  if (!UseRichNotifications())
    return;

  // Set up the internal state that FetchBitmaps() would have set.
  notification1_->notification_manager_ = notification_manager();

  // Add the bitmaps to the queue for us to match up.
  notification1_->CreateBitmapFetcher(GURL(kIconUrl1));
  notification1_->CreateBitmapFetcher(GURL(kImageUrl1));
  notification1_->CreateBitmapFetcher(GURL(kButtonOneIconUrl));
  notification1_->CreateBitmapFetcher(GURL(kButtonTwoIconUrl));

  // Put some realistic looking bitmap data into the url_fetcher.
  SkBitmap bitmap;

  // Put a real bitmap into "bitmap".  2x2 bitmap of green 32 bit pixels.
  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
  bitmap.allocPixels();
  bitmap.eraseColor(SK_ColorGREEN);

  // Allocate the button_bitmaps_ array as the calling function normally would.
  AddButtonBitmaps(notification1_.get(), 2);

  notification1_->OnFetchComplete(GURL(kIconUrl1), &bitmap);

  // When we call OnFetchComplete on the last bitmap, show should be called.
  notification1_->OnFetchComplete(GURL(kImageUrl1), &bitmap);

  notification1_->OnFetchComplete(GURL(kButtonOneIconUrl), &bitmap);

  notification1_->OnFetchComplete(GURL(kButtonTwoIconUrl), &bitmap);

  // Expect that the app icon has some data in it.
  EXPECT_FALSE(notification1_->GetAppIcon().IsEmpty());
  EXPECT_FALSE(notification_manager()->notification().small_image().IsEmpty());

  // Since we check Show() thoroughly in its own test, we only check cursorily.
  EXPECT_EQ(message_center::NOTIFICATION_TYPE_IMAGE,
            notification_manager()->notification().type());
  EXPECT_EQ(std::string(kTitle1),
            base::UTF16ToUTF8(notification_manager()->notification().title()));
  EXPECT_EQ(
      std::string(kText1),
      base::UTF16ToUTF8(notification_manager()->notification().message()));

  // TODO(petewil): Check that the bitmap in the notification is what we expect.
  // This fails today, the type info is different.
  // EXPECT_TRUE(gfx::BitmapsAreEqual(
  //     image, notification1_->GetAppIconBitmap()));
}

// TODO(petewil): Empty bitmap should count as a successful fetch.
TEST_F(SyncedNotificationTest, EmptyBitmapTest) {
  if (!UseRichNotifications())
    return;

  // Set up the internal state that FetchBitmaps() would have set.
  notification1_->notification_manager_ = notification_manager();

  // Add the bitmaps to the queue for us to match up.
  notification1_->CreateBitmapFetcher(GURL(kIconUrl1));
  notification1_->CreateBitmapFetcher(GURL(kImageUrl1));
  notification1_->CreateBitmapFetcher(GURL(kButtonOneIconUrl));
  notification1_->CreateBitmapFetcher(GURL(kButtonTwoIconUrl));

  // Put some realistic looking bitmap data into the url_fetcher.
  SkBitmap bitmap;
  SkBitmap empty_bitmap;

  // Put a real bitmap into "bitmap".  2x2 bitmap of green 32 bit pixels.
  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
  bitmap.allocPixels();
  bitmap.eraseColor(SK_ColorGREEN);

  // Put a null bitmap into "bitmap".  2x2 bitmap of green 32 bit pixels.
  empty_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 0, 0);
  empty_bitmap.allocPixels();
  empty_bitmap.eraseColor(SK_ColorGREEN);

  // Allocate the button_bitmaps_ array as the calling function normally would.
  AddButtonBitmaps(notification1_.get(), 2);

  notification1_->OnFetchComplete(GURL(kIconUrl1), &bitmap);

  // When we call OnFetchComplete on the last bitmap, show should be called.
  notification1_->OnFetchComplete(GURL(kImageUrl1), &bitmap);

  notification1_->OnFetchComplete(GURL(kButtonOneIconUrl), &empty_bitmap);

  notification1_->OnFetchComplete(GURL(kButtonTwoIconUrl), NULL);

  // Since we check Show() thoroughly in its own test, we only check cursorily.
  EXPECT_EQ(message_center::NOTIFICATION_TYPE_IMAGE,
            notification_manager()->notification().type());
  EXPECT_EQ(std::string(kTitle1),
            base::UTF16ToUTF8(notification_manager()->notification().title()));
  EXPECT_EQ(
      std::string(kText1),
      base::UTF16ToUTF8(notification_manager()->notification().message()));
}

TEST_F(SyncedNotificationTest, ShowIfNewlyEnabledTest) {
  if (!UseRichNotifications())
    return;

  // Call the method using the wrong app id, nothing should get shown.
  notification1_->ShowAllForAppId(NULL, kAppId2);

  // Ensure no notification was generated and shown.
  const Notification notification1 = notification_manager()->notification();
  EXPECT_EQ(std::string(), base::UTF16ToUTF8(notification1.replace_id()));

  // Call the method under test using the pre-populated data.
  notification1_->ShowAllForAppId(NULL, kAppId1);

  const Notification notification2 = notification_manager()->notification();

  // Check the base fields of the notification.
  EXPECT_EQ(message_center::NOTIFICATION_TYPE_IMAGE, notification2.type());
  EXPECT_EQ(std::string(kTitle1), base::UTF16ToUTF8(notification2.title()));
  EXPECT_EQ(std::string(kText1), base::UTF16ToUTF8(notification2.message()));
  EXPECT_EQ(std::string(kExpectedOriginUrl), notification2.origin_url().spec());
  EXPECT_EQ(std::string(kKey1), base::UTF16ToUTF8(notification2.replace_id()));

  EXPECT_EQ(kFakeCreationTime, notification2.timestamp().ToDoubleT());
  EXPECT_EQ(kNotificationPriority, notification2.priority());
}

TEST_F(SyncedNotificationTest, HideIfNewlyRemovedTest) {
  if (!UseRichNotifications())
    return;

  // Add the notification to the notification manger, so it exists before we
  // we remove it.
  notification1_->Show(NULL);
  const Notification* found1 = notification_manager()->FindById(kKey1);
  EXPECT_NE(reinterpret_cast<Notification*>(NULL), found1);

  // Call the method under test using the pre-populated data.
  notification1_->HideAllForAppId(kAppId1);

  // Ensure the notification was removed from the notification manager
  EXPECT_EQ(std::string(kKey1), notification_manager()->dismissed_id());
}

// TODO(petewil): Add a test for a notification being read and or deleted.

}  // namespace notifier

/* [<][>][^][v][top][bottom][index][help] */