chromium/chrome/browser/ash/sync/sync_user_settings_client_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_user_settings_client_ash.h"

#include <optional>

#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "chromeos/crosapi/mojom/sync.mojom.h"
#include "components/sync/base/user_selectable_type.h"
#include "components/sync/test/mock_sync_service.h"
#include "components/sync/test/sync_user_settings_mock.h"
#include "mojo/public/cpp/bindings/receiver.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 {

using testing::Eq;
using testing::Ne;
using testing::Return;

class TestSyncUserSettingsClientObserver
    : public crosapi::mojom::SyncUserSettingsClientObserver {
 public:
  TestSyncUserSettingsClientObserver() = default;
  TestSyncUserSettingsClientObserver(
      const TestSyncUserSettingsClientObserver&) = delete;
  TestSyncUserSettingsClientObserver& operator=(
      const TestSyncUserSettingsClientObserver&) = delete;
  ~TestSyncUserSettingsClientObserver() override = default;

  void Observe(SyncUserSettingsClientAsh* client) {
    auto remote = receiver_.BindNewPipeAndPassRemote();
    client->AddObserver(std::move(remote));
  }

  std::optional<bool> GetLastAppsSyncEnabled() const {
    return last_apps_sync_enabled_;
  }

  // crosapi::mojom::SyncUserSettingsClientObserver implementation.
  void OnAppsSyncEnabledChanged(bool enabled) override {
    last_apps_sync_enabled_ = enabled;
  }

 private:
  std::optional<bool> last_apps_sync_enabled_;

  mojo::Receiver<crosapi::mojom::SyncUserSettingsClientObserver> receiver_{
      this};
};

class SyncUserSettingsClientAshTest : public testing::Test {
 public:
  SyncUserSettingsClientAshTest() {}
  SyncUserSettingsClientAshTest(const SyncUserSettingsClientAshTest&) = delete;
  SyncUserSettingsClientAshTest& operator=(
      const SyncUserSettingsClientAshTest&) = delete;
  ~SyncUserSettingsClientAshTest() override = default;

  void SetupClient() {
    client_ = std::make_unique<SyncUserSettingsClientAsh>(&sync_service_);
    client_->BindReceiver(client_remote_.BindNewPipeAndPassReceiver());
  }

  SyncUserSettingsClientAsh* client() {
    DCHECK(client_);
    return client_.get();
  }

  syncer::MockSyncService* sync_service() { return &sync_service_; }

  syncer::SyncUserSettingsMock* sync_user_settings() {
    return sync_service_.GetMockUserSettings();
  }

  bool IsAppsSyncEnabled() const {
    return IsAppsSyncEnabled(client_remote_.get());
  }

  bool IsAppsSyncEnabled(crosapi::mojom::SyncUserSettingsClient* client) const {
    base::test::TestFuture<bool> future;
    client->IsAppsSyncEnabled(future.GetCallback());
    return future.Take();
  }

 private:
  base::test::SingleThreadTaskEnvironment task_environment_;

  testing::NiceMock<syncer::MockSyncService> sync_service_;

  std::unique_ptr<SyncUserSettingsClientAsh> client_;
  mojo::Remote<crosapi::mojom::SyncUserSettingsClient> client_remote_;
};

TEST_F(SyncUserSettingsClientAshTest, ShouldExposeAppsSyncEnabled) {
  ON_CALL(*sync_user_settings(), GetSelectedOsTypes())
      .WillByDefault(Return(syncer::UserSelectableOsTypeSet(
          {syncer::UserSelectableOsType::kOsApps})));
  SetupClient();

  EXPECT_TRUE(IsAppsSyncEnabled());
}

TEST_F(SyncUserSettingsClientAshTest, ShouldExposeAppsSyncDisabled) {
  ON_CALL(*sync_user_settings(), GetSelectedOsTypes())
      .WillByDefault(Return(syncer::UserSelectableOsTypeSet()));
  SetupClient();

  EXPECT_FALSE(IsAppsSyncEnabled());
}

TEST_F(SyncUserSettingsClientAshTest, ShouldSupportMultipleReceivers) {
  ON_CALL(*sync_user_settings(), GetSelectedOsTypes())
      .WillByDefault(Return(syncer::UserSelectableOsTypeSet(
          {syncer::UserSelectableOsType::kOsApps})));
  SetupClient();

  mojo::Remote<crosapi::mojom::SyncUserSettingsClient> other_remote;
  client()->BindReceiver(other_remote.BindNewPipeAndPassReceiver());

  EXPECT_TRUE(IsAppsSyncEnabled());
  EXPECT_TRUE(IsAppsSyncEnabled(other_remote.get()));
}

TEST_F(SyncUserSettingsClientAshTest, ShouldNotifyObserver) {
  ON_CALL(*sync_user_settings(), GetSelectedOsTypes())
      .WillByDefault(Return(syncer::UserSelectableOsTypeSet()));
  SetupClient();

  TestSyncUserSettingsClientObserver observer;
  observer.Observe(client());

  // No state changes, observer shouldn't be notified.
  client()->OnStateChanged(sync_service());
  client()->FlushMojoForTesting();
  EXPECT_THAT(observer.GetLastAppsSyncEnabled(), Eq(std::nullopt));

  // Mimic apps sync being enabled.
  ON_CALL(*sync_user_settings(), GetSelectedOsTypes())
      .WillByDefault(Return(syncer::UserSelectableOsTypeSet(
          {syncer::UserSelectableOsType::kOsApps})));
  client()->OnStateChanged(sync_service());
  client()->FlushMojoForTesting();
  ASSERT_THAT(observer.GetLastAppsSyncEnabled(), Ne(std::nullopt));
  EXPECT_TRUE(*observer.GetLastAppsSyncEnabled());

  // Mimic apps sync being disabled again.
  ON_CALL(*sync_user_settings(), GetSelectedOsTypes())
      .WillByDefault(Return(syncer::UserSelectableOsTypeSet()));
  client()->OnStateChanged(sync_service());
  client()->FlushMojoForTesting();
  ASSERT_THAT(observer.GetLastAppsSyncEnabled(), Ne(std::nullopt));
  EXPECT_FALSE(*observer.GetLastAppsSyncEnabled());
}

TEST_F(SyncUserSettingsClientAshTest, ShouldSupportMultipleObservers) {
  ON_CALL(*sync_user_settings(), GetSelectedOsTypes())
      .WillByDefault(Return(syncer::UserSelectableOsTypeSet()));
  SetupClient();

  TestSyncUserSettingsClientObserver observer1;
  observer1.Observe(client());

  TestSyncUserSettingsClientObserver observer2;
  observer2.Observe(client());

  // Mimic apps sync being enabled.
  ON_CALL(*sync_user_settings(), GetSelectedOsTypes())
      .WillByDefault(Return(syncer::UserSelectableOsTypeSet(
          {syncer::UserSelectableOsType::kOsApps})));
  client()->OnStateChanged(sync_service());
  client()->FlushMojoForTesting();

  ASSERT_THAT(observer1.GetLastAppsSyncEnabled(), Ne(std::nullopt));
  EXPECT_TRUE(*observer1.GetLastAppsSyncEnabled());

  ASSERT_THAT(observer2.GetLastAppsSyncEnabled(), Ne(std::nullopt));
  EXPECT_TRUE(*observer2.GetLastAppsSyncEnabled());
}

}  // namespace

}  // namespace ash