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