chromium/components/policy/core/common/android/policy_service_android_unittest.cc

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

#include "components/policy/core/common/android/policy_service_android.h"

#include <jni.h>

#include "base/android/java_exception_reporter.h"
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
#include "base/memory/raw_ptr.h"
#include "components/policy/core/common/mock_policy_service.h"
#include "testing/gtest/include/gtest/gtest.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "components/policy/android/test_jni_headers/PolicyServiceTestSupporter_jni.h"

using ::testing::Return;
using ::testing::ReturnRef;

namespace policy {
namespace android {

// Tests the bridge class PolicyServiceAndroid. It uses the Java helper class in
// //components/policy/android/javatest/.../test/PolicyServiceTestSupporter.java
class PolicyServiceAndroidTest : public ::testing::Test {
 public:
  PolicyServiceAndroidTest() {
    EXPECT_CALL(policy_service_, GetPolicies(PolicyNamespace(
                                     POLICY_DOMAIN_CHROME, std::string())))
        .WillOnce(ReturnRef(policies));
    policy_service_android_ =
        std::make_unique<PolicyServiceAndroid>(&policy_service_);
    j_support_ = Java_PolicyServiceTestSupporter_Constructor(
        env_, policy_service_android_->GetJavaObject());
  }
  ~PolicyServiceAndroidTest() override {
    Java_PolicyServiceTestSupporter_verifyNoMoreInteractions(env_, j_support_);
  }

  raw_ptr<JNIEnv> env_ = base::android::AttachCurrentThread();
  MockPolicyService policy_service_;
  policy::PolicyMap policies;
  std::unique_ptr<PolicyServiceAndroid> policy_service_android_;
  base::android::ScopedJavaLocalRef<jobject> j_support_;
};

TEST_F(PolicyServiceAndroidTest, IsInitializationComplete) {
  EXPECT_CALL(policy_service_, IsInitializationComplete(POLICY_DOMAIN_CHROME))
      .Times(2)
      .WillOnce(Return(false))
      .WillOnce(Return(true));
  EXPECT_CALL(policy_service_,
              IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS))
      .Times(0);
  EXPECT_CALL(policy_service_,
              IsInitializationComplete(POLICY_DOMAIN_SIGNIN_EXTENSIONS))
      .Times(0);
  Java_PolicyServiceTestSupporter_verifyIsInitalizationComplete(
      env_, j_support_, false);
  Java_PolicyServiceTestSupporter_verifyIsInitalizationComplete(
      env_, j_support_, true);

  ::testing::Mock::VerifyAndClearExpectations(&policy_service_);
}

TEST_F(PolicyServiceAndroidTest, OneObserver) {
  EXPECT_CALL(policy_service_,
              AddObserver(POLICY_DOMAIN_CHROME, policy_service_android_.get()))
      .Times(1);
  int observer_id =
      Java_PolicyServiceTestSupporter_addObserver(env_, j_support_);

  policy_service_android_->OnPolicyServiceInitialized(POLICY_DOMAIN_CHROME);
  Java_PolicyServiceTestSupporter_verifyInitializationEvent(
      env_, j_support_, /*index*/ 0, /*times*/ 1);

  policy_service_android_->OnPolicyUpdated(
      PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()), PolicyMap(),
      PolicyMap());
  Java_PolicyServiceTestSupporter_verifyPolicyUpdatedEvent(
      env_, j_support_, /*index*/ 0, /*times*/ 1);

  EXPECT_CALL(policy_service_, RemoveObserver(POLICY_DOMAIN_CHROME,
                                              policy_service_android_.get()))
      .Times(1);
  Java_PolicyServiceTestSupporter_removeObserver(env_, j_support_, observer_id);
  ::testing::Mock::VerifyAndClearExpectations(&policy_service_);
}

TEST_F(PolicyServiceAndroidTest, MultipleObservers) {
  // When multiple observers are added in Java, only one observer will be
  // created in C++.
  EXPECT_CALL(policy_service_,
              AddObserver(POLICY_DOMAIN_CHROME, policy_service_android_.get()))
      .Times(1);
  int observer1 = Java_PolicyServiceTestSupporter_addObserver(env_, j_support_);
  int observer2 = Java_PolicyServiceTestSupporter_addObserver(env_, j_support_);

  // And we still observing the PolicyService as long as there is one Java
  // observer.
  Java_PolicyServiceTestSupporter_removeObserver(env_, j_support_, observer2);

  ::testing::Mock::VerifyAndClearExpectations(&policy_service_);

  // Trigger the event and only the activated Java observer get notified.
  policy_service_android_->OnPolicyServiceInitialized(POLICY_DOMAIN_CHROME);
  Java_PolicyServiceTestSupporter_verifyInitializationEvent(
      env_, j_support_, observer1, /*times*/ 1);
  Java_PolicyServiceTestSupporter_verifyInitializationEvent(
      env_, j_support_, observer2, /*times*/ 0);

  // Remove the last Java observers and triggers the C++ observer cleanup too.
  EXPECT_CALL(policy_service_, RemoveObserver(POLICY_DOMAIN_CHROME,
                                              policy_service_android_.get()))
      .Times(1);
  Java_PolicyServiceTestSupporter_removeObserver(env_, j_support_, observer1);
  ::testing::Mock::VerifyAndClearExpectations(&policy_service_);
}

TEST_F(PolicyServiceAndroidTest, PolicyUpdateEvent) {
  EXPECT_CALL(policy_service_,
              AddObserver(POLICY_DOMAIN_CHROME, policy_service_android_.get()))
      .Times(1);
  int observer_id =
      Java_PolicyServiceTestSupporter_addObserver(env_, j_support_);

  PolicyMap previous;
  PolicyMap current;
  previous.Set("policy", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
               POLICY_SOURCE_PLATFORM, base::Value(1), nullptr);
  current.Set("policy", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
              POLICY_SOURCE_PLATFORM, base::Value(2), nullptr);

  // PolicyMapAndroid needs to be valid until the verification is over.
  PolicyMapAndroid previous_android(previous);
  PolicyMapAndroid current_android(current);

  Java_PolicyServiceTestSupporter_setupPolicyUpdatedEventWithValues(
      env_, j_support_, /*index*/ 0, previous_android.GetJavaObject(),
      current_android.GetJavaObject());
  policy_service_android_->OnPolicyUpdated(
      PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()), previous, current);
  Java_PolicyServiceTestSupporter_verifyPolicyUpdatedEventWithValues(
      env_, j_support_, /*index*/ 0, /*times*/ 1);

  EXPECT_CALL(policy_service_, RemoveObserver(POLICY_DOMAIN_CHROME,
                                              policy_service_android_.get()))
      .Times(1);
  Java_PolicyServiceTestSupporter_removeObserver(env_, j_support_, observer_id);
  ::testing::Mock::VerifyAndClearExpectations(&policy_service_);
}

}  // namespace android
}  // namespace policy