| Index: chrome/common/conflicts/module_watcher_win_unittest.cc
|
| diff --git a/chrome/common/conflicts/module_watcher_win_unittest.cc b/chrome/common/conflicts/module_watcher_win_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f712eaaac317c358d399ad1597c6250298d5d990
|
| --- /dev/null
|
| +++ b/chrome/common/conflicts/module_watcher_win_unittest.cc
|
| @@ -0,0 +1,141 @@
|
| +// Copyright 2016 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/common/conflicts/module_watcher_win.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/observer_list_threadsafe.h"
|
| +#include "base/run_loop.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace conflicts {
|
| +
|
| +class ModuleWatcherTest : public testing::Test {
|
| + public:
|
| + ModuleWatcherTest()
|
| + : module_(nullptr),
|
| + module_event_count_(0),
|
| + module_already_loaded_event_count_(0),
|
| + module_loaded_event_count_(0),
|
| + module_unloaded_event_count_(0) {}
|
| +
|
| + void OnModuleEvent(const ModuleWatcher::ModuleEvent& event) {
|
| + module_event_count_++;
|
| + switch (event.event_type) {
|
| + case ModuleWatcher::MODULE_ALREADY_LOADED:
|
| + module_already_loaded_event_count_++;
|
| + break;
|
| + case ModuleWatcher::MODULE_LOADED:
|
| + module_loaded_event_count_++;
|
| + break;
|
| + case ModuleWatcher::MODULE_UNLOADED:
|
| + module_unloaded_event_count_++;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + void SetUp() override {
|
| + message_loop_.reset(new base::MessageLoopForUI());
|
| + observer_ = mw_.RegisterCallback(
|
| + base::Bind(&ModuleWatcherTest::OnModuleEvent, base::Unretained(this)));
|
| + }
|
| +
|
| + void TearDown() override {
|
| + observer_.reset();
|
| + message_loop_.reset();
|
| + UnloadModule();
|
| + }
|
| +
|
| + void RunLoopUntilIdle() { base::RunLoop().RunUntilIdle(); }
|
| +
|
| + void AssertNoObservers() { mw_.observer_list_->AssertEmpty(); }
|
| +
|
| + void LoadModule() {
|
| + if (module_)
|
| + return;
|
| + // This module should not be a static dependency of the unit-test
|
| + // executable, but should be a build-system dependency or a module that is
|
| + // present on any Windows machine.
|
| + static const wchar_t kModuleName[] = L"chrome.dll";
|
| + // The module should not already be loaded.
|
| + ASSERT_FALSE(::GetModuleHandle(kModuleName));
|
| + // It should have loaded successfully.
|
| + module_ = ::LoadLibrary(kModuleName);
|
| + ASSERT_TRUE(module_);
|
| + }
|
| +
|
| + void UnloadModule() {
|
| + if (!module_)
|
| + return;
|
| + ::FreeLibrary(module_);
|
| + module_ = nullptr;
|
| + }
|
| +
|
| + // The module watcher used by the test.
|
| + ModuleWatcher mw_;
|
| +
|
| + // The observer object.
|
| + std::unique_ptr<ModuleWatcher::Observer> observer_;
|
| +
|
| + // Holds a handle to a loaded module.
|
| + HMODULE module_;
|
| +
|
| + // Total number of module events seen.
|
| + size_t module_event_count_;
|
| + // Total number of MODULE_ALREADY_LOADED events seen.
|
| + size_t module_already_loaded_event_count_;
|
| + // Total number of MODULE_LOADED events seen.
|
| + size_t module_loaded_event_count_;
|
| + // Total number of MODULE_UNLOADED events seen.
|
| + size_t module_unloaded_event_count_;
|
| +
|
| + private:
|
| + std::unique_ptr<base::MessageLoopForUI> message_loop_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ModuleWatcherTest);
|
| +};
|
| +
|
| +TEST_F(ModuleWatcherTest, ModuleEvents) {
|
| + EXPECT_FALSE(mw_.IsRunning());
|
| + EXPECT_EQ(0u, module_event_count_);
|
| +
|
| + // Start the watcher and ensure it enumerates already loaded modules.
|
| + mw_.Start();
|
| + EXPECT_TRUE(mw_.IsRunning());
|
| + RunLoopUntilIdle();
|
| + EXPECT_LT(0u, module_event_count_);
|
| + EXPECT_LT(0u, module_already_loaded_event_count_);
|
| + EXPECT_EQ(0u, module_loaded_event_count_);
|
| + EXPECT_EQ(0u, module_unloaded_event_count_);
|
| +
|
| + // Dynamically load a module and ensure it a notification is received for it.
|
| + LoadModule();
|
| + RunLoopUntilIdle();
|
| + EXPECT_EQ(1u, module_loaded_event_count_);
|
| +
|
| + // Unload the module and ensure another notification is received.
|
| + UnloadModule();
|
| + RunLoopUntilIdle();
|
| + EXPECT_EQ(1u, module_unloaded_event_count_);
|
| +
|
| + // Dynamically load a module and ensure it a notification is received for it.
|
| + LoadModule();
|
| + RunLoopUntilIdle();
|
| + EXPECT_EQ(2u, module_loaded_event_count_);
|
| +
|
| + // Stop the module watcher.
|
| + mw_.Stop();
|
| +
|
| + // Unload the module and ensure no notification is received this time.
|
| + UnloadModule();
|
| + RunLoopUntilIdle();
|
| + EXPECT_EQ(1u, module_unloaded_event_count_);
|
| +
|
| + // Clean up the observer and ensure it was removed.
|
| + observer_.reset();
|
| + AssertNoObservers();
|
| +}
|
| +
|
| +} // namespace conflicts
|
|
|