| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_SYNC_TEST_H_ |
| #define CHROME_BROWSER_SYNC_TEST_INTEGRATION_SYNC_TEST_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/scoped_observation.h" |
| #include "base/test/scoped_run_loop_timeout.h" |
| #include "base/time/time.h" |
| #include "build/build_config.h" |
| #include "build/buildflag.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/profiles/profile_manager_observer.h" |
| #include "chrome/browser/profiles/profile_observer.h" |
| #include "chrome/browser/sync/test/integration/invalidations/fake_server_sync_invalidation_sender.h" |
| #include "chrome/browser/sync/test/integration/sync_test_account.h" |
| #include "chrome/common/buildflags.h" |
| #include "chrome/test/base/platform_browser_test.h" |
| #include "components/sync/base/data_type.h" |
| #include "components/sync/base/features.h" |
| #include "components/sync/base/user_selectable_type.h" |
| #include "components/sync/test/embedded_fake_server_adapter.h" |
| #include "components/sync/test/fake_server.h" |
| #include "content/public/test/network_connection_change_simulator.h" |
| #include "net/base/net_errors.h" |
| #include "net/http/http_status_code.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "services/network/test/test_url_loader_factory.h" |
| #include "url/gurl.h" |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| #include "chrome/browser/ash/app_list/app_list_syncable_service.h" |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| |
| #if BUILDFLAG(IS_ANDROID) |
| #include "components/gcm_driver/instance_id/scoped_use_fake_instance_id_android.h" |
| #else |
| #include "extensions/browser/install_verifier.h" |
| #endif |
| |
| // The E2E tests are designed to run against real backend servers. To identify |
| // those tests we use *E2ETest* test name filter and run disabled tests. |
| // |
| // The following macros define how a test is run: |
| // - E2E_ONLY: Marks a test to run only as an E2E test against backend servers. |
| // These tests DO NOT run on regular Chromium waterfalls. |
| // - E2E_ENABLED: Marks a test to run as an E2E test in addition to Chromium |
| // waterfalls. |
| // |
| // To disable a test from running on Chromium waterfalls, you would still use |
| // the default DISABLED_test_name macro. To disable it from running as an E2E |
| // test outside Chromium waterfalls you would need to remove the E2E* macro. |
| #define MACRO_CONCAT(prefix, test_name) prefix##_##test_name |
| #define E2E_ONLY(test_name) MACRO_CONCAT(DISABLED_E2ETest, test_name) |
| #define E2E_ENABLED(test_name) MACRO_CONCAT(test_name, E2ETest) |
| |
| class BrowserWindowInterface; |
| class FakeSyncGCMDriver; |
| class KeyedService; |
| class ProfileManager; |
| class SyncServiceImplHarness; |
| |
| namespace arc { |
| class SyncArcPackageHelper; |
| } // namespace arc |
| |
| namespace base { |
| class CommandLine; |
| class ScopedTempDir; |
| } // namespace base |
| |
| namespace content { |
| class URLLoaderInterceptor; |
| } // namespace content |
| |
| namespace gaia { |
| class FakeOAuth2TokenResponse; |
| } // namespace gaia |
| |
| namespace syncer { |
| class SyncServiceImpl; |
| } // namespace syncer |
| |
| // This is the base class for integration tests for all sync data types. Derived |
| // classes must be defined for each sync data type. Individual tests are defined |
| // using the IN_PROC_BROWSER_TEST_F macro. |
| // |
| // By default, tests use a fake_server::FakeServer to emulate the sync server. |
| // To run tests against an external server instead, use command-line flag |
| // --sync-url along with other required arguments. In this case the ServerType |
| // of the test becomes EXTERNAL_LIVE_SERVER. |
| class SyncTest : public PlatformBrowserTest, |
| public ProfileObserver, |
| public ProfileManagerObserver { |
| public: |
| // The different types of live sync tests that can be implemented. |
| enum TestType { |
| // Tests where only one client profile is synced with the server. Typically |
| // sanity level tests. |
| SINGLE_CLIENT, |
| |
| // Tests where two client profiles are synced with the server. Typically |
| // functionality level tests. |
| TWO_CLIENT, |
| }; |
| |
| // The type of server we're running against. |
| enum ServerType { |
| EXTERNAL_LIVE_SERVER, // A remote server that the test code has no control |
| // over whatsoever; cross your fingers that the |
| // account state is initially clean. |
| IN_PROCESS_FAKE_SERVER, // The fake Sync server (FakeServer) running |
| // in-process (bypassing HTTP calls). |
| }; |
| |
| // Waiting condition when setting up sync. |
| enum SyncWaitCondition { |
| // Do not wait for clients to be ready to sync. |
| NO_WAITING, |
| |
| // Wait for sync engine initialization only. This may be used when waiting |
| // for commits is impossible (e.g. due to commit errors or a custom |
| // passphrase). |
| WAIT_FOR_SYNC_SETUP_TO_COMPLETE, |
| |
| // Wait for all the changes to be committed including asynchronous changes |
| // (e.g. DeviceInfo fields). |
| WAIT_FOR_COMMITS_TO_COMPLETE, |
| }; |
| |
| // Modes when setting up sync. |
| enum class SetupSyncMode { |
| kSyncTransportOnly, |
| kSyncTheFeature, |
| }; |
| |
| // A SyncTest must be associated with a particular test type. |
| explicit SyncTest(TestType test_type); |
| |
| SyncTest(const SyncTest&) = delete; |
| SyncTest& operator=(const SyncTest&) = delete; |
| |
| ~SyncTest() override; |
| |
| void SetUp() override; |
| void TearDown() override; |
| void PostRunTestOnMainThread() override; |
| void CreatedBrowserMainParts(content::BrowserMainParts* parts) override; |
| void SetUpLocalStatePrefService(PrefService* local_state) override; |
| |
| // Sets up command line flags required for sync tests. |
| void SetUpCommandLine(base::CommandLine* cl) override; |
| |
| // Used to get the number of sync clients used by a test. |
| int num_clients() { return num_clients_; } |
| |
| // Returns a pointer to a particular sync profile. Callee owns the object |
| // and manages its lifetime. |
| Profile* GetProfile(int index) const; |
| |
| // Returns a list of all profiles. Callee owns the objects and manages |
| // their lifetime. |
| std::vector<raw_ptr<Profile, VectorExperimental>> GetAllProfiles(); |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| // Enable using primary user profile for the sync test. |
| // When this is set, the number of profiles must be one. |
| void SetUsePrimaryUserProfile(bool value); |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| // Returns a pointer to the browser at `window_index` for profile |
| // `profile_index`. Callee owns the object and manages its lifetime. |
| BrowserWindowInterface* GetBrowser(int profile_index, |
| int window_index = 0) const; |
| |
| // Adds a new browser belonging to profile `profile_index`, and appends |
| // it to that client's list of browsers. |
| BrowserWindowInterface* AddBrowser(int profile_index); |
| #endif |
| |
| // Returns a pointer to a particular sync client. Callee owns the object |
| // and manages its lifetime. |
| SyncServiceImplHarness* GetClient(int index); |
| const SyncServiceImplHarness* GetClient(int index) const; |
| |
| // Returns a list of the collection of sync clients. |
| std::vector<SyncServiceImplHarness*> GetSyncClients(); |
| |
| // Returns a SyncServiceImpl at the given index. |
| syncer::SyncServiceImpl* GetSyncService(int index) const; |
| |
| // Returns the set of SyncServiceImpls. |
| std::vector<raw_ptr<syncer::SyncServiceImpl, VectorExperimental>> |
| GetSyncServices(); |
| |
| // Returns the set of registered UserSelectableTypes. This is retrieved from |
| // the SyncServiceImpl at the given |index|. |
| syncer::UserSelectableTypeSet GetRegisteredSelectableTypes(int index); |
| |
| // Returns the SetupSyncMode to be used for setting up sync. |
| // Subclasses should override this method to specify the desired mode, often |
| // in conjunction with test parameterization. |
| virtual SetupSyncMode GetSetupSyncMode() const; |
| |
| // Returns the URL to be opened in the initial tab of each profile's browser |
| // window. |
| virtual GURL GetInitialURL() const; |
| |
| // Initializes sync clients and profiles but does not sync any of them. |
| [[nodiscard]] virtual bool SetupClients(); |
| |
| // Initializes sync clients and waits for different stages to complete |
| // depending on `wait_condition`. |
| [[nodiscard]] bool SetupSync( |
| SyncWaitCondition wait_condition = WAIT_FOR_COMMITS_TO_COMPLETE); |
| [[nodiscard]] bool SetupSync( |
| SyncTestAccount account, |
| SyncWaitCondition wait_condition = WAIT_FOR_COMMITS_TO_COMPLETE); |
| |
| // Signs in to a primary and enables sync transport, without enabling |
| // sync-the-feature. |
| [[nodiscard]] bool SignIn( |
| SyncTestAccount account = SyncTestAccount::kDefaultAccount); |
| |
| // Should only be used if SetupSync() and SignIn() aren't sufficient, i.e. |
| // `setup_mode` is only known during runtime (usually parameterized tests). |
| // |
| // Note that, for kSyncTransportOnly, history sync |
| // is enabled, to make the behavior more similar to the SyncTheFeature case, |
| // for convenience of parameterized tests. |
| [[nodiscard]] bool SetupSyncWithMode( |
| SetupSyncMode setup_mode, |
| SyncWaitCondition wait_condition = WAIT_FOR_COMMITS_TO_COMPLETE, |
| SyncTestAccount account = SyncTestAccount::kDefaultAccount); |
| |
| // This is similar to click the reset button on chrome.google.com/data. |
| // Only takes effect when running with external servers. |
| // Please call this before setting anything. |
| [[nodiscard]] bool ResetSyncForPrimaryAccount(); |
| |
| // Sets whether or not the sync clients in this test should respond to |
| // notifications of their own commits. Real sync clients do not do this, but |
| // many test assertions require this behavior. |
| // |
| // Default is to return true. Test should override this if they require |
| // different behavior. |
| virtual bool TestUsesSelfNotifications(); |
| |
| // Blocks until all sync clients have completed their mutual sync cycles. |
| // Returns true if a quiescent state was successfully reached. Not supported |
| // for E2E tests. |
| // |
| // WARNING: Prefer using other test-specific methods to wait for a specific |
| // state because current checker is too generic and can lead to test flakiness |
| // in some cases. This method can be used in cases where "no changes" are |
| // expected to be applied to the server or to the client. |
| [[nodiscard]] bool AwaitQuiescence(); |
| |
| // Sets the mock gaia response for when an OAuth2 token is requested. |
| // Each call to this method will overwrite responses that were previously set. |
| void SetOAuth2TokenResponse(const gaia::FakeOAuth2TokenResponse& response); |
| |
| // Triggers a migration for one or more datatypes, and waits |
| // for the server to complete it. This operation is available |
| // only if ServerSupportsErrorTriggering() returned true. |
| void TriggerMigrationDoneError(syncer::DataTypeSet data_types); |
| |
| // Returns the FakeServer being used for the test or null if FakeServer is |
| // not being used. |
| fake_server::FakeServer* GetFakeServer() const; |
| |
| // Mimics the device being offline. |
| void DisableNetwork(); |
| |
| // Mimics the device being online. |
| void EnableNetwork(); |
| |
| // Triggers a sync for the given |data_types| for the Profile at |index|. |
| void TriggerSyncForDataTypes(int index, syncer::DataTypeSet data_types); |
| |
| arc::SyncArcPackageHelper* sync_arc_helper(); |
| |
| std::string GetCacheGuid(size_t profile_index) const; |
| |
| protected: |
| // BrowserTestBase implementation: |
| void SetUpOnMainThread() override; |
| void TearDownOnMainThread() override; |
| |
| // ProfileObserver implementation. |
| void OnProfileWillBeDestroyed(Profile* profile) override; |
| |
| // ProfileManagerObserver implementation. |
| void OnProfileAdded(Profile* profile) override; |
| void OnProfileManagerDestroying() override; |
| void OnProfileCreationStarted(Profile* profile) override; |
| |
| // The name for a directory under chrome::DIR_USER_DATA. |
| virtual base::FilePath GetProfileBaseName(int index); |
| |
| // Implementations of the EnableNotifications() and DisableNotifications() |
| // functions defined above. |
| void DisableNotificationsImpl(); |
| void EnableNotificationsImpl(); |
| |
| // Exclude data types from end of test checks in CheckForDataTypeFailures(). |
| // Note that this replaces the list of excluded types (if set earlier). |
| void ExcludeDataTypesFromCheckForDataTypeFailures(syncer::DataTypeSet types); |
| |
| // The FakeServer used in tests with server type IN_PROCESS_FAKE_SERVER, along |
| // with the adapter to integrate it with EmbeddedTestServer. |
| std::unique_ptr<fake_server::FakeServer> fake_server_; |
| std::unique_ptr<fake_server::EmbeddedFakeServerAdapter> |
| embedded_fake_server_adapter_; |
| |
| net::test_server::EmbeddedTestServerHandle embedded_test_server_handle_; |
| |
| // The factory used to mock out GAIA signin. |
| network::TestURLLoaderFactory test_url_loader_factory_; |
| |
| private: |
| // Invoked during initialization when threads have been initialized. |
| void PostCreateThreads(); |
| |
| // Handles Profile creation for given index. Profile's path and type is |
| // determined at runtime based on server type. |
| bool CreateProfile(int index); |
| |
| // Creates a fake GCMProfileService to simulate sync invalidations. |
| std::unique_ptr<KeyedService> CreateGCMProfileService( |
| content::BrowserContext* context); |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| // Called when the |browser| was removed externally. This just marks the |
| // |browser| in the |browsers_| list as nullptr to keep indexes in |browsers_| |
| // and |profiles_| in sync. It is used when the |browser| is removed within a |
| // test (e.g. when the last tab is closed for the |browser|). |
| void OnBrowserRemoved(BrowserWindowInterface* browser); |
| #endif |
| |
| // Helper to block the current thread while the data models sync depends on |
| // finish loading. |
| void WaitForDataModels(Profile* profile); |
| |
| // Helper method used to set up fake responses for kClientLoginUrl, |
| // kIssueAuthTokenUrl, kGetUserInfoUrl and kSearchDomainCheckUrl in order to |
| // mock out calls to GAIA servers. |
| void SetupMockGaiaResponses(); |
| |
| // Helper method used to clear any fake responses that might have been set for |
| // various gaia URLs, cancel any outstanding URL requests, and return to using |
| // the default URLFetcher creation mechanism. |
| void ClearMockGaiaResponses(); |
| |
| // Initializes any custom services needed for the |profile| at |index|. |
| void InitializeProfile(int index, Profile* profile); |
| |
| // Internal routine for setting up sync. |
| [[nodiscard]] bool SetupSyncInternal( |
| SetupSyncMode setup_mode, |
| SyncWaitCondition wait_condition, |
| SyncTestAccount account, |
| bool enable_history_sync_in_transport_mode); |
| |
| // Used to determine whether ARC_PACKAGE data type needs to be enabled. This |
| // is applicable on ChromeOS-Ash platform only. |
| bool UseArcPackage(); |
| |
| // Waits for all the changes which might be done asynchronously after setting |
| // up sync engine. This is used to prevent starting another sync cycle after |
| // SetupSync() call which might be unexpected in several tests. |
| bool WaitForAsyncChangesToBeCommitted(size_t profile_index) const; |
| |
| // Verifies that there are no data type failures for the given |client_index|. |
| // Otherwise, causes test failure. A corresponding client must exist. |
| void CheckForDataTypeFailures(size_t client_index) const; |
| |
| // Used to differentiate between single-client and two-client tests. |
| const TestType test_type_; |
| |
| // The kind of server being used, c.f. ServerType. |
| const ServerType server_type_; |
| |
| // Used to remember when the test fixture was constructed and later understand |
| // how long the setup took. |
| const base::Time test_construction_time_; |
| |
| // Number of sync clients that will be created by a test. |
| const int num_clients_; |
| |
| // Used to catch any timeout within RunLoop and cause test error. |
| base::test::ScopedRunLoopTimeout sync_run_loop_timeout_; |
| |
| // The default profile, created before our actual testing |profiles_|. This is |
| // needed in a workaround for https://crbug.com/41364511, see comments in the |
| // .cc file. |
| raw_ptr<Profile, AcrossTasksDanglingUntriaged> previous_profile_ = nullptr; |
| |
| // Stores the state of a sync client, including its profile, sync service |
| // harness, and associated browser windows. |
| struct SyncClientState { |
| SyncClientState(); |
| ~SyncClientState(); |
| SyncClientState(SyncClientState&&); |
| SyncClientState& operator=(SyncClientState&&); |
| |
| // The profile for this sync client. Owned by ProfileManager. Can be null if |
| // destroyed earlier (e.g. in OnProfileWillBeDestroyed). |
| raw_ptr<Profile, AcrossTasksDanglingUntriaged> profile = nullptr; |
| std::unique_ptr<SyncServiceImplHarness> harness; |
| #if !BUILDFLAG(IS_ANDROID) |
| std::vector<raw_ptr<BrowserWindowInterface, AcrossTasksDanglingUntriaged>> |
| browsers; |
| #endif |
| }; |
| |
| // List of temporary directories that need to be deleted when the test is |
| // completed, used for two-client tests with external server. |
| std::vector<std::unique_ptr<base::ScopedTempDir>> scoped_temp_dirs_; |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| class ClosedBrowserObserver; |
| std::unique_ptr<ClosedBrowserObserver> browser_list_observer_; |
| #endif |
| |
| // Collection of sync clients used by a test, storing each client's profile, |
| // sync harness, and browser windows. |
| std::vector<SyncClientState> clients_; |
| |
| // Used to deliver invalidations to different profiles within |
| // FakeSyncServerInvalidationSender. |
| // TODO(crbug.com/40855871): Move this into SyncClientState. |
| std::map<raw_ptr<Profile, AcrossTasksDanglingUntriaged>, |
| raw_ptr<FakeSyncGCMDriver, AcrossTasksDanglingUntriaged>> |
| profile_to_fake_gcm_driver_; |
| |
| syncer::DataTypeSet excluded_types_from_check_for_data_type_failures_; |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| // Disable extension install verification. |
| extensions::ScopedInstallVerifierBypassForTest ignore_install_verification_; |
| #endif |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| // A factory-like callback to create a model updater for testing, which will |
| // take the place of the real updater in AppListSyncableService for testing. |
| std::unique_ptr<base::ScopedClosureRunner> model_updater_factory_scope_; |
| |
| bool use_primary_user_profile_ = false; |
| #endif |
| |
| #if BUILDFLAG(IS_ANDROID) |
| instance_id::ScopedUseFakeInstanceIDAndroid |
| scoped_use_fake_instance_id_android_; |
| #endif |
| |
| std::unique_ptr<fake_server::FakeServerSyncInvalidationSender> |
| fake_server_sync_invalidation_sender_; |
| |
| std::unique_ptr<content::URLLoaderInterceptor> url_loader_interceptor_; |
| content::NetworkConnectionChangeSimulator connection_change_simulator_; |
| |
| base::ScopedObservation<ProfileManager, ProfileManagerObserver> |
| profile_manager_observation_{this}; |
| base::WeakPtrFactory<SyncTest> weak_ptr_factory_{this}; |
| }; |
| |
| inline auto GetSyncTestModes() { |
| #if (BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)) && \ |
| !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER) && \ |
| !defined(MEMORY_SANITIZER) |
| return testing::Values(SyncTest::SetupSyncMode::kSyncTransportOnly, |
| SyncTest::SetupSyncMode::kSyncTheFeature); |
| // On non-Linux, non-ChromeOS, and on expensive (ASan etc) bots, run only the |
| // single most important configuration, for capacity reasons. |
| #else |
| return testing::Values(SyncTest::SetupSyncMode::kSyncTransportOnly); |
| #endif |
| } |
| |
| // Enables user-readable output from gtest (instead of binary streams). |
| std::ostream& operator<<(std::ostream& stream, |
| SyncTest::SetupSyncMode sync_test_mode); |
| std::string SetupSyncModeAsString(SyncTest::SetupSyncMode sync_test_mode); |
| |
| syncer::DataTypeSet AllowedTypesInStandaloneTransportMode(); |
| |
| #endif // CHROME_BROWSER_SYNC_TEST_INTEGRATION_SYNC_TEST_H_ |