xref: /qemu/tests/unit/test-throttle.c (revision d861ab3acf8dcf817e0c2335979b258847b69564)
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"
211fee955fSAlberto Garcia #include "block/throttle-groups.h"
2231dce3ccSKevin Wolf #include "sysemu/block-backend.h"
23f17cfe81SBenoît Canet 
24748bfb4eSStefan Weil static AioContext     *ctx;
25748bfb4eSStefan Weil static LeakyBucket    bkt;
26748bfb4eSStefan Weil static ThrottleConfig cfg;
27c61791fcSManos Pitsidianakis static ThrottleGroupMember tgm;
28748bfb4eSStefan Weil static ThrottleState  ts;
29c61791fcSManos Pitsidianakis static ThrottleTimers *tt;
30f17cfe81SBenoît Canet 
3173f395faSStefan Weil /* useful function */
32f17cfe81SBenoît Canet static bool double_cmp(double x, double y)
33f17cfe81SBenoît Canet {
34f17cfe81SBenoît Canet     return fabsl(x - y) < 1e-6;
35f17cfe81SBenoît Canet }
36f17cfe81SBenoît Canet 
37f17cfe81SBenoît Canet /* tests for single bucket operations */
38f17cfe81SBenoît Canet static void test_leak_bucket(void)
39f17cfe81SBenoît Canet {
401588ab5dSAlberto Garcia     throttle_config_init(&cfg);
411588ab5dSAlberto Garcia     bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
421588ab5dSAlberto Garcia 
43f17cfe81SBenoît Canet     /* set initial value */
44f17cfe81SBenoît Canet     bkt.avg = 150;
45f17cfe81SBenoît Canet     bkt.max = 15;
46f17cfe81SBenoît Canet     bkt.level = 1.5;
47f17cfe81SBenoît Canet 
48f17cfe81SBenoît Canet     /* leak an op work of time */
4913566fe3SStefan Hajnoczi     throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
50f17cfe81SBenoît Canet     g_assert(bkt.avg == 150);
51f17cfe81SBenoît Canet     g_assert(bkt.max == 15);
52f17cfe81SBenoît Canet     g_assert(double_cmp(bkt.level, 0.5));
53f17cfe81SBenoît Canet 
54f17cfe81SBenoît Canet     /* leak again emptying the bucket */
5513566fe3SStefan Hajnoczi     throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
56f17cfe81SBenoît Canet     g_assert(bkt.avg == 150);
57f17cfe81SBenoît Canet     g_assert(bkt.max == 15);
58f17cfe81SBenoît Canet     g_assert(double_cmp(bkt.level, 0));
59f17cfe81SBenoît Canet 
60f17cfe81SBenoît Canet     /* check that the bucket level won't go lower */
6113566fe3SStefan Hajnoczi     throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
62f17cfe81SBenoît Canet     g_assert(bkt.avg == 150);
63f17cfe81SBenoît Canet     g_assert(bkt.max == 15);
64f17cfe81SBenoît Canet     g_assert(double_cmp(bkt.level, 0));
65eb8a1a1cSAlberto Garcia 
66eb8a1a1cSAlberto Garcia     /* check that burst_level leaks correctly */
67eb8a1a1cSAlberto Garcia     bkt.burst_level = 6;
68eb8a1a1cSAlberto Garcia     bkt.max = 250;
69eb8a1a1cSAlberto Garcia     bkt.burst_length = 2; /* otherwise burst_level will not leak */
70eb8a1a1cSAlberto Garcia     throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
71eb8a1a1cSAlberto Garcia     g_assert(double_cmp(bkt.burst_level, 3.5));
72eb8a1a1cSAlberto Garcia 
73eb8a1a1cSAlberto Garcia     throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
74eb8a1a1cSAlberto Garcia     g_assert(double_cmp(bkt.burst_level, 1));
75eb8a1a1cSAlberto Garcia 
76eb8a1a1cSAlberto Garcia     throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
77eb8a1a1cSAlberto Garcia     g_assert(double_cmp(bkt.burst_level, 0));
78eb8a1a1cSAlberto Garcia 
79eb8a1a1cSAlberto Garcia     throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
80eb8a1a1cSAlberto Garcia     g_assert(double_cmp(bkt.burst_level, 0));
81f17cfe81SBenoît Canet }
82f17cfe81SBenoît Canet 
83f17cfe81SBenoît Canet static void test_compute_wait(void)
84f17cfe81SBenoît Canet {
85f9d05885SAlberto Garcia     unsigned i;
86f17cfe81SBenoît Canet     int64_t wait;
87f17cfe81SBenoît Canet     int64_t result;
88f17cfe81SBenoît Canet 
891588ab5dSAlberto Garcia     throttle_config_init(&cfg);
901588ab5dSAlberto Garcia     bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
911588ab5dSAlberto Garcia 
92f17cfe81SBenoît Canet     /* no operation limit set */
93f17cfe81SBenoît Canet     bkt.avg = 0;
94f17cfe81SBenoît Canet     bkt.max = 15;
95f17cfe81SBenoît Canet     bkt.level = 1.5;
96f17cfe81SBenoît Canet     wait = throttle_compute_wait(&bkt);
97f17cfe81SBenoît Canet     g_assert(!wait);
98f17cfe81SBenoît Canet 
99f17cfe81SBenoît Canet     /* zero delta */
100f17cfe81SBenoît Canet     bkt.avg = 150;
101f17cfe81SBenoît Canet     bkt.max = 15;
102f17cfe81SBenoît Canet     bkt.level = 15;
103f17cfe81SBenoît Canet     wait = throttle_compute_wait(&bkt);
104f17cfe81SBenoît Canet     g_assert(!wait);
105f17cfe81SBenoît Canet 
106f17cfe81SBenoît Canet     /* below zero delta */
107f17cfe81SBenoît Canet     bkt.avg = 150;
108f17cfe81SBenoît Canet     bkt.max = 15;
109f17cfe81SBenoît Canet     bkt.level = 9;
110f17cfe81SBenoît Canet     wait = throttle_compute_wait(&bkt);
111f17cfe81SBenoît Canet     g_assert(!wait);
112f17cfe81SBenoît Canet 
113f17cfe81SBenoît Canet     /* half an operation above max */
114f17cfe81SBenoît Canet     bkt.avg = 150;
115f17cfe81SBenoît Canet     bkt.max = 15;
116f17cfe81SBenoît Canet     bkt.level = 15.5;
117f17cfe81SBenoît Canet     wait = throttle_compute_wait(&bkt);
118f17cfe81SBenoît Canet     /* time required to do half an operation */
11913566fe3SStefan Hajnoczi     result = (int64_t)  NANOSECONDS_PER_SECOND / 150 / 2;
120f17cfe81SBenoît Canet     g_assert(wait == result);
121f9d05885SAlberto Garcia 
122f9d05885SAlberto Garcia     /* Perform I/O for 2.2 seconds at a rate of bkt.max */
123f9d05885SAlberto Garcia     bkt.burst_length = 2;
124f9d05885SAlberto Garcia     bkt.level = 0;
125f9d05885SAlberto Garcia     bkt.avg = 10;
126f9d05885SAlberto Garcia     bkt.max = 200;
127f9d05885SAlberto Garcia     for (i = 0; i < 22; i++) {
128f9d05885SAlberto Garcia         double units = bkt.max / 10;
129f9d05885SAlberto Garcia         bkt.level += units;
130f9d05885SAlberto Garcia         bkt.burst_level += units;
131f9d05885SAlberto Garcia         throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 10);
132f9d05885SAlberto Garcia         wait = throttle_compute_wait(&bkt);
133f9d05885SAlberto Garcia         g_assert(double_cmp(bkt.burst_level, 0));
134f9d05885SAlberto Garcia         g_assert(double_cmp(bkt.level, (i + 1) * (bkt.max - bkt.avg) / 10));
135f9d05885SAlberto Garcia         /* We can do bursts for the 2 seconds we have configured in
136f9d05885SAlberto Garcia          * burst_length. We have 100 extra miliseconds of burst
137f9d05885SAlberto Garcia          * because bkt.level has been leaking during this time.
138f9d05885SAlberto Garcia          * After that, we have to wait. */
139f9d05885SAlberto Garcia         result = i < 21 ? 0 : 1.8 * NANOSECONDS_PER_SECOND;
140f9d05885SAlberto Garcia         g_assert(wait == result);
141f9d05885SAlberto Garcia     }
142f17cfe81SBenoît Canet }
143f17cfe81SBenoît Canet 
144f17cfe81SBenoît Canet /* functions to test ThrottleState initialization/destroy methods */
145f17cfe81SBenoît Canet static void read_timer_cb(void *opaque)
146f17cfe81SBenoît Canet {
147f17cfe81SBenoît Canet }
148f17cfe81SBenoît Canet 
149f17cfe81SBenoît Canet static void write_timer_cb(void *opaque)
150f17cfe81SBenoît Canet {
151f17cfe81SBenoît Canet }
152f17cfe81SBenoît Canet 
153f17cfe81SBenoît Canet static void test_init(void)
154f17cfe81SBenoît Canet {
155f17cfe81SBenoît Canet     int i;
156f17cfe81SBenoît Canet 
157c61791fcSManos Pitsidianakis     tt = &tgm.throttle_timers;
158c61791fcSManos Pitsidianakis 
1590e5b0a2dSBenoît Canet     /* fill the structures with crap */
160f17cfe81SBenoît Canet     memset(&ts, 1, sizeof(ts));
161c61791fcSManos Pitsidianakis     memset(tt, 1, sizeof(*tt));
162f17cfe81SBenoît Canet 
1630e5b0a2dSBenoît Canet     /* init structures */
1640e5b0a2dSBenoît Canet     throttle_init(&ts);
165c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
16613af91ebSStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
167f17cfe81SBenoît Canet 
168f17cfe81SBenoît Canet     /* check initialized fields */
169c61791fcSManos Pitsidianakis     g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
170c61791fcSManos Pitsidianakis     g_assert(tt->timers[0]);
171c61791fcSManos Pitsidianakis     g_assert(tt->timers[1]);
172f17cfe81SBenoît Canet 
173f17cfe81SBenoît Canet     /* check other fields where cleared */
174f17cfe81SBenoît Canet     g_assert(!ts.previous_leak);
175f17cfe81SBenoît Canet     g_assert(!ts.cfg.op_size);
176f17cfe81SBenoît Canet     for (i = 0; i < BUCKETS_COUNT; i++) {
177f17cfe81SBenoît Canet         g_assert(!ts.cfg.buckets[i].avg);
178f17cfe81SBenoît Canet         g_assert(!ts.cfg.buckets[i].max);
179f17cfe81SBenoît Canet         g_assert(!ts.cfg.buckets[i].level);
180f17cfe81SBenoît Canet     }
181f17cfe81SBenoît Canet 
182c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
183f17cfe81SBenoît Canet }
184f17cfe81SBenoît Canet 
185f17cfe81SBenoît Canet static void test_destroy(void)
186f17cfe81SBenoît Canet {
187f17cfe81SBenoît Canet     int i;
1880e5b0a2dSBenoît Canet     throttle_init(&ts);
189c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
19013af91ebSStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
191c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
192f17cfe81SBenoît Canet     for (i = 0; i < 2; i++) {
193c61791fcSManos Pitsidianakis         g_assert(!tt->timers[i]);
194f17cfe81SBenoît Canet     }
195f17cfe81SBenoît Canet }
196f17cfe81SBenoît Canet 
197f17cfe81SBenoît Canet /* function to test throttle_config and throttle_get_config */
198f17cfe81SBenoît Canet static void test_config_functions(void)
199f17cfe81SBenoît Canet {
200f17cfe81SBenoît Canet     int i;
201f17cfe81SBenoît Canet     ThrottleConfig orig_cfg, final_cfg;
202f17cfe81SBenoît Canet 
203f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_TOTAL].avg = 153;
204f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_READ].avg  = 56;
205f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_WRITE].avg = 1;
206f17cfe81SBenoît Canet 
207f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_TOTAL].avg = 150;
208f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_READ].avg  = 69;
209f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_WRITE].avg = 23;
210f17cfe81SBenoît Canet 
211d72915c6SStefan Hajnoczi     orig_cfg.buckets[THROTTLE_BPS_TOTAL].max = 0;
212d72915c6SStefan Hajnoczi     orig_cfg.buckets[THROTTLE_BPS_READ].max  = 56;
213f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_WRITE].max = 120;
214f17cfe81SBenoît Canet 
215f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_TOTAL].max = 150;
216f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_READ].max  = 400;
217f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_WRITE].max = 500;
218f17cfe81SBenoît Canet 
219f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_TOTAL].level = 45;
220f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_READ].level  = 65;
221f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_WRITE].level = 23;
222f17cfe81SBenoît Canet 
223f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_TOTAL].level = 1;
224f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_READ].level  = 90;
225f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_WRITE].level = 75;
226f17cfe81SBenoît Canet 
227f17cfe81SBenoît Canet     orig_cfg.op_size = 1;
228f17cfe81SBenoît Canet 
2290e5b0a2dSBenoît Canet     throttle_init(&ts);
230c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
23113af91ebSStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
232f17cfe81SBenoît Canet     /* structure reset by throttle_init previous_leak should be null */
233f17cfe81SBenoît Canet     g_assert(!ts.previous_leak);
23427e4cf13SManos Pitsidianakis     throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &orig_cfg);
235f17cfe81SBenoît Canet 
236f17cfe81SBenoît Canet     /* has previous leak been initialized by throttle_config ? */
237f17cfe81SBenoît Canet     g_assert(ts.previous_leak);
238f17cfe81SBenoît Canet 
239f17cfe81SBenoît Canet     /* get back the fixed configuration */
240f17cfe81SBenoît Canet     throttle_get_config(&ts, &final_cfg);
241f17cfe81SBenoît Canet 
242c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
243f17cfe81SBenoît Canet 
244f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153);
245f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg  == 56);
246f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].avg == 1);
247f17cfe81SBenoît Canet 
248f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].avg == 150);
249f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_READ].avg  == 69);
250f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].avg == 23);
251f17cfe81SBenoît Canet 
252d72915c6SStefan Hajnoczi     g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].max == 0);
253d72915c6SStefan Hajnoczi     g_assert(final_cfg.buckets[THROTTLE_BPS_READ].max  == 56);
254f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].max == 120);
255f17cfe81SBenoît Canet 
256f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].max == 150);
257f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_READ].max  == 400);
258f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].max == 500);
259f17cfe81SBenoît Canet 
260f17cfe81SBenoît Canet     g_assert(final_cfg.op_size == 1);
261f17cfe81SBenoît Canet 
262f17cfe81SBenoît Canet     /* check bucket have been cleared */
263f17cfe81SBenoît Canet     for (i = 0; i < BUCKETS_COUNT; i++) {
264f17cfe81SBenoît Canet         g_assert(!final_cfg.buckets[i].level);
265f17cfe81SBenoît Canet     }
266f17cfe81SBenoît Canet }
267f17cfe81SBenoît Canet 
268f17cfe81SBenoît Canet /* functions to test is throttle is enabled by a config */
269f17cfe81SBenoît Canet static void set_cfg_value(bool is_max, int index, int value)
270f17cfe81SBenoît Canet {
271f17cfe81SBenoît Canet     if (is_max) {
272f17cfe81SBenoît Canet         cfg.buckets[index].max = value;
2736f9b6d57SAlberto Garcia         /* If max is set, avg should never be 0 */
2746f9b6d57SAlberto Garcia         cfg.buckets[index].avg = MAX(cfg.buckets[index].avg, 1);
275f17cfe81SBenoît Canet     } else {
276f17cfe81SBenoît Canet         cfg.buckets[index].avg = value;
277f17cfe81SBenoît Canet     }
278f17cfe81SBenoît Canet }
279f17cfe81SBenoît Canet 
280f17cfe81SBenoît Canet static void test_enabled(void)
281f17cfe81SBenoît Canet {
282f17cfe81SBenoît Canet     int i;
283f17cfe81SBenoît Canet 
2841588ab5dSAlberto Garcia     throttle_config_init(&cfg);
285f17cfe81SBenoît Canet     g_assert(!throttle_enabled(&cfg));
286f17cfe81SBenoît Canet 
287f17cfe81SBenoît Canet     for (i = 0; i < BUCKETS_COUNT; i++) {
2881588ab5dSAlberto Garcia         throttle_config_init(&cfg);
289f17cfe81SBenoît Canet         set_cfg_value(false, i, 150);
290d00e6923SAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
291f17cfe81SBenoît Canet         g_assert(throttle_enabled(&cfg));
292f17cfe81SBenoît Canet     }
293f17cfe81SBenoît Canet 
294f17cfe81SBenoît Canet     for (i = 0; i < BUCKETS_COUNT; i++) {
2951588ab5dSAlberto Garcia         throttle_config_init(&cfg);
296f17cfe81SBenoît Canet         set_cfg_value(false, i, -150);
297d00e6923SAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
298f17cfe81SBenoît Canet     }
299f17cfe81SBenoît Canet }
300f17cfe81SBenoît Canet 
301f17cfe81SBenoît Canet /* tests functions for throttle_conflicting */
302f17cfe81SBenoît Canet 
303f17cfe81SBenoît Canet static void test_conflicts_for_one_set(bool is_max,
304f17cfe81SBenoît Canet                                        int total,
305f17cfe81SBenoît Canet                                        int read,
306f17cfe81SBenoît Canet                                        int write)
307f17cfe81SBenoît Canet {
3081588ab5dSAlberto Garcia     throttle_config_init(&cfg);
309d5851089SAlberto Garcia     g_assert(throttle_is_valid(&cfg, NULL));
310f17cfe81SBenoît Canet 
311f17cfe81SBenoît Canet     set_cfg_value(is_max, total, 1);
312f17cfe81SBenoît Canet     set_cfg_value(is_max, read,  1);
313d5851089SAlberto Garcia     g_assert(!throttle_is_valid(&cfg, NULL));
314f17cfe81SBenoît Canet 
3151588ab5dSAlberto Garcia     throttle_config_init(&cfg);
316f17cfe81SBenoît Canet     set_cfg_value(is_max, total, 1);
317f17cfe81SBenoît Canet     set_cfg_value(is_max, write, 1);
318d5851089SAlberto Garcia     g_assert(!throttle_is_valid(&cfg, NULL));
319f17cfe81SBenoît Canet 
3201588ab5dSAlberto Garcia     throttle_config_init(&cfg);
321f17cfe81SBenoît Canet     set_cfg_value(is_max, total, 1);
322f17cfe81SBenoît Canet     set_cfg_value(is_max, read,  1);
323f17cfe81SBenoît Canet     set_cfg_value(is_max, write, 1);
324d5851089SAlberto Garcia     g_assert(!throttle_is_valid(&cfg, NULL));
325f17cfe81SBenoît Canet 
3261588ab5dSAlberto Garcia     throttle_config_init(&cfg);
327f17cfe81SBenoît Canet     set_cfg_value(is_max, total, 1);
328d5851089SAlberto Garcia     g_assert(throttle_is_valid(&cfg, NULL));
329f17cfe81SBenoît Canet 
3301588ab5dSAlberto Garcia     throttle_config_init(&cfg);
331f17cfe81SBenoît Canet     set_cfg_value(is_max, read,  1);
332f17cfe81SBenoît Canet     set_cfg_value(is_max, write, 1);
333d5851089SAlberto Garcia     g_assert(throttle_is_valid(&cfg, NULL));
334f17cfe81SBenoît Canet }
335f17cfe81SBenoît Canet 
336f17cfe81SBenoît Canet static void test_conflicting_config(void)
337f17cfe81SBenoît Canet {
338f17cfe81SBenoît Canet     /* bps average conflicts */
339f17cfe81SBenoît Canet     test_conflicts_for_one_set(false,
340f17cfe81SBenoît Canet                                THROTTLE_BPS_TOTAL,
341f17cfe81SBenoît Canet                                THROTTLE_BPS_READ,
342f17cfe81SBenoît Canet                                THROTTLE_BPS_WRITE);
343f17cfe81SBenoît Canet 
344f17cfe81SBenoît Canet     /* ops average conflicts */
345f17cfe81SBenoît Canet     test_conflicts_for_one_set(false,
346f17cfe81SBenoît Canet                                THROTTLE_OPS_TOTAL,
347f17cfe81SBenoît Canet                                THROTTLE_OPS_READ,
348f17cfe81SBenoît Canet                                THROTTLE_OPS_WRITE);
349f17cfe81SBenoît Canet 
350f17cfe81SBenoît Canet     /* bps average conflicts */
351f17cfe81SBenoît Canet     test_conflicts_for_one_set(true,
352f17cfe81SBenoît Canet                                THROTTLE_BPS_TOTAL,
353f17cfe81SBenoît Canet                                THROTTLE_BPS_READ,
354f17cfe81SBenoît Canet                                THROTTLE_BPS_WRITE);
355f17cfe81SBenoît Canet     /* ops average conflicts */
356f17cfe81SBenoît Canet     test_conflicts_for_one_set(true,
357f17cfe81SBenoît Canet                                THROTTLE_OPS_TOTAL,
358f17cfe81SBenoît Canet                                THROTTLE_OPS_READ,
359f17cfe81SBenoît Canet                                THROTTLE_OPS_WRITE);
360f17cfe81SBenoît Canet }
361f17cfe81SBenoît Canet /* functions to test the throttle_is_valid function */
362f17cfe81SBenoît Canet static void test_is_valid_for_value(int value, bool should_be_valid)
363f17cfe81SBenoît Canet {
364f17cfe81SBenoît Canet     int is_max, index;
365f17cfe81SBenoît Canet     for (is_max = 0; is_max < 2; is_max++) {
366f17cfe81SBenoît Canet         for (index = 0; index < BUCKETS_COUNT; index++) {
3671588ab5dSAlberto Garcia             throttle_config_init(&cfg);
368f17cfe81SBenoît Canet             set_cfg_value(is_max, index, value);
36903ba36c8SAlberto Garcia             g_assert(throttle_is_valid(&cfg, NULL) == should_be_valid);
370f17cfe81SBenoît Canet         }
371f17cfe81SBenoît Canet     }
372f17cfe81SBenoît Canet }
373f17cfe81SBenoît Canet 
374f17cfe81SBenoît Canet static void test_is_valid(void)
375f17cfe81SBenoît Canet {
376f17cfe81SBenoît Canet     /* negative number are invalid */
377f17cfe81SBenoît Canet     test_is_valid_for_value(-1, false);
378f17cfe81SBenoît Canet     /* zero are valids */
379f17cfe81SBenoît Canet     test_is_valid_for_value(0, true);
380f17cfe81SBenoît Canet     /* positives numers are valids */
381f17cfe81SBenoît Canet     test_is_valid_for_value(1, true);
382f17cfe81SBenoît Canet }
383f17cfe81SBenoît Canet 
384d942feecSAlberto Garcia static void test_ranges(void)
385d942feecSAlberto Garcia {
386d942feecSAlberto Garcia     int i;
387d942feecSAlberto Garcia 
388d942feecSAlberto Garcia     for (i = 0; i < BUCKETS_COUNT; i++) {
389d942feecSAlberto Garcia         LeakyBucket *b = &cfg.buckets[i];
390d942feecSAlberto Garcia         throttle_config_init(&cfg);
391d942feecSAlberto Garcia 
392d942feecSAlberto Garcia         /* avg = 0 means throttling is disabled, but the config is valid */
393d942feecSAlberto Garcia         b->avg = 0;
394d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
395d942feecSAlberto Garcia         g_assert(!throttle_enabled(&cfg));
396d942feecSAlberto Garcia 
397d942feecSAlberto Garcia         /* These are valid configurations (values <= THROTTLE_VALUE_MAX) */
398d942feecSAlberto Garcia         b->avg = 1;
399d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
400d942feecSAlberto Garcia 
401d942feecSAlberto Garcia         b->avg = THROTTLE_VALUE_MAX;
402d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
403d942feecSAlberto Garcia 
404d942feecSAlberto Garcia         b->avg = THROTTLE_VALUE_MAX;
405d942feecSAlberto Garcia         b->max = THROTTLE_VALUE_MAX;
406d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
407d942feecSAlberto Garcia 
408d942feecSAlberto Garcia         /* Values over THROTTLE_VALUE_MAX are not allowed */
409d942feecSAlberto Garcia         b->avg = THROTTLE_VALUE_MAX + 1;
410d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
411d942feecSAlberto Garcia 
412d942feecSAlberto Garcia         b->avg = THROTTLE_VALUE_MAX;
413d942feecSAlberto Garcia         b->max = THROTTLE_VALUE_MAX + 1;
414d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
415d942feecSAlberto Garcia 
416d942feecSAlberto Garcia         /* burst_length must be between 1 and THROTTLE_VALUE_MAX */
417d942feecSAlberto Garcia         b->avg = 1;
418d942feecSAlberto Garcia         b->max = 1;
419d942feecSAlberto Garcia         b->burst_length = 0;
420d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
421d942feecSAlberto Garcia 
422d942feecSAlberto Garcia         b->avg = 1;
423d942feecSAlberto Garcia         b->max = 1;
424d942feecSAlberto Garcia         b->burst_length = 1;
425d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
426d942feecSAlberto Garcia 
427d942feecSAlberto Garcia         b->avg = 1;
428d942feecSAlberto Garcia         b->max = 1;
429d942feecSAlberto Garcia         b->burst_length = THROTTLE_VALUE_MAX;
430d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
431d942feecSAlberto Garcia 
432d942feecSAlberto Garcia         b->avg = 1;
433d942feecSAlberto Garcia         b->max = 1;
434d942feecSAlberto Garcia         b->burst_length = THROTTLE_VALUE_MAX + 1;
435d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
436d942feecSAlberto Garcia 
437d942feecSAlberto Garcia         /* burst_length * max cannot exceed THROTTLE_VALUE_MAX */
438d942feecSAlberto Garcia         b->avg = 1;
439d942feecSAlberto Garcia         b->max = 2;
440d942feecSAlberto Garcia         b->burst_length = THROTTLE_VALUE_MAX / 2;
441d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
442d942feecSAlberto Garcia 
443d942feecSAlberto Garcia         b->avg = 1;
444d942feecSAlberto Garcia         b->max = 3;
445d942feecSAlberto Garcia         b->burst_length = THROTTLE_VALUE_MAX / 2;
446d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
447d942feecSAlberto Garcia 
448d942feecSAlberto Garcia         b->avg = 1;
449d942feecSAlberto Garcia         b->max = THROTTLE_VALUE_MAX;
450d942feecSAlberto Garcia         b->burst_length = 1;
451d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
452d942feecSAlberto Garcia 
453d942feecSAlberto Garcia         b->avg = 1;
454d942feecSAlberto Garcia         b->max = THROTTLE_VALUE_MAX;
455d942feecSAlberto Garcia         b->burst_length = 2;
456d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
457d942feecSAlberto Garcia     }
458d942feecSAlberto Garcia }
459d942feecSAlberto Garcia 
46092e11a17SStefan Hajnoczi static void test_max_is_missing_limit(void)
46192e11a17SStefan Hajnoczi {
46292e11a17SStefan Hajnoczi     int i;
46392e11a17SStefan Hajnoczi 
46492e11a17SStefan Hajnoczi     for (i = 0; i < BUCKETS_COUNT; i++) {
4651588ab5dSAlberto Garcia         throttle_config_init(&cfg);
46692e11a17SStefan Hajnoczi         cfg.buckets[i].max = 100;
46792e11a17SStefan Hajnoczi         cfg.buckets[i].avg = 0;
468d5851089SAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
46992e11a17SStefan Hajnoczi 
47092e11a17SStefan Hajnoczi         cfg.buckets[i].max = 0;
47192e11a17SStefan Hajnoczi         cfg.buckets[i].avg = 0;
472d5851089SAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
47392e11a17SStefan Hajnoczi 
47492e11a17SStefan Hajnoczi         cfg.buckets[i].max = 0;
47592e11a17SStefan Hajnoczi         cfg.buckets[i].avg = 100;
476d5851089SAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
4775fc8c052SAlberto Garcia 
4785fc8c052SAlberto Garcia         cfg.buckets[i].max = 30;
4795fc8c052SAlberto Garcia         cfg.buckets[i].avg = 100;
4805fc8c052SAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
4815fc8c052SAlberto Garcia 
4825fc8c052SAlberto Garcia         cfg.buckets[i].max = 100;
4835fc8c052SAlberto Garcia         cfg.buckets[i].avg = 100;
4845fc8c052SAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
48592e11a17SStefan Hajnoczi     }
48692e11a17SStefan Hajnoczi }
48792e11a17SStefan Hajnoczi 
4888860eabdSStefan Hajnoczi static void test_iops_size_is_missing_limit(void)
4898860eabdSStefan Hajnoczi {
4908860eabdSStefan Hajnoczi     /* A total/read/write iops limit is required */
4918860eabdSStefan Hajnoczi     throttle_config_init(&cfg);
4928860eabdSStefan Hajnoczi     cfg.op_size = 4096;
4938860eabdSStefan Hajnoczi     g_assert(!throttle_is_valid(&cfg, NULL));
4948860eabdSStefan Hajnoczi }
4958860eabdSStefan Hajnoczi 
496f17cfe81SBenoît Canet static void test_have_timer(void)
497f17cfe81SBenoît Canet {
4980e5b0a2dSBenoît Canet     /* zero structures */
499f17cfe81SBenoît Canet     memset(&ts, 0, sizeof(ts));
500c61791fcSManos Pitsidianakis     memset(tt, 0, sizeof(*tt));
501f17cfe81SBenoît Canet 
50273f395faSStefan Weil     /* no timer set should return false */
503c61791fcSManos Pitsidianakis     g_assert(!throttle_timers_are_initialized(tt));
504f17cfe81SBenoît Canet 
5050e5b0a2dSBenoît Canet     /* init structures */
5060e5b0a2dSBenoît Canet     throttle_init(&ts);
507c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
50813af91ebSStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
509f17cfe81SBenoît Canet 
510f17cfe81SBenoît Canet     /* timer set by init should return true */
511c61791fcSManos Pitsidianakis     g_assert(throttle_timers_are_initialized(tt));
512f17cfe81SBenoît Canet 
513c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
514f17cfe81SBenoît Canet }
515f17cfe81SBenoît Canet 
51622524f72SStefan Hajnoczi static void test_detach_attach(void)
51722524f72SStefan Hajnoczi {
5180e5b0a2dSBenoît Canet     /* zero structures */
51922524f72SStefan Hajnoczi     memset(&ts, 0, sizeof(ts));
520c61791fcSManos Pitsidianakis     memset(tt, 0, sizeof(*tt));
52122524f72SStefan Hajnoczi 
52222524f72SStefan Hajnoczi     /* init the structure */
5230e5b0a2dSBenoît Canet     throttle_init(&ts);
524c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
52522524f72SStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
52622524f72SStefan Hajnoczi 
52722524f72SStefan Hajnoczi     /* timer set by init should return true */
528c61791fcSManos Pitsidianakis     g_assert(throttle_timers_are_initialized(tt));
52922524f72SStefan Hajnoczi 
53022524f72SStefan Hajnoczi     /* timer should no longer exist after detaching */
531c61791fcSManos Pitsidianakis     throttle_timers_detach_aio_context(tt);
532c61791fcSManos Pitsidianakis     g_assert(!throttle_timers_are_initialized(tt));
53322524f72SStefan Hajnoczi 
53422524f72SStefan Hajnoczi     /* timer should exist again after attaching */
535c61791fcSManos Pitsidianakis     throttle_timers_attach_aio_context(tt, ctx);
536c61791fcSManos Pitsidianakis     g_assert(throttle_timers_are_initialized(tt));
53722524f72SStefan Hajnoczi 
538c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
53922524f72SStefan Hajnoczi }
54022524f72SStefan Hajnoczi 
541f17cfe81SBenoît Canet static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
542f17cfe81SBenoît Canet                 int size,                   /* size of the operation to do */
543f17cfe81SBenoît Canet                 double avg,                 /* io limit */
544f17cfe81SBenoît Canet                 uint64_t op_size,           /* ideal size of an io */
545f17cfe81SBenoît Canet                 double total_result,
546f17cfe81SBenoît Canet                 double read_result,
547f17cfe81SBenoît Canet                 double write_result)
548f17cfe81SBenoît Canet {
549f17cfe81SBenoît Canet     BucketType to_test[2][3] = { { THROTTLE_BPS_TOTAL,
550f17cfe81SBenoît Canet                                    THROTTLE_BPS_READ,
551f17cfe81SBenoît Canet                                    THROTTLE_BPS_WRITE, },
552f17cfe81SBenoît Canet                                  { THROTTLE_OPS_TOTAL,
553f17cfe81SBenoît Canet                                    THROTTLE_OPS_READ,
554f17cfe81SBenoît Canet                                    THROTTLE_OPS_WRITE, } };
555f17cfe81SBenoît Canet     ThrottleConfig cfg;
556f17cfe81SBenoît Canet     BucketType index;
557f17cfe81SBenoît Canet     int i;
558f17cfe81SBenoît Canet 
559f17cfe81SBenoît Canet     for (i = 0; i < 3; i++) {
560f17cfe81SBenoît Canet         BucketType index = to_test[is_ops][i];
561f17cfe81SBenoît Canet         cfg.buckets[index].avg = avg;
562f17cfe81SBenoît Canet     }
563f17cfe81SBenoît Canet 
564f17cfe81SBenoît Canet     cfg.op_size = op_size;
565f17cfe81SBenoît Canet 
5660e5b0a2dSBenoît Canet     throttle_init(&ts);
567c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
56813af91ebSStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
56927e4cf13SManos Pitsidianakis     throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &cfg);
570f17cfe81SBenoît Canet 
571f17cfe81SBenoît Canet     /* account a read */
572f17cfe81SBenoît Canet     throttle_account(&ts, false, size);
573f17cfe81SBenoît Canet     /* account a write */
574f17cfe81SBenoît Canet     throttle_account(&ts, true, size);
575f17cfe81SBenoît Canet 
576f17cfe81SBenoît Canet     /* check total result */
577f17cfe81SBenoît Canet     index = to_test[is_ops][0];
578f17cfe81SBenoît Canet     if (!double_cmp(ts.cfg.buckets[index].level, total_result)) {
579f17cfe81SBenoît Canet         return false;
580f17cfe81SBenoît Canet     }
581f17cfe81SBenoît Canet 
582f17cfe81SBenoît Canet     /* check read result */
583f17cfe81SBenoît Canet     index = to_test[is_ops][1];
584f17cfe81SBenoît Canet     if (!double_cmp(ts.cfg.buckets[index].level, read_result)) {
585f17cfe81SBenoît Canet         return false;
586f17cfe81SBenoît Canet     }
587f17cfe81SBenoît Canet 
588f17cfe81SBenoît Canet     /* check write result */
589f17cfe81SBenoît Canet     index = to_test[is_ops][2];
590f17cfe81SBenoît Canet     if (!double_cmp(ts.cfg.buckets[index].level, write_result)) {
591f17cfe81SBenoît Canet         return false;
592f17cfe81SBenoît Canet     }
593f17cfe81SBenoît Canet 
594c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
595f17cfe81SBenoît Canet 
596f17cfe81SBenoît Canet     return true;
597f17cfe81SBenoît Canet }
598f17cfe81SBenoît Canet 
599f17cfe81SBenoît Canet static void test_accounting(void)
600f17cfe81SBenoît Canet {
601f17cfe81SBenoît Canet     /* tests for bps */
602f17cfe81SBenoît Canet 
603f17cfe81SBenoît Canet     /* op of size 1 */
604f17cfe81SBenoît Canet     g_assert(do_test_accounting(false,
605f17cfe81SBenoît Canet                                 1 * 512,
606f17cfe81SBenoît Canet                                 150,
607f17cfe81SBenoît Canet                                 0,
608f17cfe81SBenoît Canet                                 1024,
609f17cfe81SBenoît Canet                                 512,
610f17cfe81SBenoît Canet                                 512));
611f17cfe81SBenoît Canet 
612f17cfe81SBenoît Canet     /* op of size 2 */
613f17cfe81SBenoît Canet     g_assert(do_test_accounting(false,
614f17cfe81SBenoît Canet                                 2 * 512,
615f17cfe81SBenoît Canet                                 150,
616f17cfe81SBenoît Canet                                 0,
617f17cfe81SBenoît Canet                                 2048,
618f17cfe81SBenoît Canet                                 1024,
619f17cfe81SBenoît Canet                                 1024));
620f17cfe81SBenoît Canet 
621f17cfe81SBenoît Canet     /* op of size 2 and orthogonal parameter change */
622f17cfe81SBenoît Canet     g_assert(do_test_accounting(false,
623f17cfe81SBenoît Canet                                 2 * 512,
624f17cfe81SBenoît Canet                                 150,
625f17cfe81SBenoît Canet                                 17,
626f17cfe81SBenoît Canet                                 2048,
627f17cfe81SBenoît Canet                                 1024,
628f17cfe81SBenoît Canet                                 1024));
629f17cfe81SBenoît Canet 
630f17cfe81SBenoît Canet 
631f17cfe81SBenoît Canet     /* tests for ops */
632f17cfe81SBenoît Canet 
633f17cfe81SBenoît Canet     /* op of size 1 */
634f17cfe81SBenoît Canet     g_assert(do_test_accounting(true,
635f17cfe81SBenoît Canet                                 1 * 512,
636f17cfe81SBenoît Canet                                 150,
637f17cfe81SBenoît Canet                                 0,
638f17cfe81SBenoît Canet                                 2,
639f17cfe81SBenoît Canet                                 1,
640f17cfe81SBenoît Canet                                 1));
641f17cfe81SBenoît Canet 
642f17cfe81SBenoît Canet     /* op of size 2 */
643f17cfe81SBenoît Canet     g_assert(do_test_accounting(true,
644f17cfe81SBenoît Canet                                 2 *  512,
645f17cfe81SBenoît Canet                                 150,
646f17cfe81SBenoît Canet                                 0,
647f17cfe81SBenoît Canet                                 2,
648f17cfe81SBenoît Canet                                 1,
649f17cfe81SBenoît Canet                                 1));
650f17cfe81SBenoît Canet 
651f17cfe81SBenoît Canet     /* jumbo op accounting fragmentation : size 64 with op size of 13 units */
652f17cfe81SBenoît Canet     g_assert(do_test_accounting(true,
653f17cfe81SBenoît Canet                                 64 * 512,
654f17cfe81SBenoît Canet                                 150,
655f17cfe81SBenoît Canet                                 13 * 512,
656f17cfe81SBenoît Canet                                 (64.0 * 2) / 13,
657f17cfe81SBenoît Canet                                 (64.0 / 13),
658f17cfe81SBenoît Canet                                 (64.0 / 13)));
659f17cfe81SBenoît Canet 
660f17cfe81SBenoît Canet     /* same with orthogonal parameters changes */
661f17cfe81SBenoît Canet     g_assert(do_test_accounting(true,
662f17cfe81SBenoît Canet                                 64 * 512,
663f17cfe81SBenoît Canet                                 300,
664f17cfe81SBenoît Canet                                 13 * 512,
665f17cfe81SBenoît Canet                                 (64.0 * 2) / 13,
666f17cfe81SBenoît Canet                                 (64.0 / 13),
667f17cfe81SBenoît Canet                                 (64.0 / 13)));
668f17cfe81SBenoît Canet }
669f17cfe81SBenoît Canet 
6701fee955fSAlberto Garcia static void test_groups(void)
6711fee955fSAlberto Garcia {
6721fee955fSAlberto Garcia     ThrottleConfig cfg1, cfg2;
673a5614993SKevin Wolf     BlockBackend *blk1, *blk2, *blk3;
67427ccdd52SKevin Wolf     BlockBackendPublic *blkp1, *blkp2, *blkp3;
675022cdc9fSManos Pitsidianakis     ThrottleGroupMember *tgm1, *tgm2, *tgm3;
6761fee955fSAlberto Garcia 
6772807c0cdSKevin Wolf     /* No actual I/O is performed on these devices */
678*d861ab3aSKevin Wolf     blk1 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
679*d861ab3aSKevin Wolf     blk2 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
680*d861ab3aSKevin Wolf     blk3 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
681a5614993SKevin Wolf 
68227ccdd52SKevin Wolf     blkp1 = blk_get_public(blk1);
68327ccdd52SKevin Wolf     blkp2 = blk_get_public(blk2);
68427ccdd52SKevin Wolf     blkp3 = blk_get_public(blk3);
68527ccdd52SKevin Wolf 
686022cdc9fSManos Pitsidianakis     tgm1 = &blkp1->throttle_group_member;
687022cdc9fSManos Pitsidianakis     tgm2 = &blkp2->throttle_group_member;
688022cdc9fSManos Pitsidianakis     tgm3 = &blkp3->throttle_group_member;
6891fee955fSAlberto Garcia 
690022cdc9fSManos Pitsidianakis     g_assert(tgm1->throttle_state == NULL);
691022cdc9fSManos Pitsidianakis     g_assert(tgm2->throttle_state == NULL);
692022cdc9fSManos Pitsidianakis     g_assert(tgm3->throttle_state == NULL);
6931fee955fSAlberto Garcia 
694c61791fcSManos Pitsidianakis     throttle_group_register_tgm(tgm1, "bar", blk_get_aio_context(blk1));
695c61791fcSManos Pitsidianakis     throttle_group_register_tgm(tgm2, "foo", blk_get_aio_context(blk2));
696c61791fcSManos Pitsidianakis     throttle_group_register_tgm(tgm3, "bar", blk_get_aio_context(blk3));
6971fee955fSAlberto Garcia 
698022cdc9fSManos Pitsidianakis     g_assert(tgm1->throttle_state != NULL);
699022cdc9fSManos Pitsidianakis     g_assert(tgm2->throttle_state != NULL);
700022cdc9fSManos Pitsidianakis     g_assert(tgm3->throttle_state != NULL);
701022cdc9fSManos Pitsidianakis 
702022cdc9fSManos Pitsidianakis     g_assert(!strcmp(throttle_group_get_name(tgm1), "bar"));
703022cdc9fSManos Pitsidianakis     g_assert(!strcmp(throttle_group_get_name(tgm2), "foo"));
704022cdc9fSManos Pitsidianakis     g_assert(tgm1->throttle_state == tgm3->throttle_state);
7051fee955fSAlberto Garcia 
7061fee955fSAlberto Garcia     /* Setting the config of a group member affects the whole group */
7071588ab5dSAlberto Garcia     throttle_config_init(&cfg1);
7081fee955fSAlberto Garcia     cfg1.buckets[THROTTLE_BPS_READ].avg  = 500000;
7091fee955fSAlberto Garcia     cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000;
7101fee955fSAlberto Garcia     cfg1.buckets[THROTTLE_OPS_READ].avg  = 20000;
7111fee955fSAlberto Garcia     cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000;
712022cdc9fSManos Pitsidianakis     throttle_group_config(tgm1, &cfg1);
7131fee955fSAlberto Garcia 
714022cdc9fSManos Pitsidianakis     throttle_group_get_config(tgm1, &cfg1);
715022cdc9fSManos Pitsidianakis     throttle_group_get_config(tgm3, &cfg2);
7161fee955fSAlberto Garcia     g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
7171fee955fSAlberto Garcia 
7181fee955fSAlberto Garcia     cfg2.buckets[THROTTLE_BPS_READ].avg  = 4547;
7191fee955fSAlberto Garcia     cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349;
7201fee955fSAlberto Garcia     cfg2.buckets[THROTTLE_OPS_READ].avg  = 123;
7211fee955fSAlberto Garcia     cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86;
722022cdc9fSManos Pitsidianakis     throttle_group_config(tgm3, &cfg1);
7231fee955fSAlberto Garcia 
724022cdc9fSManos Pitsidianakis     throttle_group_get_config(tgm1, &cfg1);
725022cdc9fSManos Pitsidianakis     throttle_group_get_config(tgm3, &cfg2);
7261fee955fSAlberto Garcia     g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
7271fee955fSAlberto Garcia 
728022cdc9fSManos Pitsidianakis     throttle_group_unregister_tgm(tgm1);
729022cdc9fSManos Pitsidianakis     throttle_group_unregister_tgm(tgm2);
730022cdc9fSManos Pitsidianakis     throttle_group_unregister_tgm(tgm3);
7311fee955fSAlberto Garcia 
732022cdc9fSManos Pitsidianakis     g_assert(tgm1->throttle_state == NULL);
733022cdc9fSManos Pitsidianakis     g_assert(tgm2->throttle_state == NULL);
734022cdc9fSManos Pitsidianakis     g_assert(tgm3->throttle_state == NULL);
7351fee955fSAlberto Garcia }
7361fee955fSAlberto Garcia 
737f17cfe81SBenoît Canet int main(int argc, char **argv)
738f17cfe81SBenoît Canet {
73973eaa047SMarkus Armbruster     qemu_init_main_loop(&error_fatal);
7401fee955fSAlberto Garcia     ctx = qemu_get_aio_context();
7411fee955fSAlberto Garcia     bdrv_init();
742432d889eSManos Pitsidianakis     module_call_init(MODULE_INIT_QOM);
74313af91ebSStefan Hajnoczi 
744f17cfe81SBenoît Canet     do {} while (g_main_context_iteration(NULL, false));
745f17cfe81SBenoît Canet 
746f17cfe81SBenoît Canet     /* tests in the same order as the header function declarations */
747f17cfe81SBenoît Canet     g_test_init(&argc, &argv, NULL);
748f17cfe81SBenoît Canet     g_test_add_func("/throttle/leak_bucket",        test_leak_bucket);
749f17cfe81SBenoît Canet     g_test_add_func("/throttle/compute_wait",       test_compute_wait);
750f17cfe81SBenoît Canet     g_test_add_func("/throttle/init",               test_init);
751f17cfe81SBenoît Canet     g_test_add_func("/throttle/destroy",            test_destroy);
752f17cfe81SBenoît Canet     g_test_add_func("/throttle/have_timer",         test_have_timer);
75322524f72SStefan Hajnoczi     g_test_add_func("/throttle/detach_attach",      test_detach_attach);
754f17cfe81SBenoît Canet     g_test_add_func("/throttle/config/enabled",     test_enabled);
755f17cfe81SBenoît Canet     g_test_add_func("/throttle/config/conflicting", test_conflicting_config);
756f17cfe81SBenoît Canet     g_test_add_func("/throttle/config/is_valid",    test_is_valid);
757d942feecSAlberto Garcia     g_test_add_func("/throttle/config/ranges",      test_ranges);
75892e11a17SStefan Hajnoczi     g_test_add_func("/throttle/config/max",         test_max_is_missing_limit);
7598860eabdSStefan Hajnoczi     g_test_add_func("/throttle/config/iops_size",
7608860eabdSStefan Hajnoczi                     test_iops_size_is_missing_limit);
761f17cfe81SBenoît Canet     g_test_add_func("/throttle/config_functions",   test_config_functions);
762f17cfe81SBenoît Canet     g_test_add_func("/throttle/accounting",         test_accounting);
7631fee955fSAlberto Garcia     g_test_add_func("/throttle/groups",             test_groups);
764f17cfe81SBenoît Canet     return g_test_run();
765f17cfe81SBenoît Canet }
766f17cfe81SBenoît Canet 
767