1 #include "config.h"
2 
3 #ifdef HAVE_UNISTD_H
4 #include <unistd.h>
5 #endif
6 
7 #include <iostream>
8 #include <string>
9 #include <fstream>
10 #include <iomanip>
11 #include <string>
12 #include <cassert>
13 #include <algorithm>
14 
15 #include "asserts.h"
16 #include "error.h"
17 #include "fs.h"
18 #include "rconfig.h"
19 #include "logger.h"
20 #include "vaulter.h"
21 #include "archiver.h"
22 #include "cataloger.h"
23 #include "reporter.h"
24 #include "test-fs-cwd.h"
25 
26 #define ERR_OUT(e) std::cerr << e
27 // #define ERR_OUT(e)
28 
make_dir(const std::string & path)29 bool make_dir(const std::string& path)
30 {
31 	bool thrown;
32 	bool value;
33 
34 	thrown = false;
35 	try {
36 		mk_dir(path);
37 	}
38 	catch(...) {
39 		thrown = true;
40 	}
41 
42 	value = (thrown == false);
43 
44 	return(value);
45 }
46 
setup(void)47 void setup(void)
48 {
49 	std::ofstream out;
50 
51 	assert(make_dir("./test-rvm.dir"));
52 	assert(make_dir("./test-rvm.dir/vault"));
53 	assert(make_dir("./test-rvm.dir/log.dir"));
54 	assert(make_dir("./test-rvm.dir/catalog.dir"));
55 
56 	out.open("./test-rvm.dir/file.conf");
57 	assert(out.is_open());
58 	out << "link-catalog-dir ./test-rvm.dir/catalog.dir" << std::endl;
59 	out << "log-dir ./test-rvm.dir/log.dir" << std::endl;
60 	out << "logging-level rsync" << std::endl;
61 	out << "rsync-local-path " << LOCAL_RSYNC << std::endl;
62 	out << "rsync-parallel 1" << std::endl;
63 	out << "timestamp-resolution second" << std::endl;
64 	out << "vault ./test-rvm.dir/vault" << std::endl;
65 	out << "vault-overflow-behavior quit" << std::endl;
66 	out << "vault-overflow-blocks 0" << std::endl;
67 	out << "vault-overflow-inodes 0" << std::endl;
68 	out << "vault-selection-behavior round-robin" << std::endl;
69 	out << "<job>" << std::endl;
70 	out << "	jobname test-job" << std::endl;
71 	out << "	archive-path jobname/permutation" << std::endl;
72 	out << "	path " << check_cwd << "/" << std::endl;
73 	out << "	rsync-connection-type local" << std::endl;
74 	out << "	rsync-hardlink true" << std::endl;
75 	out << "	rsync-multi-hardlink true" << std::endl;
76 	out << "	<rsync-options>" << std::endl;
77 	out << "		-a -v --progress --stats" << std::endl;
78 	out << "		--exclude '/.svn/'" << std::endl;
79 	out << "		--exclude '/.deps/'" << std::endl;
80 	out << "		--exclude '/autom4te.cache/'" << std::endl;
81 	out << "		--exclude '/test-rvm.dir/'" << std::endl;
82 	out << "	</rsync-options>" << std::endl;
83 	out << "	rsync-retry-count 3" << std::endl;
84 	out << "</job>" << std::endl;
85 	out.close();
86 }
87 
cleanup(void)88 void cleanup(void)
89 {
90 	assert(system("rm -fr ./test-rvm.dir") == 0);
91 }
92 
test_inodes(const std::string & path1,const std::string & path2,const std::string & file)93 bool test_inodes(
94 	const std::string& path1,
95 	const std::string& path2,
96 	const std::string& file
97 	)
98 {
99 	estring p1, p2;
100 	filestatus f1, f2;
101 	bool r;
102 
103 	p1 = path1;
104 	p1 += "/";
105 	p1 += file;
106 	p1 = reform_path(p1);
107 	f1.path(p1);
108 
109 	p2 = path2;
110 	p2 += "/";
111 	p2 += file;
112 	p2 = reform_path(p2);
113 	f2.path(p2);
114 
115 	r = (f1.inode() == f2.inode());
116 
117 	return(r);
118 }
119 
test_rvm(void)120 void test_rvm(void)
121 {
122 	std::string local_rsync;
123 	estring adir[4];
124 	int adirc = 0;
125 
126 	local_rsync = LOCAL_RSYNC;
127 	if (local_rsync.size() == 0) {
128 		char const * text[] = {
129 			"",
130 			"NOTICE: Skipping this test",
131 			"",
132 			"This test cannot be run because no local rsync binary was found during",
133 			"configuration.  This also means that RVM will be compiled with no",
134 			"default value for the rsync-local-path command.",
135 			"",
136 			"To change this, run the configure script with --with-rsync=<path>,",
137 			"where <path> is the absolute path to the rsync binary.",
138 			"",
139 			0
140 		};
141 		int c;
142 
143 		for (c = 0; text[c] != 0; ++c) {
144 			std::cerr << text[c] << std::endl;
145 		}
146 		return;
147 	}
148 
149 	{
150 		char const * argv[256] = { 0 };
151 		int argc = 0;
152 		bool thrown = false;
153 		subdirectory subdir;
154 		estring dir;
155 
156 		argv[argc++] = "<program>";
157 		argv[argc++] = "--archive";
158 
159 		cataloger.clear();
160 		archiver.clear();
161 		reporter.clear();
162 		vaulter.clear();
163 		logger.clear();
164 		config.clear();
165 
166 		config.default_file("./test-rvm.dir/file.conf");
167 		try {
168 			timer t;
169 
170 			t.start();
171 
172 			config.init(argc, argv);
173 			logger.init();
174 			vaulter.init();
175 			reporter.init();
176 			archiver.init();
177 			archiver.archive();
178 			cataloger.init();
179 			cataloger.catalog();
180 
181 			t.stop();
182 			reporter.set_total_time(t);
183 
184 			// reporter.print_report();
185 			reporter.file_report();
186 			logger.clear();
187 
188 			// std::cerr << "vaulter.vault() == " << vaulter.vault() << std::endl;
189 			assert(vaulter.vault() == "./test-rvm.dir/vault");
190 
191 			dir = vaulter.vault();
192 			dir += "/";
193 			dir += config.timestamp().str();
194 			dir += "/";
195 			dir += config.jobs()[0].generate_archive_path(check_cwd);
196 			adir[adirc] = dir;
197 			// std::cerr << "adir[" << adirc << "] = " << adir[adirc] << std::endl;
198 			adirc++;
199 
200 			// std::cout << "dir = " << dir << std::endl;
201 
202 			assert(
203 				exists(
204 					config.log_dir()
205 					+ static_cast<std::string>("/")
206 					+ config.timestamp().str()
207 					+ static_cast<std::string>(".log")
208 					)
209 				);
210 			assert(
211 				exists(
212 					config.log_dir()
213 					+ static_cast<std::string>("/")
214 					+ config.timestamp().str()
215 					+ static_cast<std::string>(".report")
216 					)
217 				);
218 
219 			subdir.path(dir);
220 			assert(find(subdir.begin(), subdir.end(), "AUTHORS") != subdir.end());
221 			assert(find(subdir.begin(), subdir.end(), "COPYING") != subdir.end());
222 			assert(find(subdir.begin(), subdir.end(), "INSTALL") != subdir.end());
223 			assert(find(subdir.begin(), subdir.end(), "Makefile") != subdir.end());
224 			assert(find(subdir.begin(), subdir.end(), "Makefile.in") != subdir.end());
225 			assert(find(subdir.begin(), subdir.end(), "README") != subdir.end());
226 			assert(find(subdir.begin(), subdir.end(), "archiver.cc") != subdir.end());
227 			assert(find(subdir.begin(), subdir.end(), "archiver.h") != subdir.end());
228 			assert(find(subdir.begin(), subdir.end(), "config.h") != subdir.end());
229 			assert(find(subdir.begin(), subdir.end(), "config.h.in") != subdir.end());
230 			assert(find(subdir.begin(), subdir.end(), "configure") != subdir.end());
231 			assert(find(subdir.begin(), subdir.end(), "error.cc") != subdir.end());
232 			assert(find(subdir.begin(), subdir.end(), "error.h") != subdir.end());
233 			assert(find(subdir.begin(), subdir.end(), "estring.cc") != subdir.end());
234 			assert(find(subdir.begin(), subdir.end(), "estring.h") != subdir.end());
235 			assert(find(subdir.begin(), subdir.end(), "exec.cc") != subdir.end());
236 			assert(find(subdir.begin(), subdir.end(), "exec.h") != subdir.end());
237 			assert(find(subdir.begin(), subdir.end(), "fs.cc") != subdir.end());
238 			assert(find(subdir.begin(), subdir.end(), "fs.h") != subdir.end());
239 			assert(find(subdir.begin(), subdir.end(), "help.cc") != subdir.end());
240 			assert(find(subdir.begin(), subdir.end(), "help.h") != subdir.end());
241 			assert(find(subdir.begin(), subdir.end(), "logger.cc") != subdir.end());
242 			assert(find(subdir.begin(), subdir.end(), "logger.h") != subdir.end());
243 			assert(find(subdir.begin(), subdir.end(), "make-test-fs-cc") != subdir.end());
244 			assert(find(subdir.begin(), subdir.end(), "rconfig.cc") != subdir.end());
245 			assert(find(subdir.begin(), subdir.end(), "rconfig.h") != subdir.end());
246 			assert(find(subdir.begin(), subdir.end(), "rmath.h") != subdir.end());
247 			assert(find(subdir.begin(), subdir.end(), "rvm.cc") != subdir.end());
248 			assert(find(subdir.begin(), subdir.end(), "rvm.1") != subdir.end());
249 			assert(find(subdir.begin(), subdir.end(), "rvm.1.in") != subdir.end());
250 			assert(find(subdir.begin(), subdir.end(), "test-rvm-001.cc") != subdir.end());
251 			assert(find(subdir.begin(), subdir.end(), "test-error.cc") != subdir.end());
252 			assert(find(subdir.begin(), subdir.end(), "test-estring.cc") != subdir.end());
253 			assert(find(subdir.begin(), subdir.end(), "test-exec.cc") != subdir.end());
254 			assert(find(subdir.begin(), subdir.end(), "test-fs-cwd.cc") != subdir.end());
255 			assert(find(subdir.begin(), subdir.end(), "test-fs.cc") != subdir.end());
256 			// assert(find(subdir.begin(), subdir.end(), "test-job.cc") != subdir.end());
257 			assert(find(subdir.begin(), subdir.end(), "test-logger.cc") != subdir.end());
258 			// assert(find(subdir.begin(), subdir.end(), "test-rconfig.cc") != subdir.end());
259 			assert(find(subdir.begin(), subdir.end(), "test-rmath.cc") != subdir.end());
260 			assert(find(subdir.begin(), subdir.end(), "test-strfmt.cc") != subdir.end());
261 			assert(find(subdir.begin(), subdir.end(), "test-timer.cc") != subdir.end());
262 			assert(find(subdir.begin(), subdir.end(), "test-tstamp.cc") != subdir.end());
263 			assert(find(subdir.begin(), subdir.end(), "test-types.cc") != subdir.end());
264 			assert(find(subdir.begin(), subdir.end(), "timer.cc") != subdir.end());
265 			assert(find(subdir.begin(), subdir.end(), "timer.h") != subdir.end());
266 			assert(find(subdir.begin(), subdir.end(), "tstamp.cc") != subdir.end());
267 			assert(find(subdir.begin(), subdir.end(), "tstamp.h") != subdir.end());
268 			assert(find(subdir.begin(), subdir.end(), "types.h") != subdir.end());
269 			assert(find(subdir.begin(), subdir.end(), "vaulter.cc") != subdir.end());
270 			assert(find(subdir.begin(), subdir.end(), "vaulter.h") != subdir.end());
271 		}
272 		catch(error e) {
273 			ERR_OUT(e);
274 			thrown = true;
275 		}
276 		catch(...) {
277 			ERR_OUT(err_unknown);
278 			assert(0);
279 		}
280 		assert(!thrown);
281 	}
282 
283 	sleep(2);
284 
285 	{
286 		char const * argv[256] = { 0 };
287 		int argc = 0;
288 		bool thrown = false;
289 		subdirectory subdir;
290 		estring dir;
291 
292 		argv[argc++] = "<program>";
293 		argv[argc++] = "--archive";
294 
295 		cataloger.clear();
296 		archiver.clear();
297 		reporter.clear();
298 		vaulter.clear();
299 		logger.clear();
300 		config.clear();
301 
302 		config.default_file("./test-rvm.dir/file.conf");
303 		try {
304 			timer t;
305 
306 			t.start();
307 
308 			config.init(argc, argv);
309 			logger.init();
310 			vaulter.init();
311 			reporter.init();
312 			archiver.init();
313 			archiver.archive();
314 			estring path;
315 			filestatus fstat1, fstat2;
316 			cataloger.init();
317 			cataloger.catalog();
318 
319 			t.stop();
320 			reporter.set_total_time(t);
321 
322 			// reporter.print_report();
323 			reporter.file_report();
324 			logger.clear();
325 
326 			// std::cerr << "vaulter.vault() == " << vaulter.vault() << std::endl;
327 			assert(vaulter.vault() == "./test-rvm.dir/vault");
328 
329 			dir = vaulter.vault();
330 			dir += "/";
331 			dir += config.timestamp().str();
332 			dir += "/";
333 			dir += config.jobs()[0].generate_archive_path(check_cwd);
334 			adir[adirc] = dir;
335 			// std::cerr << "adir[" << adirc << "] = " << adir[adirc] << std::endl;
336 			adirc++;
337 
338 			// std::cout << "dir = " << dir << std::endl;
339 
340 			subdir.path(dir);
341 			if (subdir.size() == 0) {
342 				std::string filename;
343 				std::string line;
344 				std::ifstream in;
345 				bool found_usage_error = false;
346 				char line_cstr[2048] = { 0 };
347 				int c;
348 
349 				filename = "./test-rvm.dir/log.dir/";
350 				filename += config.timestamp().str();
351 				filename += ".log";
352 				in.open(filename.c_str());
353 				assert(in.is_open());
354 				while (in.getline(line_cstr,2048)) {
355 					line = line_cstr;
356 					if (line.find("Rsync exit code: [1]") != std::string::npos)
357 						found_usage_error = true;
358 					for (c = 0; c < 2048; line_cstr[c++] = 0);
359 				}
360 				in.close();
361 
362 				if (found_usage_error) {
363 					std::cerr
364 						<< "*** NOTICE: One test has failed, the test that uses rsync with"
365 						<< std::endl
366 						<< "            the --hard-links and --link-dest command line"
367 						<< std::endl
368 						<< "            options.  Rsync reported a syntax or usage error,"
369 						<< std::endl
370 						<< "            which may indicate that this version of rsync is"
371 						<< std::endl
372 						<< "            old enough to not have these options."
373 						<< std::endl
374 						<< std::endl
375 						<< "            In order to be able to hard-link files that have"
376 						<< std::endl
377 						<< "            not changed from one archive to the next, you"
378 						<< std::endl
379 						<< "            will have to upgrade rsync."
380 						<< std::endl
381 						;
382 				}
383 				assert(found_usage_error);
384 			}
385 			else {
386 				assert(find(subdir.begin(), subdir.end(), "AUTHORS") != subdir.end());
387 				assert(find(subdir.begin(), subdir.end(), "COPYING") != subdir.end());
388 				assert(find(subdir.begin(), subdir.end(), "INSTALL") != subdir.end());
389 				assert(find(subdir.begin(), subdir.end(), "Makefile") != subdir.end());
390 				assert(find(subdir.begin(), subdir.end(), "Makefile.in") != subdir.end());
391 				assert(find(subdir.begin(), subdir.end(), "README") != subdir.end());
392 				assert(find(subdir.begin(), subdir.end(), "archiver.cc") != subdir.end());
393 				assert(find(subdir.begin(), subdir.end(), "archiver.h") != subdir.end());
394 				assert(find(subdir.begin(), subdir.end(), "config.h") != subdir.end());
395 				assert(find(subdir.begin(), subdir.end(), "config.h.in") != subdir.end());
396 				assert(find(subdir.begin(), subdir.end(), "configure") != subdir.end());
397 				assert(find(subdir.begin(), subdir.end(), "error.cc") != subdir.end());
398 				assert(find(subdir.begin(), subdir.end(), "error.h") != subdir.end());
399 				assert(find(subdir.begin(), subdir.end(), "estring.cc") != subdir.end());
400 				assert(find(subdir.begin(), subdir.end(), "estring.h") != subdir.end());
401 				assert(find(subdir.begin(), subdir.end(), "exec.cc") != subdir.end());
402 				assert(find(subdir.begin(), subdir.end(), "exec.h") != subdir.end());
403 				assert(find(subdir.begin(), subdir.end(), "fs.cc") != subdir.end());
404 				assert(find(subdir.begin(), subdir.end(), "fs.h") != subdir.end());
405 				assert(find(subdir.begin(), subdir.end(), "help.cc") != subdir.end());
406 				assert(find(subdir.begin(), subdir.end(), "help.h") != subdir.end());
407 				assert(find(subdir.begin(), subdir.end(), "logger.cc") != subdir.end());
408 				assert(find(subdir.begin(), subdir.end(), "logger.h") != subdir.end());
409 				assert(find(subdir.begin(), subdir.end(), "make-test-fs-cc") != subdir.end());
410 				assert(find(subdir.begin(), subdir.end(), "rconfig.cc") != subdir.end());
411 				assert(find(subdir.begin(), subdir.end(), "rconfig.h") != subdir.end());
412 				assert(find(subdir.begin(), subdir.end(), "rmath.h") != subdir.end());
413 				assert(find(subdir.begin(), subdir.end(), "rvm.cc") != subdir.end());
414 				assert(find(subdir.begin(), subdir.end(), "rvm.1") != subdir.end());
415 				assert(find(subdir.begin(), subdir.end(), "rvm.1.in") != subdir.end());
416 				assert(find(subdir.begin(), subdir.end(), "test-rvm-001.cc") != subdir.end());
417 				assert(find(subdir.begin(), subdir.end(), "test-error.cc") != subdir.end());
418 				assert(find(subdir.begin(), subdir.end(), "test-estring.cc") != subdir.end());
419 				assert(find(subdir.begin(), subdir.end(), "test-exec.cc") != subdir.end());
420 				assert(find(subdir.begin(), subdir.end(), "test-fs-cwd.cc") != subdir.end());
421 				assert(find(subdir.begin(), subdir.end(), "test-fs.cc") != subdir.end());
422 				// assert(find(subdir.begin(), subdir.end(), "test-job.cc") != subdir.end());
423 				assert(find(subdir.begin(), subdir.end(), "test-logger.cc") != subdir.end());
424 				// assert(find(subdir.begin(), subdir.end(), "test-rconfig.cc") != subdir.end());
425 				assert(find(subdir.begin(), subdir.end(), "test-rmath.cc") != subdir.end());
426 				assert(find(subdir.begin(), subdir.end(), "test-strfmt.cc") != subdir.end());
427 				assert(find(subdir.begin(), subdir.end(), "test-timer.cc") != subdir.end());
428 				assert(find(subdir.begin(), subdir.end(), "test-tstamp.cc") != subdir.end());
429 				assert(find(subdir.begin(), subdir.end(), "test-types.cc") != subdir.end());
430 				assert(find(subdir.begin(), subdir.end(), "timer.cc") != subdir.end());
431 				assert(find(subdir.begin(), subdir.end(), "timer.h") != subdir.end());
432 				assert(find(subdir.begin(), subdir.end(), "tstamp.cc") != subdir.end());
433 				assert(find(subdir.begin(), subdir.end(), "tstamp.h") != subdir.end());
434 				assert(find(subdir.begin(), subdir.end(), "types.h") != subdir.end());
435 				assert(find(subdir.begin(), subdir.end(), "vaulter.cc") != subdir.end());
436 				assert(find(subdir.begin(), subdir.end(), "vaulter.h") != subdir.end());
437 
438 				assert(test_inodes(adir[0], adir[1], "AUTHORS"));
439 			}
440 
441 			// TODO: Check output
442 			assert(
443 				exists(
444 					static_cast<std::string>("./test-rvm.dir/catalog.dir/")
445 					+ config.timestamp().str()
446 				)
447 			);
448 		}
449 		catch(error e) {
450 			ERR_OUT(e);
451 			thrown = true;
452 		}
453 		catch(...) {
454 			ERR_OUT(err_unknown);
455 			assert(0);
456 		}
457 		assert(!thrown);
458 	}
459 
460 	sleep(2);
461 
462 	{
463 		char const * argv[256] = { 0 };
464 		int argc = 0;
465 		bool thrown = false;
466 		subdirectory subdir;
467 		estring dir;
468 
469 		argv[argc++] = "<program>";
470 		argv[argc++] = "--archive";
471 
472 		cataloger.clear();
473 		archiver.clear();
474 		reporter.clear();
475 		vaulter.clear();
476 		logger.clear();
477 		config.clear();
478 
479 		estring file;
480 		file = adir[1].c_str();
481 		file += "/";
482 		file += "COPYING";
483 		unlink(file.c_str());
484 
485 		config.default_file("./test-rvm.dir/file.conf");
486 		try {
487 			timer t;
488 
489 			t.start();
490 
491 			config.init(argc, argv);
492 			logger.init();
493 			vaulter.init();
494 			reporter.init();
495 			archiver.init();
496 			archiver.archive();
497 			estring path;
498 			filestatus fstat1, fstat2;
499 			cataloger.init();
500 			cataloger.catalog();
501 
502 			t.stop();
503 			reporter.set_total_time(t);
504 
505 			// reporter.print_report();
506 			reporter.file_report();
507 			logger.clear();
508 
509 			// std::cerr << "vaulter.vault() == " << vaulter.vault() << std::endl;
510 			assert(vaulter.vault() == "./test-rvm.dir/vault");
511 
512 			dir = vaulter.vault();
513 			dir += "/";
514 			dir += config.timestamp().str();
515 			dir += "/";
516 			dir += config.jobs()[0].generate_archive_path(check_cwd);
517 			adir[adirc] = dir;
518 			// std::cerr << "adir[" << adirc << "] = " << adir[adirc] << std::endl;
519 			adirc++;
520 
521 			// std::cout << "dir = " << dir << std::endl;
522 
523 			subdir.path(dir);
524 			if (subdir.size() == 0) {
525 				std::string filename;
526 				std::string line;
527 				std::ifstream in;
528 				bool found_usage_error = false;
529 				char line_cstr[2048] = { 0 };
530 				int c;
531 
532 				filename = "./test-rvm.dir/log.dir/";
533 				filename += config.timestamp().str();
534 				filename += ".log";
535 				in.open(filename.c_str());
536 				assert(in.is_open());
537 				while (in.getline(line_cstr,2048)) {
538 					line = line_cstr;
539 					if (line.find("Rsync exit code: [1]") != std::string::npos)
540 						found_usage_error = true;
541 					for (c = 0; c < 2048; line_cstr[c++] = 0);
542 				}
543 				in.close();
544 
545 				if (found_usage_error) {
546 					std::cerr
547 						<< "*** NOTICE: One test has failed, the test that uses rsync with"
548 						<< std::endl
549 						<< "            the --hard-links and --link-dest command line"
550 						<< std::endl
551 						<< "            options.  Rsync reported a syntax or usage error,"
552 						<< std::endl
553 						<< "            which may indicate that this version of rsync is"
554 						<< std::endl
555 						<< "            old enough to not have these options."
556 						<< std::endl
557 						<< std::endl
558 						<< "            In order to be able to hard-link files that have"
559 						<< std::endl
560 						<< "            not changed from one archive to the next, you"
561 						<< std::endl
562 						<< "            will have to upgrade rsync."
563 						<< std::endl
564 						;
565 				}
566 				assert(found_usage_error);
567 			}
568 			else {
569 				assert(find(subdir.begin(), subdir.end(), "AUTHORS") != subdir.end());
570 				assert(find(subdir.begin(), subdir.end(), "COPYING") != subdir.end());
571 				assert(find(subdir.begin(), subdir.end(), "INSTALL") != subdir.end());
572 				assert(find(subdir.begin(), subdir.end(), "Makefile") != subdir.end());
573 				assert(find(subdir.begin(), subdir.end(), "Makefile.in") != subdir.end());
574 				assert(find(subdir.begin(), subdir.end(), "README") != subdir.end());
575 				assert(find(subdir.begin(), subdir.end(), "archiver.cc") != subdir.end());
576 				assert(find(subdir.begin(), subdir.end(), "archiver.h") != subdir.end());
577 				assert(find(subdir.begin(), subdir.end(), "config.h") != subdir.end());
578 				assert(find(subdir.begin(), subdir.end(), "config.h.in") != subdir.end());
579 				assert(find(subdir.begin(), subdir.end(), "configure") != subdir.end());
580 				assert(find(subdir.begin(), subdir.end(), "error.cc") != subdir.end());
581 				assert(find(subdir.begin(), subdir.end(), "error.h") != subdir.end());
582 				assert(find(subdir.begin(), subdir.end(), "estring.cc") != subdir.end());
583 				assert(find(subdir.begin(), subdir.end(), "estring.h") != subdir.end());
584 				assert(find(subdir.begin(), subdir.end(), "exec.cc") != subdir.end());
585 				assert(find(subdir.begin(), subdir.end(), "exec.h") != subdir.end());
586 				assert(find(subdir.begin(), subdir.end(), "fs.cc") != subdir.end());
587 				assert(find(subdir.begin(), subdir.end(), "fs.h") != subdir.end());
588 				assert(find(subdir.begin(), subdir.end(), "help.cc") != subdir.end());
589 				assert(find(subdir.begin(), subdir.end(), "help.h") != subdir.end());
590 				assert(find(subdir.begin(), subdir.end(), "logger.cc") != subdir.end());
591 				assert(find(subdir.begin(), subdir.end(), "logger.h") != subdir.end());
592 				assert(find(subdir.begin(), subdir.end(), "make-test-fs-cc") != subdir.end());
593 				assert(find(subdir.begin(), subdir.end(), "rconfig.cc") != subdir.end());
594 				assert(find(subdir.begin(), subdir.end(), "rconfig.h") != subdir.end());
595 				assert(find(subdir.begin(), subdir.end(), "rmath.h") != subdir.end());
596 				assert(find(subdir.begin(), subdir.end(), "rvm.cc") != subdir.end());
597 				assert(find(subdir.begin(), subdir.end(), "rvm.1") != subdir.end());
598 				assert(find(subdir.begin(), subdir.end(), "rvm.1.in") != subdir.end());
599 				assert(find(subdir.begin(), subdir.end(), "test-rvm-001.cc") != subdir.end());
600 				assert(find(subdir.begin(), subdir.end(), "test-error.cc") != subdir.end());
601 				assert(find(subdir.begin(), subdir.end(), "test-estring.cc") != subdir.end());
602 				assert(find(subdir.begin(), subdir.end(), "test-exec.cc") != subdir.end());
603 				assert(find(subdir.begin(), subdir.end(), "test-fs-cwd.cc") != subdir.end());
604 				assert(find(subdir.begin(), subdir.end(), "test-fs.cc") != subdir.end());
605 				// assert(find(subdir.begin(), subdir.end(), "test-job.cc") != subdir.end());
606 				assert(find(subdir.begin(), subdir.end(), "test-logger.cc") != subdir.end());
607 				// assert(find(subdir.begin(), subdir.end(), "test-rconfig.cc") != subdir.end());
608 				assert(find(subdir.begin(), subdir.end(), "test-rmath.cc") != subdir.end());
609 				assert(find(subdir.begin(), subdir.end(), "test-strfmt.cc") != subdir.end());
610 				assert(find(subdir.begin(), subdir.end(), "test-timer.cc") != subdir.end());
611 				assert(find(subdir.begin(), subdir.end(), "test-tstamp.cc") != subdir.end());
612 				assert(find(subdir.begin(), subdir.end(), "test-types.cc") != subdir.end());
613 				assert(find(subdir.begin(), subdir.end(), "timer.cc") != subdir.end());
614 				assert(find(subdir.begin(), subdir.end(), "timer.h") != subdir.end());
615 				assert(find(subdir.begin(), subdir.end(), "tstamp.cc") != subdir.end());
616 				assert(find(subdir.begin(), subdir.end(), "tstamp.h") != subdir.end());
617 				assert(find(subdir.begin(), subdir.end(), "types.h") != subdir.end());
618 				assert(find(subdir.begin(), subdir.end(), "vaulter.cc") != subdir.end());
619 				assert(find(subdir.begin(), subdir.end(), "vaulter.h") != subdir.end());
620 
621 				assert(test_inodes(adir[0], adir[1], "AUTHORS"));
622 				assert(test_inodes(adir[0], adir[2], "AUTHORS"));
623 				assert(test_inodes(adir[0], adir[2], "COPYING"));
624 			}
625 
626 			// TODO: Check output
627 			assert(
628 				exists(
629 					static_cast<std::string>("./test-rvm.dir/catalog.dir/")
630 					+ config.timestamp().str()
631 				)
632 			);
633 		}
634 		catch(error e) {
635 			ERR_OUT(e);
636 			thrown = true;
637 		}
638 		catch(...) {
639 			ERR_OUT(err_unknown);
640 			assert(0);
641 		}
642 		assert(!thrown);
643 	}
644 }
645 
main(int argc,char const * argv[])646 int main(int argc, char const * argv[])
647 {
648 	cleanup();
649 	setup();
650 	try {
651 		test_rvm();
652 	}
653 	catch(error e) {
654 		std::cerr << e;
655 		assert(0);
656 	}
657 	catch(...) {
658 		std::cerr << err_unknown;
659 		assert(0);
660 	}
661 	cleanup();
662 	return(0);
663 }
664 
665