1 //
2 /**************************************************************************************************
3 * IOWOW library
4 *
5 * MIT License
6 *
7 * Copyright (c) 2012-2020 Softmotions Ltd <info@softmotions.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in all
17 * copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *************************************************************************************************/
27
28
29 #include "iowow.h"
30 #include "log/iwlog.h"
31 #include "fs/iwexfile.h"
32 #include "utils/iwutils.h"
33
34 #include "iwcfg.h"
35 #include <CUnit/Basic.h>
36 #include <unistd.h>
37
38 #define UNLINK() \
39 unlink("iwfs_exfile_test1.dat"); \
40 unlink("iwfs_exfile_test1_2.dat"); \
41 unlink("test_mmap1.dat"); \
42 unlink("test_fibo_inc.dat")
43
44
init_suite()45 int init_suite() {
46 int rc = iw_init();
47 UNLINK();
48 return rc;
49 }
50
clean_suite()51 int clean_suite() {
52 UNLINK();
53 return 0;
54 }
55
iwfs_exfile_test1()56 void iwfs_exfile_test1() {
57 iwrc rc = 0;
58 IWFS_EXT ef;
59
60 const char *path = "iwfs_exfile_test1.dat";
61 IWFS_EXT_OPTS opts = {
62 .file = {
63 .path = path,
64 .lock_mode = IWP_WLOCK,
65 .omode = IWFS_DEFAULT_OMODE | IWFS_OTRUNC
66 },
67 .use_locks = 1
68 };
69 IWRC(iwfs_exfile_open(&ef, &opts), rc);
70 CU_ASSERT_EQUAL_FATAL(rc, 0);
71
72 char data[] = "b069a540-bc92-49ba-95e9-d1a2ee9e8c8f";
73 size_t sp, sp2;
74
75 // iwrc(*write)(struct IWFS_EXT* f, off_t off, const void *buf, size_t siz,
76 // size_t *sp);
77 IWRC(ef.write(&ef, 0, 0, 0, &sp), rc);
78 CU_ASSERT_EQUAL_FATAL(rc, 0);
79 CU_ASSERT_EQUAL(sp, 0);
80
81 IWRC(ef.write(&ef, 1, 0, 0, &sp), rc);
82 CU_ASSERT_EQUAL_FATAL(rc, 0);
83
84 IWP_FILE_STAT fstat;
85 IWRC(iwp_fstat(path, &fstat), rc);
86 CU_ASSERT_EQUAL_FATAL(rc, 0);
87 CU_ASSERT_EQUAL(sp, 0);
88 CU_ASSERT_EQUAL(fstat.size, iwp_alloc_unit());
89
90 IWRC(ef.write(&ef, 1, data, sizeof(data), &sp), rc);
91 CU_ASSERT_EQUAL_FATAL(rc, 0);
92 CU_ASSERT_EQUAL(sp, 37);
93
94 IWRC(ef.close(&ef), rc);
95 CU_ASSERT_EQUAL(rc, 0);
96
97 // Now reopen the file
98
99 opts.file.omode = IWFS_OREAD;
100 IWRC(iwfs_exfile_open(&ef, &opts), rc);
101 CU_ASSERT_EQUAL_FATAL(rc, 0);
102
103 char rdata[37];
104 // iwrc(*read)(struct IWFS_EXT* f, off_t off, void *buf, size_t siz, size_t
105 // *sp);
106 IWRC(ef.read(&ef, 1, rdata, sp, &sp2), rc);
107 CU_ASSERT_EQUAL_FATAL(rc, 0);
108 CU_ASSERT_EQUAL(sp, sp2);
109 CU_ASSERT_FALSE(strncmp(rdata, data, sizeof(data)));
110
111 rc = ef.write(&ef, 1, data, sizeof(data), &sp);
112 CU_ASSERT_EQUAL(IW_ERROR_READONLY, rc);
113
114 size_t ps = iwp_alloc_unit();
115 rc = 0;
116 IWRC(ef.read(&ef, ps - 1, rdata, 2, &sp2), rc);
117 CU_ASSERT_EQUAL_FATAL(rc, 0);
118 CU_ASSERT_EQUAL(sp2, 1);
119
120 IWRC(ef.close(&ef), rc);
121 CU_ASSERT_EQUAL(rc, 0);
122 }
123
iwfs_exfile_test1_2()124 void iwfs_exfile_test1_2() {
125 iwrc rc = 0;
126 IWFS_EXT f;
127 const char *path = "exfile_test1_2-"; // Temp file prefix
128 IWFS_EXT_OPTS opts = {
129 .file = {
130 .path = path,
131 .omode = IWFS_OTMP | IWFS_OUNLINK
132 }
133 };
134 rc = iwfs_exfile_open(&f, &opts);
135 CU_ASSERT_EQUAL_FATAL(rc, 0);
136
137 IWFS_EXT_STATE state;
138 rc = f.state(&f, &state);
139 CU_ASSERT_EQUAL_FATAL(rc, 0);
140
141 char *tpath = strdup(state.file.opts.path);
142 fprintf(stderr, "\nTmp file: %s\n", tpath);
143
144 IWP_FILE_STAT fstat;
145 rc = iwp_fstat(tpath, &fstat);
146 CU_ASSERT_EQUAL_FATAL(rc, 0);
147
148 rc = f.close(&f);
149 CU_ASSERT_EQUAL_FATAL(rc, 0);
150
151 memset(&fstat, 0, sizeof(fstat));
152 rc = iwp_fstat(tpath, &fstat);
153 CU_ASSERT_EQUAL_FATAL(rc, IW_ERROR_NOT_EXISTS);
154
155 free(tpath);
156 }
157
test_fibo_inc(void)158 void test_fibo_inc(void) {
159 const char *path = "test_fibo_inc.dat";
160 IWFS_EXT ef;
161 IWFS_EXT_OPTS opts = {
162 .file = {
163 .path = path,
164 .lock_mode = IWP_WLOCK,
165 .omode = IWFS_DEFAULT_OMODE | IWFS_OTRUNC
166 },
167 .use_locks = 0,
168 .rspolicy = iw_exfile_szpolicy_fibo
169 };
170 iwrc rc = 0;
171 size_t sp;
172 uint64_t wd = (uint64_t)(-1);
173
174 IWRC(iwfs_exfile_open(&ef, &opts), rc);
175 CU_ASSERT_EQUAL_FATAL(rc, 0);
176
177 // iwrc(*write)(struct IWFS_EXT* f, off_t off, const void *buf, size_t siz,
178 // size_t *sp);
179 IWRC(ef.write(&ef, 0, &wd, 1, &sp), rc);
180 CU_ASSERT_EQUAL_FATAL(rc, 0);
181
182 size_t psize = iwp_alloc_unit();
183 IWP_FILE_STAT fstat;
184 IWRC(iwp_fstat(path, &fstat), rc);
185 CU_ASSERT_EQUAL_FATAL(rc, 0);
186 CU_ASSERT_EQUAL_FATAL(fstat.size, psize);
187
188 IWRC(ef.write(&ef, fstat.size, &wd, 1, &sp), rc);
189 CU_ASSERT_EQUAL_FATAL(rc, 0);
190
191 IWRC(iwp_fstat(path, &fstat), rc);
192 CU_ASSERT_EQUAL_FATAL(rc, 0);
193 CU_ASSERT_EQUAL_FATAL(fstat.size, 2 * psize);
194
195 IWRC(ef.write(&ef, fstat.size, &wd, 1, &sp), rc);
196 CU_ASSERT_EQUAL_FATAL(rc, 0);
197
198 IWRC(iwp_fstat(path, &fstat), rc);
199 CU_ASSERT_EQUAL_FATAL(rc, 0);
200 CU_ASSERT_EQUAL_FATAL(fstat.size, 3 * psize);
201
202 IWRC(ef.write(&ef, fstat.size, &wd, 1, &sp), rc);
203 CU_ASSERT_EQUAL_FATAL(rc, 0);
204
205 IWRC(iwp_fstat(path, &fstat), rc);
206 CU_ASSERT_EQUAL_FATAL(rc, 0);
207 CU_ASSERT_EQUAL_FATAL(fstat.size, 5 * psize);
208
209 IWRC(ef.close(&ef), rc);
210 CU_ASSERT_EQUAL(rc, 0);
211 }
212
test_mmap1(void)213 void test_mmap1(void) {
214 iwrc rc = 0;
215 size_t psize = iwp_alloc_unit();
216 size_t sp;
217 const int dsize = psize * 4;
218 uint8_t *data = malloc(dsize);
219 uint8_t *cdata = malloc(dsize);
220
221 const char *path = "test_mmap1.dat";
222 IWFS_EXT ef;
223 IWFS_EXT_OPTS opts = {.file = {.path = path, .omode = IWFS_OTRUNC}, .use_locks = 0};
224
225 for (int i = 0; i < dsize; ++i) {
226 data[i] = iwu_rand_range(256);
227 }
228 rc = iwfs_exfile_open(&ef, &opts);
229 CU_ASSERT_EQUAL_FATAL(rc, 0);
230
231 rc = ef.add_mmap(&ef, 2 * psize, psize, 0);
232 CU_ASSERT_EQUAL_FATAL(rc, 0);
233
234 rc = ef.add_mmap(&ef, psize, psize, 0);
235 CU_ASSERT_EQUAL_FATAL(rc, 0);
236
237 rc = ef.add_mmap(&ef, 0, psize, 0);
238 CU_ASSERT_EQUAL_FATAL(rc, 0);
239
240 rc = ef.add_mmap(&ef, psize, 2 * psize, 0);
241 CU_ASSERT_EQUAL_FATAL(rc, IWFS_ERROR_MMAP_OVERLAP);
242
243 #ifndef IW_32
244 rc = ef.add_mmap(&ef, 3 * psize, UINT64_MAX, 0);
245 CU_ASSERT_EQUAL_FATAL(rc, 0);
246 #else
247 rc = ef.add_mmap(&ef, 3 * psize, UINT32_MAX >> 1, 0);
248 CU_ASSERT_EQUAL_FATAL(rc, 0);
249 #endif
250
251 rc = ef.write(&ef, psize / 2, data, psize, &sp);
252 CU_ASSERT_EQUAL_FATAL(rc, 0);
253 CU_ASSERT_EQUAL_FATAL(sp, psize);
254
255 rc = ef.read(&ef, psize / 2, cdata, psize, &sp);
256 CU_ASSERT_EQUAL_FATAL(rc, 0);
257 CU_ASSERT_EQUAL_FATAL(sp, psize);
258 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
259
260 for (int i = 0; i < dsize; ++i) {
261 data[i] = iwu_rand_range(256);
262 }
263
264 // iwrc(*remove_mmap)(struct IWFS_EXT* f, off_t off);
265 rc = ef.remove_mmap(&ef, psize);
266 CU_ASSERT_EQUAL_FATAL(rc, 0);
267 rc = ef.write(&ef, psize / 2, data, psize, &sp);
268 CU_ASSERT_EQUAL_FATAL(rc, 0);
269 CU_ASSERT_EQUAL_FATAL(psize, sp);
270
271 rc = ef.read(&ef, psize / 2, cdata, psize, &sp);
272 CU_ASSERT_EQUAL_FATAL(rc, 0);
273 CU_ASSERT_EQUAL_FATAL(psize, sp);
274 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
275
276 for (int i = 0; i < 10; ++i) {
277 rc = ef.write(&ef, psize * i, data, dsize, &sp);
278 CU_ASSERT_EQUAL_FATAL(rc, 0);
279 CU_ASSERT_EQUAL_FATAL(dsize, sp);
280
281 rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
282 CU_ASSERT_EQUAL_FATAL(rc, 0);
283 CU_ASSERT_EQUAL_FATAL(dsize, sp);
284 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
285 }
286
287 for (int i = 0; i < dsize; ++i) {
288 data[i] = iwu_rand_range(256);
289 }
290
291 rc = ef.remove_mmap(&ef, 0);
292 CU_ASSERT_EQUAL_FATAL(rc, 0);
293 for (int i = 0; i < 10; ++i) {
294 rc = ef.write(&ef, psize * i, data, dsize, &sp);
295 CU_ASSERT_EQUAL_FATAL(rc, 0);
296 CU_ASSERT_EQUAL_FATAL(dsize, sp);
297
298 rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
299 CU_ASSERT_EQUAL_FATAL(rc, 0);
300 CU_ASSERT_EQUAL_FATAL(dsize, sp);
301 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
302 }
303
304 for (int i = 0; i < dsize; ++i) {
305 data[i] = iwu_rand_range(256);
306 }
307 rc = ef.remove_mmap(&ef, 2 * psize);
308 CU_ASSERT_EQUAL_FATAL(rc, 0);
309 for (int i = 0; i < 10; ++i) {
310 rc = ef.write(&ef, psize * i, data, dsize, &sp);
311 CU_ASSERT_EQUAL_FATAL(rc, 0);
312 CU_ASSERT_EQUAL_FATAL(dsize, sp);
313
314 rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
315 CU_ASSERT_EQUAL_FATAL(rc, 0);
316 CU_ASSERT_EQUAL_FATAL(dsize, sp);
317 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
318 }
319
320 for (int i = 0; i < dsize; ++i) {
321 data[i] = iwu_rand_range(256);
322 }
323 rc = ef.remove_mmap(&ef, 3 * psize);
324 CU_ASSERT_EQUAL_FATAL(rc, 0);
325 for (int i = 0; i < 10; ++i) {
326 rc = ef.write(&ef, psize * i, data, dsize, &sp);
327 CU_ASSERT_EQUAL_FATAL(rc, 0);
328 CU_ASSERT_EQUAL_FATAL(dsize, sp);
329
330 rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
331 CU_ASSERT_EQUAL_FATAL(rc, 0);
332 CU_ASSERT_EQUAL_FATAL(dsize, sp);
333 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
334 }
335
336 IWRC(ef.close(&ef), rc);
337 CU_ASSERT_EQUAL(rc, 0);
338
339 free(data);
340 free(cdata);
341 }
342
main()343 int main() {
344 CU_pSuite pSuite = NULL;
345
346 /* Initialize the CUnit test registry */
347 if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error();
348
349 /* Add a suite to the registry */
350 pSuite = CU_add_suite("iwfs_test1", init_suite, clean_suite);
351
352 if (NULL == pSuite) {
353 CU_cleanup_registry();
354 return CU_get_error();
355 }
356
357 /* Add the tests to the suite */
358 if ((NULL == CU_add_test(pSuite, "iwfs_exfile_test1", iwfs_exfile_test1)) ||
359 (NULL == CU_add_test(pSuite, "iwfs_exfile_test1_2", iwfs_exfile_test1_2)) ||
360 (NULL == CU_add_test(pSuite, "test_fibo_inc", test_fibo_inc)) ||
361 (NULL == CU_add_test(pSuite, "test_mmap1", test_mmap1))) {
362 CU_cleanup_registry();
363 return CU_get_error();
364 }
365
366 /* Run all tests using the CUnit Basic interface */
367 CU_basic_set_mode(CU_BRM_VERBOSE);
368 CU_basic_run_tests();
369 int ret = CU_get_error() || CU_get_number_of_failures();
370 CU_cleanup_registry();
371 return ret;
372 }
373