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