blob: d5af530f90f89ae68645297bf6410613241fdb1b [file] [log] [blame]
Harald Weltefaa42922019-03-04 18:31:11 +01001module RemsimServer_Tests {
2
3/* Integration Tests for osmo-remsim-server
4 * (C) 2019 by Harald Welte <laforge@gnumonks.org>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 *
12 * This test suite tests osmo-remsim-server by attaching to the external interfaces
13 * such as RSPRO for simulated clients + bankds and RSRES (REST backend interface).
14 */
15
16import from Osmocom_Types all;
17
18import from RSPRO all;
19import from RSRES all;
20import from RSPRO_Types all;
21import from REMSIM_Tests all;
22
23import from IPA_Emulation all;
24
25import from HTTPmsg_Types all;
26import from HTTPmsg_PortType all;
Harald Welte55e879c2021-02-19 13:16:28 +010027import from HTTP_Adapter all;
Harald Weltefaa42922019-03-04 18:31:11 +010028import from JSON_Types all;
29
Harald Weltefaa42922019-03-04 18:31:11 +010030/* run a HTTP GET on specified URL expecting json in RSRES format as response */
31function f_rsres_get(charstring url, template integer exp_sts := 200)
32runs on http_CT return JsRoot {
33 var HTTPMessage http_resp;
34 http_resp := f_http_transact(url, exp := tr_HTTP_Resp(exp_sts));
35 return f_dec_JsRoot(char2oct(http_resp.response.body));
36}
37
38/* run a HTTP PUT to add a new slotmap to the remsim-server */
39function f_rsres_post_slotmap(JsSlotmap slotmap, template integer exp_sts := 201)
40runs on http_CT return HTTPResponse {
41 var charstring body := oct2char(f_enc_JsSlotmap(slotmap));
42 var HTTPMessage http_resp;
43 http_resp := f_http_transact(url := "/api/backend/v1/slotmaps", method := "POST",
44 body := body, exp := tr_HTTP_Resp(exp_sts))
45 return http_resp.response;
46}
47
48/* run a HTTP PUT to add a new slotmap to the remsim-server */
49function f_rsres_post_reset(template integer exp_sts := 200)
50runs on http_CT return HTTPResponse {
51 var HTTPMessage http_resp;
52 http_resp := f_http_transact(url := "/api/backend/v1/global-reset", method := "POST",
53 body := "", exp := tr_HTTP_Resp(exp_sts))
54 return http_resp.response;
55}
56
57
58/* run a HTTP DELETE to remove a slotmap from te remsim-server */
59function f_rsres_delete_slotmap(BankSlot bs, template integer exp_sts := 200)
60runs on http_CT return HTTPResponse {
61 var HTTPMessage http_resp;
62 var integer slotmap_id := bs.bankId * 65536 + bs.slotNr;
63 http_resp := f_http_transact(url := "/api/backend/v1/slotmaps/" & int2str(slotmap_id),
64 method := "DELETE", exp := tr_HTTP_Resp(exp_sts));
65 return http_resp.response;
66}
67
68
69function f_rsres_init() runs on http_CT {
70 f_http_init(mp_server_ip, mp_rsres_port);
71 f_rsres_post_reset();
72}
73
74type component test_CT extends rspro_client_CT, http_CT {
75};
76
77
Vadim Yanitskiy7d30c572021-02-28 16:46:13 +010078testcase TC_connect_and_nothing() runs on test_CT {
Harald Weltefaa42922019-03-04 18:31:11 +010079 var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, "foobar"));
80 timer T := 20.0;
81
82 f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
83 T.start;
84 /* expect that we're disconnected if we never send a ConnectClientReq */
85 alt {
Vadim Yanitskiy61564be2020-05-18 20:44:14 +070086 [] RSPRO[0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) { repeat; }
87 [] RSPRO[0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
Harald Weltefaa42922019-03-04 18:31:11 +010088 setverdict(pass);
89 }
90 [] T.timeout {
91 setverdict(fail, "Timeout waiting for disconnect");
92 }
93 }
94}
95
96testcase TC_connect_client() runs on test_CT {
97 var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, "foobar"));
98 var JsRoot js;
99
100 f_rsres_init();
101 f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
102 rspro[0].rspro_client_slot := valueof(ts_ClientSlot(3,4));
103
104 js := f_rsres_get("/api/backend/v1/clients");
105 if (not match(js.clients, JsClients:{})) {
106 setverdict(fail, "Initial state not empty");
107 mtc.stop;
108 }
109 f_rspro_connect_client(0);
110 js := f_rsres_get("/api/backend/v1/clients");
111 if (not match(js.clients[0], tr_JsClient(CONNECTED_CLIENT, rspro[0].rspro_id))) {
112 setverdict(fail, "Non-matching JSON response");
113 mtc.stop;
114 }
115 //as_rspro_cfg_client_id(0, cslot);
116 setverdict(pass);
117}
118
119testcase TC_connect_bank() runs on test_CT {
120 var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, "foobar"));
121 var JsRoot js;
122
123 f_rsres_init();
124 f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
125 rspro[0].rspro_bank_id := 1;
126 rspro[0].rspro_bank_nslots := 8;
127
128 js := f_rsres_get("/api/backend/v1/banks");
129 if (not match(js.banks, JsBanks:{})) {
130 setverdict(fail, "Initial state not empty");
131 mtc.stop;
132 }
133 f_rspro_connect_client(0);
134 js := f_rsres_get("/api/backend/v1/banks");
135 if (not match(js.banks[0], tr_JsBank(CONNECTED_BANKD, rspro[0].rspro_id, rspro[0].rspro_bank_id,
136 rspro[0].rspro_bank_nslots))) {
137 setverdict(fail, "Non-matching JSON response");
138 mtc.stop;
139 }
140 setverdict(pass);
141}
142
143function f_ensure_slotmaps(template JsSlotmaps maps)
144runs on http_CT {
145 var JsRoot js;
146
147 /* check that it is actually added */
148 js := f_rsres_get("/api/backend/v1/slotmaps");
149 if (match(js.slotmaps, maps)) {
150 setverdict(pass);
151 } else {
152 setverdict(fail, "Unexpected slotmaps: ", js);
153 }
154}
155
156/* verify that exactly only one slotmap exists (the specified one) */
157function f_ensure_slotmap_exists_only(template ClientSlot cslot, template BankSlot bslot,
158 template SlotmapState state := ?)
159runs on http_CT {
160 f_ensure_slotmaps({ tr_JsSlotmap(bslot, cslot, state) } );
161}
162
163/* verify that exactly only one slotmap exists (possibly among others) */
164function f_ensure_slotmap_exists(template ClientSlot cslot, template BankSlot bslot,
165 template SlotmapState state := ?)
166runs on http_CT {
167 f_ensure_slotmaps({ *, tr_JsSlotmap(bslot, cslot, state), * } );
168}
169
170
171/* test adding a single slotmap */
172testcase TC_slotmap_add() runs on test_CT {
173 f_rsres_init();
174
175 var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
176 var HTTPResponse res := f_rsres_post_slotmap(sm);
177
178 /* check that it is actually added */
179 f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
180}
181
Harald Welteb12a0ff2020-02-20 18:48:22 +0100182/* test adding a single slotmap with out-of-range values */
183testcase TC_slotmap_add_out_of_range() runs on test_CT {
184 f_rsres_init();
185
186 var HTTPMessage http_resp;
187 var charstring body;
188
189 body := "{ \"bank\": { \"bankId\": 10000, \"slotNr\": 2 }, \"client\": { \"clientId\": 3, \"slotNr\": 4 } }";
190 http_resp := f_http_transact(url := "/api/backend/v1/slotmaps", method := "POST",
191 body := body, exp := tr_HTTP_Resp(400));
192
193 body := "{ \"bank\": { \"bankId\": 100, \"slotNr\": 2000 }, \"client\": { \"clientId\": 3, \"slotNr\": 4 } }";
194 http_resp := f_http_transact(url := "/api/backend/v1/slotmaps", method := "POST",
195 body := body, exp := tr_HTTP_Resp(400));
196
197 body := "{ \"bank\": { \"bankId\": 100, \"slotNr\": 2 }, \"client\": { \"clientId\": 3000, \"slotNr\": 4 } }";
198 http_resp := f_http_transact(url := "/api/backend/v1/slotmaps", method := "POST",
199 body := body, exp := tr_HTTP_Resp(400));
200
201 body := "{ \"bank\": { \"bankId\": 100, \"slotNr\": 2 }, \"client\": { \"clientId\": 3, \"slotNr\": 4000 } }";
202 http_resp := f_http_transact(url := "/api/backend/v1/slotmaps", method := "POST",
203 body := body, exp := tr_HTTP_Resp(400));
204}
205
206
Harald Weltefaa42922019-03-04 18:31:11 +0100207/* test adding a slotmap and then connecting a client + bankd */
208testcase TC_slotmap_add_conn_cl_b() runs on test_CT {
209 /* Simulate one client */
210 var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, testcasename()));
211 f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
212 rspro[0].rspro_client_slot := valueof(ts_ClientSlot(3,4));
213
214 /* Simulate one bankd */
215 var BankSlot bslot := valueof(ts_BankSlot(1,2));
216 var ComponentIdentity rspro_bank_id := valueof(ts_CompId(remsimBankd, testcasename()));
217 f_rspro_init(rspro[1], mp_server_ip, mp_server_port, rspro_bank_id, 1);
218 rspro[1].rspro_bank_id := bslot.bankId;
219 rspro[1].rspro_bank_nslots := 8
220
221 f_rsres_init();
222 var JsSlotmap sm := valueof(ts_JsSlotmap(bslot, rspro[0].rspro_client_slot));
223 var HTTPResponse res;
224
225 /* 1) Create a new slotmap via HTTP */
226 res := f_rsres_post_slotmap(sm);
227
228 /* 2) verify that the slotmap exists and is NEW */
229 f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
230
231 /* 3) connect a client for that slotmap */
232 f_rspro_connect_client(0);
233
234 /* 4) connect a bankd for that slotmap */
235 f_rspro_connect_client(1);
236
237 /* 5) verify that the slotmap exists and is UNACKNOWLEDGED */
238 f_ensure_slotmap_exists_only(sm.client, sm.bank, UNACKNOWLEDGED);
239
240 /* 6) expect bankd to receive that mapping */
241 as_rspro_create_mapping(1, sm.client, sm.bank);
242
243 /* 7) verify that the slotmap exists and is ACTIVE */
244 f_ensure_slotmap_exists_only(sm.client, sm.bank, ACTIVE);
245
246 /* 8) expect the client to be configured with bankd side settings */
247 as_rspro_cfg_client_bank(0, bslot, ?);
248}
249
250/* test connecting a client and later adding a slotmap for it */
251testcase TC_conn_cl_b_slotmap_add() runs on test_CT {
252 /* Simulate one client */
253 var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, testcasename()));
254 f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
255 rspro[0].rspro_client_slot := valueof(ts_ClientSlot(3,4));
256
257 /* Simulate one bankd */
258 var BankSlot bslot := valueof(ts_BankSlot(1,2));
259 var ComponentIdentity rspro_bank_id := valueof(ts_CompId(remsimBankd, testcasename()));
260 f_rspro_init(rspro[1], mp_server_ip, mp_server_port, rspro_bank_id, 1);
261 rspro[1].rspro_bank_id := bslot.bankId;
262 rspro[1].rspro_bank_nslots := 8
263
264 f_rsres_init();
265 var JsSlotmap sm := valueof(ts_JsSlotmap(bslot, rspro[0].rspro_client_slot));
266 var HTTPResponse res;
267
268 /* 1) connect a client for that slotmap */
269 f_rspro_connect_client(0);
270
271 /* 2) Create a new slotmap via HTTP */
272 res := f_rsres_post_slotmap(sm);
273
274 /* 3) verify that the slotmap exists and is NEW */
275 f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
276
277 /* 4) connect a bankd for that slotmap */
278 f_rspro_connect_client(1);
279
280 /* 5) verify that the slotmap exists and is UNACKNOWLEDGED */
281 f_ensure_slotmap_exists_only(sm.client, sm.bank, UNACKNOWLEDGED);
282
283 /* 6) expect bankd to receive that mapping */
284 as_rspro_create_mapping(1, sm.client, sm.bank);
285
286 /* 7) verify that the slotmap exists and is ACTIVE */
287 f_ensure_slotmap_exists_only(sm.client, sm.bank, ACTIVE);
288
289 /* 8) expect the client to be configured with bankd IP/port */
290 as_rspro_cfg_client_bank(0, bslot, ?);
291}
292
293/* simple delete of a 'NEW' slotmap */
294testcase TC_slotmap_del_new() runs on test_CT {
295 f_rsres_init();
296
297 var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
298 var HTTPResponse res := f_rsres_post_slotmap(sm);
299 log(res);
300 res := f_rsres_delete_slotmap(sm.bank);
301 log(res);
302}
303
Harald Welte3993c812020-02-20 10:12:28 +0100304/* simple delete of a non-existant slotmap */
305testcase TC_slotmap_del_nonexistant() runs on test_CT {
306 f_rsres_init();
307
308 var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(11,12), ts_ClientSlot(13,14)));
309 var HTTPResponse res := f_rsres_delete_slotmap(sm.bank, exp_sts:=404);
310 log(res);
311}
312
313
Harald Weltefaa42922019-03-04 18:31:11 +0100314/* simple delete of a 'UNACKNOWLEDGED' slotmap */
315testcase TC_slotmap_del_unack() runs on test_CT {
316 var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
317 f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
318 rspro[0].rspro_bank_id := 1;
319 rspro[0].rspro_bank_nslots := 8;
320
321 f_rsres_init();
322 var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
323 var HTTPResponse res;
324
325 /* Create a new slotmap via HTTP */
326 res := f_rsres_post_slotmap(sm);
327
328 /* verify that the slotmap exists and is NEW */
329 f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
330
331 /* connect a bankd for that slotmap */
332 f_rspro_connect_client(0);
333
334 /* expect the slotmap to be pushed to bank but don't ACK it */
335 f_rspro_exp(tr_RSPRO_CreateMappingReq(sm.client, sm.bank));
336
337 /* verify that the slotmap exists and is UNACKNOWLEDGED */
338 f_ensure_slotmap_exists_only(sm.client, sm.bank, UNACKNOWLEDGED);
339
340 /* delete the slotmap via REST */
341 res := f_rsres_delete_slotmap(sm.bank);
342
343 /* verify the slotmap is gone */
344 f_ensure_slotmaps({});
345}
346
Harald Welte77cde212020-02-16 15:35:07 +0100347/* simple delete of a 'ACTIVE' slotmap from server + bankd */
Harald Weltefaa42922019-03-04 18:31:11 +0100348testcase TC_slotmap_del_active() runs on test_CT {
349 var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
350 f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
351 rspro[0].rspro_bank_id := 1;
352 rspro[0].rspro_bank_nslots := 8;
353
354 f_rsres_init();
355 var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
356 var HTTPResponse res;
357
358 /* Create a new slotmap via HTTP */
359 res := f_rsres_post_slotmap(sm);
360
361 /* verify that the slotmap exists and is NEW */
362 f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
363
364 /* connect a bankd for that slotmap */
365 f_rspro_connect_client(0);
366
367 /* expect the slotmap to be pushed to bank and ACK it */
368 as_rspro_create_mapping(0, sm.client, sm.bank);
369
370 /* verify that the slotmap exists and is ACTIVE */
371 f_ensure_slotmap_exists_only(sm.client, sm.bank, ACTIVE);
372
373 f_sleep(1.0);
374
375 /* delete the slotmap via REST */
376 res := f_rsres_delete_slotmap(sm.bank);
377
378 /* verify the slotmap is gone from REST interface immediately */
379 f_ensure_slotmaps({});
380
381 /* verify the slotmap is removed from bankd */
382 as_rspro_remove_mapping(0, sm.client, sm.bank);
383}
384
385
Harald Welte77cde212020-02-16 15:35:07 +0100386/* simple delete of a 'ACTIVE' slotmap from client */
387testcase TC_slotmap_del_active_client() runs on test_CT {
388 var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
389 f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
390 rspro[0].rspro_bank_id := 1;
391 rspro[0].rspro_bank_nslots := 8;
392
393 rspro_id := valueof(ts_CompId(remsimClient, testcasename()));
394 f_rspro_init(rspro[1], mp_server_ip, mp_server_port, rspro_id, 1);
395 rspro[1].rspro_client_slot := valueof(ts_ClientSlot(3,4));
396
397 f_rsres_init();
398 var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
399 var HTTPResponse res;
400
401 /* Create a new slotmap via HTTP */
402 res := f_rsres_post_slotmap(sm);
403
404 /* verify that the slotmap exists and is NEW */
405 f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
406
407 /* connect a bankd for that slotmap */
408 f_rspro_connect_client(0);
409
410 /* connect a client for that slotmap */
411 f_rspro_connect_client(1);
412
413 /* expect the slotmap to be pushed to bank and ACK it */
414 as_rspro_create_mapping(0, sm.client, sm.bank);
415
416 /* verify that the slotmap exists and is ACTIVE */
417 f_ensure_slotmap_exists_only(sm.client, sm.bank, ACTIVE);
418
419 /* expect the client to be configured with bankd side settings */
420 as_rspro_cfg_client_bank(1, sm.bank, ?/*FIXME*/);
421
422 f_sleep(1.0);
423
424 /* delete the slotmap via REST */
425 res := f_rsres_delete_slotmap(sm.bank);
426
427 /* verify the slotmap is gone from REST interface immediately */
428 f_ensure_slotmaps({});
429
430 /* verify the slotmap is removed from bankd */
431 as_rspro_remove_mapping(0, sm.client, sm.bank);
432
433 /* verify the slotmap is removed from client by setting IP/port to '0' */
434 as_rspro_cfg_client_bank(1, ?, tr_IpPort(ts_IPv4("0.0.0.0"), 0));
435}
436
437
Harald Weltefaa42922019-03-04 18:31:11 +0100438/* Add a slotmap to a currently active bank */
439testcase TC_slotmap_add_active_bank() runs on test_CT {
440 var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
441 f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
442 rspro[0].rspro_bank_id := 1;
443 rspro[0].rspro_bank_nslots := 8;
444
445 f_rsres_init();
446 var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
447 var HTTPResponse res;
448
449 /* connect a bankd for that slotmap */
450 f_rspro_connect_client(0);
451
452 /* Create a new slotmap via HTTP */
453 res := f_rsres_post_slotmap(sm);
454
455 /* expect the slotmap to be pushed to bank and ACK it */
456 as_rspro_create_mapping(0, sm.client, sm.bank);
457
458 /* verify that the slotmap exists and is ACTIVE */
459 f_ensure_slotmap_exists_only(sm.client, sm.bank, ACTIVE);
460}
461
462
463
464
465/* TODO
Harald Weltefaa42922019-03-04 18:31:11 +0100466 * - connect client w/slotmap; delete slotmap via REST (see if it is deleted)
467 * - don't acknowledge delete from client, disconnect client (see if slotmap is deleted)
Harald Weltefaa42922019-03-04 18:31:11 +0100468
469 * - connect from unknown client (name not known, no clientId provisioned?
470 * - add client name/ID mappings from REST API?
471 */
472
473
474control {
475 execute( TC_connect_and_nothing() );
476 execute( TC_connect_client() );
477 execute( TC_connect_bank() );
478 execute( TC_slotmap_add() );
479 execute( TC_slotmap_add_conn_cl_b() );
Harald Welteb12a0ff2020-02-20 18:48:22 +0100480 execute( TC_slotmap_add_out_of_range() );
Harald Weltefaa42922019-03-04 18:31:11 +0100481 execute( TC_conn_cl_b_slotmap_add() );
482 execute( TC_slotmap_del_new() );
Harald Welte3993c812020-02-20 10:12:28 +0100483 execute( TC_slotmap_del_nonexistant() );
Harald Weltefaa42922019-03-04 18:31:11 +0100484 execute( TC_slotmap_del_unack() );
485 execute( TC_slotmap_del_active() );
Harald Welte77cde212020-02-16 15:35:07 +0100486 execute( TC_slotmap_del_active_client() );
Harald Weltefaa42922019-03-04 18:31:11 +0100487 execute( TC_slotmap_add_active_bank() );
488}
489
490
491}