ringfs
 All Data Structures Files Functions Variables Enumerations Enumerator Macros Groups Pages
tests.c
Go to the documentation of this file.
1 /*
2  * Copyright © 2014 Kosma Moczek <kosma@cloudyourcar.com>
3  * This program is free software. It comes without any warranty, to the extent
4  * permitted by applicable law. You can redistribute it and/or modify it under
5  * the terms of the Do What The Fuck You Want To Public License, Version 2, as
6  * published by Sam Hocevar. See the COPYING file for more details.
7  */
8 
9 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <stdbool.h>
14 #include <string.h>
15 #include <check.h>
16 
17 #include "ringfs.h"
18 #include "flashsim.h"
19 
20 START_TEST(test_flashsim)
21 {
22  printf("# test_flashsim\n");
23 
24  struct flashsim *sim = flashsim_open("test.sim", 1024, 16);
25  uint8_t buf[48];
26  uint8_t data[16];
27 
28  flashsim_sector_erase(sim, 0);
29  flashsim_sector_erase(sim, 16);
30  flashsim_sector_erase(sim, 32);
31 
32  memset(data, 0x5a, 16);
33  flashsim_program(sim, 16, data, 16);
34 
35  flashsim_read(sim, 0, buf, 48);
36  for (int i=0; i<16; i++)
37  ck_assert_int_eq(buf[i], 0xff);
38  for (int i=16; i<32; i++)
39  ck_assert_int_eq(buf[i], 0x5a);
40  for (int i=32; i<48; i++)
41  ck_assert_int_eq(buf[i], 0xff);
42 
43  memset(data, 0x01, 16);
44  flashsim_program(sim, 0, data, 16);
45  memset(data, 0x10, 16);
46  flashsim_program(sim, 32, data, 16);
47  flashsim_sector_erase(sim, 16);
48 
49  flashsim_read(sim, 0, buf, 48);
50  for (int i=0; i<16; i++)
51  ck_assert_int_eq(buf[i], 0x01);
52  for (int i=16; i<32; i++)
53  ck_assert_int_eq(buf[i], 0xff);
54  for (int i=32; i<48; i++)
55  ck_assert_int_eq(buf[i], 0x10);
56 
57  free(sim);
58 }
59 END_TEST
60 
61 static struct flashsim *sim;
62 
63 static int op_sector_erase(int address)
64 {
65  flashsim_sector_erase(sim, address);
66  return 0;
67 }
68 
69 static ssize_t op_program(int address, const void *data, size_t size)
70 {
71  flashsim_program(sim, address, data, size);
72  return size;
73 }
74 
75 static ssize_t op_read(int address, void *data, size_t size)
76 {
77  flashsim_read(sim, address, data, size);
78  return size;
79 }
80 
81 static const struct ringfs_flash_partition flash = {
82  .sector_size = 65536,
83  .sector_offset = 3,
84  .sector_count = 13,
85 
86  .sector_erase = op_sector_erase,
87  .program = op_program,
88  .read = op_read,
89 };
90 
91 START_TEST(test_ringfs_format)
92 {
93  printf("# test_ringfs_format\n");
94  sim = flashsim_open("ringfs_format.sim", 65536*16, 65536);
95 
96  struct ringfs fs1;
97  printf("## ringfs_init()\n");
98  ringfs_init(&fs1, &flash, 0x00000042, 4);
99  printf("## ringfs_format()\n");
100  ringfs_format(&fs1);
101 }
102 END_TEST
103 
104 START_TEST(test_ringfs_scan)
105 {
106  printf("# test_ringfs_scan\n");
107  sim = flashsim_open("ringfs_scan.sim", 65536*16, 65536);
108 
109  /* first format a filesystem */
110  struct ringfs fs1;
111  printf("## ringfs_init()\n");
112  ringfs_init(&fs1, &flash, 0x00000042, 4);
113  printf("## ringfs_format()\n");
114  ringfs_format(&fs1);
115 
116  /* now try to scan it */
117  struct ringfs fs2;
118  printf("## ringfs_init()\n");
119  ringfs_init(&fs2, &flash, 0x00000042, 4);
120  printf("## ringfs_scan()\n");
121  ck_assert(ringfs_scan(&fs2) == 0);
122 
123  /* this is an empty FS, should start with this: */
124  ck_assert_int_eq(fs2.slots_per_sector, (65536-8)/(4+4));
125  ck_assert_int_eq(fs2.read.sector, 0);
126  ck_assert_int_eq(fs2.read.slot, 0);
127  ck_assert_int_eq(fs2.write.sector, 0);
128  ck_assert_int_eq(fs2.write.slot, 0);
129  ck_assert_int_eq(fs2.cursor.sector, 0);
130  ck_assert_int_eq(fs2.cursor.slot, 0);
131 
132  /* now insert some objects */
133  ck_assert(ringfs_append(&fs2, (int[]) { 0x11 }) == 0);
134  ck_assert(ringfs_append(&fs2, (int[]) { 0x22 }) == 0);
135  ck_assert(ringfs_append(&fs2, (int[]) { 0x33 }) == 0);
136 
137  /* rescan */
138  printf("## ringfs_scan()\n");
139  ck_assert(ringfs_scan(&fs2) == 0);
140 
141  /* make sure the objects are there */
142  ck_assert(ringfs_count_exact(&fs2) == 3);
143 
144  /* scan should fail if we supply a different version */
145  struct ringfs fs3;
146  printf("## ringfs_init()\n");
147  ringfs_init(&fs3, &flash, 0x00000043, 4);
148  printf("## ringfs_scan()\n");
149  ck_assert(ringfs_scan(&fs3) != 0);
150 }
151 END_TEST
152 
153 START_TEST(test_ringfs_append)
154 {
155  printf("# test_ringfs_append\n");
156  sim = flashsim_open("ringfs_append.sim", 65536*16, 65536);
157 
158  /* first format a filesystem */
159  struct ringfs fs;
160  printf("## ringfs_init()\n");
161  ringfs_init(&fs, &flash, 0x00000042, 4);
162  printf("## ringfs_format()\n");
163  ringfs_format(&fs);
164 
165  /* now we're brave and we write some data */
166  for (int i=0; i<3; i++) {
167  printf("## ringfs_append()\n");
168  ringfs_append(&fs, (int[]) { 0x11*(i+1) });
169 
170  /* make sure the write head has advanced */
171  ck_assert_int_eq(fs.write.slot, i+1);
172  }
173 
174  /* now we fetch at it. */
175  int obj;
176  for (int i=0; i<3; i++) {
177  printf("## ringfs_fetch()\n");
178  ck_assert(ringfs_fetch(&fs, &obj) == 0);
179  ck_assert_int_eq(obj, 0x11*(i+1));
180 
181  /* make sure the cursor head has advanced */
182  ck_assert_int_eq(fs.cursor.slot, i+1);
183  }
184  /* there should be no data left */
185  ck_assert(ringfs_fetch(&fs, &obj) < 0);
186 
187  /* test the rewind. */
188  ck_assert(ringfs_rewind(&fs) == 0);
189  ck_assert_int_eq(fs.cursor.slot, 0);
190 
191  /* try to read the objects once again. */
192  for (int i=0; i<3; i++) {
193  printf("## ringfs_fetch()\n");
194  ck_assert(ringfs_fetch(&fs, &obj) == 0);
195  ck_assert_int_eq(obj, 0x11*(i+1));
196  }
197 }
198 END_TEST
199 
200 START_TEST(test_ringfs_discard)
201 {
202  printf("# test_ringfs_discard\n");
203  sim = flashsim_open("ringfs_discard.sim", 65536*16, 65536);
204 
205  struct ringfs fs;
206  printf("## ringfs_init()\n");
207  ringfs_init(&fs, &flash, 0x00000042, 4);
208  printf("## ringfs_format()\n");
209  ringfs_format(&fs);
210 
211  /* write some records */
212  for (int i=0; i<4; i++) {
213  printf("## ringfs_append()\n");
214  ringfs_append(&fs, (int[]) { 0x11*(i+1) });
215  }
216  /* read some of them */
217  int obj;
218  for (int i=0; i<2; i++) {
219  printf("## ringfs_fetch()\n");
220  ck_assert(ringfs_fetch(&fs, &obj) == 0);
221  ck_assert_int_eq(obj, 0x11*(i+1));
222  }
223  /* discard whatever was read */
224  ck_assert(ringfs_discard(&fs) == 0);
225  /* make sure we're consistent */
226  ck_assert_int_eq(fs.read.slot, 2);
227  ck_assert_int_eq(fs.cursor.slot, 2);
228  ck_assert_int_eq(fs.write.slot, 4);
229 
230  /* read the rest of the records */
231  for (int i=2; i<4; i++) {
232  printf("## ringfs_fetch()\n");
233  ck_assert(ringfs_fetch(&fs, &obj) == 0);
234  ck_assert_int_eq(obj, 0x11*(i+1));
235  }
236  /* discard them */
237  ck_assert(ringfs_discard(&fs) == 0);
238  ck_assert_int_eq(fs.read.slot, 4);
239  ck_assert_int_eq(fs.cursor.slot, 4);
240  ck_assert_int_eq(fs.write.slot, 4);
241 }
242 END_TEST
243 
244 START_TEST(test_ringfs_capacity)
245 {
246  printf("# test_ringfs_capacity\n");
247  sim = flashsim_open("ringfs_capacity.sim", 65536*16, 65536);
248 
249  struct ringfs fs;
250  ringfs_init(&fs, &flash, 0x00000042, 4);
251 
252  int slots_per_sector = (65536-8)/(4+4);
253  int sectors = 13;
254  ck_assert_int_eq(ringfs_capacity(&fs), (sectors-1) * slots_per_sector);
255 }
256 END_TEST
257 
258 START_TEST(test_ringfs_count)
259 {
260  printf("# test_ringfs_count\n");
261  sim = flashsim_open("ringfs_count.sim", 65536*16, 65536);
262 
263  int obj;
264  struct ringfs fs;
265  ringfs_init(&fs, &flash, 0x00000042, 4);
266  ringfs_format(&fs);
267  ck_assert(ringfs_count_exact(&fs) == 0);
268 
269  printf("## write some records\n");
270  for (int i=0; i<10; i++)
271  ringfs_append(&fs, (int[]) { 0x11*(i+1) });
272  ck_assert_int_eq(ringfs_count_exact(&fs), 10);
273  ck_assert_int_eq(ringfs_count_estimate(&fs), 10);
274 
275  printf("## rescan\n");
276  ck_assert(ringfs_scan(&fs) == 0);
277  ck_assert_int_eq(ringfs_count_exact(&fs), 10);
278  ck_assert_int_eq(ringfs_count_estimate(&fs), 10);
279 
280  printf("## append more records\n");
281  for (int i=10; i<13; i++)
282  ringfs_append(&fs, (int[]) { 0x11*(i+1) });
283  ck_assert_int_eq(ringfs_count_exact(&fs), 13);
284  ck_assert_int_eq(ringfs_count_estimate(&fs), 13);
285 
286  printf("## fetch some objects without discard\n");
287  for (int i=0; i<4; i++) {
288  ck_assert(ringfs_fetch(&fs, &obj) == 0);
289  ck_assert_int_eq(obj, 0x11*(i+1));
290  }
291  ck_assert_int_eq(ringfs_count_exact(&fs), 13);
292  ck_assert_int_eq(ringfs_count_estimate(&fs), 13);
293 
294  printf("## rescan\n");
295  ck_assert(ringfs_scan(&fs) == 0);
296  ck_assert_int_eq(ringfs_count_exact(&fs), 13);
297  ck_assert_int_eq(ringfs_count_estimate(&fs), 13);
298 
299  printf("## fetch some objects with discard\n");
300  for (int i=0; i<4; i++) {
301  ck_assert(ringfs_fetch(&fs, &obj) == 0);
302  ck_assert_int_eq(obj, 0x11*(i+1));
303  }
304  ck_assert_int_eq(ringfs_count_exact(&fs), 13);
305  ck_assert_int_eq(ringfs_count_estimate(&fs), 13);
306  ck_assert(ringfs_discard(&fs) == 0);
307  ck_assert_int_eq(ringfs_count_exact(&fs), 9);
308  ck_assert_int_eq(ringfs_count_estimate(&fs), 9);
309 
310  printf("## fill the segment\n");
311  int count = fs.slots_per_sector - 4;
312  for (int i=0; i<count; i++)
313  ringfs_append(&fs, (int[]) { 0x42 });
314  ck_assert_int_eq(ringfs_count_exact(&fs), 9+count);
315  ck_assert_int_eq(ringfs_count_estimate(&fs), 9+count);
316 
317  printf("## extra synthetic tests for estimation\n");
318  /* wrapping around */
319  fs.read = (struct ringfs_loc) { 12, fs.slots_per_sector - 1 };
320  fs.write = (struct ringfs_loc) { 0, 0 };
321  ck_assert_int_eq(ringfs_count_estimate(&fs), 1);
322 }
323 END_TEST
324 
325 Suite *ringfs_suite(void)
326 {
327  Suite *s = suite_create ("ringfs");
328  TCase *tc;
329 
330  tc = tcase_create("flashsim");
331  tcase_add_test(tc, test_flashsim);
332  suite_add_tcase(s, tc);
333 
334  tc = tcase_create("ringfs");
335  tcase_add_test(tc, test_ringfs_format);
336  tcase_add_test(tc, test_ringfs_scan);
337  tcase_add_test(tc, test_ringfs_append);
338  tcase_add_test(tc, test_ringfs_discard);
339  tcase_add_test(tc, test_ringfs_capacity);
340  tcase_add_test(tc, test_ringfs_count);
341  suite_add_tcase(s, tc);
342 
343  return s;
344 }
345 
346 int main()
347 {
348  int number_failed;
349  Suite *s = ringfs_suite();
350  SRunner *sr = srunner_create(s);
351  srunner_run_all(sr, CK_NORMAL);
352  number_failed = srunner_ntests_failed(sr);
353  srunner_free(sr);
354  return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
355 }
356 
357 /* vim: set ts=4 sw=4 et: */
int sector_size
Sector size, in bytes.
Definition: ringfs.h:25
int ringfs_format(struct ringfs *fs)
Format the flash memory.
Definition: ringfs.c:153
void flashsim_program(struct flashsim *sim, int addr, const uint8_t *buf, int len)
Definition: flashsim.c:86
struct ringfs_loc write
Definition: ringfs.h:73
int main()
Definition: tests.c:346
int ringfs_capacity(struct ringfs *fs)
Calculate maximum RingFS capacity.
Definition: ringfs.c:278
int ringfs_init(struct ringfs *fs, const struct ringfs_flash_partition *flash, uint32_t version, int object_size)
Initialize a RingFS instance.
Definition: ringfs.c:139
void flashsim_read(struct flashsim *sim, int addr, uint8_t *buf, int len)
Definition: flashsim.c:70
Flash memory+parition descriptor.
Definition: ringfs.h:23
void flashsim_sector_erase(struct flashsim *sim, int addr)
Definition: flashsim.c:55
struct flashsim * flashsim_open(const char *name, int size, int sector_size)
Definition: flashsim.c:36
struct ringfs_loc cursor
Definition: ringfs.h:74
int ringfs_count_exact(struct ringfs *fs)
Calculate exact object count.
Definition: ringfs.c:291
int slots_per_sector
Definition: ringfs.h:69
int ringfs_count_estimate(struct ringfs *fs)
Calculate approximate object count.
Definition: ringfs.c:283
static ssize_t op_read(int address, void *data, size_t size)
Definition: tests.c:75
int ringfs_discard(struct ringfs *fs)
Discard all fetched objects up to the read cursor.
Definition: ringfs.c:384
RingFS instance.
Definition: ringfs.h:63
int ringfs_scan(struct ringfs *fs)
Scan the flash memory for a valid filesystem.
Definition: ringfs.c:174
static END_TEST struct flashsim * sim
Definition: tests.c:61
int ringfs_fetch(struct ringfs *fs, void *object)
Fetch next object from the ring, oldest-first.
Definition: ringfs.c:363
struct ringfs_loc read
Definition: ringfs.h:72
int size
Definition: flashsim.c:30
START_TEST(test_flashsim)
Definition: tests.c:20
static const struct ringfs_flash_partition flash
Definition: tests.c:81
END_TEST Suite * ringfs_suite(void)
Definition: tests.c:325
static ssize_t op_program(int address, const void *data, size_t size)
Definition: tests.c:69
int ringfs_rewind(struct ringfs *fs)
Rewind the read cursor back to the oldest object.
Definition: ringfs.c:394
static int op_sector_erase(int address)
Definition: tests.c:63
int ringfs_append(struct ringfs *fs, const void *object)
Append an object at the end of the ring.
Definition: ringfs.c:310