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