Add snprintf wrapper for GCC 8.2/3
[collectd.git] / src / utils / format_graphite / format_graphite_test.c
1 /**
2  * collectd - src/utils_format_graphite_test.c
3  * Copyright (C) 2016       Florian octo Forster
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Florian octo Forster <octo at collectd.org>
25  */
26
27 #include "collectd.h"
28
29 #include "testing.h"
30 #include "utils/common/common.h" /* for STATIC_ARRAY_SIZE */
31 #include "utils/format_graphite/format_graphite.h"
32
33 static data_set_t ds_single = {
34     .type = "single",
35     .ds_num = 1,
36     .ds = &(data_source_t){"value", DS_TYPE_GAUGE, NAN, NAN},
37 };
38
39 /*
40 static data_set_t ds_double = {
41     .type = "double",
42     .ds_num = 2,
43     .ds =
44         (data_source_t[]){
45             {"one", DS_TYPE_DERIVE, 0, NAN}, {"two", DS_TYPE_DERIVE, 0, NAN},
46         },
47 };
48 */
49
50 DEF_TEST(metric_name) {
51   struct {
52     const char *plugin_instance;
53     const char *type_instance;
54     const char *prefix;
55     const char *suffix;
56     unsigned int flags;
57     const char *want_name;
58   } cases[] = {
59       {
60           .want_name = "example@com.test.single",
61       },
62       /* plugin and type instances */
63       {
64           .plugin_instance = "foo",
65           .type_instance = "bar",
66           .want_name = "example@com.test-foo.single-bar",
67       },
68       {
69           .plugin_instance = NULL,
70           .type_instance = "bar",
71           .want_name = "example@com.test.single-bar",
72       },
73       {
74           .plugin_instance = "foo",
75           .type_instance = NULL,
76           .want_name = "example@com.test-foo.single",
77       },
78       /* special chars */
79       {
80           .plugin_instance = "foo (test)",
81           .type_instance = "test: \"hello\"",
82           .want_name = "example@com.test-foo@@test@.single-test@@@hello@",
83       },
84       /* flag GRAPHITE_SEPARATE_INSTANCES */
85       {
86           .plugin_instance = "foo",
87           .type_instance = "bar",
88           .flags = GRAPHITE_SEPARATE_INSTANCES,
89           .want_name = "example@com.test.foo.single.bar",
90       },
91       /* flag GRAPHITE_ALWAYS_APPEND_DS */
92       {
93           .plugin_instance = "foo",
94           .type_instance = "bar",
95           .flags = GRAPHITE_ALWAYS_APPEND_DS,
96           .want_name = "example@com.test-foo.single-bar.value",
97       },
98       /* flag GRAPHITE_PRESERVE_SEPARATOR */
99       {
100           .plugin_instance = "f.o.o",
101           .type_instance = "b.a.r",
102           .flags = 0,
103           .want_name = "example@com.test-f@o@o.single-b@a@r",
104       },
105       {
106           .plugin_instance = "f.o.o",
107           .type_instance = "b.a.r",
108           .flags = GRAPHITE_PRESERVE_SEPARATOR,
109           .want_name = "example.com.test-f.o.o.single-b.a.r",
110       },
111       /* prefix and suffix */
112       {
113           .prefix = "foo.",
114           .suffix = ".bar",
115           .want_name = "foo.example@com.bar.test.single",
116       },
117       {
118           .prefix = NULL,
119           .suffix = ".bar",
120           .want_name = "example@com.bar.test.single",
121       },
122       {
123           .prefix = "foo.",
124           .suffix = NULL,
125           .want_name = "foo.example@com.test.single",
126       },
127       /* flag GRAPHITE_USE_TAGS */
128       {.flags = GRAPHITE_USE_TAGS,
129        .want_name = "test.single;host=example.com;plugin=test;type=single"},
130       {.plugin_instance = "f.o.o",
131        .type_instance = "b.a.r",
132        .flags = GRAPHITE_USE_TAGS,
133        .want_name = "test.single;host=example.com;plugin=test;plugin_instance="
134                     "f.o.o;type=single;type_instance=b.a.r"},
135       {.flags = GRAPHITE_USE_TAGS ^ GRAPHITE_ALWAYS_APPEND_DS,
136        .want_name = "test.single.value;host=example.com;plugin=test;type="
137                     "single;ds_name=value"},
138       {.plugin_instance = "foo",
139        .type_instance = "foo",
140        .flags = GRAPHITE_USE_TAGS ^ GRAPHITE_DROP_DUPE_FIELDS,
141        .want_name = "test.single;host=example.com;plugin=test;plugin_instance="
142                     "foo;type=single"},
143   };
144
145   for (size_t i = 0; i < STATIC_ARRAY_SIZE(cases); i++) {
146     value_list_t vl = {
147         .values = &(value_t){.gauge = 42},
148         .values_len = 1,
149         .time = TIME_T_TO_CDTIME_T_STATIC(1480063672),
150         .interval = TIME_T_TO_CDTIME_T_STATIC(10),
151         .host = "example.com",
152         .plugin = "test",
153         .type = "single",
154     };
155
156     char want[1024];
157     ssnprintf(want, sizeof(want), "%s 42 1480063672\r\n", cases[i].want_name);
158
159     if (cases[i].plugin_instance != NULL)
160       sstrncpy(vl.plugin_instance, cases[i].plugin_instance,
161                sizeof(vl.plugin_instance));
162     if (cases[i].type_instance != NULL)
163       sstrncpy(vl.type_instance, cases[i].type_instance,
164                sizeof(vl.type_instance));
165
166     char got[1024];
167     EXPECT_EQ_INT(0, format_graphite(got, sizeof(got), &ds_single, &vl,
168                                      cases[i].prefix, cases[i].suffix, '@',
169                                      cases[i].flags));
170     EXPECT_EQ_STR(want, got);
171   }
172
173   return 0;
174 }
175
176 DEF_TEST(null_termination) {
177   value_list_t vl = {
178       .values = &(value_t){.gauge = 1337},
179       .values_len = 1,
180       .time = TIME_T_TO_CDTIME_T_STATIC(1480063672),
181       .interval = TIME_T_TO_CDTIME_T_STATIC(10),
182       .host = "example.com",
183       .plugin = "test",
184       .type = "single",
185   };
186   char const *want = "example_com.test.single 1337 1480063672\r\n";
187
188   char buffer[128];
189   for (size_t i = 0; i < sizeof(buffer); i++)
190     buffer[i] = (char)i;
191
192   EXPECT_EQ_INT(0, format_graphite(buffer, sizeof(buffer), &ds_single, &vl,
193                                    NULL, NULL, '_', 0));
194   EXPECT_EQ_STR(want, buffer);
195   EXPECT_EQ_INT(0, buffer[strlen(want)]);
196   for (size_t i = strlen(want) + 1; i < sizeof(buffer); i++)
197     EXPECT_EQ_INT((int)i, (int)buffer[i]);
198
199   return 0;
200 }
201
202 int main(void) {
203   RUN_TEST(metric_name);
204   RUN_TEST(null_termination);
205
206   END_TEST;
207 }