qemu/tests/test-throttle.c
<<
>>
Prefs
   1/*
   2 * Throttle infrastructure tests
   3 *
   4 * Copyright Nodalink, EURL. 2013-2014
   5 * Copyright Igalia, S.L. 2015
   6 *
   7 * Authors:
   8 *  BenoƮt Canet     <benoit.canet@nodalink.com>
   9 *  Alberto Garcia   <berto@igalia.com>
  10 *
  11 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
  12 * See the COPYING.LIB file in the top-level directory.
  13 */
  14
  15#include "qemu/osdep.h"
  16#include <glib.h>
  17#include <math.h>
  18#include "block/aio.h"
  19#include "qapi/error.h"
  20#include "qemu/throttle.h"
  21#include "qemu/error-report.h"
  22#include "block/throttle-groups.h"
  23
  24static AioContext     *ctx;
  25static LeakyBucket    bkt;
  26static ThrottleConfig cfg;
  27static ThrottleState  ts;
  28static ThrottleTimers tt;
  29
  30/* useful function */
  31static bool double_cmp(double x, double y)
  32{
  33    return fabsl(x - y) < 1e-6;
  34}
  35
  36/* tests for single bucket operations */
  37static void test_leak_bucket(void)
  38{
  39    throttle_config_init(&cfg);
  40    bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
  41
  42    /* set initial value */
  43    bkt.avg = 150;
  44    bkt.max = 15;
  45    bkt.level = 1.5;
  46
  47    /* leak an op work of time */
  48    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
  49    g_assert(bkt.avg == 150);
  50    g_assert(bkt.max == 15);
  51    g_assert(double_cmp(bkt.level, 0.5));
  52
  53    /* leak again emptying the bucket */
  54    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
  55    g_assert(bkt.avg == 150);
  56    g_assert(bkt.max == 15);
  57    g_assert(double_cmp(bkt.level, 0));
  58
  59    /* check that the bucket level won't go lower */
  60    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
  61    g_assert(bkt.avg == 150);
  62    g_assert(bkt.max == 15);
  63    g_assert(double_cmp(bkt.level, 0));
  64
  65    /* check that burst_level leaks correctly */
  66    bkt.burst_level = 6;
  67    bkt.max = 250;
  68    bkt.burst_length = 2; /* otherwise burst_level will not leak */
  69    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
  70    g_assert(double_cmp(bkt.burst_level, 3.5));
  71
  72    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
  73    g_assert(double_cmp(bkt.burst_level, 1));
  74
  75    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
  76    g_assert(double_cmp(bkt.burst_level, 0));
  77
  78    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
  79    g_assert(double_cmp(bkt.burst_level, 0));
  80}
  81
  82static void test_compute_wait(void)
  83{
  84    unsigned i;
  85    int64_t wait;
  86    int64_t result;
  87
  88    throttle_config_init(&cfg);
  89    bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
  90
  91    /* no operation limit set */
  92    bkt.avg = 0;
  93    bkt.max = 15;
  94    bkt.level = 1.5;
  95    wait = throttle_compute_wait(&bkt);
  96    g_assert(!wait);
  97
  98    /* zero delta */
  99    bkt.avg = 150;
 100    bkt.max = 15;
 101    bkt.level = 15;
 102    wait = throttle_compute_wait(&bkt);
 103    g_assert(!wait);
 104
 105    /* below zero delta */
 106    bkt.avg = 150;
 107    bkt.max = 15;
 108    bkt.level = 9;
 109    wait = throttle_compute_wait(&bkt);
 110    g_assert(!wait);
 111
 112    /* half an operation above max */
 113    bkt.avg = 150;
 114    bkt.max = 15;
 115    bkt.level = 15.5;
 116    wait = throttle_compute_wait(&bkt);
 117    /* time required to do half an operation */
 118    result = (int64_t)  NANOSECONDS_PER_SECOND / 150 / 2;
 119    g_assert(wait == result);
 120
 121    /* Perform I/O for 2.2 seconds at a rate of bkt.max */
 122    bkt.burst_length = 2;
 123    bkt.level = 0;
 124    bkt.avg = 10;
 125    bkt.max = 200;
 126    for (i = 0; i < 22; i++) {
 127        double units = bkt.max / 10;
 128        bkt.level += units;
 129        bkt.burst_level += units;
 130        throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 10);
 131        wait = throttle_compute_wait(&bkt);
 132        g_assert(double_cmp(bkt.burst_level, 0));
 133        g_assert(double_cmp(bkt.level, (i + 1) * (bkt.max - bkt.avg) / 10));
 134        /* We can do bursts for the 2 seconds we have configured in
 135         * burst_length. We have 100 extra miliseconds of burst
 136         * because bkt.level has been leaking during this time.
 137         * After that, we have to wait. */
 138        result = i < 21 ? 0 : 1.8 * NANOSECONDS_PER_SECOND;
 139        g_assert(wait == result);
 140    }
 141}
 142
 143/* functions to test ThrottleState initialization/destroy methods */
 144static void read_timer_cb(void *opaque)
 145{
 146}
 147
 148static void write_timer_cb(void *opaque)
 149{
 150}
 151
 152static void test_init(void)
 153{
 154    int i;
 155
 156    /* fill the structures with crap */
 157    memset(&ts, 1, sizeof(ts));
 158    memset(&tt, 1, sizeof(tt));
 159
 160    /* init structures */
 161    throttle_init(&ts);
 162    throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
 163                         read_timer_cb, write_timer_cb, &ts);
 164
 165    /* check initialized fields */
 166    g_assert(tt.clock_type == QEMU_CLOCK_VIRTUAL);
 167    g_assert(tt.timers[0]);
 168    g_assert(tt.timers[1]);
 169
 170    /* check other fields where cleared */
 171    g_assert(!ts.previous_leak);
 172    g_assert(!ts.cfg.op_size);
 173    for (i = 0; i < BUCKETS_COUNT; i++) {
 174        g_assert(!ts.cfg.buckets[i].avg);
 175        g_assert(!ts.cfg.buckets[i].max);
 176        g_assert(!ts.cfg.buckets[i].level);
 177    }
 178
 179    throttle_timers_destroy(&tt);
 180}
 181
 182static void test_destroy(void)
 183{
 184    int i;
 185    throttle_init(&ts);
 186    throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
 187                         read_timer_cb, write_timer_cb, &ts);
 188    throttle_timers_destroy(&tt);
 189    for (i = 0; i < 2; i++) {
 190        g_assert(!tt.timers[i]);
 191    }
 192}
 193
 194/* function to test throttle_config and throttle_get_config */
 195static void test_config_functions(void)
 196{
 197    int i;
 198    ThrottleConfig orig_cfg, final_cfg;
 199
 200    orig_cfg.buckets[THROTTLE_BPS_TOTAL].avg = 153;
 201    orig_cfg.buckets[THROTTLE_BPS_READ].avg  = 56;
 202    orig_cfg.buckets[THROTTLE_BPS_WRITE].avg = 1;
 203
 204    orig_cfg.buckets[THROTTLE_OPS_TOTAL].avg = 150;
 205    orig_cfg.buckets[THROTTLE_OPS_READ].avg  = 69;
 206    orig_cfg.buckets[THROTTLE_OPS_WRITE].avg = 23;
 207
 208    orig_cfg.buckets[THROTTLE_BPS_TOTAL].max = 0; /* should be corrected */
 209    orig_cfg.buckets[THROTTLE_BPS_READ].max  = 1; /* should not be corrected */
 210    orig_cfg.buckets[THROTTLE_BPS_WRITE].max = 120;
 211
 212    orig_cfg.buckets[THROTTLE_OPS_TOTAL].max = 150;
 213    orig_cfg.buckets[THROTTLE_OPS_READ].max  = 400;
 214    orig_cfg.buckets[THROTTLE_OPS_WRITE].max = 500;
 215
 216    orig_cfg.buckets[THROTTLE_BPS_TOTAL].level = 45;
 217    orig_cfg.buckets[THROTTLE_BPS_READ].level  = 65;
 218    orig_cfg.buckets[THROTTLE_BPS_WRITE].level = 23;
 219
 220    orig_cfg.buckets[THROTTLE_OPS_TOTAL].level = 1;
 221    orig_cfg.buckets[THROTTLE_OPS_READ].level  = 90;
 222    orig_cfg.buckets[THROTTLE_OPS_WRITE].level = 75;
 223
 224    orig_cfg.op_size = 1;
 225
 226    throttle_init(&ts);
 227    throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
 228                         read_timer_cb, write_timer_cb, &ts);
 229    /* structure reset by throttle_init previous_leak should be null */
 230    g_assert(!ts.previous_leak);
 231    throttle_config(&ts, &tt, &orig_cfg);
 232
 233    /* has previous leak been initialized by throttle_config ? */
 234    g_assert(ts.previous_leak);
 235
 236    /* get back the fixed configuration */
 237    throttle_get_config(&ts, &final_cfg);
 238
 239    throttle_timers_destroy(&tt);
 240
 241    g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153);
 242    g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg  == 56);
 243    g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].avg == 1);
 244
 245    g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].avg == 150);
 246    g_assert(final_cfg.buckets[THROTTLE_OPS_READ].avg  == 69);
 247    g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].avg == 23);
 248
 249    g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].max == 15.3);/* fixed */
 250    g_assert(final_cfg.buckets[THROTTLE_BPS_READ].max  == 1);   /* not fixed */
 251    g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].max == 120);
 252
 253    g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].max == 150);
 254    g_assert(final_cfg.buckets[THROTTLE_OPS_READ].max  == 400);
 255    g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].max == 500);
 256
 257    g_assert(final_cfg.op_size == 1);
 258
 259    /* check bucket have been cleared */
 260    for (i = 0; i < BUCKETS_COUNT; i++) {
 261        g_assert(!final_cfg.buckets[i].level);
 262    }
 263}
 264
 265/* functions to test is throttle is enabled by a config */
 266static void set_cfg_value(bool is_max, int index, int value)
 267{
 268    if (is_max) {
 269        cfg.buckets[index].max = value;
 270        /* If max is set, avg should never be 0 */
 271        cfg.buckets[index].avg = MAX(cfg.buckets[index].avg, 1);
 272    } else {
 273        cfg.buckets[index].avg = value;
 274    }
 275}
 276
 277static void test_enabled(void)
 278{
 279    int i;
 280
 281    throttle_config_init(&cfg);
 282    g_assert(!throttle_enabled(&cfg));
 283
 284    for (i = 0; i < BUCKETS_COUNT; i++) {
 285        throttle_config_init(&cfg);
 286        set_cfg_value(false, i, 150);
 287        g_assert(throttle_enabled(&cfg));
 288    }
 289
 290    for (i = 0; i < BUCKETS_COUNT; i++) {
 291        throttle_config_init(&cfg);
 292        set_cfg_value(false, i, -150);
 293        g_assert(!throttle_enabled(&cfg));
 294    }
 295}
 296
 297/* tests functions for throttle_conflicting */
 298
 299static void test_conflicts_for_one_set(bool is_max,
 300                                       int total,
 301                                       int read,
 302                                       int write)
 303{
 304    throttle_config_init(&cfg);
 305    g_assert(throttle_is_valid(&cfg, NULL));
 306
 307    set_cfg_value(is_max, total, 1);
 308    set_cfg_value(is_max, read,  1);
 309    g_assert(!throttle_is_valid(&cfg, NULL));
 310
 311    throttle_config_init(&cfg);
 312    set_cfg_value(is_max, total, 1);
 313    set_cfg_value(is_max, write, 1);
 314    g_assert(!throttle_is_valid(&cfg, NULL));
 315
 316    throttle_config_init(&cfg);
 317    set_cfg_value(is_max, total, 1);
 318    set_cfg_value(is_max, read,  1);
 319    set_cfg_value(is_max, write, 1);
 320    g_assert(!throttle_is_valid(&cfg, NULL));
 321
 322    throttle_config_init(&cfg);
 323    set_cfg_value(is_max, total, 1);
 324    g_assert(throttle_is_valid(&cfg, NULL));
 325
 326    throttle_config_init(&cfg);
 327    set_cfg_value(is_max, read,  1);
 328    set_cfg_value(is_max, write, 1);
 329    g_assert(throttle_is_valid(&cfg, NULL));
 330}
 331
 332static void test_conflicting_config(void)
 333{
 334    /* bps average conflicts */
 335    test_conflicts_for_one_set(false,
 336                               THROTTLE_BPS_TOTAL,
 337                               THROTTLE_BPS_READ,
 338                               THROTTLE_BPS_WRITE);
 339
 340    /* ops average conflicts */
 341    test_conflicts_for_one_set(false,
 342                               THROTTLE_OPS_TOTAL,
 343                               THROTTLE_OPS_READ,
 344                               THROTTLE_OPS_WRITE);
 345
 346    /* bps average conflicts */
 347    test_conflicts_for_one_set(true,
 348                               THROTTLE_BPS_TOTAL,
 349                               THROTTLE_BPS_READ,
 350                               THROTTLE_BPS_WRITE);
 351    /* ops average conflicts */
 352    test_conflicts_for_one_set(true,
 353                               THROTTLE_OPS_TOTAL,
 354                               THROTTLE_OPS_READ,
 355                               THROTTLE_OPS_WRITE);
 356}
 357/* functions to test the throttle_is_valid function */
 358static void test_is_valid_for_value(int value, bool should_be_valid)
 359{
 360    int is_max, index;
 361    for (is_max = 0; is_max < 2; is_max++) {
 362        for (index = 0; index < BUCKETS_COUNT; index++) {
 363            throttle_config_init(&cfg);
 364            set_cfg_value(is_max, index, value);
 365            g_assert(throttle_is_valid(&cfg, NULL) == should_be_valid);
 366        }
 367    }
 368}
 369
 370static void test_is_valid(void)
 371{
 372    /* negative number are invalid */
 373    test_is_valid_for_value(-1, false);
 374    /* zero are valids */
 375    test_is_valid_for_value(0, true);
 376    /* positives numers are valids */
 377    test_is_valid_for_value(1, true);
 378}
 379
 380static void test_max_is_missing_limit(void)
 381{
 382    int i;
 383
 384    for (i = 0; i < BUCKETS_COUNT; i++) {
 385        throttle_config_init(&cfg);
 386        cfg.buckets[i].max = 100;
 387        cfg.buckets[i].avg = 0;
 388        g_assert(!throttle_is_valid(&cfg, NULL));
 389
 390        cfg.buckets[i].max = 0;
 391        cfg.buckets[i].avg = 0;
 392        g_assert(throttle_is_valid(&cfg, NULL));
 393
 394        cfg.buckets[i].max = 0;
 395        cfg.buckets[i].avg = 100;
 396        g_assert(throttle_is_valid(&cfg, NULL));
 397    }
 398}
 399
 400static void test_have_timer(void)
 401{
 402    /* zero structures */
 403    memset(&ts, 0, sizeof(ts));
 404    memset(&tt, 0, sizeof(tt));
 405
 406    /* no timer set should return false */
 407    g_assert(!throttle_timers_are_initialized(&tt));
 408
 409    /* init structures */
 410    throttle_init(&ts);
 411    throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
 412                         read_timer_cb, write_timer_cb, &ts);
 413
 414    /* timer set by init should return true */
 415    g_assert(throttle_timers_are_initialized(&tt));
 416
 417    throttle_timers_destroy(&tt);
 418}
 419
 420static void test_detach_attach(void)
 421{
 422    /* zero structures */
 423    memset(&ts, 0, sizeof(ts));
 424    memset(&tt, 0, sizeof(tt));
 425
 426    /* init the structure */
 427    throttle_init(&ts);
 428    throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
 429                         read_timer_cb, write_timer_cb, &ts);
 430
 431    /* timer set by init should return true */
 432    g_assert(throttle_timers_are_initialized(&tt));
 433
 434    /* timer should no longer exist after detaching */
 435    throttle_timers_detach_aio_context(&tt);
 436    g_assert(!throttle_timers_are_initialized(&tt));
 437
 438    /* timer should exist again after attaching */
 439    throttle_timers_attach_aio_context(&tt, ctx);
 440    g_assert(throttle_timers_are_initialized(&tt));
 441
 442    throttle_timers_destroy(&tt);
 443}
 444
 445static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
 446                int size,                   /* size of the operation to do */
 447                double avg,                 /* io limit */
 448                uint64_t op_size,           /* ideal size of an io */
 449                double total_result,
 450                double read_result,
 451                double write_result)
 452{
 453    BucketType to_test[2][3] = { { THROTTLE_BPS_TOTAL,
 454                                   THROTTLE_BPS_READ,
 455                                   THROTTLE_BPS_WRITE, },
 456                                 { THROTTLE_OPS_TOTAL,
 457                                   THROTTLE_OPS_READ,
 458                                   THROTTLE_OPS_WRITE, } };
 459    ThrottleConfig cfg;
 460    BucketType index;
 461    int i;
 462
 463    for (i = 0; i < 3; i++) {
 464        BucketType index = to_test[is_ops][i];
 465        cfg.buckets[index].avg = avg;
 466    }
 467
 468    cfg.op_size = op_size;
 469
 470    throttle_init(&ts);
 471    throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL,
 472                         read_timer_cb, write_timer_cb, &ts);
 473    throttle_config(&ts, &tt, &cfg);
 474
 475    /* account a read */
 476    throttle_account(&ts, false, size);
 477    /* account a write */
 478    throttle_account(&ts, true, size);
 479
 480    /* check total result */
 481    index = to_test[is_ops][0];
 482    if (!double_cmp(ts.cfg.buckets[index].level, total_result)) {
 483        return false;
 484    }
 485
 486    /* check read result */
 487    index = to_test[is_ops][1];
 488    if (!double_cmp(ts.cfg.buckets[index].level, read_result)) {
 489        return false;
 490    }
 491
 492    /* check write result */
 493    index = to_test[is_ops][2];
 494    if (!double_cmp(ts.cfg.buckets[index].level, write_result)) {
 495        return false;
 496    }
 497
 498    throttle_timers_destroy(&tt);
 499
 500    return true;
 501}
 502
 503static void test_accounting(void)
 504{
 505    /* tests for bps */
 506
 507    /* op of size 1 */
 508    g_assert(do_test_accounting(false,
 509                                1 * 512,
 510                                150,
 511                                0,
 512                                1024,
 513                                512,
 514                                512));
 515
 516    /* op of size 2 */
 517    g_assert(do_test_accounting(false,
 518                                2 * 512,
 519                                150,
 520                                0,
 521                                2048,
 522                                1024,
 523                                1024));
 524
 525    /* op of size 2 and orthogonal parameter change */
 526    g_assert(do_test_accounting(false,
 527                                2 * 512,
 528                                150,
 529                                17,
 530                                2048,
 531                                1024,
 532                                1024));
 533
 534
 535    /* tests for ops */
 536
 537    /* op of size 1 */
 538    g_assert(do_test_accounting(true,
 539                                1 * 512,
 540                                150,
 541                                0,
 542                                2,
 543                                1,
 544                                1));
 545
 546    /* op of size 2 */
 547    g_assert(do_test_accounting(true,
 548                                2 *  512,
 549                                150,
 550                                0,
 551                                2,
 552                                1,
 553                                1));
 554
 555    /* jumbo op accounting fragmentation : size 64 with op size of 13 units */
 556    g_assert(do_test_accounting(true,
 557                                64 * 512,
 558                                150,
 559                                13 * 512,
 560                                (64.0 * 2) / 13,
 561                                (64.0 / 13),
 562                                (64.0 / 13)));
 563
 564    /* same with orthogonal parameters changes */
 565    g_assert(do_test_accounting(true,
 566                                64 * 512,
 567                                300,
 568                                13 * 512,
 569                                (64.0 * 2) / 13,
 570                                (64.0 / 13),
 571                                (64.0 / 13)));
 572}
 573
 574static void test_groups(void)
 575{
 576    ThrottleConfig cfg1, cfg2;
 577    BlockDriverState *bdrv1, *bdrv2, *bdrv3;
 578
 579    bdrv1 = bdrv_new();
 580    bdrv2 = bdrv_new();
 581    bdrv3 = bdrv_new();
 582
 583    g_assert(bdrv1->throttle_state == NULL);
 584    g_assert(bdrv2->throttle_state == NULL);
 585    g_assert(bdrv3->throttle_state == NULL);
 586
 587    throttle_group_register_bs(bdrv1, "bar");
 588    throttle_group_register_bs(bdrv2, "foo");
 589    throttle_group_register_bs(bdrv3, "bar");
 590
 591    g_assert(bdrv1->throttle_state != NULL);
 592    g_assert(bdrv2->throttle_state != NULL);
 593    g_assert(bdrv3->throttle_state != NULL);
 594
 595    g_assert(!strcmp(throttle_group_get_name(bdrv1), "bar"));
 596    g_assert(!strcmp(throttle_group_get_name(bdrv2), "foo"));
 597    g_assert(bdrv1->throttle_state == bdrv3->throttle_state);
 598
 599    /* Setting the config of a group member affects the whole group */
 600    throttle_config_init(&cfg1);
 601    cfg1.buckets[THROTTLE_BPS_READ].avg  = 500000;
 602    cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000;
 603    cfg1.buckets[THROTTLE_OPS_READ].avg  = 20000;
 604    cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000;
 605    throttle_group_config(bdrv1, &cfg1);
 606
 607    throttle_group_get_config(bdrv1, &cfg1);
 608    throttle_group_get_config(bdrv3, &cfg2);
 609    g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
 610
 611    cfg2.buckets[THROTTLE_BPS_READ].avg  = 4547;
 612    cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349;
 613    cfg2.buckets[THROTTLE_OPS_READ].avg  = 123;
 614    cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86;
 615    throttle_group_config(bdrv3, &cfg1);
 616
 617    throttle_group_get_config(bdrv1, &cfg1);
 618    throttle_group_get_config(bdrv3, &cfg2);
 619    g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
 620
 621    throttle_group_unregister_bs(bdrv1);
 622    throttle_group_unregister_bs(bdrv2);
 623    throttle_group_unregister_bs(bdrv3);
 624
 625    g_assert(bdrv1->throttle_state == NULL);
 626    g_assert(bdrv2->throttle_state == NULL);
 627    g_assert(bdrv3->throttle_state == NULL);
 628}
 629
 630int main(int argc, char **argv)
 631{
 632    qemu_init_main_loop(&error_fatal);
 633    ctx = qemu_get_aio_context();
 634    bdrv_init();
 635
 636    do {} while (g_main_context_iteration(NULL, false));
 637
 638    /* tests in the same order as the header function declarations */
 639    g_test_init(&argc, &argv, NULL);
 640    g_test_add_func("/throttle/leak_bucket",        test_leak_bucket);
 641    g_test_add_func("/throttle/compute_wait",       test_compute_wait);
 642    g_test_add_func("/throttle/init",               test_init);
 643    g_test_add_func("/throttle/destroy",            test_destroy);
 644    g_test_add_func("/throttle/have_timer",         test_have_timer);
 645    g_test_add_func("/throttle/detach_attach",      test_detach_attach);
 646    g_test_add_func("/throttle/config/enabled",     test_enabled);
 647    g_test_add_func("/throttle/config/conflicting", test_conflicting_config);
 648    g_test_add_func("/throttle/config/is_valid",    test_is_valid);
 649    g_test_add_func("/throttle/config/max",         test_max_is_missing_limit);
 650    g_test_add_func("/throttle/config_functions",   test_config_functions);
 651    g_test_add_func("/throttle/accounting",         test_accounting);
 652    g_test_add_func("/throttle/groups",             test_groups);
 653    return g_test_run();
 654}
 655
 656