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