rpc_cap_test: adding missing include
[barrelfish] / usr / tests / rpc_cap_test / rpc_cap_test.c
1 /** \file
2  *  \brief RPC system test code
3  */
4
5 /*
6  * Copyright (c) 2010, ETH Zurich.
7  * All rights reserved.
8  *
9  * This file is distributed under the terms in the attached LICENSE file.
10  * If you do not find this file, copies can be found by writing to:
11  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
12  */
13
14 #include <string.h>
15 #include <stdio.h>
16 #include <stdarg.h>
17 #include <barrelfish/barrelfish.h>
18 #include <barrelfish/nameservice_client.h>
19
20 #include <if/test_rpc_cap_defs.h>
21 #include <if/test_rpc_cap_defs.h>
22
23 static const char *my_service_name = "rpc_cap_test";
24 uint8_t is_server = 0x0;
25 int client_id = 0;
26
27 __attribute__((format(printf, 1, 2)))
28 static void my_debug_printf(const char *fmt, ...)
29 {
30     struct thread *me = thread_self();
31     va_list argptr;
32     char id[32] = "-";
33     char str[1024];
34     size_t len;
35
36     if (me)
37         snprintf(id, sizeof(id), "%"PRIuPTR, thread_get_id(me));
38     len = snprintf(str, sizeof(str), "\033[34m%.*s.\033[31m%u.%s\033[0m: ",
39                    DISP_NAME_LEN, disp_name(), disp_get_core_id(), id);
40
41     if(is_server){
42         len += snprintf(str + len, sizeof(str) - len, "server: ");
43     } else {
44         len += snprintf(str + len, sizeof(str) - len, "client(%d): ",
45                 client_id);
46     }
47
48     if (len < sizeof(str)) {
49         va_start(argptr, fmt);
50         vsnprintf(str + len, sizeof(str) - len, fmt, argptr);
51         va_end(argptr);
52     }
53     sys_print(str, sizeof(str));
54 }
55
56
57
58 struct echo_response {
59     struct test_rpc_cap_binding *b;
60     uint32_t response;
61 };
62
63 static void send_echo_response(void *arg){
64     struct echo_response * resp = arg;
65     errval_t err;
66     err = test_rpc_cap_echo_response__tx(resp->b, NOP_CONT, resp->response);
67     assert(err_is_ok(err));
68 }
69
70
71 static void handle_echo_call(struct test_rpc_cap_binding *b,
72         uint32_t arg_in)
73 {
74     my_debug_printf("handle_echo_call (bind=%p) arg=%"PRIu32"\n", b, arg_in);
75     struct echo_response * resp = malloc(sizeof(*resp));
76     resp->b = b;
77     resp->response = arg_in;
78     send_echo_response(resp);
79 }
80
81
82 static void handle_send_cap_one_call(struct test_rpc_cap_binding *b,
83         struct capref incap)
84 {
85     my_debug_printf("handle_send_cap_one_call (bind=%p)\n", b);
86     errval_t err = SYS_ERR_OK;
87     struct capability cap;
88     err = debug_cap_identify(incap, &cap );
89
90     test_rpc_cap_send_cap_one_response__tx(b, NOP_CONT, err);
91 }
92
93 static void handle_send_cap_two_call(struct test_rpc_cap_binding *b,
94         struct capref incap1, struct capref incap2)
95 {
96     my_debug_printf("handle_send_cap_two_call (bind=%p)\n", b);
97     errval_t err = SYS_ERR_OK;
98     struct capability cap;
99
100     err = debug_cap_identify(incap1, &cap);
101     assert(err_is_ok(err));
102     err = debug_cap_identify(incap2, &cap);
103     assert(err_is_ok(err));
104
105     test_rpc_cap_send_cap_two_response__tx(b, NOP_CONT, err);
106 }
107
108 static struct test_rpc_cap_rx_vtbl rx_vtbl = {
109     .echo_call = handle_echo_call,
110     .send_cap_one_call = handle_send_cap_one_call,
111     .send_cap_two_call = handle_send_cap_two_call
112 };
113
114 /* ------------------------------ CLIENT ------------------------------ */
115
116 static struct test_rpc_cap_binding *test_rpc_binding;
117
118 static void client_call_test_1(void){
119     uint32_t res=0;
120     errval_t err;
121     err = test_rpc_binding->rpc_tx_vtbl.echo(test_rpc_binding, client_id, &res);
122     if(err_is_fail(err)){
123         my_debug_printf("Error in rpc call (1)\n");
124     } else if(res != client_id) {
125         my_debug_printf("Wrong result?\n");
126     } else {
127         my_debug_printf("client_call_test_1 successful!\n");
128     }
129 }
130
131 static void client_call_test_2(void){
132     struct capref my_frame;
133     errval_t err, msg_err;
134
135     err = frame_alloc(&my_frame, BASE_PAGE_SIZE, NULL);
136     assert(err_is_ok(err));
137
138     err = test_rpc_binding->rpc_tx_vtbl.send_cap_one(test_rpc_binding, my_frame, &msg_err);
139     if(err_is_fail(err)){
140         USER_PANIC_ERR(err, "Error in rpc call (2)\n");
141     } else if(err_is_fail(msg_err)) {
142         USER_PANIC_ERR(err, "Server msg (2)\n");
143     } else {
144         my_debug_printf("client_call_test_2 successful!\n");
145     }
146 }
147
148 static void client_call_test_3(int i){
149     struct capref frame1, frame2;
150     struct capability cap1, cap2;
151     char buf[1024];
152     int buf_idx=0;
153     errval_t err, msg_err;
154
155     err = frame_alloc(&frame1, BASE_PAGE_SIZE, NULL);
156     assert(err_is_ok(err));
157     err = debug_cap_identify(frame1, &cap1);
158     assert(err_is_ok(err));
159     buf_idx += debug_print_cap(buf, sizeof(buf), &cap1);
160
161     err = frame_alloc(&frame2, BASE_PAGE_SIZE, NULL);
162     assert(err_is_ok(err));
163     err = debug_cap_identify(frame2, &cap2);
164     assert(err_is_ok(err));
165     buf_idx += debug_print_cap(buf+buf_idx, sizeof(buf)-buf_idx, &cap2);
166
167     my_debug_printf("Calling send_cap_two: %s\n", buf);
168
169     err = test_rpc_binding->rpc_tx_vtbl.send_cap_two(test_rpc_binding, frame1, frame2, &msg_err);
170     if(err_is_fail(err)){
171         USER_PANIC_ERR(err, "Error in rpc call (3)\n");
172     } else if(err_is_fail(msg_err)) {
173         USER_PANIC_ERR(err, "Server msg (3)\n");
174     } else {
175         my_debug_printf("client_call_test_3(%d) successful!\n", i);
176     }
177 }
178
179 static void bind_cb(void *st,
180                     errval_t err,
181                     struct test_rpc_cap_binding *b)
182 {
183     if (err_is_fail(err)) {
184         USER_PANIC_ERR(err, "bind failed");
185     }
186
187     my_debug_printf("client: bound!\n");
188
189     test_rpc_binding = b;
190     test_rpc_cap_rpc_client_init(b);
191
192     client_call_test_1();
193     client_call_test_2();
194     for(int i=0; i<100;i++){
195         client_call_test_3(i);
196     }
197     printf("TEST PASSED\n");
198 }
199
200 static void start_client(void)
201 {
202     iref_t iref;
203     errval_t err;
204
205     my_debug_printf("client: looking up '%s' in name service...\n", my_service_name);
206     err = nameservice_blocking_lookup(my_service_name, &iref);
207     if (err_is_fail(err)) {
208         USER_PANIC_ERR(err, "nameservice_blocking_lookup failed");
209     }
210
211     my_debug_printf("client: binding to %"PRIuIREF"...\n", iref);
212     err = test_rpc_cap_bind(iref, bind_cb, NULL ,
213                                  get_default_waitset(),
214                                  IDC_BIND_FLAGS_DEFAULT);
215     if (err_is_fail(err)) {
216         USER_PANIC_ERR(err, "bind failed");
217     }
218 }
219
220 /* ------------------------------ SERVER ------------------------------ */
221
222
223 static void export_cb(void *st,
224                       errval_t err,
225                       iref_t iref)
226 {
227     if (err_is_fail(err)) {
228         USER_PANIC_ERR(err, "export failed");
229     }
230
231     // register this iref with the name service
232     err = nameservice_register(my_service_name, iref);
233     if (err_is_fail(err)) {
234         USER_PANIC_ERR(err, "nameservice_register failed");
235     }
236
237     my_debug_printf("server: service %s exported at iref %"PRIuIREF"\n", my_service_name, iref);
238 }
239
240 static errval_t connect_cb(void *st,
241                            struct test_rpc_cap_binding *b)
242 {
243     my_debug_printf("server: client connected!\n");
244
245     // copy my message receive handler vtable to the binding
246     b->rx_vtbl = rx_vtbl;
247
248     // accept the connection (we could return an error to refuse it)
249     return SYS_ERR_OK;
250 }
251
252 static void start_server(void)
253 {
254     errval_t err;
255
256     my_debug_printf("server: Starting server...\n");
257
258     is_server = 0x1;
259
260     err = test_rpc_cap_export(NULL,
261                               export_cb,
262                               connect_cb,
263                               get_default_waitset(),
264                               IDC_EXPORT_FLAGS_DEFAULT);
265     if (err_is_fail(err)) {
266         USER_PANIC_ERR(err, "export failed");
267     }
268 }
269
270 /* ------------------------------ MAIN ------------------------------ */
271
272 static int usage(char * argv[]){
273     printf("Usage: %s client|server [id=INT]\n", argv[0]);
274     return EXIT_FAILURE;
275 }
276
277 int main(int argc,
278          char *argv[])
279 {
280     errval_t err;
281
282     if (argc >= 2 && strcmp(argv[1], "client") == 0) {
283         for(int i = 2; i < argc; i++){
284             if(strncmp(argv[i], "id=", strlen("id=")) == 0){
285                 client_id = atoi(argv[i] + 3);
286             } else {
287                 printf("Unknonw argument: %s\n", argv[i]);
288                 return usage(argv);
289             }
290         }
291         start_client();
292     } else if (argc == 2 && strcmp(argv[1], "server") == 0) {
293         start_server();
294     } else {
295         return usage(argv);
296     }
297
298     struct waitset *ws = get_default_waitset();
299     while (1) {
300         err = event_dispatch(ws);
301         if (err_is_fail(err)) {
302             DEBUG_ERR(err, "in event_dispatch");
303             break;
304         }
305     }
306
307     return EXIT_FAILURE;
308 }