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