1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <errno.h>
19 #include <stdbool.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <getopt.h>
24 #include <sys/uio.h>
25
26 #include <trusty/tipc.h>
27
28 #define TIPC_DEFAULT_DEVNAME "/dev/trusty-ipc-dev0"
29
30 static const char *dev_name = NULL;
31 static const char *test_name = NULL;
32
33 static const char *uuid_name = "com.android.ipc-unittest.srv.uuid";
34 static const char *echo_name = "com.android.ipc-unittest.srv.echo";
35 static const char *ta_only_name = "com.android.ipc-unittest.srv.ta_only";
36 static const char *ns_only_name = "com.android.ipc-unittest.srv.ns_only";
37 static const char *datasink_name = "com.android.ipc-unittest.srv.datasink";
38 static const char *closer1_name = "com.android.ipc-unittest.srv.closer1";
39 static const char *closer2_name = "com.android.ipc-unittest.srv.closer2";
40 static const char *closer3_name = "com.android.ipc-unittest.srv.closer3";
41 static const char *main_ctrl_name = "com.android.ipc-unittest.ctrl";
42
43 static const char *_sopts = "hsvD:t:r:m:b:";
44 static const struct option _lopts[] = {
45 {"help", no_argument, 0, 'h'},
46 {"silent", no_argument, 0, 's'},
47 {"variable",no_argument, 0, 'v'},
48 {"dev", required_argument, 0, 'D'},
49 {"repeat", required_argument, 0, 'r'},
50 {"burst", required_argument, 0, 'b'},
51 {"msgsize", required_argument, 0, 'm'},
52 {0, 0, 0, 0}
53 };
54
55 static const char *usage =
56 "Usage: %s [options]\n"
57 "\n"
58 "options:\n"
59 " -h, --help prints this message and exit\n"
60 " -D, --dev name device name\n"
61 " -t, --test name test to run\n"
62 " -r, --repeat cnt repeat count\n"
63 " -m, --msgsize size max message size\n"
64 " -v, --variable variable message size\n"
65 " -s, --silent silent\n"
66 "\n"
67 ;
68
69 static const char *usage_long =
70 "\n"
71 "The following tests are available:\n"
72 " connect - connect to datasink service\n"
73 " connect_foo - connect to non existing service\n"
74 " burst_write - send messages to datasink service\n"
75 " echo - send/receive messages to echo service\n"
76 " select - test select call\n"
77 " blocked_read - test blocked read\n"
78 " closer1 - connection closed by remote (test1)\n"
79 " closer2 - connection closed by remote (test2)\n"
80 " closer3 - connection closed by remote (test3)\n"
81 " ta2ta-ipc - execute TA to TA unittest\n"
82 " dev-uuid - print device uuid\n"
83 " ta-access - test ta-access flags\n"
84 " writev - writev test\n"
85 " readv - readv test\n"
86 "\n"
87 ;
88
89 static uint opt_repeat = 1;
90 static uint opt_msgsize = 32;
91 static uint opt_msgburst = 32;
92 static bool opt_variable = false;
93 static bool opt_silent = false;
94
print_usage_and_exit(const char * prog,int code,bool verbose)95 static void print_usage_and_exit(const char *prog, int code, bool verbose)
96 {
97 fprintf (stderr, usage, prog);
98 if (verbose)
99 fprintf (stderr, "%s", usage_long);
100 exit(code);
101 }
102
parse_options(int argc,char ** argv)103 static void parse_options(int argc, char **argv)
104 {
105 int c;
106 int oidx = 0;
107
108 while (1)
109 {
110 c = getopt_long (argc, argv, _sopts, _lopts, &oidx);
111 if (c == -1)
112 break; /* done */
113
114 switch (c) {
115
116 case 'D':
117 dev_name = strdup(optarg);
118 break;
119
120 case 't':
121 test_name = strdup(optarg);
122 break;
123
124 case 'v':
125 opt_variable = true;
126 break;
127
128 case 'r':
129 opt_repeat = atoi(optarg);
130 break;
131
132 case 'm':
133 opt_msgsize = atoi(optarg);
134 break;
135
136 case 'b':
137 opt_msgburst = atoi(optarg);
138 break;
139
140 case 's':
141 opt_silent = true;
142 break;
143
144 case 'h':
145 print_usage_and_exit(argv[0], EXIT_SUCCESS, true);
146 break;
147
148 default:
149 print_usage_and_exit(argv[0], EXIT_FAILURE, false);
150 }
151 }
152 }
153
connect_test(uint repeat)154 static int connect_test(uint repeat)
155 {
156 uint i;
157 int echo_fd;
158 int dsink_fd;
159
160 if (!opt_silent) {
161 printf("%s: repeat = %u\n", __func__, repeat);
162 }
163
164 for (i = 0; i < repeat; i++) {
165 echo_fd = tipc_connect(dev_name, echo_name);
166 if (echo_fd < 0) {
167 fprintf(stderr, "Failed to connect to '%s' service\n",
168 "echo");
169 }
170 dsink_fd = tipc_connect(dev_name, datasink_name);
171 if (dsink_fd < 0) {
172 fprintf(stderr, "Failed to connect to '%s' service\n",
173 "datasink");
174 }
175
176 if (echo_fd >= 0) {
177 tipc_close(echo_fd);
178 }
179 if (dsink_fd >= 0) {
180 tipc_close(dsink_fd);
181 }
182 }
183
184 if (!opt_silent) {
185 printf("%s: done\n", __func__);
186 }
187
188 return 0;
189 }
190
connect_foo(uint repeat)191 static int connect_foo(uint repeat)
192 {
193 uint i;
194 int fd;
195
196 if (!opt_silent) {
197 printf("%s: repeat = %u\n", __func__, repeat);
198 }
199
200 for (i = 0; i < repeat; i++) {
201 fd = tipc_connect(dev_name, "foo");
202 if (fd >= 0) {
203 fprintf(stderr, "succeeded to connect to '%s' service\n",
204 "foo");
205 tipc_close(fd);
206 }
207 }
208
209 if (!opt_silent) {
210 printf("%s: done\n", __func__);
211 }
212
213 return 0;
214 }
215
216
closer1_test(uint repeat)217 static int closer1_test(uint repeat)
218 {
219 uint i;
220 int fd;
221
222 if (!opt_silent) {
223 printf("%s: repeat = %u\n", __func__, repeat);
224 }
225
226 for (i = 0; i < repeat; i++) {
227 fd = tipc_connect(dev_name, closer1_name);
228 if (fd < 0) {
229 fprintf(stderr, "Failed to connect to '%s' service\n",
230 "closer1");
231 continue;
232 }
233 if (!opt_silent) {
234 printf("%s: connected\n", __func__);
235 }
236 tipc_close(fd);
237 }
238
239 if (!opt_silent) {
240 printf("%s: done\n", __func__);
241 }
242
243 return 0;
244 }
245
closer2_test(uint repeat)246 static int closer2_test(uint repeat)
247 {
248 uint i;
249 int fd;
250
251 if (!opt_silent) {
252 printf("%s: repeat = %u\n", __func__, repeat);
253 }
254
255 for (i = 0; i < repeat; i++) {
256 fd = tipc_connect(dev_name, closer2_name);
257 if (fd < 0) {
258 if (!opt_silent) {
259 printf("failed to connect to '%s' service\n", "closer2");
260 }
261 } else {
262 /* this should always fail */
263 fprintf(stderr, "connected to '%s' service\n", "closer2");
264 tipc_close(fd);
265 }
266 }
267
268 if (!opt_silent) {
269 printf("%s: done\n", __func__);
270 }
271
272 return 0;
273 }
274
closer3_test(uint repeat)275 static int closer3_test(uint repeat)
276 {
277 uint i, j;
278 ssize_t rc;
279 int fd[4];
280 char buf[64];
281
282 if (!opt_silent) {
283 printf("%s: repeat = %u\n", __func__, repeat);
284 }
285
286 for (i = 0; i < repeat; i++) {
287
288 /* open 4 connections to closer3 service */
289 for (j = 0; j < 4; j++) {
290 fd[j] = tipc_connect(dev_name, closer3_name);
291 if (fd[j] < 0) {
292 fprintf(stderr, "fd[%d]: failed to connect to '%s' service\n", j, "closer3");
293 } else {
294 if (!opt_silent) {
295 printf("%s: fd[%d]=%d: connected\n", __func__, j, fd[j]);
296 }
297 memset(buf, i + j, sizeof(buf));
298 rc = write(fd[j], buf, sizeof(buf));
299 if (rc != sizeof(buf)) {
300 if (!opt_silent) {
301 printf("%s: fd[%d]=%d: write returned = %zd\n",
302 __func__, j, fd[j], rc);
303 }
304 perror("closer3_test: write");
305 }
306 }
307 }
308
309 /* sleep a bit */
310 sleep(1);
311
312 /* It is expected that they will be closed by remote */
313 for (j = 0; j < 4; j++) {
314 if (fd[j] < 0)
315 continue;
316 rc = write(fd[j], buf, sizeof(buf));
317 if (rc != sizeof(buf)) {
318 if (!opt_silent) {
319 printf("%s: fd[%d]=%d: write returned = %zd\n",
320 __func__, j, fd[j], rc);
321 }
322 perror("closer3_test: write");
323 }
324 }
325
326 /* then they have to be closed by remote */
327 for (j = 0; j < 4; j++) {
328 if (fd[j] >= 0) {
329 tipc_close(fd[j]);
330 }
331 }
332 }
333
334 if (!opt_silent) {
335 printf("%s: done\n", __func__);
336 }
337
338 return 0;
339 }
340
341
echo_test(uint repeat,uint msgsz,bool var)342 static int echo_test(uint repeat, uint msgsz, bool var)
343 {
344 uint i;
345 ssize_t rc;
346 size_t msg_len;
347 int echo_fd =-1;
348 char tx_buf[msgsz];
349 char rx_buf[msgsz];
350
351 if (!opt_silent) {
352 printf("%s: repeat %u: msgsz %u: variable %s\n",
353 __func__, repeat, msgsz, var ? "true" : "false");
354 }
355
356 echo_fd = tipc_connect(dev_name, echo_name);
357 if (echo_fd < 0) {
358 fprintf(stderr, "Failed to connect to service\n");
359 return echo_fd;
360 }
361
362 for (i = 0; i < repeat; i++) {
363
364 msg_len = msgsz;
365 if (opt_variable && msgsz) {
366 msg_len = rand() % msgsz;
367 }
368
369 memset(tx_buf, i + 1, msg_len);
370
371 rc = write(echo_fd, tx_buf, msg_len);
372 if ((size_t)rc != msg_len) {
373 perror("echo_test: write");
374 break;
375 }
376
377 rc = read(echo_fd, rx_buf, msg_len);
378 if (rc < 0) {
379 perror("echo_test: read");
380 break;
381 }
382
383 if ((size_t)rc != msg_len) {
384 fprintf(stderr, "data truncated (%zu vs. %zu)\n",
385 rc, msg_len);
386 continue;
387 }
388
389 if (memcmp(tx_buf, rx_buf, (size_t) rc)) {
390 fprintf(stderr, "data mismatch\n");
391 continue;
392 }
393 }
394
395 tipc_close(echo_fd);
396
397 if (!opt_silent) {
398 printf("%s: done\n",__func__);
399 }
400
401 return 0;
402 }
403
burst_write_test(uint repeat,uint msgburst,uint msgsz,bool var)404 static int burst_write_test(uint repeat, uint msgburst, uint msgsz, bool var)
405 {
406 int fd;
407 uint i, j;
408 ssize_t rc;
409 size_t msg_len;
410 char tx_buf[msgsz];
411
412 if (!opt_silent) {
413 printf("%s: repeat %u: burst %u: msgsz %u: variable %s\n",
414 __func__, repeat, msgburst, msgsz,
415 var ? "true" : "false");
416 }
417
418 for (i = 0; i < repeat; i++) {
419
420 fd = tipc_connect(dev_name, datasink_name);
421 if (fd < 0) {
422 fprintf(stderr, "Failed to connect to '%s' service\n",
423 "datasink");
424 break;
425 }
426
427 for (j = 0; j < msgburst; j++) {
428 msg_len = msgsz;
429 if (var && msgsz) {
430 msg_len = rand() % msgsz;
431 }
432
433 memset(tx_buf, i + 1, msg_len);
434 rc = write(fd, tx_buf, msg_len);
435 if ((size_t)rc != msg_len) {
436 perror("burst_test: write");
437 break;
438 }
439 }
440
441 tipc_close(fd);
442 }
443
444 if (!opt_silent) {
445 printf("%s: done\n",__func__);
446 }
447
448 return 0;
449 }
450
451
_wait_for_msg(int fd,uint msgsz,int timeout)452 static int _wait_for_msg(int fd, uint msgsz, int timeout)
453 {
454 int rc;
455 fd_set rfds;
456 uint msgcnt = 0;
457 char rx_buf[msgsz];
458 struct timeval tv;
459
460 if (!opt_silent) {
461 printf("waiting (%d) for msg\n", timeout);
462 }
463
464 FD_ZERO(&rfds);
465 FD_SET(fd, &rfds);
466
467 tv.tv_sec = timeout;
468 tv.tv_usec = 0;
469
470 for(;;) {
471 rc = select(fd+1, &rfds, NULL, NULL, &tv);
472
473 if (rc == 0) {
474 if (!opt_silent) {
475 printf("select timedout\n");
476 }
477 break;
478 }
479
480 if (rc == -1) {
481 perror("select_test: select");
482 return rc;
483 }
484
485 rc = read(fd, rx_buf, sizeof(rx_buf));
486 if (rc < 0) {
487 perror("select_test: read");
488 return rc;
489 } else {
490 if (rc > 0) {
491 msgcnt++;
492 }
493 }
494 }
495
496 if (!opt_silent) {
497 printf("got %u messages\n", msgcnt);
498 }
499
500 return 0;
501 }
502
503
select_test(uint repeat,uint msgburst,uint msgsz)504 static int select_test(uint repeat, uint msgburst, uint msgsz)
505 {
506 int fd;
507 uint i, j;
508 ssize_t rc;
509 char tx_buf[msgsz];
510
511 if (!opt_silent) {
512 printf("%s: repeat %u\n", __func__, repeat);
513 }
514
515 fd = tipc_connect(dev_name, echo_name);
516 if (fd < 0) {
517 fprintf(stderr, "Failed to connect to '%s' service\n",
518 "echo");
519 return fd;
520 }
521
522 for (i = 0; i < repeat; i++) {
523
524 _wait_for_msg(fd, msgsz, 1);
525
526 if (!opt_silent) {
527 printf("sending burst: %u msg\n", msgburst);
528 }
529
530 for (j = 0; j < msgburst; j++) {
531 memset(tx_buf, i + j, msgsz);
532 rc = write(fd, tx_buf, msgsz);
533 if ((size_t)rc != msgsz) {
534 perror("burst_test: write");
535 break;
536 }
537 }
538 }
539
540 tipc_close(fd);
541
542 if (!opt_silent) {
543 printf("%s: done\n",__func__);
544 }
545
546 return 0;
547 }
548
blocked_read_test(uint repeat)549 static int blocked_read_test(uint repeat)
550 {
551 int fd;
552 uint i;
553 ssize_t rc;
554 char rx_buf[512];
555
556 if (!opt_silent) {
557 printf("%s: repeat %u\n", __func__, repeat);
558 }
559
560 fd = tipc_connect(dev_name, echo_name);
561 if (fd < 0) {
562 fprintf(stderr, "Failed to connect to '%s' service\n",
563 "echo");
564 return fd;
565 }
566
567 for (i = 0; i < repeat; i++) {
568 rc = read(fd, rx_buf, sizeof(rx_buf));
569 if (rc < 0) {
570 perror("select_test: read");
571 break;
572 } else {
573 if (!opt_silent) {
574 printf("got %zd bytes\n", rc);
575 }
576 }
577 }
578
579 tipc_close(fd);
580
581 if (!opt_silent) {
582 printf("%s: done\n",__func__);
583 }
584
585 return 0;
586 }
587
ta2ta_ipc_test(void)588 static int ta2ta_ipc_test(void)
589 {
590 enum test_message_header {
591 TEST_PASSED = 0,
592 TEST_FAILED = 1,
593 TEST_MESSAGE = 2,
594 };
595
596 int fd;
597 int ret;
598 unsigned char rx_buf[256];
599
600 if (!opt_silent) {
601 printf("%s:\n", __func__);
602 }
603
604 fd = tipc_connect(dev_name, main_ctrl_name);
605 if (fd < 0) {
606 fprintf(stderr, "Failed to connect to '%s' service\n",
607 "main_ctrl");
608 return fd;
609 }
610
611 /* Wait for tests to complete and read status */
612 while (true) {
613 ret = read(fd, rx_buf, sizeof(rx_buf));
614 if (ret <= 0 || ret >= (int)sizeof(rx_buf)) {
615 fprintf(stderr, "%s: Read failed: %d\n", __func__, ret);
616 tipc_close(fd);
617 return -1;
618 }
619
620 if (rx_buf[0] == TEST_PASSED) {
621 break;
622 } else if (rx_buf[0] == TEST_FAILED) {
623 break;
624 } else if (rx_buf[0] == TEST_MESSAGE) {
625 write(STDOUT_FILENO, rx_buf + 1, ret - 1);
626 } else {
627 fprintf(stderr, "%s: Bad message header: %d\n",
628 __func__, rx_buf[0]);
629 break;
630 }
631 }
632
633 tipc_close(fd);
634
635 return rx_buf[0] == TEST_PASSED ? 0 : -1;
636 }
637
638 typedef struct uuid
639 {
640 uint32_t time_low;
641 uint16_t time_mid;
642 uint16_t time_hi_and_version;
643 uint8_t clock_seq_and_node[8];
644 } uuid_t;
645
print_uuid(const char * dev,uuid_t * uuid)646 static void print_uuid(const char *dev, uuid_t *uuid)
647 {
648 printf("%s:", dev);
649 printf("uuid: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
650 uuid->time_low,
651 uuid->time_mid,
652 uuid->time_hi_and_version,
653 uuid->clock_seq_and_node[0],
654 uuid->clock_seq_and_node[1],
655 uuid->clock_seq_and_node[2],
656 uuid->clock_seq_and_node[3],
657 uuid->clock_seq_and_node[4],
658 uuid->clock_seq_and_node[5],
659 uuid->clock_seq_and_node[6],
660 uuid->clock_seq_and_node[7]
661 );
662 }
663
dev_uuid_test(void)664 static int dev_uuid_test(void)
665 {
666 int fd;
667 ssize_t rc;
668 uuid_t uuid;
669
670 fd = tipc_connect(dev_name, uuid_name);
671 if (fd < 0) {
672 fprintf(stderr, "Failed to connect to '%s' service\n",
673 "uuid");
674 return fd;
675 }
676
677 /* wait for test to complete */
678 rc = read(fd, &uuid, sizeof(uuid));
679 if (rc < 0) {
680 perror("dev_uuid_test: read");
681 } else if (rc != sizeof(uuid)) {
682 fprintf(stderr, "unexpected uuid size (%d vs. %d)\n",
683 (int)rc, (int)sizeof(uuid));
684 } else {
685 print_uuid(dev_name, &uuid);
686 }
687
688 tipc_close(fd);
689
690 return 0;
691 }
692
ta_access_test(void)693 static int ta_access_test(void)
694 {
695 int fd;
696
697 if (!opt_silent) {
698 printf("%s:\n", __func__);
699 }
700
701 fd = tipc_connect(dev_name, ta_only_name);
702 if (fd >= 0) {
703 fprintf(stderr, "Succeed to connect to '%s' service\n",
704 "ta_only");
705 tipc_close(fd);
706 }
707
708 fd = tipc_connect(dev_name, ns_only_name);
709 if (fd < 0) {
710 fprintf(stderr, "Failed to connect to '%s' service\n",
711 "ns_only");
712 return fd;
713 }
714 tipc_close(fd);
715
716 if (!opt_silent) {
717 printf("%s: done\n",__func__);
718 }
719
720 return 0;
721 }
722
723
writev_test(uint repeat,uint msgsz,bool var)724 static int writev_test(uint repeat, uint msgsz, bool var)
725 {
726 uint i;
727 ssize_t rc;
728 size_t msg_len;
729 int echo_fd = -1;
730 char tx0_buf[msgsz];
731 char tx1_buf[msgsz];
732 char rx_buf [msgsz];
733 struct iovec iovs[2]= {{tx0_buf, 0}, {tx1_buf, 0}};
734
735 if (!opt_silent) {
736 printf("%s: repeat %u: msgsz %u: variable %s\n",
737 __func__, repeat, msgsz, var ? "true" : "false");
738 }
739
740 echo_fd = tipc_connect(dev_name, echo_name);
741 if (echo_fd < 0) {
742 fprintf(stderr, "Failed to connect to service\n");
743 return echo_fd;
744 }
745
746 for (i = 0; i < repeat; i++) {
747
748 msg_len = msgsz;
749 if (opt_variable && msgsz) {
750 msg_len = rand() % msgsz;
751 }
752
753 iovs[0].iov_len = msg_len / 3;
754 iovs[1].iov_len = msg_len - iovs[0].iov_len;
755
756 memset(tx0_buf, i + 1, iovs[0].iov_len);
757 memset(tx1_buf, i + 2, iovs[1].iov_len);
758 memset(rx_buf, i + 3, sizeof(rx_buf));
759
760 rc = writev(echo_fd, iovs, 2);
761 if (rc < 0) {
762 perror("writev_test: writev");
763 break;
764 }
765
766 if ((size_t)rc != msg_len) {
767 fprintf(stderr,
768 "%s: %s: data size mismatch (%zd vs. %zd)\n",
769 __func__, "writev", (size_t)rc, msg_len);
770 break;
771 }
772
773 rc = read(echo_fd, rx_buf, sizeof(rx_buf));
774 if (rc < 0) {
775 perror("writev_test: read");
776 break;
777 }
778
779 if ((size_t)rc != msg_len) {
780 fprintf(stderr,
781 "%s: %s: data size mismatch (%zd vs. %zd)\n",
782 __func__, "read", (size_t)rc, msg_len);
783 break;
784 }
785
786 if (memcmp(tx0_buf, rx_buf, iovs[0].iov_len)) {
787 fprintf(stderr, "%s: data mismatch: buf 0\n", __func__);
788 break;
789 }
790
791 if (memcmp(tx1_buf, rx_buf + iovs[0].iov_len, iovs[1].iov_len)) {
792 fprintf(stderr, "%s: data mismatch, buf 1\n", __func__);
793 break;
794 }
795 }
796
797 tipc_close(echo_fd);
798
799 if (!opt_silent) {
800 printf("%s: done\n",__func__);
801 }
802
803 return 0;
804 }
805
readv_test(uint repeat,uint msgsz,bool var)806 static int readv_test(uint repeat, uint msgsz, bool var)
807 {
808 uint i;
809 ssize_t rc;
810 size_t msg_len;
811 int echo_fd = -1;
812 char tx_buf [msgsz];
813 char rx0_buf[msgsz];
814 char rx1_buf[msgsz];
815 struct iovec iovs[2]= {{rx0_buf, 0}, {rx1_buf, 0}};
816
817 if (!opt_silent) {
818 printf("%s: repeat %u: msgsz %u: variable %s\n",
819 __func__, repeat, msgsz, var ? "true" : "false");
820 }
821
822 echo_fd = tipc_connect(dev_name, echo_name);
823 if (echo_fd < 0) {
824 fprintf(stderr, "Failed to connect to service\n");
825 return echo_fd;
826 }
827
828 for (i = 0; i < repeat; i++) {
829
830 msg_len = msgsz;
831 if (opt_variable && msgsz) {
832 msg_len = rand() % msgsz;
833 }
834
835 iovs[0].iov_len = msg_len / 3;
836 iovs[1].iov_len = msg_len - iovs[0].iov_len;
837
838 memset(tx_buf, i + 1, sizeof(tx_buf));
839 memset(rx0_buf, i + 2, iovs[0].iov_len);
840 memset(rx1_buf, i + 3, iovs[1].iov_len);
841
842 rc = write(echo_fd, tx_buf, msg_len);
843 if (rc < 0) {
844 perror("readv_test: write");
845 break;
846 }
847
848 if ((size_t)rc != msg_len) {
849 fprintf(stderr,
850 "%s: %s: data size mismatch (%zd vs. %zd)\n",
851 __func__, "write", (size_t)rc, msg_len);
852 break;
853 }
854
855 rc = readv(echo_fd, iovs, 2);
856 if (rc < 0) {
857 perror("readv_test: readv");
858 break;
859 }
860
861 if ((size_t)rc != msg_len) {
862 fprintf(stderr,
863 "%s: %s: data size mismatch (%zd vs. %zd)\n",
864 __func__, "write", (size_t)rc, msg_len);
865 break;
866 }
867
868 if (memcmp(rx0_buf, tx_buf, iovs[0].iov_len)) {
869 fprintf(stderr, "%s: data mismatch: buf 0\n", __func__);
870 break;
871 }
872
873 if (memcmp(rx1_buf, tx_buf + iovs[0].iov_len, iovs[1].iov_len)) {
874 fprintf(stderr, "%s: data mismatch, buf 1\n", __func__);
875 break;
876 }
877 }
878
879 tipc_close(echo_fd);
880
881 if (!opt_silent) {
882 printf("%s: done\n",__func__);
883 }
884
885 return 0;
886 }
887
888
main(int argc,char ** argv)889 int main(int argc, char **argv)
890 {
891 int rc = 0;
892
893 if (argc <= 1) {
894 print_usage_and_exit(argv[0], EXIT_FAILURE, false);
895 }
896
897 parse_options(argc, argv);
898
899 if (!dev_name) {
900 dev_name = TIPC_DEFAULT_DEVNAME;
901 }
902
903 if (!test_name) {
904 fprintf(stderr, "need a Test to run\n");
905 print_usage_and_exit(argv[0], EXIT_FAILURE, true);
906 }
907
908 if (strcmp(test_name, "connect") == 0) {
909 rc = connect_test(opt_repeat);
910 } else if (strcmp(test_name, "connect_foo") == 0) {
911 rc = connect_foo(opt_repeat);
912 } else if (strcmp(test_name, "burst_write") == 0) {
913 rc = burst_write_test(opt_repeat, opt_msgburst, opt_msgsize, opt_variable);
914 } else if (strcmp(test_name, "select") == 0) {
915 rc = select_test(opt_repeat, opt_msgburst, opt_msgsize);
916 } else if (strcmp(test_name, "blocked_read") == 0) {
917 rc = blocked_read_test(opt_repeat);
918 } else if (strcmp(test_name, "closer1") == 0) {
919 rc = closer1_test(opt_repeat);
920 } else if (strcmp(test_name, "closer2") == 0) {
921 rc = closer2_test(opt_repeat);
922 } else if (strcmp(test_name, "closer3") == 0) {
923 rc = closer3_test(opt_repeat);
924 } else if (strcmp(test_name, "echo") == 0) {
925 rc = echo_test(opt_repeat, opt_msgsize, opt_variable);
926 } else if(strcmp(test_name, "ta2ta-ipc") == 0) {
927 rc = ta2ta_ipc_test();
928 } else if (strcmp(test_name, "dev-uuid") == 0) {
929 rc = dev_uuid_test();
930 } else if (strcmp(test_name, "ta-access") == 0) {
931 rc = ta_access_test();
932 } else if (strcmp(test_name, "writev") == 0) {
933 rc = writev_test(opt_repeat, opt_msgsize, opt_variable);
934 } else if (strcmp(test_name, "readv") == 0) {
935 rc = readv_test(opt_repeat, opt_msgsize, opt_variable);
936 } else {
937 fprintf(stderr, "Unrecognized test name '%s'\n", test_name);
938 print_usage_and_exit(argv[0], EXIT_FAILURE, true);
939 }
940
941 return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
942 }
943