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