blob: 22b1838d50da9c985047d1aa99af779e9c748b2d [file] [log] [blame]
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2016, Regents of the University of California.
4 *
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 */
Alexander Afanasyevf4cde4e2016-12-25 13:42:57 -080020#include "fs-watcher.hpp"
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080021#include <boost/bind.hpp>
Zhenkai Zhud1756272013-02-01 17:02:18 -080022#include <boost/filesystem.hpp>
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080023#include <boost/lexical_cast.hpp>
24#include <boost/make_shared.hpp>
Zhenkai Zhud1756272013-02-01 17:02:18 -080025#include <boost/test/unit_test.hpp>
26#include <boost/thread/thread.hpp>
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080027#include <QtGui>
Zhenkai Zhud1756272013-02-01 17:02:18 -080028#include <fstream>
29#include <set>
Zhenkai Zhud1756272013-02-01 17:02:18 -080030
31using namespace std;
32using namespace boost;
33namespace fs = boost::filesystem;
34
Alexander Afanasyeva3230632013-02-07 16:24:30 -080035BOOST_AUTO_TEST_SUITE(TestFsWatcher)
Zhenkai Zhud1756272013-02-01 17:02:18 -080036
37void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080038onChange(set<string>& files, const fs::path& file)
Zhenkai Zhud1756272013-02-01 17:02:18 -080039{
Yingdi Yua264b872013-07-10 18:07:23 -070040 cerr << "onChange called" << endl;
Zhenkai Zhud1756272013-02-01 17:02:18 -080041 files.insert(file.string());
42}
43
44void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080045onDelete(set<string>& files, const fs::path& file)
Zhenkai Zhud1756272013-02-01 17:02:18 -080046{
47 files.erase(file.string());
48}
49
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080050void
51create_file(const fs::path& ph, const std::string& contents)
Zhenkai Zhud1756272013-02-01 17:02:18 -080052{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080053 std::ofstream f(ph.string().c_str());
54 if (!f) {
Zhenkai Zhud1756272013-02-01 17:02:18 -080055 abort();
56 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080057 if (!contents.empty()) {
Zhenkai Zhud1756272013-02-01 17:02:18 -080058 f << contents;
59 }
60}
61
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080062void
63run(fs::path dir, FsWatcher::LocalFile_Change_Callback c, FsWatcher::LocalFile_Change_Callback d)
Zhenkai Zhud1756272013-02-01 17:02:18 -080064{
65 int x = 0;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080066 QCoreApplication app(x, 0);
67 FsWatcher watcher(dir.string().c_str(), c, d);
Zhenkai Zhud1756272013-02-01 17:02:18 -080068 app.exec();
69 sleep(100);
70}
71
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080072BOOST_AUTO_TEST_CASE(TestFsWatcher)
Zhenkai Zhud1756272013-02-01 17:02:18 -080073{
74 fs::path dir = fs::absolute(fs::path("TestFsWatcher"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080075 if (fs::exists(dir)) {
Zhenkai Zhud1756272013-02-01 17:02:18 -080076 fs::remove_all(dir);
77 }
78
79 fs::create_directory(dir);
80
81 set<string> files;
82
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080083 FsWatcher::LocalFile_Change_Callback fileChange = boost::bind(onChange, ref(files), _1);
Zhenkai Zhud1756272013-02-01 17:02:18 -080084 FsWatcher::LocalFile_Change_Callback fileDelete = boost::bind(onDelete, ref(files), _1);
85
86 thread workThread(run, dir, fileChange, fileDelete);
87 //FsWatcher watcher (dir.string().c_str(), fileChange, fileDelete);
88
89 // ============ check create file detection ================
90 create_file(dir / "test.txt", "hello");
91 // have to at least wait 0.5 seconds
Yingdi Yua264b872013-07-10 18:07:23 -070092 usleep(1000000);
Zhenkai Zhud1756272013-02-01 17:02:18 -080093 // test.txt
94 BOOST_CHECK_EQUAL(files.size(), 1);
95 BOOST_CHECK(files.find("test.txt") != files.end());
96
97 // =========== check create a bunch of files in sub dir =============
98 fs::path subdir = dir / "sub";
99 fs::create_directory(subdir);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800100 for (int i = 0; i < 10; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800101 string filename = boost::lexical_cast<string>(i);
102 create_file(subdir / filename.c_str(), boost::lexical_cast<string>(i));
103 }
104 // have to at least wait 0.5 * 2 seconds
105 usleep(1100000);
106 // test.txt
107 // sub/0..9
108 BOOST_CHECK_EQUAL(files.size(), 11);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800109 for (int i = 0; i < 10; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800110 string filename = boost::lexical_cast<string>(i);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800111 BOOST_CHECK(files.find("sub/" + filename) != files.end());
Zhenkai Zhud1756272013-02-01 17:02:18 -0800112 }
113
114 // ============== check copy directory with files to two levels of sub dirs =================
115 fs::create_directory(dir / "sub1");
116 fs::path subdir1 = dir / "sub1" / "sub2";
117 fs::copy_directory(subdir, subdir1);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800118 for (int i = 0; i < 5; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800119 string filename = boost::lexical_cast<string>(i);
120 fs::copy_file(subdir / filename.c_str(), subdir1 / filename.c_str());
121 }
122 // have to at least wait 0.5 * 2 seconds
123 usleep(1100000);
124 // test.txt
125 // sub/0..9
126 // sub1/sub2/0..4
127 BOOST_CHECK_EQUAL(files.size(), 16);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800128 for (int i = 0; i < 5; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800129 string filename = boost::lexical_cast<string>(i);
130 BOOST_CHECK(files.find("sub1/sub2/" + filename) != files.end());
131 }
132
133 // =============== check remove files =========================
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800134 for (int i = 0; i < 7; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800135 string filename = boost::lexical_cast<string>(i);
136 fs::remove(subdir / filename.c_str());
137 }
138 usleep(1100000);
139 // test.txt
140 // sub/7..9
141 // sub1/sub2/0..4
142 BOOST_CHECK_EQUAL(files.size(), 9);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800143 for (int i = 0; i < 10; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800144 string filename = boost::lexical_cast<string>(i);
145 if (i < 7)
146 BOOST_CHECK(files.find("sub/" + filename) == files.end());
147 else
148 BOOST_CHECK(files.find("sub/" + filename) != files.end());
149 }
150
151 // =================== check remove files again, remove the whole dir this time ===================
152 // before remove check
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800153 for (int i = 0; i < 5; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800154 string filename = boost::lexical_cast<string>(i);
155 BOOST_CHECK(files.find("sub1/sub2/" + filename) != files.end());
156 }
157 fs::remove_all(subdir1);
158 usleep(1100000);
159 BOOST_CHECK_EQUAL(files.size(), 4);
160 // test.txt
161 // sub/7..9
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800162 for (int i = 0; i < 5; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800163 string filename = boost::lexical_cast<string>(i);
164 BOOST_CHECK(files.find("sub1/sub2/" + filename) == files.end());
165 }
166
167 // =================== check rename files =======================
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800168 for (int i = 7; i < 10; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800169 string filename = boost::lexical_cast<string>(i);
170 fs::rename(subdir / filename.c_str(), dir / filename.c_str());
171 }
172 usleep(1100000);
173 // test.txt
174 // 7
175 // 8
176 // 9
177 // sub
178 BOOST_CHECK_EQUAL(files.size(), 4);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800179 for (int i = 7; i < 10; i++) {
Zhenkai Zhud1756272013-02-01 17:02:18 -0800180 string filename = boost::lexical_cast<string>(i);
181 BOOST_CHECK(files.find("sub/" + filename) == files.end());
182 BOOST_CHECK(files.find(filename) != files.end());
183 }
184
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800185 create_file(dir / "add-removal-check.txt", "add-removal-check");
186 usleep(1200000);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800187 BOOST_CHECK(files.find("add-removal-check.txt") != files.end());
Zhenkai Zhud1756272013-02-01 17:02:18 -0800188
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800189 fs::remove(dir / "add-removal-check.txt");
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800190 usleep(1200000);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800191 BOOST_CHECK(files.find("add-removal-check.txt") == files.end());
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800192
193 create_file(dir / "add-removal-check.txt", "add-removal-check");
194 usleep(1200000);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800195 BOOST_CHECK(files.find("add-removal-check.txt") != files.end());
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800196
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800197 fs::remove(dir / "add-removal-check.txt");
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800198 usleep(1200000);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800199 BOOST_CHECK(files.find("add-removal-check.txt") == files.end());
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800200
201 create_file(dir / "add-removal-check.txt", "add-removal-check");
202 usleep(1200000);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800203 BOOST_CHECK(files.find("add-removal-check.txt") != files.end());
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800204
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800205 fs::remove(dir / "add-removal-check.txt");
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800206 usleep(1200000);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800207 BOOST_CHECK(files.find("add-removal-check.txt") == files.end());
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800208
209 // cleanup
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800210 if (fs::exists(dir)) {
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800211 fs::remove_all(dir);
212 }
Zhenkai Zhud1756272013-02-01 17:02:18 -0800213}
214
215BOOST_AUTO_TEST_SUITE_END()