1 #include "../../test.h"
2 #include "../../builders/build.h"
3 #include "../../prng.h"
4 #include "../../../src/alloc.h"
5 #include "../../../src/asfd.h"
6 #include "../../../src/async.h"
7 #include "../../../src/attribs.h"
8 #include "../../../src/base64.h"
9 #include "../../../src/bu.h"
10 #include "../../../src/hexmap.h"
11 #include "../../../src/fsops.h"
12 #include "../../../src/iobuf.h"
13 #include "../../../src/server/protocol1/backup_phase2.h"
14 #include "../../../src/server/sdirs.h"
15 #include "../../../src/slist.h"
16 #include "../../builders/build_asfd_mock.h"
17 #include "../../builders/build_file.h"
18 
19 #define BASE	"utest_server_protocol1_backup_phase2"
20 
21 static struct ioevent_list reads;
22 static struct ioevent_list writes;
23 
do_sdirs_init(struct sdirs * sdirs)24 static void do_sdirs_init(struct sdirs *sdirs)
25 {
26 	fail_unless(!sdirs_init(sdirs, PROTO_1,
27 		BASE, // directory
28 		"utestclient", // cname
29 		NULL, // client_lockdir
30 		"a_group", // dedup_group
31 		NULL // manual_delete
32 	));
33 }
34 
setup_sdirs(void)35 static struct sdirs *setup_sdirs(void)
36 {
37 	struct sdirs *sdirs;
38 	fail_unless((sdirs=sdirs_alloc())!=NULL);
39 	do_sdirs_init(sdirs);
40 	return sdirs;
41 }
42 
setup_conf(void)43 static struct conf **setup_conf(void)
44 {
45 	struct conf **confs=NULL;
46 	fail_unless((confs=confs_alloc())!=NULL);
47 	fail_unless(!confs_init(confs));
48 	return confs;
49 }
50 
setup_async(void)51 static struct async *setup_async(void)
52 {
53 	struct async *as;
54 	fail_unless((as=async_alloc())!=NULL);
55 	as->init(as, 0 /* estimate */);
56 	return as;
57 }
58 
setup(struct async ** as,struct sdirs ** sdirs,struct conf *** confs)59 static void setup(struct async **as,
60 	struct sdirs **sdirs, struct conf ***confs)
61 {
62 	if(as) *as=setup_async();
63 	if(sdirs) *sdirs=setup_sdirs();
64 	if(confs) *confs=setup_conf();
65 	fail_unless(!recursive_delete(BASE));
66 }
67 
tear_down(struct async ** as,struct sdirs ** sdirs,struct conf *** confs)68 static void tear_down(struct async **as,
69 	struct sdirs **sdirs, struct conf ***confs)
70 {
71 	async_free(as);
72 	sdirs_free(sdirs);
73 	confs_free(confs);
74 	fail_unless(!recursive_delete(BASE));
75 //printf("%d %d\n", alloc_count, free_count);
76 	alloc_check();
77 }
78 
START_TEST(test_phase2_unset_as_sdirs_confs)79 START_TEST(test_phase2_unset_as_sdirs_confs)
80 {
81 	setup(NULL, NULL, NULL);
82 	fail_unless(backup_phase2_server_protocol1(
83 		NULL, // as
84 		NULL, // sdirs
85 		NULL, // incexc
86 		0, // resume
87 		NULL // confs
88 	)==-1);
89 	tear_down(NULL, NULL, NULL);
90 }
91 END_TEST
92 
START_TEST(test_phase2_unset_sdirs_confs)93 START_TEST(test_phase2_unset_sdirs_confs)
94 {
95 	struct async *as;
96 	setup(&as, NULL, NULL);
97 	fail_unless(backup_phase2_server_protocol1(
98 		as,
99 		NULL, // sdirs
100 		NULL, // incexc
101 		0, // resume
102 		NULL // confs
103 	)==-1);
104 	tear_down(&as, NULL, NULL);
105 }
106 END_TEST
107 
START_TEST(test_phase2_unset_confs)108 START_TEST(test_phase2_unset_confs)
109 {
110 	struct async *as;
111 	struct sdirs *sdirs;
112 	setup(&as, &sdirs, NULL);
113 	fail_unless(backup_phase2_server_protocol1(
114 		as,
115 		sdirs,
116 		NULL, // incexc
117 		0, // resume
118 		NULL // confs
119 	)==-1);
120 	tear_down(&as, &sdirs, NULL);
121 }
122 END_TEST
123 
START_TEST(test_phase2_unset_sdirs)124 START_TEST(test_phase2_unset_sdirs)
125 {
126 	struct async *as;
127 	struct conf **confs;
128 	setup(&as, NULL, &confs);
129 	fail_unless(backup_phase2_server_protocol1(
130 		as,
131 		NULL, // sdirs
132 		NULL, // incexc
133 		0, // resume
134 		confs
135 	)==-1);
136 	tear_down(&as, NULL, &confs);
137 }
138 END_TEST
139 
START_TEST(test_phase2_unset_asfd)140 START_TEST(test_phase2_unset_asfd)
141 {
142 	struct async *as;
143 	struct sdirs *sdirs;
144 	struct conf **confs;
145 	setup(&as, &sdirs, &confs);
146 	fail_unless(backup_phase2_server_protocol1(
147 		as,
148 		sdirs,
149 		NULL, // incexc
150 		0, // resume
151 		confs
152 	)==-1);
153 	tear_down(&as, &sdirs, &confs);
154 }
155 END_TEST
156 
async_rw_simple(struct async * as)157 static int async_rw_simple(struct async *as)
158 {
159 	return as->asfd->read(as->asfd);
160 }
161 
162 static struct sd sd1[] = {
163 	{ "0000001 1970-01-01 00:00:00", 1, 1, BU_WORKING },
164 };
165 
setup_writes_from_slist(struct asfd * asfd,int * w,struct slist * slist,int changed)166 static void setup_writes_from_slist(struct asfd *asfd,
167 	int *w, struct slist *slist, int changed)
168 {
169 	struct sbuf *s;
170 	if(!slist) return;
171 	for(s=slist->head; s; s=s->next)
172 	{
173 		if(!sbuf_is_filedata(s))
174 			continue;
175 		if(changed && !sbuf_is_encrypted(s))
176 			asfd_assert_write_iobuf(asfd,
177 				w, 0, &s->protocol1->datapth);
178 		asfd_assert_write_iobuf(asfd, w, 0, &s->attr);
179 		asfd_assert_write_iobuf(asfd, w, 0, &s->path);
180 		if(changed && !sbuf_is_encrypted(s))
181 		{
182 			struct iobuf wbuf;
183 			char empty_sig[12]={'r', 's', 0x01, '6',
184 				0, 0x02, 0, 0, 0, 0, 0, 0x10};
185 			iobuf_set(&wbuf, CMD_APPEND,
186 				empty_sig, sizeof(empty_sig));
187 			asfd_assert_write_iobuf(asfd, w, 0, &wbuf);
188 			asfd_assert_write(asfd, w, 0, CMD_END_FILE, "endfile");
189 		}
190 	}
191 }
192 
setup_asfds_happy_path_nothing_from_client(struct asfd * asfd,struct slist * slist)193 static void setup_asfds_happy_path_nothing_from_client(struct asfd *asfd,
194 	struct slist *slist)
195 {
196 	int r=0, w=0;
197 	setup_writes_from_slist(asfd, &w, slist, 0 /* not changed */);
198 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "backupphase2end");
199 	asfd_mock_read_no_op(asfd, &r, 20);
200 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "okbackupphase2end");
201 }
202 
setup_asfds_happy_path_interrupts_from_client(struct asfd * asfd,struct slist * slist)203 static void setup_asfds_happy_path_interrupts_from_client(struct asfd *asfd,
204 	struct slist *slist)
205 {
206 	int r=0, w=0;
207 	struct sbuf *s;
208 	setup_writes_from_slist(asfd, &w, slist, 0 /* not changed */);
209 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "backupphase2end");
210 	asfd_mock_read_no_op(asfd, &r, 200);
211 	for(s=slist->head; s; s=s->next)
212 	{
213 		if(!sbuf_is_filedata(s))
214 			continue;
215 		asfd_mock_read(asfd, &r, 0, CMD_INTERRUPT, s->path.buf);
216 	}
217 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "okbackupphase2end");
218 }
219 
setup_asfds_happy_path_new_files(struct asfd * asfd,struct slist * slist)220 static void setup_asfds_happy_path_new_files(struct asfd *asfd,
221 	struct slist *slist)
222 {
223 	int r=0, w=0;
224 	struct sbuf *s;
225 	setup_writes_from_slist(asfd, &w, slist, 0 /* not changed */);
226 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "backupphase2end");
227 	asfd_mock_read_no_op(asfd, &r, 200);
228 	for(s=slist->head; s; s=s->next)
229 	{
230 		if(!sbuf_is_filedata(s))
231 			continue;
232 		asfd_mock_read_iobuf(asfd, &r, 0, &s->attr);
233 		asfd_mock_read_iobuf(asfd, &r, 0, &s->path);
234 		asfd_mock_read(asfd, &r, 0, CMD_APPEND, "some data");
235 		asfd_mock_read(asfd, &r, 0, CMD_END_FILE,
236 			"0:d41d8cd98f00b204e9800998ecf8427e");
237 	}
238 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "okbackupphase2end");
239 }
240 
run_test(int expected_ret,int manio_entries,void setup_asfds_callback (struct asfd * asfd,struct slist * slist))241 static void run_test(int expected_ret,
242         int manio_entries,
243         void setup_asfds_callback(struct asfd *asfd, struct slist *slist))
244 {
245 	struct asfd *asfd;
246 	struct async *as;
247 	struct sdirs *sdirs;
248 	struct conf **confs;
249 	struct slist *slist=NULL;
250 	prng_init(0);
251 	base64_init();
252 	hexmap_init();
253 	setup(&as, &sdirs, &confs);
254 	asfd=asfd_mock_setup(&reads, &writes);
255 	as->asfd_add(as, asfd);
256 	as->read_write=async_rw_simple;
257 	asfd->as=as;
258 
259 	build_storage_dirs(sdirs, sd1, ARR_LEN(sd1));
260 	fail_unless(!sdirs_get_real_working_from_symlink(sdirs));
261 	if(manio_entries)
262 	{
263 		slist=build_manifest(sdirs->phase1data,
264 				PROTO_1, manio_entries, 1 /*phase*/);
265 	}
266 	setup_asfds_callback(asfd, slist);
267 
268 	fail_unless(backup_phase2_server_protocol1(
269 		as,
270 		sdirs,
271 		NULL, // incexc
272 		0, // resume
273 		confs
274 	)==expected_ret);
275 
276 	if(!expected_ret)
277 	{
278 		// FIX THIS: Should check for the presence and correctness of
279 		// changed and unchanged manios.
280 	}
281 	asfd_free(&asfd);
282 	asfd_mock_teardown(&reads, &writes);
283 	slist_free(&slist);
284 	tear_down(&as, &sdirs, &confs);
285 }
286 
START_TEST(test_phase2_happy_path_nothing_from_client)287 START_TEST(test_phase2_happy_path_nothing_from_client)
288 {
289 	run_test(0, 10, setup_asfds_happy_path_nothing_from_client);
290 }
291 END_TEST
292 
START_TEST(test_phase2_happy_path_interrupts_from_client)293 START_TEST(test_phase2_happy_path_interrupts_from_client)
294 {
295 	run_test(0, 100, setup_asfds_happy_path_interrupts_from_client);
296 }
297 END_TEST
298 
START_TEST(test_phase2_happy_path_new_files)299 START_TEST(test_phase2_happy_path_new_files)
300 {
301 	run_test(0, 10, setup_asfds_happy_path_new_files);
302 }
303 END_TEST
304 
305 static struct sd sd2[] = {
306 	{ "0000001 1970-01-01 00:00:00", 1, 1, BU_CURRENT },
307 	{ "0000002 1970-01-01 00:00:00", 2, 2, BU_WORKING },
308 };
309 
setup_asfds_happy_path_changed_files(struct asfd * asfd,struct slist * slist)310 static void setup_asfds_happy_path_changed_files(struct asfd *asfd,
311 	struct slist *slist)
312 {
313 	int r=0, w=0;
314 	struct sbuf *s;
315 	char empty_delta[4]={'r', 's', 0x02, '6'};
316 	setup_writes_from_slist(asfd, &w, slist, 1 /* changed */);
317 	asfd_assert_write(asfd, &w, 0, CMD_GEN, "backupphase2end");
318 	asfd_mock_read_no_op(asfd, &r, 200);
319 	if(slist) for(s=slist->head; s; s=s->next)
320 	{
321 		struct iobuf rbuf;
322 		if(!sbuf_is_filedata(s))
323 			continue;
324 		asfd_mock_read_iobuf(asfd, &r, 0, &s->protocol1->datapth);
325 		asfd_mock_read_iobuf(asfd, &r, 0, &s->attr);
326 		asfd_mock_read_iobuf(asfd, &r, 0, &s->path);
327 		if(sbuf_is_encrypted(s))
328 		{
329 			asfd_mock_read(asfd, &r, 0, CMD_APPEND, "some data");
330 		}
331 		else
332 		{
333 			iobuf_set(&rbuf, CMD_APPEND,
334 				empty_delta, sizeof(empty_delta));
335 			asfd_mock_read_iobuf(asfd, &r, 0, &rbuf);
336 		}
337 		asfd_mock_read_iobuf(asfd, &r, 0, &s->endfile);
338 	}
339 	asfd_mock_read(asfd, &r, 0, CMD_GEN, "okbackupphase2end");
340 }
341 
run_test_changed(int expected_ret,int manio_entries,void setup_asfds_callback (struct asfd * asfd,struct slist * slist))342 static void run_test_changed(int expected_ret,
343         int manio_entries,
344         void setup_asfds_callback(struct asfd *asfd, struct slist *slist))
345 {
346 	struct asfd *asfd;
347 	struct async *as;
348 	struct sdirs *sdirs;
349 	struct conf **confs;
350 	struct slist *slist=NULL;
351 	prng_init(0);
352 	base64_init();
353 	hexmap_init();
354 	setup(&as, &sdirs, &confs);
355 	asfd=asfd_mock_setup(&reads, &writes);
356 	as->asfd_add(as, asfd);
357 	as->read_write=async_rw_simple;
358 	asfd->as=as;
359 
360 	build_storage_dirs(sdirs, sd2, ARR_LEN(sd2));
361 	fail_unless(!sdirs_get_real_working_from_symlink(sdirs));
362 	if(manio_entries)
363 	{
364 		struct sbuf *s;
365 		slist=build_manifest(sdirs->cmanifest,
366 			PROTO_1, manio_entries, 0 /*phase*/);
367 		for(s=slist->head; s; s=s->next)
368 		{
369 			char path[256];
370 			if(!sbuf_is_filedata(s))
371 				continue;
372 			snprintf(path, sizeof(path), "%s/%s%s",
373 				sdirs->currentdata, TREE_DIR, s->path.buf);
374 			build_file(path, "");
375 			// Adjust mtimes so that differences are detected.
376 			fail_unless(!lstat(path, &s->statp));
377 			s->winattr=0;
378 			s->compression=0;
379 			attribs_encode(s);
380 		}
381 		build_manifest_phase1_from_slist(sdirs->phase1data,
382 			slist, PROTO_1);
383 		build_file(sdirs->cincexc, NULL);
384 	}
385 	setup_asfds_callback(asfd, slist);
386 
387 	fail_unless(backup_phase2_server_protocol1(
388 		as,
389 		sdirs,
390 		NULL, // incexc
391 		0, // resume
392 		confs
393 	)==expected_ret);
394 
395 	if(!expected_ret)
396 	{
397 		// FIX THIS: Should check for the presence and correctness of
398 		// changed and unchanged manios.
399 	}
400 	asfd_free(&asfd);
401 	asfd_mock_teardown(&reads, &writes);
402 	slist_free(&slist);
403 	tear_down(&as, &sdirs, &confs);
404 }
405 
START_TEST(test_phase2_happy_path_no_files)406 START_TEST(test_phase2_happy_path_no_files)
407 {
408 	run_test_changed(0, 0, setup_asfds_happy_path_changed_files);
409 }
410 END_TEST
411 
START_TEST(test_phase2_happy_path_changed_files)412 START_TEST(test_phase2_happy_path_changed_files)
413 {
414 	run_test_changed(0, 10, setup_asfds_happy_path_changed_files);
415 }
416 END_TEST
417 
suite_server_protocol1_backup_phase2(void)418 Suite *suite_server_protocol1_backup_phase2(void)
419 {
420 	Suite *s;
421 	TCase *tc_core;
422 
423 	s=suite_create("server_protocol1_backup_phase2");
424 
425 	tc_core=tcase_create("Core");
426 	tcase_set_timeout(tc_core, 60);
427 
428 	tcase_add_test(tc_core, test_phase2_unset_as_sdirs_confs);
429 	tcase_add_test(tc_core, test_phase2_unset_sdirs_confs);
430 	tcase_add_test(tc_core, test_phase2_unset_confs);
431 	tcase_add_test(tc_core, test_phase2_unset_sdirs);
432 	tcase_add_test(tc_core, test_phase2_unset_asfd);
433 
434 	tcase_add_test(tc_core, test_phase2_happy_path_nothing_from_client);
435 	tcase_add_test(tc_core, test_phase2_happy_path_interrupts_from_client);
436 	tcase_add_test(tc_core, test_phase2_happy_path_new_files);
437 
438 	tcase_add_test(tc_core, test_phase2_happy_path_no_files);
439 	tcase_add_test(tc_core, test_phase2_happy_path_changed_files);
440 
441 	suite_add_tcase(s, tc_core);
442 
443 	return s;
444 }
445