blob: e25929c2c25cf1cd885fe373b5be980229786b0a [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 },
157 { "GET 1 variable value",
158 {
159 .type = CTRL_TYPE_GET,
160 .id = "1",
161 .variable = "variable",
162 .value = NULL,
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100163 },
164 "ERROR 1 Command not found",
165
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200166 },
167 { "GET 1 variable value\n",
168 {
169 .type = CTRL_TYPE_GET,
170 .id = "1",
171 .variable = "variable",
172 .value = NULL,
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100173 },
174 "ERROR 1 Command not found",
175
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200176 },
177 { "GET 1 variable multiple value tokens",
178 {
179 .type = CTRL_TYPE_GET,
180 .id = "1",
181 .variable = "variable",
182 .value = NULL,
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100183 },
184 "ERROR 1 Command not found",
185
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200186 },
187 { "GET 1 variable multiple value tokens\n",
188 {
189 .type = CTRL_TYPE_GET,
190 .id = "1",
191 .variable = "variable",
192 .value = NULL,
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100193 },
194 "ERROR 1 Command not found",
195
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200196 },
197 { "SET 1 variable value",
198 {
199 .type = CTRL_TYPE_SET,
200 .id = "1",
201 .variable = "variable",
202 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100203 },
204 "ERROR 1 Command not found",
205
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200206 },
207 { "SET 1 variable value\n",
208 {
209 .type = CTRL_TYPE_SET,
210 .id = "1",
211 .variable = "variable",
212 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100213 },
214 "ERROR 1 Command not found",
215
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200216 },
217 { "SET weird_id variable value",
218 {
219 .type = CTRL_TYPE_SET,
220 .id = "weird_id",
221 .variable = "variable",
222 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100223 },
224 "ERROR weird_id Command not found",
225
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200226 },
227 { "SET weird_id variable value\n",
228 {
229 .type = CTRL_TYPE_SET,
230 .id = "weird_id",
231 .variable = "variable",
232 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100233 },
234 "ERROR weird_id Command not found",
235
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200236 },
237 { "SET 1 variable multiple value tokens",
238 {
239 .type = CTRL_TYPE_SET,
240 .id = "1",
241 .variable = "variable",
242 .value = "multiple value tokens",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100243 },
244 "ERROR 1 Command not found",
245
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200246 },
247 { "SET 1 variable multiple value tokens\n",
248 {
249 .type = CTRL_TYPE_SET,
250 .id = "1",
251 .variable = "variable",
252 .value = "multiple value tokens",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100253 },
254 "ERROR 1 Command not found",
255
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200256 },
257 { "SET 1 variable value_with_trailing_spaces ",
258 {
259 .type = CTRL_TYPE_SET,
260 .id = "1",
261 .variable = "variable",
262 .value = "value_with_trailing_spaces ",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100263 },
264 "ERROR 1 Command not found",
265
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200266 },
267 { "SET 1 variable value_with_trailing_spaces \n",
268 {
269 .type = CTRL_TYPE_SET,
270 .id = "1",
271 .variable = "variable",
272 .value = "value_with_trailing_spaces ",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100273 },
274 "ERROR 1 Command not found",
275
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200276 },
277 { "SET \n special_char_id value",
278 {
279 .type = CTRL_TYPE_SET,
280 .id = "\n",
281 .variable = "special_char_id",
282 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100283 },
284 "ERROR \n Command not found",
285
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200286 },
287 { "SET \t special_char_id value",
288 {
289 .type = CTRL_TYPE_SET,
290 .id = "\t",
291 .variable = "special_char_id",
292 .value = "value",
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100293 },
294 "ERROR \t Command not found",
295
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200296 },
Neels Hofmeyr6769ad62017-12-16 04:01:54 +0100297 { "GET_REPLY 1 variable OK",
298 {
299 .type = CTRL_TYPE_GET_REPLY,
300 .id = "1",
301 .variable = "variable",
302 .reply = "OK",
303 },
304 .reply_str = NULL,
305 },
306 { "SET_REPLY 1 variable OK",
307 {
308 .type = CTRL_TYPE_SET_REPLY,
309 .id = "1",
310 .variable = "variable",
311 .reply = "OK",
312 },
313 .reply_str = NULL,
314 },
315
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200316};
317
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100318static void test_messages()
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200319{
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100320 struct ctrl_handle *ctrl;
321 struct ctrl_connection *ccon;
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200322 int i;
323
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100324 ctrl = ctrl_handle_alloc2(ctx, NULL, NULL, 0);
325 ccon = talloc_zero(ctx, struct ctrl_connection);
326
327 osmo_wqueue_init(&ccon->write_queue, 1);
328
329 for (i = 0; i < ARRAY_SIZE(test_messages_list); i++)
330 assert_test(ctrl, ccon, &test_messages_list[i]);
331
332 talloc_free(ccon);
333 talloc_free(ctrl);
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200334}
335
336static struct log_info_cat test_categories[] = {
337};
338
339static struct log_info info = {
340 .cat = test_categories,
341 .num_cat = ARRAY_SIZE(test_categories),
342};
343
Max70c7d412017-02-24 13:59:14 +0100344int main(int argc, char **argv)
345{
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200346 ctx = talloc_named_const(NULL, 1, "ctrl_test");
347 osmo_init_logging(&info);
348
Max70c7d412017-02-24 13:59:14 +0100349 printf("Checking ctrl types...\n");
350
351 check_type(CTRL_TYPE_UNKNOWN);
352 check_type(CTRL_TYPE_GET);
353 check_type(CTRL_TYPE_SET);
354 check_type(CTRL_TYPE_GET_REPLY);
355 check_type(CTRL_TYPE_SET_REPLY);
356 check_type(CTRL_TYPE_TRAP);
357 check_type(CTRL_TYPE_ERROR);
358 check_type(64);
359
Neels Hofmeyr83aee832017-12-16 05:38:37 +0100360 test_messages();
Neels Hofmeyr505c9652017-09-26 15:24:58 +0200361
Max70c7d412017-02-24 13:59:14 +0100362 return 0;
363}