qemu/tests/unit/test-string-input-visitor.c
<<
>>
Prefs
   1/*
   2 * String Input Visitor unit-tests.
   3 *
   4 * Copyright (C) 2012 Red Hat Inc.
   5 *
   6 * Authors:
   7 *  Paolo Bonzini <pbonzini@redhat.com> (based on test-qobject-input-visitor)
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10 * See the COPYING file in the top-level directory.
  11 */
  12
  13#include "qemu/osdep.h"
  14
  15#include "qemu-common.h"
  16#include "qapi/error.h"
  17#include "qapi/string-input-visitor.h"
  18#include "test-qapi-visit.h"
  19
  20typedef struct TestInputVisitorData {
  21    Visitor *v;
  22} TestInputVisitorData;
  23
  24static void visitor_input_teardown(TestInputVisitorData *data,
  25                                   const void *unused)
  26{
  27    if (data->v) {
  28        visit_free(data->v);
  29        data->v = NULL;
  30    }
  31}
  32
  33/* This is provided instead of a test setup function so that the JSON
  34   string used by the tests are kept in the test functions (and not
  35   int main()) */
  36static
  37Visitor *visitor_input_test_init(TestInputVisitorData *data,
  38                                 const char *string)
  39{
  40    visitor_input_teardown(data, NULL);
  41
  42    data->v = string_input_visitor_new(string);
  43    g_assert(data->v);
  44    return data->v;
  45}
  46
  47static void test_visitor_in_int(TestInputVisitorData *data,
  48                                const void *unused)
  49{
  50    int64_t res = 0, value = -42;
  51    Error *err = NULL;
  52    Visitor *v;
  53
  54    v = visitor_input_test_init(data, "-42");
  55
  56    visit_type_int(v, NULL, &res, &error_abort);
  57    g_assert_cmpint(res, ==, value);
  58
  59    v = visitor_input_test_init(data, "not an int");
  60
  61    visit_type_int(v, NULL, &res, &err);
  62    error_free_or_abort(&err);
  63
  64    v = visitor_input_test_init(data, "");
  65
  66    visit_type_int(v, NULL, &res, &err);
  67    error_free_or_abort(&err);
  68}
  69
  70static void check_ilist(Visitor *v, int64_t *expected, size_t n)
  71{
  72    int64List *res = NULL;
  73    int64List *tail;
  74    int i;
  75
  76    visit_type_int64List(v, NULL, &res, &error_abort);
  77    tail = res;
  78    for (i = 0; i < n; i++) {
  79        g_assert(tail);
  80        g_assert_cmpint(tail->value, ==, expected[i]);
  81        tail = tail->next;
  82    }
  83    g_assert(!tail);
  84
  85    qapi_free_int64List(res);
  86}
  87
  88static void check_ulist(Visitor *v, uint64_t *expected, size_t n)
  89{
  90    uint64List *res = NULL;
  91    uint64List *tail;
  92    int i;
  93
  94    visit_type_uint64List(v, NULL, &res, &error_abort);
  95    tail = res;
  96    for (i = 0; i < n; i++) {
  97        g_assert(tail);
  98        g_assert_cmpuint(tail->value, ==, expected[i]);
  99        tail = tail->next;
 100    }
 101    g_assert(!tail);
 102
 103    qapi_free_uint64List(res);
 104}
 105
 106static void test_visitor_in_intList(TestInputVisitorData *data,
 107                                    const void *unused)
 108{
 109    int64_t expect1[] = { 1, 2, 0, 2, 3, 4, 20, 5, 6, 7,
 110                          8, 9, 1, 2, 3, 4, 5, 6, 7, 8 };
 111    int64_t expect2[] = { 32767, -32768, -32767 };
 112    int64_t expect3[] = { INT64_MIN, INT64_MAX };
 113    int64_t expect4[] = { 1 };
 114    int64_t expect5[] = { INT64_MAX - 2,  INT64_MAX - 1, INT64_MAX };
 115    Error *err = NULL;
 116    int64List *res = NULL;
 117    Visitor *v;
 118    int64_t val;
 119
 120    /* Valid lists */
 121
 122    v = visitor_input_test_init(data, "1,2,0,2-4,20,5-9,1-8");
 123    check_ilist(v, expect1, ARRAY_SIZE(expect1));
 124
 125    v = visitor_input_test_init(data, "32767,-32768--32767");
 126    check_ilist(v, expect2, ARRAY_SIZE(expect2));
 127
 128    v = visitor_input_test_init(data,
 129                                "-9223372036854775808,9223372036854775807");
 130    check_ilist(v, expect3, ARRAY_SIZE(expect3));
 131
 132    v = visitor_input_test_init(data, "1-1");
 133    check_ilist(v, expect4, ARRAY_SIZE(expect4));
 134
 135    v = visitor_input_test_init(data,
 136                                "9223372036854775805-9223372036854775807");
 137    check_ilist(v, expect5, ARRAY_SIZE(expect5));
 138
 139    /* Value too large */
 140
 141    v = visitor_input_test_init(data, "9223372036854775808");
 142    visit_type_int64List(v, NULL, &res, &err);
 143    error_free_or_abort(&err);
 144    g_assert(!res);
 145
 146    /* Value too small */
 147
 148    v = visitor_input_test_init(data, "-9223372036854775809");
 149    visit_type_int64List(v, NULL, &res, &err);
 150    error_free_or_abort(&err);
 151    g_assert(!res);
 152
 153    /* Range not ascending */
 154
 155    v = visitor_input_test_init(data, "3-1");
 156    visit_type_int64List(v, NULL, &res, &err);
 157    error_free_or_abort(&err);
 158    g_assert(!res);
 159
 160    v = visitor_input_test_init(data, "9223372036854775807-0");
 161    visit_type_int64List(v, NULL, &res, &err);
 162    error_free_or_abort(&err);
 163    g_assert(!res);
 164
 165    /* Range too big (65536 is the limit against DOS attacks) */
 166
 167    v = visitor_input_test_init(data, "0-65536");
 168    visit_type_int64List(v, NULL, &res, &err);
 169    error_free_or_abort(&err);
 170    g_assert(!res);
 171
 172    /* Empty list */
 173
 174    v = visitor_input_test_init(data, "");
 175    visit_type_int64List(v, NULL, &res, &error_abort);
 176    g_assert(!res);
 177
 178    /* Not a list */
 179
 180    v = visitor_input_test_init(data, "not an int list");
 181
 182    visit_type_int64List(v, NULL, &res, &err);
 183    error_free_or_abort(&err);
 184    g_assert(!res);
 185
 186    /* Unvisited list tail */
 187
 188    v = visitor_input_test_init(data, "0,2-3");
 189
 190    visit_start_list(v, NULL, NULL, 0, &error_abort);
 191    visit_type_int64(v, NULL, &val, &error_abort);
 192    g_assert_cmpint(val, ==, 0);
 193    visit_type_int64(v, NULL, &val, &error_abort);
 194    g_assert_cmpint(val, ==, 2);
 195
 196    visit_check_list(v, &err);
 197    error_free_or_abort(&err);
 198    visit_end_list(v, NULL);
 199
 200    /* Visit beyond end of list */
 201
 202    v = visitor_input_test_init(data, "0");
 203
 204    visit_start_list(v, NULL, NULL, 0, &error_abort);
 205    visit_type_int64(v, NULL, &val, &err);
 206    g_assert_cmpint(val, ==, 0);
 207    visit_type_int64(v, NULL, &val, &err);
 208    error_free_or_abort(&err);
 209
 210    visit_check_list(v, &error_abort);
 211    visit_end_list(v, NULL);
 212}
 213
 214static void test_visitor_in_uintList(TestInputVisitorData *data,
 215                                     const void *unused)
 216{
 217    uint64_t expect1[] = { 1, 2, 0, 2, 3, 4, 20, 5, 6, 7,
 218                           8, 9, 1, 2, 3, 4, 5, 6, 7, 8 };
 219    uint64_t expect2[] = { 32767, -32768, -32767 };
 220    uint64_t expect3[] = { INT64_MIN, INT64_MAX };
 221    uint64_t expect4[] = { 1 };
 222    uint64_t expect5[] = { UINT64_MAX };
 223    uint64_t expect6[] = { UINT64_MAX - 2,  UINT64_MAX - 1, UINT64_MAX };
 224    Error *err = NULL;
 225    uint64List *res = NULL;
 226    Visitor *v;
 227    uint64_t val;
 228
 229    /* Valid lists */
 230
 231    v = visitor_input_test_init(data, "1,2,0,2-4,20,5-9,1-8");
 232    check_ulist(v, expect1, ARRAY_SIZE(expect1));
 233
 234    v = visitor_input_test_init(data, "32767,-32768--32767");
 235    check_ulist(v, expect2, ARRAY_SIZE(expect2));
 236
 237    v = visitor_input_test_init(data,
 238                                "-9223372036854775808,9223372036854775807");
 239    check_ulist(v, expect3, ARRAY_SIZE(expect3));
 240
 241    v = visitor_input_test_init(data, "1-1");
 242    check_ulist(v, expect4, ARRAY_SIZE(expect4));
 243
 244    v = visitor_input_test_init(data, "18446744073709551615");
 245    check_ulist(v, expect5, ARRAY_SIZE(expect5));
 246
 247    v = visitor_input_test_init(data,
 248                                "18446744073709551613-18446744073709551615");
 249    check_ulist(v, expect6, ARRAY_SIZE(expect6));
 250
 251    /* Value too large */
 252
 253    v = visitor_input_test_init(data, "18446744073709551616");
 254    visit_type_uint64List(v, NULL, &res, &err);
 255    error_free_or_abort(&err);
 256    g_assert(!res);
 257
 258    /* Value too small */
 259
 260    v = visitor_input_test_init(data, "-18446744073709551616");
 261    visit_type_uint64List(v, NULL, &res, &err);
 262    error_free_or_abort(&err);
 263    g_assert(!res);
 264
 265    /* Range not ascending */
 266
 267    v = visitor_input_test_init(data, "3-1");
 268    visit_type_uint64List(v, NULL, &res, &err);
 269    error_free_or_abort(&err);
 270    g_assert(!res);
 271
 272    v = visitor_input_test_init(data, "18446744073709551615-0");
 273    visit_type_uint64List(v, NULL, &res, &err);
 274    error_free_or_abort(&err);
 275    g_assert(!res);
 276
 277    /* Range too big (65536 is the limit against DOS attacks) */
 278
 279    v = visitor_input_test_init(data, "0-65536");
 280    visit_type_uint64List(v, NULL, &res, &err);
 281    error_free_or_abort(&err);
 282    g_assert(!res);
 283
 284    /* Empty list */
 285
 286    v = visitor_input_test_init(data, "");
 287    visit_type_uint64List(v, NULL, &res, &error_abort);
 288    g_assert(!res);
 289
 290    /* Not a list */
 291
 292    v = visitor_input_test_init(data, "not an uint list");
 293
 294    visit_type_uint64List(v, NULL, &res, &err);
 295    error_free_or_abort(&err);
 296    g_assert(!res);
 297
 298    /* Unvisited list tail */
 299
 300    v = visitor_input_test_init(data, "0,2-3");
 301
 302    visit_start_list(v, NULL, NULL, 0, &error_abort);
 303    visit_type_uint64(v, NULL, &val, &error_abort);
 304    g_assert_cmpuint(val, ==, 0);
 305    visit_type_uint64(v, NULL, &val, &error_abort);
 306    g_assert_cmpuint(val, ==, 2);
 307
 308    visit_check_list(v, &err);
 309    error_free_or_abort(&err);
 310    visit_end_list(v, NULL);
 311
 312    /* Visit beyond end of list */
 313
 314    v = visitor_input_test_init(data, "0");
 315
 316    visit_start_list(v, NULL, NULL, 0, &error_abort);
 317    visit_type_uint64(v, NULL, &val, &err);
 318    g_assert_cmpuint(val, ==, 0);
 319    visit_type_uint64(v, NULL, &val, &err);
 320    error_free_or_abort(&err);
 321
 322    visit_check_list(v, &error_abort);
 323    visit_end_list(v, NULL);
 324}
 325
 326static void test_visitor_in_bool(TestInputVisitorData *data,
 327                                 const void *unused)
 328{
 329    bool res = false;
 330    Visitor *v;
 331
 332    v = visitor_input_test_init(data, "true");
 333
 334    visit_type_bool(v, NULL, &res, &error_abort);
 335    g_assert_cmpint(res, ==, true);
 336
 337    v = visitor_input_test_init(data, "yes");
 338
 339    visit_type_bool(v, NULL, &res, &error_abort);
 340    g_assert_cmpint(res, ==, true);
 341
 342    v = visitor_input_test_init(data, "on");
 343
 344    visit_type_bool(v, NULL, &res, &error_abort);
 345    g_assert_cmpint(res, ==, true);
 346
 347    v = visitor_input_test_init(data, "false");
 348
 349    visit_type_bool(v, NULL, &res, &error_abort);
 350    g_assert_cmpint(res, ==, false);
 351
 352    v = visitor_input_test_init(data, "no");
 353
 354    visit_type_bool(v, NULL, &res, &error_abort);
 355    g_assert_cmpint(res, ==, false);
 356
 357    v = visitor_input_test_init(data, "off");
 358
 359    visit_type_bool(v, NULL, &res, &error_abort);
 360    g_assert_cmpint(res, ==, false);
 361}
 362
 363static void test_visitor_in_number(TestInputVisitorData *data,
 364                                   const void *unused)
 365{
 366    double res = 0, value = 3.14;
 367    Error *err = NULL;
 368    Visitor *v;
 369
 370    v = visitor_input_test_init(data, "3.14");
 371
 372    visit_type_number(v, NULL, &res, &error_abort);
 373    g_assert_cmpfloat(res, ==, value);
 374
 375    /* NaN and infinity has to be rejected */
 376
 377    v = visitor_input_test_init(data, "NaN");
 378
 379    visit_type_number(v, NULL, &res, &err);
 380    error_free_or_abort(&err);
 381
 382    v = visitor_input_test_init(data, "inf");
 383
 384    visit_type_number(v, NULL, &res, &err);
 385    error_free_or_abort(&err);
 386
 387}
 388
 389static void test_visitor_in_string(TestInputVisitorData *data,
 390                                   const void *unused)
 391{
 392    char *res = NULL, *value = (char *) "Q E M U";
 393    Visitor *v;
 394
 395    v = visitor_input_test_init(data, value);
 396
 397    visit_type_str(v, NULL, &res, &error_abort);
 398    g_assert_cmpstr(res, ==, value);
 399
 400    g_free(res);
 401}
 402
 403static void test_visitor_in_enum(TestInputVisitorData *data,
 404                                 const void *unused)
 405{
 406    Visitor *v;
 407    EnumOne i;
 408
 409    for (i = 0; i < ENUM_ONE__MAX; i++) {
 410        EnumOne res = -1;
 411
 412        v = visitor_input_test_init(data, EnumOne_str(i));
 413
 414        visit_type_EnumOne(v, NULL, &res, &error_abort);
 415        g_assert_cmpint(i, ==, res);
 416    }
 417}
 418
 419/* Try to crash the visitors */
 420static void test_visitor_in_fuzz(TestInputVisitorData *data,
 421                                 const void *unused)
 422{
 423    int64_t ires;
 424    intList *ilres;
 425    bool bres;
 426    double nres;
 427    char *sres;
 428    EnumOne eres;
 429    Visitor *v;
 430    unsigned int i;
 431    char buf[10000];
 432
 433    for (i = 0; i < 100; i++) {
 434        unsigned int j, k;
 435
 436        j = g_test_rand_int_range(0, sizeof(buf) - 1);
 437
 438        buf[j] = '\0';
 439
 440        for (k = 0; k != j; k++) {
 441            buf[k] = (char)g_test_rand_int_range(0, 256);
 442        }
 443
 444        v = visitor_input_test_init(data, buf);
 445        visit_type_int(v, NULL, &ires, NULL);
 446
 447        v = visitor_input_test_init(data, buf);
 448        visit_type_intList(v, NULL, &ilres, NULL);
 449        qapi_free_intList(ilres);
 450
 451        v = visitor_input_test_init(data, buf);
 452        visit_type_bool(v, NULL, &bres, NULL);
 453
 454        v = visitor_input_test_init(data, buf);
 455        visit_type_number(v, NULL, &nres, NULL);
 456
 457        v = visitor_input_test_init(data, buf);
 458        sres = NULL;
 459        visit_type_str(v, NULL, &sres, NULL);
 460        g_free(sres);
 461
 462        v = visitor_input_test_init(data, buf);
 463        visit_type_EnumOne(v, NULL, &eres, NULL);
 464    }
 465}
 466
 467static void input_visitor_test_add(const char *testpath,
 468                                   TestInputVisitorData *data,
 469                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
 470{
 471    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
 472               visitor_input_teardown);
 473}
 474
 475int main(int argc, char **argv)
 476{
 477    TestInputVisitorData in_visitor_data;
 478
 479    g_test_init(&argc, &argv, NULL);
 480
 481    input_visitor_test_add("/string-visitor/input/int",
 482                           &in_visitor_data, test_visitor_in_int);
 483    input_visitor_test_add("/string-visitor/input/intList",
 484                           &in_visitor_data, test_visitor_in_intList);
 485    input_visitor_test_add("/string-visitor/input/uintList",
 486                           &in_visitor_data, test_visitor_in_uintList);
 487    input_visitor_test_add("/string-visitor/input/bool",
 488                           &in_visitor_data, test_visitor_in_bool);
 489    input_visitor_test_add("/string-visitor/input/number",
 490                           &in_visitor_data, test_visitor_in_number);
 491    input_visitor_test_add("/string-visitor/input/string",
 492                            &in_visitor_data, test_visitor_in_string);
 493    input_visitor_test_add("/string-visitor/input/enum",
 494                            &in_visitor_data, test_visitor_in_enum);
 495    input_visitor_test_add("/string-visitor/input/fuzz",
 496                            &in_visitor_data, test_visitor_in_fuzz);
 497
 498    g_test_run();
 499
 500    return 0;
 501}
 502