1 | #include "common.h" |
2 | |
3 | #define CTEST_MAIN |
4 | #include "ctest.h" |
5 | |
6 | #include "vws.h" |
7 | #include "url.h" |
8 | #include "util/sc_map.h" |
9 | #include "util/sc_queue.h" |
10 | |
11 | #pragma GCC diagnostic push |
12 | #pragma GCC diagnostic ignored "-Wunused-parameter" |
13 | #pragma clang diagnostic push |
14 | #pragma clang diagnostic ignored "-Wunused-parameter" |
15 | |
16 | |
17 | CTEST_DATA(test) |
18 | { |
19 | unsigned char* buffer; |
20 | }; |
21 | |
22 | CTEST_SETUP(test) |
23 | { |
24 | CTEST_LOG("%s()" , __func__); |
25 | |
26 | data->buffer = (unsigned char*)malloc(1024); |
27 | } |
28 | |
29 | CTEST_TEARDOWN(test) |
30 | { |
31 | CTEST_LOG("%s()" , __func__); |
32 | |
33 | if (data->buffer) |
34 | { |
35 | free(data->buffer); |
36 | } |
37 | } |
38 | |
39 | CTEST2(test, vws_kvs) |
40 | { |
41 | // Initialize the dynamic array |
42 | vws_kvs* map = vws_kvs_new(20); |
43 | |
44 | // Insert items |
45 | int val1 = 100; |
46 | double val2 = 200.5; |
47 | char val3[] = "value" ; |
48 | |
49 | vws_kvs_set(map, "key1" , &val1, sizeof(val1)); |
50 | vws_kvs_set(map, "key2" , &val2, sizeof(val2)); |
51 | vws_kvs_set(map, "key3" , val3, sizeof(val3)); |
52 | |
53 | ASSERT_TRUE(vws_kvs_size(map) == 3); |
54 | |
55 | const char* keys[] = { "key1" , "key2" , "key3" }; |
56 | |
57 | for (int i = 0; i < 3; i++) |
58 | { |
59 | vws_value* val = vws_kvs_get(map, keys[i]); |
60 | |
61 | ASSERT_TRUE(val != NULL); |
62 | |
63 | if (strcmp(keys[i], "key1" ) == 0) |
64 | { |
65 | ASSERT_TRUE(*(int*)(val->data) == val1); |
66 | } |
67 | |
68 | if (strcmp(keys[i], "key2" ) == 0) |
69 | { |
70 | ASSERT_TRUE(*(double*)(val->data) == val2); |
71 | } |
72 | |
73 | if (strcmp(keys[i], "key3" ) == 0) |
74 | { |
75 | ASSERT_TRUE(strncmp(val->data, val3, val->size) == 0); |
76 | } |
77 | } |
78 | |
79 | //> Remove |
80 | |
81 | vws_kvs_remove(map, "key1" ); |
82 | vws_kvs_remove(map, "key2" ); |
83 | vws_kvs_remove(map, "key3" ); |
84 | |
85 | ASSERT_TRUE(vws_kvs_size(map) == 0); |
86 | |
87 | // Insert items |
88 | |
89 | const char* values[] = { "value1" , "value2" , "value3" }; |
90 | |
91 | vws_kvs_set_cstring(map, "key1" , values[0]); |
92 | vws_kvs_set_cstring(map, "key2" , values[1]); |
93 | vws_kvs_set_cstring(map, "key3" , values[2]); |
94 | |
95 | // Find and print values |
96 | for (int i = 0; i < 3; i++) |
97 | { |
98 | const char* val = vws_kvs_get_cstring(map, keys[i]); |
99 | ASSERT_TRUE(val != NULL); |
100 | ASSERT_TRUE(strcmp(val, values[i]) == 0); |
101 | } |
102 | |
103 | vws_kvs_remove(map, "key1" ); |
104 | vws_kvs_remove(map, "key2" ); |
105 | vws_kvs_remove(map, "key3" ); |
106 | |
107 | vws_kvs_clear(map); |
108 | ASSERT_TRUE(vws_kvs_size(map) == 0); |
109 | |
110 | // Free the dynamic array |
111 | vws_kvs_free(map); |
112 | } |
113 | |
114 | CTEST2(test, map_bench) |
115 | { |
116 | // Initialize the dynamic array |
117 | vws_kvs* map = vws_kvs_new(20); |
118 | |
119 | // Initialize the hashtable |
120 | struct sc_map_str ht; |
121 | sc_map_init_str(&ht, 0, 0); |
122 | |
123 | // Add key/value pairs |
124 | |
125 | size_t searches = 1000000; |
126 | size_t size = 3; |
127 | char kbuf[256]; |
128 | char vbuf[256]; |
129 | |
130 | const char** keys = malloc(sizeof(char*) * size); |
131 | const char** values = malloc(sizeof(char*) * size); |
132 | |
133 | // Find and print values |
134 | for (size_t i = 0; i < size; i++) |
135 | { |
136 | sprintf(&kbuf[0],"key%i" , i); |
137 | sprintf(&vbuf[0],"value%i" , i); |
138 | |
139 | keys[i] = strdup(&kbuf[i]); |
140 | values[i] = strdup(&vbuf[i]); |
141 | |
142 | vws_kvs_set_cstring(map, keys[i], values[i]); |
143 | vws_map_set(&ht, keys[i], values[i]); |
144 | } |
145 | |
146 | // Measure map speed |
147 | |
148 | clock_t start_time = clock(); |
149 | |
150 | for (size_t i = 0; i < searches; i++) |
151 | { |
152 | vws_kvs_get_cstring(map, keys[i % size]); |
153 | } |
154 | |
155 | clock_t end_time = clock(); |
156 | double kvs_duration = (double)(end_time - start_time) / CLOCKS_PER_SEC; |
157 | |
158 | // Measure hashtable speed |
159 | |
160 | start_time = clock(); |
161 | |
162 | for (size_t i = 0; i < searches; i++) |
163 | { |
164 | vws_map_get(&ht, keys[i % size]); |
165 | } |
166 | |
167 | end_time = clock(); |
168 | double map_duration = (double)(end_time - start_time) / CLOCKS_PER_SEC; |
169 | |
170 | printf("KVS: %f seconds %G ref/sec\n" , kvs_duration, kvs_duration/searches); |
171 | printf("Hashtable: %f seconds %G ref/sec\n" , map_duration, map_duration/searches); |
172 | printf("Factor: %f seconds\n" , map_duration/kvs_duration); |
173 | |
174 | //> Cleanup |
175 | |
176 | // Find and print values |
177 | for (size_t i = 0; i < size; i++) |
178 | { |
179 | free(keys[i]); |
180 | free(values[i]); |
181 | } |
182 | |
183 | free(keys); |
184 | free(values); |
185 | |
186 | vws_kvs_free(map); |
187 | vws_map_clear(&ht); |
188 | sc_map_term_str(&ht); |
189 | } |
190 | |
191 | CTEST2(test, error_callbacks) |
192 | { |
193 | vws.error(VE_SUCCESS, "No error" ); |
194 | } |
195 | |
196 | CTEST2(test, test_url) |
197 | { |
198 | cstr value = "http://user:pass@host.com:8080" |
199 | "/path/to/something?query=string#hash" ; |
200 | url_data_t* url = url_parse(value); |
201 | |
202 | vws.trace(VL_INFO, "url protocol: %s" , url->protocol); |
203 | vws.trace(VL_INFO, "url host: %s" , url->host); |
204 | vws.trace(VL_INFO, "url auth: %s" , url->auth); |
205 | vws.trace(VL_INFO, "url hostname: %s" , url->hostname); |
206 | vws.trace(VL_INFO, "url pathname: %s" , url->pathname); |
207 | vws.trace(VL_INFO, "url search: %s" , url->search); |
208 | vws.trace(VL_INFO, "url path: %s" , url->path); |
209 | vws.trace(VL_INFO, "url query: %s" , url->query); |
210 | vws.trace(VL_INFO, "url port: %s" , url->port); |
211 | |
212 | url_free(url); |
213 | } |
214 | |
215 | CTEST2(test, base64) |
216 | { |
217 | const unsigned char original_data[] = "Hello, World!" ; |
218 | size_t original_length = strlen((const char *)original_data); |
219 | |
220 | // Encoding |
221 | |
222 | char* encoded = vws_base64_encode(original_data, original_length); |
223 | |
224 | // Decoding |
225 | |
226 | unsigned char* decoded; |
227 | size_t output_length = 0; |
228 | decoded = vws_base64_decode(encoded, &output_length); |
229 | |
230 | printf("Base64 Encoded: %s\n" , encoded); |
231 | printf("Base64 Decoded: %s\n" , decoded); |
232 | |
233 | free(encoded); |
234 | free(decoded); |
235 | } |
236 | |
237 | CTEST2(test, buffer) |
238 | { |
239 | vws_buffer* buffer = vws_buffer_new(&buffer); |
240 | |
241 | // Append data to the buffer |
242 | cstr data1 = "Hello, " ; |
243 | vws_buffer_append(buffer, (ucstr)data1, strlen(data1)); |
244 | |
245 | cstr data2 = "world!" ; |
246 | vws_buffer_append(buffer, (ucstr)data2, strlen(data2)); |
247 | |
248 | // Drain the first 7 bytes from the buffer |
249 | vws_buffer_drain(buffer, 7); |
250 | |
251 | // Print the remaining data in the buffer |
252 | printf("%s\n" , buffer->data); |
253 | ASSERT_STR((cstr)buffer->data, "world!" ); |
254 | |
255 | // Free the buffer |
256 | vws_buffer_free(buffer); |
257 | } |
258 | |
259 | CTEST2(test, queue) |
260 | { |
261 | const void* elem; |
262 | struct sc_queue_ptr queue; |
263 | |
264 | sc_queue_init(&queue); |
265 | sc_queue_add_last(&queue, "one" ); |
266 | sc_queue_add_last(&queue, "one" ); |
267 | sc_queue_add_last(&queue, "one" ); |
268 | |
269 | sc_queue_foreach (&queue, elem) |
270 | { |
271 | ASSERT_STR(elem, "one" ); |
272 | } |
273 | |
274 | sc_queue_term(&queue); |
275 | } |
276 | |
277 | CTEST(test, map) |
278 | { |
279 | ASSERT_EQUAL(1, 1); |
280 | ASSERT_STR("test" , "test" ); |
281 | } |
282 | |
283 | CTEST(test, trace) |
284 | { |
285 | printf("\n" ); |
286 | |
287 | vws.trace(VL_DEBUG, "vws.trace(%s)" , "DEBUG" ); |
288 | vws.trace(VL_INFO, "vws.trace(%s)" , "INFO" ); |
289 | vws.trace(VL_WARN, "vws.trace(%s)" , "WARNING" ); |
290 | vws.trace(VL_ERROR, "vws.trace(%s)" , "ERROR" ); |
291 | } |
292 | |
293 | CTEST(test, error) |
294 | { |
295 | printf("\n" ); |
296 | |
297 | vws.tracelevel = true; |
298 | vws.error(VE_RT, "Handshake invalid" ); |
299 | |
300 | vws_cleanup(); |
301 | } |
302 | |
303 | int main(int argc, const char* argv[]) |
304 | { |
305 | return ctest_main(argc, argv); |
306 | } |
307 | |
308 | #pragma GCC diagnostic pop |
309 | #pragma clang diagnostic pop |
310 | |