| // Copyright 2018 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 "chrome/chrome_cleaner/components/recovery_component.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "base/files/file.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/test/test_simple_task_runner.h" |
| #include "chrome/chrome_cleaner/http/mock_http_agent_factory.h" |
| #include "chrome/chrome_cleaner/test/test_pup_data.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace chrome_cleaner { |
| |
| namespace { |
| |
| const UwSId kRemovableUwSId = 42; |
| const UwSId kReportOnlyUwSId = 21; |
| |
| } // namespace |
| |
| class TestRecoveryComponent : public RecoveryComponent { |
| public: |
| TestRecoveryComponent() = default; |
| |
| using RecoveryComponent::WaitForDoneExpandingCrxForTest; |
| |
| bool run_called() const { return run_called_; } |
| bool unpack_component_called() const { return unpack_component_called_; } |
| const std::string& crx_file_contents() const { return crx_file_contents_; } |
| |
| protected: |
| // RecoveryComponent. |
| void Run() override { run_called_ = true; } |
| void UnpackComponent(const base::FilePath& crx_file) override { |
| unpack_component_called_ = true; |
| |
| if (base::PathExists(crx_file)) { |
| ASSERT_TRUE(base::ReadFileToString(crx_file, &crx_file_contents_)); |
| } |
| } |
| |
| private: |
| bool run_called_{false}; |
| bool unpack_component_called_{false}; |
| std::string crx_file_contents_; |
| }; |
| |
| class RecoveryComponentTest : public testing::Test { |
| public: |
| void SetUp() override { |
| RecoveryComponent::SetHttpAgentFactoryForTesting(factory_.get()); |
| } |
| |
| void TearDown() override { |
| RecoveryComponent::SetHttpAgentFactoryForTesting(nullptr); |
| } |
| |
| protected: |
| RecoveryComponentTest() : task_runner_(new base::TestSimpleTaskRunner) {} |
| |
| // A message loop is needed for the current task runner to be available. |
| base::MessageLoopForUI ui_message_loop_; |
| |
| // The recover component under test. This declaration must be after the |
| // |ui_message_loop_| because the |RecoveryComponent| constructor needs |
| // a reference to the current run loop. |
| TestRecoveryComponent recovery_component_; |
| |
| // A task runner and a URL fetcher factory are necessary to test URL requests. |
| scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
| |
| MockHttpAgentConfig config_; |
| std::unique_ptr<HttpAgentFactory> factory_{ |
| std::make_unique<MockHttpAgentFactory>(&config_)}; |
| }; |
| |
| TEST_F(RecoveryComponentTest, Success) { |
| MockHttpAgentConfig::Calls calls(HttpStatus::kOk); |
| config_.AddCalls(calls); |
| |
| recovery_component_.PreScan(); |
| recovery_component_.WaitForDoneExpandingCrxForTest(); |
| EXPECT_TRUE(recovery_component_.unpack_component_called()); |
| } |
| |
| TEST_F(RecoveryComponentTest, Failure) { |
| MockHttpAgentConfig::Calls calls(HttpStatus::kOk); |
| calls.request_succeeds = false; |
| config_.AddCalls(calls); |
| |
| recovery_component_.PreScan(); |
| recovery_component_.WaitForDoneExpandingCrxForTest(); |
| EXPECT_FALSE(recovery_component_.unpack_component_called()); |
| } |
| |
| TEST_F(RecoveryComponentTest, CrxDataSavedToDisk) { |
| const std::string test_data = "test data"; |
| |
| MockHttpAgentConfig::Calls calls(HttpStatus::kOk); |
| calls.read_data_result = test_data; |
| config_.AddCalls(calls); |
| |
| recovery_component_.PreScan(); |
| recovery_component_.WaitForDoneExpandingCrxForTest(); |
| EXPECT_TRUE(recovery_component_.unpack_component_called()); |
| EXPECT_EQ(test_data, recovery_component_.crx_file_contents()); |
| } |
| |
| TEST_F(RecoveryComponentTest, CrxDataPartiallySavedToDisk) { |
| // Ensure the buffer is large enough, so a second buffer needs to be read. |
| const std::string test_data = |
| std::string(RecoveryComponent::kReadDataFromResponseBufferSize + 1, 'x'); |
| |
| MockHttpAgentConfig::Calls calls(HttpStatus::kOk); |
| calls.read_data_result = test_data; |
| calls.read_data_success_sequence.push_back(true); |
| calls.read_data_success_sequence.push_back(false); |
| config_.AddCalls(calls); |
| |
| recovery_component_.PreScan(); |
| recovery_component_.WaitForDoneExpandingCrxForTest(); |
| EXPECT_FALSE(recovery_component_.unpack_component_called()); |
| } |
| |
| TEST_F(RecoveryComponentTest, RunCalledForRemovablePUP) { |
| const UwSId kRemovableUwSId = 42; |
| std::vector<UwSId> found_pups; |
| TestPUPData test_pup_data; |
| |
| // When a removable PUP was found, the post scan shouldn't run, it should |
| // wait for the post-cleanup. |
| test_pup_data.AddPUP(kRemovableUwSId, PUPData::FLAGS_ACTION_REMOVE, nullptr, |
| PUPData::kMaxFilesToRemoveSmallUwS); |
| found_pups.push_back(kRemovableUwSId); |
| recovery_component_.PostScan(found_pups); |
| EXPECT_FALSE(recovery_component_.run_called()); |
| recovery_component_.PostCleanup(RESULT_CODE_SUCCESS, nullptr); |
| EXPECT_TRUE(recovery_component_.run_called()); |
| } |
| |
| TEST_F(RecoveryComponentTest, RunCalledForNoPUPs) { |
| std::vector<UwSId> found_pups; |
| TestPUPData test_pup_data; |
| |
| // When no PUPs are found, the post scan should run, but not the post-cleanup. |
| found_pups.clear(); |
| recovery_component_.PostScan(found_pups); |
| EXPECT_TRUE(recovery_component_.run_called()); |
| } |
| |
| TEST_F(RecoveryComponentTest, RunCalledForReportOnlyUwS) { |
| std::vector<UwSId> found_pups; |
| TestPUPData test_pup_data; |
| |
| // When only report only PUPs are found, the post scan should run, but not the |
| // post-cleanup. |
| test_pup_data.AddPUP(kReportOnlyUwSId, PUPData::FLAGS_NONE, nullptr, |
| PUPData::kMaxFilesToRemoveSmallUwS); |
| found_pups.push_back(kReportOnlyUwSId); |
| recovery_component_.PostScan(found_pups); |
| EXPECT_TRUE(recovery_component_.run_called()); |
| } |
| |
| TEST_F(RecoveryComponentTest, RunNotCalledPreReboot) { |
| std::vector<UwSId> found_pups; |
| TestPUPData test_pup_data; |
| |
| // And finally, when a reboot will be needed, none should call run. |
| test_pup_data.AddPUP(kRemovableUwSId, PUPData::FLAGS_ACTION_REMOVE, nullptr, |
| PUPData::kMaxFilesToRemoveSmallUwS); |
| found_pups.push_back(kRemovableUwSId); |
| recovery_component_.PostScan(found_pups); |
| EXPECT_FALSE(recovery_component_.run_called()); |
| recovery_component_.PostCleanup(RESULT_CODE_PENDING_REBOOT, nullptr); |
| EXPECT_FALSE(recovery_component_.run_called()); |
| } |
| |
| } // namespace chrome_cleaner |