chromium/chrome/browser/ash/child_accounts/event_based_status_reporting_service_unittest.cc

// Copyright 2019 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/child_accounts/event_based_status_reporting_service.h"

#include <memory>

#include "ash/components/arc/mojom/app.mojom.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "chrome/browser/ash/app_list/arc/arc_app_test.h"
#include "chrome/browser/ash/child_accounts/child_status_reporting_service.h"
#include "chrome/browser/ash/child_accounts/child_status_reporting_service_factory.h"
#include "chrome/browser/ash/child_accounts/screen_time_controller.h"
#include "chrome/browser/ash/child_accounts/screen_time_controller_factory.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/ash/components/dbus/system_clock/system_clock_client.h"
#include "chromeos/dbus/power/fake_power_manager_client.h"
#include "components/account_id/account_id.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/session_manager/core/session_manager.h"
#include "components/user_manager/fake_user_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {

namespace {

class TestingConsumerStatusReportingService
    : public ChildStatusReportingService {
 public:
  explicit TestingConsumerStatusReportingService(
      content::BrowserContext* context)
      : ChildStatusReportingService(context) {}

  TestingConsumerStatusReportingService(
      const TestingConsumerStatusReportingService&) = delete;
  TestingConsumerStatusReportingService& operator=(
      const TestingConsumerStatusReportingService&) = delete;

  ~TestingConsumerStatusReportingService() override = default;

  bool RequestImmediateStatusReport() override {
    performed_status_reports_++;
    return true;
  }

  int performed_status_reports() const { return performed_status_reports_; }

 private:
  int performed_status_reports_ = 0;
};

class TestingScreenTimeController : public ScreenTimeController {
 public:
  explicit TestingScreenTimeController(content::BrowserContext* context)
      : ScreenTimeController(context) {}

  TestingScreenTimeController(const TestingScreenTimeController&) = delete;
  TestingScreenTimeController& operator=(const TestingScreenTimeController&) =
      delete;

  ~TestingScreenTimeController() override = default;

  // Override this method so that it doesn't call the StatusUploader instance in
  // ConsumerStatusReportingService, which doesn't exist in these tests.
  base::TimeDelta GetScreenTimeDuration() override { return base::TimeDelta(); }
};

std::unique_ptr<KeyedService> CreateTestingConsumerStatusReportingService(
    content::BrowserContext* browser_context) {
  return std::unique_ptr<KeyedService>(
      new TestingConsumerStatusReportingService(browser_context));
}

std::unique_ptr<KeyedService> CreateTestingScreenTimeController(
    content::BrowserContext* browser_context) {
  return std::unique_ptr<KeyedService>(
      new TestingScreenTimeController(browser_context));
}

}  // namespace

class EventBasedStatusReportingServiceTest : public testing::Test {
 public:
  EventBasedStatusReportingServiceTest(
      const EventBasedStatusReportingServiceTest&) = delete;
  EventBasedStatusReportingServiceTest& operator=(
      const EventBasedStatusReportingServiceTest&) = delete;

 protected:
  EventBasedStatusReportingServiceTest() = default;
  ~EventBasedStatusReportingServiceTest() override = default;

  void SetUp() override {
    chromeos::PowerManagerClient::InitializeFake();
    SystemClockClient::InitializeFake();

    profile_ = std::make_unique<TestingProfile>();
    profile_->SetIsSupervisedProfile();
    arc_test_.SetUp(profile());

    session_manager_.CreateSession(
        account_id(),
        user_manager::FakeUserManager::GetFakeUsernameHash(account_id()), true);
    session_manager_.SetSessionState(
        session_manager::SessionState::LOGIN_PRIMARY);

    ChildStatusReportingServiceFactory::GetInstance()->SetTestingFactory(
        profile(),
        base::BindRepeating(&CreateTestingConsumerStatusReportingService));
    ChildStatusReportingService* consumer_status_reporting_service =
        ChildStatusReportingServiceFactory::GetForBrowserContext(profile());
    test_consumer_status_reporting_service_ =
        static_cast<TestingConsumerStatusReportingService*>(
            consumer_status_reporting_service);

    ScreenTimeControllerFactory::GetInstance()->SetTestingFactory(
        profile(), base::BindRepeating(&CreateTestingScreenTimeController));
    ScreenTimeController* screen_time_controller =
        ScreenTimeControllerFactory::GetForBrowserContext(profile());
    test_screen_time_controller_ =
        static_cast<TestingScreenTimeController*>(screen_time_controller);
    service_ =
        std::make_unique<EventBasedStatusReportingService>(profile_.get());
  }

