blob: e74c06a28a991571c179afe27581ca3810d61ada [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 */
20
Alexander Afanasyevf4cde4e2016-12-25 13:42:57 -080021#include "fs-watcher.hpp"
Zhenkai Zhud1756272013-02-01 17:02:18 -080022#include <boost/make_shared.hpp>
23#include <boost/filesystem.hpp>
24#include <boost/test/unit_test.hpp>
25#include <boost/thread/thread.hpp>
26#include <boost/bind.hpp>
27#include <boost/lexical_cast.hpp>
28#include <fstream>
29#include <set>
30#include <QtGui>
Yingdi Yua264b872013-07-10 18:07:23 -070031#include <iostream>
Zhenkai Zhud1756272013-02-01 17:02:18 -080032
33using namespace std;
34using namespace boost;
35namespace fs = boost::filesystem;
36
Alexander Afanasyeva3230632013-02-07 16:24:30 -080037BOOST_AUTO_TEST_SUITE(TestFsWatcher)
Zhenkai Zhud1756272013-02-01 17:02:18 -080038
39void
40onChange(set<string> &files, const fs::path &file)
41{
Yingdi Yua264b872013-07-10 18:07:23 -070042 cerr << "onChange called" << endl;
Zhenkai Zhud1756272013-02-01 17:02:18 -080043 files.insert(file.string());
44}
45
46void
47onDelete(set<string> &files, const fs::path &file)
48{
49 files.erase(file.string());
50}
51
52void create_file( const fs::path & ph, const std::string & contents )
53{
54 std::ofstream f( ph.string().c_str() );
55 if ( !f )
56 {
57 abort();
58 }
59 if ( !contents.empty() )
60 {
61 f << contents;
62 }
63}
64
65void run(fs::path dir, FsWatcher::LocalFile_Change_Callback c, FsWatcher::LocalFile_Change_Callback d)
66{
67 int x = 0;
68 QCoreApplication app (x, 0);
69 FsWatcher watcher (dir.string().c_str(), c, d);
70 app.exec();
71 sleep(100);
72}
73
74BOOST_AUTO_TEST_CASE (TestFsWatcher)
75{
76 fs::path dir = fs::absolute(fs::path("TestFsWatcher"));
77 if (fs::exists(dir))
78 {
79 fs::remove_all(dir);
80 }
81
82 fs::create_directory(dir);
83
84 set<string> files;
85
86 FsWatcher::LocalFile_Change_Callback fileChange = boost::bind(onChange,ref(files), _1);
87 FsWatcher::LocalFile_Change_Callback fileDelete = boost::bind(onDelete, ref(files), _1);
88
89 thread workThread(run, dir, fileChange, fileDelete);
90 //FsWatcher watcher (dir.string().c_str(), fileChange, fileDelete);
91
92 // ============ check create file detection ================
93 create_file(dir / "test.txt", "hello");
94 // have to at least wait 0.5 seconds
Yingdi Yua264b872013-07-10 18:07:23 -070095 usleep(1000000);
Zhenkai Zhud1756272013-02-01 17:02:18 -080096 // test.txt
97 BOOST_CHECK_EQUAL(files.size(), 1);
98 BOOST_CHECK(files.find("test.txt") != files.end());
99
100 // =========== check create a bunch of files in sub dir =============
101 fs::path subdir = dir / "sub";
102 fs::create_directory(subdir);
103 for (int i = 0; i < 10; i++)
104 {
105 string filename = boost::lexical_cast<string>(i);
106 create_file(subdir / filename.c_str(), boost::lexical_cast<string>(i));
107 }
108 // have to at least wait 0.5 * 2 seconds
109 usleep(1100000);
110 // test.txt
111 // sub/0..9
112 BOOST_CHECK_EQUAL(files.size(), 11);
113 for (int i = 0; i < 10; i++)
114 {
115 string filename = boost::lexical_cast<string>(i);
116 BOOST_CHECK(files.find("sub/" +filename) != files.end());
117 }
118
119 // ============== check copy directory with files to two levels of sub dirs =================
120 fs::create_directory(dir / "sub1");
121 fs::path subdir1 = dir / "sub1" / "sub2";
122 fs::copy_directory(subdir, subdir1);
123 for (int i = 0; i < 5; i++)
124 {
125 string filename = boost::lexical_cast<string>(i);
126 fs::copy_file(subdir / filename.c_str(), subdir1 / filename.c_str());
127 }
128 // have to at least wait 0.5 * 2 seconds
129 usleep(1100000);
130 // test.txt
131 // sub/0..9
132 // sub1/sub2/0..4
133 BOOST_CHECK_EQUAL(files.size(), 16);
134 for (int i = 0; i < 5; i++)
135 {
136 string filename = boost::lexical_cast<string>(i);
137 BOOST_CHECK(files.find("sub1/sub2/" + filename) != files.end());
138 }
139
140 // =============== check remove files =========================
141 for (int i = 0; i < 7; i++)
142 {
143 string filename = boost::lexical_cast<string>(i);
144 fs::remove(subdir / filename.c_str());
145 }
146 usleep(1100000);
147 // test.txt
148 // sub/7..9
149 // sub1/sub2/0..4
150 BOOST_CHECK_EQUAL(files.size(), 9);
151 for (int i = 0; i < 10; i++)
152 {
153 string filename = boost::lexical_cast<string>(i);
154 if (i < 7)
155 BOOST_CHECK(files.find("sub/" + filename) == files.end());
156 else
157 BOOST_CHECK(files.find("sub/" + filename) != files.end());
158 }
159
160 // =================== check remove files again, remove the whole dir this time ===================
161 // before remove check
162 for (int i = 0; i < 5; i++)
163 {
164 string filename = boost::lexical_cast<string>(i);
165 BOOST_CHECK(files.find("sub1/sub2/" + filename) != files.end());
166 }
167 fs::remove_all(subdir1);
168 usleep(1100000);
169 BOOST_CHECK_EQUAL(files.size(), 4);
170 // test.txt
171 // sub/7..9
172 for (int i = 0; i < 5; i++)
173 {
174 string filename = boost::lexical_cast<string>(i);
175 BOOST_CHECK(files.find("sub1/sub2/" + filename) == files.end());
176 }
177
178 // =================== check rename files =======================
179 for (int i = 7; i < 10; i++)
180 {
181 string filename = boost::lexical_cast<string>(i);
182 fs::rename(subdir / filename.c_str(), dir / filename.c_str());
183 }
184 usleep(1100000);
185 // test.txt
186 // 7
187 // 8
188 // 9
189 // sub
190 BOOST_CHECK_EQUAL(files.size(), 4);
191 for (int i = 7; i < 10; i++)
192 {
193 string filename = boost::lexical_cast<string>(i);
194 BOOST_CHECK(files.find("sub/" + filename) == files.end());
195 BOOST_CHECK(files.find(filename) != files.end());
196 }
197
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800198 create_file(dir / "add-removal-check.txt", "add-removal-check");
199 usleep(1200000);
200 BOOST_CHECK (files.find("add-removal-check.txt") != files.end());
Zhenkai Zhud1756272013-02-01 17:02:18 -0800201
Alexander Afanasyeva3230632013-02-07 16:24:30 -0800202 fs::remove (dir / "add-removal-check.txt");
203 usleep(1200000);
204 BOOST_CHECK (files.find("add-removal-check.txt") == files.end());
205
206 create_file(dir / "add-removal-check.txt", "add-removal-check");
207 usleep(1200000);
208 BOOST_CHECK (files.find("add-removal-check.txt") != files.end());
209
210 fs::remove (dir / "add-removal-check.txt");
211 usleep(1200000);
212 BOOST_CHECK (files.find("add-removal-check.txt") == files.end());
213
214 create_file(dir / "add-removal-check.txt", "add-removal-check");
215 usleep(1200000);
216 BOOST_CHECK (files.find("add-removal-check.txt") != files.end());
217
218 fs::remove (dir / "add-removal-check.txt");
219 usleep(1200000);
220 BOOST_CHECK (files.find("add-removal-check.txt") == files.end());
221
222 // cleanup
223 if (fs::exists(dir))
224 {
225 fs::remove_all(dir);
226 }
Zhenkai Zhud1756272013-02-01 17:02:18 -0800227}
228
229BOOST_AUTO_TEST_SUITE_END()