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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 using browser_sync::MockJsReplyHandler; | 65 using browser_sync::MockJsReplyHandler; |
66 using browser_sync::ModelSafeRoutingInfo; | 66 using browser_sync::ModelSafeRoutingInfo; |
67 using browser_sync::ModelSafeWorker; | 67 using browser_sync::ModelSafeWorker; |
68 using browser_sync::ModelSafeWorkerRegistrar; | 68 using browser_sync::ModelSafeWorkerRegistrar; |
69 using browser_sync::sessions::SyncSessionSnapshot; | 69 using browser_sync::sessions::SyncSessionSnapshot; |
70 using browser_sync::WeakHandle; | 70 using browser_sync::WeakHandle; |
71 using syncable::GetAllRealModelTypes; | 71 using syncable::GetAllRealModelTypes; |
72 using syncable::kEncryptedString; | 72 using syncable::kEncryptedString; |
73 using syncable::ModelType; | 73 using syncable::ModelType; |
74 using syncable::ModelTypeSet; | 74 using syncable::ModelTypeSet; |
75 using test::ExpectDictDictionaryValue; | |
76 using test::ExpectDictStringValue; | 75 using test::ExpectDictStringValue; |
77 using testing::_; | 76 using testing::_; |
78 using testing::AnyNumber; | 77 using testing::AnyNumber; |
79 using testing::AtLeast; | 78 using testing::AtLeast; |
80 using testing::InSequence; | 79 using testing::InSequence; |
81 using testing::Invoke; | 80 using testing::Invoke; |
82 using testing::SaveArg; | 81 using testing::SaveArg; |
83 using testing::StrictMock; | 82 using testing::StrictMock; |
84 | 83 |
85 namespace sync_api { | 84 namespace sync_api { |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 scoped_ptr<DictionaryValue> details(node.GetDetailsAsValue()); | 549 scoped_ptr<DictionaryValue> details(node.GetDetailsAsValue()); |
551 if (details.get()) { | 550 if (details.get()) { |
552 CheckNodeValue(node, *details, true); | 551 CheckNodeValue(node, *details, true); |
553 } else { | 552 } else { |
554 ADD_FAILURE(); | 553 ADD_FAILURE(); |
555 } | 554 } |
556 } | 555 } |
557 | 556 |
558 namespace { | 557 namespace { |
559 | 558 |
560 void ExpectChangeRecordActionValue(ChangeRecord::Action expected_value, | |
561 const DictionaryValue& value, | |
562 const std::string& key) { | |
563 std::string str_value; | |
564 EXPECT_TRUE(value.GetString(key, &str_value)); | |
565 switch (expected_value) { | |
566 case ChangeRecord::ACTION_ADD: | |
567 EXPECT_EQ("Add", str_value); | |
568 break; | |
569 case ChangeRecord::ACTION_UPDATE: | |
570 EXPECT_EQ("Update", str_value); | |
571 break; | |
572 case ChangeRecord::ACTION_DELETE: | |
573 EXPECT_EQ("Delete", str_value); | |
574 break; | |
575 default: | |
576 NOTREACHED(); | |
577 break; | |
578 } | |
579 } | |
580 | |
581 void CheckNonDeleteChangeRecordValue(const ChangeRecord& record, | |
582 const DictionaryValue& value, | |
583 BaseTransaction* trans) { | |
584 EXPECT_NE(ChangeRecord::ACTION_DELETE, record.action); | |
585 ExpectChangeRecordActionValue(record.action, value, "action"); | |
586 { | |
587 ReadNode node(trans); | |
588 EXPECT_TRUE(node.InitByIdLookup(record.id)); | |
589 scoped_ptr<DictionaryValue> expected_details(node.GetDetailsAsValue()); | |
590 ExpectDictDictionaryValue(*expected_details, value, "node"); | |
591 } | |
592 } | |
593 | |
594 void CheckDeleteChangeRecordValue(const ChangeRecord& record, | |
595 const DictionaryValue& value) { | |
596 EXPECT_EQ(ChangeRecord::ACTION_DELETE, record.action); | |
597 ExpectChangeRecordActionValue(record.action, value, "action"); | |
598 DictionaryValue* node_value = NULL; | |
599 EXPECT_TRUE(value.GetDictionary("node", &node_value)); | |
600 if (node_value) { | |
601 ExpectInt64Value(record.id, *node_value, "id"); | |
602 scoped_ptr<DictionaryValue> expected_specifics_value( | |
603 browser_sync::EntitySpecificsToValue(record.specifics)); | |
604 ExpectDictDictionaryValue(*expected_specifics_value, | |
605 *node_value, "specifics"); | |
606 scoped_ptr<DictionaryValue> expected_extra_value; | |
607 if (record.extra.get()) { | |
608 expected_extra_value.reset(record.extra->ToValue()); | |
609 } | |
610 Value* extra_value = NULL; | |
611 EXPECT_EQ(record.extra.get() != NULL, | |
612 node_value->Get("extra", &extra_value)); | |
613 EXPECT_TRUE(Value::Equals(extra_value, expected_extra_value.get())); | |
614 } | |
615 } | |
616 | |
617 class MockExtraChangeRecordData | |
618 : public ExtraPasswordChangeRecordData { | |
619 public: | |
620 MOCK_CONST_METHOD0(ToValue, DictionaryValue*()); | |
621 }; | |
622 | |
623 } // namespace | |
624 | |
625 TEST_F(SyncApiTest, ChangeRecordToValue) { | |
626 int64 child_id = MakeNode(test_user_share_.user_share(), | |
627 syncable::BOOKMARKS, "testtag"); | |
628 sync_pb::EntitySpecifics child_specifics; | |
629 { | |
630 ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); | |
631 ReadNode node(&trans); | |
632 EXPECT_TRUE(node.InitByIdLookup(child_id)); | |
633 child_specifics = node.GetEntry()->Get(syncable::SPECIFICS); | |
634 } | |
635 | |
636 // Add | |
637 { | |
638 ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); | |
639 ChangeRecord record; | |
640 record.action = ChangeRecord::ACTION_ADD; | |
641 record.id = 1; | |
642 record.specifics = child_specifics; | |
643 record.extra.reset(new StrictMock<MockExtraChangeRecordData>()); | |
644 scoped_ptr<DictionaryValue> value(record.ToValue(&trans)); | |
645 CheckNonDeleteChangeRecordValue(record, *value, &trans); | |
646 } | |
647 | |
648 // Update | |
649 { | |
650 ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); | |
651 ChangeRecord record; | |
652 record.action = ChangeRecord::ACTION_UPDATE; | |
653 record.id = child_id; | |
654 record.specifics = child_specifics; | |
655 record.extra.reset(new StrictMock<MockExtraChangeRecordData>()); | |
656 scoped_ptr<DictionaryValue> value(record.ToValue(&trans)); | |
657 CheckNonDeleteChangeRecordValue(record, *value, &trans); | |
658 } | |
659 | |
660 // Delete (no extra) | |
661 { | |
662 ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); | |
663 ChangeRecord record; | |
664 record.action = ChangeRecord::ACTION_DELETE; | |
665 record.id = child_id + 1; | |
666 record.specifics = child_specifics; | |
667 scoped_ptr<DictionaryValue> value(record.ToValue(&trans)); | |
668 CheckDeleteChangeRecordValue(record, *value); | |
669 } | |
670 | |
671 // Delete (with extra) | |
672 { | |
673 ReadTransaction trans(FROM_HERE, test_user_share_.user_share()); | |
674 ChangeRecord record; | |
675 record.action = ChangeRecord::ACTION_DELETE; | |
676 record.id = child_id + 1; | |
677 record.specifics = child_specifics; | |
678 | |
679 DictionaryValue extra_value; | |
680 extra_value.SetString("foo", "bar"); | |
681 scoped_ptr<StrictMock<MockExtraChangeRecordData> > extra( | |
682 new StrictMock<MockExtraChangeRecordData>()); | |
683 EXPECT_CALL(*extra, ToValue()).Times(2).WillRepeatedly( | |
684 Invoke(&extra_value, &DictionaryValue::DeepCopy)); | |
685 | |
686 record.extra.reset(extra.release()); | |
687 scoped_ptr<DictionaryValue> value(record.ToValue(&trans)); | |
688 CheckDeleteChangeRecordValue(record, *value); | |
689 } | |
690 } | |
691 | |
692 namespace { | |
693 | |
694 class TestHttpPostProviderInterface : public HttpPostProviderInterface { | 559 class TestHttpPostProviderInterface : public HttpPostProviderInterface { |
695 public: | 560 public: |
696 virtual ~TestHttpPostProviderInterface() {} | 561 virtual ~TestHttpPostProviderInterface() {} |
697 | 562 |
698 virtual void SetUserAgent(const char* user_agent) OVERRIDE {} | 563 virtual void SetUserAgent(const char* user_agent) OVERRIDE {} |
699 virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE {} | 564 virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE {} |
700 virtual void SetURL(const char* url, int port) OVERRIDE {} | 565 virtual void SetURL(const char* url, int port) OVERRIDE {} |
701 virtual void SetPostPayload(const char* content_type, | 566 virtual void SetPostPayload(const char* content_type, |
702 int content_length, | 567 int content_length, |
703 const char* content) OVERRIDE {} | 568 const char* content) OVERRIDE {} |
(...skipping 20 matching lines...) Expand all Loading... |
724 virtual HttpPostProviderInterface* Create() OVERRIDE { | 589 virtual HttpPostProviderInterface* Create() OVERRIDE { |
725 return new TestHttpPostProviderInterface(); | 590 return new TestHttpPostProviderInterface(); |
726 } | 591 } |
727 virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE { | 592 virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE { |
728 delete http; | 593 delete http; |
729 } | 594 } |
730 }; | 595 }; |
731 | 596 |
732 class SyncManagerObserverMock : public SyncManager::Observer { | 597 class SyncManagerObserverMock : public SyncManager::Observer { |
733 public: | 598 public: |
734 MOCK_METHOD3(OnChangesApplied, | |
735 void(ModelType, | |
736 const BaseTransaction*, | |
737 const ImmutableChangeRecordList&)); // NOLINT | |
738 MOCK_METHOD1(OnChangesComplete, void(ModelType)); // NOLINT | |
739 MOCK_METHOD1(OnSyncCycleCompleted, | 599 MOCK_METHOD1(OnSyncCycleCompleted, |
740 void(const SyncSessionSnapshot*)); // NOLINT | 600 void(const SyncSessionSnapshot*)); // NOLINT |
741 MOCK_METHOD2(OnInitializationComplete, | 601 MOCK_METHOD2(OnInitializationComplete, |
742 void(const WeakHandle<JsBackend>&, bool)); // NOLINT | 602 void(const WeakHandle<JsBackend>&, bool)); // NOLINT |
743 MOCK_METHOD1(OnAuthError, void(const GoogleServiceAuthError&)); // NOLINT | 603 MOCK_METHOD1(OnAuthError, void(const GoogleServiceAuthError&)); // NOLINT |
744 MOCK_METHOD1(OnPassphraseRequired, | 604 MOCK_METHOD1(OnPassphraseRequired, |
745 void(sync_api::PassphraseRequiredReason)); // NOLINT | 605 void(sync_api::PassphraseRequiredReason)); // NOLINT |
746 MOCK_METHOD1(OnPassphraseAccepted, void(const std::string&)); // NOLINT | 606 MOCK_METHOD1(OnPassphraseAccepted, void(const std::string&)); // NOLINT |
747 MOCK_METHOD0(OnStopSyncingPermanently, void()); // NOLINT | 607 MOCK_METHOD0(OnStopSyncingPermanently, void()); // NOLINT |
748 MOCK_METHOD1(OnUpdatedToken, void(const std::string&)); // NOLINT | 608 MOCK_METHOD1(OnUpdatedToken, void(const std::string&)); // NOLINT |
(...skipping 11 matching lines...) Expand all Loading... |
760 MOCK_METHOD1(SetUniqueId, void(const std::string&)); | 620 MOCK_METHOD1(SetUniqueId, void(const std::string&)); |
761 MOCK_METHOD1(SetState, void(const std::string&)); | 621 MOCK_METHOD1(SetState, void(const std::string&)); |
762 MOCK_METHOD2(UpdateCredentials, | 622 MOCK_METHOD2(UpdateCredentials, |
763 void(const std::string&, const std::string&)); | 623 void(const std::string&, const std::string&)); |
764 MOCK_METHOD1(UpdateEnabledTypes, | 624 MOCK_METHOD1(UpdateEnabledTypes, |
765 void(const syncable::ModelTypeSet&)); | 625 void(const syncable::ModelTypeSet&)); |
766 MOCK_METHOD1(SendNotification, void(const syncable::ModelTypeSet&)); | 626 MOCK_METHOD1(SendNotification, void(const syncable::ModelTypeSet&)); |
767 }; | 627 }; |
768 | 628 |
769 class SyncManagerTest : public testing::Test, | 629 class SyncManagerTest : public testing::Test, |
770 public ModelSafeWorkerRegistrar { | 630 public ModelSafeWorkerRegistrar, |
| 631 public SyncManager::ChangeDelegate { |
771 protected: | 632 protected: |
772 SyncManagerTest() | 633 SyncManagerTest() |
773 : ui_thread_(BrowserThread::UI, &ui_loop_), | 634 : ui_thread_(BrowserThread::UI, &ui_loop_), |
774 sync_notifier_mock_(NULL), | 635 sync_notifier_mock_(NULL), |
775 sync_manager_("Test sync manager"), | 636 sync_manager_("Test sync manager"), |
776 sync_notifier_observer_(NULL), | 637 sync_notifier_observer_(NULL), |
777 update_enabled_types_call_count_(0) {} | 638 update_enabled_types_call_count_(0) {} |
778 | 639 |
779 virtual ~SyncManagerTest() { | 640 virtual ~SyncManagerTest() { |
780 EXPECT_FALSE(sync_notifier_mock_); | 641 EXPECT_FALSE(sync_notifier_mock_); |
(...skipping 25 matching lines...) Expand all Loading... |
806 EXPECT_CALL(observer_, OnInitializationComplete(_, _)). | 667 EXPECT_CALL(observer_, OnInitializationComplete(_, _)). |
807 WillOnce(SaveArg<0>(&js_backend_)); | 668 WillOnce(SaveArg<0>(&js_backend_)); |
808 | 669 |
809 EXPECT_FALSE(sync_notifier_observer_); | 670 EXPECT_FALSE(sync_notifier_observer_); |
810 EXPECT_FALSE(js_backend_.IsInitialized()); | 671 EXPECT_FALSE(js_backend_.IsInitialized()); |
811 | 672 |
812 // Takes ownership of |sync_notifier_mock_|. | 673 // Takes ownership of |sync_notifier_mock_|. |
813 sync_manager_.Init(temp_dir_.path(), | 674 sync_manager_.Init(temp_dir_.path(), |
814 WeakHandle<JsEventHandler>(), | 675 WeakHandle<JsEventHandler>(), |
815 "bogus", 0, false, | 676 "bogus", 0, false, |
816 new TestHttpPostProviderFactory(), this, "bogus", | 677 new TestHttpPostProviderFactory(), this, this, "bogus", |
817 credentials, sync_notifier_mock_, "", | 678 credentials, sync_notifier_mock_, "", |
818 true /* setup_for_test_mode */); | 679 true /* setup_for_test_mode */); |
819 | 680 |
820 EXPECT_TRUE(sync_notifier_observer_); | 681 EXPECT_TRUE(sync_notifier_observer_); |
821 EXPECT_TRUE(js_backend_.IsInitialized()); | 682 EXPECT_TRUE(js_backend_.IsInitialized()); |
822 | 683 |
823 EXPECT_EQ(1, update_enabled_types_call_count_); | 684 EXPECT_EQ(1, update_enabled_types_call_count_); |
824 | 685 |
825 ModelSafeRoutingInfo routes; | 686 ModelSafeRoutingInfo routes; |
826 GetModelSafeRoutingInfo(&routes); | 687 GetModelSafeRoutingInfo(&routes); |
827 for (ModelSafeRoutingInfo::iterator i = routes.begin(); i != routes.end(); | 688 for (ModelSafeRoutingInfo::iterator i = routes.begin(); i != routes.end(); |
828 ++i) { | 689 ++i) { |
829 EXPECT_CALL(observer_, OnChangesApplied(i->first, _, _)) | |
830 .RetiresOnSaturation(); | |
831 EXPECT_CALL(observer_, OnChangesComplete(i->first)) | |
832 .RetiresOnSaturation(); | |
833 type_roots_[i->first] = MakeServerNodeForType( | 690 type_roots_[i->first] = MakeServerNodeForType( |
834 sync_manager_.GetUserShare(), i->first); | 691 sync_manager_.GetUserShare(), i->first); |
835 } | 692 } |
836 PumpLoop(); | 693 PumpLoop(); |
837 } | 694 } |
838 | 695 |
839 void TearDown() { | 696 void TearDown() { |
840 sync_manager_.RemoveObserver(&observer_); | 697 sync_manager_.RemoveObserver(&observer_); |
841 sync_manager_.Shutdown(); | 698 sync_manager_.Shutdown(); |
842 sync_notifier_mock_ = NULL; | 699 sync_notifier_mock_ = NULL; |
843 EXPECT_FALSE(sync_notifier_observer_); | 700 EXPECT_FALSE(sync_notifier_observer_); |
844 PumpLoop(); | 701 PumpLoop(); |
845 } | 702 } |
846 | 703 |
847 // ModelSafeWorkerRegistrar implementation. | 704 // ModelSafeWorkerRegistrar implementation. |
848 virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) { | 705 virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) OVERRIDE { |
849 NOTIMPLEMENTED(); | 706 NOTIMPLEMENTED(); |
850 out->clear(); | 707 out->clear(); |
851 } | 708 } |
852 virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) { | 709 virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) OVERRIDE { |
853 (*out)[syncable::NIGORI] = browser_sync::GROUP_PASSIVE; | 710 (*out)[syncable::NIGORI] = browser_sync::GROUP_PASSIVE; |
854 (*out)[syncable::BOOKMARKS] = browser_sync::GROUP_PASSIVE; | 711 (*out)[syncable::BOOKMARKS] = browser_sync::GROUP_PASSIVE; |
855 (*out)[syncable::THEMES] = browser_sync::GROUP_PASSIVE; | 712 (*out)[syncable::THEMES] = browser_sync::GROUP_PASSIVE; |
856 (*out)[syncable::SESSIONS] = browser_sync::GROUP_PASSIVE; | 713 (*out)[syncable::SESSIONS] = browser_sync::GROUP_PASSIVE; |
857 (*out)[syncable::PASSWORDS] = browser_sync::GROUP_PASSIVE; | 714 (*out)[syncable::PASSWORDS] = browser_sync::GROUP_PASSIVE; |
858 } | 715 } |
859 | 716 |
| 717 virtual void OnChangesApplied( |
| 718 syncable::ModelType model_type, |
| 719 const BaseTransaction* trans, |
| 720 const ImmutableChangeRecordList& changes) OVERRIDE {} |
| 721 |
| 722 virtual void OnChangesComplete(syncable::ModelType model_type) OVERRIDE {} |
| 723 |
860 // Helper methods. | 724 // Helper methods. |
861 bool SetUpEncryption() { | 725 bool SetUpEncryption() { |
862 // Mock the Mac Keychain service. The real Keychain can block on user input. | 726 // Mock the Mac Keychain service. The real Keychain can block on user input. |
863 #if defined(OS_MACOSX) | 727 #if defined(OS_MACOSX) |
864 Encryptor::UseMockKeychain(true); | 728 Encryptor::UseMockKeychain(true); |
865 #endif | 729 #endif |
866 | 730 |
867 // We need to create the nigori node as if it were an applied server update. | 731 // We need to create the nigori node as if it were an applied server update. |
868 UserShare* share = sync_manager_.GetUserShare(); | 732 UserShare* share = sync_manager_.GetUserShare(); |
869 int64 nigori_id = GetIdForDataType(syncable::NIGORI); | 733 int64 nigori_id = GetIdForDataType(syncable::NIGORI); |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1547 ReadNode node(&trans); | 1411 ReadNode node(&trans); |
1548 EXPECT_TRUE(node.InitByIdLookup(node1)); | 1412 EXPECT_TRUE(node.InitByIdLookup(node1)); |
1549 EXPECT_EQ(syncable::BOOKMARKS, node.GetModelType()); | 1413 EXPECT_EQ(syncable::BOOKMARKS, node.GetModelType()); |
1550 EXPECT_EQ(title, node.GetTitle()); | 1414 EXPECT_EQ(title, node.GetTitle()); |
1551 EXPECT_EQ(title, node.GetBookmarkSpecifics().title()); | 1415 EXPECT_EQ(title, node.GetBookmarkSpecifics().title()); |
1552 EXPECT_EQ(url, node.GetBookmarkSpecifics().url()); | 1416 EXPECT_EQ(url, node.GetBookmarkSpecifics().url()); |
1553 } | 1417 } |
1554 } | 1418 } |
1555 | 1419 |
1556 } // namespace browser_sync | 1420 } // namespace browser_sync |
OLD | NEW |