chromium/chrome/browser/ash/policy/reporting/app_install_event_log_manager_wrapper_unittest.cc

// Copyright 2018 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/policy/reporting/app_install_event_log_manager_wrapper.h"

#include "ash/components/arc/arc_prefs.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/ash/policy/reporting/arc_app_install_event_log.h"
#include "chrome/browser/ash/policy/reporting/arc_app_install_event_log_manager.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using testing::Mock;

namespace em = enterprise_management;

namespace policy {

namespace {

constexpr base::FilePath::CharType kLogFileName[] =
    FILE_PATH_LITERAL("app_push_install_log");

constexpr char kPackageName[] = "com.example.app";

class AppInstallEventLogManagerWrapperTestable
    : public AppInstallEventLogManagerWrapper {
 public:
  explicit AppInstallEventLogManagerWrapperTestable(Profile* profile)
      : AppInstallEventLogManagerWrapper(profile) {}

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

  scoped_refptr<base::SequencedTaskRunner> log_task_runner() {
    return log_task_runner_->GetTaskRunner();
  }

  // Make |Init()| visible for testing.
  using AppInstallEventLogManagerWrapper::Init;

  // AppInstallEventLogManagerWrapper:
  MOCK_METHOD(void, CreateManager, (), (override));
  MOCK_METHOD(void, DestroyManager, (), (override));
  MOCK_METHOD(void, CreateEncryptedReporter, (), (override));
  MOCK_METHOD(void, DestroyEncryptedReporter, (), (override));
};

}  // namespace

class AppInstallEventLogManagerWrapperTest
    : public testing::Test,
      public ::testing::WithParamInterface<bool> {
 protected:
  AppInstallEventLogManagerWrapperTest()
      : log_file_path_(profile_.GetPath().Append(kLogFileName)) {}

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

  // testing::Test:
  void SetUp() override {
    app_list_.Append(kPackageName);
    if (encrypted_reporting_feature_enabled()) {
      scoped_feature_list_.InitAndEnableFeature(
          policy::kUseEncryptedReportingPipelineToReportArcAppInstallEvents);
    } else {
      scoped_feature_list_.InitAndDisableFeature(
          policy::kUseEncryptedReportingPipelineToReportArcAppInstallEvents);
    }
  }

  void PopulateLogFileAndPrefs() {
    ArcAppInstallEventLog log(log_file_path_);
    em::AppInstallReportLogEvent event;
    event.set_timestamp(0);
    event.set_event_type(em::AppInstallReportLogEvent::SUCCESS);
    log.Add(kPackageName, event);
    log.Store();
    profile_.GetPrefs()->SetList(arc::prefs::kArcPushInstallAppsRequested,
                                 app_list_.Clone());
    profile_.GetPrefs()->SetList(arc::prefs::kArcPushInstallAppsPending,
                                 app_list_.Clone());
  }

  void FlushPendingTasks() {
    base::RunLoop run_loop;
    ASSERT_TRUE(log_task_runner_);
    log_task_runner_->PostTaskAndReply(FROM_HERE, base::DoNothing(),
                                       run_loop.QuitClosure());
    run_loop.Run();
  }

  void CreateWrapper() {
    wrapper_ =
        std::make_unique<AppInstallEventLogManagerWrapperTestable>(&profile_);
    log_task_runner_ = wrapper_->log_task_runner();
  }

  void DestroyWrapper() {
    wrapper_.reset();
    FlushPendingTasks();
    log_task_runner_ = nullptr;
  }

  void InitWrapper() {
    ASSERT_TRUE(wrapper_);
    wrapper_->Init();
    FlushPendingTasks();
  }

  void VerifyLogFileAndPrefsNotCleared() {
    EXPECT_TRUE(base::PathExists(log_file_path_));
    EXPECT_EQ(app_list_, profile_.GetPrefs()->GetList(
                             arc::prefs::kArcPushInstallAppsRequested));
    EXPECT_EQ(app_list_, profile_.GetPrefs()->GetList(
                             arc::prefs::kArcPushInstallAppsPending));
  }

  void VerifyLogFileAndPrefsCleared() {
    EXPECT_FALSE(base::PathExists(log_file_path_));
    EXPECT_TRUE(profile_.GetPrefs()
                    ->FindPreference(arc::prefs::kArcPushInstallAppsRequested)
                    ->IsDefaultValue());
    EXPECT_TRUE(profile_.GetPrefs()
                    ->FindPreference(arc::prefs::kArcPushInstallAppsPending)
                    ->IsDefaultValue());
  }

  bool encrypted_reporting_feature_enabled() { return GetParam(); }

  content::BrowserTaskEnvironment task_environment_;
  TestingProfile profile_;

  const base::FilePath log_file_path_;
  base::Value::List app_list_;

  std::unique_ptr<AppInstallEventLogManagerWrapperTestable> wrapper_;

  scoped_refptr<base::SequencedTaskRunner> log_task_runner_;
  base::test::ScopedFeatureList scoped_feature_list_;
};

// Populate a log file and the prefs holding the lists of apps for which
// push-install has been requested and is still pending. Enable reporting.
// Create a wrapper. Verify that a manager is created and neither the log file
// nor the prefs are cleared. Then, destroy the wrapper. Verify that neither the
// log file nor the prefs are cleared.
TEST_P(AppInstallEventLogManagerWrapperTest, EnableCreate) {
  PopulateLogFileAndPrefs();
  profile_.GetPrefs()->SetBoolean(prefs::kArcAppInstallEventLoggingEnabled,
                                  true);

  CreateWrapper();

  if (encrypted_reporting_feature_enabled()) {
    EXPECT_CALL(*wrapper_, CreateEncryptedReporter());
    EXPECT_CALL(*wrapper_, DestroyEncryptedReporter()).Times(0);
  } else {
    EXPECT_CALL(*wrapper_, CreateManager());
    EXPECT_CALL(*wrapper_, DestroyManager()).Times(0);
  }
  InitWrapper();
  VerifyLogFileAndPrefsNotCleared();
  Mock::VerifyAndClearExpectations(&wrapper_);

  DestroyWrapper();
  VerifyLogFileAndPrefsNotCleared();
}

// Populate a log file and the prefs holding the lists of apps for which
// push-install has been requested and is still pending. Disable reporting.
// Create a wrapper. Verify that no manager is created and the log file and the
// prefs are cleared.
TEST_P(AppInstallEventLogManagerWrapperTest, DisableCreate) {
  PopulateLogFileAndPrefs();
  profile_.GetPrefs()->SetBoolean(prefs::kArcAppInstallEventLoggingEnabled,
                                  false);

  CreateWrapper();

  if (encrypted_reporting_feature_enabled()) {
    EXPECT_CALL(*wrapper_, CreateEncryptedReporter()).Times(0);
    EXPECT_CALL(*wrapper_, DestroyEncryptedReporter());
  } else {
    EXPECT_CALL(*wrapper_, CreateManager()).Times(0);
    EXPECT_CALL(*wrapper_, DestroyManager());
  }
  InitWrapper();
  VerifyLogFileAndPrefsCleared();
}

// Disable reporting. Create a wrapper. Verify that no manager is created. Then,
// enable reporting. Verify that a manager is created. Populate a log file and
// the prefs holding the lists of apps for which push-install has been requested
// and is still pending. Then, destroy the wrapper. Verify that neither the log
// file nor the prefs are cleared.
TEST_P(AppInstallEventLogManagerWrapperTest, CreateEnable) {
  profile_.GetPrefs()->SetBoolean(prefs::kArcAppInstallEventLoggingEnabled,
                                  false);

  CreateWrapper();

  if (encrypted_reporting_feature_enabled()) {
    EXPECT_CALL(*wrapper_, CreateEncryptedReporter()).Times(0);
    EXPECT_CALL(*wrapper_, DestroyEncryptedReporter());
  } else {
    EXPECT_CALL(*wrapper_, CreateManager()).Times(0);
    EXPECT_CALL(*wrapper_, DestroyManager());
  }
  InitWrapper();
  Mock::VerifyAndClearExpectations(&wrapper_);

  if (encrypted_reporting_feature_enabled()) {
    EXPECT_CALL(*wrapper_, CreateEncryptedReporter());
    EXPECT_CALL(*wrapper_, DestroyEncryptedReporter()).Times(0);
  } else {
    EXPECT_CALL(*wrapper_, CreateManager());
    EXPECT_CALL(*wrapper_, DestroyManager()).Times(0);
  }
  profile_.GetPrefs()->SetBoolean(prefs::kArcAppInstallEventLoggingEnabled,
                                  true);
  Mock::VerifyAndClearExpectations(&wrapper_);
  FlushPendingTasks();

  PopulateLogFileAndPrefs();

  DestroyWrapper();
  VerifyLogFileAndPrefsNotCleared();
}

// Populate a log file and the prefs holding the lists of apps for which
// push-install has been requested and is still pending. Enable reporting.
// Create a wrapper. Verify that a manager is created and neither the log file
// nor the prefs are cleared. Then, disable reporting. Verify that the manager
// is destroyed and the log file and the prefs are cleared.
TEST_P(AppInstallEventLogManagerWrapperTest, CreateDisable) {
  PopulateLogFileAndPrefs();
  profile_.GetPrefs()->SetBoolean(prefs::kArcAppInstallEventLoggingEnabled,
                                  true);

  CreateWrapper();

  if (encrypted_reporting_feature_enabled()) {
    EXPECT_CALL(*wrapper_, CreateEncryptedReporter());
    EXPECT_CALL(*wrapper_, DestroyEncryptedReporter()).Times(0);
  } else {
    EXPECT_CALL(*wrapper_, CreateManager());
    EXPECT_CALL(*wrapper_, DestroyManager()).Times(0);
  }
  InitWrapper();
  VerifyLogFileAndPrefsNotCleared();
  Mock::VerifyAndClearExpectations(&wrapper_);

  if (encrypted_reporting_feature_enabled()) {
    EXPECT_CALL(*wrapper_, CreateEncryptedReporter()).Times(0);
    EXPECT_CALL(*wrapper_, DestroyEncryptedReporter());
  } else {
    EXPECT_CALL(*wrapper_, CreateManager()).Times(0);
    EXPECT_CALL(*wrapper_, DestroyManager());
  }
  profile_.GetPrefs()->SetBoolean(prefs::kArcAppInstallEventLoggingEnabled,
                                  false);
  Mock::VerifyAndClearExpectations(&wrapper_);
  FlushPendingTasks();
  VerifyLogFileAndPrefsCleared();
}

INSTANTIATE_TEST_SUITE_P(All,
                         AppInstallEventLogManagerWrapperTest,
                         testing::Bool());
}  // namespace policy