src/utils_parse_json.c: Implement parse_json().
[collectd.git] / src / utils_parse_json_test.c
1 /**
2  * collectd - src/tests/utils_parse_json_test.c
3  * Copyright (C) 2018  Florian Forster
4  *
5  * MIT License
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * Authors:
26  *   Florian Forster <octo at collectd.org>
27  **/
28
29 #include "utils_parse_json.h"
30 #include "testing.h"
31
32 DEF_TEST(single_value) /* {{{ */
33 {
34   char const *json =
35       "["
36       /* gauge */
37       "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
38       "\"time\":1434357493.398,\"interval\":10.000,"
39       "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
40       /* gauge (NaN) */
41       "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"gauge\","
42       "\"time\":1434357493.398,\"interval\":10.000,"
43       "\"dstypes\":[\"gauge\"],\"values\":[null]},"
44       /* derive */
45       "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"total_things\","
46       "\"plugin_instance\":\"foo\",\"type_instance\":\"bar\","
47       "\"time\":1434357493.398,\"interval\":10.000,"
48       "\"dstypes\":[\"derive\"],\"values\":[31337]}"
49       "]";
50
51   value_list_t **vls = NULL;
52   size_t vls_num = 0;
53
54   CHECK_ZERO(parse_json(json, &vls, &vls_num));
55   OK(vls_num == 3);
56   if (vls_num != 3)
57     return (-1);
58
59   value_list_t *vl = vls[0];
60   EXPECT_EQ_STR("example.com", vl->host);
61   EXPECT_EQ_STR("test", vl->plugin);
62   EXPECT_EQ_STR("", vl->plugin_instance);
63   EXPECT_EQ_STR("answer", vl->type);
64   EXPECT_EQ_STR("", vl->type_instance);
65   OK(vl->time == 1540129631229236480);
66   OK(vl->interval == 10737418240);
67   OK(vl->values_len == 1);
68   OK(vl->values[0].gauge == 42.0);
69
70   vl = vls[1];
71   OK(vl->values_len == 1);
72   OK(isnan(vl->values[0].gauge));
73
74   vl = vls[2];
75   EXPECT_EQ_STR("example.com", vl->host);
76   EXPECT_EQ_STR("test", vl->plugin);
77   EXPECT_EQ_STR("foo", vl->plugin_instance);
78   EXPECT_EQ_STR("total_things", vl->type);
79   EXPECT_EQ_STR("bar", vl->type_instance);
80   OK(vl->time == 1540129631229236480);
81   OK(vl->interval == 10737418240);
82   OK(vl->values_len == 1);
83   OK(vl->values[0].derive == 31337);
84
85   free(vls[0]->values);
86   free(vls[0]);
87   free(vls[1]->values);
88   free(vls[1]);
89   free(vls);
90   return (0);
91 } /* }}} single_value */
92
93 DEF_TEST(multi_value) /* {{{ */
94 {
95   char const *json =
96       "["
97       "{\"host\":\"example.com\",\"plugin\":\"load\",\"type\":\"load\","
98       "\"time\":1434357493,\"interval\":10,"
99       "\"dstypes\":[\"gauge\",\"gauge\",\"gauge\"],\"values\":[1.12,0.56,0.64]}"
100       "]";
101
102   value_list_t **vls = NULL;
103   size_t vls_num = 0;
104
105   CHECK_ZERO(parse_json(json, &vls, &vls_num));
106   OK(vls_num == 1);
107
108   value_list_t *vl = vls[0];
109   EXPECT_EQ_STR("example.com", vl->host);
110   EXPECT_EQ_STR("load", vl->plugin);
111   EXPECT_EQ_STR("load", vl->type);
112   OK(vl->time == 1540129630801887232);
113   OK(vl->interval == 10737418240);
114
115   OK(vl->values_len == 3);
116   OK(vl->values[0].gauge == 1.12);
117   OK(vl->values[1].gauge == 0.56);
118   OK(vl->values[2].gauge == 0.64);
119
120   free(vl->values);
121   free(vl);
122   free(vls);
123   return (0);
124 } /* }}} multi_value */
125
126 DEF_TEST(failures) /* {{{ */
127 {
128   char const *json =
129       "["
130       /* host missing */
131       "{\"plugin\":\"test\",\"type\":\"answer\","
132       "\"time\":1434357493.398,\"interval\":10.000,"
133       "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
134       /* plugin missing */
135       "{\"host\":\"example.com\",\"type\":\"answer\","
136       "\"time\":1434357493.398,\"interval\":10.000,"
137       "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
138       /* type missing */
139       "{\"host\":\"example.com\",\"plugin\":\"test\","
140       "\"time\":1434357493.398,\"interval\":10.000,"
141       "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
142       /* time missing */
143       "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
144       "\"interval\":10.000,"
145       "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
146       /* interval missing */
147       "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
148       "\"time\":1434357493.398,"
149       "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
150       /* derive -> floating point mismatch */
151       "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
152       "\"time\":1434357493.398,\"interval\":10.000,"
153       "\"dstypes\":[\"derive\"],\"values\":[42.0]},"
154       /* len(dstypes) != len(values) */
155       "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
156       "\"time\":1434357493.398,\"interval\":10.000,"
157       "\"dstypes\":[\"gauge\"],\"values\":[42.0, 23.0]},"
158       /* type mismatch: got boolean, want string */
159       "{\"host\":true,\"plugin\":\"test\",\"type\":\"answer\","
160       "\"time\":1434357493.398,\"interval\":10.000,"
161       "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
162       /* type mismatch: got boolean, want number */
163       "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
164       "\"time\":true,\"interval\":10.000,"
165       "\"dstypes\":[\"gauge\"],\"values\":[42.0]},"
166       /* type mismatch: got string/number, want array/array */
167       "{\"host\":\"example.com\",\"plugin\":\"test\",\"type\":\"answer\","
168       "\"time\":1434357493.398,\"interval\":10.000,"
169       "\"dstypes\":\"gauge\",\"values\":42.0}"
170       "]";
171
172   value_list_t **vls = NULL;
173   size_t vls_num = 0;
174
175   CHECK_ZERO(parse_json(json, &vls, &vls_num));
176   CHECK_ZERO(vls_num);
177
178   return (0);
179 } /* }}} failures */
180
181 int main(int argc, char **argv) /* {{{ */
182 {
183   RUN_TEST(single_value);
184   RUN_TEST(multi_value);
185   RUN_TEST(failures);
186
187   END_TEST;
188 } /* }}} int main */
189
190 /* vim: set sw=2 sts=2 et fdm=marker : */