1f17cfe81SBenoît Canet /*
2f17cfe81SBenoît Canet * Throttle infrastructure tests
3f17cfe81SBenoît Canet *
41fee955fSAlberto Garcia * Copyright Nodalink, EURL. 2013-2014
51fee955fSAlberto Garcia * Copyright Igalia, S.L. 2015
6f17cfe81SBenoît Canet *
7f17cfe81SBenoît Canet * Authors:
81fee955fSAlberto Garcia * Benoît Canet <benoit.canet@nodalink.com>
91fee955fSAlberto Garcia * Alberto Garcia <berto@igalia.com>
10f17cfe81SBenoît Canet *
11f17cfe81SBenoît Canet * This work is licensed under the terms of the GNU LGPL, version 2 or later.
12f17cfe81SBenoît Canet * See the COPYING.LIB file in the top-level directory.
13f17cfe81SBenoît Canet */
14f17cfe81SBenoît Canet
15681c28a3SPeter Maydell #include "qemu/osdep.h"
16f17cfe81SBenoît Canet #include <math.h>
1713af91ebSStefan Hajnoczi #include "block/aio.h"
18da34e65cSMarkus Armbruster #include "qapi/error.h"
19f17cfe81SBenoît Canet #include "qemu/throttle.h"
202f78e491SChrysostomos Nanakos #include "qemu/error-report.h"
21db725815SMarkus Armbruster #include "qemu/main-loop.h"
220b8fa32fSMarkus Armbruster #include "qemu/module.h"
231fee955fSAlberto Garcia #include "block/throttle-groups.h"
24*32cad1ffSPhilippe Mathieu-Daudé #include "system/block-backend.h"
25f17cfe81SBenoît Canet
26748bfb4eSStefan Weil static AioContext *ctx;
27748bfb4eSStefan Weil static LeakyBucket bkt;
28748bfb4eSStefan Weil static ThrottleConfig cfg;
29c61791fcSManos Pitsidianakis static ThrottleGroupMember tgm;
30748bfb4eSStefan Weil static ThrottleState ts;
31c61791fcSManos Pitsidianakis static ThrottleTimers *tt;
32f17cfe81SBenoît Canet
3373f395faSStefan Weil /* useful function */
double_cmp(double x,double y)34f17cfe81SBenoît Canet static bool double_cmp(double x, double y)
35f17cfe81SBenoît Canet {
36f17cfe81SBenoît Canet return fabsl(x - y) < 1e-6;
37f17cfe81SBenoît Canet }
38f17cfe81SBenoît Canet
39f17cfe81SBenoît Canet /* tests for single bucket operations */
test_leak_bucket(void)40f17cfe81SBenoît Canet static void test_leak_bucket(void)
41f17cfe81SBenoît Canet {
421588ab5dSAlberto Garcia throttle_config_init(&cfg);
431588ab5dSAlberto Garcia bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
441588ab5dSAlberto Garcia
45f17cfe81SBenoît Canet /* set initial value */
46f17cfe81SBenoît Canet bkt.avg = 150;
47f17cfe81SBenoît Canet bkt.max = 15;
48f17cfe81SBenoît Canet bkt.level = 1.5;
49f17cfe81SBenoît Canet
50f17cfe81SBenoît Canet /* leak an op work of time */
5113566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
52f17cfe81SBenoît Canet g_assert(bkt.avg == 150);
53f17cfe81SBenoît Canet g_assert(bkt.max == 15);
54f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0.5));
55f17cfe81SBenoît Canet
56f17cfe81SBenoît Canet /* leak again emptying the bucket */
5713566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
58f17cfe81SBenoît Canet g_assert(bkt.avg == 150);
59f17cfe81SBenoît Canet g_assert(bkt.max == 15);
60f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0));
61f17cfe81SBenoît Canet
62f17cfe81SBenoît Canet /* check that the bucket level won't go lower */
6313566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
64f17cfe81SBenoît Canet g_assert(bkt.avg == 150);
65f17cfe81SBenoît Canet g_assert(bkt.max == 15);
66f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0));
67eb8a1a1cSAlberto Garcia
68eb8a1a1cSAlberto Garcia /* check that burst_level leaks correctly */
69eb8a1a1cSAlberto Garcia bkt.burst_level = 6;
70eb8a1a1cSAlberto Garcia bkt.max = 250;
71eb8a1a1cSAlberto Garcia bkt.burst_length = 2; /* otherwise burst_level will not leak */
72eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
73eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 3.5));
74eb8a1a1cSAlberto Garcia
75eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
76eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 1));
77eb8a1a1cSAlberto Garcia
78eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
79eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 0));
80eb8a1a1cSAlberto Garcia
81eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
82eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 0));
83f17cfe81SBenoît Canet }
84f17cfe81SBenoît Canet
test_compute_wait(void)85f17cfe81SBenoît Canet static void test_compute_wait(void)
86f17cfe81SBenoît Canet {
87f9d05885SAlberto Garcia unsigned i;
88f17cfe81SBenoît Canet int64_t wait;
89f17cfe81SBenoît Canet int64_t result;
90f17cfe81SBenoît Canet
911588ab5dSAlberto Garcia throttle_config_init(&cfg);
921588ab5dSAlberto Garcia bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
931588ab5dSAlberto Garcia
94f17cfe81SBenoît Canet /* no operation limit set */
95f17cfe81SBenoît Canet bkt.avg = 0;
96f17cfe81SBenoît Canet bkt.max = 15;
97f17cfe81SBenoît Canet bkt.level = 1.5;
98f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt);
99f17cfe81SBenoît Canet g_assert(!wait);
100f17cfe81SBenoît Canet
101f17cfe81SBenoît Canet /* zero delta */
102f17cfe81SBenoît Canet bkt.avg = 150;
103f17cfe81SBenoît Canet bkt.max = 15;
104f17cfe81SBenoît Canet bkt.level = 15;
105f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt);
106f17cfe81SBenoît Canet g_assert(!wait);
107f17cfe81SBenoît Canet
108f17cfe81SBenoît Canet /* below zero delta */
109f17cfe81SBenoît Canet bkt.avg = 150;
110f17cfe81SBenoît Canet bkt.max = 15;
111f17cfe81SBenoît Canet bkt.level = 9;
112f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt);
113f17cfe81SBenoît Canet g_assert(!wait);
114f17cfe81SBenoît Canet
115f17cfe81SBenoît Canet /* half an operation above max */
116f17cfe81SBenoît Canet bkt.avg = 150;
117f17cfe81SBenoît Canet bkt.max = 15;
118f17cfe81SBenoît Canet bkt.level = 15.5;
119f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt);
120f17cfe81SBenoît Canet /* time required to do half an operation */
12113566fe3SStefan Hajnoczi result = (int64_t) NANOSECONDS_PER_SECOND / 150 / 2;
122f17cfe81SBenoît Canet g_assert(wait == result);
123f9d05885SAlberto Garcia
124f9d05885SAlberto Garcia /* Perform I/O for 2.2 seconds at a rate of bkt.max */
125f9d05885SAlberto Garcia bkt.burst_length = 2;
126f9d05885SAlberto Garcia bkt.level = 0;
127f9d05885SAlberto Garcia bkt.avg = 10;
128f9d05885SAlberto Garcia bkt.max = 200;
129f9d05885SAlberto Garcia for (i = 0; i < 22; i++) {
13043199b13SPeter Maydell double units = bkt.max / 10.0;
131f9d05885SAlberto Garcia bkt.level += units;
132f9d05885SAlberto Garcia bkt.burst_level += units;
133f9d05885SAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 10);
134f9d05885SAlberto Garcia wait = throttle_compute_wait(&bkt);
135f9d05885SAlberto Garcia g_assert(double_cmp(bkt.burst_level, 0));
13643199b13SPeter Maydell g_assert(double_cmp(bkt.level, (i + 1) * (bkt.max - bkt.avg) / 10.0));
137f9d05885SAlberto Garcia /* We can do bursts for the 2 seconds we have configured in
13896420a30SMichael Tokarev * burst_length. We have 100 extra milliseconds of burst
139f9d05885SAlberto Garcia * because bkt.level has been leaking during this time.
140f9d05885SAlberto Garcia * After that, we have to wait. */
141f9d05885SAlberto Garcia result = i < 21 ? 0 : 1.8 * NANOSECONDS_PER_SECOND;
142f9d05885SAlberto Garcia g_assert(wait == result);
143f9d05885SAlberto Garcia }
144f17cfe81SBenoît Canet }
145f17cfe81SBenoît Canet
146f17cfe81SBenoît Canet /* functions to test ThrottleState initialization/destroy methods */
read_timer_cb(void * opaque)147f17cfe81SBenoît Canet static void read_timer_cb(void *opaque)
148f17cfe81SBenoît Canet {
149f17cfe81SBenoît Canet }
150f17cfe81SBenoît Canet
write_timer_cb(void * opaque)151f17cfe81SBenoît Canet static void write_timer_cb(void *opaque)
152f17cfe81SBenoît Canet {
153f17cfe81SBenoît Canet }
154f17cfe81SBenoît Canet
test_init(void)155f17cfe81SBenoît Canet static void test_init(void)
156f17cfe81SBenoît Canet {
157f17cfe81SBenoît Canet int i;
158f17cfe81SBenoît Canet
159c61791fcSManos Pitsidianakis tt = &tgm.throttle_timers;
160c61791fcSManos Pitsidianakis
1610e5b0a2dSBenoît Canet /* fill the structures with crap */
162f17cfe81SBenoît Canet memset(&ts, 1, sizeof(ts));
163c61791fcSManos Pitsidianakis memset(tt, 1, sizeof(*tt));
164f17cfe81SBenoît Canet
1650e5b0a2dSBenoît Canet /* init structures */
1660e5b0a2dSBenoît Canet throttle_init(&ts);
167c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
16813af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts);
169f17cfe81SBenoît Canet
170f17cfe81SBenoît Canet /* check initialized fields */
171c61791fcSManos Pitsidianakis g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
1721322f63dSzhenwei pi g_assert(tt->timers[THROTTLE_READ]);
1731322f63dSzhenwei pi g_assert(tt->timers[THROTTLE_WRITE]);
174f17cfe81SBenoît Canet
175f17cfe81SBenoît Canet /* check other fields where cleared */
176f17cfe81SBenoît Canet g_assert(!ts.previous_leak);
177f17cfe81SBenoît Canet g_assert(!ts.cfg.op_size);
178f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) {
179f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].avg);
180f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].max);
181f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].level);
182f17cfe81SBenoît Canet }
183f17cfe81SBenoît Canet
184c61791fcSManos Pitsidianakis throttle_timers_destroy(tt);
185f17cfe81SBenoît Canet }
186f17cfe81SBenoît Canet
test_init_readonly(void)18702add531Szhenwei pi static void test_init_readonly(void)
18802add531Szhenwei pi {
18902add531Szhenwei pi int i;
19002add531Szhenwei pi
19102add531Szhenwei pi tt = &tgm.throttle_timers;
19202add531Szhenwei pi
19302add531Szhenwei pi /* fill the structures with crap */
19402add531Szhenwei pi memset(&ts, 1, sizeof(ts));
19502add531Szhenwei pi memset(tt, 1, sizeof(*tt));
19602add531Szhenwei pi
19702add531Szhenwei pi /* init structures */
19802add531Szhenwei pi throttle_init(&ts);
19902add531Szhenwei pi throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
20002add531Szhenwei pi read_timer_cb, NULL, &ts);
20102add531Szhenwei pi
20202add531Szhenwei pi /* check initialized fields */
20302add531Szhenwei pi g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
20402add531Szhenwei pi g_assert(tt->timers[THROTTLE_READ]);
20502add531Szhenwei pi g_assert(!tt->timers[THROTTLE_WRITE]);
20602add531Szhenwei pi
20702add531Szhenwei pi /* check other fields where cleared */
20802add531Szhenwei pi g_assert(!ts.previous_leak);
20902add531Szhenwei pi g_assert(!ts.cfg.op_size);
21002add531Szhenwei pi for (i = 0; i < BUCKETS_COUNT; i++) {
21102add531Szhenwei pi g_assert(!ts.cfg.buckets[i].avg);
21202add531Szhenwei pi g_assert(!ts.cfg.buckets[i].max);
21302add531Szhenwei pi g_assert(!ts.cfg.buckets[i].level);
21402add531Szhenwei pi }
21502add531Szhenwei pi
21602add531Szhenwei pi throttle_timers_destroy(tt);
21702add531Szhenwei pi }
21802add531Szhenwei pi
test_init_writeonly(void)21902add531Szhenwei pi static void test_init_writeonly(void)
22002add531Szhenwei pi {
22102add531Szhenwei pi int i;
22202add531Szhenwei pi
22302add531Szhenwei pi tt = &tgm.throttle_timers;
22402add531Szhenwei pi
22502add531Szhenwei pi /* fill the structures with crap */
22602add531Szhenwei pi memset(&ts, 1, sizeof(ts));
22702add531Szhenwei pi memset(tt, 1, sizeof(*tt));
22802add531Szhenwei pi
22902add531Szhenwei pi /* init structures */
23002add531Szhenwei pi throttle_init(&ts);
23102add531Szhenwei pi throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
23202add531Szhenwei pi NULL, write_timer_cb, &ts);
23302add531Szhenwei pi
23402add531Szhenwei pi /* check initialized fields */
23502add531Szhenwei pi g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
23602add531Szhenwei pi g_assert(!tt->timers[THROTTLE_READ]);
23702add531Szhenwei pi g_assert(tt->timers[THROTTLE_WRITE]);
238f17cfe81SBenoît Canet
239f17cfe81SBenoît Canet /* check other fields where cleared */
240f17cfe81SBenoît Canet g_assert(!ts.previous_leak);
241f17cfe81SBenoît Canet g_assert(!ts.cfg.op_size);
242f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) {
243f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].avg);
244f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].max);
245f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].level);
246f17cfe81SBenoît Canet }
247f17cfe81SBenoît Canet
248f17cfe81SBenoît Canet throttle_timers_destroy(tt);
249f17cfe81SBenoît Canet }
250f17cfe81SBenoît Canet
test_destroy(void)251f17cfe81SBenoît Canet static void test_destroy(void)
252f17cfe81SBenoît Canet {
253f17cfe81SBenoît Canet int i;
2540e5b0a2dSBenoît Canet throttle_init(&ts);
255c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
25613af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts);
257c61791fcSManos Pitsidianakis throttle_timers_destroy(tt);
2581322f63dSzhenwei pi for (i = 0; i < THROTTLE_MAX; i++) {
259c61791fcSManos Pitsidianakis g_assert(!tt->timers[i]);
260f17cfe81SBenoît Canet }
261f17cfe81SBenoît Canet }
262f17cfe81SBenoît Canet
263f17cfe81SBenoît Canet /* function to test throttle_config and throttle_get_config */
test_config_functions(void)264f17cfe81SBenoît Canet static void test_config_functions(void)
265f17cfe81SBenoît Canet {
266f17cfe81SBenoît Canet int i;
267f17cfe81SBenoît Canet ThrottleConfig orig_cfg, final_cfg;
268f17cfe81SBenoît Canet
269f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_TOTAL].avg = 153;
270f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_READ].avg = 56;
271f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].avg = 1;
272f17cfe81SBenoît Canet
273f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].avg = 150;
274f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].avg = 69;
275f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].avg = 23;
276f17cfe81SBenoît Canet
277d72915c6SStefan Hajnoczi orig_cfg.buckets[THROTTLE_BPS_TOTAL].max = 0;
278d72915c6SStefan Hajnoczi orig_cfg.buckets[THROTTLE_BPS_READ].max = 56;
279f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].max = 120;
280f17cfe81SBenoît Canet
281f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].max = 150;
282f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].max = 400;
283f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].max = 500;
284f17cfe81SBenoît Canet
285f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_TOTAL].level = 45;
286f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_READ].level = 65;
287f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].level = 23;
288f17cfe81SBenoît Canet
289f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].level = 1;
290f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].level = 90;
291f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].level = 75;
292f17cfe81SBenoît Canet
293f17cfe81SBenoît Canet orig_cfg.op_size = 1;
294f17cfe81SBenoît Canet
2950e5b0a2dSBenoît Canet throttle_init(&ts);
296c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
29713af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts);
298f17cfe81SBenoît Canet /* structure reset by throttle_init previous_leak should be null */
299f17cfe81SBenoît Canet g_assert(!ts.previous_leak);
30027e4cf13SManos Pitsidianakis throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &orig_cfg);
301f17cfe81SBenoît Canet
302f17cfe81SBenoît Canet /* has previous leak been initialized by throttle_config ? */
303f17cfe81SBenoît Canet g_assert(ts.previous_leak);
304f17cfe81SBenoît Canet
305f17cfe81SBenoît Canet /* get back the fixed configuration */
306f17cfe81SBenoît Canet throttle_get_config(&ts, &final_cfg);
307f17cfe81SBenoît Canet
308c61791fcSManos Pitsidianakis throttle_timers_destroy(tt);
309f17cfe81SBenoît Canet
310f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153);
311f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg == 56);
312f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].avg == 1);
313f17cfe81SBenoît Canet
314f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].avg == 150);
315f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_READ].avg == 69);
316f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].avg == 23);
317f17cfe81SBenoît Canet
318d72915c6SStefan Hajnoczi g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].max == 0);
319d72915c6SStefan Hajnoczi g_assert(final_cfg.buckets[THROTTLE_BPS_READ].max == 56);
320f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].max == 120);
321f17cfe81SBenoît Canet
322f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].max == 150);
323f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_READ].max == 400);
324f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].max == 500);
325f17cfe81SBenoît Canet
326f17cfe81SBenoît Canet g_assert(final_cfg.op_size == 1);
327f17cfe81SBenoît Canet
328f17cfe81SBenoît Canet /* check bucket have been cleared */
329f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) {
330f17cfe81SBenoît Canet g_assert(!final_cfg.buckets[i].level);
331f17cfe81SBenoît Canet }
332f17cfe81SBenoît Canet }
333f17cfe81SBenoît Canet
334f17cfe81SBenoît Canet /* functions to test is throttle is enabled by a config */
set_cfg_value(bool is_max,int index,int value)335f17cfe81SBenoît Canet static void set_cfg_value(bool is_max, int index, int value)
336f17cfe81SBenoît Canet {
337f17cfe81SBenoît Canet if (is_max) {
338f17cfe81SBenoît Canet cfg.buckets[index].max = value;
3396f9b6d57SAlberto Garcia /* If max is set, avg should never be 0 */
3406f9b6d57SAlberto Garcia cfg.buckets[index].avg = MAX(cfg.buckets[index].avg, 1);
341f17cfe81SBenoît Canet } else {
342f17cfe81SBenoît Canet cfg.buckets[index].avg = value;
343f17cfe81SBenoît Canet }
344f17cfe81SBenoît Canet }
345f17cfe81SBenoît Canet
test_enabled(void)346f17cfe81SBenoît Canet static void test_enabled(void)
347f17cfe81SBenoît Canet {
348f17cfe81SBenoît Canet int i;
349f17cfe81SBenoît Canet
3501588ab5dSAlberto Garcia throttle_config_init(&cfg);
351f17cfe81SBenoît Canet g_assert(!throttle_enabled(&cfg));
352f17cfe81SBenoît Canet
353f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) {
3541588ab5dSAlberto Garcia throttle_config_init(&cfg);
355f17cfe81SBenoît Canet set_cfg_value(false, i, 150);
356d00e6923SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
357f17cfe81SBenoît Canet g_assert(throttle_enabled(&cfg));
358f17cfe81SBenoît Canet }
359f17cfe81SBenoît Canet
360f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) {
3611588ab5dSAlberto Garcia throttle_config_init(&cfg);
362f17cfe81SBenoît Canet set_cfg_value(false, i, -150);
363d00e6923SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
364f17cfe81SBenoît Canet }
365f17cfe81SBenoît Canet }
366f17cfe81SBenoît Canet
367f17cfe81SBenoît Canet /* tests functions for throttle_conflicting */
368f17cfe81SBenoît Canet
test_conflicts_for_one_set(bool is_max,int total,int read,int write)369f17cfe81SBenoît Canet static void test_conflicts_for_one_set(bool is_max,
370f17cfe81SBenoît Canet int total,
371f17cfe81SBenoît Canet int read,
372f17cfe81SBenoît Canet int write)
373f17cfe81SBenoît Canet {
3741588ab5dSAlberto Garcia throttle_config_init(&cfg);
375d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
376f17cfe81SBenoît Canet
377f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1);
378f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1);
379d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
380f17cfe81SBenoît Canet
3811588ab5dSAlberto Garcia throttle_config_init(&cfg);
382f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1);
383f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1);
384d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
385f17cfe81SBenoît Canet
3861588ab5dSAlberto Garcia throttle_config_init(&cfg);
387f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1);
388f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1);
389f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1);
390d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
391f17cfe81SBenoît Canet
3921588ab5dSAlberto Garcia throttle_config_init(&cfg);
393f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1);
394d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
395f17cfe81SBenoît Canet
3961588ab5dSAlberto Garcia throttle_config_init(&cfg);
397f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1);
398f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1);
399d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
400f17cfe81SBenoît Canet }
401f17cfe81SBenoît Canet
test_conflicting_config(void)402f17cfe81SBenoît Canet static void test_conflicting_config(void)
403f17cfe81SBenoît Canet {
404f17cfe81SBenoît Canet /* bps average conflicts */
405f17cfe81SBenoît Canet test_conflicts_for_one_set(false,
406f17cfe81SBenoît Canet THROTTLE_BPS_TOTAL,
407f17cfe81SBenoît Canet THROTTLE_BPS_READ,
408f17cfe81SBenoît Canet THROTTLE_BPS_WRITE);
409f17cfe81SBenoît Canet
410f17cfe81SBenoît Canet /* ops average conflicts */
411f17cfe81SBenoît Canet test_conflicts_for_one_set(false,
412f17cfe81SBenoît Canet THROTTLE_OPS_TOTAL,
413f17cfe81SBenoît Canet THROTTLE_OPS_READ,
414f17cfe81SBenoît Canet THROTTLE_OPS_WRITE);
415f17cfe81SBenoît Canet
416f17cfe81SBenoît Canet /* bps average conflicts */
417f17cfe81SBenoît Canet test_conflicts_for_one_set(true,
418f17cfe81SBenoît Canet THROTTLE_BPS_TOTAL,
419f17cfe81SBenoît Canet THROTTLE_BPS_READ,
420f17cfe81SBenoît Canet THROTTLE_BPS_WRITE);
421f17cfe81SBenoît Canet /* ops average conflicts */
422f17cfe81SBenoît Canet test_conflicts_for_one_set(true,
423f17cfe81SBenoît Canet THROTTLE_OPS_TOTAL,
424f17cfe81SBenoît Canet THROTTLE_OPS_READ,
425f17cfe81SBenoît Canet THROTTLE_OPS_WRITE);
426f17cfe81SBenoît Canet }
427f17cfe81SBenoît Canet /* functions to test the throttle_is_valid function */
test_is_valid_for_value(int value,bool should_be_valid)428f17cfe81SBenoît Canet static void test_is_valid_for_value(int value, bool should_be_valid)
429f17cfe81SBenoît Canet {
430f17cfe81SBenoît Canet int is_max, index;
431f17cfe81SBenoît Canet for (is_max = 0; is_max < 2; is_max++) {
432f17cfe81SBenoît Canet for (index = 0; index < BUCKETS_COUNT; index++) {
4331588ab5dSAlberto Garcia throttle_config_init(&cfg);
434f17cfe81SBenoît Canet set_cfg_value(is_max, index, value);
43503ba36c8SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL) == should_be_valid);
436f17cfe81SBenoît Canet }
437f17cfe81SBenoît Canet }
438f17cfe81SBenoît Canet }
439f17cfe81SBenoît Canet
test_is_valid(void)440f17cfe81SBenoît Canet static void test_is_valid(void)
441f17cfe81SBenoît Canet {
44296420a30SMichael Tokarev /* negative numbesr are invalid */
443f17cfe81SBenoît Canet test_is_valid_for_value(-1, false);
44496420a30SMichael Tokarev /* zero is valid */
445f17cfe81SBenoît Canet test_is_valid_for_value(0, true);
44696420a30SMichael Tokarev /* positives numbers are valid */
447f17cfe81SBenoît Canet test_is_valid_for_value(1, true);
448f17cfe81SBenoît Canet }
449f17cfe81SBenoît Canet
test_ranges(void)450d942feecSAlberto Garcia static void test_ranges(void)
451d942feecSAlberto Garcia {
452d942feecSAlberto Garcia int i;
453d942feecSAlberto Garcia
454d942feecSAlberto Garcia for (i = 0; i < BUCKETS_COUNT; i++) {
455d942feecSAlberto Garcia LeakyBucket *b = &cfg.buckets[i];
456d942feecSAlberto Garcia throttle_config_init(&cfg);
457d942feecSAlberto Garcia
458d942feecSAlberto Garcia /* avg = 0 means throttling is disabled, but the config is valid */
459d942feecSAlberto Garcia b->avg = 0;
460d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
461d942feecSAlberto Garcia g_assert(!throttle_enabled(&cfg));
462d942feecSAlberto Garcia
463d942feecSAlberto Garcia /* These are valid configurations (values <= THROTTLE_VALUE_MAX) */
464d942feecSAlberto Garcia b->avg = 1;
465d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
466d942feecSAlberto Garcia
467d942feecSAlberto Garcia b->avg = THROTTLE_VALUE_MAX;
468d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
469d942feecSAlberto Garcia
470d942feecSAlberto Garcia b->avg = THROTTLE_VALUE_MAX;
471d942feecSAlberto Garcia b->max = THROTTLE_VALUE_MAX;
472d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
473d942feecSAlberto Garcia
474d942feecSAlberto Garcia /* Values over THROTTLE_VALUE_MAX are not allowed */
475d942feecSAlberto Garcia b->avg = THROTTLE_VALUE_MAX + 1;
476d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
477d942feecSAlberto Garcia
478d942feecSAlberto Garcia b->avg = THROTTLE_VALUE_MAX;
479d942feecSAlberto Garcia b->max = THROTTLE_VALUE_MAX + 1;
480d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
481d942feecSAlberto Garcia
482d942feecSAlberto Garcia /* burst_length must be between 1 and THROTTLE_VALUE_MAX */
483d942feecSAlberto Garcia b->avg = 1;
484d942feecSAlberto Garcia b->max = 1;
485d942feecSAlberto Garcia b->burst_length = 0;
486d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
487d942feecSAlberto Garcia
488d942feecSAlberto Garcia b->avg = 1;
489d942feecSAlberto Garcia b->max = 1;
490d942feecSAlberto Garcia b->burst_length = 1;
491d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
492d942feecSAlberto Garcia
493d942feecSAlberto Garcia b->avg = 1;
494d942feecSAlberto Garcia b->max = 1;
495d942feecSAlberto Garcia b->burst_length = THROTTLE_VALUE_MAX;
496d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
497d942feecSAlberto Garcia
498d942feecSAlberto Garcia b->avg = 1;
499d942feecSAlberto Garcia b->max = 1;
500d942feecSAlberto Garcia b->burst_length = THROTTLE_VALUE_MAX + 1;
501d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
502d942feecSAlberto Garcia
503d942feecSAlberto Garcia /* burst_length * max cannot exceed THROTTLE_VALUE_MAX */
504d942feecSAlberto Garcia b->avg = 1;
505d942feecSAlberto Garcia b->max = 2;
506d942feecSAlberto Garcia b->burst_length = THROTTLE_VALUE_MAX / 2;
507d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
508d942feecSAlberto Garcia
509d942feecSAlberto Garcia b->avg = 1;
510d942feecSAlberto Garcia b->max = 3;
511d942feecSAlberto Garcia b->burst_length = THROTTLE_VALUE_MAX / 2;
512d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
513d942feecSAlberto Garcia
514d942feecSAlberto Garcia b->avg = 1;
515d942feecSAlberto Garcia b->max = THROTTLE_VALUE_MAX;
516d942feecSAlberto Garcia b->burst_length = 1;
517d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
518d942feecSAlberto Garcia
519d942feecSAlberto Garcia b->avg = 1;
520d942feecSAlberto Garcia b->max = THROTTLE_VALUE_MAX;
521d942feecSAlberto Garcia b->burst_length = 2;
522d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
523d942feecSAlberto Garcia }
524d942feecSAlberto Garcia }
525d942feecSAlberto Garcia
test_max_is_missing_limit(void)52692e11a17SStefan Hajnoczi static void test_max_is_missing_limit(void)
52792e11a17SStefan Hajnoczi {
52892e11a17SStefan Hajnoczi int i;
52992e11a17SStefan Hajnoczi
53092e11a17SStefan Hajnoczi for (i = 0; i < BUCKETS_COUNT; i++) {
5311588ab5dSAlberto Garcia throttle_config_init(&cfg);
53292e11a17SStefan Hajnoczi cfg.buckets[i].max = 100;
53392e11a17SStefan Hajnoczi cfg.buckets[i].avg = 0;
534d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
53592e11a17SStefan Hajnoczi
53692e11a17SStefan Hajnoczi cfg.buckets[i].max = 0;
53792e11a17SStefan Hajnoczi cfg.buckets[i].avg = 0;
538d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
53992e11a17SStefan Hajnoczi
54092e11a17SStefan Hajnoczi cfg.buckets[i].max = 0;
54192e11a17SStefan Hajnoczi cfg.buckets[i].avg = 100;
542d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
5435fc8c052SAlberto Garcia
5445fc8c052SAlberto Garcia cfg.buckets[i].max = 30;
5455fc8c052SAlberto Garcia cfg.buckets[i].avg = 100;
5465fc8c052SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL));
5475fc8c052SAlberto Garcia
5485fc8c052SAlberto Garcia cfg.buckets[i].max = 100;
5495fc8c052SAlberto Garcia cfg.buckets[i].avg = 100;
5505fc8c052SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL));
55192e11a17SStefan Hajnoczi }
55292e11a17SStefan Hajnoczi }
55392e11a17SStefan Hajnoczi
test_iops_size_is_missing_limit(void)5548860eabdSStefan Hajnoczi static void test_iops_size_is_missing_limit(void)
5558860eabdSStefan Hajnoczi {
5568860eabdSStefan Hajnoczi /* A total/read/write iops limit is required */
5578860eabdSStefan Hajnoczi throttle_config_init(&cfg);
5588860eabdSStefan Hajnoczi cfg.op_size = 4096;
5598860eabdSStefan Hajnoczi g_assert(!throttle_is_valid(&cfg, NULL));
5608860eabdSStefan Hajnoczi }
5618860eabdSStefan Hajnoczi
test_have_timer(void)562f17cfe81SBenoît Canet static void test_have_timer(void)
563f17cfe81SBenoît Canet {
5640e5b0a2dSBenoît Canet /* zero structures */
565f17cfe81SBenoît Canet memset(&ts, 0, sizeof(ts));
566c61791fcSManos Pitsidianakis memset(tt, 0, sizeof(*tt));
567f17cfe81SBenoît Canet
56873f395faSStefan Weil /* no timer set should return false */
569c61791fcSManos Pitsidianakis g_assert(!throttle_timers_are_initialized(tt));
570f17cfe81SBenoît Canet
5710e5b0a2dSBenoît Canet /* init structures */
5720e5b0a2dSBenoît Canet throttle_init(&ts);
573c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
57413af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts);
575f17cfe81SBenoît Canet
576f17cfe81SBenoît Canet /* timer set by init should return true */
577c61791fcSManos Pitsidianakis g_assert(throttle_timers_are_initialized(tt));
578f17cfe81SBenoît Canet
579c61791fcSManos Pitsidianakis throttle_timers_destroy(tt);
580f17cfe81SBenoît Canet }
581f17cfe81SBenoît Canet
test_detach_attach(void)58222524f72SStefan Hajnoczi static void test_detach_attach(void)
58322524f72SStefan Hajnoczi {
5840e5b0a2dSBenoît Canet /* zero structures */
58522524f72SStefan Hajnoczi memset(&ts, 0, sizeof(ts));
586c61791fcSManos Pitsidianakis memset(tt, 0, sizeof(*tt));
58722524f72SStefan Hajnoczi
58822524f72SStefan Hajnoczi /* init the structure */
5890e5b0a2dSBenoît Canet throttle_init(&ts);
590c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
59122524f72SStefan Hajnoczi read_timer_cb, write_timer_cb, &ts);
59222524f72SStefan Hajnoczi
59322524f72SStefan Hajnoczi /* timer set by init should return true */
594c61791fcSManos Pitsidianakis g_assert(throttle_timers_are_initialized(tt));
59522524f72SStefan Hajnoczi
59622524f72SStefan Hajnoczi /* timer should no longer exist after detaching */
597c61791fcSManos Pitsidianakis throttle_timers_detach_aio_context(tt);
598c61791fcSManos Pitsidianakis g_assert(!throttle_timers_are_initialized(tt));
59922524f72SStefan Hajnoczi
60022524f72SStefan Hajnoczi /* timer should exist again after attaching */
601c61791fcSManos Pitsidianakis throttle_timers_attach_aio_context(tt, ctx);
602c61791fcSManos Pitsidianakis g_assert(throttle_timers_are_initialized(tt));
60322524f72SStefan Hajnoczi
604c61791fcSManos Pitsidianakis throttle_timers_destroy(tt);
60522524f72SStefan Hajnoczi }
60622524f72SStefan Hajnoczi
do_test_accounting(bool is_ops,int size,double avg,uint64_t op_size,double total_result,double read_result,double write_result)607f17cfe81SBenoît Canet static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
608f17cfe81SBenoît Canet int size, /* size of the operation to do */
609f17cfe81SBenoît Canet double avg, /* io limit */
610f17cfe81SBenoît Canet uint64_t op_size, /* ideal size of an io */
611f17cfe81SBenoît Canet double total_result,
612f17cfe81SBenoît Canet double read_result,
613f17cfe81SBenoît Canet double write_result)
614f17cfe81SBenoît Canet {
615f17cfe81SBenoît Canet BucketType to_test[2][3] = { { THROTTLE_BPS_TOTAL,
616f17cfe81SBenoît Canet THROTTLE_BPS_READ,
617f17cfe81SBenoît Canet THROTTLE_BPS_WRITE, },
618f17cfe81SBenoît Canet { THROTTLE_OPS_TOTAL,
619f17cfe81SBenoît Canet THROTTLE_OPS_READ,
620f17cfe81SBenoît Canet THROTTLE_OPS_WRITE, } };
621f17cfe81SBenoît Canet BucketType index;
622f17cfe81SBenoît Canet int i;
623f17cfe81SBenoît Canet
624ef0aa6afSAndrey Shinkevich throttle_config_init(&cfg);
625ef0aa6afSAndrey Shinkevich
626f17cfe81SBenoît Canet for (i = 0; i < 3; i++) {
627d8573092SAlberto Garcia index = to_test[is_ops][i];
628f17cfe81SBenoît Canet cfg.buckets[index].avg = avg;
629f17cfe81SBenoît Canet }
630f17cfe81SBenoît Canet
631f17cfe81SBenoît Canet cfg.op_size = op_size;
632f17cfe81SBenoît Canet
6330e5b0a2dSBenoît Canet throttle_init(&ts);
634c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
63513af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts);
63627e4cf13SManos Pitsidianakis throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &cfg);
637f17cfe81SBenoît Canet
638f17cfe81SBenoît Canet /* account a read */
639e76f201fSzhenwei pi throttle_account(&ts, THROTTLE_READ, size);
640f17cfe81SBenoît Canet /* account a write */
641e76f201fSzhenwei pi throttle_account(&ts, THROTTLE_WRITE, size);
642f17cfe81SBenoît Canet
643f17cfe81SBenoît Canet /* check total result */
644f17cfe81SBenoît Canet index = to_test[is_ops][0];
645f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, total_result)) {
646f17cfe81SBenoît Canet return false;
647f17cfe81SBenoît Canet }
648f17cfe81SBenoît Canet
649f17cfe81SBenoît Canet /* check read result */
650f17cfe81SBenoît Canet index = to_test[is_ops][1];
651f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, read_result)) {
652f17cfe81SBenoît Canet return false;
653f17cfe81SBenoît Canet }
654f17cfe81SBenoît Canet
655f17cfe81SBenoît Canet /* check write result */
656f17cfe81SBenoît Canet index = to_test[is_ops][2];
657f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, write_result)) {
658f17cfe81SBenoît Canet return false;
659f17cfe81SBenoît Canet }
660f17cfe81SBenoît Canet
661c61791fcSManos Pitsidianakis throttle_timers_destroy(tt);
662f17cfe81SBenoît Canet
663f17cfe81SBenoît Canet return true;
664f17cfe81SBenoît Canet }
665f17cfe81SBenoît Canet
test_accounting(void)666f17cfe81SBenoît Canet static void test_accounting(void)
667f17cfe81SBenoît Canet {
668f17cfe81SBenoît Canet /* tests for bps */
669f17cfe81SBenoît Canet
670f17cfe81SBenoît Canet /* op of size 1 */
671f17cfe81SBenoît Canet g_assert(do_test_accounting(false,
672f17cfe81SBenoît Canet 1 * 512,
673f17cfe81SBenoît Canet 150,
674f17cfe81SBenoît Canet 0,
675f17cfe81SBenoît Canet 1024,
676f17cfe81SBenoît Canet 512,
677f17cfe81SBenoît Canet 512));
678f17cfe81SBenoît Canet
679f17cfe81SBenoît Canet /* op of size 2 */
680f17cfe81SBenoît Canet g_assert(do_test_accounting(false,
681f17cfe81SBenoît Canet 2 * 512,
682f17cfe81SBenoît Canet 150,
683f17cfe81SBenoît Canet 0,
684f17cfe81SBenoît Canet 2048,
685f17cfe81SBenoît Canet 1024,
686f17cfe81SBenoît Canet 1024));
687f17cfe81SBenoît Canet
688f17cfe81SBenoît Canet /* op of size 2 and orthogonal parameter change */
689f17cfe81SBenoît Canet g_assert(do_test_accounting(false,
690f17cfe81SBenoît Canet 2 * 512,
691f17cfe81SBenoît Canet 150,
692f17cfe81SBenoît Canet 17,
693f17cfe81SBenoît Canet 2048,
694f17cfe81SBenoît Canet 1024,
695f17cfe81SBenoît Canet 1024));
696f17cfe81SBenoît Canet
697f17cfe81SBenoît Canet
698f17cfe81SBenoît Canet /* tests for ops */
699f17cfe81SBenoît Canet
700f17cfe81SBenoît Canet /* op of size 1 */
701f17cfe81SBenoît Canet g_assert(do_test_accounting(true,
702f17cfe81SBenoît Canet 1 * 512,
703f17cfe81SBenoît Canet 150,
704f17cfe81SBenoît Canet 0,
705f17cfe81SBenoît Canet 2,
706f17cfe81SBenoît Canet 1,
707f17cfe81SBenoît Canet 1));
708f17cfe81SBenoît Canet
709f17cfe81SBenoît Canet /* op of size 2 */
710f17cfe81SBenoît Canet g_assert(do_test_accounting(true,
711f17cfe81SBenoît Canet 2 * 512,
712f17cfe81SBenoît Canet 150,
713f17cfe81SBenoît Canet 0,
714f17cfe81SBenoît Canet 2,
715f17cfe81SBenoît Canet 1,
716f17cfe81SBenoît Canet 1));
717f17cfe81SBenoît Canet
718f17cfe81SBenoît Canet /* jumbo op accounting fragmentation : size 64 with op size of 13 units */
719f17cfe81SBenoît Canet g_assert(do_test_accounting(true,
720f17cfe81SBenoît Canet 64 * 512,
721f17cfe81SBenoît Canet 150,
722f17cfe81SBenoît Canet 13 * 512,
723f17cfe81SBenoît Canet (64.0 * 2) / 13,
724f17cfe81SBenoît Canet (64.0 / 13),
725f17cfe81SBenoît Canet (64.0 / 13)));
726f17cfe81SBenoît Canet
727f17cfe81SBenoît Canet /* same with orthogonal parameters changes */
728f17cfe81SBenoît Canet g_assert(do_test_accounting(true,
729f17cfe81SBenoît Canet 64 * 512,
730f17cfe81SBenoît Canet 300,
731f17cfe81SBenoît Canet 13 * 512,
732f17cfe81SBenoît Canet (64.0 * 2) / 13,
733f17cfe81SBenoît Canet (64.0 / 13),
734f17cfe81SBenoît Canet (64.0 / 13)));
735f17cfe81SBenoît Canet }
736f17cfe81SBenoît Canet
test_groups(void)7371fee955fSAlberto Garcia static void test_groups(void)
7381fee955fSAlberto Garcia {
7391fee955fSAlberto Garcia ThrottleConfig cfg1, cfg2;
740a5614993SKevin Wolf BlockBackend *blk1, *blk2, *blk3;
74127ccdd52SKevin Wolf BlockBackendPublic *blkp1, *blkp2, *blkp3;
742022cdc9fSManos Pitsidianakis ThrottleGroupMember *tgm1, *tgm2, *tgm3;
7431fee955fSAlberto Garcia
7442807c0cdSKevin Wolf /* No actual I/O is performed on these devices */
745d861ab3aSKevin Wolf blk1 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
746d861ab3aSKevin Wolf blk2 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
747d861ab3aSKevin Wolf blk3 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
748a5614993SKevin Wolf
74927ccdd52SKevin Wolf blkp1 = blk_get_public(blk1);
75027ccdd52SKevin Wolf blkp2 = blk_get_public(blk2);
75127ccdd52SKevin Wolf blkp3 = blk_get_public(blk3);
75227ccdd52SKevin Wolf
753022cdc9fSManos Pitsidianakis tgm1 = &blkp1->throttle_group_member;
754022cdc9fSManos Pitsidianakis tgm2 = &blkp2->throttle_group_member;
755022cdc9fSManos Pitsidianakis tgm3 = &blkp3->throttle_group_member;
7561fee955fSAlberto Garcia
757022cdc9fSManos Pitsidianakis g_assert(tgm1->throttle_state == NULL);
758022cdc9fSManos Pitsidianakis g_assert(tgm2->throttle_state == NULL);
759022cdc9fSManos Pitsidianakis g_assert(tgm3->throttle_state == NULL);
7601fee955fSAlberto Garcia
761c61791fcSManos Pitsidianakis throttle_group_register_tgm(tgm1, "bar", blk_get_aio_context(blk1));
762c61791fcSManos Pitsidianakis throttle_group_register_tgm(tgm2, "foo", blk_get_aio_context(blk2));
763c61791fcSManos Pitsidianakis throttle_group_register_tgm(tgm3, "bar", blk_get_aio_context(blk3));
7641fee955fSAlberto Garcia
765022cdc9fSManos Pitsidianakis g_assert(tgm1->throttle_state != NULL);
766022cdc9fSManos Pitsidianakis g_assert(tgm2->throttle_state != NULL);
767022cdc9fSManos Pitsidianakis g_assert(tgm3->throttle_state != NULL);
768022cdc9fSManos Pitsidianakis
769022cdc9fSManos Pitsidianakis g_assert(!strcmp(throttle_group_get_name(tgm1), "bar"));
770022cdc9fSManos Pitsidianakis g_assert(!strcmp(throttle_group_get_name(tgm2), "foo"));
771022cdc9fSManos Pitsidianakis g_assert(tgm1->throttle_state == tgm3->throttle_state);
7721fee955fSAlberto Garcia
7731fee955fSAlberto Garcia /* Setting the config of a group member affects the whole group */
7741588ab5dSAlberto Garcia throttle_config_init(&cfg1);
7751fee955fSAlberto Garcia cfg1.buckets[THROTTLE_BPS_READ].avg = 500000;
7761fee955fSAlberto Garcia cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000;
7771fee955fSAlberto Garcia cfg1.buckets[THROTTLE_OPS_READ].avg = 20000;
7781fee955fSAlberto Garcia cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000;
779022cdc9fSManos Pitsidianakis throttle_group_config(tgm1, &cfg1);
7801fee955fSAlberto Garcia
781022cdc9fSManos Pitsidianakis throttle_group_get_config(tgm1, &cfg1);
782022cdc9fSManos Pitsidianakis throttle_group_get_config(tgm3, &cfg2);
7831fee955fSAlberto Garcia g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
7841fee955fSAlberto Garcia
7851fee955fSAlberto Garcia cfg2.buckets[THROTTLE_BPS_READ].avg = 4547;
7861fee955fSAlberto Garcia cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349;
7871fee955fSAlberto Garcia cfg2.buckets[THROTTLE_OPS_READ].avg = 123;
7881fee955fSAlberto Garcia cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86;
789022cdc9fSManos Pitsidianakis throttle_group_config(tgm3, &cfg1);
7901fee955fSAlberto Garcia
791022cdc9fSManos Pitsidianakis throttle_group_get_config(tgm1, &cfg1);
792022cdc9fSManos Pitsidianakis throttle_group_get_config(tgm3, &cfg2);
7931fee955fSAlberto Garcia g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
7941fee955fSAlberto Garcia
795022cdc9fSManos Pitsidianakis throttle_group_unregister_tgm(tgm1);
796022cdc9fSManos Pitsidianakis throttle_group_unregister_tgm(tgm2);
797022cdc9fSManos Pitsidianakis throttle_group_unregister_tgm(tgm3);
7981fee955fSAlberto Garcia
799022cdc9fSManos Pitsidianakis g_assert(tgm1->throttle_state == NULL);
800022cdc9fSManos Pitsidianakis g_assert(tgm2->throttle_state == NULL);
801022cdc9fSManos Pitsidianakis g_assert(tgm3->throttle_state == NULL);
8021fee955fSAlberto Garcia }
8031fee955fSAlberto Garcia
main(int argc,char ** argv)804f17cfe81SBenoît Canet int main(int argc, char **argv)
805f17cfe81SBenoît Canet {
80673eaa047SMarkus Armbruster qemu_init_main_loop(&error_fatal);
8071fee955fSAlberto Garcia ctx = qemu_get_aio_context();
8081fee955fSAlberto Garcia bdrv_init();
809432d889eSManos Pitsidianakis module_call_init(MODULE_INIT_QOM);
81013af91ebSStefan Hajnoczi
811f17cfe81SBenoît Canet do {} while (g_main_context_iteration(NULL, false));
812f17cfe81SBenoît Canet
813f17cfe81SBenoît Canet /* tests in the same order as the header function declarations */
814f17cfe81SBenoît Canet g_test_init(&argc, &argv, NULL);
815f17cfe81SBenoît Canet g_test_add_func("/throttle/leak_bucket", test_leak_bucket);
816f17cfe81SBenoît Canet g_test_add_func("/throttle/compute_wait", test_compute_wait);
817f17cfe81SBenoît Canet g_test_add_func("/throttle/init", test_init);
81802add531Szhenwei pi g_test_add_func("/throttle/init_readonly", test_init_readonly);
81902add531Szhenwei pi g_test_add_func("/throttle/init_writeonly", test_init_writeonly);
820f17cfe81SBenoît Canet g_test_add_func("/throttle/destroy", test_destroy);
821f17cfe81SBenoît Canet g_test_add_func("/throttle/have_timer", test_have_timer);
82222524f72SStefan Hajnoczi g_test_add_func("/throttle/detach_attach", test_detach_attach);
823f17cfe81SBenoît Canet g_test_add_func("/throttle/config/enabled", test_enabled);
824f17cfe81SBenoît Canet g_test_add_func("/throttle/config/conflicting", test_conflicting_config);
825f17cfe81SBenoît Canet g_test_add_func("/throttle/config/is_valid", test_is_valid);
826d942feecSAlberto Garcia g_test_add_func("/throttle/config/ranges", test_ranges);
82792e11a17SStefan Hajnoczi g_test_add_func("/throttle/config/max", test_max_is_missing_limit);
8288860eabdSStefan Hajnoczi g_test_add_func("/throttle/config/iops_size",
8298860eabdSStefan Hajnoczi test_iops_size_is_missing_limit);
830f17cfe81SBenoît Canet g_test_add_func("/throttle/config_functions", test_config_functions);
831f17cfe81SBenoît Canet g_test_add_func("/throttle/accounting", test_accounting);
8321fee955fSAlberto Garcia g_test_add_func("/throttle/groups", test_groups);
833f17cfe81SBenoît Canet return g_test_run();
834f17cfe81SBenoît Canet }
835f17cfe81SBenoît Canet
836