1 #include <r_util.h>
2 #include <r_io.h>
3 #include <stdlib.h>
4 #include "minunit.h"
5
test_buf(RBuffer * b)6 bool test_buf(RBuffer *b) {
7 ut8 buffer[1024] = { 0 };
8 const char *content = "Something To\nSay Here..";
9 const int length = 23;
10 int r;
11
12 ut64 buf_sz = r_buf_size (b);
13 mu_assert_eq (buf_sz, length, "file size should be computed");
14
15 r = r_buf_read (b, buffer, length);
16 mu_assert_eq (r, length, "r_buf_read_at failed");
17 mu_assert_memeq (buffer, (ut8 *)content, length, "r_buf_read_at has corrupted content");
18
19 const char *s = "This is a new content";
20 const size_t sl = strlen (s);
21 bool res = r_buf_set_bytes (b, (ut8 *)s, sl);
22 mu_assert ("New content should be written", res);
23
24 r_buf_seek (b, 0, R_BUF_SET);
25 r = r_buf_read (b, buffer, sl);
26 mu_assert_eq (r, sl, "r_buf_read_at failed");
27 mu_assert_memeq (buffer, (ut8 *)s, sl, "r_buf_read_at has corrupted content");
28
29 r_buf_seek (b, 0, R_BUF_SET);
30 r = r_buf_read (b, buffer, 3);
31 mu_assert_eq (r, 3, "r_buf_read_at failed");
32 mu_assert_memeq (buffer, (ut8 *)"Thi", 3, "r_buf_read_at has corrupted content");
33 r = r_buf_read (b, buffer, 5);
34 mu_assert_eq (r, 5, "r_buf_read_at failed");
35 mu_assert_memeq (buffer, (ut8 *)"s is ", 5, "r_buf_read_at has corrupted content");
36
37 const char *s2 = ", hello world";
38 const size_t s2l = strlen (s2);
39 res = r_buf_append_string (b, s2);
40 mu_assert ("string should be appended", res);
41
42 buf_sz = r_buf_size (b);
43 mu_assert_eq (buf_sz, sl + s2l, "file size should be computed");
44
45 res = r_buf_resize (b, 10);
46 mu_assert ("file should be resized", res);
47 buf_sz = r_buf_size (b);
48 mu_assert_eq (buf_sz, 10, "file size should be 10");
49
50 const int rl = r_buf_read_at (b, 1, buffer, sizeof (buffer));
51 mu_assert_eq (rl, 9, "only 9 bytes can be read from offset 1");
52 mu_assert_memeq (buffer, (ut8 *)"his is a ", 9, "read right bytes from offset 1");
53
54 r_buf_set_bytes (b, (ut8 *)"World", strlen ("World"));
55 char *base = r_buf_to_string (b);
56 mu_assert_notnull (base, "string should be there");
57 mu_assert_streq (base, "World", "World there");
58 free (base);
59
60 const char *s3 = "Hello ";
61 res = r_buf_prepend_bytes (b, (const ut8 *)s3, strlen (s3));
62 mu_assert ("bytes should be prepended", res);
63 char *st = r_buf_to_string (b);
64 mu_assert_notnull (st, "string should be there");
65 mu_assert_streq (st, "Hello World", "hello world there");
66 free (st);
67
68 r_buf_insert_bytes (b, 5, (ut8 *)",", 1);
69 char *st2 = r_buf_to_string (b);
70 mu_assert_notnull (st2, "string should be there");
71 mu_assert_streq (st2, "Hello, World", "comma inserted");
72 free (st2);
73
74 r = r_buf_seek (b, 0x100, R_BUF_SET);
75 mu_assert_eq (r, 0x100, "moving seek out of current length");
76 r = r_buf_write (b, (ut8 *)"mydata", 6);
77 mu_assert_eq (r, 6, "writes 6 bytes");
78 r = r_buf_read_at (b, 0xf0, buffer, sizeof (buffer));
79 mu_assert_eq (r, 0x16, "read 16 bytes at the end of gap and new data");
80 mu_assert_memeq (buffer, (ut8 *)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, "first bytes should be 0");
81 mu_assert_memeq (buffer + 0x10, (ut8 *)"mydata", 6, "then there is mydata");
82
83 r_buf_set_bytes (b, (ut8 *)"Hello", 5);
84 RBuffer *sec_buf = r_buf_new_with_bytes ((ut8 *)" second", 7);
85 res = r_buf_append_buf (b, sec_buf);
86 mu_assert ("append buf should succeed", res);
87 char *st3 = r_buf_to_string (b);
88 mu_assert_streq (st3, "Hello second", "append buf correctly");
89 free (st3);
90 r_buf_free (sec_buf);
91
92 sec_buf = r_buf_new_with_bytes ((ut8 *)"123456789", 9);
93 res = r_buf_append_buf_slice (b, sec_buf, 5, 3);
94 mu_assert ("append buf slice should succeed", res);
95 char *st4 = r_buf_to_string (b);
96 mu_assert_streq (st4, "Hello second678", "append buf slice correctly");
97 free (st4);
98 r_buf_free (sec_buf);
99
100 return MU_PASSED;
101 }
102
test_r_buf_file(void)103 bool test_r_buf_file(void) {
104 RBuffer *b;
105 char *filename = "r2-XXXXXX";
106 const char *content = "Something To\nSay Here..";
107 const int length = 23;
108
109 // Prepare file
110 int fd = r_file_mkstemp ("", &filename);
111 mu_assert_neq ((ut64)fd, (ut64)-1, "mkstemp failed...");
112 write (fd, content, length);
113 close (fd);
114
115 b = r_buf_new_file (filename, O_RDWR, 0);
116 mu_assert_notnull (b, "r_buf_new_file failed");
117
118 if (test_buf (b) != MU_PASSED) {
119 mu_fail ("test failed");
120 }
121
122 // Cleanup
123 r_buf_free (b);
124 unlink (filename);
125 free (filename);
126 mu_end;
127 }
128
test_r_buf_bytes(void)129 bool test_r_buf_bytes(void) {
130 RBuffer *b;
131 const char *content = "Something To\nSay Here..";
132 const int length = 23;
133
134 b = r_buf_new_with_bytes ((const ut8 *)content, length);
135 mu_assert_notnull (b, "r_buf_new_with_bytes failed");
136
137 if (test_buf (b) != MU_PASSED) {
138 mu_fail ("test failed");
139 }
140
141 // Cleanup
142 r_buf_free (b);
143 mu_end;
144 }
145
test_r_buf_mmap(void)146 bool test_r_buf_mmap(void) {
147 RBuffer *b;
148 char *filename = "r2-XXXXXX";
149 const char *content = "Something To\nSay Here..";
150 const int length = 23;
151
152 // Prepare file
153 int fd = r_file_mkstemp ("", &filename);
154 mu_assert_neq ((long long)fd, -1LL, "mkstemp failed...");
155 write (fd, content, length);
156 close (fd);
157
158 b = r_buf_new_mmap (filename, R_PERM_RW);
159 mu_assert_notnull (b, "r_buf_new_mmap failed");
160
161 if (test_buf (b) != MU_PASSED) {
162 unlink(filename);
163 mu_fail ("test failed");
164 }
165
166 // Cleanup
167 r_buf_free (b);
168 unlink(filename);
169 free (filename);
170 mu_end;
171 }
172
test_r_buf_io(void)173 bool test_r_buf_io(void) {
174 RBuffer *b;
175 const char *content = "Something To\nSay Here..";
176 const int length = 23;
177
178 RIO *io = r_io_new ();
179 RIODesc *desc = r_io_open_at (io, "file:///tmp/r-buf-io.test", R_PERM_RW | R_PERM_CREAT, 0644, 0);
180 mu_assert_notnull (desc, "file should be opened for writing");
181
182 bool res = r_io_write_at (io, 0, (ut8 *)content, length);
183 mu_assert ("initial content should be written", res);
184
185 RIOBind bnd;
186 r_io_bind (io, &bnd);
187
188 b = r_buf_new_with_io(&bnd, desc->fd);
189 mu_assert_notnull (b, "r_buf_new_file failed");
190
191 if (test_buf (b) != MU_PASSED) {
192 mu_fail ("test failed");
193 }
194
195 // Cleanup
196 r_buf_free (b);
197 r_io_close (io);
198 r_io_free (io);
199 mu_end;
200 }
201
test_r_buf_sparse(void)202 bool test_r_buf_sparse(void) {
203 RBuffer *b;
204 const char *content = "Something To\nSay Here..";
205 const int length = 23;
206
207 b = r_buf_new_sparse (0);
208 mu_assert_notnull (b, "r_buf_new_file failed");
209
210 r_buf_write (b, (ut8 *)content, length);
211 r_buf_seek (b, 0, R_BUF_SET);
212
213 if (test_buf (b) != MU_PASSED) {
214 mu_fail ("test failed");
215 }
216
217 // Cleanup
218 r_buf_free (b);
219 mu_end;
220 }
221
test_r_buf_sparse2(void)222 bool test_r_buf_sparse2(void) {
223 RBuffer *b = r_buf_new_sparse (0xff);
224 r_buf_write (b, (ut8 *)"aaaa", 4);
225 r_buf_write (b, (ut8 *)"bbbbb", 5);
226 r_buf_write (b, (ut8 *)"cccccc", 6);
227 r_buf_write_at (b, 2, (ut8 *)"D", 1);
228 r_buf_write_at (b, 7, (ut8 *)"EEE", 3);
229
230 ut8 tmp[20];
231 int r = r_buf_read_at (b, 0, tmp, sizeof (tmp));
232 mu_assert_eq (r, 15, "read only 15 bytes");
233 mu_assert_memeq (tmp, (ut8 *)"aaDabbbEEEccccc", 15, "read the right bytes");
234
235 bool res = r_buf_resize (b, 0);
236 mu_assert ("resized to 0", res);
237
238 r = r_buf_read_at (b, 0, tmp, sizeof (tmp));
239 mu_assert_eq (r, 0, "nothing to read");
240
241 r_buf_write_at (b, 3, (ut8 *)"aaaa", 4);
242 r = r_buf_read_at (b, 0, tmp, sizeof (tmp));
243 mu_assert_eq (r, 7, "read the initial 0xff bytes");
244 mu_assert_memeq (tmp, (ut8 *)"\xff\xff\xff\x61\x61\x61\x61", 7, "right 7 bytes");
245
246 res = r_buf_resize (b, 10);
247 mu_assert ("resized to 10", res);
248
249 ut64 sz = r_buf_size (b);
250 mu_assert_eq (sz, 10, "size is 10");
251 r = r_buf_read_at (b, 0, tmp, sizeof (tmp));
252 mu_assert_eq (r, 10, "read the initial/final 0xff bytes");
253 mu_assert_memeq (tmp, (ut8 *)"\xff\xff\xff\x61\x61\x61\x61\xff\xff\xff", 10, "right 10 bytes");
254
255 r = r_buf_write_at (b, 0x100, (ut8 *)"ABCDEF", 6);
256 mu_assert_eq (r, 6, "write 6 bytes at 0x100");
257 r = r_buf_read_at (b, 0xfe, tmp, sizeof (tmp));
258 mu_assert_eq (r, 8, "read 8 bytes");
259 mu_assert_memeq (tmp, (ut8 *)"\xff\xff\x41\x42\x43\x44\x45\x46", 8, "right bytes");
260
261 sz = r_buf_size (b);
262 mu_assert_eq (sz, 0x106, "size is 0x106");
263
264 r_buf_free (b);
265 mu_end;
266 }
267
test_r_buf_bytes_steal(void)268 bool test_r_buf_bytes_steal(void) {
269 RBuffer *b;
270 const char *content = "Something To\nSay Here..";
271 const int length = 23;
272
273 b = r_buf_new_with_bytes ((const ut8 *)content, length);
274 mu_assert_notnull (b, "r_buf_new_file failed");
275 char *s = r_buf_to_string (b);
276 mu_assert_streq (s, content, "content is right");
277 free (s);
278
279 // Cleanup
280 r_buf_free (b);
281 mu_end;
282 }
283
test_r_buf_format(void)284 bool test_r_buf_format(void) {
285 RBuffer *b = r_buf_new ();
286 uint16_t a[] = {0xdead, 0xbeef, 0xcafe, 0xbabe};
287 ut8 buf[4 * sizeof (uint16_t)];
288
289 r_buf_fwrite (b, (ut8 *)a, "4s", 1);
290 r_buf_read_at (b, 0, buf, sizeof (buf));
291 mu_assert_memeq (buf, (ut8 *)"\xad\xde\xef\xbe\xfe\xca\xbe\xba", sizeof(buf), "fwrite");
292
293 r_buf_fread_at (b, 0, (ut8 *)a, "S", 4);
294 mu_assert_eq (a[0], 0xadde, "first");
295 mu_assert_eq (a[1], 0xefbe, "second");
296 mu_assert_eq (a[2], 0xfeca, "third");
297 mu_assert_eq (a[3], 0xbeba, "fourth");
298
299 r_buf_free (b);
300 mu_end;
301 }
302
test_r_buf_with_buf(void)303 bool test_r_buf_with_buf(void) {
304 const char *content = "Something To\nSay Here..";
305 const int length = 23;
306 RBuffer *buf = r_buf_new_with_bytes ((ut8 *)content, length);
307
308 RBuffer *b = r_buf_new_with_buf (buf);
309 mu_assert_notnull (b, "r_buf_new_with_buf failed");
310 r_buf_free (buf);
311
312 if (test_buf (b) != MU_PASSED) {
313 mu_fail ("r_buf_with_buf failed");
314 }
315
316 // Cleanup
317 r_buf_free (b);
318 mu_end;
319 }
320
test_r_buf_slice(void)321 bool test_r_buf_slice(void) {
322 const char *content = "AAAAAAAAAASomething To\nSay Here..BBBBBBBBBB";
323 const int length = strlen (content);
324 RBuffer *buf = r_buf_new_with_bytes ((ut8 *)content, length);
325 ut8 buffer[1024];
326
327 RBuffer *b = r_buf_new_slice (buf, 10, 23);
328 mu_assert_notnull (b, "r_buf_new_slice failed");
329
330 ut64 buf_sz = r_buf_size (b);
331 mu_assert_eq (buf_sz, 23, "file size should be computed");
332
333 int r = r_buf_read_at (b, 0, buffer, 23);
334 mu_assert_eq (r, 23, "r_buf_read_at failed");
335 mu_assert_memeq (buffer, (ut8 *)"Something To\nSay Here..", 23, "r_buf_read_at has corrupted content");
336
337 r_buf_seek (b, 3, R_BUF_SET);
338 r = r_buf_read (b, buffer, 3);
339 mu_assert_eq (r, 3, "only 3 read");
340 mu_assert_memeq (buffer, (ut8 *)"eth", 3, "base should be considered");
341
342 r = r_buf_read (b, buffer, 40);
343 mu_assert_eq (r, 23 - 6, "consider limit");
344
345 bool res = r_buf_resize (b, 30);
346 mu_assert ("file should be resized", res);
347 buf_sz = r_buf_size (b);
348 mu_assert_eq (buf_sz, 30, "file size should be 30");
349
350 // Cleanup
351 r_buf_free (b);
352 r_buf_free (buf);
353 mu_end;
354 }
355
test_r_buf_get_string(void)356 bool test_r_buf_get_string(void) {
357 ut8 *ch = malloc (128);
358 memset (ch, 'A', 127);
359 ch[127] = '\0';
360 RBuffer *b = r_buf_new_with_bytes (ch, 128);
361 char *s = r_buf_get_string (b, 100);
362 mu_assert_streq (s, (char *)ch + 100, "the string is the same");
363 free (s);
364 s = r_buf_get_string (b, 0);
365 mu_assert_streq (s, (char *)ch, "the string is the same");
366 free (s);
367 s = r_buf_get_string (b, 127);
368 mu_assert_streq (s, "\x00", "the string is empty");
369 free (s);
370 r_buf_free (b);
371 free (ch);
372 mu_end;
373 }
374
test_r_buf_get_string_nothing(void)375 bool test_r_buf_get_string_nothing(void) {
376 RBuffer *b = r_buf_new_with_bytes ((ut8 *)"\x33\x22", 2);
377 char *s = r_buf_get_string (b, 0);
378 mu_assert_null (s, "there is no string in the buffer (no null terminator)");
379 r_buf_append_bytes (b, (ut8 *)"\x00", 1);
380 s = r_buf_get_string (b, 0);
381 mu_assert_streq (s, "\x33\x22", "now there is a string because of the null terminator");
382 free (s);
383 r_buf_free (b);
384 mu_end;
385 }
386
test_r_buf_slice_too_big(void)387 bool test_r_buf_slice_too_big(void) {
388 RBuffer *buf = r_buf_new_with_bytes ((ut8 *)"AAAA", 4);
389 RBuffer *sl = r_buf_new_slice (buf, 1, 5);
390 ut64 sz = r_buf_size (sl);
391 mu_assert_eq (sz, 3, "the size cannot be more than the original buffer");
392 r_buf_resize (sl, 1);
393 sz = r_buf_size (sl);
394 mu_assert_eq (sz, 1, "it should be shrinked to 1 byte");
395 bool res = r_buf_resize (sl, 7);
396 mu_assert ("the resize should be successful", res);
397 sz = r_buf_size (sl);
398 mu_assert_eq (sz, 3, "but it should just use the biggest value");
399 r_buf_free (sl);
400 r_buf_free (buf);
401 mu_end;
402 }
403
all_tests()404 int all_tests() {
405 mu_run_test (test_r_buf_file);
406 mu_run_test (test_r_buf_bytes);
407 mu_run_test (test_r_buf_mmap);
408 mu_run_test (test_r_buf_with_buf);
409 mu_run_test (test_r_buf_slice);
410 mu_run_test (test_r_buf_io);
411 mu_run_test (test_r_buf_sparse);
412 mu_run_test (test_r_buf_sparse2);
413 mu_run_test (test_r_buf_bytes_steal);
414 mu_run_test (test_r_buf_format);
415 mu_run_test (test_r_buf_get_string);
416 mu_run_test (test_r_buf_get_string_nothing);
417 mu_run_test (test_r_buf_slice_too_big);
418 return tests_passed != tests_run;
419 }
420
main(int argc,char ** argv)421 int main(int argc, char **argv) {
422 return all_tests();
423 }
424