1 //
2 /**************************************************************************************************
3 * IOWOW library
4 *
5 * MIT License
6 *
7 * Copyright (c) 2012-2022 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
init_suite()44 int init_suite() {
45 int rc = iw_init();
46 UNLINK();
47 return rc;
48 }
49
clean_suite()50 int clean_suite() {
51 UNLINK();
52 return 0;
53 }
54
iwfs_exfile_test1()55 void iwfs_exfile_test1() {
56 iwrc rc = 0;
57 IWFS_EXT ef;
58
59 const char *path = "iwfs_exfile_test1.dat";
60 IWFS_EXT_OPTS opts = {
61 .file = {
62 .path = path,
63 .lock_mode = IWP_WLOCK,
64 .omode = IWFS_DEFAULT_OMODE | IWFS_OTRUNC
65 },
66 .use_locks = 1
67 };
68 IWRC(iwfs_exfile_open(&ef, &opts), rc);
69 CU_ASSERT_EQUAL_FATAL(rc, 0);
70
71 char data[] = "b069a540-bc92-49ba-95e9-d1a2ee9e8c8f";
72 size_t sp, sp2;
73
74 // iwrc(*write)(struct IWFS_EXT* f, off_t off, const void *buf, size_t siz,
75 // size_t *sp);
76 IWRC(ef.write(&ef, 0, 0, 0, &sp), rc);
77 CU_ASSERT_EQUAL_FATAL(rc, 0);
78 CU_ASSERT_EQUAL(sp, 0);
79
80 IWRC(ef.write(&ef, 1, 0, 0, &sp), rc);
81 CU_ASSERT_EQUAL_FATAL(rc, 0);
82
83 IWP_FILE_STAT fstat;
84 IWRC(iwp_fstat(path, &fstat), rc);
85 CU_ASSERT_EQUAL_FATAL(rc, 0);
86 CU_ASSERT_EQUAL(sp, 0);
87 CU_ASSERT_EQUAL(fstat.size, iwp_alloc_unit());
88
89 IWRC(ef.write(&ef, 1, data, sizeof(data), &sp), rc);
90 CU_ASSERT_EQUAL_FATAL(rc, 0);
91 CU_ASSERT_EQUAL(sp, 37);
92
93 IWRC(ef.close(&ef), rc);
94 CU_ASSERT_EQUAL(rc, 0);
95
96 // Now reopen the file
97
98 opts.file.omode = IWFS_OREAD;
99 IWRC(iwfs_exfile_open(&ef, &opts), rc);
100 CU_ASSERT_EQUAL_FATAL(rc, 0);
101
102 char rdata[37];
103 // iwrc(*read)(struct IWFS_EXT* f, off_t off, void *buf, size_t siz, size_t
104 // *sp);
105 IWRC(ef.read(&ef, 1, rdata, sp, &sp2), rc);
106 CU_ASSERT_EQUAL_FATAL(rc, 0);
107 CU_ASSERT_EQUAL(sp, sp2);
108 CU_ASSERT_FALSE(strncmp(rdata, data, sizeof(data)));
109
110 rc = ef.write(&ef, 1, data, sizeof(data), &sp);
111 CU_ASSERT_EQUAL(IW_ERROR_READONLY, rc);
112
113 size_t ps = iwp_alloc_unit();
114 rc = 0;
115 IWRC(ef.read(&ef, ps - 1, rdata, 2, &sp2), rc);
116 CU_ASSERT_EQUAL_FATAL(rc, 0);
117 CU_ASSERT_EQUAL(sp2, 1);
118
119 IWRC(ef.close(&ef), rc);
120 CU_ASSERT_EQUAL(rc, 0);
121 }
122
iwfs_exfile_test1_2()123 void iwfs_exfile_test1_2() {
124 iwrc rc = 0;
125 IWFS_EXT f;
126 const char *path = "exfile_test1_2-"; // Temp file prefix
127 IWFS_EXT_OPTS opts = {
128 .file = {
129 .path = path,
130 .omode = IWFS_OTMP | IWFS_OUNLINK
131 }
132 };
133 rc = iwfs_exfile_open(&f, &opts);
134 CU_ASSERT_EQUAL_FATAL(rc, 0);
135
136 IWFS_EXT_STATE state;
137 rc = f.state(&f, &state);
138 CU_ASSERT_EQUAL_FATAL(rc, 0);
139
140 char *tpath = strdup(state.file.opts.path);
141 fprintf(stderr, "\nTmp file: %s\n", tpath);
142
143 IWP_FILE_STAT fstat;
144 rc = iwp_fstat(tpath, &fstat);
145 CU_ASSERT_EQUAL_FATAL(rc, 0);
146
147 rc = f.close(&f);
148 CU_ASSERT_EQUAL_FATAL(rc, 0);
149
150 memset(&fstat, 0, sizeof(fstat));
151 rc = iwp_fstat(tpath, &fstat);
152 CU_ASSERT_EQUAL_FATAL(rc, IW_ERROR_NOT_EXISTS);
153
154 free(tpath);
155 }
156
test_fibo_inc(void)157 void test_fibo_inc(void) {
158 const char *path = "test_fibo_inc.dat";
159 IWFS_EXT ef;
160 IWFS_EXT_OPTS opts = {
161 .file = {
162 .path = path,
163 .lock_mode = IWP_WLOCK,
164 .omode = IWFS_DEFAULT_OMODE | IWFS_OTRUNC
165 },
166 .use_locks = 0,
167 .rspolicy = iw_exfile_szpolicy_fibo
168 };
169 iwrc rc = 0;
170 size_t sp;
171 uint64_t wd = (uint64_t) (-1);
172
173 IWRC(iwfs_exfile_open(&ef, &opts), rc);
174 CU_ASSERT_EQUAL_FATAL(rc, 0);
175
176 // iwrc(*write)(struct IWFS_EXT* f, off_t off, const void *buf, size_t siz,
177 // size_t *sp);
178 IWRC(ef.write(&ef, 0, &wd, 1, &sp), rc);
179 CU_ASSERT_EQUAL_FATAL(rc, 0);
180
181 size_t psize = iwp_alloc_unit();
182 IWP_FILE_STAT fstat;
183 IWRC(iwp_fstat(path, &fstat), rc);
184 CU_ASSERT_EQUAL_FATAL(rc, 0);
185 CU_ASSERT_EQUAL_FATAL(fstat.size, psize);
186
187 IWRC(ef.write(&ef, fstat.size, &wd, 1, &sp), rc);
188 CU_ASSERT_EQUAL_FATAL(rc, 0);
189
190 IWRC(iwp_fstat(path, &fstat), rc);
191 CU_ASSERT_EQUAL_FATAL(rc, 0);
192 CU_ASSERT_EQUAL_FATAL(fstat.size, 2 * psize);
193
194 IWRC(ef.write(&ef, fstat.size, &wd, 1, &sp), rc);
195 CU_ASSERT_EQUAL_FATAL(rc, 0);
196
197 IWRC(iwp_fstat(path, &fstat), rc);
198 CU_ASSERT_EQUAL_FATAL(rc, 0);
199 CU_ASSERT_EQUAL_FATAL(fstat.size, 3 * psize);
200
201 IWRC(ef.write(&ef, fstat.size, &wd, 1, &sp), rc);
202 CU_ASSERT_EQUAL_FATAL(rc, 0);
203
204 IWRC(iwp_fstat(path, &fstat), rc);
205 CU_ASSERT_EQUAL_FATAL(rc, 0);
206 CU_ASSERT_EQUAL_FATAL(fstat.size, 5 * psize);
207
208 IWRC(ef.close(&ef), rc);
209 CU_ASSERT_EQUAL(rc, 0);
210 }
211
test_mmap1(void)212 void test_mmap1(void) {
213 iwrc rc = 0;
214 size_t psize = iwp_alloc_unit();
215 size_t sp;
216 const int dsize = psize * 4;
217 uint8_t *data = malloc(dsize);
218 uint8_t *cdata = malloc(dsize);
219
220 const char *path = "test_mmap1.dat";
221 IWFS_EXT ef;
222 IWFS_EXT_OPTS opts = { .file = { .path = path, .omode = IWFS_OTRUNC }, .use_locks = 0 };
223
224 for (int i = 0; i < dsize; ++i) {
225 data[i] = iwu_rand_range(256);
226 }
227 rc = iwfs_exfile_open(&ef, &opts);
228 CU_ASSERT_EQUAL_FATAL(rc, 0);
229
230 rc = ef.add_mmap(&ef, 2 * psize, psize, 0);
231 CU_ASSERT_EQUAL_FATAL(rc, 0);
232
233 rc = ef.add_mmap(&ef, psize, psize, 0);
234 CU_ASSERT_EQUAL_FATAL(rc, 0);
235
236 rc = ef.add_mmap(&ef, 0, psize, 0);
237 CU_ASSERT_EQUAL_FATAL(rc, 0);
238
239 rc = ef.add_mmap(&ef, psize, 2 * psize, 0);
240 CU_ASSERT_EQUAL_FATAL(rc, IWFS_ERROR_MMAP_OVERLAP);
241
242 #ifndef IW_32
243 rc = ef.add_mmap(&ef, 3 * psize, UINT64_MAX, 0);
244 CU_ASSERT_EQUAL_FATAL(rc, 0);
245 #else
246 rc = ef.add_mmap(&ef, 3 * psize, UINT32_MAX >> 1, 0);
247 CU_ASSERT_EQUAL_FATAL(rc, 0);
248 #endif
249
250 rc = ef.write(&ef, psize / 2, data, psize, &sp);
251 CU_ASSERT_EQUAL_FATAL(rc, 0);
252 CU_ASSERT_EQUAL_FATAL(sp, psize);
253
254 rc = ef.read(&ef, psize / 2, cdata, psize, &sp);
255 CU_ASSERT_EQUAL_FATAL(rc, 0);
256 CU_ASSERT_EQUAL_FATAL(sp, psize);
257 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
258
259 for (int i = 0; i < dsize; ++i) {
260 data[i] = iwu_rand_range(256);
261 }
262
263 // iwrc(*remove_mmap)(struct IWFS_EXT* f, off_t off);
264 rc = ef.remove_mmap(&ef, psize);
265 CU_ASSERT_EQUAL_FATAL(rc, 0);
266 rc = ef.write(&ef, psize / 2, data, psize, &sp);
267 CU_ASSERT_EQUAL_FATAL(rc, 0);
268 CU_ASSERT_EQUAL_FATAL(psize, sp);
269
270 rc = ef.read(&ef, psize / 2, cdata, psize, &sp);
271 CU_ASSERT_EQUAL_FATAL(rc, 0);
272 CU_ASSERT_EQUAL_FATAL(psize, sp);
273 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
274
275 for (int i = 0; i < 10; ++i) {
276 rc = ef.write(&ef, psize * i, data, dsize, &sp);
277 CU_ASSERT_EQUAL_FATAL(rc, 0);
278 CU_ASSERT_EQUAL_FATAL(dsize, sp);
279
280 rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
281 CU_ASSERT_EQUAL_FATAL(rc, 0);
282 CU_ASSERT_EQUAL_FATAL(dsize, sp);
283 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
284 }
285
286 for (int i = 0; i < dsize; ++i) {
287 data[i] = iwu_rand_range(256);
288 }
289
290 rc = ef.remove_mmap(&ef, 0);
291 CU_ASSERT_EQUAL_FATAL(rc, 0);
292 for (int i = 0; i < 10; ++i) {
293 rc = ef.write(&ef, psize * i, data, dsize, &sp);
294 CU_ASSERT_EQUAL_FATAL(rc, 0);
295 CU_ASSERT_EQUAL_FATAL(dsize, sp);
296
297 rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
298 CU_ASSERT_EQUAL_FATAL(rc, 0);
299 CU_ASSERT_EQUAL_FATAL(dsize, sp);
300 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
301 }
302
303 for (int i = 0; i < dsize; ++i) {
304 data[i] = iwu_rand_range(256);
305 }
306 rc = ef.remove_mmap(&ef, 2 * psize);
307 CU_ASSERT_EQUAL_FATAL(rc, 0);
308 for (int i = 0; i < 10; ++i) {
309 rc = ef.write(&ef, psize * i, data, dsize, &sp);
310 CU_ASSERT_EQUAL_FATAL(rc, 0);
311 CU_ASSERT_EQUAL_FATAL(dsize, sp);
312
313 rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
314 CU_ASSERT_EQUAL_FATAL(rc, 0);
315 CU_ASSERT_EQUAL_FATAL(dsize, sp);
316 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
317 }
318
319 for (int i = 0; i < dsize; ++i) {
320 data[i] = iwu_rand_range(256);
321 }
322 rc = ef.remove_mmap(&ef, 3 * psize);
323 CU_ASSERT_EQUAL_FATAL(rc, 0);
324 for (int i = 0; i < 10; ++i) {
325 rc = ef.write(&ef, psize * i, data, dsize, &sp);
326 CU_ASSERT_EQUAL_FATAL(rc, 0);
327 CU_ASSERT_EQUAL_FATAL(dsize, sp);
328
329 rc = ef.read(&ef, psize * i, cdata, dsize, &sp);
330 CU_ASSERT_EQUAL_FATAL(rc, 0);
331 CU_ASSERT_EQUAL_FATAL(dsize, sp);
332 CU_ASSERT_EQUAL_FATAL(memcmp(data, cdata, psize), 0);
333 }
334
335 IWRC(ef.close(&ef), rc);
336 CU_ASSERT_EQUAL(rc, 0);
337
338 free(data);
339 free(cdata);
340 }
341
main()342 int main() {
343 CU_pSuite pSuite = NULL;
344
345 /* Initialize the CUnit test registry */
346 if (CUE_SUCCESS != CU_initialize_registry()) {
347 return CU_get_error();
348 }
349
350 /* Add a suite to the registry */
351 pSuite = CU_add_suite("iwfs_test1", init_suite, clean_suite);
352
353 if (NULL == pSuite) {
354 CU_cleanup_registry();
355 return CU_get_error();
356 }
357
358 /* Add the tests to the suite */
359 if ( (NULL == CU_add_test(pSuite, "iwfs_exfile_test1", iwfs_exfile_test1))
360 || (NULL == CU_add_test(pSuite, "iwfs_exfile_test1_2", iwfs_exfile_test1_2))
361 || (NULL == CU_add_test(pSuite, "test_fibo_inc", test_fibo_inc))
362 || (NULL == CU_add_test(pSuite, "test_mmap1", test_mmap1))) {
363 CU_cleanup_registry();
364 return CU_get_error();
365 }
366
367 /* Run all tests using the CUnit Basic interface */
368 CU_basic_set_mode(CU_BRM_VERBOSE);
369 CU_basic_run_tests();
370 int ret = CU_get_error() || CU_get_number_of_failures();
371 CU_cleanup_registry();
372 return ret;
373 }
374