Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(721)

Side by Side Diff: app/tests/port_tests.c

Issue 1437453002: [kernel][ports] Add basic ports functionality (Closed) Base URL: https://github.com/travisg/lk.git@master
Patch Set: fix Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « app/tests/include/app/tests.h ('k') | app/tests/rules.mk » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2015 Carlos Pizano-Uribe cpu@chromium.org
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <debug.h>
25 #include <err.h>
26 #include <string.h>
27 #include <rand.h>
28
29 #include <kernel/port.h>
30 #include <kernel/thread.h>
31
32 #include <platform.h>
33
34 void* context1 = (void*) 0x53;
35
36 static void dump_port_result(const port_result_t* result)
37 {
38 const port_packet_t* p = &result->packet;
39 printf("[%02x %02x %02x %02x %02x %02x %02x %02x]\n",
40 p->value[0], p->value[1], p->value[2], p->value[3],
41 p->value[4], p->value[5], p->value[6], p->value[7]);
42 }
43
44 static int single_thread_basic(void)
45 {
46 port_t w_port;
47 status_t st = port_create("sh_prt1", PORT_MODE_UNICAST, &w_port);
48 if (st < 0) {
49 printf("could not create port, status = %d\n", st);
50 return __LINE__;
51 }
52
53 port_t r_port;
54 st = port_open("sh_prt0", context1, &r_port);
55 if (st != ERR_NOT_FOUND) {
56 printf("expected not to find port, status = %d\n", st);
57 return __LINE__;
58 }
59
60 st = port_open("sh_prt1", context1, &r_port);
61 if (st < 0) {
62 printf("could not open port, status = %d\n", st);
63 return __LINE__;
64 }
65
66
67 port_packet_t packet[3] = {
68 {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}},
69 {{0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11}},
70 {{0x33, 0x66, 0x99, 0xcc, 0x33, 0x66, 0x99, 0xcc}},
71 };
72
73 st = port_write(w_port, &packet[0], 1);
74 if (st < 0) {
75 printf("could not write port, status = %d\n", st);
76 return __LINE__;
77 }
78
79 printf("reading from port:\n");
80
81 port_result_t res = {0};
82
83 st = port_read(r_port, 0, &res);
84 if (st < 0) {
85 printf("could not read port, status = %d\n", st);
86 return __LINE__;
87 }
88 if (res.ctx != context1) {
89 printf("bad context! = %p\n", res.ctx);
90 return __LINE__;
91 }
92
93 st = port_read(r_port, 0, &res);
94 if (st != ERR_TIMED_OUT) {
95 printf("expected timeout, status = %d\n", st);
96 return __LINE__;
97 }
98
99 st = port_write(w_port, &packet[1], 1);
100 if (st < 0) {
101 printf("could not write port, status = %d\n", st);
102 return __LINE__;
103 }
104
105 st = port_write(w_port, &packet[0], 1);
106 if (st < 0) {
107 printf("could not write port, status = %d\n", st);
108 return __LINE__;
109 }
110
111 st = port_write(w_port, &packet[2], 1);
112 if (st < 0) {
113 printf("could not write port, status = %d\n", st);
114 return __LINE__;
115 }
116
117 int expected_count = 3;
118 while (true) {
119 st = port_read(r_port, 0, &res);
120 if (st < 0)
121 break;
122 dump_port_result(&res);
123 --expected_count;
124 }
125
126 if (expected_count != 0) {
127 printf("invalid read count = %d\n", expected_count);
128 return __LINE__;
129 }
130
131 printf("\n");
132
133 // port should be empty. should be able to write 8 packets.
134 expected_count = 8;
135 while (true) {
136 st = port_write(w_port, &packet[1], 1);
137 if (st < 0)
138 break;
139 --expected_count;
140 st = port_write(w_port, &packet[2], 1);
141 if (st < 0)
142 break;
143 --expected_count;
144 }
145
146 if (expected_count != 0) {
147 printf("invalid write count = %d\n", expected_count);
148 return __LINE__;
149 }
150
151 // tod(cpu) fix this possibly wrong error.
152 if (st != ERR_PARTIAL_WRITE) {
153 printf("expected buffer error, status =%d\n", st);
154 return __LINE__;
155 }
156
157 // read 3 packets.
158 for (int ix = 0; ix != 3; ++ix) {
159 st = port_read(r_port, 0, &res);
160 if (st < 0) {
161 printf("could not read port, status = %d\n", st);
162 return __LINE__;
163 }
164 }
165
166 // there are 5 packets, now we add another 3.
167 st = port_write(w_port, packet, 3);
168 if (st < 0) {
169 printf("could not write port, status = %d\n", st);
170 return __LINE__;
171 }
172
173 expected_count = 8;
174 while (true) {
175 st = port_read(r_port, 0, &res);
176 if (st < 0)
177 break;
178 dump_port_result(&res);
179 --expected_count;
180 }
181
182 if (expected_count != 0) {
183 printf("invalid read count = %d\n", expected_count);
184 return __LINE__;
185 }
186
187 // attempt to use the wrong port.
188 st = port_write(r_port, &packet[1], 1);
189 if (st != ERR_BAD_HANDLE) {
190 printf("expected bad handle error, status = %d\n", st);
191 return __LINE__;
192 }
193
194 st = port_read(w_port, 0, &res);
195 if (st != ERR_BAD_HANDLE) {
196 printf("expected bad handle error, status = %d\n", st);
197 return __LINE__;
198 }
199
200 st = port_close(r_port);
201 if (st < 0) {
202 printf("could not close read port, status = %d\n", st);
203 return __LINE__;
204 }
205
206 st = port_close(w_port);
207 if (st < 0) {
208 printf("could not close write port, status = %d\n", st);
209 return __LINE__;
210 }
211
212 st = port_close(r_port);
213 if (st != ERR_BAD_HANDLE) {
214 printf("expected bad handle error, status = %d\n", st);
215 return __LINE__;
216 }
217
218 st = port_close(w_port);
219 if (st != ERR_BAD_HANDLE) {
220 printf("expected bad handle error, status = %d\n", st);
221 return __LINE__;
222 }
223
224 st = port_destroy(w_port);
225 if (st < 0) {
226 printf("could not destroy port, status = %d\n", st);
227 return __LINE__;
228 }
229
230 printf("single_thread_basic : ok\n");
231 return 0;
232 }
233
234 static int ping_pong_thread(void *arg)
235 {
236 port_t r_port;
237 status_t st = port_open("ping_port", NULL, &r_port);
238 if (st < 0) {
239 printf("thread: could not open port, status = %d\n", st);
240 return __LINE__;
241 }
242
243 bool should_dispose_pong_port = true;
244 port_t w_port;
245 st = port_create("pong_port", PORT_MODE_UNICAST, &w_port);
246 if (st == ERR_ALREADY_EXISTS) {
247 // won the race to create the port.
248 should_dispose_pong_port = false;
249 } else if (st < 0) {
250 printf("thread: could not open port, status = %d\n", st);
251 return __LINE__;
252 }
253
254 port_result_t pr;
255
256 // the loop is read-mutate-write until the write port
257 // is closed by the master thread.
258 while (true) {
259 st = port_read(r_port, INFINITE_TIME, &pr);
260
261 if (st == ERR_CANCELLED) {
262 break;
263 } else if (st < 0) {
264 printf("thread: could not read port, status = %d\n", st);
265 return __LINE__;
266 }
267
268 pr.packet.value[0]++;
269 pr.packet.value[5]--;
270
271 st = port_write(w_port, &pr.packet, 1);
272 if (st < 0) {
273 printf("thread: could not write port, status = %d\n", st);
274 return __LINE__;
275 }
276 }
277
278 port_close(r_port);
279
280 if (should_dispose_pong_port) {
281 port_close(w_port);
282 port_destroy(w_port);
283 }
284
285 return 0;
286
287 bail:
288 return __LINE__;
289 }
290
291
292 int two_threads_basic(void)
293 {
294 port_t w_port;
295 status_t st = port_create("ping_port", PORT_MODE_BROADCAST, &w_port);
296 if (st < 0) {
297 printf("could not create port, status = %d\n", st);
298 return __LINE__;
299 }
300
301 thread_t* t1 = thread_create(
302 "worker1", &ping_pong_thread, NULL, DEFAULT_PRIORITY, DEF AULT_STACK_SIZE);
303 thread_t* t2 = thread_create(
304 "worker2", &ping_pong_thread, NULL, DEFAULT_PRIORITY, DEF AULT_STACK_SIZE);
305 thread_resume(t1);
306 thread_resume(t2);
307
308 // wait for the pong port to be created, the two threads race to do it.
309 port_t r_port;
310 while (true) {
311 status_t st = port_open("pong_port", NULL, &r_port);
312 if (st == NO_ERROR) {
313 break;
314 } else if (st == ERR_NOT_FOUND) {
315 thread_sleep(100);
316 } else {
317 printf("could not open port, status = %d\n", st);
318 return __LINE__;
319 }
320 }
321
322 // We have two threads listening to the ping port. Which both reply
323 // on the pong port, so we get two packets in per packet out.
324 const int passes = 256;
325 printf("two_threads_basic test, %d passes\n", passes);
326
327 port_packet_t packet_out = {{0xaf, 0x77, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05} };
328
329 port_result_t pr;
330 for (int ix = 0; ix != passes; ++ix) {
331 const size_t count = 1 + ((unsigned int)rand() % 3);
332
333 for (size_t jx = 0; jx != count; ++jx) {
334 st = port_write(w_port, &packet_out, 1);
335 if (st < 0) {
336 printf("could not write port, status = %d\n", st);
337 return __LINE__;
338 }
339 }
340
341 packet_out.value[0]++;
342 packet_out.value[5]--;
343
344 for (size_t jx = 0; jx != count * 2; ++jx) {
345 st = port_read(r_port, INFINITE_TIME, &pr);
346 if (st < 0) {
347 printf("could not read port, status = %d\n", st);
348 return __LINE__;
349 }
350
351 if ((pr.packet.value[0] != packet_out.value[0]) ||
352 (pr.packet.value[5] != packet_out.value[5])) {
353 printf("unexpected data in packet, loop %d", ix);
354 return __LINE__;
355 }
356 }
357 }
358
359 thread_sleep(100);
360
361 // there should be no more packets to read.
362 st = port_read(r_port, 0, &pr);
363 if (st != ERR_TIMED_OUT) {
364 printf("unexpected packet, status = %d\n", st);
365 return __LINE__;
366 }
367
368 printf("two_threads_basic master shutdown\n");
369
370 st = port_close(r_port);
371 if (st < 0) {
372 printf("could not close port, status = %d\n", st);
373 return __LINE__;
374 }
375
376 st = port_close(w_port);
377 if (st < 0) {
378 printf("could not close port, status = %d\n", st);
379 return __LINE__;
380 }
381
382 st = port_destroy(w_port);
383 if (st < 0) {
384 printf("could not destroy port, status = %d\n", st);
385 return __LINE__;
386 }
387
388 int retcode = -1;
389 thread_join(t1, &retcode, INFINITE_TIME);
390 if (retcode)
391 goto fail;
392
393 thread_join(t2, &retcode, INFINITE_TIME);
394 if (retcode)
395 goto fail;
396
397 return 0;
398
399 fail:
400 printf("child thread exited with %d\n", retcode);
401 return __LINE__;
402 }
403
404 #define RUN_TEST(t) result = t(); if (result) goto fail
405
406 int port_tests(void)
407 {
408 int result;
409 int count = 2;
410 while (count--) {
411 RUN_TEST(single_thread_basic);
412 RUN_TEST(two_threads_basic);
413 }
414
415 printf("all tests passed\n");
416 return 0;
417 fail:
418 printf("test failed at line %d\n", result);
419 return 1;
420 }
421
422 #undef RUN_TEST
OLDNEW
« no previous file with comments | « app/tests/include/app/tests.h ('k') | app/tests/rules.mk » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698