  void TearDown() override {
    service_->Shutdown();
    arc_test_.TearDown();
    profile_.reset();
    SystemClockClient::Shutdown();
    chromeos::PowerManagerClient::Shutdown();
  }

  void SetConnectionType(network::mojom::ConnectionType type) {
    network::TestNetworkConnectionTracker::GetInstance()->SetConnectionType(
        type);
    task_environment_.RunUntilIdle();
  }

  arc::mojom::AppHost* app_host() { return arc_test_.arc_app_list_prefs(); }
  Profile* profile() { return profile_.get(); }
  chromeos::FakePowerManagerClient* power_manager_client() {
    return chromeos::FakePowerManagerClient::Get();
  }

  TestingConsumerStatusReportingService*
  test_consumer_status_reporting_service() {
    return test_consumer_status_reporting_service_;
  }

  TestingScreenTimeController* test_screen_time_controller() {
    return test_screen_time_controller_;
  }

  session_manager::SessionManager* session_manager() {
    return &session_manager_;
  }

  AccountId account_id() {
    return ProfileHelper::Get()->GetUserByProfile(profile())->GetAccountId();
  }

  base::HistogramTester histogram_tester_;

 private:
  content::BrowserTaskEnvironment task_environment_;
  ArcAppTest arc_test_;
  std::unique_ptr<TestingProfile> profile_;
  raw_ptr<TestingConsumerStatusReportingService, DanglingUntriaged>
      test_consumer_status_reporting_service_;
  raw_ptr<TestingScreenTimeController, DanglingUntriaged>
      test_screen_time_controller_;
  session_manager::SessionManager session_manager_;
  std::unique_ptr<EventBasedStatusReportingService> service_;
};

TEST_F(EventBasedStatusReportingServiceTest, ReportWhenAppInstall) {
  ASSERT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  app_host()->OnPackageAdded(arc::mojom::ArcPackageInfo::New());
  EXPECT_EQ(
      1, test_consumer_status_reporting_service()->performed_status_reports());

  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kAppInstalled, 1);
  histogram_tester_.ExpectTotalCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent, 1);
}

TEST_F(EventBasedStatusReportingServiceTest, ReportWhenAppUpdate) {
  ASSERT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  app_host()->OnPackageModified(arc::mojom::ArcPackageInfo::New());
  EXPECT_EQ(
      1, test_consumer_status_reporting_service()->performed_status_reports());

  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kAppUpdated, 1);
  histogram_tester_.ExpectTotalCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent, 1);
}

TEST_F(EventBasedStatusReportingServiceTest, DoNotReportWhenUserJustSignIn) {
  ASSERT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  session_manager()->SetSessionState(session_manager::SessionState::ACTIVE);
  EXPECT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());

  histogram_tester_.ExpectTotalCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent, 0);
}

TEST_F(EventBasedStatusReportingServiceTest, ReportWhenSessionIsLocked) {
  ASSERT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  session_manager()->SetSessionState(session_manager::SessionState::ACTIVE);
  EXPECT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  session_manager()->SetSessionState(session_manager::SessionState::LOCKED);
  EXPECT_EQ(
      1, test_consumer_status_reporting_service()->performed_status_reports());

  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kSessionLocked, 1);
  histogram_tester_.ExpectTotalCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent, 1);
}

