]> git.saurik.com Git - apple/xnu.git/blame - tools/tests/xnu_quick_test/pipes_tests.c
xnu-2782.40.9.tar.gz
[apple/xnu.git] / tools / tests / xnu_quick_test / pipes_tests.c
CommitLineData
316670eb
A
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>
39236c6e 47#include <pthread.h>
fe8ab488 48#include <mach/vm_param.h>
316670eb
A
49
50/**************************/
51/**************************/
52/* Unit Testing Framework */
53/**************************/
54/**************************/
55
56/*********************/
57/* Private interface */
58/*********************/
59
60static const char frameworkname[] = "pipes_unitester";
61
62/* Type for test, fixture set up and fixture tear down functions. */
63typedef void (*test_fn_t)();
64
65/* Unit test structure. */
66typedef struct {
67 const char *name;
68 test_fn_t test;
69} unit_test_t;
70
71/* Test suite structure. */
72typedef 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
80int _quietness = 0;
81unsigned int _timeout = 0;
82int _expected_signal = 0;
83
84struct {
85 uintmax_t numoftests;
86 uintmax_t passed_tests;
87} results = { 0, 0 };
88
89void logr(char *format, ...) __printflike(1, 2);
90
91static 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
100static void die_on_stdout_error()
101{
102 die(ferror(stdout), "stdout");
103}
104
105/* Individual test result logging. */
106void 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
118static 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
133static void destroy_suite(suite_t *suite)
134{
135 free(suite);
136}
137
138static 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
144static 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
150static void log_test_info(unit_test_t *unit_test)
151{
152 logr("[BEGIN] %s\n", unit_test->name);
153}
154
155static 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. */
163static 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. */
172static 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. */
189static 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. */
222static 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. */
242static 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
280typedef unit_test_t UnitTests[];
281
282void _fatal(const char *file, int line, const char *function,
283 int exit_status, const char *format, ...)
284 __printflike(5, 6);
285void _run_suite(int numoftests, test_fn_t set_up, UnitTests tests,
286 test_fn_t tear_down, const char *format, ...)
287 __printflike(5, 6);
288void logv(char *format, ...) __printflike(1, 2);
289
290void _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
304void _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. */
323void 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. */
335void set_timeout(unsigned int time)
336{
337 _timeout = time;
338}
339
340unsigned int get_timeout()
341{
342 return _timeout;
343}
344
345/* Expected signal for a test, default is 0. */
346void set_expected_signal(int signal)
347{
348 _expected_signal = signal;
349}
350
351int get_expected_signal()
352{
353 return _expected_signal;
354}
355
356/* Logging verbosity. */
357void set_quietness(int value)
358{
359 _quietness = value;
360}
361
362int get_quietness()
363{
364 return _quietness;
365}
366
367/* For fixture set up and tear down functions, and units tests. */
368void do_nothing() {
369}
370
371/* Verbose (default) logging. */
372void 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
384void 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
400static const char progname[] = "pipes_unitester";
401
402static 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
413static void usage(int exit_status)
414{
415 printf("Usage : %s\n", progname);
416 exit(exit_status);
417}
418
419static 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. */
429static 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
451static 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
489void initialize_data(int *ptr, int len);
490
491int verify_data(int *base, int *target, int len);
492
493void 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
fe8ab488 502const unsigned int pipesize_blocks[] = {128,256,1024,2048,4096,8192,16384};
316670eb
A
503static const int bufsizes[] = { 128, 512, 1024, 2048, 4096, 16384 };
504
505int data[BUFMAX],readbuf[BUFMAX];
506int pipefd[2] = {0,0};
507
508typedef int * pipe_t;
509
510struct thread_work_data {
511 pipe_t p;
512 unsigned int total_bytes;
513 unsigned int chunk_size;
514};
515
516void * reader_thread(void *ptr);
517void * writer_thread(void *ptr);
518
519dispatch_semaphore_t r_sem, w_sem;
520
521unsigned long current_buf_size=0;
522
523/*************************************/
524/* Global variables set up functions */
525/*************************************/
526
527
528void 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
538void 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
548int 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
563void 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
573ssize_t read_whole_buffer(pipe_t p, void *scratch_buf, int size);
574ssize_t pipe_read_data(pipe_t p, void *dest_buf, int size);
575ssize_t pipe_write_data(pipe_t p, void *src_buf, int size);
576
577ssize_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
589ssize_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
600ssize_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
612void * 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
630void * 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
650void 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/*******************************/
673void 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
687void 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
700void 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
719void 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
732void 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
746void 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
763void 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
777void 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
802void 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
831void 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
862int 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 */
874int 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}