hw/hppa/Kconfig: Fix building with "configure --without-default-devices"
[qemu/ar7.git] / tests / unit / test-throttle.c
blob2146cfacd3635723aa6a5ea1dc8d29da5d4204cc
1 /*
2 * Throttle infrastructure tests
4 * Copyright Nodalink, EURL. 2013-2014
5 * Copyright Igalia, S.L. 2015
7 * Authors:
8 * BenoƮt Canet <benoit.canet@nodalink.com>
9 * Alberto Garcia <berto@igalia.com>
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.
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/main-loop.h"
22 #include "qemu/module.h"
23 #include "block/throttle-groups.h"
24 #include "sysemu/block-backend.h"
26 static AioContext *ctx;
27 static LeakyBucket bkt;
28 static ThrottleConfig cfg;
29 static ThrottleGroupMember tgm;
30 static ThrottleState ts;
31 static ThrottleTimers *tt;
33 /* useful function */
34 static bool double_cmp(double x, double y)
36 return fabsl(x - y) < 1e-6;
39 /* tests for single bucket operations */
40 static void test_leak_bucket(void)
42 throttle_config_init(&cfg);
43 bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
45 /* set initial value */
46 bkt.avg = 150;
47 bkt.max = 15;
48 bkt.level = 1.5;
50 /* leak an op work of time */
51 throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
52 g_assert(bkt.avg == 150);
53 g_assert(bkt.max == 15);
54 g_assert(double_cmp(bkt.level, 0.5));
56 /* leak again emptying the bucket */
57 throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
58 g_assert(bkt.avg == 150);
59 g_assert(bkt.max == 15);
60 g_assert(double_cmp(bkt.level, 0));
62 /* check that the bucket level won't go lower */
63 throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
64 g_assert(bkt.avg == 150);
65 g_assert(bkt.max == 15);
66 g_assert(double_cmp(bkt.level, 0));
68 /* check that burst_level leaks correctly */
69 bkt.burst_level = 6;
70 bkt.max = 250;
71 bkt.burst_length = 2; /* otherwise burst_level will not leak */
72 throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
73 g_assert(double_cmp(bkt.burst_level, 3.5));
75 throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
76 g_assert(double_cmp(bkt.burst_level, 1));
78 throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
79 g_assert(double_cmp(bkt.burst_level, 0));
81 throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
82 g_assert(double_cmp(bkt.burst_level, 0));
85 static void test_compute_wait(void)
87 unsigned i;
88 int64_t wait;
89 int64_t result;
91 throttle_config_init(&cfg);
92 bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
94 /* no operation limit set */
95 bkt.avg = 0;
96 bkt.max = 15;
97 bkt.level = 1.5;
98 wait = throttle_compute_wait(&bkt);
99 g_assert(!wait);
101 /* zero delta */
102 bkt.avg = 150;
103 bkt.max = 15;
104 bkt.level = 15;
105 wait = throttle_compute_wait(&bkt);
106 g_assert(!wait);
108 /* below zero delta */
109 bkt.avg = 150;
110 bkt.max = 15;
111 bkt.level = 9;
112 wait = throttle_compute_wait(&bkt);
113 g_assert(!wait);
115 /* half an operation above max */
116 bkt.avg = 150;
117 bkt.max = 15;
118 bkt.level = 15.5;
119 wait = throttle_compute_wait(&bkt);
120 /* time required to do half an operation */
121 result = (int64_t) NANOSECONDS_PER_SECOND / 150 / 2;
122 g_assert(wait == result);
124 /* Perform I/O for 2.2 seconds at a rate of bkt.max */
125 bkt.burst_length = 2;
126 bkt.level = 0;
127 bkt.avg = 10;
128 bkt.max = 200;
129 for (i = 0; i < 22; i++) {
130 double units = bkt.max / 10;
131 bkt.level += units;
132 bkt.burst_level += units;
133 throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 10);
134 wait = throttle_compute_wait(&bkt);
135 g_assert(double_cmp(bkt.burst_level, 0));
136 g_assert(double_cmp(bkt.level, (i + 1) * (bkt.max - bkt.avg) / 10));
137 /* We can do bursts for the 2 seconds we have configured in
138 * burst_length. We have 100 extra milliseconds of burst
139 * because bkt.level has been leaking during this time.
140 * After that, we have to wait. */
141 result = i < 21 ? 0 : 1.8 * NANOSECONDS_PER_SECOND;
142 g_assert(wait == result);
146 /* functions to test ThrottleState initialization/destroy methods */
147 static void read_timer_cb(void *opaque)
151 static void write_timer_cb(void *opaque)
155 static void test_init(void)
157 int i;
159 tt = &tgm.throttle_timers;
161 /* fill the structures with crap */
162 memset(&ts, 1, sizeof(ts));
163 memset(tt, 1, sizeof(*tt));
165 /* init structures */
166 throttle_init(&ts);
167 throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
168 read_timer_cb, write_timer_cb, &ts);
170 /* check initialized fields */
171 g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
172 g_assert(tt->timers[THROTTLE_READ]);
173 g_assert(tt->timers[THROTTLE_WRITE]);
175 /* check other fields where cleared */
176 g_assert(!ts.previous_leak);
177 g_assert(!ts.cfg.op_size);
178 for (i = 0; i < BUCKETS_COUNT; i++) {
179 g_assert(!ts.cfg.buckets[i].avg);
180 g_assert(!ts.cfg.buckets[i].max);
181 g_assert(!ts.cfg.buckets[i].level);
184 throttle_timers_destroy(tt);
187 static void test_init_readonly(void)
189 int i;
191 tt = &tgm.throttle_timers;
193 /* fill the structures with crap */
194 memset(&ts, 1, sizeof(ts));
195 memset(tt, 1, sizeof(*tt));
197 /* init structures */
198 throttle_init(&ts);
199 throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
200 read_timer_cb, NULL, &ts);
202 /* check initialized fields */
203 g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
204 g_assert(tt->timers[THROTTLE_READ]);
205 g_assert(!tt->timers[THROTTLE_WRITE]);
207 /* check other fields where cleared */
208 g_assert(!ts.previous_leak);
209 g_assert(!ts.cfg.op_size);
210 for (i = 0; i < BUCKETS_COUNT; i++) {
211 g_assert(!ts.cfg.buckets[i].avg);
212 g_assert(!ts.cfg.buckets[i].max);
213 g_assert(!ts.cfg.buckets[i].level);
216 throttle_timers_destroy(tt);
219 static void test_init_writeonly(void)
221 int i;
223 tt = &tgm.throttle_timers;
225 /* fill the structures with crap */
226 memset(&ts, 1, sizeof(ts));
227 memset(tt, 1, sizeof(*tt));
229 /* init structures */
230 throttle_init(&ts);
231 throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
232 NULL, write_timer_cb, &ts);
234 /* check initialized fields */
235 g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
236 g_assert(!tt->timers[THROTTLE_READ]);
237 g_assert(tt->timers[THROTTLE_WRITE]);
239 /* check other fields where cleared */
240 g_assert(!ts.previous_leak);
241 g_assert(!ts.cfg.op_size);
242 for (i = 0; i < BUCKETS_COUNT; i++) {
243 g_assert(!ts.cfg.buckets[i].avg);
244 g_assert(!ts.cfg.buckets[i].max);
245 g_assert(!ts.cfg.buckets[i].level);
248 throttle_timers_destroy(tt);
251 static void test_destroy(void)
253 int i;
254 throttle_init(&ts);
255 throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
256 read_timer_cb, write_timer_cb, &ts);
257 throttle_timers_destroy(tt);
258 for (i = 0; i < THROTTLE_MAX; i++) {
259 g_assert(!tt->timers[i]);
263 /* function to test throttle_config and throttle_get_config */
264 static void test_config_functions(void)
266 int i;
267 ThrottleConfig orig_cfg, final_cfg;
269 orig_cfg.buckets[THROTTLE_BPS_TOTAL].avg = 153;
270 orig_cfg.buckets[THROTTLE_BPS_READ].avg = 56;
271 orig_cfg.buckets[THROTTLE_BPS_WRITE].avg = 1;
273 orig_cfg.buckets[THROTTLE_OPS_TOTAL].avg = 150;
274 orig_cfg.buckets[THROTTLE_OPS_READ].avg = 69;
275 orig_cfg.buckets[THROTTLE_OPS_WRITE].avg = 23;
277 orig_cfg.buckets[THROTTLE_BPS_TOTAL].max = 0;
278 orig_cfg.buckets[THROTTLE_BPS_READ].max = 56;
279 orig_cfg.buckets[THROTTLE_BPS_WRITE].max = 120;
281 orig_cfg.buckets[THROTTLE_OPS_TOTAL].max = 150;
282 orig_cfg.buckets[THROTTLE_OPS_READ].max = 400;
283 orig_cfg.buckets[THROTTLE_OPS_WRITE].max = 500;
285 orig_cfg.buckets[THROTTLE_BPS_TOTAL].level = 45;
286 orig_cfg.buckets[THROTTLE_BPS_READ].level = 65;
287 orig_cfg.buckets[THROTTLE_BPS_WRITE].level = 23;
289 orig_cfg.buckets[THROTTLE_OPS_TOTAL].level = 1;
290 orig_cfg.buckets[THROTTLE_OPS_READ].level = 90;
291 orig_cfg.buckets[THROTTLE_OPS_WRITE].level = 75;
293 orig_cfg.op_size = 1;
295 throttle_init(&ts);
296 throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
297 read_timer_cb, write_timer_cb, &ts);
298 /* structure reset by throttle_init previous_leak should be null */
299 g_assert(!ts.previous_leak);
300 throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &orig_cfg);
302 /* has previous leak been initialized by throttle_config ? */
303 g_assert(ts.previous_leak);
305 /* get back the fixed configuration */
306 throttle_get_config(&ts, &final_cfg);
308 throttle_timers_destroy(tt);
310 g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153);
311 g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg == 56);
312 g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].avg == 1);
314 g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].avg == 150);
315 g_assert(final_cfg.buckets[THROTTLE_OPS_READ].avg == 69);
316 g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].avg == 23);
318 g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].max == 0);
319 g_assert(final_cfg.buckets[THROTTLE_BPS_READ].max == 56);
320 g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].max == 120);
322 g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].max == 150);
323 g_assert(final_cfg.buckets[THROTTLE_OPS_READ].max == 400);
324 g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].max == 500);
326 g_assert(final_cfg.op_size == 1);
328 /* check bucket have been cleared */
329 for (i = 0; i < BUCKETS_COUNT; i++) {
330 g_assert(!final_cfg.buckets[i].level);
334 /* functions to test is throttle is enabled by a config */
335 static void set_cfg_value(bool is_max, int index, int value)
337 if (is_max) {
338 cfg.buckets[index].max = value;
339 /* If max is set, avg should never be 0 */
340 cfg.buckets[index].avg = MAX(cfg.buckets[index].avg, 1);
341 } else {
342 cfg.buckets[index].avg = value;
346 static void test_enabled(void)
348 int i;
350 throttle_config_init(&cfg);
351 g_assert(!throttle_enabled(&cfg));
353 for (i = 0; i < BUCKETS_COUNT; i++) {
354 throttle_config_init(&cfg);
355 set_cfg_value(false, i, 150);
356 g_assert(throttle_is_valid(&cfg, NULL));
357 g_assert(throttle_enabled(&cfg));
360 for (i = 0; i < BUCKETS_COUNT; i++) {
361 throttle_config_init(&cfg);
362 set_cfg_value(false, i, -150);
363 g_assert(!throttle_is_valid(&cfg, NULL));
367 /* tests functions for throttle_conflicting */
369 static void test_conflicts_for_one_set(bool is_max,
370 int total,
371 int read,
372 int write)
374 throttle_config_init(&cfg);
375 g_assert(throttle_is_valid(&cfg, NULL));
377 set_cfg_value(is_max, total, 1);
378 set_cfg_value(is_max, read, 1);
379 g_assert(!throttle_is_valid(&cfg, NULL));
381 throttle_config_init(&cfg);
382 set_cfg_value(is_max, total, 1);
383 set_cfg_value(is_max, write, 1);
384 g_assert(!throttle_is_valid(&cfg, NULL));
386 throttle_config_init(&cfg);
387 set_cfg_value(is_max, total, 1);
388 set_cfg_value(is_max, read, 1);
389 set_cfg_value(is_max, write, 1);
390 g_assert(!throttle_is_valid(&cfg, NULL));
392 throttle_config_init(&cfg);
393 set_cfg_value(is_max, total, 1);
394 g_assert(throttle_is_valid(&cfg, NULL));
396 throttle_config_init(&cfg);
397 set_cfg_value(is_max, read, 1);
398 set_cfg_value(is_max, write, 1);
399 g_assert(throttle_is_valid(&cfg, NULL));
402 static void test_conflicting_config(void)
404 /* bps average conflicts */
405 test_conflicts_for_one_set(false,
406 THROTTLE_BPS_TOTAL,
407 THROTTLE_BPS_READ,
408 THROTTLE_BPS_WRITE);
410 /* ops average conflicts */
411 test_conflicts_for_one_set(false,
412 THROTTLE_OPS_TOTAL,
413 THROTTLE_OPS_READ,
414 THROTTLE_OPS_WRITE);
416 /* bps average conflicts */
417 test_conflicts_for_one_set(true,
418 THROTTLE_BPS_TOTAL,
419 THROTTLE_BPS_READ,
420 THROTTLE_BPS_WRITE);
421 /* ops average conflicts */
422 test_conflicts_for_one_set(true,
423 THROTTLE_OPS_TOTAL,
424 THROTTLE_OPS_READ,
425 THROTTLE_OPS_WRITE);
427 /* functions to test the throttle_is_valid function */
428 static void test_is_valid_for_value(int value, bool should_be_valid)
430 int is_max, index;
431 for (is_max = 0; is_max < 2; is_max++) {
432 for (index = 0; index < BUCKETS_COUNT; index++) {
433 throttle_config_init(&cfg);
434 set_cfg_value(is_max, index, value);
435 g_assert(throttle_is_valid(&cfg, NULL) == should_be_valid);
440 static void test_is_valid(void)
442 /* negative numbesr are invalid */
443 test_is_valid_for_value(-1, false);
444 /* zero is valid */
445 test_is_valid_for_value(0, true);
446 /* positives numbers are valid */
447 test_is_valid_for_value(1, true);
450 static void test_ranges(void)
452 int i;
454 for (i = 0; i < BUCKETS_COUNT; i++) {
455 LeakyBucket *b = &cfg.buckets[i];
456 throttle_config_init(&cfg);
458 /* avg = 0 means throttling is disabled, but the config is valid */
459 b->avg = 0;
460 g_assert(throttle_is_valid(&cfg, NULL));
461 g_assert(!throttle_enabled(&cfg));
463 /* These are valid configurations (values <= THROTTLE_VALUE_MAX) */
464 b->avg = 1;
465 g_assert(throttle_is_valid(&cfg, NULL));
467 b->avg = THROTTLE_VALUE_MAX;
468 g_assert(throttle_is_valid(&cfg, NULL));
470 b->avg = THROTTLE_VALUE_MAX;
471 b->max = THROTTLE_VALUE_MAX;
472 g_assert(throttle_is_valid(&cfg, NULL));
474 /* Values over THROTTLE_VALUE_MAX are not allowed */
475 b->avg = THROTTLE_VALUE_MAX + 1;
476 g_assert(!throttle_is_valid(&cfg, NULL));
478 b->avg = THROTTLE_VALUE_MAX;
479 b->max = THROTTLE_VALUE_MAX + 1;
480 g_assert(!throttle_is_valid(&cfg, NULL));
482 /* burst_length must be between 1 and THROTTLE_VALUE_MAX */
483 b->avg = 1;
484 b->max = 1;
485 b->burst_length = 0;
486 g_assert(!throttle_is_valid(&cfg, NULL));
488 b->avg = 1;
489 b->max = 1;
490 b->burst_length = 1;
491 g_assert(throttle_is_valid(&cfg, NULL));
493 b->avg = 1;
494 b->max = 1;
495 b->burst_length = THROTTLE_VALUE_MAX;
496 g_assert(throttle_is_valid(&cfg, NULL));
498 b->avg = 1;
499 b->max = 1;
500 b->burst_length = THROTTLE_VALUE_MAX + 1;
501 g_assert(!throttle_is_valid(&cfg, NULL));
503 /* burst_length * max cannot exceed THROTTLE_VALUE_MAX */
504 b->avg = 1;
505 b->max = 2;
506 b->burst_length = THROTTLE_VALUE_MAX / 2;
507 g_assert(throttle_is_valid(&cfg, NULL));
509 b->avg = 1;
510 b->max = 3;
511 b->burst_length = THROTTLE_VALUE_MAX / 2;
512 g_assert(!throttle_is_valid(&cfg, NULL));
514 b->avg = 1;
515 b->max = THROTTLE_VALUE_MAX;
516 b->burst_length = 1;
517 g_assert(throttle_is_valid(&cfg, NULL));
519 b->avg = 1;
520 b->max = THROTTLE_VALUE_MAX;
521 b->burst_length = 2;
522 g_assert(!throttle_is_valid(&cfg, NULL));
526 static void test_max_is_missing_limit(void)
528 int i;
530 for (i = 0; i < BUCKETS_COUNT; i++) {
531 throttle_config_init(&cfg);
532 cfg.buckets[i].max = 100;
533 cfg.buckets[i].avg = 0;
534 g_assert(!throttle_is_valid(&cfg, NULL));
536 cfg.buckets[i].max = 0;
537 cfg.buckets[i].avg = 0;
538 g_assert(throttle_is_valid(&cfg, NULL));
540 cfg.buckets[i].max = 0;
541 cfg.buckets[i].avg = 100;
542 g_assert(throttle_is_valid(&cfg, NULL));
544 cfg.buckets[i].max = 30;
545 cfg.buckets[i].avg = 100;
546 g_assert(!throttle_is_valid(&cfg, NULL));
548 cfg.buckets[i].max = 100;
549 cfg.buckets[i].avg = 100;
550 g_assert(throttle_is_valid(&cfg, NULL));
554 static void test_iops_size_is_missing_limit(void)
556 /* A total/read/write iops limit is required */
557 throttle_config_init(&cfg);
558 cfg.op_size = 4096;
559 g_assert(!throttle_is_valid(&cfg, NULL));
562 static void test_have_timer(void)
564 /* zero structures */
565 memset(&ts, 0, sizeof(ts));
566 memset(tt, 0, sizeof(*tt));
568 /* no timer set should return false */
569 g_assert(!throttle_timers_are_initialized(tt));
571 /* init structures */
572 throttle_init(&ts);
573 throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
574 read_timer_cb, write_timer_cb, &ts);
576 /* timer set by init should return true */
577 g_assert(throttle_timers_are_initialized(tt));
579 throttle_timers_destroy(tt);
582 static void test_detach_attach(void)
584 /* zero structures */
585 memset(&ts, 0, sizeof(ts));
586 memset(tt, 0, sizeof(*tt));
588 /* init the structure */
589 throttle_init(&ts);
590 throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
591 read_timer_cb, write_timer_cb, &ts);
593 /* timer set by init should return true */
594 g_assert(throttle_timers_are_initialized(tt));
596 /* timer should no longer exist after detaching */
597 throttle_timers_detach_aio_context(tt);
598 g_assert(!throttle_timers_are_initialized(tt));
600 /* timer should exist again after attaching */
601 throttle_timers_attach_aio_context(tt, ctx);
602 g_assert(throttle_timers_are_initialized(tt));
604 throttle_timers_destroy(tt);
607 static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
608 int size, /* size of the operation to do */
609 double avg, /* io limit */
610 uint64_t op_size, /* ideal size of an io */
611 double total_result,
612 double read_result,
613 double write_result)
615 BucketType to_test[2][3] = { { THROTTLE_BPS_TOTAL,
616 THROTTLE_BPS_READ,
617 THROTTLE_BPS_WRITE, },
618 { THROTTLE_OPS_TOTAL,
619 THROTTLE_OPS_READ,
620 THROTTLE_OPS_WRITE, } };
621 BucketType index;
622 int i;
624 throttle_config_init(&cfg);
626 for (i = 0; i < 3; i++) {
627 index = to_test[is_ops][i];
628 cfg.buckets[index].avg = avg;
631 cfg.op_size = op_size;
633 throttle_init(&ts);
634 throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
635 read_timer_cb, write_timer_cb, &ts);
636 throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &cfg);
638 /* account a read */
639 throttle_account(&ts, THROTTLE_READ, size);
640 /* account a write */
641 throttle_account(&ts, THROTTLE_WRITE, size);
643 /* check total result */
644 index = to_test[is_ops][0];
645 if (!double_cmp(ts.cfg.buckets[index].level, total_result)) {
646 return false;
649 /* check read result */
650 index = to_test[is_ops][1];
651 if (!double_cmp(ts.cfg.buckets[index].level, read_result)) {
652 return false;
655 /* check write result */
656 index = to_test[is_ops][2];
657 if (!double_cmp(ts.cfg.buckets[index].level, write_result)) {
658 return false;
661 throttle_timers_destroy(tt);
663 return true;
666 static void test_accounting(void)
668 /* tests for bps */
670 /* op of size 1 */
671 g_assert(do_test_accounting(false,
672 1 * 512,
673 150,
675 1024,
676 512,
677 512));
679 /* op of size 2 */
680 g_assert(do_test_accounting(false,
681 2 * 512,
682 150,
684 2048,
685 1024,
686 1024));
688 /* op of size 2 and orthogonal parameter change */
689 g_assert(do_test_accounting(false,
690 2 * 512,
691 150,
693 2048,
694 1024,
695 1024));
698 /* tests for ops */
700 /* op of size 1 */
701 g_assert(do_test_accounting(true,
702 1 * 512,
703 150,
707 1));
709 /* op of size 2 */
710 g_assert(do_test_accounting(true,
711 2 * 512,
712 150,
716 1));
718 /* jumbo op accounting fragmentation : size 64 with op size of 13 units */
719 g_assert(do_test_accounting(true,
720 64 * 512,
721 150,
722 13 * 512,
723 (64.0 * 2) / 13,
724 (64.0 / 13),
725 (64.0 / 13)));
727 /* same with orthogonal parameters changes */
728 g_assert(do_test_accounting(true,
729 64 * 512,
730 300,
731 13 * 512,
732 (64.0 * 2) / 13,
733 (64.0 / 13),
734 (64.0 / 13)));
737 static void test_groups(void)
739 ThrottleConfig cfg1, cfg2;
740 BlockBackend *blk1, *blk2, *blk3;
741 BlockBackendPublic *blkp1, *blkp2, *blkp3;
742 ThrottleGroupMember *tgm1, *tgm2, *tgm3;
744 /* No actual I/O is performed on these devices */
745 blk1 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
746 blk2 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
747 blk3 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
749 blkp1 = blk_get_public(blk1);
750 blkp2 = blk_get_public(blk2);
751 blkp3 = blk_get_public(blk3);
753 tgm1 = &blkp1->throttle_group_member;
754 tgm2 = &blkp2->throttle_group_member;
755 tgm3 = &blkp3->throttle_group_member;
757 g_assert(tgm1->throttle_state == NULL);
758 g_assert(tgm2->throttle_state == NULL);
759 g_assert(tgm3->throttle_state == NULL);
761 throttle_group_register_tgm(tgm1, "bar", blk_get_aio_context(blk1));
762 throttle_group_register_tgm(tgm2, "foo", blk_get_aio_context(blk2));
763 throttle_group_register_tgm(tgm3, "bar", blk_get_aio_context(blk3));
765 g_assert(tgm1->throttle_state != NULL);
766 g_assert(tgm2->throttle_state != NULL);
767 g_assert(tgm3->throttle_state != NULL);
769 g_assert(!strcmp(throttle_group_get_name(tgm1), "bar"));
770 g_assert(!strcmp(throttle_group_get_name(tgm2), "foo"));
771 g_assert(tgm1->throttle_state == tgm3->throttle_state);
773 /* Setting the config of a group member affects the whole group */
774 throttle_config_init(&cfg1);
775 cfg1.buckets[THROTTLE_BPS_READ].avg = 500000;
776 cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000;
777 cfg1.buckets[THROTTLE_OPS_READ].avg = 20000;
778 cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000;
779 throttle_group_config(tgm1, &cfg1);
781 throttle_group_get_config(tgm1, &cfg1);
782 throttle_group_get_config(tgm3, &cfg2);
783 g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
785 cfg2.buckets[THROTTLE_BPS_READ].avg = 4547;
786 cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349;
787 cfg2.buckets[THROTTLE_OPS_READ].avg = 123;
788 cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86;
789 throttle_group_config(tgm3, &cfg1);
791 throttle_group_get_config(tgm1, &cfg1);
792 throttle_group_get_config(tgm3, &cfg2);
793 g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
795 throttle_group_unregister_tgm(tgm1);
796 throttle_group_unregister_tgm(tgm2);
797 throttle_group_unregister_tgm(tgm3);
799 g_assert(tgm1->throttle_state == NULL);
800 g_assert(tgm2->throttle_state == NULL);
801 g_assert(tgm3->throttle_state == NULL);
804 int main(int argc, char **argv)
806 qemu_init_main_loop(&error_fatal);
807 ctx = qemu_get_aio_context();
808 bdrv_init();
809 module_call_init(MODULE_INIT_QOM);
811 do {} while (g_main_context_iteration(NULL, false));
813 /* tests in the same order as the header function declarations */
814 g_test_init(&argc, &argv, NULL);
815 g_test_add_func("/throttle/leak_bucket", test_leak_bucket);
816 g_test_add_func("/throttle/compute_wait", test_compute_wait);
817 g_test_add_func("/throttle/init", test_init);
818 g_test_add_func("/throttle/init_readonly", test_init_readonly);
819 g_test_add_func("/throttle/init_writeonly", test_init_writeonly);
820 g_test_add_func("/throttle/destroy", test_destroy);
821 g_test_add_func("/throttle/have_timer", test_have_timer);
822 g_test_add_func("/throttle/detach_attach", test_detach_attach);
823 g_test_add_func("/throttle/config/enabled", test_enabled);
824 g_test_add_func("/throttle/config/conflicting", test_conflicting_config);
825 g_test_add_func("/throttle/config/is_valid", test_is_valid);
826 g_test_add_func("/throttle/config/ranges", test_ranges);
827 g_test_add_func("/throttle/config/max", test_max_is_missing_limit);
828 g_test_add_func("/throttle/config/iops_size",
829 test_iops_size_is_missing_limit);
830 g_test_add_func("/throttle/config_functions", test_config_functions);
831 g_test_add_func("/throttle/accounting", test_accounting);
832 g_test_add_func("/throttle/groups", test_groups);
833 return g_test_run();