chromium/chrome/browser/ash/sync/sync_mojo_service_ash_unittest.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/sync/sync_mojo_service_ash.h"

#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "components/sync/base/features.h"
#include "components/sync/test/mock_sync_service.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {

namespace {

class SyncMojoServiceAshTest : public testing::Test {
 public:
  SyncMojoServiceAshTest() {
    override_features_.InitWithFeatures(
        /*enabled_features=*/{syncer::kSyncChromeOSExplicitPassphraseSharing,
                              syncer::kSyncChromeOSAppsToggleSharing,
                              syncer::kChromeOSSyncedSessionSharing},
        /*disabled_features=*/{});
    sync_mojo_service_ash_ =
        std::make_unique<SyncMojoServiceAsh>(&sync_service_);
  }

  SyncMojoServiceAshTest(const SyncMojoServiceAshTest&) = delete;
  SyncMojoServiceAshTest& operator=(const SyncMojoServiceAshTest&) = delete;
  ~SyncMojoServiceAshTest() override = default;

  SyncMojoServiceAsh* sync_mojo_service_ash() {
    return sync_mojo_service_ash_.get();
  }

  void RunAllPendingTasks() { task_environment_.RunUntilIdle(); }

  void CreateSyncedSessionClient(base::OnceClosure callback) {
    sync_mojo_service_ash_->CreateSyncedSessionClient(
        base::BindOnce(&SyncMojoServiceAshTest::OnCreateSyncedSessionClient,
                       base::Unretained(this), std::move(callback)));
  }

  void OnCreateSyncedSessionClient(
      base::OnceClosure callback,
      mojo::PendingRemote<crosapi::mojom::SyncedSessionClient> pending_remote) {
    synced_session_client_remote_.Bind(std::move(pending_remote));
    std::move(callback).Run();
  }

  mojo::Remote<crosapi::mojom::SyncedSessionClient>&
  synced_session_client_remote() {
    return synced_session_client_remote_;
  }

 private:
  base::test::SingleThreadTaskEnvironment task_environment_;
  base::test::ScopedFeatureList override_features_;

  testing::NiceMock<syncer::MockSyncService> sync_service_;
  std::unique_ptr<SyncMojoServiceAsh> sync_mojo_service_ash_;
  mojo::Remote<crosapi::mojom::SyncedSessionClient>
      synced_session_client_remote_;
};

TEST_F(SyncMojoServiceAshTest, ShouldSupportMultipleRemotes) {
  mojo::Remote<crosapi::mojom::SyncService> remote1;
  sync_mojo_service_ash()->BindReceiver(remote1.BindNewPipeAndPassReceiver());

  mojo::Remote<crosapi::mojom::SyncService> remote2;
  sync_mojo_service_ash()->BindReceiver(remote2.BindNewPipeAndPassReceiver());

  // Disconnect handlers are not called synchronously. They shouldn't be called
  // in this test, but to verify that wait for all pending tasks to be
  // completed.
  RunAllPendingTasks();
  EXPECT_TRUE(remote1.is_connected());
  EXPECT_TRUE(remote2.is_connected());
}

TEST_F(SyncMojoServiceAshTest, ShouldDisconnectOnShutdown) {
  mojo::Remote<crosapi::mojom::SyncService> sync_mojo_service_ash_remote;
  sync_mojo_service_ash()->BindReceiver(
      sync_mojo_service_ash_remote.BindNewPipeAndPassReceiver());
  ASSERT_TRUE(sync_mojo_service_ash_remote.is_connected());

  mojo::Remote<crosapi::mojom::SyncExplicitPassphraseClient>
      explicit_passphrase_client_remote;
  sync_mojo_service_ash()->BindExplicitPassphraseClient(
      explicit_passphrase_client_remote.BindNewPipeAndPassReceiver());
  ASSERT_TRUE(explicit_passphrase_client_remote.is_connected());

  mojo::Remote<crosapi::mojom::SyncUserSettingsClient>
      user_settings_client_remote;
  sync_mojo_service_ash()->BindUserSettingsClient(
      user_settings_client_remote.BindNewPipeAndPassReceiver());
  ASSERT_TRUE(user_settings_client_remote.is_connected());

  base::RunLoop run_loop;
  CreateSyncedSessionClient(run_loop.QuitClosure());
  run_loop.Run();
  ASSERT_TRUE(synced_session_client_remote().is_connected());

  sync_mojo_service_ash()->Shutdown();
  // Wait for the disconnect handler to be called.
  RunAllPendingTasks();
  EXPECT_FALSE(sync_mojo_service_ash_remote.is_connected());
  EXPECT_FALSE(explicit_passphrase_client_remote.is_connected());
  EXPECT_FALSE(user_settings_client_remote.is_connected());
  EXPECT_FALSE(synced_session_client_remote().is_connected());
}

}  // namespace
}  // namespace ash