Index: chrome/browser/extensions/extension_install_checker_unittest.cc |
diff --git a/chrome/browser/extensions/extension_install_checker_unittest.cc b/chrome/browser/extensions/extension_install_checker_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..af9ccb6964e53ec936dedd2bbbc0b9b5e1b0e632 |
--- /dev/null |
+++ b/chrome/browser/extensions/extension_install_checker_unittest.cc |
@@ -0,0 +1,349 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/bind.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
+#include "chrome/browser/extensions/extension_install_checker.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace extensions { |
+ |
+namespace { |
+ |
+const char kDummyRequirementsError[] = "Requirements error"; |
+const char kDummyPolicyError[] = "Cannot install extension"; |
+ |
+} // namespace |
+ |
+// Stubs most of the checks since we are interested in validating the logic in |
+// the install checker. This class implements a synchronous version of all |
+// checks. |
+class ExtensionInstallCheckerForTest : public ExtensionInstallChecker { |
+ public: |
+ ExtensionInstallCheckerForTest() |
+ : ExtensionInstallChecker(NULL), |
+ requirements_check_called_(false), |
+ blacklist_check_called_(false), |
+ policy_check_called_(false), |
+ blacklist_state_(NOT_BLACKLISTED) {} |
+ |
+ virtual ~ExtensionInstallCheckerForTest() {} |
+ |
+ void set_requirements_error(const std::string& error) { |
+ requirements_error_ = error; |
+ } |
+ void set_policy_check_error(const std::string& error) { |
+ policy_check_error_ = error; |
+ } |
+ void set_blacklist_state(BlacklistState state) { blacklist_state_ = state; } |
+ |
+ bool requirements_check_called() const { return requirements_check_called_; } |
+ bool blacklist_check_called() const { return blacklist_check_called_; } |
+ bool policy_check_called() const { return policy_check_called_; } |
+ |
+ void MockCheckRequirements() { |
+ std::vector<std::string> errors; |
+ if (!requirements_error_.empty()) |
+ errors.push_back(requirements_error_); |
+ OnRequirementsCheckDone(errors); |
+ } |
+ |
+ void MockCheckBlacklistState() { |
+ OnBlacklistStateCheckDone(blacklist_state_); |
+ } |
+ |
+ protected: |
+ virtual void CheckRequirements() OVERRIDE { |
+ requirements_check_called_ = true; |
+ MockCheckRequirements(); |
+ } |
+ |
+ virtual void CheckManagementPolicy() OVERRIDE { |
+ policy_check_called_ = true; |
+ OnManagementPolicyCheckDone(policy_check_error_.empty(), |
+ policy_check_error_); |
+ } |
+ |
+ virtual void CheckBlacklistState() OVERRIDE { |
+ blacklist_check_called_ = true; |
+ MockCheckBlacklistState(); |
+ } |
+ |
+ virtual void ResetResults() OVERRIDE { |
+ ExtensionInstallChecker::ResetResults(); |
+ |
+ requirements_check_called_ = false; |
+ blacklist_check_called_ = false; |
+ policy_check_called_ = false; |
+ } |
+ |
+ bool requirements_check_called_; |
+ bool blacklist_check_called_; |
+ bool policy_check_called_; |
+ |
+ // Dummy errors for testing. |
+ std::string requirements_error_; |
+ std::string policy_check_error_; |
+ BlacklistState blacklist_state_; |
+}; |
+ |
+// This class implements asynchronous mocks of the requirements and blacklist |
+// checks. |
+class ExtensionInstallCheckerAsync : public ExtensionInstallCheckerForTest { |
+ protected: |
+ virtual void CheckRequirements() OVERRIDE { |
+ requirements_check_called_ = true; |
+ |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&ExtensionInstallCheckerForTest::MockCheckRequirements, |
+ base::Unretained(this))); |
+ } |
+ |
+ virtual void CheckBlacklistState() OVERRIDE { |
+ blacklist_check_called_ = true; |
+ |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&ExtensionInstallCheckerForTest::MockCheckBlacklistState, |
+ base::Unretained(this))); |
+ } |
+}; |
+ |
+class CheckObserver { |
+ public: |
+ CheckObserver() : result_(0), call_count_(0) {} |
+ |
+ int result() const { return result_; } |
+ int call_count() const { return call_count_; } |
+ |
+ void OnChecksComplete(int checks_failed) { |
+ result_ = checks_failed; |
+ ++call_count_; |
+ } |
+ |
+ void Wait() { |
+ if (call_count_) |
+ return; |
+ |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+ |
+ private: |
+ int result_; |
+ int call_count_; |
+}; |
+ |
+class ExtensionInstallCheckerTest : public testing::Test { |
+ protected: |
+ ExtensionInstallCheckerTest() {} |
+ virtual ~ExtensionInstallCheckerTest() {} |
+ |
+ void SetAllErrors(ExtensionInstallCheckerForTest* checker) { |
+ checker->set_blacklist_state(BLACKLISTED_MALWARE); |
+ checker->set_policy_check_error(kDummyPolicyError); |
+ checker->set_requirements_error(kDummyRequirementsError); |
+ } |
+ |
+ void ValidateExpectedCalls(int call_mask, |
+ const ExtensionInstallCheckerForTest& checker) { |
+ bool expect_blacklist_checked = |
+ (call_mask & ExtensionInstallChecker::CHECK_BLACKLIST) != 0; |
+ bool expect_requirements_checked = |
+ (call_mask & ExtensionInstallChecker::CHECK_REQUIREMENTS) != 0; |
+ bool expect_policy_checked = |
+ (call_mask & ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY) != 0; |
+ EXPECT_EQ(expect_blacklist_checked, checker.blacklist_check_called()); |
+ EXPECT_EQ(expect_policy_checked, checker.policy_check_called()); |
+ EXPECT_EQ(expect_requirements_checked, checker.requirements_check_called()); |
+ } |
+ |
+ void ExpectRequirementsPass(const ExtensionInstallCheckerForTest& checker) { |
+ EXPECT_TRUE(checker.requirement_errors().empty()); |
+ } |
+ |
+ void ExpectRequirementsError(const ExtensionInstallCheckerForTest& checker) { |
+ EXPECT_FALSE(checker.requirement_errors().empty()); |
+ EXPECT_EQ(std::string(kDummyRequirementsError), |
+ checker.requirement_errors().front()); |
+ } |
+ |
+ void ExpectBlacklistPass(const ExtensionInstallCheckerForTest& checker) { |
+ EXPECT_EQ(NOT_BLACKLISTED, checker.blacklist_state()); |
+ } |
+ |
+ void ExpectBlacklistError(const ExtensionInstallCheckerForTest& checker) { |
+ EXPECT_EQ(BLACKLISTED_MALWARE, checker.blacklist_state()); |
+ } |
+ |
+ void ExpectPolicyPass(const ExtensionInstallCheckerForTest& checker) { |
+ EXPECT_TRUE(checker.policy_allows_load()); |
+ EXPECT_TRUE(checker.policy_error().empty()); |
+ } |
+ |
+ void ExpectPolicyError(const ExtensionInstallCheckerForTest& checker) { |
+ EXPECT_FALSE(checker.policy_allows_load()); |
+ EXPECT_FALSE(checker.policy_error().empty()); |
+ EXPECT_EQ(std::string(kDummyPolicyError), checker.policy_error()); |
+ } |
+ |
+ void RunChecker(ExtensionInstallCheckerForTest* checker, |
+ bool fail_fast, |
+ int checks_to_run, |
+ int expected_checks_run, |
+ int expected_result) { |
+ CheckObserver observer; |
+ checker->Start(checks_to_run, |
+ fail_fast, |
+ base::Bind(&CheckObserver::OnChecksComplete, |
+ base::Unretained(&observer))); |
+ observer.Wait(); |
+ |
+ EXPECT_FALSE(checker->is_running()); |
+ EXPECT_EQ(expected_result, observer.result()); |
+ EXPECT_EQ(1, observer.call_count()); |
+ ValidateExpectedCalls(expected_checks_run, *checker); |
+ } |
+ |
+ void DoRunAllChecksPass(ExtensionInstallCheckerForTest* checker) { |
+ RunChecker(checker, |
+ false, |
+ ExtensionInstallChecker::CHECK_ALL, |
+ ExtensionInstallChecker::CHECK_ALL, |
+ 0); |
+ |
+ ExpectRequirementsPass(*checker); |
+ ExpectPolicyPass(*checker); |
+ ExpectBlacklistPass(*checker); |
+ } |
+ |
+ void DoRunAllChecksFail(ExtensionInstallCheckerForTest* checker) { |
+ SetAllErrors(checker); |
+ RunChecker(checker, |
+ false, |
+ ExtensionInstallChecker::CHECK_ALL, |
+ ExtensionInstallChecker::CHECK_ALL, |
+ ExtensionInstallChecker::CHECK_ALL); |
+ |
+ ExpectRequirementsError(*checker); |
+ ExpectPolicyError(*checker); |
+ ExpectBlacklistError(*checker); |
+ } |
+ |
+ void DoRunSubsetOfChecks(ExtensionInstallCheckerForTest* checker) { |
+ // Test check set 1. |
+ int tests_to_run = ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY | |
+ ExtensionInstallChecker::CHECK_REQUIREMENTS; |
+ SetAllErrors(checker); |
+ RunChecker(checker, false, tests_to_run, tests_to_run, tests_to_run); |
+ |
+ ExpectRequirementsError(*checker); |
+ ExpectPolicyError(*checker); |
+ ExpectBlacklistPass(*checker); |
+ |
+ // Test check set 2. |
+ tests_to_run = ExtensionInstallChecker::CHECK_BLACKLIST | |
+ ExtensionInstallChecker::CHECK_REQUIREMENTS; |
+ SetAllErrors(checker); |
+ RunChecker(checker, false, tests_to_run, tests_to_run, tests_to_run); |
+ |
+ ExpectRequirementsError(*checker); |
+ ExpectPolicyPass(*checker); |
+ ExpectBlacklistError(*checker); |
+ |
+ // Test a single check. |
+ tests_to_run = ExtensionInstallChecker::CHECK_BLACKLIST; |
+ SetAllErrors(checker); |
+ RunChecker(checker, false, tests_to_run, tests_to_run, tests_to_run); |
+ |
+ ExpectRequirementsPass(*checker); |
+ ExpectPolicyPass(*checker); |
+ ExpectBlacklistError(*checker); |
+ } |
+ |
+ private: |
+ // A message loop is required for the asynchronous tests. |
+ base::MessageLoop message_loop; |
+}; |
+ |
+// Test the case where all tests pass. |
+TEST_F(ExtensionInstallCheckerTest, AllSucceeded) { |
+ ExtensionInstallCheckerForTest sync_checker; |
+ DoRunAllChecksPass(&sync_checker); |
+ |
+ ExtensionInstallCheckerAsync async_checker; |
+ DoRunAllChecksPass(&async_checker); |
+} |
+ |
+// Test the case where all tests fail. |
+TEST_F(ExtensionInstallCheckerTest, AllFailed) { |
+ ExtensionInstallCheckerForTest sync_checker; |
+ DoRunAllChecksFail(&sync_checker); |
+ |
+ ExtensionInstallCheckerAsync async_checker; |
+ DoRunAllChecksFail(&async_checker); |
+} |
+ |
+// Test running only a subset of tests. |
+TEST_F(ExtensionInstallCheckerTest, RunSubsetOfChecks) { |
+ ExtensionInstallCheckerForTest sync_checker; |
+ ExtensionInstallCheckerAsync async_checker; |
+ DoRunSubsetOfChecks(&sync_checker); |
+ DoRunSubsetOfChecks(&async_checker); |
+} |
+ |
+// Test fail fast with synchronous callbacks. |
+TEST_F(ExtensionInstallCheckerTest, FailFastSync) { |
+ // This test assumes some internal knowledge of the implementation - that |
+ // the policy check runs first. |
+ ExtensionInstallCheckerForTest checker; |
+ SetAllErrors(&checker); |
+ RunChecker(&checker, |
+ true, |
+ ExtensionInstallChecker::CHECK_ALL, |
+ ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY, |
+ ExtensionInstallChecker::CHECK_MANAGEMENT_POLICY); |
+ |
+ ExpectRequirementsPass(checker); |
+ ExpectPolicyError(checker); |
+ ExpectBlacklistPass(checker); |
+ |
+ // This test assumes some internal knowledge of the implementation - that |
+ // the requirements check runs before the blacklist check. |
+ SetAllErrors(&checker); |
+ RunChecker(&checker, |
+ true, |
+ ExtensionInstallChecker::CHECK_REQUIREMENTS | |
+ ExtensionInstallChecker::CHECK_BLACKLIST, |
+ ExtensionInstallChecker::CHECK_REQUIREMENTS, |
+ ExtensionInstallChecker::CHECK_REQUIREMENTS); |
+ |
+ ExpectRequirementsError(checker); |
+ ExpectPolicyPass(checker); |
+ ExpectBlacklistPass(checker); |
+} |
+ |
+// Test fail fast with asynchronous callbacks. |
+TEST_F(ExtensionInstallCheckerTest, FailFastAsync) { |
+ // This test assumes some internal knowledge of the implementation - that |
+ // the requirements check runs before the blacklist check. |
+ // Both checks should be called, but the requirements check callback arrives |
+ // first and the blacklist result will be discarded. |
+ ExtensionInstallCheckerAsync checker; |
+ SetAllErrors(&checker); |
+ RunChecker(&checker, |
+ true, |
+ ExtensionInstallChecker::CHECK_REQUIREMENTS | |
+ ExtensionInstallChecker::CHECK_BLACKLIST, |
+ ExtensionInstallChecker::CHECK_REQUIREMENTS | |
+ ExtensionInstallChecker::CHECK_BLACKLIST, |
+ ExtensionInstallChecker::CHECK_REQUIREMENTS); |
+ |
+ ExpectRequirementsError(checker); |
+ ExpectPolicyPass(checker); |
+ ExpectBlacklistPass(checker); |
+} |
+ |
+} // namespace extensions |