1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "remoting/host/config_file_watcher.h" 6 7#include "base/files/file_path.h" 8#include "base/files/file_util.h" 9#include "base/message_loop/message_loop.h" 10#include "base/run_loop.h" 11#include "remoting/base/auto_thread.h" 12#include "remoting/base/auto_thread_task_runner.h" 13#include "testing/gmock/include/gmock/gmock.h" 14#include "testing/gmock_mutant.h" 15#include "testing/gtest/include/gtest/gtest.h" 16 17using testing::_; 18using testing::AnyNumber; 19using testing::Return; 20 21namespace remoting { 22 23namespace { 24 25class ConfigFileWatcherDelegate : public ConfigFileWatcher::Delegate { 26 public: 27 ConfigFileWatcherDelegate() {} 28 virtual ~ConfigFileWatcherDelegate() {} 29 30 MOCK_METHOD1(OnConfigUpdated, void(const std::string&)); 31 MOCK_METHOD0(OnConfigWatcherError, void()); 32 33 private: 34 DISALLOW_COPY_AND_ASSIGN(ConfigFileWatcherDelegate); 35}; 36 37} // namespace 38 39class ConfigFileWatcherTest : public testing::Test { 40 public: 41 ConfigFileWatcherTest(); 42 virtual ~ConfigFileWatcherTest(); 43 44 // testing::Test overrides 45 virtual void SetUp() OVERRIDE; 46 virtual void TearDown() OVERRIDE; 47 48 // Stops the config file watcher. 49 void StopWatcher(); 50 51 protected: 52 base::MessageLoopForUI message_loop_; 53 base::RunLoop run_loop_; 54 55 ConfigFileWatcherDelegate delegate_; 56 57 // Path to the configuration file used. 58 base::FilePath config_file_; 59 60 // The configuration file watcher that is being tested. 61 scoped_ptr<ConfigFileWatcher> watcher_; 62}; 63 64ConfigFileWatcherTest::ConfigFileWatcherTest() { 65} 66 67ConfigFileWatcherTest::~ConfigFileWatcherTest() { 68} 69 70void ConfigFileWatcherTest::StopWatcher() { 71 watcher_.reset(); 72} 73 74void ConfigFileWatcherTest::SetUp() { 75 EXPECT_TRUE(base::CreateTemporaryFile(&config_file_)); 76 77 // Arrange to run |message_loop_| until no components depend on it. 78 scoped_refptr<AutoThreadTaskRunner> task_runner = new AutoThreadTaskRunner( 79 message_loop_.message_loop_proxy(), run_loop_.QuitClosure()); 80 81 scoped_refptr<AutoThreadTaskRunner> io_task_runner = 82 AutoThread::CreateWithType( 83 "IPC thread", task_runner, base::MessageLoop::TYPE_IO); 84 85 // Create an instance of the config watcher. 86 watcher_.reset( 87 new ConfigFileWatcher(task_runner, io_task_runner, config_file_)); 88} 89 90void ConfigFileWatcherTest::TearDown() { 91 // Delete the test file. 92 if (!config_file_.empty()) 93 base::DeleteFile(config_file_, false); 94} 95 96// Verifies that the initial notification is delivered. 97TEST_F(ConfigFileWatcherTest, Basic) { 98 std::string data("test"); 99 EXPECT_NE(base::WriteFile(config_file_, data.c_str(), 100 static_cast<int>(data.size())), -1); 101 102 EXPECT_CALL(delegate_, OnConfigUpdated(_)) 103 .Times(1) 104 .WillOnce(InvokeWithoutArgs(this, &ConfigFileWatcherTest::StopWatcher)); 105 EXPECT_CALL(delegate_, OnConfigWatcherError()) 106 .Times(0); 107 108 watcher_->Watch(&delegate_); 109 run_loop_.Run(); 110} 111 112MATCHER_P(EqualsString, s, "") { 113 return arg == s; 114} 115 116// Verifies that an update notification is sent when the file is changed. 117TEST_F(ConfigFileWatcherTest, Update) { 118 EXPECT_CALL(delegate_, OnConfigUpdated(EqualsString("test"))) 119 .Times(1) 120 .WillOnce(InvokeWithoutArgs(this, &ConfigFileWatcherTest::StopWatcher)); 121 EXPECT_CALL(delegate_, OnConfigWatcherError()) 122 .Times(0); 123 124 watcher_->Watch(&delegate_); 125 126 // Modify the watched file. 127 std::string data("test"); 128 EXPECT_NE(base::WriteFile(config_file_, data.c_str(), 129 static_cast<int>(data.size())), -1); 130 131 run_loop_.Run(); 132} 133 134} // namespace remoting 135