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