chromium/ash/webui/eche_app_ui/eche_presence_manager_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 "ash/webui/eche_app_ui/eche_presence_manager.h"

#include "ash/constants/ash_features.h"
#include "ash/webui/eche_app_ui/fake_eche_connector.h"
#include "ash/webui/eche_app_ui/fake_eche_message_receiver.h"
#include "ash/webui/eche_app_ui/fake_feature_status_provider.h"
#include "ash/webui/eche_app_ui/proto/exo_messages.pb.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "chromeos/ash/components/multidevice/remote_device_test_util.h"
#include "chromeos/ash/services/device_sync/public/cpp/fake_device_sync_client.h"
#include "chromeos/ash/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h"
#include "chromeos/ash/services/secure_channel/public/cpp/client/presence_monitor_client_impl.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {
namespace eche_app {

static size_t num_start_monitor_calls_ = 0;
static size_t num_stop_monitor_calls_ = 0;

namespace {

class FakePresenceMonitorClient : public secure_channel::PresenceMonitorClient {
 public:
  FakePresenceMonitorClient() = default;
  ~FakePresenceMonitorClient() override = default;

 private:
  // secure_channel::PresenceMonitorClient:
  void SetPresenceMonitorCallbacks(
      secure_channel::PresenceMonitor::ReadyCallback ready_callback,
      secure_channel::PresenceMonitor::DeviceSeenCallback device_seen_callback)
      override {}
  void StartMonitoring(
      const multidevice::RemoteDeviceRef& remote_device_ref,
      const multidevice::RemoteDeviceRef& local_device_ref) override {
    num_start_monitor_calls_++;
  }
  void StopMonitoring() override { num_stop_monitor_calls_++; }
};
}  // namespace

class EchePresenceManagerTest : public testing::Test {
 protected:
  EchePresenceManagerTest()
      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
        test_remote_device_(multidevice::CreateRemoteDeviceRefForTest()),
        test_devices_(multidevice::CreateRemoteDeviceRefListForTest(1)) {}
  EchePresenceManagerTest(const EchePresenceManagerTest&) = delete;
  EchePresenceManagerTest& operator=(const EchePresenceManagerTest&) = delete;
  ~EchePresenceManagerTest() override = default;

  void SetUp() override {
    fake_multidevice_setup_client_.SetHostStatusWithDevice(
        std::make_pair(multidevice_setup::mojom::HostStatus::kHostVerified,
                       test_remote_device_));
    fake_device_sync_client_.set_local_device_metadata(test_devices_[0]);
    fake_device_sync_client_.NotifyReady();
    fake_eche_connector_ = std::make_unique<FakeEcheConnector>();
    fake_eche_message_receiver_ = std::make_unique<FakeEcheMessageReceiver>();
    fake_feature_status_provider_ = std::make_unique<FakeFeatureStatusProvider>(
        FeatureStatus::kDependentFeature);
    fake_presence_monitor_client_ =
        std::make_unique<FakePresenceMonitorClient>();
    eche_presence_manager_ = std::make_unique<EchePresenceManager>(
        fake_feature_status_provider_.get(), &fake_device_sync_client_,
        &fake_multidevice_setup_client_,
        std::move(fake_presence_monitor_client_), fake_eche_connector_.get(),
        fake_eche_message_receiver_.get());
  }

  void TearDown() override {
    eche_presence_manager_.reset();
    fake_eche_connector_.reset();
    fake_eche_message_receiver_.reset();
    fake_feature_status_provider_.reset();
    fake_presence_monitor_client_.reset();
  }

  void SetFeatureStatus(FeatureStatus status) {
    fake_feature_status_provider_->SetStatus(status);
  }

  FeatureStatus GetFeatureStatus() {
    return fake_feature_status_provider_->GetStatus();
  }

  void SetStreamStatus(proto::StatusChangeType type) {
    fake_eche_message_receiver_->FakeStatusChange(type);
  }

  void Reset() {
    num_start_monitor_calls_ = 0;
    num_stop_monitor_calls_ = 0;
  }

  base::test::TaskEnvironment task_environment_;
  base::test::ScopedFeatureList scoped_feature_list_;

