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
17CTEST_DATA(test)
18{
19 unsigned char* buffer;
20};
21
22CTEST_SETUP(test)
23{
24 CTEST_LOG("%s()", __func__);
25
26 data->buffer = (unsigned char*)malloc(1024);
27}
28
29CTEST_TEARDOWN(test)
30{
31 CTEST_LOG("%s()", __func__);
32
33 if (data->buffer)
34 {
35 free(data->buffer);
36 }
37}
38
39CTEST2(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
114CTEST2(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
191CTEST2(test, error_callbacks)
192{
193 vws.error(VE_SUCCESS, "No error");
194}
195
196CTEST2(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
215CTEST2(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
237CTEST2(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
259CTEST2(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
277CTEST(test, map)
278{
279 ASSERT_EQUAL(1, 1);
280 ASSERT_STR("test", "test");
281}
282
283CTEST(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
293CTEST(test, error)
294{
295 printf("\n");
296
297 vws.tracelevel = true;
298 vws.error(VE_RT, "Handshake invalid");
299
300 vws_cleanup();
301}
302
303int 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