1 /*
2  * Copyright (c) 2020 Friedt Professional Engineering Services, Inc
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "_main.h"
8 
9 struct ctx {
10 	/* true if test is write_block(), false if test is read_block() */
11 	bool write;
12 	/* the secondary-side socket of the socketpair */
13 	int fd;
14 	/* the count of the main thread */
15 	atomic_t m;
16 };
17 static ZTEST_BMEM struct ctx ctx;
18 static ZTEST_BMEM struct k_work work;
19 
work_handler(struct k_work * w)20 static void work_handler(struct k_work *w)
21 {
22 	int res;
23 	char c = '\0';
24 
25 	(void)w;
26 
27 	LOG_DBG("doing work");
28 
29 	while (true) {
30 		if (ctx.write) {
31 			LOG_DBG("ctx.m: %lu", atomic_get(&ctx.m));
32 			if (atomic_get(&ctx.m)
33 				< CONFIG_NET_SOCKETPAIR_BUFFER_SIZE) {
34 				continue;
35 			}
36 			LOG_DBG("ready to read!");
37 		} else {
38 			LOG_DBG("sleeping for 100ms..");
39 			k_sleep(K_MSEC(100));
40 			LOG_DBG("ready to write!");
41 		}
42 		break;
43 	}
44 
45 	LOG_DBG("%sing 1 byte %s fd %d", ctx.write ? "read" : "writ",
46 		ctx.write ? "from" : "to", ctx.fd);
47 	if (ctx.write) {
48 		res = recv(ctx.fd, &c, 1, 0);
49 	} else {
50 		res = send(ctx.fd, "x", 1, 0);
51 	}
52 	if (-1 == res || 1 != res) {
53 		LOG_DBG("%s() failed: %d", ctx.write ? "recv" : "send", errno);
54 	} else {
55 		LOG_DBG("%s 1 byte", ctx.write ? "read" : "wrote");
56 	}
57 }
58 
ZTEST_F(net_socketpair,test_write_block)59 ZTEST_F(net_socketpair, test_write_block)
60 {
61 	int res;
62 
63 	for (size_t i = 0; i < 2; ++i) {
64 
65 		LOG_DBG("data direction %d -> %d", fixture->sv[i], fixture->sv[(!i) & 1]);
66 
67 		LOG_DBG("setting up context");
68 		memset(&ctx, 0, sizeof(ctx));
69 		ctx.write = true;
70 		ctx.fd = fixture->sv[(!i) & 1];
71 
72 		LOG_DBG("queueing work");
73 		k_work_init(&work, work_handler);
74 		k_work_submit(&work);
75 
76 		/* fill up the buffer */
77 		for (ctx.m = 0; atomic_get(&ctx.m)
78 			< CONFIG_NET_SOCKETPAIR_BUFFER_SIZE;) {
79 
80 			res = send(fixture->sv[i], "x", 1, 0);
81 			zassert_not_equal(res, -1, "send() failed: %d", errno);
82 			zassert_equal(res, 1, "wrote %d bytes instead of 1",
83 				res);
84 
85 			atomic_inc(&ctx.m);
86 			LOG_DBG("have written %lu bytes", atomic_get(&ctx.m));
87 		}
88 
89 		/* try to write one more byte */
90 		LOG_DBG("writing to fd %d", fixture->sv[i]);
91 		res = send(fixture->sv[i], "x", 1, 0);
92 		zassert_not_equal(res, -1, "send() failed: %d", errno);
93 		zassert_equal(res, 1, "wrote %d bytes instead of 1", res);
94 
95 		LOG_DBG("success!");
96 	}
97 }
98 
ZTEST_F(net_socketpair,test_read_block)99 ZTEST_F(net_socketpair, test_read_block)
100 {
101 	int res;
102 	char x;
103 
104 	for (size_t i = 0; i < 2; ++i) {
105 
106 		LOG_DBG("data direction %d <- %d", fixture->sv[i], fixture->sv[(!i) & 1]);
107 
108 		LOG_DBG("setting up context");
109 		memset(&ctx, 0, sizeof(ctx));
110 		ctx.write = false;
111 		ctx.fd = fixture->sv[(!i) & 1];
112 
113 		LOG_DBG("queueing work");
114 		k_work_init(&work, work_handler);
115 		k_work_submit(&work);
116 
117 		/* try to read one byte */
118 		LOG_DBG("reading from fd %d", fixture->sv[i]);
119 		x = '\0';
120 		res = recv(fixture->sv[i], &x, 1, 0);
121 		zassert_not_equal(res, -1, "recv() failed: %d", errno);
122 		zassert_equal(res, 1, "read %d bytes instead of 1", res);
123 
124 		LOG_DBG("success!");
125 	}
126 }
127