OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Unit tests for the SyncApi. Note that a lot of the underlying | 5 // Unit tests for the SyncApi. Note that a lot of the underlying |
6 // functionality is provided by the Syncable layer, which has its own | 6 // functionality is provided by the Syncable layer, which has its own |
7 // unit tests. We'll test SyncApi specific things in this harness. | 7 // unit tests. We'll test SyncApi specific things in this harness. |
8 | 8 |
9 #include <cstddef> | 9 #include <cstddef> |
10 #include <map> | 10 #include <map> |
(...skipping 22 matching lines...) Expand all Loading... |
33 #include "chrome/browser/sync/internal_api/write_node.h" | 33 #include "chrome/browser/sync/internal_api/write_node.h" |
34 #include "chrome/browser/sync/internal_api/write_transaction.h" | 34 #include "chrome/browser/sync/internal_api/write_transaction.h" |
35 #include "chrome/browser/sync/js/js_arg_list.h" | 35 #include "chrome/browser/sync/js/js_arg_list.h" |
36 #include "chrome/browser/sync/js/js_backend.h" | 36 #include "chrome/browser/sync/js/js_backend.h" |
37 #include "chrome/browser/sync/js/js_event_handler.h" | 37 #include "chrome/browser/sync/js/js_event_handler.h" |
38 #include "chrome/browser/sync/js/js_reply_handler.h" | 38 #include "chrome/browser/sync/js/js_reply_handler.h" |
39 #include "chrome/browser/sync/js/js_test_util.h" | 39 #include "chrome/browser/sync/js/js_test_util.h" |
40 #include "chrome/browser/sync/notifier/sync_notifier.h" | 40 #include "chrome/browser/sync/notifier/sync_notifier.h" |
41 #include "chrome/browser/sync/notifier/sync_notifier_observer.h" | 41 #include "chrome/browser/sync/notifier/sync_notifier_observer.h" |
42 #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" | 42 #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" |
| 43 #include "chrome/browser/sync/protocol/extension_specifics.pb.h" |
43 #include "chrome/browser/sync/protocol/password_specifics.pb.h" | 44 #include "chrome/browser/sync/protocol/password_specifics.pb.h" |
44 #include "chrome/browser/sync/protocol/proto_value_conversions.h" | 45 #include "chrome/browser/sync/protocol/proto_value_conversions.h" |
45 #include "chrome/browser/sync/protocol/sync.pb.h" | 46 #include "chrome/browser/sync/protocol/sync.pb.h" |
46 #include "chrome/browser/sync/sessions/sync_session.h" | 47 #include "chrome/browser/sync/sessions/sync_session.h" |
47 #include "chrome/browser/sync/syncable/directory_manager.h" | 48 #include "chrome/browser/sync/syncable/directory_manager.h" |
48 #include "chrome/browser/sync/syncable/syncable.h" | 49 #include "chrome/browser/sync/syncable/syncable.h" |
49 #include "chrome/browser/sync/syncable/syncable_id.h" | 50 #include "chrome/browser/sync/syncable/syncable_id.h" |
50 #include "chrome/browser/sync/test/engine/test_user_share.h" | 51 #include "chrome/browser/sync/test/engine/test_user_share.h" |
51 #include "chrome/browser/sync/util/cryptographer.h" | 52 #include "chrome/browser/sync/util/cryptographer.h" |
52 #include "chrome/test/base/values_test_util.h" | 53 #include "chrome/test/base/values_test_util.h" |
(...skipping 13 matching lines...) Expand all Loading... |
66 using browser_sync::MockJsReplyHandler; | 67 using browser_sync::MockJsReplyHandler; |
67 using browser_sync::ModelSafeRoutingInfo; | 68 using browser_sync::ModelSafeRoutingInfo; |
68 using browser_sync::ModelSafeWorker; | 69 using browser_sync::ModelSafeWorker; |
69 using browser_sync::ModelSafeWorkerRegistrar; | 70 using browser_sync::ModelSafeWorkerRegistrar; |
70 using browser_sync::sessions::SyncSessionSnapshot; | 71 using browser_sync::sessions::SyncSessionSnapshot; |
71 using browser_sync::WeakHandle; | 72 using browser_sync::WeakHandle; |
72 using syncable::GetAllRealModelTypes; | 73 using syncable::GetAllRealModelTypes; |
73 using syncable::kEncryptedString; | 74 using syncable::kEncryptedString; |
74 using syncable::ModelType; | 75 using syncable::ModelType; |
75 using syncable::ModelTypeSet; | 76 using syncable::ModelTypeSet; |
76 using test::ExpectDictDictionaryValue; | |
77 using test::ExpectDictStringValue; | 77 using test::ExpectDictStringValue; |
78 using testing::_; | 78 using testing::_; |
79 using testing::AnyNumber; | 79 using testing::AnyNumber; |
80 using testing::AtLeast; | 80 using testing::AtLeast; |
81 using testing::InSequence; | 81 using testing::InSequence; |
82 using testing::Invoke; | 82 using testing::Invoke; |
83 using testing::SaveArg; | 83 using testing::SaveArg; |
84 using testing::StrictMock; | 84 using testing::StrictMock; |
85 | 85 |
86 namespace sync_api { | 86 namespace sync_api { |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 scoped_ptr<DictionaryValue> details(node.GetDetailsAsValue()); | 551 scoped_ptr<DictionaryValue> details(node.GetDetailsAsValue()); |
552 if (details.get()) { | 552 if (details.get()) { |
553 CheckNodeValue(node, *details, true); | 553 CheckNodeValue(node, *details, true); |
554 } else { | 554 } else { |
555 ADD_FAILURE(); | 555 ADD_FAILURE(); |
556 } | 556 } |
557 } | 557 } |
558 | 558 |
559 namespace { | 559 namespace { |
560 | 560 |
561 void ExpectChangeRecordActionValue(ChangeRecord::Action expected_value, | |
562 const DictionaryValue& value, | |
563 const std::string& key) { | |
564 std::string str_value; | |
565 EXPECT_TRUE(value.GetString(key, &str_value)); | |
566 switch (expected_value) { | |
567 case ChangeRecord::ACTION_ADD: | |
568 EXPECT_EQ("Add", str_value); | |
569 break; | |
570 case ChangeRecord::ACTION_UPDATE: | |
571 EXPECT_EQ("Update", str_value); | |
572 break; | |
573 case ChangeRecord::ACTION_DELETE: | |
574 EXPECT_EQ("Delete", str_value); | |
575 break; | |
576 default: | |
577 NOTREACHED(); | |
578 break; | |
579 } | |
580 } | |
581 | |
582 void CheckNonDeleteChangeRecordValue(const ChangeRecord& record, | |
583 const DictionaryValue& value, | |
584 BaseTransaction* trans) { | |
585 EXPECT_NE(ChangeRecord::ACTION_DELETE, record.action); | |
586 ExpectChangeRecordActionValue(record.action, value, "action"); | |
587 { | |
588 ReadNode node(trans); | |
589 EXPECT_TRUE(node.InitByIdLookup(record.id)); | |
590 scoped_ptr<DictionaryValue> expected_details(node.GetDetailsAsValue()); | |
591 ExpectDictDictionaryValue(*expected_details, value, "node"); | |
592 } | |
593 } | |
594 | |
595 void CheckDeleteChangeRecordValue(const ChangeRecord& record, | |
596 const DictionaryValue& value) { | |
597 EXPECT_EQ(ChangeRecord::ACTION_DELETE, record.action); | |
598 ExpectChangeRecordActionValue(record.action, value, "action"); | |
599 DictionaryValue* node_value = NULL; | |
600 EXPECT_TRUE(value.GetDictionary("node", &node_value)); | |
601 if (node_value) { | |
602 ExpectInt64Value(record.id, *node_value, "id"); | |
603 scoped_ptr<DictionaryValue> expected_specifics_value( | |
604 browser_sync::EntitySpecificsToValue(record.specifics)); | |
605 ExpectDictDictionaryValue(*expected_specifics_value, | |
606 *node_value, "specifics"); | |
607 scoped_ptr<DictionaryValue> expected_extra_value; | |
608 if (record.extra.get()) { | |
609 expected_extra_value.reset(record.extra->ToValue()); | |
610 } | |
611 Value* extra_value = NULL; | |
612 EXPECT_EQ(record.extra.get() != NULL, | |
613 node_value->Get("extra", &extra_value)); | |
614 EXPECT_TRUE(Value::Equals(extra_value, expected_extra_value.get())); | |
615 } | |
616 } | |
617 | |
618 class MockExtraChangeRecordData | |
619 : public ExtraPasswordChangeRecordData { | |
620 public: | |
621 MOCK_CONST_METHOD0(ToValue, DictionaryValue*()); | |
622 }; | |
623 | |
624 } // namespace | |
625 | |
626 TEST_F(SyncApiTest, ChangeRecordToValue) { | |
627 int64 child_id = MakeNode(test_user_share_.user_share(), | |
628 syncable::BOOKMARKS, "testtag"); | |
629 sync_pb::EntitySpecifics child_specifics; | |
630 { | |
631 ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); | |
632 ReadNode node(&trans); | |
633 EXPECT_TRUE(node.InitByIdLookup(child_id)); | |
634 child_specifics = node.GetEntry()->Get(syncable::SPECIFICS); | |
635 } | |
636 | |
637 // Add | |
638 { | |
639 ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); | |
640 ChangeRecord record; | |
641 record.action = ChangeRecord::ACTION_ADD; | |
642 record.id = 1; | |
643 record.specifics = child_specifics; | |
644 record.extra.reset(new StrictMock<MockExtraChangeRecordData>()); | |
645 scoped_ptr<DictionaryValue> value(record.ToValue(&trans)); | |
646 CheckNonDeleteChangeRecordValue(record, *value, &trans); | |
647 } | |
648 | |
649 // Update | |
650 { | |
651 ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); | |
652 ChangeRecord record; | |
653 record.action = ChangeRecord::ACTION_UPDATE; | |
654 record.id = child_id; | |
655 record.specifics = child_specifics; | |
656 record.extra.reset(new StrictMock<MockExtraChangeRecordData>()); | |
657 scoped_ptr<DictionaryValue> value(record.ToValue(&trans)); | |
658 CheckNonDeleteChangeRecordValue(record, *value, &trans); | |
659 } | |
660 | |
661 // Delete (no extra) | |
662 { | |
663 ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); | |
664 ChangeRecord record; | |
665 record.action = ChangeRecord::ACTION_DELETE; | |
666 record.id = child_id + 1; | |
667 record.specifics = child_specifics; | |
668 scoped_ptr<DictionaryValue> value(record.ToValue(&trans)); | |
669 CheckDeleteChangeRecordValue(record, *value); | |
670 } | |
671 | |
672 // Delete (with extra) | |
673 { | |
674 ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); | |
675 ChangeRecord record; | |
676 record.action = ChangeRecord::ACTION_DELETE; | |
677 record.id = child_id + 1; | |
678 record.specifics = child_specifics; | |
679 | |
680 DictionaryValue extra_value; | |
681 extra_value.SetString("foo", "bar"); | |
682 scoped_ptr<StrictMock<MockExtraChangeRecordData> > extra( | |
683 new StrictMock<MockExtraChangeRecordData>()); | |
684 EXPECT_CALL(*extra, ToValue()).Times(2).WillRepeatedly( | |
685 Invoke(&extra_value, &DictionaryValue::DeepCopy)); | |
686 | |
687 record.extra.reset(extra.release()); | |
688 scoped_ptr<DictionaryValue> value(record.ToValue(&trans)); | |
689 CheckDeleteChangeRecordValue(record, *value); | |
690 } | |
691 } | |
692 | |
693 namespace { | |
694 | |
695 class TestHttpPostProviderInterface : public HttpPostProviderInterface { | 561 class TestHttpPostProviderInterface : public HttpPostProviderInterface { |
696 public: | 562 public: |
697 virtual ~TestHttpPostProviderInterface() {} | 563 virtual ~TestHttpPostProviderInterface() {} |
698 | 564 |
699 virtual void SetUserAgent(const char* user_agent) OVERRIDE {} | 565 virtual void SetUserAgent(const char* user_agent) OVERRIDE {} |
700 virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE {} | 566 virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE {} |
701 virtual void SetURL(const char* url, int port) OVERRIDE {} | 567 virtual void SetURL(const char* url, int port) OVERRIDE {} |
702 virtual void SetPostPayload(const char* content_type, | 568 virtual void SetPostPayload(const char* content_type, |
703 int content_length, | 569 int content_length, |
704 const char* content) OVERRIDE {} | 570 const char* content) OVERRIDE {} |
(...skipping 20 matching lines...) Expand all Loading... |
725 virtual HttpPostProviderInterface* Create() OVERRIDE { | 591 virtual HttpPostProviderInterface* Create() OVERRIDE { |
726 return new TestHttpPostProviderInterface(); | 592 return new TestHttpPostProviderInterface(); |
727 } | 593 } |
728 virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE { | 594 virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE { |
729 delete http; | 595 delete http; |
730 } | 596 } |
731 }; | 597 }; |
732 | 598 |
733 class SyncManagerObserverMock : public SyncManager::Observer { | 599 class SyncManagerObserverMock : public SyncManager::Observer { |
734 public: | 600 public: |
735 MOCK_METHOD3(OnChangesApplied, | |
736 void(ModelType, | |
737 const BaseTransaction*, | |
738 const ImmutableChangeRecordList&)); // NOLINT | |
739 MOCK_METHOD1(OnChangesComplete, void(ModelType)); // NOLINT | |
740 MOCK_METHOD1(OnSyncCycleCompleted, | 601 MOCK_METHOD1(OnSyncCycleCompleted, |
741 void(const SyncSessionSnapshot*)); // NOLINT | 602 void(const SyncSessionSnapshot*)); // NOLINT |
742 MOCK_METHOD2(OnInitializationComplete, | 603 MOCK_METHOD2(OnInitializationComplete, |
743 void(const WeakHandle<JsBackend>&, bool)); // NOLINT | 604 void(const WeakHandle<JsBackend>&, bool)); // NOLINT |
744 MOCK_METHOD1(OnAuthError, void(const GoogleServiceAuthError&)); // NOLINT | 605 MOCK_METHOD1(OnAuthError, void(const GoogleServiceAuthError&)); // NOLINT |
745 MOCK_METHOD1(OnPassphraseRequired, | 606 MOCK_METHOD1(OnPassphraseRequired, |
746 void(sync_api::PassphraseRequiredReason)); // NOLINT | 607 void(sync_api::PassphraseRequiredReason)); // NOLINT |
747 MOCK_METHOD1(OnPassphraseAccepted, void(const std::string&)); // NOLINT | 608 MOCK_METHOD1(OnPassphraseAccepted, void(const std::string&)); // NOLINT |
748 MOCK_METHOD0(OnStopSyncingPermanently, void()); // NOLINT | 609 MOCK_METHOD0(OnStopSyncingPermanently, void()); // NOLINT |
749 MOCK_METHOD1(OnUpdatedToken, void(const std::string&)); // NOLINT | 610 MOCK_METHOD1(OnUpdatedToken, void(const std::string&)); // NOLINT |
(...skipping 11 matching lines...) Expand all Loading... |
761 MOCK_METHOD1(SetUniqueId, void(const std::string&)); | 622 MOCK_METHOD1(SetUniqueId, void(const std::string&)); |
762 MOCK_METHOD1(SetState, void(const std::string&)); | 623 MOCK_METHOD1(SetState, void(const std::string&)); |
763 MOCK_METHOD2(UpdateCredentials, | 624 MOCK_METHOD2(UpdateCredentials, |
764 void(const std::string&, const std::string&)); | 625 void(const std::string&, const std::string&)); |
765 MOCK_METHOD1(UpdateEnabledTypes, | 626 MOCK_METHOD1(UpdateEnabledTypes, |
766 void(const syncable::ModelTypeSet&)); | 627 void(const syncable::ModelTypeSet&)); |
767 MOCK_METHOD1(SendNotification, void(const syncable::ModelTypeSet&)); | 628 MOCK_METHOD1(SendNotification, void(const syncable::ModelTypeSet&)); |
768 }; | 629 }; |
769 | 630 |
770 class SyncManagerTest : public testing::Test, | 631 class SyncManagerTest : public testing::Test, |
771 public ModelSafeWorkerRegistrar { | 632 public ModelSafeWorkerRegistrar, |
| 633 public SyncManager::ChangeDelegate { |
772 protected: | 634 protected: |
773 SyncManagerTest() | 635 SyncManagerTest() |
774 : ui_thread_(BrowserThread::UI, &ui_loop_), | 636 : ui_thread_(BrowserThread::UI, &ui_loop_), |
775 sync_notifier_mock_(NULL), | 637 sync_notifier_mock_(NULL), |
776 sync_manager_("Test sync manager"), | 638 sync_manager_("Test sync manager"), |
777 sync_notifier_observer_(NULL), | 639 sync_notifier_observer_(NULL), |
778 update_enabled_types_call_count_(0) {} | 640 update_enabled_types_call_count_(0) {} |
779 | 641 |
780 virtual ~SyncManagerTest() { | 642 virtual ~SyncManagerTest() { |
781 EXPECT_FALSE(sync_notifier_mock_); | 643 EXPECT_FALSE(sync_notifier_mock_); |
(...skipping 25 matching lines...) Expand all Loading... |
807 EXPECT_CALL(observer_, OnInitializationComplete(_, _)). | 669 EXPECT_CALL(observer_, OnInitializationComplete(_, _)). |
808 WillOnce(SaveArg<0>(&js_backend_)); | 670 WillOnce(SaveArg<0>(&js_backend_)); |
809 | 671 |
810 EXPECT_FALSE(sync_notifier_observer_); | 672 EXPECT_FALSE(sync_notifier_observer_); |
811 EXPECT_FALSE(js_backend_.IsInitialized()); | 673 EXPECT_FALSE(js_backend_.IsInitialized()); |
812 | 674 |
813 // Takes ownership of |sync_notifier_mock_|. | 675 // Takes ownership of |sync_notifier_mock_|. |
814 sync_manager_.Init(temp_dir_.path(), | 676 sync_manager_.Init(temp_dir_.path(), |
815 WeakHandle<JsEventHandler>(), | 677 WeakHandle<JsEventHandler>(), |
816 "bogus", 0, false, | 678 "bogus", 0, false, |
817 new TestHttpPostProviderFactory(), this, "bogus", | 679 new TestHttpPostProviderFactory(), this, this, "bogus", |
818 credentials, sync_notifier_mock_, "", | 680 credentials, sync_notifier_mock_, "", |
819 true /* setup_for_test_mode */); | 681 true /* setup_for_test_mode */); |
820 | 682 |
821 EXPECT_TRUE(sync_notifier_observer_); | 683 EXPECT_TRUE(sync_notifier_observer_); |
822 EXPECT_TRUE(js_backend_.IsInitialized()); | 684 EXPECT_TRUE(js_backend_.IsInitialized()); |
823 | 685 |
824 EXPECT_EQ(1, update_enabled_types_call_count_); | 686 EXPECT_EQ(1, update_enabled_types_call_count_); |
825 | 687 |
826 ModelSafeRoutingInfo routes; | 688 ModelSafeRoutingInfo routes; |
827 GetModelSafeRoutingInfo(&routes); | 689 GetModelSafeRoutingInfo(&routes); |
828 for (ModelSafeRoutingInfo::iterator i = routes.begin(); i != routes.end(); | 690 for (ModelSafeRoutingInfo::iterator i = routes.begin(); i != routes.end(); |
829 ++i) { | 691 ++i) { |
830 EXPECT_CALL(observer_, OnChangesApplied(i->first, _, _)) | |
831 .RetiresOnSaturation(); | |
832 EXPECT_CALL(observer_, OnChangesComplete(i->first)) | |
833 .RetiresOnSaturation(); | |
834 type_roots_[i->first] = MakeServerNodeForType( | 692 type_roots_[i->first] = MakeServerNodeForType( |
835 sync_manager_.GetUserShare(), i->first); | 693 sync_manager_.GetUserShare(), i->first); |
836 } | 694 } |
837 PumpLoop(); | 695 PumpLoop(); |
838 } | 696 } |
839 | 697 |
840 void TearDown() { | 698 void TearDown() { |
841 sync_manager_.RemoveObserver(&observer_); | 699 sync_manager_.RemoveObserver(&observer_); |
842 sync_manager_.Shutdown(); | 700 sync_manager_.Shutdown(); |
843 sync_notifier_mock_ = NULL; | 701 sync_notifier_mock_ = NULL; |
844 EXPECT_FALSE(sync_notifier_observer_); | 702 EXPECT_FALSE(sync_notifier_observer_); |
845 PumpLoop(); | 703 PumpLoop(); |
846 } | 704 } |
847 | 705 |
848 // ModelSafeWorkerRegistrar implementation. | 706 // ModelSafeWorkerRegistrar implementation. |
849 virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) { | 707 virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) OVERRIDE { |
850 NOTIMPLEMENTED(); | 708 NOTIMPLEMENTED(); |
851 out->clear(); | 709 out->clear(); |
852 } | 710 } |
853 virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) { | 711 virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) OVERRIDE { |
854 (*out)[syncable::NIGORI] = browser_sync::GROUP_PASSIVE; | 712 (*out)[syncable::NIGORI] = browser_sync::GROUP_PASSIVE; |
855 (*out)[syncable::BOOKMARKS] = browser_sync::GROUP_PASSIVE; | 713 (*out)[syncable::BOOKMARKS] = browser_sync::GROUP_PASSIVE; |
856 (*out)[syncable::THEMES] = browser_sync::GROUP_PASSIVE; | 714 (*out)[syncable::THEMES] = browser_sync::GROUP_PASSIVE; |
857 (*out)[syncable::SESSIONS] = browser_sync::GROUP_PASSIVE; | 715 (*out)[syncable::SESSIONS] = browser_sync::GROUP_PASSIVE; |
858 (*out)[syncable::PASSWORDS] = browser_sync::GROUP_PASSIVE; | 716 (*out)[syncable::PASSWORDS] = browser_sync::GROUP_PASSIVE; |
859 } | 717 } |
860 | 718 |
| 719 virtual void OnChangesApplied( |
| 720 syncable::ModelType model_type, |
| 721 const BaseTransaction* trans, |
| 722 const ImmutableChangeRecordList& changes) OVERRIDE {} |
| 723 |
| 724 virtual void OnChangesComplete(syncable::ModelType model_type) OVERRIDE {} |
| 725 |
861 // Helper methods. | 726 // Helper methods. |
862 bool SetUpEncryption() { | 727 bool SetUpEncryption() { |
863 // Mock the Mac Keychain service. The real Keychain can block on user input. | 728 // Mock the Mac Keychain service. The real Keychain can block on user input. |
864 #if defined(OS_MACOSX) | 729 #if defined(OS_MACOSX) |
865 Encryptor::UseMockKeychain(true); | 730 Encryptor::UseMockKeychain(true); |
866 #endif | 731 #endif |
867 | 732 |
868 // We need to create the nigori node as if it were an applied server update. | 733 // We need to create the nigori node as if it were an applied server update. |
869 UserShare* share = sync_manager_.GetUserShare(); | 734 UserShare* share = sync_manager_.GetUserShare(); |
870 int64 nigori_id = GetIdForDataType(syncable::NIGORI); | 735 int64 nigori_id = GetIdForDataType(syncable::NIGORI); |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1585 EXPECT_EQ(syncable::BOOKMARKS, node2.GetModelType()); | 1450 EXPECT_EQ(syncable::BOOKMARKS, node2.GetModelType()); |
1586 // We should de-canonicalize the title in GetTitle(), but the title in the | 1451 // We should de-canonicalize the title in GetTitle(), but the title in the |
1587 // specifics should be stored in the server legal form. | 1452 // specifics should be stored in the server legal form. |
1588 EXPECT_EQ(raw_title2, node2.GetTitle()); | 1453 EXPECT_EQ(raw_title2, node2.GetTitle()); |
1589 EXPECT_EQ(title2, node2.GetBookmarkSpecifics().title()); | 1454 EXPECT_EQ(title2, node2.GetBookmarkSpecifics().title()); |
1590 EXPECT_EQ(url2, node2.GetBookmarkSpecifics().url()); | 1455 EXPECT_EQ(url2, node2.GetBookmarkSpecifics().url()); |
1591 } | 1456 } |
1592 } | 1457 } |
1593 | 1458 |
1594 } // namespace browser_sync | 1459 } // namespace browser_sync |
OLD | NEW |