blob: dc4430414eba5e39563918e363e92be5ba276c4f [file] [log] [blame]
Harald Welte00a067f2017-09-13 23:27:17 +02001module MGCP_Test {
2 import from MGCP_Types all;
Harald Welte3c6ebb92017-09-16 00:56:57 +08003 import from SDP_Types all;
4 import from MGCP_CodecPort all;
5 import from MGCP_CodecPort_CtrlFunct all;
6 import from IPL4asp_Types all;
Harald Welte00a067f2017-09-13 23:27:17 +02007
Harald Welte21ba5572017-09-19 17:55:05 +08008 /* any variables declared in the component will be available to
9 * all functions that 'run on' the named component, similar to
10 * class members in C++ */
Harald Welte00a067f2017-09-13 23:27:17 +020011 type component dummy_CT {
Harald Welte3c6ebb92017-09-16 00:56:57 +080012 port MGCP_CODEC_PT MGCP;
13 var boolean initialized := false;
Harald Welte55015362017-11-18 16:02:42 +010014 var ConnectionId g_mgcp_conn_id := -1;
Harald Weltee1e18c52017-09-17 16:23:07 +080015 var integer g_trans_id;
Harald Welte00a067f2017-09-13 23:27:17 +020016 };
17
Harald Weltee1e18c52017-09-17 16:23:07 +080018 function get_next_trans_id() runs on dummy_CT return MgcpTransId {
19 var MgcpTransId tid := int2str(g_trans_id);
20 g_trans_id := g_trans_id + 1;
21 return tid;
22 }
23
Harald Welte21ba5572017-09-19 17:55:05 +080024 /* all parameters declared here can be modified / overridden by
25 * the config file in the [MODULE_PARAMETERS] section. If no
26 * config file is used or the file doesn't specify them, the
27 * default values assigned below are used */
Harald Welte3c6ebb92017-09-16 00:56:57 +080028 modulepar {
29 PortNumber mp_local_udp_port := 2727;
30 charstring mp_local_ip := "127.0.0.1";
31 PortNumber mp_remote_udp_port := 2427;
32 charstring mp_remote_ip := "127.0.0.1";
33 }
34
Harald Welte21ba5572017-09-19 17:55:05 +080035 /* initialization function, called by each test case at the
36 * beginning, but 'initialized' variable ensures its body is
37 * only executed once */
Harald Welte3c6ebb92017-09-16 00:56:57 +080038 private function f_init()runs on dummy_CT {
39 var Result res;
40 if (initialized == true) {
41 return;
42 }
43 initialized := true;
44
Harald Welte21ba5572017-09-19 17:55:05 +080045 /* some random number for the initial transaction id */
Harald Weltee1e18c52017-09-17 16:23:07 +080046 g_trans_id := float2int(rnd()*65535.0);
Harald Welte3c6ebb92017-09-16 00:56:57 +080047 map(self:MGCP, system:MGCP_CODEC_PT);
Harald Welte21ba5572017-09-19 17:55:05 +080048 /* connect the MGCP test port using the given
Harald Welte55015362017-11-18 16:02:42 +010049 * source/destionation ip/port and store the connection id in g_mgcp_conn_id
Harald Welte21ba5572017-09-19 17:55:05 +080050 * */
Harald Welte55015362017-11-18 16:02:42 +010051 res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, mp_remote_ip, mp_remote_udp_port, mp_local_ip, mp_local_udp_port, 0, { udp := {} });
52 g_mgcp_conn_id := res.connId;
Harald Welte3c6ebb92017-09-16 00:56:57 +080053 }
54
55 /* 3.2.2.6 Connection Mode (sendonly, recvonly, sendrecv, confrnce, inactive, loopback,
56 * conttest, netwloop, netwtest) */
57 template MgcpParameter t_MgcpParConnMode(template MgcpConnectionMode mode) := { "M", mode };
58
59 /* 3.2.2.2 CallId: maximum 32 hex chars */
60 template MgcpParameter ts_MgcpParCallId(MgcpCallId cid) := {
61 code := "C",
62 val := hex2str(cid)
63 };
64
65 /* 3.2.2.18 RequestIdentifier: Maximum 32 hex chars */
66 template MgcpParameter ts_MgcpParReqId(MgcpRequestId rid) := {
67 code := "X",
68 val := hex2str(rid)
69 };
70
71 /* 3.2.2.10: LocalConnectionOptions (codec, packetization, bandwidth, ToS, eco, gain, silence, ...) */
72 template MgcpParameter t_MgcpParLocConnOpt(template charstring lco) := { "L", lco };
73
74 /* 3.2.2.5: ConnectionId: maximum 32 hex chars */
75 template MgcpParameter ts_MgcpParConnectionId(MgcpConnectionId cid) := {
76 code := "I",
77 val := hex2str(cid)
78 };
79
80 /* osmo-bsc_mgcp implements L/C/M/X only, osmo-mgw adds 'I' */
81 /* SDP: osmo-bsc_mgcp implements Tx of v,o,s,c,t,m,a */
82
Harald Weltee636afd2017-09-17 16:24:09 +080083 template MgcpResponse tr_MgcpResp_Err(template MgcpResponseCode code) := {
84 line := {
85 code := code,
86 trans_id := ?,
87 string := ?
88 },
89 params := {},
90 sdp := omit
91 }
92
Harald Welte3c6ebb92017-09-16 00:56:57 +080093 template MgcpCommandLine t_MgcpCmdLine(template charstring verb, template MgcpTransId trans_id, template charstring ep) := {
94 verb := verb,
95 trans_id := trans_id,
96 ep := ep,
97 ver := "1.0"
98 };
99
100 template MgcpCommand ts_CRCX(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, template SDP_Message sdp := omit) := {
101 line := t_MgcpCmdLine("CRCX", trans_id, ep),
102 params := {
103 t_MgcpParConnMode(mode),
104 ts_MgcpParCallId(call_id),
105 //t_MgcpParReqId(omit),
106 t_MgcpParLocConnOpt("p: 20")
107 },
108 sdp := sdp
109 }
110
Harald Weltee636afd2017-09-17 16:24:09 +0800111 template MgcpCommand ts_MDCX(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, template SDP_Message sdp := omit) := {
112 line := t_MgcpCmdLine("MDCX", trans_id, ep),
113 params := {
114 t_MgcpParConnMode(mode),
115 ts_MgcpParCallId(call_id),
116 //t_MgcpParReqId(omit),
117 t_MgcpParLocConnOpt("p: 20")
118 },
119 sdp := sdp
120 }
121
122 template MgcpCommand ts_DLCX(MgcpTransId trans_id, charstring ep, MgcpCallId call_id) := {
123 line := t_MgcpCmdLine("DLCX", trans_id, ep),
124 params := {
125 ts_MgcpParCallId(call_id)
126 },
127 sdp := omit
128 }
129
130 /* SDP Templates */
131 template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id,
132 charstring session_version := "1",
133 charstring addr_type := "IP4",
134 charstring user_name := "-") := {
135 user_name := user_name,
136 session_id := session_id,
137 session_version := session_version,
138 net_type := "IN",
139 addr_type := addr_type,
140 addr := addr
141 }
142
143 template SDP_connection ts_SDP_connection_IP(charstring addr, charstring addr_type := "IP4",
144 template integer ttl := omit,
145 template integer num_of_addr := omit) :={
146 net_type := "IN",
147 addr_type := addr_type,
148 conn_addr := {
149 addr := addr,
150 ttl := ttl,
151 num_of_addr := num_of_addr
152 }
153 }
154
155 template SDP_time ts_SDP_time(charstring beg, charstring end) := {
156 time_field := {
157 start_time := beg,
158 stop_time := end
159 },
160 time_repeat := omit
161 }
162
163 template SDP_media_desc ts_SDP_media_desc(integer port_number, SDP_fmt_list fmts,
164 SDP_attribute_list attributes) := {
165 media_field := {
166 media := "audio",
167 ports := {
168 port_number := port_number,
169 num_of_ports := omit
170 },
171 transport := "ARTP/AVP",
172 fmts := fmts
173 },
174 information := omit,
175 connections := omit,
176 bandwidth := omit,
177 key := omit,
178 attributes := attributes
179 }
180
Harald Welte21ba5572017-09-19 17:55:05 +0800181 /* master template for generating SDP based in template arguments */
Harald Weltee636afd2017-09-17 16:24:09 +0800182 template SDP_Message ts_SDP(charstring local_addr, charstring remote_addr,
183 charstring session_id, charstring session_version,
184 integer rtp_port, SDP_fmt_list fmts,
185 SDP_attribute_list attributes) := {
186 protocol_version := 0,
187 origin := ts_SDP_origin(local_addr, session_id, session_version),
188 session_name := "-",
189 information := omit,
190 uri := omit,
191 emails := omit,
192 phone_numbers := omit,
193 connection := ts_SDP_connection_IP(remote_addr),
194 bandwidth := omit,
195 times := { ts_SDP_time("0","0") },
196 timezone_adjustments := omit,
197 key := omit,
198 attributes := omit,
199 media_list := { ts_SDP_media_desc(rtp_port, fmts, attributes) }
200 }
201
202 template SDP_attribute ts_SDP_rtpmap(integer fmt, charstring val) := {
203 rtpmap := {
204 attr_value := int2str(fmt) & " " & val
205 }
206 }
207 template SDP_attribute ts_SDP_ptime(integer p) := {
208 ptime := {
209 attr_value := int2str(p)
210 }
211 }
212
Harald Welte00a067f2017-09-13 23:27:17 +0200213 testcase TC_selftest() runs on dummy_CT {
214 const charstring c_auep := "AUEP 158663169 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n";
215 const charstring c_mdcx3 := "MDCX 18983215 1@mgw MGCP 1.0\r\n";
216 const charstring c_mdcx3_ret := "200 18983215 OK\r\n" &
217 "I: 1\n" &
218 "\n" &
219 "v=0\r\n" &
220 "o=- 1 23 IN IP4 0.0.0.0\r\n" &
221 "s=-\r\n" &
222 "c=IN IP4 0.0.0.0\r\n" &
223 "t=0 0\r\n" &
224 "m=audio 0 RTP/AVP 126\r\n" &
225 "a=rtpmap:126 AMR/8000\r\n" &
226 "a=ptime:20\r\n";
227 const charstring c_mdcx4 := "MDCX 18983216 1@mgw MGCP 1.0\r\n" &
228 "M: sendrecv\r" &
229 "C: 2\r\n" &
230 "I: 1\r\n" &
231 "L: p:20, a:AMR, nt:IN\r\n" &
232 "\n" &
233 "v=0\r\n" &
234 "o=- 1 23 IN IP4 0.0.0.0\r\n" &
Harald Welte2871d0b2017-09-14 22:42:12 +0800235 "s=-\r\n" &
Harald Welte00a067f2017-09-13 23:27:17 +0200236 "c=IN IP4 0.0.0.0\r\n" &
237 "t=0 0\r\n" &
238 "m=audio 4441 RTP/AVP 99\r\n" &
239 "a=rtpmap:99 AMR/8000\r\n" &
240 "a=ptime:40\r\n";
Harald Welte3c6ebb92017-09-16 00:56:57 +0800241 const charstring c_crcx510_ret := "510 23 FAIL\r\n"
Harald Welte00a067f2017-09-13 23:27:17 +0200242
243 log(c_auep);
244 log(dec_MgcpCommand(c_auep));
245
246 log(c_mdcx3);
247 log(dec_MgcpCommand(c_mdcx3));
248
249 log(c_mdcx3_ret);
250 log(dec_MgcpResponse(c_mdcx3_ret));
251
252 log(c_mdcx4);
253 log(dec_MgcpCommand(c_mdcx4));
Harald Welte3c6ebb92017-09-16 00:56:57 +0800254
255 log(ts_CRCX("23", "42@mgw", "sendrecv", '1234'H));
256 log(enc_MgcpCommand(valueof(ts_CRCX("23", "42@mgw", "sendrecv", '1234'H))));
257
258 log(c_crcx510_ret);
259 log(dec_MgcpResponse(c_crcx510_ret));
260 log(dec_MgcpMessage(c_crcx510_ret));
261 }
262
Harald Weltee636afd2017-09-17 16:24:09 +0800263 /* CRCX test ideas:
264 * - without mandatory CallId
265 * - without mandatory ConnectionId
266 * - with forbidden parameters (e.g. Capabilities, PackageList, ...
267 * - CRCX with remote session description and without
268 *
269 * general ideas:
270 * - packetization != 20ms
271 * - invalid mode
272 * x unsupported mode (517)
273 * x bidirectional mode before RemoteConnDesc: 527
274 * - invalid codec
275 * - retransmission of same transaction
276 * - unsupported LocalConnectionOptions ("b", "a", "e", "gc", "s", "r", "k", ..)
277 */
278
Harald Welte21ba5572017-09-19 17:55:05 +0800279 /* build a receive template for receiving a MGCP message. You
280 * pass the MGCP response template in, and it will generate an
281 * MGCP_RecvFrom template that can match the primitives arriving on the
282 * MGCP_CodecPort */
Harald Weltee636afd2017-09-17 16:24:09 +0800283 function tr_MGCP_RecvFrom_R(template MgcpResponse resp) runs on dummy_CT return template MGCP_RecvFrom {
284 var template MGCP_RecvFrom mrf := {
Harald Welte55015362017-11-18 16:02:42 +0100285 connId := g_mgcp_conn_id,
Harald Weltee636afd2017-09-17 16:24:09 +0800286 remName := mp_remote_ip,
287 remPort := mp_remote_udp_port,
288 locName := mp_local_ip,
289 locPort := mp_local_udp_port,
290 msg := { response := resp }
291 }
292 return mrf;
293 }
294
295 /* Send a MGCP request + receive a (matching!) response */
296 function mgcp_transceive_mgw(template MgcpCommand cmd, template MgcpResponse resp := ?) runs on dummy_CT return MgcpResponse {
297 var MgcpMessage msg := { command := valueof(cmd) };
298 resp.line.trans_id := cmd.line.trans_id;
299 var template MGCP_RecvFrom mrt := tr_MGCP_RecvFrom_R(resp);
Harald Welte3c6ebb92017-09-16 00:56:57 +0800300 var MGCP_RecvFrom mrf;
301 timer T := 5.0;
302
Harald Welte55015362017-11-18 16:02:42 +0100303 MGCP.send(t_MGCP_Send(g_mgcp_conn_id, msg));
Harald Welte3c6ebb92017-09-16 00:56:57 +0800304 T.start;
305 alt {
Harald Weltee636afd2017-09-17 16:24:09 +0800306 [] MGCP.receive(mrt) -> value mrf { }
307 [] MGCP.receive(tr_MGCP_RecvFrom_R(?)) { setverdict(fail); }
Harald Welte3c6ebb92017-09-16 00:56:57 +0800308 [] MGCP.receive { repeat; }
309 [] T.timeout { setverdict(fail); }
310 }
311 T.stop;
Harald Weltee636afd2017-09-17 16:24:09 +0800312
313 if (isbound(mrf) and isbound(mrf.msg) and ischosen(mrf.msg.response)) {
314 return mrf.msg.response;
315 } else {
316 var MgcpResponse r := { line := { code := "999", trans_id := valueof(cmd.line.trans_id) } };
317 return r;
318 }
Harald Welte00a067f2017-09-13 23:27:17 +0200319 }
320
Harald Weltee636afd2017-09-17 16:24:09 +0800321 /* test valid CRCX without SDP */
322 testcase TC_crcx() runs on dummy_CT {
323 var template MgcpCommand cmd;
324 var MgcpResponse resp;
325 var template MgcpResponse rtmpl := {
326 line := {
327 code := "200",
328 string := "OK"
329 },
Harald Welte6f960b12017-11-17 23:24:46 +0100330 params := { { "I", ? }, *},
Harald Weltee636afd2017-09-17 16:24:09 +0800331 sdp := ?
332 };
333
334 f_init();
335
336 cmd := ts_CRCX(get_next_trans_id(), "2@mgw", "sendrecv", '1234'H);
337 resp := mgcp_transceive_mgw(cmd, rtmpl);
338 setverdict(pass);
339 }
340
341 /* test CRCX with unsupported mode, expect 517 */
342 testcase TC_crcx_unsupp_mode() runs on dummy_CT {
343 var template MgcpCommand cmd;
344 var MgcpResponse resp;
345 var template MgcpResponse rtmpl := tr_MgcpResp_Err("517");
346
347 f_init();
348
349 cmd := ts_CRCX(get_next_trans_id(), "2@mgw", "netwtest", '1234'H);
350 resp := mgcp_transceive_mgw(cmd, rtmpl);
351 setverdict(pass);
352 }
353
Harald Welte21ba5572017-09-19 17:55:05 +0800354 /* test CRCX with early bi-directional mode, expect 527 as
355 * bi-diretional media can only be established once both local and
356 * remote side are specified, see MGCP RFC */
Harald Weltee636afd2017-09-17 16:24:09 +0800357 testcase TC_crcx_early_bidir_mode() runs on dummy_CT {
358 var template MgcpCommand cmd;
359 var MgcpResponse resp;
360 var template MgcpResponse rtmpl := tr_MgcpResp_Err("527");
361
362 f_init();
363
364 cmd := ts_CRCX(get_next_trans_id(), "2@mgw", "sendrecv", '1234'H);
365 resp := mgcp_transceive_mgw(cmd, rtmpl);
366 setverdict(pass);
367 }
368
369 /* test CRCX with unsupported Parameters */
370 testcase TC_crcx_unsupp_param() runs on dummy_CT {
371 var template MgcpCommand cmd;
372 var MgcpResponse resp;
373 var template MgcpResponse rtmpl := tr_MgcpResp_Err("539");
374
375 f_init();
376
377 cmd := ts_CRCX(get_next_trans_id(), "2@mgw", "recvonly", '1234'H);
378 cmd.params := {
379 t_MgcpParConnMode("recvonly"),
380 ts_MgcpParCallId('1234'H),
381 t_MgcpParLocConnOpt("p:20"),
382 /* osmo-bsc_mgcp/mgw doesn't implement notifications */
383 { "N", "foobar" }
384 }
385 resp := mgcp_transceive_mgw(cmd, rtmpl);
386 setverdict(pass);
387 }
388
389 /* test CRCX with missing CallId */
390 testcase TC_crcx_missing_callid() runs on dummy_CT {
391 var template MgcpCommand cmd;
392 var MgcpResponse resp;
393 var template MgcpResponse rtmpl := tr_MgcpResp_Err("400");
394
395 f_init();
396
397 cmd := ts_CRCX(get_next_trans_id(), "2@mgw", "recvonly", '1234'H);
398 cmd.params := {
399 t_MgcpParConnMode("recvonly"),
400 t_MgcpParLocConnOpt("p:20")
401 }
402 resp := mgcp_transceive_mgw(cmd, rtmpl);
403 setverdict(pass);
404 }
405
406 /* test CRCX with missing Mode */
407 testcase TC_crcx_missing_mode() runs on dummy_CT {
408 var template MgcpCommand cmd;
409 var MgcpResponse resp;
410 var template MgcpResponse rtmpl := tr_MgcpResp_Err("400");
411
412 f_init();
413
414 cmd := ts_CRCX(get_next_trans_id(), "2@mgw", "recvonly", '1234'H);
415 cmd.params := {
416 ts_MgcpParCallId('1234'H),
417 t_MgcpParLocConnOpt("p:20")
418 }
419 resp := mgcp_transceive_mgw(cmd, rtmpl);
420 setverdict(pass);
421 }
422
423 /* test CRCX with unsupported packetization interval */
424 testcase TC_crcx_unsupp_packet_intv() runs on dummy_CT {
425 var template MgcpCommand cmd;
426 var MgcpResponse resp;
427 var template MgcpResponse rtmpl := tr_MgcpResp_Err("532");
428
429 f_init();
430
431 cmd := ts_CRCX(get_next_trans_id(), "2@mgw", "recvonly", '1234'H);
432 cmd.params := {
433 t_MgcpParConnMode("recvonly"),
434 ts_MgcpParCallId('1234'H),
435 t_MgcpParLocConnOpt("p:111")
436 }
437 resp := mgcp_transceive_mgw(cmd, rtmpl);
438 setverdict(pass);
439 }
440
441 /* test CRCX with illegal double presence of local connection option */
442 testcase TC_crcx_illegal_double_lco() runs on dummy_CT {
443 var template MgcpCommand cmd;
444 var MgcpResponse resp;
445 var template MgcpResponse rtmpl := tr_MgcpResp_Err("524");
446
447 f_init();
448
449 cmd := ts_CRCX(get_next_trans_id(), "2@mgw", "recvonly", '1234'H);
450 cmd.params := {
451 t_MgcpParConnMode("recvonly"),
452 ts_MgcpParCallId('1234'H),
Harald Welte21ba5572017-09-19 17:55:05 +0800453 /* p:20 is permitted only once and not twice! */
Harald Weltee636afd2017-09-17 16:24:09 +0800454 t_MgcpParLocConnOpt("p:20, a:AMR, p:20")
455 }
456 resp := mgcp_transceive_mgw(cmd, rtmpl);
457 setverdict(pass);
458 }
459
460 /* test valid CRCX with valid SDP */
461 testcase TC_crcx_sdp() runs on dummy_CT {
462 var template MgcpCommand cmd;
463 var MgcpResponse resp;
464 var template MgcpResponse rtmpl := {
465 line := {
466 code := "200",
467 string := "OK"
468 },
Harald Welte6f960b12017-11-17 23:24:46 +0100469 params := { { "I", ? }, *},
Harald Weltee636afd2017-09-17 16:24:09 +0800470 sdp := ?
471 };
472
473 f_init();
474
475 cmd := ts_CRCX(get_next_trans_id(), "2@mgw", "sendrecv", '1234'H);
476 cmd.sdp := ts_SDP("127.0.0.1", "127.0.0.2", "23", "42", 2344, { "98" },
477 { valueof(ts_SDP_rtpmap(98, "AMR/8000")),
478 valueof(ts_SDP_ptime(20)) });
479 resp := mgcp_transceive_mgw(cmd, rtmpl);
480 setverdict(pass);
481 }
482
483 /* TODO: various SDP related bits */
484
485
486 /* TODO: CRCX with X-Osmux */
487 /* TODO: double CRCX without force_realloc */
488
489 /* TODO: MDCX (various) */
490
491 /* TODO: MDCX without CRCX first */
492 testcase TC_mdcx_without_crcx() runs on dummy_CT {
493 var template MgcpCommand cmd;
494 var MgcpResponse resp;
495 var template MgcpResponse rtmpl := {
496 line := {
497 /* TODO: accept/enforce better error? */
498 code := "400",
499 string := ?
500 },
501 params:= { },
502 sdp := omit
503 };
504
505 f_init();
506
507 cmd := ts_MDCX(get_next_trans_id(), "3@mgw", "sendrecv", '31234'H);
508 cmd.sdp := ts_SDP("127.0.0.1", "127.0.0.2", "23", "42", 2344, { "98" },
509 { valueof(ts_SDP_rtpmap(98, "AMR/8000")),
510 valueof(ts_SDP_ptime(20)) });
511 resp := mgcp_transceive_mgw(cmd, rtmpl);
512 setverdict(pass);
513 }
514
515 /* DLCX without CRCX first */
516 testcase TC_dlcx_without_crcx() runs on dummy_CT {
517 var template MgcpCommand cmd;
518 var MgcpResponse resp;
519 var template MgcpResponse rtmpl := {
520 line := {
521 /* TODO: accept/enforce better error? */
522 code := "400",
523 string := ?
524 },
525 params:= { },
526 sdp := omit
527 };
528
529 f_init();
530
531 cmd := ts_DLCX(get_next_trans_id(), "4@mgw", '41234'H);
532 resp := mgcp_transceive_mgw(cmd, rtmpl);
533 setverdict(pass);
534 }
535
Harald Welte21ba5572017-09-19 17:55:05 +0800536 /* Test (valid) CRCX followed by (valid) DLCX */
Harald Welte5b4c44e2017-09-17 16:35:27 +0800537 testcase TC_crcx_and_dlcx() runs on dummy_CT {
538 var template MgcpCommand cmd;
539 var MgcpResponse resp;
540 var template MgcpResponse rtmpl := {
541 line := {
542 code := ("200", "250"),
543 string := "OK"
544 },
Harald Welte6f960b12017-11-17 23:24:46 +0100545 params:= { { "I", ? }, *},
Harald Welte5b4c44e2017-09-17 16:35:27 +0800546 sdp := ?
547 };
548
549 f_init();
550
551 cmd := ts_CRCX(get_next_trans_id(), "5@mgw", "sendrecv", '51234'H);
552 resp := mgcp_transceive_mgw(cmd, rtmpl);
553
554 cmd := ts_DLCX(get_next_trans_id(), "5@mgw", '51234'H);
555 rtmpl.sdp := omit;
Harald Weltecbae9d12017-11-17 23:25:26 +0100556 rtmpl.params := *;
Harald Welte5b4c44e2017-09-17 16:35:27 +0800557 resp := mgcp_transceive_mgw(cmd, rtmpl);
558
559 setverdict(pass);
560 }
561
Harald Weltee636afd2017-09-17 16:24:09 +0800562 /* TODO: DLCX of valid endpoint but invalid call-id */
563 /* TODO: Double-DLCX (retransmission) */
564 /* TODO: Double-DLCX (no retransmission) */
565
566
567
568 /* TODO: AUEP (various) */
569 /* TODO: RSIP (various) */
570 /* TODO: RQNT (various) */
571 /* TODO: EPCF (various) */
572 /* TODO: AUCX (various) */
573 /* TODO: invalid verb (various) */
574
Harald Welte00a067f2017-09-13 23:27:17 +0200575 control {
576 execute(TC_selftest());
Harald Welte3c6ebb92017-09-16 00:56:57 +0800577 execute(TC_crcx());
Harald Weltee636afd2017-09-17 16:24:09 +0800578 execute(TC_crcx_unsupp_mode());
579 execute(TC_crcx_early_bidir_mode());
580 execute(TC_crcx_unsupp_param());
581 execute(TC_crcx_missing_callid());
582 execute(TC_crcx_missing_mode());
583 execute(TC_crcx_unsupp_packet_intv());
584 execute(TC_crcx_illegal_double_lco());
585 execute(TC_crcx_sdp());
586 execute(TC_mdcx_without_crcx());
587 execute(TC_dlcx_without_crcx());
Harald Welte5b4c44e2017-09-17 16:35:27 +0800588 execute(TC_crcx_and_dlcx());
Harald Welte00a067f2017-09-13 23:27:17 +0200589 }
590}