// Copyright 2014 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 "components/enhanced_bookmarks/enhanced_bookmark_model.h" #include "base/base64.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_node.h" #include "components/bookmarks/test/test_bookmark_client.h" #include "components/enhanced_bookmarks/enhanced_bookmark_model_observer.h" #include "components/enhanced_bookmarks/proto/metadata.pb.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; using enhanced_bookmarks::EnhancedBookmarkModel; namespace { const std::string BOOKMARK_URL("http://example.com/index.html"); const std::string IMAGE_URL("http://example.com/image.jpg"); } // namespace class EnhancedBookmarkModelTest : public testing::Test, public enhanced_bookmarks::EnhancedBookmarkModelObserver { public: EnhancedBookmarkModelTest() : loaded_calls_(0), shutting_down_calls_(0), added_calls_(0), removed_calls_(0), changed_calls_(0), all_user_nodes_removed_calls_(0), remote_id_changed_calls_(0), last_added_(NULL), last_removed_(NULL), last_changed_(NULL), last_remote_id_node_(NULL) {} ~EnhancedBookmarkModelTest() override {} void SetUp() override { message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT)); bookmark_client_.reset(new bookmarks::TestBookmarkClient()); bookmark_model_.reset(bookmark_client_->CreateModel().release()); model_.reset(new EnhancedBookmarkModel(bookmark_model_.get(), "v1.0")); model_->AddObserver(this); } void TearDown() override { if (model_) model_->Shutdown(); model_.reset(); bookmark_model_.reset(); bookmark_client_.reset(); message_loop_.reset(); } protected: const BookmarkNode* AddBookmark() { return AddBookmark("Some title", bookmark_model_->other_node()); } const BookmarkNode* AddFolder() { return AddFolder("Some title", bookmark_model_->other_node()); } const BookmarkNode* AddBookmark(const std::string& name, const BookmarkNode* parent) { return model_->AddURL(parent, 0, // index. base::ASCIIToUTF16(name), GURL(BOOKMARK_URL), base::Time::Now()); } const BookmarkNode* AddFolder(const std::string& name, const BookmarkNode* parent) { return model_->AddFolder(parent, 0, base::ASCIIToUTF16(name)); } std::string GetVersion(const BookmarkNode* node) { return GetMetaInfoField(node, "stars.version"); } std::string GetId(const BookmarkNode* node) { return GetMetaInfoField(node, "stars.id"); } std::string GetOldId(const BookmarkNode* node) { return GetMetaInfoField(node, "stars.oldId"); } std::string GetMetaInfoField(const BookmarkNode* node, const std::string& name) { std::string value; if (!node->GetMetaInfo(name, &value)) return std::string(); return value; } scoped_ptr message_loop_; scoped_ptr bookmark_client_; scoped_ptr bookmark_model_; scoped_ptr model_; // EnhancedBookmarkModelObserver implementation: void EnhancedBookmarkModelLoaded() override { loaded_calls_++; } void EnhancedBookmarkModelShuttingDown() override { shutting_down_calls_++; } void EnhancedBookmarkAdded(const BookmarkNode* node) override { added_calls_++; last_added_ = node; } void EnhancedBookmarkRemoved(const BookmarkNode* node) override { removed_calls_++; last_removed_ = node; } void EnhancedBookmarkNodeChanged(const BookmarkNode* node) override { changed_calls_++; last_changed_ = node; } void EnhancedBookmarkAllUserNodesRemoved() override { all_user_nodes_removed_calls_++; } void EnhancedBookmarkRemoteIdChanged(const BookmarkNode* node, const std::string& old_remote_id, const std::string& remote_id) override { remote_id_changed_calls_++; last_remote_id_node_ = node; last_old_remote_id_ = old_remote_id; last_remote_id_ = remote_id; } // Observer call counters: int loaded_calls_; int shutting_down_calls_; int added_calls_; int removed_calls_; int changed_calls_; int all_user_nodes_removed_calls_; int remote_id_changed_calls_; // Observer parameter cache: const BookmarkNode* last_added_; const BookmarkNode* last_removed_; const BookmarkNode* last_changed_; const BookmarkNode* last_remote_id_node_; std::string last_old_remote_id_; std::string last_remote_id_; private: DISALLOW_COPY_AND_ASSIGN(EnhancedBookmarkModelTest); }; TEST_F(EnhancedBookmarkModelTest, TestEmptySnippet) { const BookmarkNode* node = AddBookmark(); std::string snippet(model_->GetSnippet(node)); EXPECT_EQ(snippet, ""); }; TEST_F(EnhancedBookmarkModelTest, TestSnippet) { const BookmarkNode* node = AddBookmark(); // Binary serialize the protobuf. image::collections::PageData data; data.set_snippet("I'm happy!"); ASSERT_TRUE(data.IsInitialized()); std::string output; bool result = data.SerializeToString(&output); ASSERT_TRUE(result); // base64 encode the output. std::string encoded; base::Base64Encode(output, &encoded); bookmark_model_->SetNodeMetaInfo(node, "stars.pageData", encoded); std::string snippet(model_->GetSnippet(node)); EXPECT_EQ(snippet, "I'm happy!"); } TEST_F(EnhancedBookmarkModelTest, TestBadEncodingSnippet) { const BookmarkNode* node = AddBookmark(); // Binary serialize the protobuf. image::collections::PageData data; data.set_snippet("You are happy!"); ASSERT_TRUE(data.IsInitialized()); std::string output; bool result = data.SerializeToString(&output); ASSERT_TRUE(result); // don't base 64 encode the output. bookmark_model_->SetNodeMetaInfo(node, "stars.pageData", output); std::string snippet(model_->GetSnippet(node)); EXPECT_EQ(snippet, ""); } TEST_F(EnhancedBookmarkModelTest, TestOriginalImage) { const BookmarkNode* node = AddBookmark(); image::collections::ImageData data; // Intentionally make raw pointer. image::collections::ImageData_ImageInfo* info = new image::collections::ImageData_ImageInfo; info->set_url("http://example.com/foobar"); info->set_width(15); info->set_height(55); // This method consumes the pointer. data.set_allocated_original_info(info); std::string output; bool result = data.SerializePartialToString(&output); ASSERT_TRUE(result); // base64 encode the output. std::string encoded; base::Base64Encode(output, &encoded); bookmark_model_->SetNodeMetaInfo(node, "stars.imageData", encoded); GURL url; int width; int height; result = model_->GetOriginalImage(node, &url, &width, &height); ASSERT_TRUE(result); EXPECT_EQ(url, GURL("http://example.com/foobar")); EXPECT_EQ(width, 15); EXPECT_EQ(height, 55); } TEST_F(EnhancedBookmarkModelTest, TestThumbnailImage) { const BookmarkNode* node = AddBookmark(); image::collections::ImageData data; // Intentionally make raw pointer. image::collections::ImageData_ImageInfo* info = new image::collections::ImageData_ImageInfo; info->set_url("http://example.com/foobar"); info->set_width(15); info->set_height(55); // This method consumes the pointer. data.set_allocated_thumbnail_info(info); std::string output; bool result = data.SerializePartialToString(&output); ASSERT_TRUE(result); // base64 encode the output. std::string encoded; base::Base64Encode(output, &encoded); bookmark_model_->SetNodeMetaInfo(node, "stars.imageData", encoded); GURL url; int width; int height; result = model_->GetThumbnailImage(node, &url, &width, &height); ASSERT_TRUE(result); EXPECT_EQ(url, GURL("http://example.com/foobar")); EXPECT_EQ(width, 15); EXPECT_EQ(height, 55); } TEST_F(EnhancedBookmarkModelTest, TestOriginalImageMissingDimensions) { const BookmarkNode* node = AddBookmark(); image::collections::ImageData data; // Intentionally make raw pointer. image::collections::ImageData_ImageInfo* info = new image::collections::ImageData_ImageInfo; info->set_url("http://example.com/foobar"); // This method consumes the pointer. data.set_allocated_original_info(info); std::string output; bool result = data.SerializePartialToString(&output); ASSERT_TRUE(result); // base64 encode the output. std::string encoded; base::Base64Encode(output, &encoded); bookmark_model_->SetNodeMetaInfo(node, "stars.imageData", encoded); GURL url; int width; int height; result = model_->GetOriginalImage(node, &url, &width, &height); ASSERT_FALSE(result); } TEST_F(EnhancedBookmarkModelTest, TestOriginalImageBadUrl) { const BookmarkNode* node = AddBookmark(); image::collections::ImageData data; // Intentionally make raw pointer. image::collections::ImageData_ImageInfo* info = new image::collections::ImageData_ImageInfo; info->set_url("asdf. 13r"); info->set_width(15); info->set_height(55); // This method consumes the pointer. data.set_allocated_original_info(info); std::string output; bool result = data.SerializePartialToString(&output); ASSERT_TRUE(result); // base64 encode the output. std::string encoded; base::Base64Encode(output, &encoded); bookmark_model_->SetNodeMetaInfo(node, "stars.imageData", encoded); GURL url; int width; int height; result = model_->GetOriginalImage(node, &url, &width, &height); ASSERT_FALSE(result); } TEST_F(EnhancedBookmarkModelTest, TestEncodeDecode) { const BookmarkNode* node = AddBookmark(); bool result = model_->SetOriginalImage(node, GURL("http://example.com/i.jpg"), 22, 33); ASSERT_TRUE(result); GURL url; int width; int height; result = model_->GetOriginalImage(node, &url, &width, &height); ASSERT_TRUE(result); EXPECT_EQ(url, GURL("http://example.com/i.jpg")); EXPECT_EQ(width, 22); EXPECT_EQ(height, 33); EXPECT_EQ("v1.0", GetVersion(node)); } TEST_F(EnhancedBookmarkModelTest, TestDoubleEncodeDecode) { const BookmarkNode* node = AddBookmark(); // Encode some information. bool result = model_->SetOriginalImage(node, GURL("http://example.com/i.jpg"), 22, 33); ASSERT_TRUE(result); // Encode some different information. result = model_->SetOriginalImage(node, GURL("http://example.com/i.jpg"), 33, 44); ASSERT_TRUE(result); GURL url; int width; int height; result = model_->GetOriginalImage(node, &url, &width, &height); ASSERT_TRUE(result); EXPECT_EQ(url, GURL("http://example.com/i.jpg")); EXPECT_EQ(width, 33); EXPECT_EQ(height, 44); EXPECT_EQ("v1.0", GetVersion(node)); } TEST_F(EnhancedBookmarkModelTest, TestRemoteId) { const BookmarkNode* node = AddBookmark(); // Verify that the remote id starts with the correct prefix. EXPECT_TRUE(base::StartsWith(model_->GetRemoteId(node), "ebc_", base::CompareCase::SENSITIVE)); // Getting the remote id for nodes that don't have them should return the // empty string. const BookmarkNode* existing_node = bookmark_model_->AddURL(bookmark_model_->other_node(), 0, base::ASCIIToUTF16("Title"), GURL(GURL(BOOKMARK_URL))); EXPECT_TRUE(model_->GetRemoteId(existing_node).empty()); // Folder nodes should not have a remote id set on creation. const BookmarkNode* folder_node = AddFolder(); EXPECT_TRUE(model_->GetRemoteId(folder_node).empty()); } TEST_F(EnhancedBookmarkModelTest, TestEmptyDescription) { const BookmarkNode* node = AddBookmark(); std::string description(model_->GetDescription(node)); EXPECT_EQ(description, ""); } TEST_F(EnhancedBookmarkModelTest, TestDescription) { const BookmarkNode* node = AddBookmark(); const std::string description("This is the most useful description of all."); // Set the description. model_->SetDescription(node, description); // Check the description is the one that was set. EXPECT_EQ(model_->GetDescription(node), description); EXPECT_EQ("v1.0", GetVersion(node)); } // If there is no notes field, the description should fall back on the snippet. TEST_F(EnhancedBookmarkModelTest, TestDescriptionFallback) { const BookmarkNode* node = AddBookmark(); // Binary serialize the protobuf. image::collections::PageData data; data.set_snippet("Joe Bar Team"); ASSERT_TRUE(data.IsInitialized()); std::string output; bool result = data.SerializeToString(&output); ASSERT_TRUE(result); // base64 encode the output. std::string encoded; base::Base64Encode(output, &encoded); bookmark_model_->SetNodeMetaInfo(node, "stars.pageData", encoded); // The snippet is used as the description. std::string snippet(model_->GetSnippet(node)); EXPECT_EQ("Joe Bar Team", model_->GetDescription(node)); // Set the description. const std::string description("This is the most useful description of all."); model_->SetDescription(node, description); // Check the description is the one that was set. EXPECT_EQ(model_->GetDescription(node), description); } // Makes sure that the stars.version field is set every time // EnhancedBookmarkModel makes a change to a node. TEST_F(EnhancedBookmarkModelTest, TestVersionField) { const BookmarkNode* node = bookmark_model_->AddURL(bookmark_model_->other_node(), 0, base::ASCIIToUTF16("Title"), GURL(BOOKMARK_URL)); EXPECT_EQ("", GetVersion(node)); model_->SetDescription(node, "foo"); EXPECT_EQ("v1.0", GetVersion(node)); // Add a suffix to the version to set. model_->SetVersionSuffix("alpha"); model_->SetDescription(node, "foo"); // Since the description didn't actually change, the version field should // not either. EXPECT_EQ("v1.0", GetVersion(node)); model_->SetDescription(node, "bar"); EXPECT_EQ("v1.0/alpha", GetVersion(node)); } // Verifies that duplicate nodes are reset when the model is created. TEST_F(EnhancedBookmarkModelTest, ResetDuplicateNodesOnInitialization) { model_->Shutdown(); const BookmarkNode* parent = bookmark_model_->other_node(); const BookmarkNode* node1 = bookmark_model_->AddURL( parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL)); const BookmarkNode* node2 = bookmark_model_->AddURL( parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL)); const BookmarkNode* node3 = bookmark_model_->AddURL( parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL)); const BookmarkNode* node4 = bookmark_model_->AddURL( parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL)); bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1"); bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_2"); bookmark_model_->SetNodeMetaInfo(node3, "stars.id", "c_1"); bookmark_model_->SetNodeMetaInfo(node4, "stars.id", "c_1"); EXPECT_EQ("c_1", GetId(node1)); EXPECT_EQ("c_2", GetId(node2)); EXPECT_EQ("c_1", GetId(node3)); EXPECT_EQ("c_1", GetId(node4)); model_.reset(new EnhancedBookmarkModel(bookmark_model_.get(), "v2.0")); base::RunLoop().RunUntilIdle(); EXPECT_EQ("c_2", GetId(node2)); EXPECT_EQ("", GetId(node1)); EXPECT_EQ("", GetId(node3)); EXPECT_EQ("", GetId(node4)); EXPECT_EQ("c_1", GetOldId(node1)); EXPECT_EQ("c_1", GetOldId(node3)); EXPECT_EQ("c_1", GetOldId(node4)); EXPECT_EQ("v2.0", GetVersion(node1)); EXPECT_EQ("v2.0", GetVersion(node3)); EXPECT_EQ("v2.0", GetVersion(node4)); } // Verifies that duplicate nodes are reset if one is created. TEST_F(EnhancedBookmarkModelTest, ResetDuplicateAddedNodes) { BookmarkNode::MetaInfoMap meta_info; meta_info["stars.id"] = "c_1"; const BookmarkNode* parent = bookmark_model_->other_node(); const BookmarkNode* node1 = bookmark_model_->AddURLWithCreationTimeAndMetaInfo( parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL), base::Time::Now(), &meta_info); EXPECT_EQ("c_1", GetId(node1)); const BookmarkNode* node2 = bookmark_model_->AddURLWithCreationTimeAndMetaInfo( parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL), base::Time::Now(), &meta_info); base::RunLoop().RunUntilIdle(); EXPECT_EQ("", GetId(node1)); EXPECT_EQ("", GetId(node2)); EXPECT_EQ("c_1", GetOldId(node1)); EXPECT_EQ("c_1", GetOldId(node2)); EXPECT_EQ("v1.0", GetVersion(node1)); EXPECT_EQ("v1.0", GetVersion(node2)); } // Verifies that duplicate nodes are reset if an id is changed to a duplicate // value. TEST_F(EnhancedBookmarkModelTest, ResetDuplicateChangedNodes) { const BookmarkNode* node1 = AddBookmark(); const BookmarkNode* node2 = AddBookmark(); bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1"); EXPECT_EQ("c_1", GetId(node1)); bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_1"); base::RunLoop().RunUntilIdle(); EXPECT_EQ("", GetId(node1)); EXPECT_EQ("", GetId(node2)); EXPECT_EQ("c_1", GetOldId(node1)); EXPECT_EQ("c_1", GetOldId(node2)); EXPECT_EQ("v1.0", GetVersion(node1)); EXPECT_EQ("v1.0", GetVersion(node2)); } TEST_F(EnhancedBookmarkModelTest, SetMultipleMetaInfo) { const BookmarkNode* node = AddBookmark(); BookmarkNode::MetaInfoMap meta_info; meta_info["a"] = "aa"; meta_info["b"] = "bb"; model_->SetVersionSuffix("1"); model_->SetMultipleMetaInfo(node, meta_info); EXPECT_EQ("aa", GetMetaInfoField(node, "a")); EXPECT_EQ("bb", GetMetaInfoField(node, "b")); EXPECT_EQ("v1.0/1", GetVersion(node)); // Not present fields does not erase the fields already set on the node. meta_info["a"] = "aaa"; model_->SetVersionSuffix("2"); model_->SetMultipleMetaInfo(node, meta_info); EXPECT_EQ("aaa", GetMetaInfoField(node, "a")); EXPECT_EQ("bb", GetMetaInfoField(node, "b")); EXPECT_EQ("v1.0/2", GetVersion(node)); // Not actually changing any values should not set the version field. model_->SetVersionSuffix("3"); model_->SetMultipleMetaInfo(node, meta_info); EXPECT_EQ("v1.0/2", GetVersion(node)); } TEST_F(EnhancedBookmarkModelTest, ObserverShuttingDownEvent) { EXPECT_EQ(0, shutting_down_calls_); model_->Shutdown(); EXPECT_EQ(1, shutting_down_calls_); model_.reset(); } TEST_F(EnhancedBookmarkModelTest, ObserverNodeAddedEvent) { EXPECT_EQ(0, added_calls_); const BookmarkNode* node = AddBookmark(); EXPECT_EQ(1, added_calls_); EXPECT_EQ(node, last_added_); const BookmarkNode* folder = AddFolder(); EXPECT_EQ(2, added_calls_); EXPECT_EQ(folder, last_added_); } TEST_F(EnhancedBookmarkModelTest, ObserverNodeRemovedEvent) { const BookmarkNode* node = AddBookmark(); const BookmarkNode* folder = AddFolder(); EXPECT_EQ(0, removed_calls_); bookmark_model_->Remove(node); EXPECT_EQ(1, removed_calls_); EXPECT_EQ(node, last_removed_); bookmark_model_->Remove(folder); EXPECT_EQ(2, removed_calls_); EXPECT_EQ(folder, last_removed_); } TEST_F(EnhancedBookmarkModelTest, ObserverNodeChangedEvent) { const BookmarkNode* node = AddBookmark(); EXPECT_EQ(0, changed_calls_); bookmark_model_->SetTitle(node, base::ASCIIToUTF16("New Title")); EXPECT_EQ(1, changed_calls_); EXPECT_EQ(node, last_changed_); } TEST_F(EnhancedBookmarkModelTest, ObserverAllUserNodesRemovedEvent) { AddBookmark(); AddFolder(); EXPECT_EQ(0, all_user_nodes_removed_calls_); bookmark_model_->RemoveAllUserBookmarks(); EXPECT_EQ(0, removed_calls_); EXPECT_EQ(1, all_user_nodes_removed_calls_); } TEST_F(EnhancedBookmarkModelTest, ObserverRemoteIdChangedEvent) { const BookmarkNode* node1 = AddFolder(); const BookmarkNode* node2 = AddFolder(); EXPECT_EQ(0, remote_id_changed_calls_); bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1"); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, remote_id_changed_calls_); EXPECT_EQ(node1, last_remote_id_node_); EXPECT_EQ("", last_old_remote_id_); EXPECT_EQ("c_1", last_remote_id_); bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_2"); base::RunLoop().RunUntilIdle(); EXPECT_EQ(2, remote_id_changed_calls_); EXPECT_EQ(node2, last_remote_id_node_); EXPECT_EQ("", last_old_remote_id_); EXPECT_EQ("c_2", last_remote_id_); bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_3"); base::RunLoop().RunUntilIdle(); EXPECT_EQ(3, remote_id_changed_calls_); EXPECT_EQ(node1, last_remote_id_node_); EXPECT_EQ("c_1", last_old_remote_id_); EXPECT_EQ("c_3", last_remote_id_); // Set to duplicate ids. bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_3"); EXPECT_EQ(4, remote_id_changed_calls_); EXPECT_EQ(node2, last_remote_id_node_); EXPECT_EQ("c_2", last_old_remote_id_); EXPECT_EQ("c_3", last_remote_id_); base::RunLoop().RunUntilIdle(); EXPECT_EQ(6, remote_id_changed_calls_); EXPECT_EQ("", last_remote_id_); } TEST_F(EnhancedBookmarkModelTest, ShutDownWhileResetDuplicationScheduled) { const BookmarkNode* node1 = AddBookmark(); const BookmarkNode* node2 = AddBookmark(); bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1"); bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_1"); model_->Shutdown(); model_.reset(); base::RunLoop().RunUntilIdle(); } TEST_F(EnhancedBookmarkModelTest, NodeRemovedWhileResetDuplicationScheduled) { const BookmarkNode* node1 = AddBookmark(); const BookmarkNode* node2 = AddBookmark(); bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1"); bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_1"); bookmark_model_->Remove(node1); base::RunLoop().RunUntilIdle(); } TEST_F(EnhancedBookmarkModelTest, RemoveParentShouldRemoveChildrenFromMaps) { const BookmarkNode* parent = AddFolder(); const BookmarkNode* node = AddBookmark("Title", parent); std::string remote_id = GetId(node); EXPECT_EQ(node, model_->BookmarkForRemoteId(remote_id)); bookmark_model_->Remove(parent); EXPECT_FALSE(model_->BookmarkForRemoteId(remote_id)); } TEST_F(EnhancedBookmarkModelTest, AddsRemoteIdToNonClonedKeys) { const std::set& non_cloned_keys = bookmark_model_->non_cloned_keys(); EXPECT_TRUE(non_cloned_keys.find("stars.id") != non_cloned_keys.end()); } TEST_F(EnhancedBookmarkModelTest, RemoveImageData) { const BookmarkNode* node = AddBookmark(); model_->SetAllImages(node, GURL(IMAGE_URL), 64, 64, GURL(IMAGE_URL), 16, 16); GURL url; int width, height; EXPECT_TRUE(model_->GetOriginalImage(node, &url, &width, &height)); EXPECT_TRUE(model_->GetThumbnailImage(node, &url, &width, &height)); model_->RemoveImageData(node); EXPECT_FALSE(model_->GetOriginalImage(node, &url, &width, &height)); EXPECT_FALSE(model_->GetThumbnailImage(node, &url, &width, &height)); std::string meta_info = GetMetaInfoField(node, "stars.imageData"); std::string decoded; ASSERT_TRUE(base::Base64Decode(meta_info, &decoded)); image::collections::ImageData data; ASSERT_TRUE(data.ParseFromString(decoded)); EXPECT_TRUE(data.user_removed_image()); }