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