1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020 Intel Corporation
3 */
4
5 #include <string.h>
6
7 #include "telemetry_json.h"
8
9 #include "test.h"
10
11 static int
test_basic_array(void)12 test_basic_array(void)
13 {
14 const char *expected = "[\"meaning of life\",42]";
15 char buf[1024];
16 int used = 0;
17
18 printf("%s: ", __func__);
19 used = rte_tel_json_empty_array(buf, sizeof(buf), used);
20 if (used != 2 || strcmp(buf, "[]"))
21 return -1;
22
23 used = rte_tel_json_add_array_string(buf, sizeof(buf), used,
24 "meaning of life");
25 used = rte_tel_json_add_array_int(buf, sizeof(buf), used, 42);
26
27 printf("buf = '%s', expected = '%s'\n", buf, expected);
28 if (used != (int)strlen(expected))
29 return -1;
30 return strncmp(expected, buf, sizeof(buf));
31 }
32
33 static int
test_basic_obj(void)34 test_basic_obj(void)
35 {
36 const char *expected = "{\"weddings\":4,\"funerals\":1}";
37 char buf[1024];
38 int used = 0;
39
40 used = rte_tel_json_add_obj_uint(buf, sizeof(buf), used,
41 "weddings", 4);
42 used = rte_tel_json_add_obj_uint(buf, sizeof(buf), used,
43 "funerals", 1);
44
45 printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
46 if (used != (int)strlen(expected))
47 return -1;
48 return strncmp(expected, buf, sizeof(buf));
49 }
50
51 static int
test_overflow_array(void)52 test_overflow_array(void)
53 {
54 static const char * const strs[] = {"Arsenal", "Chelsea", "Liverpool",
55 "Spurs"};
56 const char *expected = "[\"Arsenal\",\"Chelsea\"]";
57 char buf[25];
58 int i, used = 0;
59
60 for (i = 0; i < (int)RTE_DIM(strs); i++)
61 used = rte_tel_json_add_array_string(buf, sizeof(buf), used,
62 strs[i]);
63
64 printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
65 if (buf[used - 1] != ']')
66 return -1;
67 if (used != (int)strlen(expected))
68 return -1;
69 return strncmp(expected, buf, sizeof(buf));
70 }
71
72 static int
test_overflow_obj(void)73 test_overflow_obj(void)
74 {
75 static const char * const names[] = {"Italy", "Wales", "Scotland",
76 "Ireland", "England", "France"};
77 const int vals[RTE_DIM(names)] = {20, 61, 10, 40, 55, 35};
78 const char *expected = "{\"Italy\":20,\"Wales\":61}";
79 char buf[25];
80 int i, used = 0;
81
82 for (i = 0; i < (int)RTE_DIM(names); i++)
83 used = rte_tel_json_add_obj_uint(buf, sizeof(buf), used, names[i], vals[i]);
84
85 printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
86 if (buf[used - 1] != '}')
87 return -1;
88 if (used != (int)strlen(expected))
89 return -1;
90 return strncmp(expected, buf, sizeof(buf));
91 }
92
93 static int
test_large_array_element(void)94 test_large_array_element(void)
95 {
96 static const char str[] = "A really long string to overflow buffer";
97 /* buffer should be unmodified so initial value and expected are same */
98 const char *expected = "ABC";
99 char buf[sizeof(str) - 5] = "ABC";
100 int used = 0;
101
102 used = rte_tel_json_add_array_string(buf, sizeof(buf), used, str);
103 printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
104 if (used != 0)
105 return -1;
106
107 return strncmp(expected, buf, sizeof(buf));
108 }
109
110 static int
test_large_obj_element(void)111 test_large_obj_element(void)
112 {
113 static const char str[] = "A really long string to overflow buffer";
114 /* buffer should be unmodified so initial value and expected are same */
115 const char *expected = "XYZ";
116 char buf[sizeof(str) - 5] = "XYZ";
117 int used = 0;
118
119 used = rte_tel_json_add_obj_uint(buf, sizeof(buf), used, str, 0);
120 printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
121 if (used != 0)
122 return -1;
123
124 return strncmp(expected, buf, sizeof(buf));
125 }
126
127 static int
test_string_char_escaping(void)128 test_string_char_escaping(void)
129 {
130 static const char str[] = "A string across\ntwo lines and \"with quotes\"!";
131 const char *expected = "\"A string across\\ntwo lines and \\\"with quotes\\\"!\"";
132 char buf[sizeof(str) + 10] = "";
133 int used = 0;
134
135 used = rte_tel_json_str(buf, sizeof(buf), used, str);
136 printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
137 if (used != (int)strlen(expected))
138 return -1;
139
140 return strncmp(expected, buf, sizeof(buf));
141 }
142
143 static int
test_array_char_escaping(void)144 test_array_char_escaping(void)
145 {
146 /* "meaning of life", with tab between first two words, '\n' at end,
147 * and "life" in quotes, followed by "all the fish" in quotes
148 */
149 const char *expected = "[\"meaning\\tof \\\"life\\\"\\n\",\"\\\"all the fish\\\"\"]";
150 char buf[1024];
151 int used = 0;
152
153 used = rte_tel_json_empty_array(buf, sizeof(buf), used);
154 if (used != 2 || strcmp(buf, "[]"))
155 return -1;
156
157 used = rte_tel_json_add_array_string(buf, sizeof(buf), used, "meaning\tof \"life\"\n");
158 used = rte_tel_json_add_array_string(buf, sizeof(buf), used, "\"all the fish\"");
159
160 printf("buf = '%s', expected = '%s'\n", buf, expected);
161 if (used != (int)strlen(expected))
162 return -1;
163 return strncmp(expected, buf, sizeof(buf));
164 }
165
166 static int
test_obj_char_escaping(void)167 test_obj_char_escaping(void)
168 {
169 const char *expected = "{\"good\":\"Clint Eastwood\\n\","
170 "\"bad\":\"Lee\\tVan\\tCleef\","
171 "\"ugly\":\"\\rEli Wallach\"}";
172 char buf[1024];
173 int used = 0;
174
175 used = rte_tel_json_empty_obj(buf, sizeof(buf), used);
176 if (used != 2 || strcmp(buf, "{}"))
177 return -1;
178
179 used = rte_tel_json_add_obj_str(buf, sizeof(buf), used, "good", "Clint Eastwood\n");
180 used = rte_tel_json_add_obj_str(buf, sizeof(buf), used, "bad", "Lee\tVan\tCleef");
181 used = rte_tel_json_add_obj_str(buf, sizeof(buf), used, "ugly", "\rEli Wallach");
182
183 printf("buf = '%s', expected = '%s'\n", buf, expected);
184 if (used != (int)strlen(expected))
185 return -1;
186 return strncmp(expected, buf, sizeof(buf));
187 }
188
189 typedef int (*test_fn)(void);
190
191 static int
test_telemetry_json(void)192 test_telemetry_json(void)
193 {
194 unsigned int i;
195 test_fn fns[] = {
196 test_basic_array,
197 test_basic_obj,
198 test_overflow_array,
199 test_overflow_obj,
200 test_large_array_element,
201 test_large_obj_element,
202 test_string_char_escaping,
203 test_array_char_escaping,
204 test_obj_char_escaping
205 };
206 for (i = 0; i < RTE_DIM(fns); i++)
207 if (fns[i]() == 0)
208 printf("OK\n");
209 else {
210 printf("ERROR\n");
211 return -1;
212 }
213 return 0;
214 }
215
216 REGISTER_FAST_TEST(telemetry_json_autotest, true, true, test_telemetry_json);
217