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
30static const char *dev_name = NULL;
31static const char *test_name = NULL;
32
33static const char *uuid_name = "com.android.ipc-unittest.srv.uuid";
34static const char *echo_name = "com.android.ipc-unittest.srv.echo";
35static const char *ta_only_name = "com.android.ipc-unittest.srv.ta_only";
36static const char *ns_only_name = "com.android.ipc-unittest.srv.ns_only";
37static const char *datasink_name = "com.android.ipc-unittest.srv.datasink";
38static const char *closer1_name = "com.android.ipc-unittest.srv.closer1";
39static const char *closer2_name = "com.android.ipc-unittest.srv.closer2";
40static const char *closer3_name = "com.android.ipc-unittest.srv.closer3";
41static const char *main_ctrl_name = "com.android.ipc-unittest.ctrl";
42
43static const char *_sopts = "hsvD:t:r:m:b:";
44static 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
55static 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
69static 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
89static uint opt_repeat  = 1;
90static uint opt_msgsize = 32;
91static uint opt_msgburst = 32;
92static bool opt_variable = false;
93static bool opt_silent = false;
94
95static 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
103static 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
154static 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
191static 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
217static 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
246static 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
275static 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
342static 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
404static 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
452static 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
504static 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
549static 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
588static int ta2ta_ipc_test(void)
589{
590	int fd;
591	char rx_buf[64];
592
593	if (!opt_silent) {
594		printf("%s:\n", __func__);
595	}
596
597	fd = tipc_connect(dev_name, main_ctrl_name);
598	if (fd < 0) {
599		fprintf(stderr, "Failed to connect to '%s' service\n",
600			"main_ctrl");
601		return fd;
602	}
603
604	/* wait for test to complete */
605	(void) read(fd, rx_buf, sizeof(rx_buf));
606
607	tipc_close(fd);
608
609	return 0;
610}
611
612typedef struct uuid
613{
614	uint32_t time_low;
615	uint16_t time_mid;
616	uint16_t time_hi_and_version;
617	uint8_t clock_seq_and_node[8];
618} uuid_t;
619
620static void print_uuid(const char *dev, uuid_t *uuid)
621{
622	printf("%s:", dev);
623	printf("uuid: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
624	       uuid->time_low,
625	       uuid->time_mid,
626	       uuid->time_hi_and_version,
627	       uuid->clock_seq_and_node[0],
628	       uuid->clock_seq_and_node[1],
629	       uuid->clock_seq_and_node[2],
630	       uuid->clock_seq_and_node[3],
631	       uuid->clock_seq_and_node[4],
632	       uuid->clock_seq_and_node[5],
633	       uuid->clock_seq_and_node[6],
634	       uuid->clock_seq_and_node[7]
635	       );
636}
637
638static int dev_uuid_test(void)
639{
640	int fd;
641	ssize_t rc;
642	uuid_t uuid;
643
644	fd = tipc_connect(dev_name, uuid_name);
645	if (fd < 0) {
646		fprintf(stderr, "Failed to connect to '%s' service\n",
647			"uuid");
648		return fd;
649	}
650
651	/* wait for test to complete */
652	rc = read(fd, &uuid, sizeof(uuid));
653	if (rc < 0) {
654		perror("dev_uuid_test: read");
655	} else if (rc != sizeof(uuid)) {
656		fprintf(stderr, "unexpected uuid size (%d vs. %d)\n",
657			(int)rc, (int)sizeof(uuid));
658	} else {
659		print_uuid(dev_name, &uuid);
660	}
661
662	tipc_close(fd);
663
664	return 0;
665}
666
667static int ta_access_test(void)
668{
669	int fd;
670
671	if (!opt_silent) {
672		printf("%s:\n", __func__);
673	}
674
675	fd = tipc_connect(dev_name, ta_only_name);
676	if (fd >= 0) {
677		fprintf(stderr, "Succeed to connect to '%s' service\n",
678			"ta_only");
679		tipc_close(fd);
680	}
681
682	fd = tipc_connect(dev_name, ns_only_name);
683	if (fd < 0) {
684		fprintf(stderr, "Failed to connect to '%s' service\n",
685			"ns_only");
686		return fd;
687	}
688	tipc_close(fd);
689
690	if (!opt_silent) {
691		printf("%s: done\n",__func__);
692	}
693
694	return 0;
695}
696
697
698static int writev_test(uint repeat, uint msgsz, bool var)
699{
700	uint i;
701	ssize_t rc;
702	size_t  msg_len;
703	int  echo_fd = -1;
704	char tx0_buf[msgsz];
705	char tx1_buf[msgsz];
706	char rx_buf [msgsz];
707	struct iovec iovs[2]= {{tx0_buf, 0}, {tx1_buf, 0}};
708
709	if (!opt_silent) {
710		printf("%s: repeat %u: msgsz %u: variable %s\n",
711			__func__, repeat, msgsz, var ? "true" : "false");
712	}
713
714	echo_fd = tipc_connect(dev_name, echo_name);
715	if (echo_fd < 0) {
716		fprintf(stderr, "Failed to connect to service\n");
717		return echo_fd;
718	}
719
720	for (i = 0; i < repeat; i++) {
721
722		msg_len = msgsz;
723		if (opt_variable && msgsz) {
724			msg_len = rand() % msgsz;
725		}
726
727		iovs[0].iov_len = msg_len / 3;
728		iovs[1].iov_len = msg_len - iovs[0].iov_len;
729
730		memset(tx0_buf, i + 1, iovs[0].iov_len);
731		memset(tx1_buf, i + 2, iovs[1].iov_len);
732		memset(rx_buf,  i + 3, sizeof(rx_buf));
733
734		rc = writev(echo_fd, iovs, 2);
735		if (rc < 0) {
736			perror("writev_test: writev");
737			break;
738		}
739
740		if ((size_t)rc != msg_len) {
741			fprintf(stderr,
742				"%s: %s: data size mismatch (%zd vs. %zd)\n",
743				__func__, "writev", (size_t)rc, msg_len);
744			break;
745		}
746
747		rc = read(echo_fd, rx_buf, sizeof(rx_buf));
748		if (rc < 0) {
749			perror("writev_test: read");
750			break;
751		}
752
753		if ((size_t)rc != msg_len) {
754			fprintf(stderr,
755				"%s: %s: data size mismatch (%zd vs. %zd)\n",
756				__func__, "read", (size_t)rc, msg_len);
757			break;
758		}
759
760		if (memcmp(tx0_buf, rx_buf, iovs[0].iov_len)) {
761			fprintf(stderr, "%s: data mismatch: buf 0\n", __func__);
762			break;
763		}
764
765		if (memcmp(tx1_buf, rx_buf + iovs[0].iov_len, iovs[1].iov_len)) {
766			fprintf(stderr, "%s: data mismatch, buf 1\n", __func__);
767			break;
768		}
769	}
770
771	tipc_close(echo_fd);
772
773	if (!opt_silent) {
774		printf("%s: done\n",__func__);
775	}
776
777	return 0;
778}
779
780static int readv_test(uint repeat, uint msgsz, bool var)
781{
782	uint i;
783	ssize_t rc;
784	size_t  msg_len;
785	int  echo_fd = -1;
786	char tx_buf [msgsz];
787	char rx0_buf[msgsz];
788	char rx1_buf[msgsz];
789	struct iovec iovs[2]= {{rx0_buf, 0}, {rx1_buf, 0}};
790
791	if (!opt_silent) {
792		printf("%s: repeat %u: msgsz %u: variable %s\n",
793			__func__, repeat, msgsz, var ? "true" : "false");
794	}
795
796	echo_fd = tipc_connect(dev_name, echo_name);
797	if (echo_fd < 0) {
798		fprintf(stderr, "Failed to connect to service\n");
799		return echo_fd;
800	}
801
802	for (i = 0; i < repeat; i++) {
803
804		msg_len = msgsz;
805		if (opt_variable && msgsz) {
806			msg_len = rand() % msgsz;
807		}
808
809		iovs[0].iov_len = msg_len / 3;
810		iovs[1].iov_len = msg_len - iovs[0].iov_len;
811
812		memset(tx_buf,  i + 1, sizeof(tx_buf));
813		memset(rx0_buf, i + 2, iovs[0].iov_len);
814		memset(rx1_buf, i + 3, iovs[1].iov_len);
815
816		rc = write(echo_fd, tx_buf, msg_len);
817		if (rc < 0) {
818			perror("readv_test: write");
819			break;
820		}
821
822		if ((size_t)rc != msg_len) {
823			fprintf(stderr,
824				"%s: %s: data size mismatch (%zd vs. %zd)\n",
825				__func__, "write", (size_t)rc, msg_len);
826			break;
827		}
828
829		rc = readv(echo_fd, iovs, 2);
830		if (rc < 0) {
831			perror("readv_test: readv");
832			break;
833		}
834
835		if ((size_t)rc != msg_len) {
836			fprintf(stderr,
837				"%s: %s: data size mismatch (%zd vs. %zd)\n",
838				__func__, "write", (size_t)rc, msg_len);
839			break;
840		}
841
842		if (memcmp(rx0_buf, tx_buf, iovs[0].iov_len)) {
843			fprintf(stderr, "%s: data mismatch: buf 0\n", __func__);
844			break;
845		}
846
847		if (memcmp(rx1_buf, tx_buf + iovs[0].iov_len, iovs[1].iov_len)) {
848			fprintf(stderr, "%s: data mismatch, buf 1\n", __func__);
849			break;
850		}
851	}
852
853	tipc_close(echo_fd);
854
855	if (!opt_silent) {
856		printf("%s: done\n",__func__);
857	}
858
859	return 0;
860}
861
862
863int main(int argc, char **argv)
864{
865	int rc = 0;
866
867	if (argc <= 1) {
868		print_usage_and_exit(argv[0], EXIT_FAILURE, false);
869	}
870
871	parse_options(argc, argv);
872
873	if (!dev_name) {
874		dev_name = TIPC_DEFAULT_DEVNAME;
875	}
876
877	if (!test_name) {
878		fprintf(stderr, "need a Test to run\n");
879		print_usage_and_exit(argv[0], EXIT_FAILURE, true);
880	}
881
882	if (strcmp(test_name, "connect") == 0) {
883		rc = connect_test(opt_repeat);
884	} else if (strcmp(test_name, "connect_foo") == 0) {
885		rc = connect_foo(opt_repeat);
886	} else if (strcmp(test_name, "burst_write") == 0) {
887		rc = burst_write_test(opt_repeat, opt_msgburst, opt_msgsize, opt_variable);
888	} else if (strcmp(test_name, "select") == 0) {
889		rc = select_test(opt_repeat, opt_msgburst,  opt_msgsize);
890	} else if (strcmp(test_name, "blocked_read") == 0) {
891		rc = blocked_read_test(opt_repeat);
892	} else if (strcmp(test_name, "closer1") == 0) {
893		rc = closer1_test(opt_repeat);
894	} else if (strcmp(test_name, "closer2") == 0) {
895		rc = closer2_test(opt_repeat);
896	} else if (strcmp(test_name, "closer3") == 0) {
897		rc = closer3_test(opt_repeat);
898	} else if (strcmp(test_name, "echo") == 0) {
899		rc = echo_test(opt_repeat, opt_msgsize, opt_variable);
900	} else if(strcmp(test_name, "ta2ta-ipc") == 0) {
901		rc = ta2ta_ipc_test();
902	} else if (strcmp(test_name, "dev-uuid") == 0) {
903		rc = dev_uuid_test();
904	} else if (strcmp(test_name, "ta-access") == 0) {
905		rc = ta_access_test();
906	} else if (strcmp(test_name, "writev") == 0) {
907		rc = writev_test(opt_repeat, opt_msgsize, opt_variable);
908	} else if (strcmp(test_name, "readv") == 0) {
909		rc = readv_test(opt_repeat, opt_msgsize, opt_variable);
910	} else {
911		fprintf(stderr, "Unrecognized test name '%s'\n", test_name);
912		print_usage_and_exit(argv[0], EXIT_FAILURE, true);
913	}
914
915	return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
916}
917