1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "components/enhanced_bookmarks/enhanced_bookmark_model.h" 6 7 #include "base/base64.h" 8 #include "base/macros.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/run_loop.h" 12 #include "base/strings/string_util.h" 13 #include "base/strings/utf_string_conversions.h" 14 #include "components/bookmarks/browser/bookmark_model.h" 15 #include "components/bookmarks/browser/bookmark_node.h" 16 #include "components/bookmarks/test/test_bookmark_client.h" 17 #include "components/enhanced_bookmarks/enhanced_bookmark_model_observer.h" 18 #include "components/enhanced_bookmarks/proto/metadata.pb.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 #include "url/gurl.h" 21 22 using enhanced_bookmarks::EnhancedBookmarkModel; 23 24 namespace { 25 const std::string BOOKMARK_URL("http://example.com/index.html"); 26 } // namespace 27 28 class EnhancedBookmarkModelTest 29 : public testing::Test, 30 public enhanced_bookmarks::EnhancedBookmarkModelObserver { 31 public: 32 EnhancedBookmarkModelTest() 33 : loaded_calls_(0), 34 shutting_down_calls_(0), 35 added_calls_(0), 36 removed_calls_(0), 37 all_user_nodes_removed_calls_(0), 38 remote_id_changed_calls_(0), 39 last_added_(NULL), 40 last_removed_(NULL), 41 last_remote_id_node_(NULL) {} 42 virtual ~EnhancedBookmarkModelTest() {} 43 44 virtual void SetUp() OVERRIDE { 45 message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT)); 46 bookmark_client_.reset(new bookmarks::TestBookmarkClient()); 47 bookmark_model_.reset(bookmark_client_->CreateModel().release()); 48 model_.reset(new EnhancedBookmarkModel(bookmark_model_.get(), "v1.0")); 49 model_->AddObserver(this); 50 } 51 52 virtual void TearDown() OVERRIDE { 53 if (model_) 54 model_->Shutdown(); 55 model_.reset(); 56 bookmark_model_.reset(); 57 bookmark_client_.reset(); 58 message_loop_.reset(); 59 } 60 61 protected: 62 const BookmarkNode* AddBookmark() { 63 return AddBookmark("Some title", bookmark_model_->other_node()); 64 } 65 66 const BookmarkNode* AddFolder() { 67 return AddFolder("Some title", bookmark_model_->other_node()); 68 } 69 70 const BookmarkNode* AddBookmark(const std::string& name, 71 const BookmarkNode* parent) { 72 return model_->AddURL(parent, 73 0, // index. 74 base::ASCIIToUTF16(name), 75 GURL(BOOKMARK_URL), 76 base::Time::Now()); 77 } 78 79 const BookmarkNode* AddFolder(const std::string& name, 80 const BookmarkNode* parent) { 81 return model_->AddFolder(parent, 0, base::ASCIIToUTF16(name)); 82 } 83 84 std::string GetVersion(const BookmarkNode* node) { 85 return GetMetaInfoField(node, "stars.version"); 86 } 87 88 std::string GetId(const BookmarkNode* node) { 89 return GetMetaInfoField(node, "stars.id"); 90 } 91 92 std::string GetOldId(const BookmarkNode* node) { 93 return GetMetaInfoField(node, "stars.oldId"); 94 } 95 96 std::string GetMetaInfoField(const BookmarkNode* node, 97 const std::string& name) { 98 std::string value; 99 if (!node->GetMetaInfo(name, &value)) 100 return std::string(); 101 return value; 102 } 103 104 scoped_ptr<base::MessageLoop> message_loop_; 105 scoped_ptr<bookmarks::TestBookmarkClient> bookmark_client_; 106 scoped_ptr<BookmarkModel> bookmark_model_; 107 scoped_ptr<EnhancedBookmarkModel> model_; 108 109 // EnhancedBookmarkModelObserver implementation: 110 virtual void EnhancedBookmarkModelLoaded() OVERRIDE { loaded_calls_++; } 111 virtual void EnhancedBookmarkModelShuttingDown() OVERRIDE { 112 shutting_down_calls_++; 113 } 114 virtual void EnhancedBookmarkAdded(const BookmarkNode* node) OVERRIDE { 115 added_calls_++; 116 last_added_ = node; 117 } 118 virtual void EnhancedBookmarkRemoved(const BookmarkNode* node) OVERRIDE { 119 removed_calls_++; 120 last_removed_ = node; 121 } 122 virtual void EnhancedBookmarkAllUserNodesRemoved() OVERRIDE { 123 all_user_nodes_removed_calls_++; 124 } 125 virtual void EnhancedBookmarkRemoteIdChanged( 126 const BookmarkNode* node, 127 const std::string& old_remote_id, 128 const std::string& remote_id) OVERRIDE { 129 remote_id_changed_calls_++; 130 last_remote_id_node_ = node; 131 last_old_remote_id_ = old_remote_id; 132 last_remote_id_ = remote_id; 133 } 134 135 // Observer call counters: 136 int loaded_calls_; 137 int shutting_down_calls_; 138 int added_calls_; 139 int removed_calls_; 140 int all_user_nodes_removed_calls_; 141 int remote_id_changed_calls_; 142 143 // Observer parameter cache: 144 const BookmarkNode* last_added_; 145 const BookmarkNode* last_removed_; 146 const BookmarkNode* last_remote_id_node_; 147 std::string last_old_remote_id_; 148 std::string last_remote_id_; 149 150 private: 151 DISALLOW_COPY_AND_ASSIGN(EnhancedBookmarkModelTest); 152 }; 153 154 TEST_F(EnhancedBookmarkModelTest, TestEmptySnippet) { 155 const BookmarkNode* node = AddBookmark(); 156 157 std::string snippet(model_->GetSnippet(node)); 158 EXPECT_EQ(snippet, ""); 159 }; 160 161 TEST_F(EnhancedBookmarkModelTest, TestSnippet) { 162 const BookmarkNode* node = AddBookmark(); 163 164 // Binary serialize the protobuf. 165 image::collections::PageData data; 166 data.set_snippet("I'm happy!"); 167 ASSERT_TRUE(data.IsInitialized()); 168 std::string output; 169 bool result = data.SerializeToString(&output); 170 ASSERT_TRUE(result); 171 172 // base64 encode the output. 173 std::string encoded; 174 base::Base64Encode(output, &encoded); 175 bookmark_model_->SetNodeMetaInfo(node, "stars.pageData", encoded); 176 177 std::string snippet(model_->GetSnippet(node)); 178 EXPECT_EQ(snippet, "I'm happy!"); 179 } 180 181 TEST_F(EnhancedBookmarkModelTest, TestBadEncodingSnippet) { 182 const BookmarkNode* node = AddBookmark(); 183 184 // Binary serialize the protobuf. 185 image::collections::PageData data; 186 data.set_snippet("You are happy!"); 187 ASSERT_TRUE(data.IsInitialized()); 188 std::string output; 189 bool result = data.SerializeToString(&output); 190 ASSERT_TRUE(result); 191 192 // don't base 64 encode the output. 193 bookmark_model_->SetNodeMetaInfo(node, "stars.pageData", output); 194 195 std::string snippet(model_->GetSnippet(node)); 196 EXPECT_EQ(snippet, ""); 197 } 198 199 TEST_F(EnhancedBookmarkModelTest, TestOriginalImage) { 200 const BookmarkNode* node = AddBookmark(); 201 202 image::collections::ImageData data; 203 // Intentionally make raw pointer. 204 image::collections::ImageData_ImageInfo* info = 205 new image::collections::ImageData_ImageInfo; 206 info->set_url("http://example.com/foobar"); 207 info->set_width(15); 208 info->set_height(55); 209 // This method consumes the pointer. 210 data.set_allocated_original_info(info); 211 212 std::string output; 213 bool result = data.SerializePartialToString(&output); 214 ASSERT_TRUE(result); 215 216 // base64 encode the output. 217 std::string encoded; 218 base::Base64Encode(output, &encoded); 219 bookmark_model_->SetNodeMetaInfo(node, "stars.imageData", encoded); 220 221 GURL url; 222 int width; 223 int height; 224 result = model_->GetOriginalImage(node, &url, &width, &height); 225 ASSERT_TRUE(result); 226 EXPECT_EQ(url, GURL("http://example.com/foobar")); 227 EXPECT_EQ(width, 15); 228 EXPECT_EQ(height, 55); 229 } 230 231 TEST_F(EnhancedBookmarkModelTest, TestThumbnailImage) { 232 const BookmarkNode* node = AddBookmark(); 233 234 image::collections::ImageData data; 235 // Intentionally make raw pointer. 236 image::collections::ImageData_ImageInfo* info = 237 new image::collections::ImageData_ImageInfo; 238 info->set_url("http://example.com/foobar"); 239 info->set_width(15); 240 info->set_height(55); 241 // This method consumes the pointer. 242 data.set_allocated_thumbnail_info(info); 243 244 std::string output; 245 bool result = data.SerializePartialToString(&output); 246 ASSERT_TRUE(result); 247 248 // base64 encode the output. 249 std::string encoded; 250 base::Base64Encode(output, &encoded); 251 bookmark_model_->SetNodeMetaInfo(node, "stars.imageData", encoded); 252 253 GURL url; 254 int width; 255 int height; 256 result = model_->GetThumbnailImage(node, &url, &width, &height); 257 ASSERT_TRUE(result); 258 EXPECT_EQ(url, GURL("http://example.com/foobar")); 259 EXPECT_EQ(width, 15); 260 EXPECT_EQ(height, 55); 261 } 262 263 TEST_F(EnhancedBookmarkModelTest, TestOriginalImageMissingDimensions) { 264 const BookmarkNode* node = AddBookmark(); 265 266 image::collections::ImageData data; 267 // Intentionally make raw pointer. 268 image::collections::ImageData_ImageInfo* info = 269 new image::collections::ImageData_ImageInfo; 270 info->set_url("http://example.com/foobar"); 271 // This method consumes the pointer. 272 data.set_allocated_original_info(info); 273 274 std::string output; 275 bool result = data.SerializePartialToString(&output); 276 ASSERT_TRUE(result); 277 278 // base64 encode the output. 279 std::string encoded; 280 base::Base64Encode(output, &encoded); 281 bookmark_model_->SetNodeMetaInfo(node, "stars.imageData", encoded); 282 283 GURL url; 284 int width; 285 int height; 286 result = model_->GetOriginalImage(node, &url, &width, &height); 287 ASSERT_FALSE(result); 288 } 289 290 TEST_F(EnhancedBookmarkModelTest, TestOriginalImageBadUrl) { 291 const BookmarkNode* node = AddBookmark(); 292 293 image::collections::ImageData data; 294 // Intentionally make raw pointer. 295 image::collections::ImageData_ImageInfo* info = 296 new image::collections::ImageData_ImageInfo; 297 info->set_url("asdf. 13r"); 298 info->set_width(15); 299 info->set_height(55); 300 // This method consumes the pointer. 301 data.set_allocated_original_info(info); 302 303 std::string output; 304 bool result = data.SerializePartialToString(&output); 305 ASSERT_TRUE(result); 306 307 // base64 encode the output. 308 std::string encoded; 309 base::Base64Encode(output, &encoded); 310 bookmark_model_->SetNodeMetaInfo(node, "stars.imageData", encoded); 311 312 GURL url; 313 int width; 314 int height; 315 result = model_->GetOriginalImage(node, &url, &width, &height); 316 ASSERT_FALSE(result); 317 } 318 319 TEST_F(EnhancedBookmarkModelTest, TestEncodeDecode) { 320 const BookmarkNode* node = AddBookmark(); 321 322 bool result = 323 model_->SetOriginalImage(node, GURL("http://example.com/i.jpg"), 22, 33); 324 ASSERT_TRUE(result); 325 326 GURL url; 327 int width; 328 int height; 329 result = model_->GetOriginalImage(node, &url, &width, &height); 330 ASSERT_TRUE(result); 331 EXPECT_EQ(url, GURL("http://example.com/i.jpg")); 332 EXPECT_EQ(width, 22); 333 EXPECT_EQ(height, 33); 334 EXPECT_EQ("v1.0", GetVersion(node)); 335 } 336 337 TEST_F(EnhancedBookmarkModelTest, TestDoubleEncodeDecode) { 338 const BookmarkNode* node = AddBookmark(); 339 340 // Encode some information. 341 bool result = 342 model_->SetOriginalImage(node, GURL("http://example.com/i.jpg"), 22, 33); 343 ASSERT_TRUE(result); 344 // Encode some different information. 345 result = 346 model_->SetOriginalImage(node, GURL("http://example.com/i.jpg"), 33, 44); 347 ASSERT_TRUE(result); 348 349 GURL url; 350 int width; 351 int height; 352 result = model_->GetOriginalImage(node, &url, &width, &height); 353 ASSERT_TRUE(result); 354 EXPECT_EQ(url, GURL("http://example.com/i.jpg")); 355 EXPECT_EQ(width, 33); 356 EXPECT_EQ(height, 44); 357 EXPECT_EQ("v1.0", GetVersion(node)); 358 } 359 360 TEST_F(EnhancedBookmarkModelTest, TestRemoteId) { 361 const BookmarkNode* node = AddBookmark(); 362 // Verify that the remote id starts with the correct prefix. 363 EXPECT_TRUE(StartsWithASCII(model_->GetRemoteId(node), "ebc_", true)); 364 365 // Getting the remote id for nodes that don't have them should return the 366 // empty string. 367 const BookmarkNode* existing_node = 368 bookmark_model_->AddURL(bookmark_model_->other_node(), 369 0, 370 base::ASCIIToUTF16("Title"), 371 GURL(GURL(BOOKMARK_URL))); 372 EXPECT_TRUE(model_->GetRemoteId(existing_node).empty()); 373 374 // Folder nodes should not have a remote id set on creation. 375 const BookmarkNode* folder_node = AddFolder(); 376 EXPECT_TRUE(model_->GetRemoteId(folder_node).empty()); 377 } 378 379 TEST_F(EnhancedBookmarkModelTest, TestEmptyDescription) { 380 const BookmarkNode* node = AddBookmark(); 381 382 std::string description(model_->GetDescription(node)); 383 EXPECT_EQ(description, ""); 384 } 385 386 TEST_F(EnhancedBookmarkModelTest, TestDescription) { 387 const BookmarkNode* node = AddBookmark(); 388 const std::string description("This is the most useful description of all."); 389 390 // Set the description. 391 model_->SetDescription(node, description); 392 393 // Check the description is the one that was set. 394 EXPECT_EQ(model_->GetDescription(node), description); 395 EXPECT_EQ("v1.0", GetVersion(node)); 396 } 397 398 // If there is no notes field, the description should fall back on the snippet. 399 TEST_F(EnhancedBookmarkModelTest, TestDescriptionFallback) { 400 const BookmarkNode* node = AddBookmark(); 401 402 // Binary serialize the protobuf. 403 image::collections::PageData data; 404 data.set_snippet("Joe Bar Team"); 405 ASSERT_TRUE(data.IsInitialized()); 406 std::string output; 407 bool result = data.SerializeToString(&output); 408 ASSERT_TRUE(result); 409 410 // base64 encode the output. 411 std::string encoded; 412 base::Base64Encode(output, &encoded); 413 bookmark_model_->SetNodeMetaInfo(node, "stars.pageData", encoded); 414 415 // The snippet is used as the description. 416 std::string snippet(model_->GetSnippet(node)); 417 EXPECT_EQ("Joe Bar Team", model_->GetDescription(node)); 418 419 // Set the description. 420 const std::string description("This is the most useful description of all."); 421 model_->SetDescription(node, description); 422 423 // Check the description is the one that was set. 424 EXPECT_EQ(model_->GetDescription(node), description); 425 } 426 427 // Makes sure that the stars.version field is set every time 428 // EnhancedBookmarkModel makes a change to a node. 429 TEST_F(EnhancedBookmarkModelTest, TestVersionField) { 430 const BookmarkNode* node = AddBookmark(); 431 EXPECT_EQ("", GetVersion(node)); 432 433 model_->SetDescription(node, "foo"); 434 EXPECT_EQ("v1.0", GetVersion(node)); 435 436 // Add a suffix to the version to set. 437 model_->SetVersionSuffix("alpha"); 438 439 model_->SetDescription(node, "foo"); 440 // Since the description didn't actually change, the version field should 441 // not either. 442 EXPECT_EQ("v1.0", GetVersion(node)); 443 444 model_->SetDescription(node, "bar"); 445 EXPECT_EQ("v1.0/alpha", GetVersion(node)); 446 } 447 448 // Verifies that duplicate nodes are reset when the model is created. 449 TEST_F(EnhancedBookmarkModelTest, ResetDuplicateNodesOnInitialization) { 450 model_->Shutdown(); 451 452 const BookmarkNode* parent = bookmark_model_->other_node(); 453 const BookmarkNode* node1 = bookmark_model_->AddURL( 454 parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL)); 455 const BookmarkNode* node2 = bookmark_model_->AddURL( 456 parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL)); 457 const BookmarkNode* node3 = bookmark_model_->AddURL( 458 parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL)); 459 const BookmarkNode* node4 = bookmark_model_->AddURL( 460 parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL)); 461 462 bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1"); 463 bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_2"); 464 bookmark_model_->SetNodeMetaInfo(node3, "stars.id", "c_1"); 465 bookmark_model_->SetNodeMetaInfo(node4, "stars.id", "c_1"); 466 EXPECT_EQ("c_1", GetId(node1)); 467 EXPECT_EQ("c_2", GetId(node2)); 468 EXPECT_EQ("c_1", GetId(node3)); 469 EXPECT_EQ("c_1", GetId(node4)); 470 471 model_.reset(new EnhancedBookmarkModel(bookmark_model_.get(), "v2.0")); 472 base::RunLoop().RunUntilIdle(); 473 EXPECT_EQ("c_2", GetId(node2)); 474 EXPECT_EQ("", GetId(node1)); 475 EXPECT_EQ("", GetId(node3)); 476 EXPECT_EQ("", GetId(node4)); 477 EXPECT_EQ("c_1", GetOldId(node1)); 478 EXPECT_EQ("c_1", GetOldId(node3)); 479 EXPECT_EQ("c_1", GetOldId(node4)); 480 EXPECT_EQ("v2.0", GetVersion(node1)); 481 EXPECT_EQ("v2.0", GetVersion(node3)); 482 EXPECT_EQ("v2.0", GetVersion(node4)); 483 } 484 485 // Verifies that duplicate nodes are reset if one is created. 486 TEST_F(EnhancedBookmarkModelTest, ResetDuplicateAddedNodes) { 487 BookmarkNode::MetaInfoMap meta_info; 488 meta_info["stars.id"] = "c_1"; 489 const BookmarkNode* parent = bookmark_model_->other_node(); 490 491 const BookmarkNode* node1 = 492 bookmark_model_->AddURLWithCreationTimeAndMetaInfo( 493 parent, 494 0, 495 base::ASCIIToUTF16("Some title"), 496 GURL(BOOKMARK_URL), 497 base::Time::Now(), 498 &meta_info); 499 EXPECT_EQ("c_1", GetId(node1)); 500 501 const BookmarkNode* node2 = 502 bookmark_model_->AddURLWithCreationTimeAndMetaInfo( 503 parent, 504 0, 505 base::ASCIIToUTF16("Some title"), 506 GURL(BOOKMARK_URL), 507 base::Time::Now(), 508 &meta_info); 509 510 base::RunLoop().RunUntilIdle(); 511 EXPECT_EQ("", GetId(node1)); 512 EXPECT_EQ("", GetId(node2)); 513 EXPECT_EQ("c_1", GetOldId(node1)); 514 EXPECT_EQ("c_1", GetOldId(node2)); 515 EXPECT_EQ("v1.0", GetVersion(node1)); 516 EXPECT_EQ("v1.0", GetVersion(node2)); 517 } 518 519 // Verifies that duplicate nodes are reset if an id is changed to a duplicate 520 // value. 521 TEST_F(EnhancedBookmarkModelTest, ResetDuplicateChangedNodes) { 522 const BookmarkNode* node1 = AddBookmark(); 523 const BookmarkNode* node2 = AddBookmark(); 524 525 bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1"); 526 EXPECT_EQ("c_1", GetId(node1)); 527 528 bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_1"); 529 base::RunLoop().RunUntilIdle(); 530 EXPECT_EQ("", GetId(node1)); 531 EXPECT_EQ("", GetId(node2)); 532 EXPECT_EQ("c_1", GetOldId(node1)); 533 EXPECT_EQ("c_1", GetOldId(node2)); 534 EXPECT_EQ("v1.0", GetVersion(node1)); 535 EXPECT_EQ("v1.0", GetVersion(node2)); 536 } 537 538 TEST_F(EnhancedBookmarkModelTest, SetMultipleMetaInfo) { 539 const BookmarkNode* node = AddBookmark(); 540 BookmarkNode::MetaInfoMap meta_info; 541 meta_info["a"] = "aa"; 542 meta_info["b"] = "bb"; 543 544 model_->SetVersionSuffix("1"); 545 model_->SetMultipleMetaInfo(node, meta_info); 546 EXPECT_EQ("aa", GetMetaInfoField(node, "a")); 547 EXPECT_EQ("bb", GetMetaInfoField(node, "b")); 548 EXPECT_EQ("v1.0/1", GetVersion(node)); 549 550 // Not present fields does not erase the fields already set on the node. 551 meta_info["a"] = "aaa"; 552 model_->SetVersionSuffix("2"); 553 model_->SetMultipleMetaInfo(node, meta_info); 554 EXPECT_EQ("aaa", GetMetaInfoField(node, "a")); 555 EXPECT_EQ("bb", GetMetaInfoField(node, "b")); 556 EXPECT_EQ("v1.0/2", GetVersion(node)); 557 558 // Not actually changing any values should not set the version field. 559 model_->SetVersionSuffix("3"); 560 model_->SetMultipleMetaInfo(node, meta_info); 561 EXPECT_EQ("v1.0/2", GetVersion(node)); 562 } 563 564 TEST_F(EnhancedBookmarkModelTest, ObserverShuttingDownEvent) { 565 EXPECT_EQ(0, shutting_down_calls_); 566 model_->Shutdown(); 567 EXPECT_EQ(1, shutting_down_calls_); 568 model_.reset(); 569 } 570 571 TEST_F(EnhancedBookmarkModelTest, ObserverNodeAddedEvent) { 572 EXPECT_EQ(0, added_calls_); 573 const BookmarkNode* node = AddBookmark(); 574 EXPECT_EQ(1, added_calls_); 575 EXPECT_EQ(node, last_added_); 576 577 const BookmarkNode* folder = AddFolder(); 578 EXPECT_EQ(2, added_calls_); 579 EXPECT_EQ(folder, last_added_); 580 } 581 582 TEST_F(EnhancedBookmarkModelTest, ObserverNodeRemovedEvent) { 583 const BookmarkNode* node = AddBookmark(); 584 const BookmarkNode* folder = AddFolder(); 585 586 EXPECT_EQ(0, removed_calls_); 587 bookmark_model_->Remove(node->parent(), node->parent()->GetIndexOf(node)); 588 EXPECT_EQ(1, removed_calls_); 589 EXPECT_EQ(node, last_removed_); 590 591 bookmark_model_->Remove(folder->parent(), 592 folder->parent()->GetIndexOf(folder)); 593 EXPECT_EQ(2, removed_calls_); 594 EXPECT_EQ(folder, last_removed_); 595 } 596 597 TEST_F(EnhancedBookmarkModelTest, ObserverAllUserNodesRemovedEvent) { 598 AddBookmark(); 599 AddFolder(); 600 EXPECT_EQ(0, all_user_nodes_removed_calls_); 601 bookmark_model_->RemoveAllUserBookmarks(); 602 EXPECT_EQ(0, removed_calls_); 603 EXPECT_EQ(1, all_user_nodes_removed_calls_); 604 } 605 606 TEST_F(EnhancedBookmarkModelTest, ObserverRemoteIdChangedEvent) { 607 const BookmarkNode* node1 = AddFolder(); 608 const BookmarkNode* node2 = AddFolder(); 609 610 EXPECT_EQ(0, remote_id_changed_calls_); 611 bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1"); 612 base::RunLoop().RunUntilIdle(); 613 EXPECT_EQ(1, remote_id_changed_calls_); 614 EXPECT_EQ(node1, last_remote_id_node_); 615 EXPECT_EQ("", last_old_remote_id_); 616 EXPECT_EQ("c_1", last_remote_id_); 617 618 bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_2"); 619 base::RunLoop().RunUntilIdle(); 620 EXPECT_EQ(2, remote_id_changed_calls_); 621 EXPECT_EQ(node2, last_remote_id_node_); 622 EXPECT_EQ("", last_old_remote_id_); 623 EXPECT_EQ("c_2", last_remote_id_); 624 625 bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_3"); 626 base::RunLoop().RunUntilIdle(); 627 EXPECT_EQ(3, remote_id_changed_calls_); 628 EXPECT_EQ(node1, last_remote_id_node_); 629 EXPECT_EQ("c_1", last_old_remote_id_); 630 EXPECT_EQ("c_3", last_remote_id_); 631 632 // Set to duplicate ids. 633 bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_3"); 634 EXPECT_EQ(4, remote_id_changed_calls_); 635 EXPECT_EQ(node2, last_remote_id_node_); 636 EXPECT_EQ("c_2", last_old_remote_id_); 637 EXPECT_EQ("c_3", last_remote_id_); 638 base::RunLoop().RunUntilIdle(); 639 EXPECT_EQ(6, remote_id_changed_calls_); 640 EXPECT_EQ("", last_remote_id_); 641 } 642 643 TEST_F(EnhancedBookmarkModelTest, ShutDownWhileResetDuplicationScheduled) { 644 const BookmarkNode* node1 = AddBookmark(); 645 const BookmarkNode* node2 = AddBookmark(); 646 bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1"); 647 bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_1"); 648 model_->Shutdown(); 649 model_.reset(); 650 base::RunLoop().RunUntilIdle(); 651 } 652