1// 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/drive/file_write_watcher.h" 6 7#include <set> 8 9#include "base/bind.h" 10#include "base/files/file_util.h" 11#include "base/files/scoped_temp_dir.h" 12#include "base/run_loop.h" 13#include "content/public/test/test_browser_thread_bundle.h" 14#include "testing/gtest/include/gtest/gtest.h" 15 16namespace drive { 17namespace internal { 18 19namespace { 20 21class TestObserver { 22 public: 23 // After all the resource_ids in |expected_upload| are notified for the 24 // need of uploading, runs |quit_closure|. Also checks that each id is 25 // notified only once. 26 TestObserver(const std::set<std::string>& expected_upload, 27 const base::Closure& quit_closure) 28 : expected_upload_(expected_upload), 29 quit_closure_(quit_closure) { 30 } 31 32 void OnWrite(const std::string& id) { 33 EXPECT_EQ(1U, expected_upload_.count(id)) << id; 34 expected_upload_.erase(id); 35 if (expected_upload_.empty()) 36 quit_closure_.Run(); 37 } 38 39 private: 40 std::set<std::string> expected_upload_; 41 base::Closure quit_closure_; 42}; 43 44// Writes something on the file at |path|. 45void WriteSomethingAfterStartWatch(const base::FilePath& path, 46 bool watch_success) { 47 EXPECT_TRUE(watch_success) << path.value(); 48 49 const char kDummy[] = "hello"; 50 ASSERT_TRUE(base::WriteFile(path, kDummy, arraysize(kDummy))); 51} 52 53class FileWriteWatcherTest : public testing::Test { 54 protected: 55 // The test requires UI thread (FileWriteWatcher DCHECKs that its public 56 // interface is running on UI thread) and FILE thread (Linux version of 57 // base::FilePathWatcher needs to live on an IOAllowed thread with TYPE_IO, 58 // which is FILE thread in the production environment). 59 // 60 // By using the IO_MAINLOOP test thread bundle, the main thread is used 61 // both as UI and FILE thread, with TYPE_IO message loop. 62 FileWriteWatcherTest() 63 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) { 64 } 65 66 virtual void SetUp() OVERRIDE { 67 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 68 } 69 70 base::FilePath GetTempPath(const std::string& name) { 71 return temp_dir_.path().Append(name); 72 } 73 74 private: 75 content::TestBrowserThreadBundle thread_bundle_; 76 base::ScopedTempDir temp_dir_; 77}; 78 79} // namespace 80 81TEST_F(FileWriteWatcherTest, WatchThreeFiles) { 82 std::set<std::string> expected; 83 expected.insert("1"); 84 expected.insert("2"); 85 expected.insert("3"); 86 87 base::RunLoop loop; 88 TestObserver observer(expected, loop.QuitClosure()); 89 90 // Set up the watcher. 91 FileWriteWatcher watcher; 92 watcher.DisableDelayForTesting(); 93 94 // Start watching and running. 95 base::FilePath path1 = GetTempPath("foo.txt"); 96 base::FilePath path2 = GetTempPath("bar.png"); 97 base::FilePath path3 = GetTempPath("buz.doc"); 98 base::FilePath path4 = GetTempPath("mya.mp3"); 99 watcher.StartWatch( 100 path1, 101 base::Bind(&WriteSomethingAfterStartWatch, path1), 102 base::Bind(&TestObserver::OnWrite, base::Unretained(&observer), "1")); 103 watcher.StartWatch( 104 path2, 105 base::Bind(&WriteSomethingAfterStartWatch, path2), 106 base::Bind(&TestObserver::OnWrite, base::Unretained(&observer), "2")); 107 watcher.StartWatch( 108 path3, 109 base::Bind(&WriteSomethingAfterStartWatch, path3), 110 base::Bind(&TestObserver::OnWrite, base::Unretained(&observer), "3")); 111 112 // Unwatched write. It shouldn't be notified. 113 WriteSomethingAfterStartWatch(path4, true); 114 115 // The loop should quit if all the three paths are notified to be written. 116 loop.Run(); 117} 118 119} // namespace internal 120} // namespace drive 121