| Index: ios/chrome/test/app/sync_test_util.mm
|
| diff --git a/ios/chrome/test/app/sync_test_util.mm b/ios/chrome/test/app/sync_test_util.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9c7559ec556e909af7d1f392039ed7384b7f133d
|
| --- /dev/null
|
| +++ b/ios/chrome/test/app/sync_test_util.mm
|
| @@ -0,0 +1,351 @@
|
| +// Copyright 2016 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.
|
| +
|
| +#import "ios/chrome/test/app/sync_test_util.h"
|
| +
|
| +#include <set>
|
| +#include <string>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/mac/bind_objc_block.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "base/test/ios/wait_util.h"
|
| +#include "components/autofill/core/browser/personal_data_manager.h"
|
| +#include "components/browser_sync/profile_sync_service.h"
|
| +#include "components/history/core/browser/history_service.h"
|
| +#include "components/keyed_service/core/service_access_type.h"
|
| +#include "components/sync/engine/net/http_bridge_network_resources.h"
|
| +#include "components/sync/test/fake_server/entity_builder_factory.h"
|
| +#include "components/sync/test/fake_server/fake_server.h"
|
| +#include "components/sync/test/fake_server/fake_server_network_resources.h"
|
| +#include "components/sync/test/fake_server/fake_server_verifier.h"
|
| +#include "components/sync/test/fake_server/sessions_hierarchy.h"
|
| +#include "components/sync/test/fake_server/tombstone_entity.h"
|
| +#include "components/sync/test/fake_server/unique_client_entity.h"
|
| +#include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
|
| +#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
|
| +#include "ios/chrome/browser/history/history_service_factory.h"
|
| +#include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
|
| +#include "ios/chrome/browser/sync/sync_setup_service.h"
|
| +#include "ios/chrome/browser/sync/sync_setup_service_factory.h"
|
| +#import "ios/chrome/test/app/chrome_test_util.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace {
|
| +
|
| +fake_server::FakeServer* gSyncFakeServer = nullptr;
|
| +
|
| +NSString* const kSyncTestErrorDomain = @"SyncTestDomain";
|
| +
|
| +// Overrides the network resources of the current ProfileSyncService with
|
| +// |resources|.
|
| +void OverrideSyncNetworkResources(
|
| + std::unique_ptr<syncer::NetworkResources> resources) {
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + DCHECK(browser_state);
|
| + browser_sync::ProfileSyncService* service =
|
| + IOSChromeProfileSyncServiceFactory::GetForBrowserState(browser_state);
|
| + service->OverrideNetworkResourcesForTest(std::move(resources));
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +namespace chrome_test_util {
|
| +
|
| +void SetUpFakeSyncServer() {
|
| + DCHECK(!gSyncFakeServer);
|
| + gSyncFakeServer = new fake_server::FakeServer();
|
| + OverrideSyncNetworkResources(base::WrapUnique<syncer::NetworkResources>(
|
| + new fake_server::FakeServerNetworkResources(
|
| + gSyncFakeServer->AsWeakPtr())));
|
| +}
|
| +
|
| +void TearDownFakeSyncServer() {
|
| + DCHECK(gSyncFakeServer);
|
| + delete gSyncFakeServer;
|
| + gSyncFakeServer = nullptr;
|
| + OverrideSyncNetworkResources(base::WrapUnique<syncer::NetworkResources>(
|
| + new syncer::HttpBridgeNetworkResources()));
|
| +}
|
| +
|
| +void StartSync() {
|
| + DCHECK(!IsSyncInitialized());
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + SyncSetupService* sync_setup_service =
|
| + SyncSetupServiceFactory::GetForBrowserState(browser_state);
|
| + sync_setup_service->SetSyncEnabled(true);
|
| +}
|
| +
|
| +void StopSync() {
|
| + DCHECK(IsSyncInitialized());
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + SyncSetupService* sync_setup_service =
|
| + SyncSetupServiceFactory::GetForBrowserState(browser_state);
|
| + sync_setup_service->SetSyncEnabled(false);
|
| +}
|
| +
|
| +void TriggerSyncCycle(syncer::ModelType type) {
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + browser_sync::ProfileSyncService* profile_sync_service =
|
| + IOSChromeProfileSyncServiceFactory::GetForBrowserState(browser_state);
|
| + const syncer::ModelTypeSet types(type);
|
| + profile_sync_service->RefreshTypesForTest(types);
|
| +}
|
| +
|
| +void ClearSyncServerData() {
|
| + DCHECK(gSyncFakeServer);
|
| + gSyncFakeServer->ClearServerData();
|
| +}
|
| +
|
| +int GetNumberOfSyncEntities(syncer::ModelType type) {
|
| + DCHECK(gSyncFakeServer);
|
| + std::unique_ptr<base::DictionaryValue> entities =
|
| + gSyncFakeServer->GetEntitiesAsDictionaryValue();
|
| +
|
| + std::string model_type_string = ModelTypeToString(type);
|
| + base::ListValue* entity_list = NULL;
|
| + if (!entities->GetList(model_type_string, &entity_list)) {
|
| + return 0;
|
| + }
|
| + return entity_list->GetSize();
|
| +}
|
| +
|
| +BOOL VerifyNumberOfSyncEntitiesWithName(syncer::ModelType type,
|
| + std::string name,
|
| + size_t count,
|
| + NSError** error) {
|
| + DCHECK(gSyncFakeServer);
|
| + fake_server::FakeServerVerifier verifier(gSyncFakeServer);
|
| + testing::AssertionResult result =
|
| + verifier.VerifyEntityCountByTypeAndName(count, type, name);
|
| + if (result != testing::AssertionSuccess() && error != nil) {
|
| + NSDictionary* errorInfo = @{
|
| + NSLocalizedDescriptionKey : base::SysUTF8ToNSString(result.message())
|
| + };
|
| + *error = [NSError errorWithDomain:kSyncTestErrorDomain
|
| + code:0
|
| + userInfo:errorInfo];
|
| + return NO;
|
| + }
|
| + return result == testing::AssertionSuccess();
|
| +}
|
| +
|
| +void InjectBookmarkOnFakeSyncServer(std::string url, std::string title) {
|
| + DCHECK(gSyncFakeServer);
|
| + fake_server::EntityBuilderFactory entity_builder_factory;
|
| + fake_server::BookmarkEntityBuilder bookmark_builder =
|
| + entity_builder_factory.NewBookmarkEntityBuilder(title);
|
| + gSyncFakeServer->InjectEntity(bookmark_builder.BuildBookmark(GURL(url)));
|
| +}
|
| +
|
| +bool IsSyncInitialized() {
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + DCHECK(browser_state);
|
| + syncer::SyncService* syncService =
|
| + IOSChromeProfileSyncServiceFactory::GetForBrowserState(browser_state);
|
| + return syncService->IsEngineInitialized();
|
| +}
|
| +
|
| +std::string GetSyncCacheGuid() {
|
| + DCHECK(IsSyncInitialized());
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + browser_sync::ProfileSyncService* profile_sync_service =
|
| + IOSChromeProfileSyncServiceFactory::GetForBrowserState(browser_state);
|
| + syncer::LocalDeviceInfoProvider* info_provider =
|
| + profile_sync_service->GetLocalDeviceInfoProvider();
|
| + return info_provider->GetLocalSyncCacheGUID();
|
| +}
|
| +
|
| +void InjectAutofillProfileOnFakeSyncServer(std::string guid,
|
| + std::string full_name) {
|
| + DCHECK(gSyncFakeServer);
|
| + sync_pb::EntitySpecifics entity_specifics;
|
| + sync_pb::AutofillProfileSpecifics* autofill_profile =
|
| + entity_specifics.mutable_autofill_profile();
|
| + autofill_profile->add_name_full(full_name);
|
| + autofill_profile->set_guid(guid);
|
| +
|
| + std::unique_ptr<fake_server::FakeServerEntity> entity =
|
| + fake_server::UniqueClientEntity::CreateForInjection(guid,
|
| + entity_specifics);
|
| + gSyncFakeServer->InjectEntity(std::move(entity));
|
| +}
|
| +
|
| +void DeleteAutofillProfileOnFakeSyncServer(std::string guid) {
|
| + DCHECK(gSyncFakeServer);
|
| + std::vector<sync_pb::SyncEntity> autofill_profiles =
|
| + gSyncFakeServer->GetSyncEntitiesByModelType(syncer::AUTOFILL_PROFILE);
|
| + std::string entity_id;
|
| + for (const sync_pb::SyncEntity& autofill_profile : autofill_profiles) {
|
| + if (autofill_profile.specifics().autofill_profile().guid() == guid) {
|
| + entity_id = autofill_profile.id_string();
|
| + break;
|
| + }
|
| + }
|
| + // Delete the entity if it exists.
|
| + if (!entity_id.empty()) {
|
| + std::unique_ptr<fake_server::FakeServerEntity> entity;
|
| + entity = fake_server::TombstoneEntity::Create(entity_id, std::string());
|
| + gSyncFakeServer->InjectEntity(std::move(entity));
|
| + }
|
| +}
|
| +
|
| +bool IsAutofillProfilePresent(std::string guid, std::string full_name) {
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + autofill::PersonalDataManager* personal_data_manager =
|
| + autofill::PersonalDataManagerFactory::GetForBrowserState(browser_state);
|
| + autofill::AutofillProfile* autofill_profile =
|
| + personal_data_manager->GetProfileByGUID(guid);
|
| +
|
| + if (autofill_profile) {
|
| + std::string actual_full_name =
|
| + base::UTF16ToUTF8(autofill_profile->GetRawInfo(autofill::NAME_FULL));
|
| + return actual_full_name == full_name;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void ClearAutofillProfile(std::string guid) {
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + autofill::PersonalDataManager* personal_data_manager =
|
| + autofill::PersonalDataManagerFactory::GetForBrowserState(browser_state);
|
| + personal_data_manager->RemoveByGUID(guid);
|
| +}
|
| +
|
| +BOOL VerifySessionsOnSyncServer(const std::multiset<std::string>& expected_urls,
|
| + NSError** error) {
|
| + DCHECK(gSyncFakeServer);
|
| + fake_server::SessionsHierarchy expected_sessions;
|
| + expected_sessions.AddWindow(expected_urls);
|
| + fake_server::FakeServerVerifier verifier(gSyncFakeServer);
|
| + testing::AssertionResult result = verifier.VerifySessions(expected_sessions);
|
| + if (result != testing::AssertionSuccess() && error != nil) {
|
| + NSDictionary* errorInfo = @{
|
| + NSLocalizedDescriptionKey : base::SysUTF8ToNSString(result.message())
|
| + };
|
| + *error = [NSError errorWithDomain:kSyncTestErrorDomain
|
| + code:0
|
| + userInfo:errorInfo];
|
| + return NO;
|
| + }
|
| + return result == testing::AssertionSuccess();
|
| +}
|
| +
|
| +void AddTypedURLOnClient(const GURL& url) {
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + history::HistoryService* historyService =
|
| + ios::HistoryServiceFactory::GetForBrowserState(
|
| + browser_state, ServiceAccessType::EXPLICIT_ACCESS);
|
| +
|
| + historyService->AddPage(url, base::Time::UnixEpoch(), nullptr, 1, GURL(),
|
| + history::RedirectList(), ui::PAGE_TRANSITION_TYPED,
|
| + history::SOURCE_BROWSED, false);
|
| +}
|
| +
|
| +void InjectTypedURLOnFakeSyncServer(const std::string& url) {
|
| + DCHECK(gSyncFakeServer);
|
| + sync_pb::EntitySpecifics entitySpecifics;
|
| + sync_pb::TypedUrlSpecifics* typedUrl = entitySpecifics.mutable_typed_url();
|
| + typedUrl->set_url(url);
|
| + typedUrl->set_title(url);
|
| + typedUrl->add_visits(base::Time::Max().ToInternalValue());
|
| + typedUrl->add_visit_transitions(sync_pb::SyncEnums::TYPED);
|
| +
|
| + std::unique_ptr<fake_server::FakeServerEntity> entity =
|
| + fake_server::UniqueClientEntity::CreateForInjection(url, entitySpecifics);
|
| + gSyncFakeServer->InjectEntity(std::move(entity));
|
| +}
|
| +
|
| +BOOL IsTypedUrlPresentOnClient(const GURL& url,
|
| + BOOL expect_present,
|
| + NSError** error) {
|
| + // Call the history service.
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + history::HistoryService* history_service =
|
| + ios::HistoryServiceFactory::GetForBrowserState(
|
| + browser_state, ServiceAccessType::EXPLICIT_ACCESS);
|
| +
|
| + const GURL block_safe_url(url);
|
| + std::set<GURL> origins;
|
| + origins.insert(block_safe_url);
|
| +
|
| + __block bool history_service_callback_called = false;
|
| + __block int count = 0;
|
| + using history::OriginCountAndLastVisitMap;
|
| + history_service->GetCountsAndLastVisitForOrigins(
|
| + origins, base::BindBlock(^(const OriginCountAndLastVisitMap& result) {
|
| + auto iter = result.find(block_safe_url);
|
| + if (iter != result.end())
|
| + count = iter->second.first;
|
| + history_service_callback_called = true;
|
| + }));
|
| +
|
| + NSDate* deadline = [NSDate dateWithTimeIntervalSinceNow:4.0];
|
| + while (!history_service_callback_called &&
|
| + [[NSDate date] compare:deadline] != NSOrderedDescending) {
|
| + base::test::ios::SpinRunLoopWithMaxDelay(
|
| + base::TimeDelta::FromSecondsD(0.1));
|
| + }
|
| +
|
| + NSString* error_message = nil;
|
| + if (!history_service_callback_called) {
|
| + error_message = @"History::GetCountsAndLastVisitForOrigins callback never "
|
| + "called, app will probably crash later.";
|
| + } else if (count == 0 && expect_present) {
|
| + error_message = @"Typed URL isn't found in HistoryService.";
|
| + } else if (count > 0 && !expect_present) {
|
| + error_message = @"Typed URL isn't supposed to be in HistoryService.";
|
| + }
|
| +
|
| + if (error_message != nil && error != nil) {
|
| + NSDictionary* error_info = @{NSLocalizedDescriptionKey : error_message};
|
| + *error = [NSError errorWithDomain:kSyncTestErrorDomain
|
| + code:0
|
| + userInfo:error_info];
|
| + return NO;
|
| + }
|
| + return error_message == nil;
|
| +}
|
| +
|
| +void DeleteTypedUrlFromClient(const GURL& url) {
|
| + ios::ChromeBrowserState* browser_state =
|
| + chrome_test_util::GetOriginalBrowserState();
|
| + history::HistoryService* history_service =
|
| + ios::HistoryServiceFactory::GetForBrowserState(
|
| + browser_state, ServiceAccessType::EXPLICIT_ACCESS);
|
| +
|
| + history_service->DeleteURL(url);
|
| +}
|
| +
|
| +void DeleteTypedUrlFromFakeSyncServer(std::string url) {
|
| + DCHECK(gSyncFakeServer);
|
| + std::vector<sync_pb::SyncEntity> typed_urls =
|
| + gSyncFakeServer->GetSyncEntitiesByModelType(syncer::TYPED_URLS);
|
| + std::string entity_id;
|
| + for (const sync_pb::SyncEntity& typed_url : typed_urls) {
|
| + if (typed_url.specifics().typed_url().url() == url) {
|
| + entity_id = typed_url.id_string();
|
| + break;
|
| + }
|
| + }
|
| + if (!entity_id.empty()) {
|
| + std::unique_ptr<fake_server::FakeServerEntity> entity;
|
| + entity = fake_server::TombstoneEntity::Create(entity_id, std::string());
|
| + gSyncFakeServer->InjectEntity(std::move(entity));
|
| + }
|
| +}
|
| +
|
| +} // namespace chrome_test_util
|
|
|