TEST_F(EventBasedStatusReportingServiceTest, ReportWhenSessionIsActive) {
  ASSERT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  session_manager()->SetSessionState(session_manager::SessionState::ACTIVE);
  EXPECT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  session_manager()->SetSessionState(session_manager::SessionState::LOCKED);
  EXPECT_EQ(
      1, test_consumer_status_reporting_service()->performed_status_reports());
  session_manager()->SetSessionState(session_manager::SessionState::ACTIVE);
  EXPECT_EQ(
      2, test_consumer_status_reporting_service()->performed_status_reports());

  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kSessionActive, 1);
  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kSessionLocked, 1);
  histogram_tester_.ExpectTotalCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent, 2);
}

TEST_F(EventBasedStatusReportingServiceTest, ReportWhenDeviceGoesOnline) {
  SetConnectionType(network::mojom::ConnectionType::CONNECTION_NONE);

  ASSERT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  SetConnectionType(network::mojom::ConnectionType::CONNECTION_ETHERNET);
  EXPECT_EQ(
      1, test_consumer_status_reporting_service()->performed_status_reports());

  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kDeviceOnline, 1);
  histogram_tester_.ExpectTotalCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent, 1);
}

TEST_F(EventBasedStatusReportingServiceTest, ReportWhenSuspendIsDone) {
  ASSERT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  power_manager_client()->SendSuspendDone();
  EXPECT_EQ(
      1, test_consumer_status_reporting_service()->performed_status_reports());

  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kSuspendDone, 1);
  histogram_tester_.ExpectTotalCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent, 1);
}

TEST_F(EventBasedStatusReportingServiceTest, ReportOnUsageTimeLimitWarning) {
  ASSERT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  test_screen_time_controller()->NotifyUsageTimeLimitWarningForTesting();
  EXPECT_EQ(
      1, test_consumer_status_reporting_service()->performed_status_reports());

  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::
          kUsageTimeLimitWarning,
      1);
  histogram_tester_.ExpectTotalCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent, 1);
}

TEST_F(EventBasedStatusReportingServiceTest, ReportForMultipleEvents) {
  SetConnectionType(network::mojom::ConnectionType::CONNECTION_NONE);

  ASSERT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  session_manager()->SetSessionState(session_manager::SessionState::ACTIVE);
  EXPECT_EQ(
      0, test_consumer_status_reporting_service()->performed_status_reports());
  session_manager()->SetSessionState(session_manager::SessionState::LOCKED);
  EXPECT_EQ(
      1, test_consumer_status_reporting_service()->performed_status_reports());
  session_manager()->SetSessionState(session_manager::SessionState::ACTIVE);
  EXPECT_EQ(
      2, test_consumer_status_reporting_service()->performed_status_reports());
  SetConnectionType(network::mojom::ConnectionType::CONNECTION_WIFI);
  EXPECT_EQ(
      3, test_consumer_status_reporting_service()->performed_status_reports());
  app_host()->OnPackageAdded(arc::mojom::ArcPackageInfo::New());
  EXPECT_EQ(
      4, test_consumer_status_reporting_service()->performed_status_reports());
  app_host()->OnPackageModified(arc::mojom::ArcPackageInfo::New());
  EXPECT_EQ(
      5, test_consumer_status_reporting_service()->performed_status_reports());
  power_manager_client()->SendSuspendDone();
  EXPECT_EQ(
      6, test_consumer_status_reporting_service()->performed_status_reports());
  test_screen_time_controller()->NotifyUsageTimeLimitWarningForTesting();
  EXPECT_EQ(
      7, test_consumer_status_reporting_service()->performed_status_reports());

  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kSessionLocked, 1);
  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kSessionActive, 1);
  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kDeviceOnline, 1);
  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kAppInstalled, 1);
  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kAppUpdated, 1);
  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::kSuspendDone, 1);
  histogram_tester_.ExpectBucketCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent,
      EventBasedStatusReportingService::StatusReportEvent::
          kUsageTimeLimitWarning,
      1);
  histogram_tester_.ExpectTotalCount(
      EventBasedStatusReportingService::kUMAStatusReportEvent, 7);
}

}  // namespace ash