1 #include "../../test.h"
2 #include "../../builders/build.h"
3 #include "../../builders/build_file.h"
4 #include "../../../src/alloc.h"
5 #include "../../../src/asfd.h"
6 #include "../../../src/bu.h"
7 #include "../../../src/conf.h"
8 #include "../../../src/conffile.h"
9 #include "../../../src/cstat.h"
10 #include "../../../src/fsops.h"
11 #include "../../../src/fzp.h"
12 #include "../../../src/handy.h"
13 #include "../../../src/iobuf.h"
14 #include "../../../src/prepend.h"
15 #include "../../../src/server/monitor/cstat.h"
16 #include "../../../src/server/monitor/json_output.h"
17 #include "../../../src/server/sdirs.h"
18 
19 #define BASE		"utest_server_monitor_json_output"
20 #define SDIRS		BASE "_sdirs"
21 #define EXPECTED	TOP_SRCDIR "/utest/json_output"
22 #define CONF_BASE	"utest_server_monitor_json_output_conf"
23 #define CONFFILE	CONF_BASE "/burp.conf"
24 
25 static struct fzp *output=NULL;
26 
setup_tz(void)27 static char *setup_tz(void)
28 {
29 	char *tz;
30 	if((tz=getenv("TZ")))
31 		fail_unless((tz=strdup_w(tz, __func__))!=NULL);
32 	setenv("TZ", "UTC-10", 1);
33 	return tz;
34 }
35 
tear_down_tz(char ** tz)36 static void tear_down_tz(char **tz)
37 {
38 	if(tz && *tz)
39 	{
40 		setenv("TZ", *tz, 1);
41 		free_w(tz);
42 	}
43 	else
44 		unsetenv("TZ");
45 }
46 
tear_down(struct asfd ** asfd,char ** tz)47 static void tear_down(struct asfd **asfd, char **tz)
48 {
49 	asfd_free(asfd);
50 	fail_unless(!fzp_close(&output));
51 	fail_unless(!recursive_delete(CLIENTCONFDIR));
52 	tear_down_tz(tz);
53 	alloc_check();
54 }
55 
my_asfd_write(struct asfd * asfd,struct iobuf * wbuf)56 static int my_asfd_write(struct asfd *asfd, struct iobuf *wbuf)
57 {
58 	fail_unless(fzp_write(output, wbuf->buf, wbuf->len)==wbuf->len);
59 	return 0;
60 }
61 
asfd_setup(const char * outputpath)62 static struct asfd *asfd_setup(const char *outputpath)
63 {
64 	struct asfd *asfd;
65 	fail_unless((asfd=asfd_alloc())!=NULL);
66 	fail_unless((asfd->rbuf=iobuf_alloc())!=NULL);
67 	asfd->write=my_asfd_write;
68 	fail_unless(!build_path_w(outputpath));
69 	fail_unless((output=fzp_open(outputpath, "wb"))!=NULL);
70 	json_set_pretty_print(1);
71 	return asfd;
72 }
73 
START_TEST(test_json_send_warn)74 START_TEST(test_json_send_warn)
75 {
76 	char *tz;
77 	struct asfd *asfd;
78 	tz=setup_tz();
79 	asfd=asfd_setup(BASE "/warning");
80 	fail_unless(!json_send_warn(asfd, "this is my warning"));
81 	tear_down(&asfd, &tz);
82 }
83 END_TEST
84 
START_TEST(test_json_send_empty)85 START_TEST(test_json_send_empty)
86 {
87 	char *tz;
88 	struct asfd *asfd;
89 	tz=setup_tz();
90 	asfd=asfd_setup(BASE "/empty");
91 	fail_unless(!json_send(asfd, NULL, NULL, NULL, NULL, NULL, 0/*cache*/,
92 		version_to_long(VERSION)));
93 	tear_down(&asfd, &tz);
94 }
95 END_TEST
96 
setup_conf(void)97 static struct conf **setup_conf(void)
98 {
99 	struct conf **confs=NULL;
100 	fail_unless((confs=confs_alloc())!=NULL);
101 	fail_unless(!confs_init(confs));
102 	return confs;
103 }
104 
START_TEST(test_json_send_clients)105 START_TEST(test_json_send_clients)
106 {
107 	char *tz;
108 	struct asfd *asfd;
109 	struct cstat *c=NULL;
110 	struct cstat *clist=NULL;
111 	struct conf **monitor_cconfs=NULL;
112 	struct conf **globalcs=NULL;
113 	struct conf **cconfs=NULL;
114 	const char *cnames[] ={"cli1", "cli2", "cli3", NULL};
115 
116 	tz=setup_tz();
117 	monitor_cconfs=setup_conf();
118 	globalcs=setup_conf();
119 	cconfs=setup_conf();
120 
121 	build_file(CONFFILE, MIN_SERVER_CONF);
122 	fail_unless(!conf_load_global_only(CONFFILE, monitor_cconfs));
123 	fail_unless(!conf_load_global_only(CONFFILE, globalcs));
124 
125 	fail_unless(recursive_delete(CLIENTCONFDIR)==0);
126 	build_clientconfdir_files(cnames, "label=abc\nlabel=xyz\n");
127 	fail_unless(!cstat_load_data_from_disk(&clist, monitor_cconfs,
128 		globalcs, cconfs));
129 	assert_cstat_list(clist, cnames);
130 	for(c=clist; c; c=c->next)
131 		c->permitted=1;
132 	asfd=asfd_setup(BASE "/clients");
133 	fail_unless(!json_send(asfd, clist, NULL, NULL, NULL, NULL, 0/*cache*/,
134 		version_to_long(VERSION)));
135 	for(c=clist; c; c=c->next)
136 		sdirs_free((struct sdirs **)&c->sdirs);
137 	cstat_list_free(&clist);
138 	confs_free(&monitor_cconfs);
139 	confs_free(&globalcs);
140 	confs_free(&cconfs);
141 	tear_down(&asfd, &tz);
142 }
143 END_TEST
144 
145 static struct sd sd1[] = {
146 	{ "0000001 1971-01-01 10:00:00 +1000", 1, 1, BU_DELETABLE|BU_CURRENT },
147 };
148 
setup_sdirs(enum protocol protocol,const char * cname)149 static struct sdirs *setup_sdirs(enum protocol protocol, const char *cname)
150 {
151 	struct sdirs *sdirs;
152 	fail_unless((sdirs=sdirs_alloc())!=NULL);
153 	fail_unless(!sdirs_init(sdirs, protocol,
154 		SDIRS, // directory
155 		cname, // cname
156 		NULL, // client_lockdir
157 		"a_group", // dedup_group
158 		NULL // manual_delete
159 	));
160 	return sdirs;
161 }
162 
cstat_list_free_sdirs(struct cstat * clist)163 static void cstat_list_free_sdirs(struct cstat *clist)
164 {
165 	struct cstat *c;
166 	for(c=clist; c; c=c->next)
167 		sdirs_free((struct sdirs **)&c->sdirs);
168 }
169 
do_test_json_send_clients_with_backup(const char * path,struct sd * sd,int s,const char * specific_client)170 static void do_test_json_send_clients_with_backup(const char *path,
171 	struct sd *sd, int s, const char *specific_client)
172 {
173 	char *tz;
174 	struct asfd *asfd;
175 	struct cstat *c=NULL;
176 	struct cstat *clist=NULL;
177 	const char *cnames[] ={"cli1", "cli2", "cli3", NULL};
178 	tz=setup_tz();
179 	fail_unless(recursive_delete(CLIENTCONFDIR)==0);
180 	build_clientconfdir_files(cnames, NULL);
181 	fail_unless(!cstat_get_client_names(&clist, CLIENTCONFDIR));
182 	assert_cstat_list(clist, cnames);
183 	for(c=clist; c; c=c->next)
184 	{
185 		c->permitted=1;
186 		c->protocol=PROTO_1;
187 		fail_unless((c->sdirs=setup_sdirs(c->protocol, c->name))!=NULL);
188 		build_storage_dirs((struct sdirs *)c->sdirs, sd, s);
189 		fail_unless(!cstat_set_backup_list(c));
190 		fail_unless(c->bu!=NULL);
191 
192 	}
193 	asfd=asfd_setup(path);
194 
195 	c=NULL;
196 	if(specific_client)
197 	  fail_unless((c=cstat_get_by_name(clist, specific_client))!=NULL);
198 
199 	fail_unless(!json_send(asfd, clist, c, NULL, NULL, NULL, 0/*cache*/,
200 		version_to_long(VERSION)));
201 	cstat_list_free_sdirs(clist);
202 	cstat_list_free(&clist);
203 	fail_unless(!recursive_delete(SDIRS));
204 	tear_down(&asfd, &tz);
205 }
206 
START_TEST(test_json_send_clients_with_backup)207 START_TEST(test_json_send_clients_with_backup)
208 {
209 	do_test_json_send_clients_with_backup(
210 		BASE "/clients_with_backup",
211 		sd1, ARR_LEN(sd1), NULL);
212 }
213 END_TEST
214 
215 static struct sd sd12345[] = {
216 	{ "0000001 1971-01-01 10:00:00 +1000", 1, 1, BU_DELETABLE|BU_MANIFEST },
217 	{ "0000002 1971-01-02 10:00:00 +1000", 2, 2, 0 },
218 	{ "0000003 1971-01-03 10:00:00 +1000", 3, 3, BU_HARDLINKED },
219 	{ "0000004 1971-01-04 10:00:00 +1000", 4, 4, BU_DELETABLE },
220 	{ "0000005 1971-01-05 10:00:00 +1000", 5, 5, BU_CURRENT|BU_MANIFEST }
221 };
222 
START_TEST(test_json_send_clients_with_backups)223 START_TEST(test_json_send_clients_with_backups)
224 {
225 	do_test_json_send_clients_with_backup(
226 		BASE "/clients_with_backups",
227 		sd12345, ARR_LEN(sd12345), NULL);
228 }
229 END_TEST
230 
231 static struct sd sd123w[] = {
232 	{ "0000001 1971-01-01 10:00:00 +1000", 1, 1, BU_DELETABLE|BU_MANIFEST },
233 	{ "0000002 1971-01-02 10:00:00 +1000", 2, 2, BU_CURRENT|BU_MANIFEST },
234 	{ "0000003 1971-01-03 10:00:00 +1000", 3, 3, BU_WORKING },
235 };
236 
START_TEST(test_json_send_clients_with_backups_working)237 START_TEST(test_json_send_clients_with_backups_working)
238 {
239 	do_test_json_send_clients_with_backup(
240 		BASE "/clients_with_backups_working",
241 		sd123w, ARR_LEN(sd123w), NULL);
242 }
243 END_TEST
244 
245 static struct sd sd123f[] = {
246 	{ "0000001 1971-01-01 10:00:00 +1000", 1, 1, BU_DELETABLE|BU_MANIFEST },
247 	{ "0000002 1971-01-02 10:00:00 +1000", 2, 2, BU_CURRENT|BU_MANIFEST },
248 	{ "0000003 1971-01-03 10:00:00 +1000", 3, 3, BU_FINISHING },
249 };
250 
START_TEST(test_json_send_clients_with_backups_finishing)251 START_TEST(test_json_send_clients_with_backups_finishing)
252 {
253 	do_test_json_send_clients_with_backup(
254 		BASE "/clients_with_backups_finishing",
255 		sd123f, ARR_LEN(sd123f), NULL);
256 }
257 END_TEST
258 
START_TEST(test_json_send_client_specific)259 START_TEST(test_json_send_client_specific)
260 {
261 	do_test_json_send_clients_with_backup(
262 		BASE "/client_specific",
263 		sd12345, ARR_LEN(sd12345), "cli2");
264 }
265 END_TEST
266 
do_assert_files_equal(const char * opath,const char * npath,int compressed)267 static void do_assert_files_equal(const char *opath, const char *npath,
268 	int compressed)
269 {
270 	fail_unless(files_equal(opath, npath, compressed)==1);
271 }
272 
assert_files_equal(const char * opath,const char * npath)273 void assert_files_equal(const char *opath, const char *npath)
274 {
275 	return do_assert_files_equal(opath, npath, 0/*compressed*/);
276 }
277 
assert_files_compressed_equal(const char * opath,const char * npath)278 void assert_files_compressed_equal(const char *opath, const char *npath)
279 {
280 	return do_assert_files_equal(opath, npath, 1/*compressed*/);
281 }
282 
START_TEST(test_json_matching_output)283 START_TEST(test_json_matching_output)
284 {
285 	int i=0;
286 	int n=0;
287 	struct dirent **dir=NULL;
288 	fail_unless((n=scandir(BASE, &dir, filter_dot, NULL))>0);
289 	for(i=0; i<n; i++)
290 	{
291 		char *bpath;
292 		char *epath;
293 		fail_unless(
294 			(bpath=prepend_s(BASE, dir[i]->d_name))!=NULL);
295 		fail_unless(
296 			(epath=prepend_s(EXPECTED, dir[i]->d_name))!=NULL);
297 
298 		assert_files_equal(bpath, epath);
299 
300 		free_w(&bpath);
301 		free_w(&epath);
302 	}
303 	for(i=0; i<n; i++) free(dir[i]);
304 	free(dir);
305 	dir=NULL;
306 
307 	// Check that all the files in the expected directory also exist
308 	// in the directory that we generated.
309 	fail_unless((n=scandir(EXPECTED, &dir, filter_dot, NULL))>0);
310 	for(i=0; i<n; i++)
311 	{
312 		char *bpath;
313 		struct stat statp;
314 		fail_unless(
315 			(bpath=prepend_s(BASE, dir[i]->d_name))!=NULL);
316 		fail_unless(!lstat(bpath, &statp));
317 		fail_unless(S_ISREG(statp.st_mode));
318 		free_w(&bpath);
319 	}
320 	for(i=0; i<n; i++) free(dir[i]);
321 	free(dir);
322 	dir=NULL;
323 	alloc_check();
324 }
325 END_TEST
326 
START_TEST(cleanup)327 START_TEST(cleanup)
328 {
329 	// Not a test. Just wanted to cleanup before and after this suite.
330 	fail_unless(!recursive_delete(BASE));
331 	fail_unless(!recursive_delete(SDIRS));
332 	fail_unless(!recursive_delete(CONF_BASE));
333 }
334 END_TEST
335 
suite_server_monitor_json_output(void)336 Suite *suite_server_monitor_json_output(void)
337 {
338 	Suite *s;
339 	TCase *tc_core;
340 
341 	s=suite_create("server_monitor_json_output");
342 
343 	tc_core=tcase_create("Core");
344 	tcase_set_timeout(tc_core, 5);
345 
346 	tcase_add_test(tc_core, cleanup);
347 	tcase_add_test(tc_core, test_json_send_warn);
348 	tcase_add_test(tc_core, test_json_send_empty);
349 	tcase_add_test(tc_core, test_json_send_clients);
350 	tcase_add_test(tc_core, test_json_send_clients_with_backup);
351 	tcase_add_test(tc_core, test_json_send_clients_with_backups);
352 	tcase_add_test(tc_core, test_json_send_clients_with_backups_finishing);
353 	tcase_add_test(tc_core, test_json_send_clients_with_backups_working);
354 	tcase_add_test(tc_core, test_json_send_client_specific);
355 	tcase_add_test(tc_core, test_json_matching_output);
356 	tcase_add_test(tc_core, cleanup);
357 
358 	suite_add_tcase(s, tc_core);
359 
360 	return s;
361 }
362