blob: c29da569860903630b531e8f2572bb013ad6749b [file] [log] [blame]
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Lijing Wange0dd63e2015-05-31 16:25:16 -07003 * Copyright (c) 2013-2017, Regents of the University of California.
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08004 *
5 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
6 *
7 * ChronoShare is free software: you can redistribute it and/or modify it under the terms
8 * of the GNU General Public License as published by the Free Software Foundation, either
9 * version 3 of the License, or (at your option) any later version.
10 *
11 * ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License along with
16 * ChronoShare, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * See AUTHORS.md for complete list of ChronoShare authors and contributors.
19 */
Yukai Tu73287f52017-02-06 15:46:40 -080020#define BOOST_TEST_MAIN 1
21#define BOOST_TEST_DYN_LINK 1
22#define BOOST_TEST_MODULE ChronoShare Integrated Tests (FsWatcher)
Lijing Wange0dd63e2015-05-31 16:25:16 -070023
Alexander Afanasyevf4cde4e2016-12-25 13:42:57 -080024#include "fs-watcher.hpp"
Lijing Wange0dd63e2015-05-31 16:25:16 -070025#include "test-common.hpp"
26
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080027#include <boost/bind.hpp>
Zhenkai Zhud1756272013-02-01 17:02:18 -080028#include <boost/filesystem.hpp>
Lijing Wange0dd63e2015-05-31 16:25:16 -070029#include <boost/filesystem/fstream.hpp>
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080030#include <boost/lexical_cast.hpp>
31#include <boost/make_shared.hpp>
Zhenkai Zhud1756272013-02-01 17:02:18 -080032#include <boost/test/unit_test.hpp>
33#include <boost/thread/thread.hpp>
Zhenkai Zhud1756272013-02-01 17:02:18 -080034#include <fstream>
Lijing Wange0dd63e2015-05-31 16:25:16 -070035#include <iostream>
36#include <thread>
Zhenkai Zhud1756272013-02-01 17:02:18 -080037#include <set>
Yukai Tu73287f52017-02-06 15:46:40 -080038#include <QtWidgets>
Lijing Wange0dd63e2015-05-31 16:25:16 -070039
Zhenkai Zhud1756272013-02-01 17:02:18 -080040using namespace std;
Zhenkai Zhud1756272013-02-01 17:02:18 -080041namespace fs = boost::filesystem;
42
Lijing Wange0dd63e2015-05-31 16:25:16 -070043_LOG_INIT(Test.FSWatcher);
Zhenkai Zhud1756272013-02-01 17:02:18 -080044
Lijing Wange0dd63e2015-05-31 16:25:16 -070045namespace ndn {
46namespace chronoshare {
47namespace tests {
48
Lijing Wange0dd63e2015-05-31 16:25:16 -070049class TestFSWatcherFixture : public IdentityManagementFixture
Zhenkai Zhud1756272013-02-01 17:02:18 -080050{
Lijing Wange0dd63e2015-05-31 16:25:16 -070051public:
52 TestFSWatcherFixture()
53 : dir(fs::path(UNIT_TEST_CONFIG_PATH) / "TestFsWatcher")
54 , argc(0)
55 {
56 if (fs::exists(dir)) {
57 fs::remove_all(dir);
58 }
59
60 fs::create_directory(dir);
Zhenkai Zhud1756272013-02-01 17:02:18 -080061 }
Zhenkai Zhud1756272013-02-01 17:02:18 -080062
Lijing Wange0dd63e2015-05-31 16:25:16 -070063 ~TestFSWatcherFixture(){
64 // cleanup
65 if (fs::exists(dir)) {
66 _LOG_DEBUG("clean all");
67 fs::remove_all(dir);
68 }
69 }
70
71 void
72 advanceClocks(std::chrono::seconds delay)
73 {
74 std::chrono::milliseconds step = delay;
75 step /= 50;
76 for (int i = 0; i < 50; ++i) {
77 std::this_thread::sleep_for(step);
78 m_io.poll();
79 m_io.reset();
80 }
81 }
82
83 void
84 onChange(set<string>& files, const fs::path& file)
85 {
86 _LOG_DEBUG("on change, file: " << file);
87 files.insert(file.string());
88 }
89
90 void
91 onDelete(set<string>& files, const fs::path& file)
92 {
93 _LOG_DEBUG("on delete, file: " << file);
94 files.erase(file.string());
95 }
96
97 void
98 create_file(const fs::path& ph, const std::string& contents)
99 {
100 std::ofstream f(ph.string().c_str());
101 if (!f) {
102 abort();
103 }
104 if (!contents.empty()) {
105 f << contents;
106 }
107 }
108
109 void
110 run()
111 {
Yukai Tu73287f52017-02-06 15:46:40 -0800112 QApplication app(argc, nullptr);
Lijing Wange0dd63e2015-05-31 16:25:16 -0700113 new FsWatcher(m_io, dir.string().c_str(),
114 std::bind(&TestFSWatcherFixture::onChange, this, std::ref(files), _1),
115 std::bind(&TestFSWatcherFixture::onDelete, this, std::ref(files), _1),
Yukai Tu73287f52017-02-06 15:46:40 -0800116 &app);
117
118 QTimer::singleShot(21000, &app, SLOT(quit()));
119 app.exec();
Lijing Wange0dd63e2015-05-31 16:25:16 -0700120 }
121
122public:
123 fs::path dir;
124 set<string> files;
125 int argc;
Yukai Tu73287f52017-02-06 15:46:40 -0800126 //fsWatcherApp* app;
Lijing Wange0dd63e2015-05-31 16:25:16 -0700127};
128
129BOOST_FIXTURE_TEST_SUITE(TestFsWatcher, TestFSWatcherFixture)
Zhenkai Zhud1756272013-02-01 17:02:18 -0800130
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800131BOOST_AUTO_TEST_CASE(TestFsWatcher)
Zhenkai Zhud1756272013-02-01 17:02:18 -0800132{
Lijing Wange0dd63e2015-05-31 16:25:16 -0700133 std::thread workThread(boost::bind(&TestFSWatcherFixture::run, this));
134 this->advanceClocks(std::chrono::seconds(2));
Zhenkai Zhud1756272013-02-01 17:02:18 -0800135
136 // ============ check create file detection ================
137 create_file(dir / "test.txt", "hello");
Lijing Wange0dd63e2015-05-31 16:25:16 -0700138 this->advanceClocks(std::chrono::seconds(2));
Zhenkai Zhud1756272013-02-01 17:02:18 -0800139 // test.txt
140 BOOST_CHECK_EQUAL(files.size(), 1);
141 BOOST_CHECK(files.find("test.txt") != files.end());
142
143 // =========== check create a bunch of files in sub dir =============
144 fs::path subdir = dir / "sub";
145 fs::create_directory(subdir);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800146 for (int i = 0; i < 10; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800147 string filename = boost::lexical_cast<string>(i);
148 create_file(subdir / filename.c_str(), boost::lexical_cast<string>(i));
149 }
Lijing Wange0dd63e2015-05-31 16:25:16 -0700150 this->advanceClocks(std::chrono::seconds(2));
Zhenkai Zhud1756272013-02-01 17:02:18 -0800151 // test.txt
152 // sub/0..9
153 BOOST_CHECK_EQUAL(files.size(), 11);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800154 for (int i = 0; i < 10; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800155 string filename = boost::lexical_cast<string>(i);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800156 BOOST_CHECK(files.find("sub/" + filename) != files.end());
Zhenkai Zhud1756272013-02-01 17:02:18 -0800157 }
158
159 // ============== check copy directory with files to two levels of sub dirs =================
160 fs::create_directory(dir / "sub1");
161 fs::path subdir1 = dir / "sub1" / "sub2";
162 fs::copy_directory(subdir, subdir1);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800163 for (int i = 0; i < 5; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800164 string filename = boost::lexical_cast<string>(i);
Lijing Wange0dd63e2015-05-31 16:25:16 -0700165 fs::copy(subdir / filename.c_str(), subdir1 / filename.c_str());
Zhenkai Zhud1756272013-02-01 17:02:18 -0800166 }
Lijing Wange0dd63e2015-05-31 16:25:16 -0700167 this->advanceClocks(std::chrono::seconds(2));
Zhenkai Zhud1756272013-02-01 17:02:18 -0800168 // test.txt
169 // sub/0..9
170 // sub1/sub2/0..4
171 BOOST_CHECK_EQUAL(files.size(), 16);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800172 for (int i = 0; i < 5; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800173 string filename = boost::lexical_cast<string>(i);
174 BOOST_CHECK(files.find("sub1/sub2/" + filename) != files.end());
175 }
176
177 // =============== check remove files =========================
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800178 for (int i = 0; i < 7; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800179 string filename = boost::lexical_cast<string>(i);
180 fs::remove(subdir / filename.c_str());
181 }
Lijing Wange0dd63e2015-05-31 16:25:16 -0700182 this->advanceClocks(std::chrono::seconds(2));
Zhenkai Zhud1756272013-02-01 17:02:18 -0800183 // test.txt
184 // sub/7..9
185 // sub1/sub2/0..4
186 BOOST_CHECK_EQUAL(files.size(), 9);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800187 for (int i = 0; i < 10; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800188 string filename = boost::lexical_cast<string>(i);
189 if (i < 7)
190 BOOST_CHECK(files.find("sub/" + filename) == files.end());
191 else
192 BOOST_CHECK(files.find("sub/" + filename) != files.end());
193 }
194
Lijing Wange0dd63e2015-05-31 16:25:16 -0700195 // =================== check remove files again, remove the whole dir this time
196 // ===================
Zhenkai Zhud1756272013-02-01 17:02:18 -0800197 // before remove check
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800198 for (int i = 0; i < 5; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800199 string filename = boost::lexical_cast<string>(i);
200 BOOST_CHECK(files.find("sub1/sub2/" + filename) != files.end());
201 }
202 fs::remove_all(subdir1);
Lijing Wange0dd63e2015-05-31 16:25:16 -0700203 this->advanceClocks(std::chrono::seconds(2));
Zhenkai Zhud1756272013-02-01 17:02:18 -0800204 BOOST_CHECK_EQUAL(files.size(), 4);
205 // test.txt
206 // sub/7..9
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800207 for (int i = 0; i < 5; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800208 string filename = boost::lexical_cast<string>(i);
209 BOOST_CHECK(files.find("sub1/sub2/" + filename) == files.end());
210 }
211
212 // =================== check rename files =======================
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800213 for (int i = 7; i < 10; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800214 string filename = boost::lexical_cast<string>(i);
215 fs::rename(subdir / filename.c_str(), dir / filename.c_str());
216 }
Lijing Wange0dd63e2015-05-31 16:25:16 -0700217 this->advanceClocks(std::chrono::seconds(2));
Zhenkai Zhud1756272013-02-01 17:02:18 -0800218 // test.txt
219 // 7
220 // 8
221 // 9
222 // sub
223 BOOST_CHECK_EQUAL(files.size(), 4);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800224 for (int i = 7; i < 10; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800225 string filename = boost::lexical_cast<string>(i);
226 BOOST_CHECK(files.find("sub/" + filename) == files.end());
227 BOOST_CHECK(files.find(filename) != files.end());
228 }
229
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800230 create_file(dir / "add-removal-check.txt", "add-removal-check");
Lijing Wange0dd63e2015-05-31 16:25:16 -0700231 this->advanceClocks(std::chrono::seconds(2));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800232 BOOST_CHECK(files.find("add-removal-check.txt") != files.end());
Zhenkai Zhud1756272013-02-01 17:02:18 -0800233
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800234 fs::remove(dir / "add-removal-check.txt");
Lijing Wange0dd63e2015-05-31 16:25:16 -0700235 this->advanceClocks(std::chrono::seconds(2));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800236 BOOST_CHECK(files.find("add-removal-check.txt") == files.end());
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800237
238 create_file(dir / "add-removal-check.txt", "add-removal-check");
Lijing Wange0dd63e2015-05-31 16:25:16 -0700239 this->advanceClocks(std::chrono::seconds(2));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800240 BOOST_CHECK(files.find("add-removal-check.txt") != files.end());
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800241
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800242 fs::remove(dir / "add-removal-check.txt");
Lijing Wange0dd63e2015-05-31 16:25:16 -0700243 this->advanceClocks(std::chrono::seconds(2));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800244 BOOST_CHECK(files.find("add-removal-check.txt") == files.end());
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800245
246 create_file(dir / "add-removal-check.txt", "add-removal-check");
Lijing Wange0dd63e2015-05-31 16:25:16 -0700247 this->advanceClocks(std::chrono::seconds(2));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800248 BOOST_CHECK(files.find("add-removal-check.txt") != files.end());
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800249
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800250 fs::remove(dir / "add-removal-check.txt");
Lijing Wange0dd63e2015-05-31 16:25:16 -0700251 this->advanceClocks(std::chrono::seconds(2));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800252 BOOST_CHECK(files.find("add-removal-check.txt") == files.end());
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800253
Yukai Tu73287f52017-02-06 15:46:40 -0800254 //emit app->stopApp();
Lijing Wange0dd63e2015-05-31 16:25:16 -0700255
256 workThread.join();
Zhenkai Zhud1756272013-02-01 17:02:18 -0800257}
258
259BOOST_AUTO_TEST_SUITE_END()
Lijing Wange0dd63e2015-05-31 16:25:16 -0700260
261} // namespace tests
262} // namespace chronoshare
263} // namespace ndn