SNMP Agent plugin:
[collectd.git] / src / snmp_agent_test.c
1 /**
2  * collectd - src/snmp_agent_test.c
3  *
4  * Copyright(c) 2017 Intel Corporation. All rights reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  * Authors:
25  *   Marcin Mozejko <marcinx.mozejko@intel.com>
26  **/
27
28 #include "snmp_agent.c"
29 #include "testing.h"
30
31 DEF_TEST(oid_to_string) {
32   oid_t o = {.oid = {1, 2, 3, 4, 5, 6, 7, 8, 9}, .oid_len = 9};
33   char oid_str[DATA_MAX_NAME_LEN];
34
35   int ret = snmp_agent_oid_to_string(oid_str, DATA_MAX_NAME_LEN, &o);
36   EXPECT_EQ_INT(o.oid_len * 2 - 1, ret);
37   EXPECT_EQ_STR("1.2.3.4.5.6.7.8.9", oid_str);
38
39   return 0;
40 }
41
42 /* Testing formatting metric name for simple scalar */
43 DEF_TEST(format_name_scalar) {
44   data_definition_t *dd = calloc(1, sizeof(*dd));
45
46   dd->plugin = strdup("test_plugin");
47   dd->plugin_instance = strdup("test_plugin_inst");
48   dd->type = strdup("test_type");
49   dd->type_instance = strdup("test_type_inst");
50
51   char name[DATA_MAX_NAME_LEN];
52   int ret = snmp_agent_format_name(name, sizeof(name), dd, NULL);
53
54   EXPECT_EQ_INT(0, ret);
55   EXPECT_EQ_STR(
56       "example.com/test_plugin-test_plugin_inst/test_type-test_type_inst",
57       name);
58
59   sfree(dd->plugin);
60   sfree(dd->plugin_instance);
61   sfree(dd->type);
62   sfree(dd->type_instance);
63   sfree(dd);
64
65   return 0;
66 }
67
68 DEF_TEST(format_name_simple_index) {
69   netsnmp_variable_list *index_list_tmp = NULL;
70   oid_t index_oid;
71   data_definition_t *dd = calloc(1, sizeof(*dd));
72   table_definition_t *td = calloc(1, sizeof(*td));
73
74   td->index_list_cont = NULL;
75   td->index_keys[0].source = INDEX_PLUGIN_INSTANCE;
76   td->index_keys[0].type = ASN_OCTET_STR;
77   td->index_keys[1].source = INDEX_TYPE_INSTANCE;
78   td->index_keys[1].type = ASN_OCTET_STR;
79   dd->table = td;
80   dd->plugin = strdup("test_plugin");
81   dd->type = strdup("test_type");
82
83   char *plugin_inst = strdup("test_plugin_inst");
84   char *type_inst = strdup("test_type_inst");
85
86   snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_OCTET_STR,
87                             plugin_inst, strlen(plugin_inst));
88   snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_OCTET_STR, type_inst,
89                             strlen(type_inst));
90
91   build_oid_noalloc(index_oid.oid, sizeof(index_oid.oid), &index_oid.oid_len,
92                     NULL, 0, index_list_tmp);
93
94   snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_OCTET_STR, NULL,
95                             0);
96   snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_OCTET_STR, NULL,
97                             0);
98
99   char name[DATA_MAX_NAME_LEN];
100
101   int ret = snmp_agent_format_name(name, DATA_MAX_NAME_LEN, dd, &index_oid);
102
103   EXPECT_EQ_INT(0, ret);
104   EXPECT_EQ_STR(
105       "example.com/test_plugin-test_plugin_inst/test_type-test_type_inst",
106       name);
107
108   snmp_free_varbind(index_list_tmp);
109   snmp_free_varbind(td->index_list_cont);
110   sfree(dd->plugin);
111   sfree(dd->type);
112   sfree(dd);
113   sfree(td);
114   sfree(plugin_inst);
115   sfree(type_inst);
116
117   return 0;
118 }
119
120 DEF_TEST(format_name_regex_index) {
121   netsnmp_variable_list *index_list_tmp = NULL;
122   oid_t index_oid;
123   data_definition_t *dd = calloc(1, sizeof(*dd));
124   table_definition_t *td = calloc(1, sizeof(*td));
125
126   td->index_keys_len = 3;
127   td->index_list_cont = NULL;
128   td->index_keys[0].source = INDEX_PLUGIN_INSTANCE;
129   td->index_keys[0].type = ASN_OCTET_STR;
130   td->index_keys[1].source = INDEX_TYPE_INSTANCE;
131   td->index_keys[1].type = ASN_INTEGER;
132   td->index_keys[1].regex = strdup("^vcpu_([0-9]{1,3})-cpu_[0-9]{1,3}$");
133   td->index_keys[1].group = 1;
134   td->index_keys[2].source = INDEX_TYPE_INSTANCE;
135   td->index_keys[2].type = ASN_INTEGER;
136   td->index_keys[2].regex = strdup("^vcpu_[0-9]{1,3}-cpu_([0-9]{1,3})$");
137   td->index_keys[2].group = 1;
138
139   dd->table = td;
140   dd->plugin = strdup("test_plugin");
141   dd->type = strdup("test_type");
142
143   char *plugin_inst = strdup("test_plugin_inst");
144   char *type_inst = strdup("vcpu_1-cpu_10");
145   int vcpu = 1;
146   int cpu = 10;
147
148   snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_OCTET_STR,
149                             plugin_inst, strlen(plugin_inst));
150   snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_INTEGER, &vcpu, 1);
151   snmp_varlist_add_variable(&index_list_tmp, NULL, 0, ASN_INTEGER, &cpu, 1);
152
153   build_oid_noalloc(index_oid.oid, sizeof(index_oid.oid), &index_oid.oid_len,
154                     NULL, 0, index_list_tmp);
155
156   token_t *token;
157   int *offset;
158
159   td->tokens[INDEX_TYPE_INSTANCE] =
160       c_avl_create((int (*)(const void *, const void *))num_compare);
161   snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_OCTET_STR, NULL,
162                             0);
163
164   token = malloc(sizeof(*token));
165   offset = malloc(sizeof(*offset));
166   token->key = snmp_varlist_add_variable(&td->index_list_cont, NULL, 0,
167                                          ASN_INTEGER, NULL, 0);
168   token->str = strdup("vcpu_");
169   *offset = 0;
170   int ret = c_avl_insert(td->tokens[INDEX_TYPE_INSTANCE], (void *)offset,
171                          (void *)token);
172
173   token = malloc(sizeof(*token));
174   offset = malloc(sizeof(*offset));
175   token->key = snmp_varlist_add_variable(&td->index_list_cont, NULL, 0,
176                                          ASN_INTEGER, NULL, 0);
177   token->str = strdup("-cpu_");
178   *offset = 6;
179   ret += c_avl_insert(td->tokens[INDEX_TYPE_INSTANCE], (void *)offset,
180                       (void *)token);
181   char name[DATA_MAX_NAME_LEN];
182
183   ret += snmp_agent_format_name(name, DATA_MAX_NAME_LEN, dd, &index_oid);
184
185   EXPECT_EQ_INT(0, ret);
186   EXPECT_EQ_STR(
187       "example.com/test_plugin-test_plugin_inst/test_type-vcpu_1-cpu_10", name);
188   while (c_avl_pick(td->tokens[INDEX_TYPE_INSTANCE], (void **)&offset,
189                     (void **)&token) == 0) {
190     sfree(offset);
191     sfree(token->str);
192     sfree(token);
193   }
194   c_avl_destroy(td->tokens[INDEX_TYPE_INSTANCE]);
195   snmp_free_varbind(index_list_tmp);
196   snmp_free_varbind(td->index_list_cont);
197   for (int i = 0; i < td->index_keys_len; i++)
198     sfree(td->index_keys[i].regex);
199   sfree(dd->plugin);
200   sfree(dd->type);
201   sfree(dd);
202   sfree(td);
203   sfree(plugin_inst);
204   sfree(type_inst);
205
206   return 0;
207 }
208
209 DEF_TEST(prep_index_list) {
210   table_definition_t *td = calloc(1, sizeof(*td));
211
212   assert(td != NULL);
213   td->index_keys_len = 5;
214   td->index_keys[0].source = INDEX_HOST;
215   td->index_keys[0].type = ASN_OCTET_STR;
216   td->index_keys[1].source = INDEX_PLUGIN;
217   td->index_keys[1].type = ASN_OCTET_STR;
218   td->index_keys[2].source = INDEX_PLUGIN_INSTANCE;
219   td->index_keys[2].type = ASN_INTEGER;
220   td->index_keys[3].source = INDEX_TYPE;
221   td->index_keys[3].type = ASN_INTEGER;
222   td->index_keys[4].source = INDEX_TYPE_INSTANCE;
223   td->index_keys[4].type = ASN_OCTET_STR;
224   td->index_list_cont = NULL;
225
226   int ret = snmp_agent_prep_index_list(td, &td->index_list_cont);
227   EXPECT_EQ_INT(0, ret);
228
229   netsnmp_variable_list *key = td->index_list_cont;
230
231   OK(key != NULL);
232   EXPECT_EQ_INT(ASN_OCTET_STR, key->type);
233   key = key->next_variable;
234   OK(key != NULL);
235   EXPECT_EQ_INT(ASN_OCTET_STR, key->type);
236   key = key->next_variable;
237   OK(key != NULL);
238   EXPECT_EQ_INT(ASN_INTEGER, key->type);
239   key = key->next_variable;
240   OK(key != NULL);
241   EXPECT_EQ_INT(ASN_INTEGER, key->type);
242   key = key->next_variable;
243   OK(key != NULL);
244   EXPECT_EQ_INT(ASN_OCTET_STR, key->type);
245   key = key->next_variable;
246   OK(key == NULL);
247
248   snmp_free_varbind(td->index_list_cont);
249   sfree(td);
250
251   return 0;
252 }
253
254 DEF_TEST(fill_index_list_simple) {
255   table_definition_t *td = calloc(1, sizeof(*td));
256   assert(td != NULL);
257
258   /* Preparing value list */
259   value_list_t *vl = calloc(1, sizeof(*vl));
260   assert(vl != NULL);
261   strncpy(vl->host, "test_hostname", DATA_MAX_NAME_LEN);
262   strncpy(vl->plugin, "test_plugin", DATA_MAX_NAME_LEN);
263   strncpy(vl->plugin_instance, "test_plugin_inst", DATA_MAX_NAME_LEN);
264   strncpy(vl->type, "test_type", DATA_MAX_NAME_LEN);
265   strncpy(vl->type_instance, "test_type_inst", DATA_MAX_NAME_LEN);
266
267   td->index_keys_len = 5;
268   td->index_keys[0].source = INDEX_HOST;
269   td->index_keys[0].type = ASN_OCTET_STR;
270   td->index_keys[1].source = INDEX_PLUGIN;
271   td->index_keys[1].type = ASN_OCTET_STR;
272   td->index_keys[2].source = INDEX_PLUGIN_INSTANCE;
273   td->index_keys[2].type = ASN_OCTET_STR;
274   td->index_keys[3].source = INDEX_TYPE;
275   td->index_keys[3].type = ASN_OCTET_STR;
276   td->index_keys[4].source = INDEX_TYPE_INSTANCE;
277   td->index_keys[4].type = ASN_OCTET_STR;
278
279   td->index_list_cont = NULL;
280   for (int i = 0; i < td->index_keys_len; i++)
281     snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_OCTET_STR,
282                               NULL, 0);
283
284   int ret = snmp_agent_fill_index_list(td, vl);
285   EXPECT_EQ_INT(0, ret);
286
287   netsnmp_variable_list *key = td->index_list_cont;
288
289   ret = 0;
290
291   OK(key != NULL);
292   EXPECT_EQ_STR(vl->host, (char *)key->val.string);
293   key = key->next_variable;
294   OK(key != NULL);
295   EXPECT_EQ_STR(vl->plugin, (char *)key->val.string);
296   key = key->next_variable;
297   OK(key != NULL);
298   EXPECT_EQ_STR(vl->plugin_instance, (char *)key->val.string);
299   key = key->next_variable;
300   OK(key != NULL);
301   EXPECT_EQ_STR(vl->type, (char *)key->val.string);
302   key = key->next_variable;
303   OK(key != NULL);
304   EXPECT_EQ_STR(vl->type_instance, (char *)key->val.string);
305   key = key->next_variable;
306   OK(key == NULL);
307
308   snmp_free_varbind(td->index_list_cont);
309   sfree(vl);
310   sfree(td);
311
312   return 0;
313 }
314
315 DEF_TEST(fill_index_list_regex) {
316   table_definition_t *td = calloc(1, sizeof(*td));
317   int ret = 0;
318
319   assert(td != NULL);
320
321   /* Preparing value list */
322   value_list_t *vl = calloc(1, sizeof(*vl));
323   strncpy(vl->plugin_instance, "test_plugin_inst", DATA_MAX_NAME_LEN);
324   strncpy(vl->type_instance, "1test2test3", DATA_MAX_NAME_LEN);
325
326   td->index_keys_len = 4;
327   td->index_keys[0].source = INDEX_PLUGIN_INSTANCE;
328   td->index_keys[0].type = ASN_OCTET_STR;
329   td->index_keys[1].source = INDEX_TYPE_INSTANCE;
330   td->index_keys[1].type = ASN_INTEGER;
331   td->index_keys[1].regex = strdup("^([0-9])test[0-9]test[0-9]$");
332   td->index_keys[1].group = 1;
333   td->index_keys[2].source = INDEX_TYPE_INSTANCE;
334   td->index_keys[2].type = ASN_INTEGER;
335   td->index_keys[2].regex = strdup("^[0-9]test([0-9])test[0-9]$");
336   td->index_keys[2].group = 1;
337   td->index_keys[3].source = INDEX_TYPE_INSTANCE;
338   td->index_keys[3].type = ASN_INTEGER;
339   td->index_keys[3].regex = strdup("^[0-9]test[0-9]test([0-9])$");
340   td->index_keys[3].group = 1;
341
342   td->index_list_cont = NULL;
343   snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_OCTET_STR, NULL,
344                             0);
345   for (int i = 1; i < td->index_keys_len; i++) {
346     snmp_varlist_add_variable(&td->index_list_cont, NULL, 0, ASN_INTEGER, NULL,
347                               0);
348     ret = regcomp(&td->index_keys[i].regex_info, td->index_keys[i].regex,
349                   REG_EXTENDED);
350     EXPECT_EQ_INT(0, ret);
351   }
352   td->tokens[INDEX_TYPE_INSTANCE] =
353       c_avl_create((int (*)(const void *, const void *))num_compare);
354   assert(td->tokens[INDEX_TYPE_INSTANCE] != NULL);
355
356   ret = snmp_agent_fill_index_list(td, vl);
357   EXPECT_EQ_INT(0, ret);
358   EXPECT_EQ_INT(1, td->tokens_done);
359
360   netsnmp_variable_list *key = td->index_list_cont;
361
362   OK(key != NULL);
363   EXPECT_EQ_STR(vl->plugin_instance, (char *)key->val.string);
364   key = key->next_variable;
365   OK(key != NULL);
366   EXPECT_EQ_INT(1, *key->val.integer);
367   key = key->next_variable;
368   OK(key != NULL);
369   EXPECT_EQ_INT(2, *key->val.integer);
370   key = key->next_variable;
371   OK(key != NULL);
372   EXPECT_EQ_INT(3, *key->val.integer);
373   key = key->next_variable;
374   OK(key == NULL);
375
376   token_t *token;
377   int *offset;
378
379   while (c_avl_pick(td->tokens[INDEX_TYPE_INSTANCE], (void **)&offset,
380                     (void **)&token) == 0) {
381     sfree(offset);
382     sfree(token->str);
383     sfree(token);
384   }
385
386   c_avl_destroy(td->tokens[INDEX_TYPE_INSTANCE]);
387   snmp_free_varbind(td->index_list_cont);
388   sfree(vl);
389
390   for (int i = 0; i < td->index_keys_len; i++) {
391     sfree(td->index_keys[i].regex);
392     regfree(&td->index_keys[i].regex_info);
393   }
394   sfree(td);
395
396   return 0;
397 }
398
399 DEF_TEST(config_index_key_source) {
400   oconfig_item_t *ci = calloc(1, sizeof(*ci));
401   table_definition_t *td = calloc(1, sizeof(*td));
402   data_definition_t *dd = calloc(1, sizeof(*dd));
403
404   assert(ci != NULL);
405   assert(td != NULL);
406   assert(dd != NULL);
407
408   ci->values = calloc(1, sizeof(*ci->values));
409   assert(ci->values != NULL);
410   ci->values_num = 1;
411   ci->values->value.string = strdup("PluginInstance");
412   ci->values->type = OCONFIG_TYPE_STRING;
413
414   int ret = snmp_agent_config_index_key_source(td, dd, ci);
415
416   EXPECT_EQ_INT(0, ret);
417   EXPECT_EQ_INT(1, td->index_keys_len);
418   EXPECT_EQ_INT(0, dd->index_key_pos);
419   EXPECT_EQ_INT(INDEX_PLUGIN_INSTANCE, td->index_keys[0].source);
420   EXPECT_EQ_INT(GROUP_UNUSED, td->index_keys[0].group);
421   OK(td->index_keys[0].regex == NULL);
422
423   sfree(ci->values->value.string);
424   sfree(ci->values);
425   sfree(ci);
426   sfree(td);
427   sfree(dd);
428
429   return 0;
430 }
431
432 DEF_TEST(config_index_key_regex) {
433   oconfig_item_t *ci = calloc(1, sizeof(*ci));
434   table_definition_t *td = calloc(1, sizeof(*td));
435   data_definition_t *dd = calloc(1, sizeof(*dd));
436
437   assert(ci != NULL);
438   assert(td != NULL);
439   assert(dd != NULL);
440
441   dd->index_key_pos = 0;
442   td->index_keys_len = 1;
443   td->index_keys[0].source = INDEX_PLUGIN_INSTANCE;
444   td->index_keys[0].group = 1;
445   ci->values = calloc(1, sizeof(*ci->values));
446   assert(ci->values != NULL);
447   ci->values_num = 1;
448   ci->values->value.string = strdup("^([0-9])test[0-9]test[0-9]$");
449   ci->values->type = OCONFIG_TYPE_STRING;
450
451   int ret = snmp_agent_config_index_key_regex(td, dd, ci);
452
453   EXPECT_EQ_INT(0, ret);
454   EXPECT_EQ_STR(td->index_keys[0].regex, "^([0-9])test[0-9]test[0-9]$");
455   OK(td->tokens[INDEX_PLUGIN_INSTANCE] != NULL);
456
457   c_avl_destroy(td->tokens[INDEX_PLUGIN_INSTANCE]);
458   sfree(ci->values->value.string);
459   sfree(ci->values);
460   sfree(ci);
461   sfree(td->index_keys[0].regex);
462   regfree(&td->index_keys[0].regex_info);
463   sfree(td);
464   sfree(dd);
465
466   return 0;
467 }
468
469 DEF_TEST(config_index_key) {
470   oconfig_item_t *ci = calloc(1, sizeof(*ci));
471   table_definition_t *td = calloc(1, sizeof(*td));
472   data_definition_t *dd = calloc(1, sizeof(*dd));
473
474   assert(ci != NULL);
475   assert(td != NULL);
476   assert(dd != NULL);
477
478   ci->children_num = 3;
479   ci->children = calloc(1, sizeof(*ci->children) * ci->children_num);
480
481   ci->children[0].key = strdup("Source");
482   ci->children[0].parent = ci;
483   ci->children[0].values_num = 1;
484   ci->children[0].values = calloc(1, sizeof(*ci->children[0].values));
485   assert(ci->children[0].values != NULL);
486   ci->children[0].values->value.string = strdup("PluginInstance");
487   ci->children[0].values->type = OCONFIG_TYPE_STRING;
488
489   ci->children[1].key = strdup("Regex");
490   ci->children[1].parent = ci;
491   ci->children[1].values_num = 1;
492   ci->children[1].values = calloc(1, sizeof(*ci->children[0].values));
493   assert(ci->children[1].values != NULL);
494   ci->children[1].values->value.string = strdup("^([0-9])test[0-9]test[0-9]$");
495   ci->children[1].values->type = OCONFIG_TYPE_STRING;
496
497   ci->children[2].key = strdup("Group");
498   ci->children[2].parent = ci;
499   ci->children[2].values_num = 1;
500   ci->children[2].values = calloc(1, sizeof(*ci->children[0].values));
501   assert(ci->children[2].values != NULL);
502   ci->children[2].values->value.number = 1;
503   ci->children[2].values->type = OCONFIG_TYPE_NUMBER;
504
505   int ret = snmp_agent_config_index_key(td, dd, ci);
506
507   EXPECT_EQ_INT(0, ret);
508   EXPECT_EQ_INT(1, td->index_keys_len);
509   EXPECT_EQ_INT(0, dd->index_key_pos);
510   EXPECT_EQ_INT(INDEX_PLUGIN_INSTANCE, td->index_keys[0].source);
511   EXPECT_EQ_INT(1, td->index_keys[0].group);
512   EXPECT_EQ_STR("^([0-9])test[0-9]test[0-9]$", td->index_keys[0].regex);
513   OK(td->tokens[INDEX_PLUGIN_INSTANCE] != NULL);
514
515   sfree(ci->children[0].values->value.string);
516   sfree(ci->children[0].values);
517   sfree(ci->children[0].key);
518
519   sfree(ci->children[1].values->value.string);
520   sfree(ci->children[1].values);
521   sfree(ci->children[1].key);
522
523   sfree(ci->children[2].values);
524   sfree(ci->children[2].key);
525
526   sfree(ci->children);
527   sfree(ci);
528
529   c_avl_destroy(td->tokens[INDEX_PLUGIN_INSTANCE]);
530   sfree(dd);
531   sfree(td->index_keys[0].regex);
532   regfree(&td->index_keys[0].regex_info);
533   sfree(td);
534
535   return 0;
536 }
537
538 DEF_TEST(parse_index_key) {
539   char *regex = strdup("test-([0-9])-([0-9])");
540   char *input = strdup("snmp-test-5-6");
541   regex_t regex_info;
542   regmatch_t match;
543
544   assert(regex != NULL);
545   assert(input != NULL);
546
547   int ret = regcomp(&regex_info, regex, REG_EXTENDED);
548   EXPECT_EQ_INT(0, ret);
549
550   ret = snmp_agent_parse_index_key(input, regex, &regex_info, 0, &match);
551   EXPECT_EQ_INT(0, ret);
552   EXPECT_EQ_INT(5, match.rm_so);
553   EXPECT_EQ_INT(13, match.rm_eo);
554
555   ret = snmp_agent_parse_index_key(input, regex, &regex_info, 1, &match);
556   EXPECT_EQ_INT(0, ret);
557   EXPECT_EQ_INT(10, match.rm_so);
558   EXPECT_EQ_INT(11, match.rm_eo);
559
560   ret = snmp_agent_parse_index_key(input, regex, &regex_info, 2, &match);
561   EXPECT_EQ_INT(0, ret);
562   EXPECT_EQ_INT(12, match.rm_so);
563   EXPECT_EQ_INT(13, match.rm_eo);
564
565   sfree(regex);
566   sfree(input);
567   regfree(&regex_info);
568
569   return 0;
570 }
571
572 DEF_TEST(create_token) {
573   c_avl_tree_t *tokens =
574       c_avl_create((int (*)(const void *, const void *))num_compare);
575   char *input = strdup("testA1-testB2");
576
577   assert(tokens != NULL);
578   assert(input != NULL);
579
580   int ret = snmp_agent_create_token(input, 0, 5, tokens, NULL);
581   EXPECT_EQ_INT(0, ret);
582   ret = snmp_agent_create_token(input, 6, 6, tokens, NULL);
583   EXPECT_EQ_INT(0, ret);
584   EXPECT_EQ_INT(2, c_avl_size(tokens));
585
586   token_t *token;
587   int *offset;
588
589   ret = c_avl_pick(tokens, (void **)&offset, (void **)&token);
590   EXPECT_EQ_INT(0, ret);
591   EXPECT_EQ_INT(6, *offset);
592   EXPECT_EQ_STR("-testB", token->str);
593   sfree(offset);
594   sfree(token->str);
595   sfree(token);
596
597   ret = c_avl_pick(tokens, (void **)&offset, (void **)&token);
598   EXPECT_EQ_INT(0, ret);
599   EXPECT_EQ_INT(0, *offset);
600   EXPECT_EQ_STR("testA", token->str);
601   sfree(offset);
602   sfree(token->str);
603   sfree(token);
604
605   ret = c_avl_pick(tokens, (void **)&offset, (void **)&token);
606   OK(ret != 0);
607
608   c_avl_destroy(tokens);
609   sfree(input);
610
611   return 0;
612 }
613
614 DEF_TEST(delete_token) {
615   c_avl_tree_t *tokens =
616       c_avl_create((int (*)(const void *, const void *))num_compare);
617   char *input = strdup("testA1-testB2-testC3");
618
619   assert(tokens != NULL);
620   assert(input != NULL);
621
622   int ret = snmp_agent_create_token(input, 0, 5, tokens, NULL);
623   EXPECT_EQ_INT(0, ret);
624   ret = snmp_agent_create_token(input, 6, 6, tokens, NULL);
625   EXPECT_EQ_INT(0, ret);
626   ret = snmp_agent_create_token(input, 13, 6, tokens, NULL);
627   EXPECT_EQ_INT(0, ret);
628   EXPECT_EQ_INT(3, c_avl_size(tokens));
629   ret = snmp_agent_delete_token(6, tokens);
630   EXPECT_EQ_INT(0, ret);
631
632   token_t *token;
633   int *offset;
634
635   ret = c_avl_pick(tokens, (void **)&offset, (void **)&token);
636   EXPECT_EQ_INT(0, ret);
637   EXPECT_EQ_INT(0, *offset);
638   EXPECT_EQ_STR("testA", token->str);
639   sfree(offset);
640   sfree(token->str);
641   sfree(token);
642
643   ret = c_avl_pick(tokens, (void **)&offset, (void **)&token);
644   EXPECT_EQ_INT(0, ret);
645   EXPECT_EQ_INT(13, *offset);
646   EXPECT_EQ_STR("-testC", token->str);
647   sfree(offset);
648   sfree(token->str);
649   sfree(token);
650
651   ret = c_avl_pick(tokens, (void **)&offset, (void **)&token);
652   OK(ret != 0);
653
654   c_avl_destroy(tokens);
655   sfree(input);
656
657   return 0;
658 }
659
660 DEF_TEST(get_token) {
661   c_avl_tree_t *tokens =
662       c_avl_create((int (*)(const void *, const void *))num_compare);
663   char *input = strdup("testA1-testB2-testC3");
664
665   assert(tokens != NULL);
666   assert(input != NULL);
667
668   int ret = snmp_agent_create_token(input, 0, 5, tokens, NULL);
669   EXPECT_EQ_INT(0, ret);
670   ret = snmp_agent_create_token(input, 6, 6, tokens, NULL);
671   EXPECT_EQ_INT(0, ret);
672   ret = snmp_agent_create_token(input, 13, 6, tokens, NULL);
673   EXPECT_EQ_INT(0, ret);
674   EXPECT_EQ_INT(3, c_avl_size(tokens));
675   ret = snmp_agent_get_token(tokens, 12);
676   EXPECT_EQ_INT(6, ret);
677
678   token_t *token;
679   int *offset;
680
681   while (c_avl_pick(tokens, (void **)&offset, (void **)&token) == 0) {
682     sfree(offset);
683     sfree(token->str);
684     sfree(token);
685   }
686
687   c_avl_destroy(tokens);
688   sfree(input);
689
690   return 0;
691 }
692
693 DEF_TEST(tokenize) {
694   regmatch_t m[3] = {{5, 6},    /* "1" */
695                      {12, 13},  /* "2" */
696                      {19, 20}}; /* "3" */
697   c_avl_tree_t *tokens =
698       c_avl_create((int (*)(const void *, const void *))num_compare);
699   char *input = strdup("testA1-testB2-testC3");
700   token_t *token;
701   int *offset;
702   c_avl_iterator_t *it;
703   int ret;
704
705   assert(tokens != NULL);
706   assert(input != NULL);
707
708   /* First pass */
709   ret = snmp_agent_tokenize(input, tokens, &m[0], NULL);
710   EXPECT_EQ_INT(0, ret);
711   it = c_avl_get_iterator(tokens);
712   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
713   EXPECT_EQ_INT(0, ret);
714   EXPECT_EQ_STR("testA", token->str);
715   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
716   EXPECT_EQ_INT(0, ret);
717   EXPECT_EQ_STR("-testB2-testC3", token->str);
718   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
719   OK(ret != 0);
720   c_avl_iterator_destroy(it);
721
722   /* Second pass */
723   ret = snmp_agent_tokenize(input, tokens, &m[1], NULL);
724   EXPECT_EQ_INT(0, ret);
725   it = c_avl_get_iterator(tokens);
726   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
727   EXPECT_EQ_INT(0, ret);
728   EXPECT_EQ_STR("testA", token->str);
729   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
730   EXPECT_EQ_INT(0, ret);
731   EXPECT_EQ_STR("-testB", token->str);
732   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
733   EXPECT_EQ_INT(0, ret);
734   EXPECT_EQ_STR("-testC3", token->str);
735   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
736   OK(ret != 0);
737   c_avl_iterator_destroy(it);
738
739   /* Third pass */
740   ret = snmp_agent_tokenize(input, tokens, &m[2], NULL);
741   EXPECT_EQ_INT(0, ret);
742   it = c_avl_get_iterator(tokens);
743   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
744   EXPECT_EQ_INT(0, ret);
745   EXPECT_EQ_STR("testA", token->str);
746   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
747   EXPECT_EQ_INT(0, ret);
748   EXPECT_EQ_STR("-testB", token->str);
749   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
750   EXPECT_EQ_INT(0, ret);
751   EXPECT_EQ_STR("-testC", token->str);
752   ret = c_avl_iterator_next(it, (void **)&offset, (void **)&token);
753   OK(ret != 0);
754   c_avl_iterator_destroy(it);
755
756   while (c_avl_pick(tokens, (void **)&offset, (void **)&token) == 0) {
757     sfree(offset);
758     sfree(token->str);
759     sfree(token);
760   }
761
762   c_avl_destroy(tokens);
763   sfree(input);
764
765   return 0;
766 }
767
768 DEF_TEST(build_name) {
769   table_definition_t *td = calloc(1, sizeof(*td));
770   c_avl_tree_t *tokens =
771       c_avl_create((int (*)(const void *, const void *))num_compare);
772
773   assert(tokens != NULL);
774   assert(td != NULL);
775
776   int n[3] = {1, 2, 3};
777   char *t[3] = {"testA", "-testB", "-testC"};
778   int off[3] = {0, 6, 13};
779   token_t *token;
780   int *offset;
781   int ret = 0;
782   char *name = NULL;
783
784   td->index_list_cont = NULL;
785   for (int i = 0; i < 3; i++) {
786     token = malloc(sizeof(*token));
787     token->str = t[i];
788     token->key = snmp_varlist_add_variable(&td->index_list_cont, NULL, 0,
789                                            ASN_INTEGER, &n[i], sizeof(n[i]));
790     assert(token->key != NULL);
791     offset = &off[i];
792     ret = c_avl_insert(tokens, (void *)offset, (void *)token);
793     assert(ret == 0);
794   }
795
796   ret = snmp_agent_build_name(&name, tokens);
797   EXPECT_EQ_INT(0, ret);
798   EXPECT_EQ_STR("testA1-testB2-testC3", name);
799
800   while (c_avl_pick(tokens, (void **)&offset, (void **)&token) == 0)
801     sfree(token);
802
803   c_avl_destroy(tokens);
804   snmp_free_varbind(td->index_list_cont);
805   sfree(td);
806   sfree(name);
807   return 0;
808 }
809
810 int main(void) {
811   /* snmp_agent_oid_to_string */
812   RUN_TEST(oid_to_string);
813
814   /* snmp_agent_prep_index_list */
815   RUN_TEST(prep_index_list);
816
817   /* snmp_agent_fill_index_list */
818   RUN_TEST(fill_index_list_simple);
819   RUN_TEST(fill_index_list_regex);
820
821   /* snmp_agent_format_name */
822   RUN_TEST(format_name_scalar);
823   RUN_TEST(format_name_simple_index);
824   RUN_TEST(format_name_regex_index);
825
826   /* snmp_agent_config_index_key_source */
827   RUN_TEST(config_index_key_source);
828
829   /* snmp_agent_config_index_key_regex */
830   RUN_TEST(config_index_key_regex);
831
832   /* snmp_agent_config_index_key */
833   RUN_TEST(config_index_key);
834
835   /*snmp_agent_parse_index_key */
836   RUN_TEST(parse_index_key);
837
838   /* snmp_agent_create_token */
839   RUN_TEST(create_token);
840
841   /* snmp_agent_delete_token */
842   RUN_TEST(delete_token);
843
844   /* snmp_agent_get_token */
845   RUN_TEST(get_token);
846
847   /* snmp_agent_tokenize */
848   RUN_TEST(tokenize);
849
850   /* snmp_agent_build_name */
851   RUN_TEST(build_name);
852
853   END_TEST;
854 }