blob: b1d4f23755db4ea1709bb5b6ef05bac3d9e47325 [file] [log] [blame]
Max70c7d412017-02-24 13:59:14 +01001#include <stdio.h>
2#include <stdlib.h>
3#include <stdint.h>
4#include <string.h>
5#include <stdbool.h>
6
7#include <osmocom/core/utils.h>
8#include <osmocom/ctrl/control_cmd.h>
Neels Hofmeyr505c9652017-09-26 15:24:58 +02009#include <osmocom/core/logging.h>
10#include <osmocom/core/msgb.h>
11#include <osmocom/core/application.h>
Neels Hofmeyr83aee832017-12-16 05:38:37 +010012#include <osmocom/gsm/protocol/ipaccess.h>
13#include <osmocom/ctrl/control_if.h>
Max70c7d412017-02-24 13:59:14 +010014
Vadim Yanitskiyc2afe812017-06-13 01:43:23 +070015static void check_type(enum ctrl_type c)
Max70c7d412017-02-24 13:59:14 +010016{
17 const char *t = get_value_string(ctrl_type_vals, c);
18 int v = get_string_value(ctrl_type_vals, t);
19
20 printf("ctrl type %d is %s ", c, t);
21 if (v < 0)
22 printf("[PARSE FAILED]\n");
23 else
24 printf("-> %d %s\n", v, c != v ? "FAIL" : "OK");
25}
26
Neels Hofmeyr505c9652017-09-26 15:24:58 +020027struct msgb *msgb_from_string(const char *str)
28{
Neels Hofmeyr83aee832017-12-16 05:38:37 +010029 struct ipaccess_head *iph;
30 struct ipaccess_head_ext *ipx;
31 char *str_msg;
Neels Hofmeyr505c9652017-09-26 15:24:58 +020032 size_t len = strlen(str) + 1;
Neels Hofmeyr83aee832017-12-16 05:38:37 +010033
34 struct msgb *msg = msgb_alloc(1024, str);
35
36 iph = (void*)msgb_put(msg, sizeof(*iph));
37 iph->proto = IPAC_PROTO_OSMO;
38
39 ipx = (void*)msgb_put(msg, sizeof(*ipx));
40 ipx->proto = IPAC_PROTO_EXT_CTRL;
41
42 str_msg = (char*)msgb_put(msg, len);
43 msg->l2h = (void*)str_msg;
44 osmo_strlcpy(str_msg, str, len);
45
46 iph->len = msgb_length(msg);
Neels Hofmeyr505c9652017-09-26 15:24:58 +020047 return msg;
48}
49
50static void *ctx = NULL;
51
Neels Hofmeyr83aee832017-12-16 05:38:37 +010052struct one_test {
53 const char *cmd_str;
54 struct ctrl_cmd expect_parsed;
55 const char *reply_str;
56};
57
Neels Hofmeyr505c9652017-09-26 15:24:58 +020058void assert_same_str(const char *label, const char *expect, const char *got)
59{
60 if ((expect == got) || (expect && got && (strcmp(expect, got) == 0))) {
Neels Hofmeyr0ab6eca2017-12-16 01:03:37 +010061 printf("%s = '%s'\n", label, osmo_escape_str(got, -1));
Neels Hofmeyr505c9652017-09-26 15:24:58 +020062 return;
63 }
64
Neels Hofmeyr0ab6eca2017-12-16 01:03:37 +010065 printf("MISMATCH for '%s':\ngot: %s\n", label, osmo_escape_str(got, -1));
66 printf("expected: %s\n", osmo_escape_str(expect, -1));
Neels Hofmeyr505c9652017-09-26 15:24:58 +020067 OSMO_ASSERT(expect == got);
68}
69
Neels Hofmeyr83aee832017-12-16 05:38:37 +010070static void assert_test(struct ctrl_handle *ctrl, struct ctrl_connection *ccon, const struct one_test *t)
Neels Hofmeyr505c9652017-09-26 15:24:58 +020071{
72 struct ctrl_cmd *cmd;
Neels Hofmeyr83aee832017-12-16 05:38:37 +010073 struct msgb *msg = msgb_from_string(t->cmd_str);
74 int ctx_size_was;
Neels Hofmeyr505c9652017-09-26 15:24:58 +020075
Neels Hofmeyr83aee832017-12-16 05:38:37 +010076 printf("test: '%s'\n", osmo_escape_str(t->cmd_str, -1));
77 printf("parsing:\n");
Neels Hofmeyr505c9652017-09-26 15:24:58 +020078
79 cmd = ctrl_cmd_parse(ctx, msg);
80 OSMO_ASSERT(cmd);
81
Neels Hofmeyr83aee832017-12-16 05:38:37 +010082 OSMO_ASSERT(t->expect_parsed.type == cmd->type);
Neels Hofmeyr505c9652017-09-26 15:24:58 +020083
84#define ASSERT_SAME_STR(field) \
Neels Hofmeyr83aee832017-12-16 05:38:37 +010085 assert_same_str(#field, t->expect_parsed.field, cmd->field)
Neels Hofmeyr505c9652017-09-26 15:24:58 +020086
87 ASSERT_SAME_STR(id);
88 ASSERT_SAME_STR(variable);
89 ASSERT_SAME_STR(value);
90 ASSERT_SAME_STR(reply);
91
92 talloc_free(cmd);
93 msgb_free(msg);
94
Neels Hofmeyr83aee832017-12-16 05:38:37 +010095 printf("handling:\n");
96
97 ctx_size_was = talloc_total_size(ctx);
98
99 msg = msgb_from_string(t->cmd_str);
100 ctrl_handle_msg(ctrl, ccon, msg);
101
102 if (llist_empty(&ccon->write_queue.msg_queue)) {
103 if (t->reply_str) {
104 printf("Got no reply, but expected \"%s\"\n", osmo_escape_str(t->reply_str, -1));
105 OSMO_ASSERT(!t->reply_str);
106 }
107 } else {
108 struct msgb *sent_msg = msgb_dequeue(&ccon->write_queue.msg_queue);
109 OSMO_ASSERT(sent_msg);
110 msgb_put_u8(sent_msg, 0);
111
112 printf("replied: '%s'\n", osmo_escape_str((char*)msgb_l2(sent_msg), -1));
113 OSMO_ASSERT(t->reply_str);
114 OSMO_ASSERT(!strcmp(t->reply_str, (char*)msgb_l2(sent_msg)))
115 msgb_free(sent_msg);
116 }
117 osmo_wqueue_clear(&ccon->write_queue);
118
119 msgb_free(msg);
120
121 if (talloc_total_size(ctx) != ctx_size_was) {
122 printf("mem leak!\n");
Neels Hofmeyrf2c10f12017-12-16 04:05:21 +0100123 talloc_report_full(ctx, stdout);
124 OSMO_ASSERT(false);
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100125 }
126
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200127 printf("ok\n");
128}
129
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100130static const struct one_test test_messages_list[] = {
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200131 { "GET 1 variable",
132 {
133 .type = CTRL_TYPE_GET,
134 .id = "1",
135 .variable = "variable",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100136 },
137 "ERROR 1 Command not found",
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200138 },
139 { "GET 1 variable\n",
140 {
141 .type = CTRL_TYPE_GET,
142 .id = "1",
143 .variable = "variable\n", /* current bug */
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100144 },
145 "ERROR 1 Command not found",
146
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200147 },
148 { "GET 1 var\ni\nable",
149 {
150 .type = CTRL_TYPE_GET,
151 .id = "1",
152 .variable = "var\ni\nable", /* current bug */
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100153 },
154 "ERROR 1 Command not found",
155
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200156 },
Neels Hofmeyr1b8b1522017-12-15 20:41:28 +0100157 { "GET 1 var\ti\table",
158 {
159 .type = CTRL_TYPE_GET,
160 .id = "1",
161 .variable = "var\ti\table", /* current bug */
162 },
163 "ERROR 1 Command not found",
164 },
165 { "GET 1 var\ri\rable",
166 {
167 .type = CTRL_TYPE_GET,
168 .id = "1",
169 .variable = "var\ri\rable", /* current bug */
170 },
171 "ERROR 1 Command not found",
172 },
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200173 { "GET 1 variable value",
174 {
175 .type = CTRL_TYPE_GET,
176 .id = "1",
177 .variable = "variable",
178 .value = NULL,
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100179 },
180 "ERROR 1 Command not found",
181
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200182 },
183 { "GET 1 variable value\n",
184 {
185 .type = CTRL_TYPE_GET,
186 .id = "1",
187 .variable = "variable",
188 .value = NULL,
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100189 },
190 "ERROR 1 Command not found",
191
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200192 },
193 { "GET 1 variable multiple value tokens",
194 {
195 .type = CTRL_TYPE_GET,
196 .id = "1",
197 .variable = "variable",
198 .value = NULL,
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100199 },
200 "ERROR 1 Command not found",
201
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200202 },
203 { "GET 1 variable multiple value tokens\n",
204 {
205 .type = CTRL_TYPE_GET,
206 .id = "1",
207 .variable = "variable",
208 .value = NULL,
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100209 },
210 "ERROR 1 Command not found",
211
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200212 },
213 { "SET 1 variable value",
214 {
215 .type = CTRL_TYPE_SET,
216 .id = "1",
217 .variable = "variable",
218 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100219 },
220 "ERROR 1 Command not found",
221
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200222 },
223 { "SET 1 variable value\n",
224 {
225 .type = CTRL_TYPE_SET,
226 .id = "1",
227 .variable = "variable",
228 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100229 },
230 "ERROR 1 Command not found",
231
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200232 },
233 { "SET weird_id variable value",
234 {
235 .type = CTRL_TYPE_SET,
236 .id = "weird_id",
237 .variable = "variable",
238 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100239 },
240 "ERROR weird_id Command not found",
241
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200242 },
243 { "SET weird_id variable value\n",
244 {
245 .type = CTRL_TYPE_SET,
246 .id = "weird_id",
247 .variable = "variable",
248 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100249 },
250 "ERROR weird_id Command not found",
251
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200252 },
253 { "SET 1 variable multiple value tokens",
254 {
255 .type = CTRL_TYPE_SET,
256 .id = "1",
257 .variable = "variable",
258 .value = "multiple value tokens",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100259 },
260 "ERROR 1 Command not found",
261
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200262 },
263 { "SET 1 variable multiple value tokens\n",
264 {
265 .type = CTRL_TYPE_SET,
266 .id = "1",
267 .variable = "variable",
268 .value = "multiple value tokens",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100269 },
270 "ERROR 1 Command not found",
271
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200272 },
273 { "SET 1 variable value_with_trailing_spaces ",
274 {
275 .type = CTRL_TYPE_SET,
276 .id = "1",
277 .variable = "variable",
278 .value = "value_with_trailing_spaces ",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100279 },
280 "ERROR 1 Command not found",
281
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200282 },
283 { "SET 1 variable value_with_trailing_spaces \n",
284 {
285 .type = CTRL_TYPE_SET,
286 .id = "1",
287 .variable = "variable",
288 .value = "value_with_trailing_spaces ",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100289 },
290 "ERROR 1 Command not found",
291
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200292 },
293 { "SET \n special_char_id value",
294 {
295 .type = CTRL_TYPE_SET,
296 .id = "\n",
297 .variable = "special_char_id",
298 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100299 },
300 "ERROR \n Command not found",
301
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200302 },
303 { "SET \t special_char_id value",
304 {
305 .type = CTRL_TYPE_SET,
306 .id = "\t",
307 .variable = "special_char_id",
308 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100309 },
310 "ERROR \t Command not found",
311
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200312 },
Neels Hofmeyr6769ad62017-12-16 04:01:54 +0100313 { "GET_REPLY 1 variable OK",
314 {
315 .type = CTRL_TYPE_GET_REPLY,
316 .id = "1",
317 .variable = "variable",
318 .reply = "OK",
319 },
320 .reply_str = NULL,
321 },
322 { "SET_REPLY 1 variable OK",
323 {
324 .type = CTRL_TYPE_SET_REPLY,
325 .id = "1",
326 .variable = "variable",
327 .reply = "OK",
328 },
329 .reply_str = NULL,
330 },
331
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200332};
333
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100334static void test_messages()
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200335{
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100336 struct ctrl_handle *ctrl;
337 struct ctrl_connection *ccon;
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200338 int i;
339
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100340 ctrl = ctrl_handle_alloc2(ctx, NULL, NULL, 0);
341 ccon = talloc_zero(ctx, struct ctrl_connection);
342
343 osmo_wqueue_init(&ccon->write_queue, 1);
344
345 for (i = 0; i < ARRAY_SIZE(test_messages_list); i++)
346 assert_test(ctrl, ccon, &test_messages_list[i]);
347
348 talloc_free(ccon);
349 talloc_free(ctrl);
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200350}
351
352static struct log_info_cat test_categories[] = {
353};
354
355static struct log_info info = {
356 .cat = test_categories,
357 .num_cat = ARRAY_SIZE(test_categories),
358};
359
Max70c7d412017-02-24 13:59:14 +0100360int main(int argc, char **argv)
361{
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200362 ctx = talloc_named_const(NULL, 1, "ctrl_test");
363 osmo_init_logging(&info);
364
Max70c7d412017-02-24 13:59:14 +0100365 printf("Checking ctrl types...\n");
366
367 check_type(CTRL_TYPE_UNKNOWN);
368 check_type(CTRL_TYPE_GET);
369 check_type(CTRL_TYPE_SET);
370 check_type(CTRL_TYPE_GET_REPLY);
371 check_type(CTRL_TYPE_SET_REPLY);
372 check_type(CTRL_TYPE_TRAP);
373 check_type(CTRL_TYPE_ERROR);
374 check_type(64);
375
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100376 test_messages();
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200377
Max70c7d412017-02-24 13:59:14 +0100378 return 0;
379}