• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "iowow.h"
2 #include "log/iwlog.h"
3 #include "fs/iwfsmfile.h"
4 #include "utils/iwutils.h"
5 
6 #include "iwcfg.h"
7 #include <CUnit/Basic.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 
12 #include "utils/kbtree.h"
13 
14 #define NRECS 10000
15 #define RECSZ (10*1024)
16 
17 #define UNLINK() \
18   unlink("test_fsm_stress.data"); \
19   unlink("test_fsm_stress1.fsm"); \
20   unlink("test_fsm_stress2.fsm")
21 
22 typedef struct SREC {
23   int id;
24   off_t addr;
25   off_t rsz;
26   off_t alc_addr;
27   off_t alc_len;
28   bool freed;
29   bool reallocated;
30 } SREC;
31 
32 #define _srec_cmp(r1, r2) ((r1).id - (r2).id)
33 
KBTREE_INIT(rt,SREC,_srec_cmp)34 KBTREE_INIT(rt, SREC, _srec_cmp)
35 
36 FILE *fstress1;
37 kbtree_t(rt) *rt;
38 
39 int init_suite(void) {
40   UNLINK();
41   int rc = iw_init();
42   RCRET(rc);
43 
44   rt = kb_init(rt, KB_DEFAULT_SIZE);
45 
46   off_t addr = 0;
47   uint64_t ts;
48   rc = iwp_current_time_ms(&ts, false);
49   RCRET(rc);
50   ts = IW_SWAB64(ts);
51   ts >>= 32;
52   iwu_rand_seed(ts);
53 
54   printf("Generating stress data file: test_fsm_stress1.data, random seed: %" PRIu64, ts);
55   fstress1 = fopen("test_fsm_stress.data", "w+");
56   char *buf = malloc(RECSZ + 1);
57   for (int i = 0, j; i < NRECS; ++i) {
58     int rsz = iwu_rand_range(RECSZ + 1);
59     if (rsz < 1) {
60       rsz = 1;
61     }
62     for (j = 0; j < rsz; ++j) {
63       buf[j] = ' ' + iwu_rand_range(95);
64     }
65     buf[j] = '\0';
66     fprintf(fstress1, "%08d:%s\n", i, buf);
67     SREC rec = {
68       .id = i,
69       .addr = addr,
70       .rsz = rsz,
71       .freed = false
72     };
73     addr += (8 + 1 + rsz + 1);
74     kb_putp(rt, rt, &rec);
75   }
76   free(buf);
77   return rc;
78 }
79 
clean_suite(void)80 int clean_suite(void) {
81   if (fstress1) {
82     fclose(fstress1);
83     fstress1 = 0;
84   }
85   kb_destroy(rt, rt);
86   UNLINK();
87   return 0;
88 }
89 
test_stress(char * path,int bpow,bool mmap_all)90 void test_stress(char *path, int bpow, bool mmap_all) {
91   IWFS_FSM fsm;
92   IWFS_FSM_OPTS opts = {
93     .exfile = {
94       .file = {
95         .path = path,
96         .omode = IWFS_OTRUNC
97       }
98     },
99     .hdrlen = 62,
100     .bpow = bpow,
101     .oflags = IWFSM_STRICT,
102     .mmap_all = mmap_all
103   };
104   iwrc rc = iwfs_fsmfile_open(&fsm, &opts);
105   CU_ASSERT_FALSE_FATAL(rc);
106 
107   fprintf(stderr, "\nRunning allocations...\n");
108 
109   char *buf = malloc(2 * RECSZ + 1);
110   for (int i = 0; i < NRECS; ++i) {
111     size_t sp;
112     SREC k = {.id = i};
113     iwfs_fsm_aflags aflags = IWFSM_SOLID_ALLOCATED_SPACE | IWFSM_ALLOC_NO_OVERALLOCATE;
114     uint32_t rop = iwu_rand_u32();
115     if (i > 0 && (!(rop % 3) || !(rop % 5))) {
116       k.id = iwu_rand_range(i);
117       SREC *pr = kb_getp(rt, rt, &k);
118       CU_ASSERT_PTR_NOT_NULL_FATAL(pr);
119       if (!pr->freed) {
120         if ((rop % 3)) { // deallocate previous
121           //fprintf(stderr, "%05d D %ld:%ld\n", pr->id, pr->alc_addr, pr->alc_len);
122           pr->freed = true;
123           rc = fsm.deallocate(&fsm, pr->alc_addr, pr->alc_len);
124           CU_ASSERT_FALSE_FATAL(rc);
125         } else if (!pr->reallocated && !(rop % 5)) { // reallocate previous
126           //fprintf(stderr, "%05d R %ld:%ld\n", pr->id, pr->alc_addr, pr->alc_len);
127           pr->reallocated = true;
128           uint32_t nlen = iwu_rand_range(2 * pr->rsz + 1);
129           if (nlen < 1) {
130             nlen = 1;
131           }
132           rc = fsm.reallocate(&fsm, nlen, &pr->alc_addr, &pr->alc_len, IWFSM_SOLID_ALLOCATED_SPACE);
133           CU_ASSERT_FALSE_FATAL(rc);
134           if (pr->alc_len > pr->rsz) {
135             rc = fsm.read(&fsm, pr->alc_addr, buf, pr->rsz, &sp);
136             CU_ASSERT_FALSE_FATAL(rc);
137             CU_ASSERT_EQUAL_FATAL(pr->rsz, sp);
138             off_t wsz = pr->alc_len - pr->rsz;
139             while (wsz > 0) {
140               int wc = MIN(wsz, pr->rsz);
141               rc = fsm.write(&fsm, pr->alc_addr + pr->alc_len - wsz, buf, wc, &sp);
142               CU_ASSERT_FALSE_FATAL(rc);
143               CU_ASSERT_EQUAL_FATAL(wc, sp);
144               wsz -= wc;
145             }
146           }
147         }
148       }
149     }
150 
151     k.id = i;
152     SREC *r = kb_getp(rt, rt, &k);
153     CU_ASSERT_PTR_NOT_NULL_FATAL(r);
154     fseek(fstress1, r->addr + 8 + 1, SEEK_SET);
155     fread(buf, r->rsz, 1, fstress1);
156     buf[r->rsz + 1] = '\0';
157 
158     rc = fsm.allocate(&fsm, r->rsz, &r->alc_addr, &r->alc_len, aflags);
159     //fprintf(stderr, "%05d A %ld:%ld\n", i, r->alc_addr, r->alc_len);
160     CU_ASSERT_FALSE_FATAL(rc);
161     CU_ASSERT_TRUE_FATAL(r->alc_len >= r->rsz);
162     rc = fsm.write(&fsm, r->alc_addr, buf, r->rsz, &sp);
163     CU_ASSERT_FALSE_FATAL(rc);
164     CU_ASSERT_EQUAL_FATAL(sp, r->rsz);
165 
166     if (r->alc_len > r->rsz) {
167       off_t wsz = r->alc_len - r->rsz;
168       while (wsz > 0) {
169         int wc = MIN(wsz, r->rsz);
170         rc = fsm.write(&fsm, r->alc_addr + r->alc_len - wsz, buf, wc, &sp);
171         CU_ASSERT_FALSE_FATAL(rc);
172         CU_ASSERT_EQUAL_FATAL(wc, sp);
173         wsz -= wc;
174       }
175     }
176   }
177   CU_ASSERT_FALSE_FATAL(fsm.close(&fsm));
178 
179   fprintf(stderr, "Checking data\n");
180   opts.exfile.file.omode = 0;
181   rc = iwfs_fsmfile_open(&fsm, &opts);
182   CU_ASSERT_FALSE_FATAL(rc);
183 
184   char *buf2 = malloc(2 * RECSZ + 1);
185   for (int i = 0; i < NRECS; ++i) {
186     size_t sp;
187     SREC k = {.id = i};
188     SREC *r = kb_getp(rt, rt, &k);
189     CU_ASSERT_PTR_NOT_NULL_FATAL(r);
190     if (r->freed) {
191       continue;
192     }
193     CU_ASSERT_TRUE(r->alc_len <= 2 * RECSZ + 1);
194     fseek(fstress1, r->addr + 8 + 1, SEEK_SET);
195     fread(buf, r->rsz, 1, fstress1);
196     buf[r->rsz + 1] = '\0';
197 
198     off_t rn = MIN(r->rsz, r->alc_len);
199     if (r->alc_len < r->rsz) {
200       CU_ASSERT_TRUE_FATAL(r->reallocated);
201     }
202     memset(buf2, 0, rn); // 20736
203     rc = fsm.read(&fsm, r->alc_addr, buf2, rn, &sp);
204     CU_ASSERT_FALSE_FATAL(rc);
205     CU_ASSERT_EQUAL_FATAL(rn, sp);
206     int ri = memcmp(buf, buf2, rn);
207     CU_ASSERT_EQUAL_FATAL(ri, 0);
208 
209     if (rn < r->alc_len) {
210       while (rn < r->alc_len) {
211         off_t rz = MIN(r->alc_len - rn, r->rsz);
212         rc = fsm.read(&fsm, r->alc_addr + rn, buf2, rz, &sp);
213         CU_ASSERT_FALSE_FATAL(rc);
214         ri = memcmp(buf, buf2, rz);
215         CU_ASSERT_EQUAL_FATAL(ri, 0);
216         rn += rz;
217       }
218     }
219   }
220   free(buf2);
221   free(buf);
222   CU_ASSERT_FALSE_FATAL(fsm.close(&fsm));
223 }
224 
test_stress1()225 static void test_stress1() {
226   test_stress("test_fsm_stress1.fsm", 6, true);
227 }
228 
test_stress2()229 static void test_stress2() {
230   test_stress("test_fsm_stress2.fsm", 6, false);
231 }
232 
main()233 int main() {
234   CU_pSuite pSuite = NULL;
235 
236   /* Initialize the CUnit test registry */
237   if (CUE_SUCCESS != CU_initialize_registry())
238     return CU_get_error();
239 
240   /* Add a suite to the registry */
241   pSuite = CU_add_suite("iwfs_test3", init_suite, clean_suite);
242 
243   if (NULL == pSuite) {
244     CU_cleanup_registry();
245     return CU_get_error();
246   }
247 
248   /* Add the tests to the suite */
249   if (
250       (NULL == CU_add_test(pSuite, "test_stress1", test_stress1)) ||
251       (NULL == CU_add_test(pSuite, "test_stress2", test_stress2))
252      ) {
253     CU_cleanup_registry();
254     return CU_get_error();
255   }
256 
257   /* Run all tests using the CUnit Basic interface */
258   CU_basic_set_mode(CU_BRM_VERBOSE);
259   CU_basic_run_tests();
260   int ret = CU_get_error() || CU_get_number_of_failures();
261   CU_cleanup_registry();
262   return ret;
263 }
264