blob: 6e96f669d119289342f93fccae4c777b5e2a2f70 [file] [log] [blame]
Ben Murdochbb1529c2013-08-08 10:24:53 +01001// Copyright 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 "chrome/browser/chromeos/extensions/file_manager/file_watcher.h"
6
7#include "base/file_util.h"
8#include "base/files/scoped_temp_dir.h"
9#include "base/message_loop/message_loop.h"
10#include "base/run_loop.h"
11#include "chrome/browser/google_apis/test_util.h"
12#include "content/public/test/test_browser_thread_bundle.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace file_manager {
16namespace {
17
18using google_apis::test_util::CreateQuitCallback;
19using google_apis::test_util::CreateCopyResultCallback;
20
21class FileManagerFileWatcherTest : public testing::Test {
22 public:
23 // Use IO_MAINLOOP so FilePathWatcher works in the fake FILE thread, which
24 // is actually shared with the main thread.
25 FileManagerFileWatcherTest()
26 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
27 }
28
29 private:
30 content::TestBrowserThreadBundle thread_bundle_;
31};
32
33TEST_F(FileManagerFileWatcherTest, AddAndRemoveOneExtensionId) {
34 const base::FilePath kVirtualPath =
35 base::FilePath::FromUTF8Unsafe("foo/bar.txt");
36 const char kExtensionId[] = "extension-id";
37
38 FileWatcher file_watcher(kVirtualPath);
39 file_watcher.AddExtension(kExtensionId);
40 std::vector<std::string> extension_ids = file_watcher.GetExtensionIds();
41
42 ASSERT_EQ(1U, extension_ids.size());
43 ASSERT_EQ(kExtensionId, extension_ids[0]);
44
45 file_watcher.RemoveExtension(kExtensionId);
46 extension_ids = file_watcher.GetExtensionIds();
47 ASSERT_EQ(0U, extension_ids.size());
48}
49
50TEST_F(FileManagerFileWatcherTest, AddAndRemoveMultipleExtensionIds) {
51 const base::FilePath kVirtualPath =
52 base::FilePath::FromUTF8Unsafe("foo/bar.txt");
53 const char kExtensionFooId[] = "extension-foo-id";
54 const char kExtensionBarId[] = "extension-bar-id";
55
56 FileWatcher file_watcher(kVirtualPath);
57 file_watcher.AddExtension(kExtensionFooId);
58 file_watcher.AddExtension(kExtensionBarId);
59 std::vector<std::string> extension_ids = file_watcher.GetExtensionIds();
60
61 // The list should be sorted.
62 ASSERT_EQ(2U, extension_ids.size());
63 ASSERT_EQ(kExtensionBarId, extension_ids[0]);
64 ASSERT_EQ(kExtensionFooId, extension_ids[1]);
65
66 // Remove Foo. Bar should remain.
67 file_watcher.RemoveExtension(kExtensionFooId);
68 extension_ids = file_watcher.GetExtensionIds();
69 ASSERT_EQ(1U, extension_ids.size());
70 ASSERT_EQ(kExtensionBarId, extension_ids[0]);
71
72 // Remove Bar. Nothing should remain.
73 file_watcher.RemoveExtension(kExtensionBarId);
74 extension_ids = file_watcher.GetExtensionIds();
75 ASSERT_EQ(0U, extension_ids.size());
76}
77
78TEST_F(FileManagerFileWatcherTest, AddSameExtensionMultipleTimes) {
79 const base::FilePath kVirtualPath =
80 base::FilePath::FromUTF8Unsafe("foo/bar.txt");
81 const char kExtensionId[] = "extension-id";
82
83 FileWatcher file_watcher(kVirtualPath);
84 // Add three times.
85 file_watcher.AddExtension(kExtensionId);
86 file_watcher.AddExtension(kExtensionId);
87 file_watcher.AddExtension(kExtensionId);
88
89 std::vector<std::string> extension_ids = file_watcher.GetExtensionIds();
90 ASSERT_EQ(1U, extension_ids.size());
91 ASSERT_EQ(kExtensionId, extension_ids[0]);
92
93 // Remove 1st time.
94 file_watcher.RemoveExtension(kExtensionId);
95 extension_ids = file_watcher.GetExtensionIds();
96 ASSERT_EQ(1U, extension_ids.size());
97
98 // Remove 2nd time.
99 file_watcher.RemoveExtension(kExtensionId);
100 extension_ids = file_watcher.GetExtensionIds();
101 ASSERT_EQ(1U, extension_ids.size());
102
103 // Remove 3rd time. The extension ID should be gone now.
104 file_watcher.RemoveExtension(kExtensionId);
105 extension_ids = file_watcher.GetExtensionIds();
106 ASSERT_EQ(0U, extension_ids.size());
107}
108
109TEST_F(FileManagerFileWatcherTest, WatchLocalFile) {
110 const base::FilePath kVirtualPath =
111 base::FilePath::FromUTF8Unsafe("foo/bar.txt");
112 const char kExtensionId[] = "extension-id";
113
114 // Create a temporary directory.
115 base::ScopedTempDir temp_dir;
116 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
117
118 // See the comment at the end of this function for why scoped_ptr is used.
119 scoped_ptr<FileWatcher> file_watcher(
120 new FileWatcher(kVirtualPath));
121 file_watcher->AddExtension(kExtensionId);
122
123 // Start watching changes in the temporary directory.
124 base::FilePath changed_path;
125 bool watcher_created = false;
126 bool on_change_error = false;
127 base::RunLoop run_loop;
128 file_watcher->WatchLocalFile(
129 temp_dir.path(),
130 CreateQuitCallback(
131 &run_loop,
132 CreateCopyResultCallback(&changed_path, &on_change_error)),
133 CreateCopyResultCallback(&watcher_created));
134 // Spin the message loop so the base::FilePathWatcher is created.
135 base::RunLoop().RunUntilIdle();
136 ASSERT_TRUE(watcher_created);
137
138 // Create a temporary file in the temporary directory. The file watcher
139 // should detect the change in the directory.
140 base::FilePath temp_file_path;
141 ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir.path(),
142 &temp_file_path));
143 // Wait until the directory change is notified.
144 run_loop.Run();
145 ASSERT_FALSE(on_change_error);
146 ASSERT_EQ(temp_dir.path().value(), changed_path.value());
147
148 // This is ugly, but FileWatcher should be deleted explicitly here, and
149 // spin the message loop so the base::FilePathWatcher is deleted.
150 // Otherwise, base::FilePathWatcher may detect a change when the temporary
151 // directory is deleted, which may result in crash.
152 file_watcher.reset();
153 base::RunLoop().RunUntilIdle();
154}
155
156} // namespace
157} // namespace file_manager.