]> git.saurik.com Git - apple/xnu.git/blob - tools/tests/xnu_quick_test/pipes_tests.c
xnu-2782.10.72.tar.gz
[apple/xnu.git] / tools / tests / xnu_quick_test / pipes_tests.c
1 /* Mach virtual memory unit tests
2 *
3 * The main goal of this code is to facilitate the construction,
4 * running, result logging and clean up of a test suite, taking care
5 * of all the scaffolding. A test suite is a sequence of very targeted
6 * unit tests, each running as a separate process to isolate its
7 * address space.
8 * A unit test is abstracted as a unit_test_t structure, consisting of
9 * a test function and a logging identifier. A test suite is a suite_t
10 * structure, consisting of an unit_test_t array, a logging identifier,
11 * and fixture set up and tear down functions.
12 * Test suites are created dynamically. Each of its unit test runs in
13 * its own fork()d process, with the fixture set up and tear down
14 * running before and after each test. The parent process will log a
15 * pass result if the child exits normally, and a fail result in any
16 * other case (non-zero exit status, abnormal signal). The suite
17 * results are then aggregated and logged, and finally the test suite
18 * is destroyed.
19 * Everything is logged to stdout in the standard Testbot format, which
20 * can be easily converted to Munin or SimonSays logging
21 * format. Logging is factored out as much as possible for future
22 * flexibility. In our particular case, a unit test is logged as a
23 * Testbot Test Case ([BEGIN]/[PASS]/[FAIL], and a test suite is
24 * logged as a Testbot Test ([TEST]). This is confusing but
25 * unfortunately cannot be avoided for compatibility. Suite results
26 * are aggregated after the [SUMMARY] keyword.
27 * The included test suites cover the various pipe buffer operations
28 * with dynamic expansion.
29 *
30 * Vishal Patel (vishal_patel@apple.com)
31 */
32
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include <inttypes.h>
36 #include <stdio.h>
37 #include <math.h>
38 #include <errno.h>
39 #include <signal.h>
40 #include <getopt.h>
41 #include <sys/sysctl.h>
42 #include <string.h>
43 #include <stdarg.h>
44 #include <unistd.h>
45 #include <sys/types.h>
46 #include <dispatch/dispatch.h>
47 #include <pthread.h>
48 #include <mach/vm_param.h>
49
50 /**************************/
51 /**************************/
52 /* Unit Testing Framework */
53 /**************************/
54 /**************************/
55
56 /*********************/
57 /* Private interface */
58 /*********************/
59
60 static const char frameworkname[] = "pipes_unitester";
61
62 /* Type for test, fixture set up and fixture tear down functions. */
63 typedef void (*test_fn_t)();
64
65 /* Unit test structure. */
66 typedef struct {
67 const char *name;
68 test_fn_t test;
69 } unit_test_t;
70
71 /* Test suite structure. */
72 typedef struct {
73 const char *name;
74 int numoftests;
75 test_fn_t set_up;
76 unit_test_t *tests;
77 test_fn_t tear_down;
78 } suite_t;
79
80 int _quietness = 0;
81 unsigned int _timeout = 0;
82 int _expected_signal = 0;
83
84 struct {
85 uintmax_t numoftests;
86 uintmax_t passed_tests;
87 } results = { 0, 0 };
88
89 void logr(char *format, ...) __printflike(1, 2);
90
91 static void die(int condition, const char *culprit)
92 {
93 if (condition) {
94 printf("%s: %s error: %s.\n", frameworkname, culprit,
95 strerror(errno));
96 exit(1);
97 }
98 }
99
100 static void die_on_stdout_error()
101 {
102 die(ferror(stdout), "stdout");
103 }
104
105 /* Individual test result logging. */
106 void logr(char *format, ...)
107 {
108 if (_quietness <= 1) {
109 va_list ap;
110
111 va_start(ap, format);
112 vprintf(format, ap);
113 va_end(ap);
114 die_on_stdout_error();
115 }
116 }
117
118 static suite_t *create_suite(const char *name, int numoftests,
119 test_fn_t set_up, unit_test_t *tests,
120 test_fn_t tear_down)
121 {
122 suite_t *suite = (suite_t *)malloc(sizeof(suite_t));
123 die(suite == NULL, "malloc()");
124
125 suite->name = name;
126 suite->numoftests = numoftests;
127 suite->set_up = set_up;
128 suite->tests = tests;
129 suite->tear_down = tear_down;
130 return suite;
131 }
132
133 static void destroy_suite(suite_t *suite)
134 {
135 free(suite);
136 }
137
138 static void log_suite_info(suite_t *suite)
139 {
140 logr("[TEST] %s\n", suite->name);
141 logr("Number of tests: %d\n\n", suite->numoftests);
142 }
143
144 static void log_suite_results(suite_t *suite, int passed_tests)
145 {
146 results.numoftests += (uintmax_t)suite->numoftests;
147 results.passed_tests += (uintmax_t)passed_tests;
148 }
149
150 static void log_test_info(unit_test_t *unit_test)
151 {
152 logr("[BEGIN] %s\n", unit_test->name);
153 }
154
155 static void log_test_result(unit_test_t *unit_test,
156 boolean_t test_passed)
157 {
158 logr("[%s] %s\n\n", test_passed ? "PASS" : "FAIL",
159 unit_test->name);
160 }
161
162 /* Handler for test time out. */
163 static void alarm_handler(int signo)
164 {
165 write(1,"Child process timed out.\n",
166 strlen("Child process timed out.\n"));
167 _Exit(6);
168 }
169
170 /* Run a test with fixture set up and teardown, while enforcing the
171 * time out constraint. */
172 static void run_test(suite_t *suite, unit_test_t *unit_test)
173 {
174 struct sigaction alarm_act;
175
176 log_test_info(unit_test);
177 alarm_act.sa_handler = alarm_handler;
178 sigemptyset(&alarm_act.sa_mask);
179 alarm_act.sa_flags = 0;
180 die(sigaction(SIGALRM, &alarm_act, NULL) != 0, "sigaction()");
181 alarm(_timeout);
182
183 suite->set_up();
184 unit_test->test();
185 suite->tear_down();
186 }
187
188 /* Check a child return status. */
189 static boolean_t child_terminated_normally(int child_status)
190 {
191 boolean_t normal_exit = FALSE;
192
193 if (WIFEXITED(child_status)) {
194 int exit_status = WEXITSTATUS(child_status);
195 if (exit_status) {
196 printf("Child process unexpectedly exited with code "
197 "%d.\n", exit_status);
198 } else if (!_expected_signal) {
199 normal_exit = TRUE;
200 }
201 } else if (WIFSIGNALED(child_status)) {
202 int signal = WTERMSIG(child_status);
203 if (signal == _expected_signal) {
204 if (_quietness <= 0) {
205 printf("Child process died with expected signal "
206 "%d.\n", signal);
207 }
208 normal_exit = TRUE;
209 } else {
210 printf("Child process unexpectedly died with signal "
211 "%d.\n", signal);
212 }
213 } else {
214 printf("Child process unexpectedly did not exit nor "
215 "die.\n");
216 }
217 die_on_stdout_error();
218 return normal_exit;
219 }
220
221 /* Run a test in its own process, and report the result. */
222 static boolean_t child_test_passed(suite_t *suite,
223 unit_test_t *unit_test)
224 {
225 int test_status;
226
227 pid_t test_pid = fork();
228 die(test_pid == -1, "fork()");
229 if (!test_pid) {
230 run_test(suite, unit_test);
231 exit(0);
232 }
233 while (waitpid(test_pid, &test_status, 0) != test_pid) {
234 continue;
235 }
236 boolean_t test_result = child_terminated_normally(test_status);
237 log_test_result(unit_test, test_result);
238 return test_result;
239 }
240
241 /* Run each test in a suite, and report the results. */
242 static int count_passed_suite_tests(suite_t *suite)
243 {
244 int passed_tests = 0;
245 int i;
246
247 for (i = 0; i < suite->numoftests; i++) {
248 passed_tests += child_test_passed(suite,
249 &(suite->tests[i]));
250 }
251 return passed_tests;
252 }
253
254 /********************/
255 /* Public interface */
256 /********************/
257
258 #define DEFAULT_TIMEOUT 5U
259 #define DEFAULT_QUIETNESS 1
260
261 #define assert(condition, exit_status, ...) \
262 if (!(condition)) { \
263 _fatal(__FILE__, __LINE__, __func__, \
264 (exit_status), __VA_ARGS__); \
265 }
266
267 /* Include in tests whose expected outcome is a specific signal. */
268 #define expect_signal(signal) \
269 struct sigaction _act; \
270 _act.sa_handler = expected_signal_handler; \
271 sigemptyset(&_act.sa_mask); \
272 _act.sa_flags = 0; \
273 assert(sigaction((signal), &_act, NULL) == 0, 1, \
274 "sigaction() error: %s.", strerror(errno));
275
276 #define run_suite(set_up, tests, tear_down, ...) \
277 _run_suite((sizeof(tests)/sizeof(tests[0])), \
278 (set_up), (tests), (tear_down), __VA_ARGS__)
279
280 typedef unit_test_t UnitTests[];
281
282 void _fatal(const char *file, int line, const char *function,
283 int exit_status, const char *format, ...)
284 __printflike(5, 6);
285 void _run_suite(int numoftests, test_fn_t set_up, UnitTests tests,
286 test_fn_t tear_down, const char *format, ...)
287 __printflike(5, 6);
288 void logv(char *format, ...) __printflike(1, 2);
289
290 void _fatal(const char *file, int line, const char *function,
291 int exit_status, const char *format, ...)
292 {
293 va_list ap;
294
295 va_start(ap, format);
296 vprintf(format, ap);
297 printf("\n");
298 printf("Assert failed in file %s, function %s(), line %d.\n",
299 file, function, line);
300 va_end(ap);
301 exit(exit_status);
302 }
303
304 void _run_suite(int numoftests, test_fn_t set_up, UnitTests tests,
305 test_fn_t tear_down, const char *format, ...)
306 {
307 va_list ap;
308 char *name;
309
310 va_start(ap, format);
311 die(vasprintf(&name, format, ap) == -1, "vasprintf()");
312 va_end(ap);
313 suite_t *suite = create_suite(name, numoftests, set_up, tests,
314 tear_down);
315 log_suite_info(suite);
316 log_suite_results(suite, count_passed_suite_tests(suite));
317 free(name);
318 destroy_suite(suite);
319 }
320
321 /* Signal handler for tests expected to terminate with a specific
322 * signal. */
323 void expected_signal_handler(int signo)
324 {
325 write(1,"Child process received expected signal.\n",
326 strlen("Child process received expected signal.\n"));
327 _Exit(0);
328 }
329
330 /* Setters and getters for various test framework global
331 * variables. Should only be used outside of the test, set up and tear
332 * down functions. */
333
334 /* Time out constraint for running a single test. */
335 void set_timeout(unsigned int time)
336 {
337 _timeout = time;
338 }
339
340 unsigned int get_timeout()
341 {
342 return _timeout;
343 }
344
345 /* Expected signal for a test, default is 0. */
346 void set_expected_signal(int signal)
347 {
348 _expected_signal = signal;
349 }
350
351 int get_expected_signal()
352 {
353 return _expected_signal;
354 }
355
356 /* Logging verbosity. */
357 void set_quietness(int value)
358 {
359 _quietness = value;
360 }
361
362 int get_quietness()
363 {
364 return _quietness;
365 }
366
367 /* For fixture set up and tear down functions, and units tests. */
368 void do_nothing() {
369 }
370
371 /* Verbose (default) logging. */
372 void logv(char *format, ...)
373 {
374 if (get_quietness() <= 0) {
375 va_list ap;
376
377 va_start(ap, format);
378 vprintf(format, ap);
379 va_end(ap);
380 die_on_stdout_error();
381 }
382 }
383
384 void log_aggregated_results()
385 {
386 printf("[SUMMARY] Aggregated Test Results\n");
387 printf("Total: %ju\n", results.numoftests);
388 printf("Passed: %ju\n", results.passed_tests);
389 printf("Failed: %ju\n\n", results.numoftests
390 - results.passed_tests);
391 die_on_stdout_error();
392 }
393
394 /*******************************/
395 /*******************************/
396 /* pipes buffer unit testing */
397 /*******************************/
398 /*******************************/
399
400 static const char progname[] = "pipes_unitester";
401
402 static void die_on_error(int condition, const char *culprit)
403 {
404 assert(!condition, 1, "%s: %s error: %s.", progname, culprit,
405 strerror(errno));
406 }
407
408
409 /*******************************/
410 /* Usage and option processing */
411 /*******************************/
412
413 static void usage(int exit_status)
414 {
415 printf("Usage : %s\n", progname);
416 exit(exit_status);
417 }
418
419 static void die_on_invalid_value(int condition,
420 const char *value_string)
421 {
422 if (condition) {
423 printf("%s: invalid value: %s.\n", progname, value_string);
424 usage(1);
425 }
426 }
427
428 /* Convert a storage unit suffix into an exponent. */
429 static int strtoexp(const char *string)
430 {
431 if (string[0] == '\0') {
432 return 0;
433 }
434
435 char first_letter = toupper(string[0]);
436 char prefixes[] = "BKMGTPE";
437 const int numofprefixes = strlen(prefixes);
438 prefixes[numofprefixes] = first_letter;
439 int i = 0;
440
441 while (prefixes[i] != first_letter) {
442 i++;
443 }
444 die_on_invalid_value(i >= numofprefixes || (string[1] != '\0' &&
445 (toupper(string[1])
446 != 'B' || string[2]
447 != '\0')), string);
448 return 10 * i;
449 }
450
451 static void process_options(int argc, char *argv[])
452 {
453 int opt;
454 char *endptr;
455
456 setvbuf(stdout, NULL, _IONBF, 0);
457
458 set_timeout(DEFAULT_TIMEOUT);
459 set_quietness(DEFAULT_QUIETNESS);
460
461 while ((opt = getopt(argc, argv, "t:vqh")) != -1) {
462 switch (opt) {
463 case 't':
464 errno = 0;
465 set_timeout(strtoul(optarg, &endptr, 0));
466 die_on_invalid_value(errno == ERANGE || *endptr != '\0'
467 || endptr == optarg, optarg);
468 break;
469 case 'q':
470 set_quietness(get_quietness() + 1);
471 break;
472 case 'v':
473 set_quietness(0);
474 break;
475 case 'h':
476 usage(0);
477 break;
478 default:
479 usage(1);
480 break;
481 }
482 }
483 }
484
485 /*********************************/
486 /* Various function declarations */
487 /*********************************/
488
489 void initialize_data(int *ptr, int len);
490
491 int verify_data(int *base, int *target, int len);
492
493 void clear_data(int *ptr, int len);
494
495 /*******************************/
496 /* Arrays for test suite loops */
497 /*******************************/
498
499 #define BUFMAX 20000
500 #define BUFMAXLEN (BUFMAX * sizeof(int))
501
502 const unsigned int pipesize_blocks[] = {128,256,1024,2048,4096,8192,16384};
503 static const int bufsizes[] = { 128, 512, 1024, 2048, 4096, 16384 };
504
505 int data[BUFMAX],readbuf[BUFMAX];
506 int pipefd[2] = {0,0};
507
508 typedef int * pipe_t;
509
510 struct thread_work_data {
511 pipe_t p;
512 unsigned int total_bytes;
513 unsigned int chunk_size;
514 };
515
516 void * reader_thread(void *ptr);
517 void * writer_thread(void *ptr);
518
519 dispatch_semaphore_t r_sem, w_sem;
520
521 unsigned long current_buf_size=0;
522
523 /*************************************/
524 /* Global variables set up functions */
525 /*************************************/
526
527
528 void initialize_data(int *ptr, int len)
529 {
530 int i;
531 if (!ptr || len <=0 )
532 return;
533
534 for (i = 0; i < len; i ++)
535 ptr[i] = i;
536 }
537
538 void clear_data(int *ptr, int len)
539 {
540
541 int i;
542 if (!ptr)
543 return;
544 for (i = 0; i < len; i++)
545 ptr[i]=0;
546 }
547
548 int verify_data(int *base, int *target, int len)
549 {
550 int i = 0;
551
552 if (!base || !target)
553 return 0;
554
555 for (i = 0; i < len; i++){
556 if (base[i] != target[i])
557 return 0;
558 }
559
560 return 1;
561 }
562
563 void initialize_data_buffer()
564 {
565 initialize_data(data, BUFMAX);
566 initialize_data(readbuf, BUFMAX);
567 }
568
569 /*******************************/
570 /* core read write helper funtions */
571 /*******************************/
572
573 ssize_t read_whole_buffer(pipe_t p, void *scratch_buf, int size);
574 ssize_t pipe_read_data(pipe_t p, void *dest_buf, int size);
575 ssize_t pipe_write_data(pipe_t p, void *src_buf, int size);
576
577 ssize_t read_whole_buffer(pipe_t p, void *scratch_buf, int size)
578 {
579 int fd = p[0];
580 logv("reading whole buffer from fd %d, size %d", fd, size);
581 int retval = pread(fd, scratch_buf, size, 0);
582 if (retval == -1 ){
583 logv("Error reading whole buffer. (%d) %s\n",errno, strerror(errno));
584 }
585 return retval;
586
587 }
588
589 ssize_t pipe_read_data(pipe_t p, void *dest_buf, int size)
590 {
591 int fd = p[0];
592 //logv("reading from pipe %d, for size %d", fd, size);
593 int retval = read(fd, dest_buf, size);
594 if (retval == -1) {
595 logv("Error reading from buffer. (%d)",errno);
596 }
597 return retval;
598 }
599
600 ssize_t pipe_write_data(pipe_t p, void *src_buf, int size)
601 {
602 int fd = p[1];
603 //logv("writing to pipe %d, for size %d", fd, size);
604 int retval = write(fd, src_buf, size);
605 if (retval == -1) {
606 logv("Error writing to buffer. (%d) %s",errno, strerror(errno));
607 }
608 return retval;
609 }
610
611
612 void * reader_thread(void *ptr)
613 {
614 struct thread_work_data *m;
615 m = (struct thread_work_data *) ptr;
616 int i = m->total_bytes/m->chunk_size;
617 int retval, data_idx=0;
618 while (i > 0){
619 dispatch_semaphore_wait(r_sem, 8000);
620 retval = pipe_read_data(m->p, &readbuf[data_idx], m->chunk_size);
621 assert(retval == m->chunk_size, 1, "Pipe read returned different amount of numbe");
622 data_idx +=m->chunk_size;
623 //logv("RD %d \n", m->chunk_size);
624 dispatch_semaphore_signal(w_sem);
625 i--;
626 }
627 return 0;
628 }
629
630 void * writer_thread(void *ptr)
631 {
632 struct thread_work_data *m;
633 m = (struct thread_work_data *)ptr;
634 int i = m->total_bytes/m->chunk_size;
635 int retval, data_idx=0;
636 while ( i > 0 ){
637
638 dispatch_semaphore_wait(w_sem, 8000);
639 //logv("WR %d \n", m->chunk_size);
640 retval=pipe_write_data(m->p, &data[data_idx], m->chunk_size);
641 assert(retval == m->chunk_size, 1, "Pipe write failed");
642 data_idx +=m->chunk_size;
643 dispatch_semaphore_signal(r_sem);
644 i--;
645 }
646 return 0;
647 }
648
649
650 void create_threads(struct thread_work_data *rdata, struct thread_work_data *wdata){
651
652 pthread_t thread1, thread2;
653 r_sem = dispatch_semaphore_create(0);
654 w_sem = dispatch_semaphore_create(1);
655 int iret1, iret2;
656 void * thread_ret1 =0;
657 void * thread_ret2 =0;
658 /* Create independent threads each of which will execute function */
659
660 iret1 = pthread_create( &thread1, NULL, reader_thread, (void*) rdata);
661 iret2 = pthread_create( &thread2, NULL, writer_thread, (void*) wdata);
662
663 pthread_join( thread2, &thread_ret1);
664 pthread_join( thread1, &thread_ret1);
665 assert(thread_ret1 == 0, 1, "Reader Thread Failed");
666 assert(thread_ret2 == 0, 1, "Writer Thread Failed");
667 }
668
669
670 /*******************************/
671 /* Pipes unit test functions */
672 /*******************************/
673 void test_pipebuffer_setup ()
674 {
675
676 logv("Setting up buffers data and readbuf\n");
677 clear_data(data, BUFMAX);
678 clear_data(readbuf, BUFMAX);
679 logv("Initializing buffers data and readbuf\n");
680 initialize_data(data, BUFMAX);
681 initialize_data(readbuf, BUFMAX);
682 logv("verifying data for correctness\n");
683 die_on_error(!verify_data(data, readbuf, BUFMAX), "data initialization");
684 clear_data(readbuf, BUFMAX);
685 }
686
687 void test_pipe_create(){
688 int pipefds[2] = {0,0};
689 pipe_t p = pipefds;
690 int err = pipe(p);
691 if ( err ){
692 logv("error opening pipes (%d) %s", errno, strerror(errno));
693 return;
694 }
695
696 die_on_error(0 != close(pipefds[0]), "close()");
697 die_on_error(0 != close(pipefds[1]), "close()");
698 }
699
700 void test_pipe_write_single_byte(){
701 int pipefds[2] = { 0 , 0 };
702 pipe_t p = pipefds;
703 die_on_error( 0 != pipe(p), "pipe()");
704 initialize_data_buffer();
705 int i = 0,retval;
706 for ( ; i < current_buf_size; i++){
707 if ( i > 16384){
708 logv("cannot fill continuously beyond 16K.");
709 break;
710 }
711 retval=pipe_write_data(p, &data[i], 1);
712 assert(retval == 1, 1, "Pipe write failed");
713 }
714
715 close(p[0]);
716 close(p[1]);
717 }
718
719 void test_pipe_single_read_write(){
720 int pipefds[2] = { 0 , 0 };
721 pipe_t p = pipefds;
722 die_on_error( 0 != pipe(p), "pipe()");
723 initialize_data_buffer();
724 struct thread_work_data d = { p, current_buf_size, 1};
725 create_threads(&d, &d);
726 verify_data(data, readbuf, current_buf_size);
727 close(p[0]);
728 close(p[1]);
729
730 }
731
732 void test_pipe_single_read_2write(){
733 int pipefds[2] = { 0 , 0 };
734 pipe_t p = pipefds;
735 die_on_error( 0 != pipe(p), "pipe()");
736 initialize_data_buffer();
737 struct thread_work_data rd = { p, current_buf_size, 1};
738 struct thread_work_data wd = { p, current_buf_size, 2};
739 create_threads(&rd, &wd);
740 verify_data(data, readbuf, current_buf_size);
741 close(p[0]);
742 close(p[1]);
743
744 }
745
746 void test_pipe_expansion_buffer(){
747 int pipefds[2] = { 0 , 0 };
748 int iter = 0;
749 pipe_t p = pipefds;
750 die_on_error( 0 != pipe(p), "pipe()");
751 initialize_data_buffer();
752 for ( iter=0; iter < sizeof(pipesize_blocks)/sizeof(unsigned int); iter++){
753 assert(pipesize_blocks[iter] == pipe_write_data(p, &data[0], pipesize_blocks[iter] ), 1, "expansion write failed");
754 assert(pipesize_blocks[iter] == pipe_read_data(p, &readbuf[0], pipesize_blocks[iter]+200), 1, "reading from expanded data failed");
755 /* logv("finished round for size %u \n", pipesize_blocks[iter]); */
756 }
757 verify_data(data, readbuf, current_buf_size);
758 close(p[0]);
759 close(p[1]);
760
761 }
762
763 void test_pipe_initial_big_allocation(){
764 int pipefds[2] = { 0 , 0 };
765 int iter = 0;
766 pipe_t p = pipefds;
767 die_on_error( 0 != pipe(p), "pipe()");
768 initialize_data_buffer();
769 assert(current_buf_size == pipe_write_data(p, &data[0], current_buf_size ), 1, "initial big allocation failed");
770 assert(current_buf_size == pipe_read_data(p, &readbuf[0], current_buf_size+200), 1, "reading from initial big write failed");
771 assert(verify_data(data, readbuf, current_buf_size), 1, "big pipe initial allocation -not able to verify data");
772 close(p[0]);
773 close(p[1]);
774
775 }
776
777 void test_pipe_cycle_small_writes(){
778 int pipefds[2] = { 0 , 0 };
779 int iter = 0;
780 pipe_t p = pipefds;
781 die_on_error( 0 != pipe(p), "pipe()");
782 initialize_data_buffer();
783 int buf_size = current_buf_size / 2;
784
785 assert(buf_size == pipe_write_data(p, &data[0], buf_size ), 1, "cycle write failed");
786 assert(buf_size == pipe_read_data(p, &readbuf[0], buf_size+200), 1, "reading from cycle read failed");
787 assert(verify_data(data, readbuf, buf_size), 1, "data verification failed");
788
789 assert(buf_size == pipe_write_data(p, &data[0], buf_size ), 1, "cycle write failed");
790 assert(buf_size == pipe_read_data(p, &readbuf[0], buf_size+200), 1, "reading from cycle read failed");
791 assert(verify_data(data, readbuf, buf_size), 1, "data verification failed");
792
793 assert(buf_size == pipe_write_data(p, &data[0], buf_size ), 1, "cycle write failed");
794 assert(buf_size == pipe_read_data(p, &readbuf[0], buf_size+200), 1, "reading from cycle read failed");
795 assert(verify_data(data, readbuf, buf_size), 1, "data verification failed");
796
797 close(p[0]);
798 close(p[1]);
799
800 }
801
802 void test_pipe_moving_data(){
803 int pipefds[2] = { 0 , 0 };
804 int iter = 0;
805 pipe_t p = pipefds;
806 die_on_error( 0 != pipe(p), "pipe()");
807 initialize_data_buffer();
808 int buf_size = current_buf_size / 2;
809 if (buf_size > PAGE_SIZE)
810 buf_size = PAGE_SIZE;
811
812 assert(buf_size == pipe_write_data(p, &data[0], buf_size ), 1, "cycle write failed");
813 logv("write of size =%d\n", buf_size);
814 assert(buf_size == pipe_write_data(p, &data[buf_size/sizeof(int)], buf_size ), 1, "cycle write failed");
815 logv("write of size =%d\n", buf_size*2);
816 assert(buf_size == pipe_write_data(p, &data[(buf_size*2)/sizeof(int)], buf_size ), 1, "cycle write failed");
817 logv("write of size =%d\n", buf_size*3);
818 assert((3*buf_size) == pipe_read_data(p, &readbuf[0], (3*buf_size)+200), 1, "reading from cycle read failed");
819 assert(verify_data(data, readbuf, (3*buf_size)/sizeof(int)), 1, "data verification failed");
820
821 close(p[0]);
822 close(p[1]);
823
824 }
825
826
827 /*************/
828 /* pipe Suites */
829 /*************/
830
831 void run_pipe_basic_tests()
832 {
833 int sizes_idx;
834 int numofsizes = sizeof(bufsizes)/sizeof(int);
835
836 logv("running tests for %d different sizes \n", numofsizes);
837
838 UnitTests pipe_basic_tests = {
839 { "1. create buffer and verify both reads/writes are valid",
840 test_pipebuffer_setup },
841 { "2. open and close pipes", test_pipe_create },
842 { "3. single byte write to full", test_pipe_write_single_byte},
843 { "4. single byte read/write in sync", test_pipe_single_read_write},
844 { "5. single byte read/2write in sync", test_pipe_single_read_2write},
845 { "6. expansion from existing size", test_pipe_expansion_buffer},
846 { "7. initial big allocation " , test_pipe_initial_big_allocation},
847 { "8. cycle_small_writes " ,test_pipe_cycle_small_writes },
848 { "9. test moving data " ,test_pipe_moving_data }
849 };
850 for (sizes_idx = 0; sizes_idx < numofsizes; sizes_idx++) {
851 current_buf_size = bufsizes[sizes_idx];
852 run_suite(do_nothing,
853 pipe_basic_tests,
854 do_nothing, "pipe create base test "
855 "Size: 0x%jx (%ju)",
856 (uintmax_t)bufsizes[sizes_idx],
857 (uintmax_t)bufsizes[sizes_idx]);
858 }
859 }
860
861
862 int pipes_test(void *the_argp)
863 {
864 set_quietness(2);
865 run_pipe_basic_tests();
866 //log_aggregated_results();
867 return results.numoftests - results.passed_tests;
868 }
869
870 /*
871 * retaining the old main function to debug issues with the tests and not the xnu_quick_test framework
872 * or the system
873 */
874 int main_nonuse(int argc, char *argv[])
875 {
876 process_options(argc, argv);
877
878 run_pipe_basic_tests();
879
880 log_aggregated_results();
881 return 0;
882 }