1 /* 2 * QDict unit-tests. 3 * 4 * Copyright (C) 2009 Red Hat Inc. 5 * 6 * Authors: 7 * Luiz Capitulino <lcapitulino@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 10 * See the COPYING.LIB file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "qapi/qmp/qdict.h" 15 #include "qapi/qmp/qnum.h" 16 #include "qapi/qmp/qstring.h" 17 18 /* 19 * Public Interface test-cases 20 * 21 * (with some violations to access 'private' data) 22 */ 23 24 static void qdict_new_test(void) 25 { 26 QDict *qdict; 27 28 qdict = qdict_new(); 29 g_assert(qdict != NULL); 30 g_assert(qdict_size(qdict) == 0); 31 g_assert(qdict->base.refcnt == 1); 32 g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT); 33 34 qobject_unref(qdict); 35 } 36 37 static void qdict_put_obj_test(void) 38 { 39 QNum *qn; 40 QDict *qdict; 41 QDictEntry *ent; 42 const int num = 42; 43 44 qdict = qdict_new(); 45 46 // key "" will have tdb hash 12345 47 qdict_put_int(qdict, "", num); 48 49 g_assert(qdict_size(qdict) == 1); 50 ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]); 51 qn = qobject_to(QNum, ent->value); 52 g_assert_cmpint(qnum_get_int(qn), ==, num); 53 54 qobject_unref(qdict); 55 } 56 57 static void qdict_destroy_simple_test(void) 58 { 59 QDict *qdict; 60 61 qdict = qdict_new(); 62 qdict_put_int(qdict, "num", 0); 63 qdict_put_str(qdict, "str", "foo"); 64 65 qobject_unref(qdict); 66 } 67 68 static void qdict_get_test(void) 69 { 70 QNum *qn; 71 QObject *obj; 72 const int value = -42; 73 const char *key = "test"; 74 QDict *tests_dict = qdict_new(); 75 76 qdict_put_int(tests_dict, key, value); 77 78 obj = qdict_get(tests_dict, key); 79 g_assert(obj != NULL); 80 81 qn = qobject_to(QNum, obj); 82 g_assert_cmpint(qnum_get_int(qn), ==, value); 83 84 qobject_unref(tests_dict); 85 } 86 87 static void qdict_get_int_test(void) 88 { 89 int ret; 90 const int value = 100; 91 const char *key = "int"; 92 QDict *tests_dict = qdict_new(); 93 94 qdict_put_int(tests_dict, key, value); 95 96 ret = qdict_get_int(tests_dict, key); 97 g_assert(ret == value); 98 99 qobject_unref(tests_dict); 100 } 101 102 static void qdict_get_try_int_test(void) 103 { 104 int ret; 105 const int value = 100; 106 const char *key = "int"; 107 QDict *tests_dict = qdict_new(); 108 109 qdict_put_int(tests_dict, key, value); 110 qdict_put_str(tests_dict, "string", "test"); 111 112 ret = qdict_get_try_int(tests_dict, key, 0); 113 g_assert(ret == value); 114 115 ret = qdict_get_try_int(tests_dict, "missing", -42); 116 g_assert_cmpuint(ret, ==, -42); 117 118 ret = qdict_get_try_int(tests_dict, "string", -42); 119 g_assert_cmpuint(ret, ==, -42); 120 121 qobject_unref(tests_dict); 122 } 123 124 static void qdict_get_str_test(void) 125 { 126 const char *p; 127 const char *key = "key"; 128 const char *str = "string"; 129 QDict *tests_dict = qdict_new(); 130 131 qdict_put_str(tests_dict, key, str); 132 133 p = qdict_get_str(tests_dict, key); 134 g_assert(p != NULL); 135 g_assert(strcmp(p, str) == 0); 136 137 qobject_unref(tests_dict); 138 } 139 140 static void qdict_get_try_str_test(void) 141 { 142 const char *p; 143 const char *key = "key"; 144 const char *str = "string"; 145 QDict *tests_dict = qdict_new(); 146 147 qdict_put_str(tests_dict, key, str); 148 149 p = qdict_get_try_str(tests_dict, key); 150 g_assert(p != NULL); 151 g_assert(strcmp(p, str) == 0); 152 153 qobject_unref(tests_dict); 154 } 155 156 static void qdict_haskey_not_test(void) 157 { 158 QDict *tests_dict = qdict_new(); 159 g_assert(qdict_haskey(tests_dict, "test") == 0); 160 161 qobject_unref(tests_dict); 162 } 163 164 static void qdict_haskey_test(void) 165 { 166 const char *key = "test"; 167 QDict *tests_dict = qdict_new(); 168 169 qdict_put_int(tests_dict, key, 0); 170 g_assert(qdict_haskey(tests_dict, key) == 1); 171 172 qobject_unref(tests_dict); 173 } 174 175 static void qdict_del_test(void) 176 { 177 const char *key = "key test"; 178 QDict *tests_dict = qdict_new(); 179 180 qdict_put_str(tests_dict, key, "foo"); 181 g_assert(qdict_size(tests_dict) == 1); 182 183 qdict_del(tests_dict, key); 184 185 g_assert(qdict_size(tests_dict) == 0); 186 g_assert(qdict_haskey(tests_dict, key) == 0); 187 188 qobject_unref(tests_dict); 189 } 190 191 static void qobject_to_qdict_test(void) 192 { 193 QDict *tests_dict = qdict_new(); 194 g_assert(qobject_to(QDict, QOBJECT(tests_dict)) == tests_dict); 195 196 qobject_unref(tests_dict); 197 } 198 199 static void qdict_iterapi_test(void) 200 { 201 int count; 202 const QDictEntry *ent; 203 QDict *tests_dict = qdict_new(); 204 205 g_assert(qdict_first(tests_dict) == NULL); 206 207 qdict_put_int(tests_dict, "key1", 1); 208 qdict_put_int(tests_dict, "key2", 2); 209 qdict_put_int(tests_dict, "key3", 3); 210 211 count = 0; 212 for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){ 213 g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1); 214 count++; 215 } 216 217 g_assert(count == qdict_size(tests_dict)); 218 219 /* Do it again to test restarting */ 220 count = 0; 221 for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){ 222 g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1); 223 count++; 224 } 225 226 g_assert(count == qdict_size(tests_dict)); 227 228 qobject_unref(tests_dict); 229 } 230 231 /* 232 * Errors test-cases 233 */ 234 235 static void qdict_put_exists_test(void) 236 { 237 int value; 238 const char *key = "exists"; 239 QDict *tests_dict = qdict_new(); 240 241 qdict_put_int(tests_dict, key, 1); 242 qdict_put_int(tests_dict, key, 2); 243 244 value = qdict_get_int(tests_dict, key); 245 g_assert(value == 2); 246 247 g_assert(qdict_size(tests_dict) == 1); 248 249 qobject_unref(tests_dict); 250 } 251 252 static void qdict_get_not_exists_test(void) 253 { 254 QDict *tests_dict = qdict_new(); 255 g_assert(qdict_get(tests_dict, "foo") == NULL); 256 257 qobject_unref(tests_dict); 258 } 259 260 /* 261 * Stress test-case 262 * 263 * This is a lot big for a unit-test, but there is no other place 264 * to have it. 265 */ 266 267 static void remove_dots(char *string) 268 { 269 char *p = strchr(string, ':'); 270 if (p) 271 *p = '\0'; 272 } 273 274 static QString *read_line(FILE *file, char *key) 275 { 276 char value[128]; 277 278 if (fscanf(file, "%127s%127s", key, value) == EOF) { 279 return NULL; 280 } 281 remove_dots(key); 282 return qstring_from_str(value); 283 } 284 285 #define reset_file(file) fseek(file, 0L, SEEK_SET) 286 287 static void qdict_stress_test(void) 288 { 289 size_t lines; 290 char key[128]; 291 FILE *test_file; 292 QDict *qdict; 293 QString *value; 294 const char *test_file_path = "tests/data/qobject/qdict.txt"; 295 296 test_file = fopen(test_file_path, "r"); 297 g_assert(test_file != NULL); 298 299 // Create the dict 300 qdict = qdict_new(); 301 g_assert(qdict != NULL); 302 303 // Add everything from the test file 304 for (lines = 0;; lines++) { 305 value = read_line(test_file, key); 306 if (!value) 307 break; 308 309 qdict_put(qdict, key, value); 310 } 311 g_assert(qdict_size(qdict) == lines); 312 313 // Check if everything is really in there 314 reset_file(test_file); 315 for (;;) { 316 const char *str1, *str2; 317 318 value = read_line(test_file, key); 319 if (!value) 320 break; 321 322 str1 = qstring_get_str(value); 323 324 str2 = qdict_get_str(qdict, key); 325 g_assert(str2 != NULL); 326 327 g_assert(strcmp(str1, str2) == 0); 328 329 qobject_unref(value); 330 } 331 332 // Delete everything 333 reset_file(test_file); 334 for (;;) { 335 value = read_line(test_file, key); 336 if (!value) 337 break; 338 339 qdict_del(qdict, key); 340 qobject_unref(value); 341 342 g_assert(qdict_haskey(qdict, key) == 0); 343 } 344 fclose(test_file); 345 346 g_assert(qdict_size(qdict) == 0); 347 qobject_unref(qdict); 348 } 349 350 int main(int argc, char **argv) 351 { 352 g_test_init(&argc, &argv, NULL); 353 354 g_test_add_func("/public/new", qdict_new_test); 355 g_test_add_func("/public/put_obj", qdict_put_obj_test); 356 g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test); 357 358 /* Continue, but now with fixtures */ 359 g_test_add_func("/public/get", qdict_get_test); 360 g_test_add_func("/public/get_int", qdict_get_int_test); 361 g_test_add_func("/public/get_try_int", qdict_get_try_int_test); 362 g_test_add_func("/public/get_str", qdict_get_str_test); 363 g_test_add_func("/public/get_try_str", qdict_get_try_str_test); 364 g_test_add_func("/public/haskey_not", qdict_haskey_not_test); 365 g_test_add_func("/public/haskey", qdict_haskey_test); 366 g_test_add_func("/public/del", qdict_del_test); 367 g_test_add_func("/public/to_qdict", qobject_to_qdict_test); 368 g_test_add_func("/public/iterapi", qdict_iterapi_test); 369 370 g_test_add_func("/errors/put_exists", qdict_put_exists_test); 371 g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test); 372 373 /* The Big one */ 374 if (g_test_slow()) { 375 g_test_add_func("/stress/test", qdict_stress_test); 376 } 377 378 return g_test_run(); 379 } 380