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