 private:
  std::unique_ptr<FakeEcheConnector> fake_eche_connector_;
  std::unique_ptr<FakeEcheMessageReceiver> fake_eche_message_receiver_;
  std::unique_ptr<FakeFeatureStatusProvider> fake_feature_status_provider_;
  const multidevice::RemoteDeviceRef test_remote_device_;
  multidevice_setup::FakeMultiDeviceSetupClient fake_multidevice_setup_client_;
  device_sync::FakeDeviceSyncClient fake_device_sync_client_;
  const multidevice::RemoteDeviceRefList test_devices_;
  std::unique_ptr<FakePresenceMonitorClient> fake_presence_monitor_client_;
  std::unique_ptr<EchePresenceManager> eche_presence_manager_;
};

TEST_F(EchePresenceManagerTest, StopMonitoring_PersistentScan) {
  scoped_feature_list_.InitWithFeatures(
      /*enabled_features=*/{},
      /*disabled_features=*/{features::kEcheShorterScanningDutyCycle});
  // Test feature status change to kIneligible
  Reset();
  SetFeatureStatus(FeatureStatus::kConnected);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_START);
  SetFeatureStatus(FeatureStatus::kIneligible);
  EXPECT_EQ(1u, num_stop_monitor_calls_);

  // Test feature status change to kDisabled
  Reset();
  SetFeatureStatus(FeatureStatus::kConnected);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_START);
  SetFeatureStatus(FeatureStatus::kDisabled);
  EXPECT_EQ(1u, num_stop_monitor_calls_);

  // Test feature status change to kDependentFeature
  Reset();
  SetFeatureStatus(FeatureStatus::kConnected);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_START);
  SetFeatureStatus(FeatureStatus::kDependentFeature);
  EXPECT_EQ(1u, num_stop_monitor_calls_);

  // Test feature status change to kDependentFeaturePending
  Reset();
  SetFeatureStatus(FeatureStatus::kConnected);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_START);
  SetFeatureStatus(FeatureStatus::kDependentFeaturePending);
  EXPECT_EQ(1u, num_stop_monitor_calls_);

  // Test feature status change to kDisconnected.
  Reset();
  SetFeatureStatus(FeatureStatus::kConnected);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_START);
  SetFeatureStatus(FeatureStatus::kDisconnected);
  EXPECT_EQ(1u, num_stop_monitor_calls_);

  // Test feature status change to kConnecting.
  Reset();
  SetFeatureStatus(FeatureStatus::kConnected);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_START);
  SetFeatureStatus(FeatureStatus::kConnecting);
  EXPECT_EQ(1u, num_stop_monitor_calls_);

  // Test stream status change to stop.
  Reset();
  SetFeatureStatus(FeatureStatus::kConnected);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_START);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_STOP);
  EXPECT_EQ(1u, num_stop_monitor_calls_);

  // Test 5 minutes not see device.
  Reset();
  SetFeatureStatus(FeatureStatus::kConnected);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_START);
  task_environment_.FastForwardBy(base::Minutes(5));
  EXPECT_EQ(1u, num_stop_monitor_calls_);
}

TEST_F(EchePresenceManagerTest, StartMonitoring) {
  Reset();
  SetFeatureStatus(FeatureStatus::kConnected);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_START);
  EXPECT_EQ(1u, num_start_monitor_calls_);
}

TEST_F(EchePresenceManagerTest, StartMonitoring_PeriodicalScanning) {
  Reset();
  SetFeatureStatus(FeatureStatus::kConnected);
  SetStreamStatus(proto::StatusChangeType::TYPE_STREAM_START);
  EXPECT_EQ(1u, num_start_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, monitoring stopped.
  EXPECT_EQ(1u, num_stop_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, started monioring again.
  EXPECT_EQ(2u, num_start_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, monitoring stopped.
  EXPECT_EQ(2u, num_stop_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, started monioring again.
  EXPECT_EQ(3u, num_start_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, monitoring stopped.
  EXPECT_EQ(3u, num_stop_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, started monioring again.
  EXPECT_EQ(4u, num_start_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, monitoring stopped.
  EXPECT_EQ(4u, num_stop_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, started monioring again.
  EXPECT_EQ(5u, num_start_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, monitoring stopped.
  EXPECT_EQ(5u, num_stop_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, started monioring again.
  EXPECT_EQ(6u, num_start_monitor_calls_);

  // 5 minutes passed since last proximity check passed.

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 30 seconds, monitoring stopped.
  EXPECT_EQ(6u, num_stop_monitor_calls_);

  task_environment_.FastForwardBy(base::Seconds(30));
  // After 5 minutesof last proximity check, monitoering should not be started
  // again.
  EXPECT_EQ(6u, num_start_monitor_calls_);
}

}  // namespace eche_app
}  // namespace ash