1 #include <check.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include "../../test.h"
6 #include "../../../src/alloc.h"
7 #include "../../../src/fsops.h"
8 #include "../../../src/hexmap.h"
9 #include "../../../src/iobuf.h"
10 #include "../../../src/lock.h"
11 #include "../../../src/prepend.h"
12 #include "../../../src/server/protocol2/dpth.h"
13 #include "../../../src/protocol2/blk.h"
14 #include "../../builders/build_file.h"
15
16 #define LOCKPATH "utest_dpth"
17 #define CFILES LOCKPATH "/cfiles"
18 #define TESTCLIENT "testclient"
19
assert_path_components(struct dpth * dpth,int prim,int seco,int tert)20 static void assert_path_components(struct dpth *dpth,
21 int prim, int seco, int tert)
22 {
23 fail_unless(dpth->comp[0]==prim);
24 fail_unless(dpth->comp[1]==seco);
25 fail_unless(dpth->comp[2]==tert);
26 }
27
assert_components(struct dpth * dpth,int prim,int seco,int tert,int sig)28 static void assert_components(struct dpth *dpth,
29 int prim, int seco, int tert, int sig)
30 {
31 assert_path_components(dpth, prim, seco, tert);
32 fail_unless(dpth->comp[3]==sig);
33 }
34
setup(void)35 static struct dpth *setup(void)
36 {
37 struct dpth *dpth;
38 hexmap_init();
39 fail_unless(recursive_delete(LOCKPATH)==0);
40 fail_unless((dpth=dpth_alloc())!=NULL);
41 assert_components(dpth, 0, 0, 0, 0);
42 return dpth;
43 }
44
tear_down(struct dpth ** dpth)45 static void tear_down(struct dpth **dpth)
46 {
47 dpth_free(dpth);
48 fail_unless(recursive_delete(LOCKPATH)==0);
49 alloc_check();
50 }
51
write_to_dpth(struct dpth * dpth,const char * savepathstr)52 static int write_to_dpth(struct dpth *dpth, const char *savepathstr)
53 {
54 int ret;
55 struct iobuf wbuf;
56 struct blk *blk=blk_alloc();
57 blk->savepath=savepathstr_with_sig_to_uint64(savepathstr);
58 wbuf.buf=strdup_w("abc", __FUNCTION__);
59 wbuf.len=3;
60 ret=dpth_protocol2_fwrite(dpth, &wbuf, blk);
61 free_w(&wbuf.buf);
62 blk_free(&blk);
63 return ret;
64 }
65
do_fork(void)66 static void do_fork(void)
67 {
68 switch(fork())
69 {
70 case -1: fail_unless(0==1);
71 break;
72 case 0: // Child.
73 {
74 struct dpth *dpth;
75 const char *savepath;
76 dpth=dpth_alloc();
77 dpth_protocol2_init(dpth,
78 LOCKPATH,
79 TESTCLIENT,
80 CFILES,
81 MAX_STORAGE_SUBDIRS);
82 savepath=dpth_protocol2_mk(dpth);
83 write_to_dpth(dpth, savepath);
84 sleep(2);
85 dpth_free(&dpth);
86 exit(0);
87 }
88 default: break;
89 }
90 // Parent.
91 }
92
prepare_simple_lock(void)93 static struct dpth *prepare_simple_lock(void)
94 {
95 struct dpth *dpth;
96 const char *savepath;
97 dpth=setup();
98 fail_unless(dpth_protocol2_init(dpth,
99 LOCKPATH,
100 TESTCLIENT,
101 CFILES,
102 MAX_STORAGE_SUBDIRS)==0);
103 savepath=dpth_protocol2_mk(dpth);
104 ck_assert_str_eq(savepath, "0000/0000/0000/0000");
105 fail_unless(dpth->head->lock->status==GET_LOCK_GOT);
106 // Fill up the data file, so that the next call to dpth_incr_sig will
107 // need to open a new one.
108 while(dpth->comp[3]<DATA_FILE_SIG_MAX-1)
109 {
110 fail_unless(write_to_dpth(dpth, savepath)==0);
111 fail_unless(dpth_protocol2_incr_sig(dpth)==0);
112 }
113 return dpth;
114 }
115
check_simple_lock(struct dpth ** dpth,const char * expected_savepath,int expected_tert)116 static void check_simple_lock(struct dpth **dpth,
117 const char *expected_savepath, int expected_tert)
118 {
119 const char *savepath;
120 fail_unless(dpth_protocol2_incr_sig(*dpth)==0);
121 savepath=dpth_protocol2_mk(*dpth);
122 ck_assert_str_eq(savepath, expected_savepath);
123 assert_components(*dpth, 0, 0, expected_tert, 0);
124 fail_unless((*dpth)->head!=(*dpth)->tail);
125 fail_unless((*dpth)->head->lock->status==GET_LOCK_GOT);
126 fail_unless((*dpth)->tail->lock->status==GET_LOCK_GOT);
127 tear_down(dpth);
128 }
129
START_TEST(test_simple_lock)130 START_TEST(test_simple_lock)
131 {
132 int stat;
133 struct dpth *dpth;
134
135 dpth=prepare_simple_lock();
136
137 // Child will lock the next data file. So, the next call to dpth_mk
138 // will get the next one after that.
139 do_fork();
140 sleep(1);
141
142 check_simple_lock(&dpth, "0000/0000/0002/0000", 2);
143
144 wait(&stat);
145 }
146 END_TEST
147
START_TEST(test_simple_lock_with_existant_data_files)148 START_TEST(test_simple_lock_with_existant_data_files)
149 {
150 struct dpth *dpth;
151
152 dpth=prepare_simple_lock();
153
154 // Create some data files that did not exist previously. The next call
155 // to incr_sig should skip over them.
156 build_file(LOCKPATH "/0000/0000/0001", "");
157 build_file(LOCKPATH "/0000/0000/0002", "");
158 build_file(LOCKPATH "/0000/0000/0003", "");
159
160 check_simple_lock(&dpth, "0000/0000/0004/0000", 4);
161 }
162 END_TEST
163
164 struct incr_data
165 {
166 uint16_t prim;
167 uint16_t seco;
168 uint16_t tert;
169 uint16_t sig;
170 uint16_t prim_expected;
171 uint16_t seco_expected;
172 uint16_t tert_expected;
173 uint16_t sig_expected;
174 int ret_expected;
175 };
176
177 static struct incr_data d[] = {
178 { 0x0000, 0x0000, 0x0000, 0x0000,
179 0x0000, 0x0000, 0x0000, 0x0001, 0 },
180 { 0x0000, 0x0000, 0x0000, 0x0001,
181 0x0000, 0x0000, 0x0000, 0x0002, 0 },
182 { 0x0000, 0x0000, 0x0000, 0x1000,
183 0x0000, 0x0000, 0x0001, 0x0000, 0 },
184 { 0x0000, 0x0000, 0x0AAA, 0x0000,
185 0x0000, 0x0000, 0x0AAA, 0x0001, 0 },
186 { 0x0000, 0x0000, 0x0AAA, 0x0AAA,
187 0x0000, 0x0000, 0x0AAA, 0x0AAB, 0 },
188 { 0x0000, 0x0000, 0xFFFF, 0x1000,
189 0x0000, 0x0001, 0x0000, 0x0000, 0 },
190 { 0x0000, 0x3333, 0xFFFF, 0x1000,
191 0x0000, 0x3334, 0x0000, 0x0000, 0 },
192 { 0x0000, 0x7530, 0xFFFF, 0x1000,
193 0x0001, 0x0000, 0x0000, 0x0000, 0 },
194 { 0x3333, 0x3333, 0x3333, 0x0050,
195 0x3333, 0x3333, 0x3333, 0x0051, 0 },
196 { 0x3333, 0xFFFF, 0xFFFF, 0x1000,
197 0x3334, 0x0000, 0x0000, 0x0000, 0 },
198 { 0x7530, 0x7530, 0xFFFF, 0x1000,
199 0x0000, 0x0000, 0x0000, 0x0000, -1 }
200 };
201
START_TEST(test_incr_sig)202 START_TEST(test_incr_sig)
203 {
204 FOREACH(d)
205 {
206 struct dpth *dpth;
207 dpth=setup();
208 fail_unless(dpth_protocol2_init(dpth,
209 LOCKPATH,
210 TESTCLIENT,
211 CFILES,
212 MAX_STORAGE_SUBDIRS)==0);
213 dpth->comp[0]=d[i].prim;
214 dpth->comp[1]=d[i].seco;
215 dpth->comp[2]=d[i].tert;
216 dpth->comp[3]=d[i].sig;
217 fail_unless(dpth_protocol2_incr_sig(dpth)==d[i].ret_expected);
218 if(!d[i].ret_expected)
219 assert_components(dpth,
220 d[i].prim_expected,
221 d[i].seco_expected,
222 d[i].tert_expected,
223 d[i].sig_expected);
224 tear_down(&dpth);
225 }
226 }
227 END_TEST
228
229 struct init_data
230 {
231 uint16_t prim;
232 uint16_t seco;
233 uint16_t tert;
234 uint16_t prim_expected;
235 uint16_t seco_expected;
236 uint16_t tert_expected;
237 int ret_expected;
238 };
239
240 static struct init_data in[] = {
241 { 0x0000, 0x0000, 0x0000,
242 0x0000, 0x0000, 0x0001, 0 },
243 { 0x0000, 0x0000, 0xAAAA,
244 0x0000, 0x0000, 0xAAAB, 0 },
245 { 0x0000, 0x0000, 0xFFFF,
246 0x0000, 0x0001, 0x0000, 0 },
247 { 0x0000, 0x3333, 0xFFFF,
248 0x0000, 0x3334, 0x0000, 0 },
249 { 0x0000, 0x7530, 0xFFFF,
250 0x0001, 0x0000, 0x0000, 0 },
251 { 0x3333, 0xFFFF, 0xFFFF,
252 0x3334, 0x0000, 0x0000, 0 },
253 { 0x7530, 0x7530, 0xFFFF,
254 0x0000, 0x0000, 0x0000, -1 }
255 };
256
START_TEST(test_init)257 START_TEST(test_init)
258 {
259 FOREACH(in)
260 {
261 struct fzp *fp=NULL;
262 char *path=NULL;
263 struct dpth *dpth;
264 char *savepath;
265 dpth=setup();
266 dpth->comp[0]=in[i].prim;
267 dpth->comp[1]=in[i].seco;
268 dpth->comp[2]=in[i].tert;
269 dpth->comp[3]=0;
270 savepath=dpth_protocol2_get_save_path(dpth);
271 // Truncate it to remove the sig part.
272 savepath[14]='\0';
273 path=prepend_s(LOCKPATH, savepath);
274 fail_unless(build_path_w(path)==0);
275 // Create a file.
276 fail_unless((fp=fzp_open(path, "wb"))!=NULL);
277 fzp_close(&fp);
278
279 // Now when calling dpth_init(), the components should be
280 // incremented appropriately.
281 dpth_free(&dpth);
282 fail_unless((dpth=dpth_alloc())!=NULL);
283 fail_unless(dpth_protocol2_init(dpth,
284 LOCKPATH,
285 TESTCLIENT,
286 CFILES,
287 MAX_STORAGE_SUBDIRS)==in[i].ret_expected);
288 assert_path_components(dpth,
289 in[i].prim_expected,
290 in[i].seco_expected,
291 in[i].tert_expected);
292
293 free_w(&path);
294 tear_down(&dpth);
295 }
296 }
297 END_TEST
298
suite_server_protocol2_dpth(void)299 Suite *suite_server_protocol2_dpth(void)
300 {
301 Suite *s;
302 TCase *tc_core;
303
304 s=suite_create("server_protocol2_dpth");
305
306 tc_core=tcase_create("Core");
307
308 tcase_add_test(tc_core, test_simple_lock);
309 tcase_add_test(tc_core, test_simple_lock_with_existant_data_files);
310 tcase_add_test(tc_core, test_incr_sig);
311 tcase_add_test(tc_core, test_init);
312 suite_add_tcase(s, tc_core);
313
314 return s;
315 }
316