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