xref: /linux/tools/testing/selftests/net/af_unix/scm_rights.c (revision 033771c085c2ed73cb29dd25e1ec8c4b2991cad9)
12aa0cff2SKuniyuki Iwashima // SPDX-License-Identifier: GPL-2.0
22aa0cff2SKuniyuki Iwashima /* Copyright Amazon.com Inc. or its affiliates. */
32aa0cff2SKuniyuki Iwashima #define _GNU_SOURCE
42aa0cff2SKuniyuki Iwashima #include <sched.h>
52aa0cff2SKuniyuki Iwashima 
62aa0cff2SKuniyuki Iwashima #include <stdio.h>
72aa0cff2SKuniyuki Iwashima #include <string.h>
82aa0cff2SKuniyuki Iwashima #include <unistd.h>
92aa0cff2SKuniyuki Iwashima #include <sys/types.h>
102aa0cff2SKuniyuki Iwashima #include <sys/socket.h>
112aa0cff2SKuniyuki Iwashima #include <sys/un.h>
122aa0cff2SKuniyuki Iwashima 
132aa0cff2SKuniyuki Iwashima #include "../../kselftest_harness.h"
142aa0cff2SKuniyuki Iwashima 
FIXTURE(scm_rights)152aa0cff2SKuniyuki Iwashima FIXTURE(scm_rights)
162aa0cff2SKuniyuki Iwashima {
17*2a79651bSKuniyuki Iwashima 	int fd[32];
182aa0cff2SKuniyuki Iwashima };
192aa0cff2SKuniyuki Iwashima 
FIXTURE_VARIANT(scm_rights)202aa0cff2SKuniyuki Iwashima FIXTURE_VARIANT(scm_rights)
212aa0cff2SKuniyuki Iwashima {
22*2a79651bSKuniyuki Iwashima 	char name[32];
232aa0cff2SKuniyuki Iwashima 	int type;
242aa0cff2SKuniyuki Iwashima 	int flags;
252aa0cff2SKuniyuki Iwashima 	bool test_listener;
262aa0cff2SKuniyuki Iwashima };
272aa0cff2SKuniyuki Iwashima 
FIXTURE_VARIANT_ADD(scm_rights,dgram)282aa0cff2SKuniyuki Iwashima FIXTURE_VARIANT_ADD(scm_rights, dgram)
292aa0cff2SKuniyuki Iwashima {
302aa0cff2SKuniyuki Iwashima 	.name = "UNIX ",
312aa0cff2SKuniyuki Iwashima 	.type = SOCK_DGRAM,
322aa0cff2SKuniyuki Iwashima 	.flags = 0,
332aa0cff2SKuniyuki Iwashima 	.test_listener = false,
342aa0cff2SKuniyuki Iwashima };
352aa0cff2SKuniyuki Iwashima 
FIXTURE_VARIANT_ADD(scm_rights,stream)362aa0cff2SKuniyuki Iwashima FIXTURE_VARIANT_ADD(scm_rights, stream)
372aa0cff2SKuniyuki Iwashima {
382aa0cff2SKuniyuki Iwashima 	.name = "UNIX-STREAM ",
392aa0cff2SKuniyuki Iwashima 	.type = SOCK_STREAM,
402aa0cff2SKuniyuki Iwashima 	.flags = 0,
412aa0cff2SKuniyuki Iwashima 	.test_listener = false,
422aa0cff2SKuniyuki Iwashima };
432aa0cff2SKuniyuki Iwashima 
FIXTURE_VARIANT_ADD(scm_rights,stream_oob)442aa0cff2SKuniyuki Iwashima FIXTURE_VARIANT_ADD(scm_rights, stream_oob)
452aa0cff2SKuniyuki Iwashima {
462aa0cff2SKuniyuki Iwashima 	.name = "UNIX-STREAM ",
472aa0cff2SKuniyuki Iwashima 	.type = SOCK_STREAM,
482aa0cff2SKuniyuki Iwashima 	.flags = MSG_OOB,
492aa0cff2SKuniyuki Iwashima 	.test_listener = false,
502aa0cff2SKuniyuki Iwashima };
512aa0cff2SKuniyuki Iwashima 
FIXTURE_VARIANT_ADD(scm_rights,stream_listener)522aa0cff2SKuniyuki Iwashima FIXTURE_VARIANT_ADD(scm_rights, stream_listener)
532aa0cff2SKuniyuki Iwashima {
542aa0cff2SKuniyuki Iwashima 	.name = "UNIX-STREAM ",
552aa0cff2SKuniyuki Iwashima 	.type = SOCK_STREAM,
562aa0cff2SKuniyuki Iwashima 	.flags = 0,
572aa0cff2SKuniyuki Iwashima 	.test_listener = true,
582aa0cff2SKuniyuki Iwashima };
592aa0cff2SKuniyuki Iwashima 
FIXTURE_VARIANT_ADD(scm_rights,stream_listener_oob)602aa0cff2SKuniyuki Iwashima FIXTURE_VARIANT_ADD(scm_rights, stream_listener_oob)
612aa0cff2SKuniyuki Iwashima {
622aa0cff2SKuniyuki Iwashima 	.name = "UNIX-STREAM ",
632aa0cff2SKuniyuki Iwashima 	.type = SOCK_STREAM,
642aa0cff2SKuniyuki Iwashima 	.flags = MSG_OOB,
652aa0cff2SKuniyuki Iwashima 	.test_listener = true,
662aa0cff2SKuniyuki Iwashima };
672aa0cff2SKuniyuki Iwashima 
count_sockets(struct __test_metadata * _metadata,const FIXTURE_VARIANT (scm_rights)* variant)682aa0cff2SKuniyuki Iwashima static int count_sockets(struct __test_metadata *_metadata,
692aa0cff2SKuniyuki Iwashima 			 const FIXTURE_VARIANT(scm_rights) *variant)
702aa0cff2SKuniyuki Iwashima {
712aa0cff2SKuniyuki Iwashima 	int sockets = -1, len, ret;
722aa0cff2SKuniyuki Iwashima 	char *line = NULL;
732aa0cff2SKuniyuki Iwashima 	size_t unused;
742aa0cff2SKuniyuki Iwashima 	FILE *f;
752aa0cff2SKuniyuki Iwashima 
762aa0cff2SKuniyuki Iwashima 	f = fopen("/proc/net/protocols", "r");
772aa0cff2SKuniyuki Iwashima 	ASSERT_NE(NULL, f);
782aa0cff2SKuniyuki Iwashima 
792aa0cff2SKuniyuki Iwashima 	len = strlen(variant->name);
802aa0cff2SKuniyuki Iwashima 
812aa0cff2SKuniyuki Iwashima 	while (getline(&line, &unused, f) != -1) {
822aa0cff2SKuniyuki Iwashima 		int unused2;
832aa0cff2SKuniyuki Iwashima 
842aa0cff2SKuniyuki Iwashima 		if (strncmp(line, variant->name, len))
852aa0cff2SKuniyuki Iwashima 			continue;
862aa0cff2SKuniyuki Iwashima 
872aa0cff2SKuniyuki Iwashima 		ret = sscanf(line + len, "%d %d", &unused2, &sockets);
882aa0cff2SKuniyuki Iwashima 		ASSERT_EQ(2, ret);
892aa0cff2SKuniyuki Iwashima 
902aa0cff2SKuniyuki Iwashima 		break;
912aa0cff2SKuniyuki Iwashima 	}
922aa0cff2SKuniyuki Iwashima 
932aa0cff2SKuniyuki Iwashima 	free(line);
942aa0cff2SKuniyuki Iwashima 
952aa0cff2SKuniyuki Iwashima 	ret = fclose(f);
962aa0cff2SKuniyuki Iwashima 	ASSERT_EQ(0, ret);
972aa0cff2SKuniyuki Iwashima 
982aa0cff2SKuniyuki Iwashima 	return sockets;
992aa0cff2SKuniyuki Iwashima }
1002aa0cff2SKuniyuki Iwashima 
FIXTURE_SETUP(scm_rights)1012aa0cff2SKuniyuki Iwashima FIXTURE_SETUP(scm_rights)
1022aa0cff2SKuniyuki Iwashima {
1032aa0cff2SKuniyuki Iwashima 	int ret;
1042aa0cff2SKuniyuki Iwashima 
1052aa0cff2SKuniyuki Iwashima 	ret = unshare(CLONE_NEWNET);
1062aa0cff2SKuniyuki Iwashima 	ASSERT_EQ(0, ret);
1072aa0cff2SKuniyuki Iwashima 
1082aa0cff2SKuniyuki Iwashima 	ret = count_sockets(_metadata, variant);
1092aa0cff2SKuniyuki Iwashima 	ASSERT_EQ(0, ret);
1102aa0cff2SKuniyuki Iwashima }
1112aa0cff2SKuniyuki Iwashima 
FIXTURE_TEARDOWN(scm_rights)1122aa0cff2SKuniyuki Iwashima FIXTURE_TEARDOWN(scm_rights)
1132aa0cff2SKuniyuki Iwashima {
1142aa0cff2SKuniyuki Iwashima 	int ret;
1152aa0cff2SKuniyuki Iwashima 
1162aa0cff2SKuniyuki Iwashima 	sleep(1);
1172aa0cff2SKuniyuki Iwashima 
1182aa0cff2SKuniyuki Iwashima 	ret = count_sockets(_metadata, variant);
1192aa0cff2SKuniyuki Iwashima 	ASSERT_EQ(0, ret);
1202aa0cff2SKuniyuki Iwashima }
1212aa0cff2SKuniyuki Iwashima 
create_listeners(struct __test_metadata * _metadata,FIXTURE_DATA (scm_rights)* self,int n)1222aa0cff2SKuniyuki Iwashima static void create_listeners(struct __test_metadata *_metadata,
1232aa0cff2SKuniyuki Iwashima 			     FIXTURE_DATA(scm_rights) *self,
1242aa0cff2SKuniyuki Iwashima 			     int n)
1252aa0cff2SKuniyuki Iwashima {
1262aa0cff2SKuniyuki Iwashima 	struct sockaddr_un addr = {
1272aa0cff2SKuniyuki Iwashima 		.sun_family = AF_UNIX,
1282aa0cff2SKuniyuki Iwashima 	};
1292aa0cff2SKuniyuki Iwashima 	socklen_t addrlen;
1302aa0cff2SKuniyuki Iwashima 	int i, ret;
1312aa0cff2SKuniyuki Iwashima 
1322aa0cff2SKuniyuki Iwashima 	for (i = 0; i < n * 2; i += 2) {
1332aa0cff2SKuniyuki Iwashima 		self->fd[i] = socket(AF_UNIX, SOCK_STREAM, 0);
1342aa0cff2SKuniyuki Iwashima 		ASSERT_LE(0, self->fd[i]);
1352aa0cff2SKuniyuki Iwashima 
1362aa0cff2SKuniyuki Iwashima 		addrlen = sizeof(addr.sun_family);
1372aa0cff2SKuniyuki Iwashima 		ret = bind(self->fd[i], (struct sockaddr *)&addr, addrlen);
1382aa0cff2SKuniyuki Iwashima 		ASSERT_EQ(0, ret);
1392aa0cff2SKuniyuki Iwashima 
1402aa0cff2SKuniyuki Iwashima 		ret = listen(self->fd[i], -1);
1412aa0cff2SKuniyuki Iwashima 		ASSERT_EQ(0, ret);
1422aa0cff2SKuniyuki Iwashima 
1432aa0cff2SKuniyuki Iwashima 		addrlen = sizeof(addr);
1442aa0cff2SKuniyuki Iwashima 		ret = getsockname(self->fd[i], (struct sockaddr *)&addr, &addrlen);
1452aa0cff2SKuniyuki Iwashima 		ASSERT_EQ(0, ret);
1462aa0cff2SKuniyuki Iwashima 
1472aa0cff2SKuniyuki Iwashima 		self->fd[i + 1] = socket(AF_UNIX, SOCK_STREAM, 0);
1482aa0cff2SKuniyuki Iwashima 		ASSERT_LE(0, self->fd[i + 1]);
1492aa0cff2SKuniyuki Iwashima 
1502aa0cff2SKuniyuki Iwashima 		ret = connect(self->fd[i + 1], (struct sockaddr *)&addr, addrlen);
1512aa0cff2SKuniyuki Iwashima 		ASSERT_EQ(0, ret);
1522aa0cff2SKuniyuki Iwashima 	}
1532aa0cff2SKuniyuki Iwashima }
1542aa0cff2SKuniyuki Iwashima 
create_socketpairs(struct __test_metadata * _metadata,FIXTURE_DATA (scm_rights)* self,const FIXTURE_VARIANT (scm_rights)* variant,int n)1552aa0cff2SKuniyuki Iwashima static void create_socketpairs(struct __test_metadata *_metadata,
1562aa0cff2SKuniyuki Iwashima 			       FIXTURE_DATA(scm_rights) *self,
1572aa0cff2SKuniyuki Iwashima 			       const FIXTURE_VARIANT(scm_rights) *variant,
1582aa0cff2SKuniyuki Iwashima 			       int n)
1592aa0cff2SKuniyuki Iwashima {
1602aa0cff2SKuniyuki Iwashima 	int i, ret;
1612aa0cff2SKuniyuki Iwashima 
1622aa0cff2SKuniyuki Iwashima 	ASSERT_GE(sizeof(self->fd) / sizeof(int), n);
1632aa0cff2SKuniyuki Iwashima 
1642aa0cff2SKuniyuki Iwashima 	for (i = 0; i < n * 2; i += 2) {
1652aa0cff2SKuniyuki Iwashima 		ret = socketpair(AF_UNIX, variant->type, 0, self->fd + i);
1662aa0cff2SKuniyuki Iwashima 		ASSERT_EQ(0, ret);
1672aa0cff2SKuniyuki Iwashima 	}
1682aa0cff2SKuniyuki Iwashima }
1692aa0cff2SKuniyuki Iwashima 
__create_sockets(struct __test_metadata * _metadata,FIXTURE_DATA (scm_rights)* self,const FIXTURE_VARIANT (scm_rights)* variant,int n)1702aa0cff2SKuniyuki Iwashima static void __create_sockets(struct __test_metadata *_metadata,
1712aa0cff2SKuniyuki Iwashima 			     FIXTURE_DATA(scm_rights) *self,
1722aa0cff2SKuniyuki Iwashima 			     const FIXTURE_VARIANT(scm_rights) *variant,
1732aa0cff2SKuniyuki Iwashima 			     int n)
1742aa0cff2SKuniyuki Iwashima {
175*2a79651bSKuniyuki Iwashima 	ASSERT_LE(n * 2, sizeof(self->fd) / sizeof(self->fd[0]));
176*2a79651bSKuniyuki Iwashima 
1772aa0cff2SKuniyuki Iwashima 	if (variant->test_listener)
1782aa0cff2SKuniyuki Iwashima 		create_listeners(_metadata, self, n);
1792aa0cff2SKuniyuki Iwashima 	else
1802aa0cff2SKuniyuki Iwashima 		create_socketpairs(_metadata, self, variant, n);
1812aa0cff2SKuniyuki Iwashima }
1822aa0cff2SKuniyuki Iwashima 
__close_sockets(struct __test_metadata * _metadata,FIXTURE_DATA (scm_rights)* self,int n)1832aa0cff2SKuniyuki Iwashima static void __close_sockets(struct __test_metadata *_metadata,
1842aa0cff2SKuniyuki Iwashima 			    FIXTURE_DATA(scm_rights) *self,
1852aa0cff2SKuniyuki Iwashima 			    int n)
1862aa0cff2SKuniyuki Iwashima {
1872aa0cff2SKuniyuki Iwashima 	int i, ret;
1882aa0cff2SKuniyuki Iwashima 
1892aa0cff2SKuniyuki Iwashima 	ASSERT_GE(sizeof(self->fd) / sizeof(int), n);
1902aa0cff2SKuniyuki Iwashima 
1912aa0cff2SKuniyuki Iwashima 	for (i = 0; i < n * 2; i++) {
1922aa0cff2SKuniyuki Iwashima 		ret = close(self->fd[i]);
1932aa0cff2SKuniyuki Iwashima 		ASSERT_EQ(0, ret);
1942aa0cff2SKuniyuki Iwashima 	}
1952aa0cff2SKuniyuki Iwashima }
1962aa0cff2SKuniyuki Iwashima 
__send_fd(struct __test_metadata * _metadata,const FIXTURE_DATA (scm_rights)* self,const FIXTURE_VARIANT (scm_rights)* variant,int inflight,int receiver)1972aa0cff2SKuniyuki Iwashima void __send_fd(struct __test_metadata *_metadata,
1982aa0cff2SKuniyuki Iwashima 	       const FIXTURE_DATA(scm_rights) *self,
1992aa0cff2SKuniyuki Iwashima 	       const FIXTURE_VARIANT(scm_rights) *variant,
2002aa0cff2SKuniyuki Iwashima 	       int inflight, int receiver)
2012aa0cff2SKuniyuki Iwashima {
202e060e433SKuniyuki Iwashima #define MSG "x"
203e060e433SKuniyuki Iwashima #define MSGLEN 1
2042aa0cff2SKuniyuki Iwashima 	struct {
2052aa0cff2SKuniyuki Iwashima 		struct cmsghdr cmsghdr;
2062aa0cff2SKuniyuki Iwashima 		int fd[2];
2072aa0cff2SKuniyuki Iwashima 	} cmsg = {
2082aa0cff2SKuniyuki Iwashima 		.cmsghdr = {
2092aa0cff2SKuniyuki Iwashima 			.cmsg_len = CMSG_LEN(sizeof(cmsg.fd)),
2102aa0cff2SKuniyuki Iwashima 			.cmsg_level = SOL_SOCKET,
2112aa0cff2SKuniyuki Iwashima 			.cmsg_type = SCM_RIGHTS,
2122aa0cff2SKuniyuki Iwashima 		},
2132aa0cff2SKuniyuki Iwashima 		.fd = {
2142aa0cff2SKuniyuki Iwashima 			self->fd[inflight * 2],
2152aa0cff2SKuniyuki Iwashima 			self->fd[inflight * 2],
2162aa0cff2SKuniyuki Iwashima 		},
2172aa0cff2SKuniyuki Iwashima 	};
2182aa0cff2SKuniyuki Iwashima 	struct iovec iov = {
2192aa0cff2SKuniyuki Iwashima 		.iov_base = MSG,
2202aa0cff2SKuniyuki Iwashima 		.iov_len = MSGLEN,
2212aa0cff2SKuniyuki Iwashima 	};
2222aa0cff2SKuniyuki Iwashima 	struct msghdr msg = {
2232aa0cff2SKuniyuki Iwashima 		.msg_name = NULL,
2242aa0cff2SKuniyuki Iwashima 		.msg_namelen = 0,
2252aa0cff2SKuniyuki Iwashima 		.msg_iov = &iov,
2262aa0cff2SKuniyuki Iwashima 		.msg_iovlen = 1,
2272aa0cff2SKuniyuki Iwashima 		.msg_control = &cmsg,
2282aa0cff2SKuniyuki Iwashima 		.msg_controllen = CMSG_SPACE(sizeof(cmsg.fd)),
2292aa0cff2SKuniyuki Iwashima 	};
2302aa0cff2SKuniyuki Iwashima 	int ret;
2312aa0cff2SKuniyuki Iwashima 
2322aa0cff2SKuniyuki Iwashima 	ret = sendmsg(self->fd[receiver * 2 + 1], &msg, variant->flags);
2332aa0cff2SKuniyuki Iwashima 	ASSERT_EQ(MSGLEN, ret);
2342aa0cff2SKuniyuki Iwashima }
2352aa0cff2SKuniyuki Iwashima 
2362aa0cff2SKuniyuki Iwashima #define create_sockets(n)					\
2372aa0cff2SKuniyuki Iwashima 	__create_sockets(_metadata, self, variant, n)
2382aa0cff2SKuniyuki Iwashima #define close_sockets(n)					\
2392aa0cff2SKuniyuki Iwashima 	__close_sockets(_metadata, self, n)
2402aa0cff2SKuniyuki Iwashima #define send_fd(inflight, receiver)				\
2412aa0cff2SKuniyuki Iwashima 	__send_fd(_metadata, self, variant, inflight, receiver)
2422aa0cff2SKuniyuki Iwashima 
TEST_F(scm_rights,self_ref)2432aa0cff2SKuniyuki Iwashima TEST_F(scm_rights, self_ref)
2442aa0cff2SKuniyuki Iwashima {
2452aa0cff2SKuniyuki Iwashima 	create_sockets(2);
2462aa0cff2SKuniyuki Iwashima 
2472aa0cff2SKuniyuki Iwashima 	send_fd(0, 0);
2482aa0cff2SKuniyuki Iwashima 
2492aa0cff2SKuniyuki Iwashima 	send_fd(1, 1);
2502aa0cff2SKuniyuki Iwashima 
2512aa0cff2SKuniyuki Iwashima 	close_sockets(2);
2522aa0cff2SKuniyuki Iwashima }
2532aa0cff2SKuniyuki Iwashima 
TEST_F(scm_rights,triangle)2542aa0cff2SKuniyuki Iwashima TEST_F(scm_rights, triangle)
2552aa0cff2SKuniyuki Iwashima {
2562aa0cff2SKuniyuki Iwashima 	create_sockets(6);
2572aa0cff2SKuniyuki Iwashima 
2582aa0cff2SKuniyuki Iwashima 	send_fd(0, 1);
2592aa0cff2SKuniyuki Iwashima 	send_fd(1, 2);
2602aa0cff2SKuniyuki Iwashima 	send_fd(2, 0);
2612aa0cff2SKuniyuki Iwashima 
2622aa0cff2SKuniyuki Iwashima 	send_fd(3, 4);
2632aa0cff2SKuniyuki Iwashima 	send_fd(4, 5);
2642aa0cff2SKuniyuki Iwashima 	send_fd(5, 3);
2652aa0cff2SKuniyuki Iwashima 
2662aa0cff2SKuniyuki Iwashima 	close_sockets(6);
2672aa0cff2SKuniyuki Iwashima }
2682aa0cff2SKuniyuki Iwashima 
TEST_F(scm_rights,cross_edge)2692aa0cff2SKuniyuki Iwashima TEST_F(scm_rights, cross_edge)
2702aa0cff2SKuniyuki Iwashima {
2712aa0cff2SKuniyuki Iwashima 	create_sockets(8);
2722aa0cff2SKuniyuki Iwashima 
2732aa0cff2SKuniyuki Iwashima 	send_fd(0, 1);
2742aa0cff2SKuniyuki Iwashima 	send_fd(1, 2);
2752aa0cff2SKuniyuki Iwashima 	send_fd(2, 0);
2762aa0cff2SKuniyuki Iwashima 	send_fd(1, 3);
2772aa0cff2SKuniyuki Iwashima 	send_fd(3, 2);
2782aa0cff2SKuniyuki Iwashima 
2792aa0cff2SKuniyuki Iwashima 	send_fd(4, 5);
2802aa0cff2SKuniyuki Iwashima 	send_fd(5, 6);
2812aa0cff2SKuniyuki Iwashima 	send_fd(6, 4);
2822aa0cff2SKuniyuki Iwashima 	send_fd(5, 7);
2832aa0cff2SKuniyuki Iwashima 	send_fd(7, 6);
2842aa0cff2SKuniyuki Iwashima 
2852aa0cff2SKuniyuki Iwashima 	close_sockets(8);
2862aa0cff2SKuniyuki Iwashima }
2872aa0cff2SKuniyuki Iwashima 
TEST_F(scm_rights,backtrack_from_scc)288*2a79651bSKuniyuki Iwashima TEST_F(scm_rights, backtrack_from_scc)
289*2a79651bSKuniyuki Iwashima {
290*2a79651bSKuniyuki Iwashima 	create_sockets(10);
291*2a79651bSKuniyuki Iwashima 
292*2a79651bSKuniyuki Iwashima 	send_fd(0, 1);
293*2a79651bSKuniyuki Iwashima 	send_fd(0, 4);
294*2a79651bSKuniyuki Iwashima 	send_fd(1, 2);
295*2a79651bSKuniyuki Iwashima 	send_fd(2, 3);
296*2a79651bSKuniyuki Iwashima 	send_fd(3, 1);
297*2a79651bSKuniyuki Iwashima 
298*2a79651bSKuniyuki Iwashima 	send_fd(5, 6);
299*2a79651bSKuniyuki Iwashima 	send_fd(5, 9);
300*2a79651bSKuniyuki Iwashima 	send_fd(6, 7);
301*2a79651bSKuniyuki Iwashima 	send_fd(7, 8);
302*2a79651bSKuniyuki Iwashima 	send_fd(8, 6);
303*2a79651bSKuniyuki Iwashima 
304*2a79651bSKuniyuki Iwashima 	close_sockets(10);
305*2a79651bSKuniyuki Iwashima }
306*2a79651bSKuniyuki Iwashima 
3072aa0cff2SKuniyuki Iwashima TEST_HARNESS_MAIN
308