2 * \brief RPC system test code
6 * Copyright (c) 2010, ETH Zurich.
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.
17 #include <barrelfish/barrelfish.h>
18 #include <barrelfish/nameservice_client.h>
20 #include <if/test_rpc_cap_defs.h>
21 #include <if/test_rpc_cap_defs.h>
23 static const char *my_service_name = "rpc_cap_test";
24 uint8_t is_server = 0x0;
27 __attribute__((format(printf, 1, 2)))
28 static void my_debug_printf(const char *fmt, ...)
30 struct thread *me = thread_self();
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);
42 len += snprintf(str + len, sizeof(str) - len, "server: ");
44 len += snprintf(str + len, sizeof(str) - len, "client(%d): ",
48 if (len < sizeof(str)) {
49 va_start(argptr, fmt);
50 vsnprintf(str + len, sizeof(str) - len, fmt, argptr);
53 sys_print(str, sizeof(str));
58 struct echo_response {
59 struct test_rpc_cap_binding *b;
63 static void send_echo_response(void *arg){
64 struct echo_response * resp = arg;
66 err = test_rpc_cap_echo_response__tx(resp->b, NOP_CONT, resp->response);
67 assert(err_is_ok(err));
71 static void handle_echo_call(struct test_rpc_cap_binding *b,
74 my_debug_printf("handle_echo_call (bind=%p) arg=%"PRIu32"\n", b, arg_in);
75 struct echo_response * resp = malloc(sizeof(*resp));
77 resp->response = arg_in;
78 send_echo_response(resp);
82 static void handle_send_cap_one_call(struct test_rpc_cap_binding *b,
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 );
90 test_rpc_cap_send_cap_one_response__tx(b, NOP_CONT, err);
93 static void handle_send_cap_two_call(struct test_rpc_cap_binding *b,
94 struct capref incap1, struct capref incap2)
96 my_debug_printf("handle_send_cap_two_call (bind=%p)\n", b);
97 errval_t err = SYS_ERR_OK;
98 struct capability cap;
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));
105 test_rpc_cap_send_cap_two_response__tx(b, NOP_CONT, err);
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
114 /* ------------------------------ CLIENT ------------------------------ */
116 static struct test_rpc_cap_binding *test_rpc_binding;
118 static void client_call_test_1(void){
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");
127 my_debug_printf("client_call_test_1 successful!\n");
131 static void client_call_test_2(void){
132 struct capref my_frame;
133 errval_t err, msg_err;
135 err = frame_alloc(&my_frame, BASE_PAGE_SIZE, NULL);
136 assert(err_is_ok(err));
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");
144 my_debug_printf("client_call_test_2 successful!\n");
148 static void client_call_test_3(int i){
149 struct capref frame1, frame2;
150 struct capability cap1, cap2;
153 errval_t err, msg_err;
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);
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);
167 my_debug_printf("Calling send_cap_two: %s\n", buf);
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");
175 my_debug_printf("client_call_test_3(%d) successful!\n", i);
179 static void bind_cb(void *st,
181 struct test_rpc_cap_binding *b)
183 if (err_is_fail(err)) {
184 USER_PANIC_ERR(err, "bind failed");
187 my_debug_printf("client: bound!\n");
189 test_rpc_binding = b;
190 test_rpc_cap_rpc_client_init(b);
192 client_call_test_1();
193 client_call_test_2();
194 for(int i=0; i<100;i++){
195 client_call_test_3(i);
197 printf("TEST PASSED\n");
200 static void start_client(void)
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");
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");
220 /* ------------------------------ SERVER ------------------------------ */
223 static void export_cb(void *st,
227 if (err_is_fail(err)) {
228 USER_PANIC_ERR(err, "export failed");
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");
237 my_debug_printf("server: service %s exported at iref %"PRIuIREF"\n", my_service_name, iref);
240 static errval_t connect_cb(void *st,
241 struct test_rpc_cap_binding *b)
243 my_debug_printf("server: client connected!\n");
245 // copy my message receive handler vtable to the binding
246 b->rx_vtbl = rx_vtbl;
248 // accept the connection (we could return an error to refuse it)
252 static void start_server(void)
256 my_debug_printf("server: Starting server...\n");
260 err = test_rpc_cap_export(NULL,
263 get_default_waitset(),
264 IDC_EXPORT_FLAGS_DEFAULT);
265 if (err_is_fail(err)) {
266 USER_PANIC_ERR(err, "export failed");
270 /* ------------------------------ MAIN ------------------------------ */
272 static int usage(char * argv[]){
273 printf("Usage: %s client|server [id=INT]\n", argv[0]);
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);
287 printf("Unknonw argument: %s\n", argv[i]);
292 } else if (argc == 2 && strcmp(argv[1], "server") == 0) {
298 struct waitset *ws = get_default_waitset();
300 err = event_dispatch(ws);
301 if (err_is_fail(err)) {
302 DEBUG_ERR(err, "in event_dispatch");