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