1 /*
2 * collectd - src/capabilities_test.c
3 *
4 * Copyright(c) 2019 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 * Kamil Wiatrowski <kamilx.wiatrowski@intel.com>
26 */
27
28 #include "capabilities.c" /* sic */
29 #include "testing.h"
30
31 #define RESULT_STRING_JSON \
32 "{\"TEST_TYPE\":[{\"Name\":{\"MapName1\":\"MapValue1\",\"ListName1\":[" \
33 "\"ListValue1\",\"ListValue2\"],\"MapName2\":\"MapValue2\"}},{\"Name\":{" \
34 "\"MapName1\":\"MapValue1\"}}]}"
35
36 static int idx = 0;
37 static char *test_dmi[][2] = {{NULL, NULL},
38 {"Name", NULL},
39 {"MapName1", "MapValue1"},
40 {"ListName1", NULL},
41 {NULL, "ListValue1"},
42 {NULL, "ListValue2"},
43 {"MapName2", "MapValue2"},
44 {NULL, NULL},
45 {"Name", NULL},
46 {"MapName1", "MapValue1"},
47 {NULL, NULL}};
48 static entry_type entry[] = {
49 DMI_ENTRY_NONE, DMI_ENTRY_NAME, DMI_ENTRY_MAP,
50 DMI_ENTRY_LIST_NAME, DMI_ENTRY_LIST_VALUE, DMI_ENTRY_LIST_VALUE,
51 DMI_ENTRY_MAP, DMI_ENTRY_NONE, DMI_ENTRY_NAME,
52 DMI_ENTRY_MAP, DMI_ENTRY_END};
53 static size_t len = STATIC_ARRAY_SIZE(entry);
54
55 static struct MHD_Response *mhd_res = NULL;
56
57 /* mock functions */
dmi_reader_init(dmi_reader_t * reader,const dmi_type type)58 int dmi_reader_init(dmi_reader_t *reader, const dmi_type type) {
59 reader->current_type = DMI_ENTRY_NONE;
60 return DMI_OK;
61 }
62
dmi_reader_clean(dmi_reader_t * reader)63 void dmi_reader_clean(dmi_reader_t *reader) {}
64
dmi_read_next(dmi_reader_t * reader)65 int dmi_read_next(dmi_reader_t *reader) {
66 if (idx >= len)
67 return DMI_ERROR;
68 reader->current_type = entry[idx];
69 reader->name = test_dmi[idx][0];
70 reader->value = test_dmi[idx][1];
71 idx++;
72 return DMI_OK;
73 }
74
MHD_start_daemon(unsigned int flags,unsigned short port,MHD_AcceptPolicyCallback apc,void * apc_cls,MHD_AccessHandlerCallback dh,void * dh_cls,...)75 struct MHD_Daemon *MHD_start_daemon(unsigned int flags, unsigned short port,
76 MHD_AcceptPolicyCallback apc, void *apc_cls,
77 MHD_AccessHandlerCallback dh, void *dh_cls,
78 ...) {
79 return NULL;
80 }
81
MHD_stop_daemon(struct MHD_Daemon * daemon)82 void MHD_stop_daemon(struct MHD_Daemon *daemon) {}
83
84 struct MHD_Response *
MHD_create_response_from_buffer(size_t size,void * data,enum MHD_ResponseMemoryMode mode)85 MHD_create_response_from_buffer(size_t size, void *data,
86 enum MHD_ResponseMemoryMode mode) {
87 return mhd_res;
88 }
89
MHD_create_response_from_data(size_t size,void * data,int must_free,int must_copy)90 struct MHD_Response *MHD_create_response_from_data(size_t size, void *data,
91 int must_free,
92 int must_copy) {
93 return mhd_res;
94 }
95
MHD_add_response_header(struct MHD_Response * response,const char * header,const char * content)96 MHD_RESULT MHD_add_response_header(struct MHD_Response *response,
97 const char *header, const char *content) {
98 return 0;
99 }
100
MHD_queue_response(struct MHD_Connection * connection,unsigned int status_code,struct MHD_Response * response)101 MHD_RESULT MHD_queue_response(struct MHD_Connection *connection,
102 unsigned int status_code,
103 struct MHD_Response *response) {
104 return MHD_HTTP_OK;
105 }
106
MHD_destroy_response(struct MHD_Response * response)107 void MHD_destroy_response(struct MHD_Response *response) {}
108 /* end mock functions */
109
DEF_TEST(plugin_config)110 DEF_TEST(plugin_config) {
111 oconfig_item_t test_cfg_parent = {"capabilities", NULL, 0, NULL, NULL, 0};
112 char value_buff[256] = "1234";
113 char key_buff[256] = "port";
114 oconfig_value_t test_cfg_value = {{value_buff}, OCONFIG_TYPE_STRING};
115 oconfig_item_t test_cfg = {
116 key_buff, &test_cfg_value, 1, &test_cfg_parent, NULL, 0};
117
118 test_cfg_parent.children = &test_cfg;
119 test_cfg_parent.children_num = 1;
120
121 int ret = cap_config(&test_cfg_parent);
122 EXPECT_EQ_INT(0, ret);
123 EXPECT_EQ_INT(1234, httpd_port);
124 OK(NULL == httpd_host);
125
126 strncpy(value_buff, "1", STATIC_ARRAY_SIZE(value_buff));
127 ret = cap_config(&test_cfg_parent);
128 EXPECT_EQ_INT(0, ret);
129 EXPECT_EQ_INT(1, httpd_port);
130
131 strncpy(value_buff, "65535", STATIC_ARRAY_SIZE(value_buff));
132 ret = cap_config(&test_cfg_parent);
133 EXPECT_EQ_INT(0, ret);
134 EXPECT_EQ_INT(65535, httpd_port);
135
136 #if defined(MHD_VERSION) && MHD_VERSION >= 0x00090000
137 strncpy(value_buff, "127.0.0.1", STATIC_ARRAY_SIZE(value_buff));
138 strncpy(key_buff, "host", STATIC_ARRAY_SIZE(key_buff));
139
140 ret = cap_config(&test_cfg_parent);
141 EXPECT_EQ_INT(0, ret);
142 EXPECT_EQ_STR("127.0.0.1", httpd_host);
143 EXPECT_EQ_INT(65535, httpd_port);
144
145 free(httpd_host);
146 strncpy(key_buff, "port", STATIC_ARRAY_SIZE(key_buff));
147 #endif
148
149 double port_value = 65535;
150 oconfig_value_t test_cfg_value2 = {{.number = port_value},
151 OCONFIG_TYPE_NUMBER};
152 test_cfg.values = &test_cfg_value2;
153 ret = cap_config(&test_cfg_parent);
154 EXPECT_EQ_INT(0, ret);
155 EXPECT_EQ_INT(65535, httpd_port);
156
157 return 0;
158 }
159
DEF_TEST(plugin_config_fail)160 DEF_TEST(plugin_config_fail) {
161 oconfig_item_t test_cfg_parent = {"capabilities", NULL, 0, NULL, NULL, 0};
162 char value_buff[256] = "1";
163 char key_buff[256] = "aport";
164 oconfig_value_t test_cfg_value = {{value_buff}, OCONFIG_TYPE_STRING};
165 oconfig_item_t test_cfg = {
166 key_buff, &test_cfg_value, 1, &test_cfg_parent, NULL, 0};
167
168 test_cfg_parent.children = &test_cfg;
169 test_cfg_parent.children_num = 1;
170
171 unsigned short default_port = httpd_port;
172 int ret = cap_config(&test_cfg_parent);
173 EXPECT_EQ_INT(-1, ret);
174 EXPECT_EQ_INT(default_port, httpd_port);
175 OK(NULL == httpd_host);
176
177 /* Correct port range is 1 - 65535 */
178 strncpy(key_buff, "port", STATIC_ARRAY_SIZE(key_buff));
179 strncpy(value_buff, "-1", STATIC_ARRAY_SIZE(value_buff));
180 ret = cap_config(&test_cfg_parent);
181 EXPECT_EQ_INT(-1, ret);
182 EXPECT_EQ_INT(default_port, httpd_port);
183 OK(NULL == httpd_host);
184
185 strncpy(value_buff, "65536", STATIC_ARRAY_SIZE(value_buff));
186 ret = cap_config(&test_cfg_parent);
187 EXPECT_EQ_INT(-1, ret);
188 EXPECT_EQ_INT(default_port, httpd_port);
189 OK(NULL == httpd_host);
190
191 #if defined(MHD_VERSION) && MHD_VERSION >= 0x00090000
192 strncpy(value_buff, "127.0.0.1", STATIC_ARRAY_SIZE(value_buff));
193 strncpy(key_buff, "host", STATIC_ARRAY_SIZE(key_buff));
194 test_cfg_value.type = OCONFIG_TYPE_NUMBER;
195 ret = cap_config(&test_cfg_parent);
196 EXPECT_EQ_INT(-1, ret);
197 EXPECT_EQ_INT(default_port, httpd_port);
198 OK(NULL == httpd_host);
199
200 strncpy(key_buff, "port", STATIC_ARRAY_SIZE(key_buff));
201 #endif
202
203 double port_value = 65536;
204 oconfig_value_t test_cfg_value2 = {{.number = port_value},
205 OCONFIG_TYPE_NUMBER};
206 test_cfg.values = &test_cfg_value2;
207 ret = cap_config(&test_cfg_parent);
208 EXPECT_EQ_INT(-1, ret);
209 EXPECT_EQ_INT(default_port, httpd_port);
210 OK(NULL == httpd_host);
211
212 return 0;
213 }
214
DEF_TEST(http_handler)215 DEF_TEST(http_handler) {
216 void *state = NULL;
217 g_cap_json = "TEST";
218 int ret = cap_http_handler(NULL, NULL, NULL, MHD_HTTP_METHOD_PUT, NULL, NULL,
219 NULL, &state);
220 EXPECT_EQ_INT(MHD_NO, ret);
221 OK(NULL == state);
222
223 ret = cap_http_handler(NULL, NULL, NULL, MHD_HTTP_METHOD_GET, NULL, NULL,
224 NULL, &state);
225 EXPECT_EQ_INT(MHD_YES, ret);
226 CHECK_NOT_NULL(state);
227
228 ret = cap_http_handler(NULL, NULL, NULL, MHD_HTTP_METHOD_GET, NULL, NULL,
229 NULL, &state);
230 EXPECT_EQ_INT(MHD_NO, ret);
231 CHECK_NOT_NULL(state);
232
233 /* mock not NULL pointer */
234 mhd_res = (struct MHD_Response *)&(int){0};
235 ret = cap_http_handler(NULL, NULL, NULL, MHD_HTTP_METHOD_GET, NULL, NULL,
236 NULL, &state);
237 EXPECT_EQ_INT(MHD_HTTP_OK, ret);
238 CHECK_NOT_NULL(state);
239
240 g_cap_json = NULL;
241 mhd_res = NULL;
242
243 return 0;
244 }
245
DEF_TEST(get_dmi_variables)246 DEF_TEST(get_dmi_variables) {
247 json_t *root = json_object();
248 CHECK_NOT_NULL(root);
249
250 int ret = cap_get_dmi_variables(root, 0, "TEST_TYPE");
251 EXPECT_EQ_INT(0, ret);
252
253 char *test_str = json_dumps(root, JSON_COMPACT | JSON_PRESERVE_ORDER);
254 CHECK_NOT_NULL(test_str);
255 json_decref(root);
256 EXPECT_EQ_STR(RESULT_STRING_JSON, test_str);
257
258 free(test_str);
259
260 root = json_object();
261 CHECK_NOT_NULL(root);
262 ret = cap_get_dmi_variables(root, 1, "TEST_TYPE2");
263 EXPECT_EQ_INT(-1, ret);
264
265 test_str = json_dumps(root, JSON_COMPACT | JSON_PRESERVE_ORDER);
266 CHECK_NOT_NULL(test_str);
267 json_decref(root);
268 EXPECT_EQ_STR("{\"TEST_TYPE2\":[]}", test_str);
269
270 free(test_str);
271
272 return 0;
273 }
274
main(void)275 int main(void) {
276 RUN_TEST(plugin_config_fail);
277 RUN_TEST(plugin_config);
278
279 RUN_TEST(http_handler);
280 RUN_TEST(get_dmi_variables);
281
282 END_TEST;
283 }
284