xref: /qemu/tests/unit/test-throttle.c (revision 1322f63df52e23ecf47cc9a5842ec3099c517183)
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"
2431dce3ccSKevin Wolf #include "sysemu/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 */
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 */
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 
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++) {
130f9d05885SAlberto Garcia         double units = bkt.max / 10;
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));
136f9d05885SAlberto Garcia         g_assert(double_cmp(bkt.level, (i + 1) * (bkt.max - bkt.avg) / 10));
137f9d05885SAlberto Garcia         /* We can do bursts for the 2 seconds we have configured in
138f9d05885SAlberto Garcia          * burst_length. We have 100 extra miliseconds 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 */
147f17cfe81SBenoît Canet static void read_timer_cb(void *opaque)
148f17cfe81SBenoît Canet {
149f17cfe81SBenoît Canet }
150f17cfe81SBenoît Canet 
151f17cfe81SBenoît Canet static void write_timer_cb(void *opaque)
152f17cfe81SBenoît Canet {
153f17cfe81SBenoît Canet }
154f17cfe81SBenoît Canet 
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);
172*1322f63dSzhenwei pi     g_assert(tt->timers[THROTTLE_READ]);
173*1322f63dSzhenwei 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 
187f17cfe81SBenoît Canet static void test_destroy(void)
188f17cfe81SBenoît Canet {
189f17cfe81SBenoît Canet     int i;
1900e5b0a2dSBenoît Canet     throttle_init(&ts);
191c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
19213af91ebSStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
193c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
194*1322f63dSzhenwei pi     for (i = 0; i < THROTTLE_MAX; i++) {
195c61791fcSManos Pitsidianakis         g_assert(!tt->timers[i]);
196f17cfe81SBenoît Canet     }
197f17cfe81SBenoît Canet }
198f17cfe81SBenoît Canet 
199f17cfe81SBenoît Canet /* function to test throttle_config and throttle_get_config */
200f17cfe81SBenoît Canet static void test_config_functions(void)
201f17cfe81SBenoît Canet {
202f17cfe81SBenoît Canet     int i;
203f17cfe81SBenoît Canet     ThrottleConfig orig_cfg, final_cfg;
204f17cfe81SBenoît Canet 
205f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_TOTAL].avg = 153;
206f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_READ].avg  = 56;
207f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_WRITE].avg = 1;
208f17cfe81SBenoît Canet 
209f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_TOTAL].avg = 150;
210f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_READ].avg  = 69;
211f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_WRITE].avg = 23;
212f17cfe81SBenoît Canet 
213d72915c6SStefan Hajnoczi     orig_cfg.buckets[THROTTLE_BPS_TOTAL].max = 0;
214d72915c6SStefan Hajnoczi     orig_cfg.buckets[THROTTLE_BPS_READ].max  = 56;
215f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_WRITE].max = 120;
216f17cfe81SBenoît Canet 
217f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_TOTAL].max = 150;
218f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_READ].max  = 400;
219f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_WRITE].max = 500;
220f17cfe81SBenoît Canet 
221f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_TOTAL].level = 45;
222f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_READ].level  = 65;
223f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_BPS_WRITE].level = 23;
224f17cfe81SBenoît Canet 
225f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_TOTAL].level = 1;
226f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_READ].level  = 90;
227f17cfe81SBenoît Canet     orig_cfg.buckets[THROTTLE_OPS_WRITE].level = 75;
228f17cfe81SBenoît Canet 
229f17cfe81SBenoît Canet     orig_cfg.op_size = 1;
230f17cfe81SBenoît Canet 
2310e5b0a2dSBenoît Canet     throttle_init(&ts);
232c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
23313af91ebSStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
234f17cfe81SBenoît Canet     /* structure reset by throttle_init previous_leak should be null */
235f17cfe81SBenoît Canet     g_assert(!ts.previous_leak);
23627e4cf13SManos Pitsidianakis     throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &orig_cfg);
237f17cfe81SBenoît Canet 
238f17cfe81SBenoît Canet     /* has previous leak been initialized by throttle_config ? */
239f17cfe81SBenoît Canet     g_assert(ts.previous_leak);
240f17cfe81SBenoît Canet 
241f17cfe81SBenoît Canet     /* get back the fixed configuration */
242f17cfe81SBenoît Canet     throttle_get_config(&ts, &final_cfg);
243f17cfe81SBenoît Canet 
244c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
245f17cfe81SBenoît Canet 
246f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153);
247f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg  == 56);
248f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].avg == 1);
249f17cfe81SBenoît Canet 
250f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].avg == 150);
251f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_READ].avg  == 69);
252f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].avg == 23);
253f17cfe81SBenoît Canet 
254d72915c6SStefan Hajnoczi     g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].max == 0);
255d72915c6SStefan Hajnoczi     g_assert(final_cfg.buckets[THROTTLE_BPS_READ].max  == 56);
256f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].max == 120);
257f17cfe81SBenoît Canet 
258f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].max == 150);
259f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_READ].max  == 400);
260f17cfe81SBenoît Canet     g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].max == 500);
261f17cfe81SBenoît Canet 
262f17cfe81SBenoît Canet     g_assert(final_cfg.op_size == 1);
263f17cfe81SBenoît Canet 
264f17cfe81SBenoît Canet     /* check bucket have been cleared */
265f17cfe81SBenoît Canet     for (i = 0; i < BUCKETS_COUNT; i++) {
266f17cfe81SBenoît Canet         g_assert(!final_cfg.buckets[i].level);
267f17cfe81SBenoît Canet     }
268f17cfe81SBenoît Canet }
269f17cfe81SBenoît Canet 
270f17cfe81SBenoît Canet /* functions to test is throttle is enabled by a config */
271f17cfe81SBenoît Canet static void set_cfg_value(bool is_max, int index, int value)
272f17cfe81SBenoît Canet {
273f17cfe81SBenoît Canet     if (is_max) {
274f17cfe81SBenoît Canet         cfg.buckets[index].max = value;
2756f9b6d57SAlberto Garcia         /* If max is set, avg should never be 0 */
2766f9b6d57SAlberto Garcia         cfg.buckets[index].avg = MAX(cfg.buckets[index].avg, 1);
277f17cfe81SBenoît Canet     } else {
278f17cfe81SBenoît Canet         cfg.buckets[index].avg = value;
279f17cfe81SBenoît Canet     }
280f17cfe81SBenoît Canet }
281f17cfe81SBenoît Canet 
282f17cfe81SBenoît Canet static void test_enabled(void)
283f17cfe81SBenoît Canet {
284f17cfe81SBenoît Canet     int i;
285f17cfe81SBenoît Canet 
2861588ab5dSAlberto Garcia     throttle_config_init(&cfg);
287f17cfe81SBenoît Canet     g_assert(!throttle_enabled(&cfg));
288f17cfe81SBenoît Canet 
289f17cfe81SBenoît Canet     for (i = 0; i < BUCKETS_COUNT; i++) {
2901588ab5dSAlberto Garcia         throttle_config_init(&cfg);
291f17cfe81SBenoît Canet         set_cfg_value(false, i, 150);
292d00e6923SAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
293f17cfe81SBenoît Canet         g_assert(throttle_enabled(&cfg));
294f17cfe81SBenoît Canet     }
295f17cfe81SBenoît Canet 
296f17cfe81SBenoît Canet     for (i = 0; i < BUCKETS_COUNT; i++) {
2971588ab5dSAlberto Garcia         throttle_config_init(&cfg);
298f17cfe81SBenoît Canet         set_cfg_value(false, i, -150);
299d00e6923SAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
300f17cfe81SBenoît Canet     }
301f17cfe81SBenoît Canet }
302f17cfe81SBenoît Canet 
303f17cfe81SBenoît Canet /* tests functions for throttle_conflicting */
304f17cfe81SBenoît Canet 
305f17cfe81SBenoît Canet static void test_conflicts_for_one_set(bool is_max,
306f17cfe81SBenoît Canet                                        int total,
307f17cfe81SBenoît Canet                                        int read,
308f17cfe81SBenoît Canet                                        int write)
309f17cfe81SBenoît Canet {
3101588ab5dSAlberto Garcia     throttle_config_init(&cfg);
311d5851089SAlberto Garcia     g_assert(throttle_is_valid(&cfg, NULL));
312f17cfe81SBenoît Canet 
313f17cfe81SBenoît Canet     set_cfg_value(is_max, total, 1);
314f17cfe81SBenoît Canet     set_cfg_value(is_max, read,  1);
315d5851089SAlberto Garcia     g_assert(!throttle_is_valid(&cfg, NULL));
316f17cfe81SBenoît Canet 
3171588ab5dSAlberto Garcia     throttle_config_init(&cfg);
318f17cfe81SBenoît Canet     set_cfg_value(is_max, total, 1);
319f17cfe81SBenoît Canet     set_cfg_value(is_max, write, 1);
320d5851089SAlberto Garcia     g_assert(!throttle_is_valid(&cfg, NULL));
321f17cfe81SBenoît Canet 
3221588ab5dSAlberto Garcia     throttle_config_init(&cfg);
323f17cfe81SBenoît Canet     set_cfg_value(is_max, total, 1);
324f17cfe81SBenoît Canet     set_cfg_value(is_max, read,  1);
325f17cfe81SBenoît Canet     set_cfg_value(is_max, write, 1);
326d5851089SAlberto Garcia     g_assert(!throttle_is_valid(&cfg, NULL));
327f17cfe81SBenoît Canet 
3281588ab5dSAlberto Garcia     throttle_config_init(&cfg);
329f17cfe81SBenoît Canet     set_cfg_value(is_max, total, 1);
330d5851089SAlberto Garcia     g_assert(throttle_is_valid(&cfg, NULL));
331f17cfe81SBenoît Canet 
3321588ab5dSAlberto Garcia     throttle_config_init(&cfg);
333f17cfe81SBenoît Canet     set_cfg_value(is_max, read,  1);
334f17cfe81SBenoît Canet     set_cfg_value(is_max, write, 1);
335d5851089SAlberto Garcia     g_assert(throttle_is_valid(&cfg, NULL));
336f17cfe81SBenoît Canet }
337f17cfe81SBenoît Canet 
338f17cfe81SBenoît Canet static void test_conflicting_config(void)
339f17cfe81SBenoît Canet {
340f17cfe81SBenoît Canet     /* bps average conflicts */
341f17cfe81SBenoît Canet     test_conflicts_for_one_set(false,
342f17cfe81SBenoît Canet                                THROTTLE_BPS_TOTAL,
343f17cfe81SBenoît Canet                                THROTTLE_BPS_READ,
344f17cfe81SBenoît Canet                                THROTTLE_BPS_WRITE);
345f17cfe81SBenoît Canet 
346f17cfe81SBenoît Canet     /* ops average conflicts */
347f17cfe81SBenoît Canet     test_conflicts_for_one_set(false,
348f17cfe81SBenoît Canet                                THROTTLE_OPS_TOTAL,
349f17cfe81SBenoît Canet                                THROTTLE_OPS_READ,
350f17cfe81SBenoît Canet                                THROTTLE_OPS_WRITE);
351f17cfe81SBenoît Canet 
352f17cfe81SBenoît Canet     /* bps average conflicts */
353f17cfe81SBenoît Canet     test_conflicts_for_one_set(true,
354f17cfe81SBenoît Canet                                THROTTLE_BPS_TOTAL,
355f17cfe81SBenoît Canet                                THROTTLE_BPS_READ,
356f17cfe81SBenoît Canet                                THROTTLE_BPS_WRITE);
357f17cfe81SBenoît Canet     /* ops average conflicts */
358f17cfe81SBenoît Canet     test_conflicts_for_one_set(true,
359f17cfe81SBenoît Canet                                THROTTLE_OPS_TOTAL,
360f17cfe81SBenoît Canet                                THROTTLE_OPS_READ,
361f17cfe81SBenoît Canet                                THROTTLE_OPS_WRITE);
362f17cfe81SBenoît Canet }
363f17cfe81SBenoît Canet /* functions to test the throttle_is_valid function */
364f17cfe81SBenoît Canet static void test_is_valid_for_value(int value, bool should_be_valid)
365f17cfe81SBenoît Canet {
366f17cfe81SBenoît Canet     int is_max, index;
367f17cfe81SBenoît Canet     for (is_max = 0; is_max < 2; is_max++) {
368f17cfe81SBenoît Canet         for (index = 0; index < BUCKETS_COUNT; index++) {
3691588ab5dSAlberto Garcia             throttle_config_init(&cfg);
370f17cfe81SBenoît Canet             set_cfg_value(is_max, index, value);
37103ba36c8SAlberto Garcia             g_assert(throttle_is_valid(&cfg, NULL) == should_be_valid);
372f17cfe81SBenoît Canet         }
373f17cfe81SBenoît Canet     }
374f17cfe81SBenoît Canet }
375f17cfe81SBenoît Canet 
376f17cfe81SBenoît Canet static void test_is_valid(void)
377f17cfe81SBenoît Canet {
378f17cfe81SBenoît Canet     /* negative number are invalid */
379f17cfe81SBenoît Canet     test_is_valid_for_value(-1, false);
380f17cfe81SBenoît Canet     /* zero are valids */
381f17cfe81SBenoît Canet     test_is_valid_for_value(0, true);
382f17cfe81SBenoît Canet     /* positives numers are valids */
383f17cfe81SBenoît Canet     test_is_valid_for_value(1, true);
384f17cfe81SBenoît Canet }
385f17cfe81SBenoît Canet 
386d942feecSAlberto Garcia static void test_ranges(void)
387d942feecSAlberto Garcia {
388d942feecSAlberto Garcia     int i;
389d942feecSAlberto Garcia 
390d942feecSAlberto Garcia     for (i = 0; i < BUCKETS_COUNT; i++) {
391d942feecSAlberto Garcia         LeakyBucket *b = &cfg.buckets[i];
392d942feecSAlberto Garcia         throttle_config_init(&cfg);
393d942feecSAlberto Garcia 
394d942feecSAlberto Garcia         /* avg = 0 means throttling is disabled, but the config is valid */
395d942feecSAlberto Garcia         b->avg = 0;
396d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
397d942feecSAlberto Garcia         g_assert(!throttle_enabled(&cfg));
398d942feecSAlberto Garcia 
399d942feecSAlberto Garcia         /* These are valid configurations (values <= THROTTLE_VALUE_MAX) */
400d942feecSAlberto Garcia         b->avg = 1;
401d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
402d942feecSAlberto Garcia 
403d942feecSAlberto Garcia         b->avg = THROTTLE_VALUE_MAX;
404d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
405d942feecSAlberto Garcia 
406d942feecSAlberto Garcia         b->avg = THROTTLE_VALUE_MAX;
407d942feecSAlberto Garcia         b->max = THROTTLE_VALUE_MAX;
408d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
409d942feecSAlberto Garcia 
410d942feecSAlberto Garcia         /* Values over THROTTLE_VALUE_MAX are not allowed */
411d942feecSAlberto Garcia         b->avg = THROTTLE_VALUE_MAX + 1;
412d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
413d942feecSAlberto Garcia 
414d942feecSAlberto Garcia         b->avg = THROTTLE_VALUE_MAX;
415d942feecSAlberto Garcia         b->max = THROTTLE_VALUE_MAX + 1;
416d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
417d942feecSAlberto Garcia 
418d942feecSAlberto Garcia         /* burst_length must be between 1 and THROTTLE_VALUE_MAX */
419d942feecSAlberto Garcia         b->avg = 1;
420d942feecSAlberto Garcia         b->max = 1;
421d942feecSAlberto Garcia         b->burst_length = 0;
422d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
423d942feecSAlberto Garcia 
424d942feecSAlberto Garcia         b->avg = 1;
425d942feecSAlberto Garcia         b->max = 1;
426d942feecSAlberto Garcia         b->burst_length = 1;
427d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
428d942feecSAlberto Garcia 
429d942feecSAlberto Garcia         b->avg = 1;
430d942feecSAlberto Garcia         b->max = 1;
431d942feecSAlberto Garcia         b->burst_length = THROTTLE_VALUE_MAX;
432d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
433d942feecSAlberto Garcia 
434d942feecSAlberto Garcia         b->avg = 1;
435d942feecSAlberto Garcia         b->max = 1;
436d942feecSAlberto Garcia         b->burst_length = THROTTLE_VALUE_MAX + 1;
437d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
438d942feecSAlberto Garcia 
439d942feecSAlberto Garcia         /* burst_length * max cannot exceed THROTTLE_VALUE_MAX */
440d942feecSAlberto Garcia         b->avg = 1;
441d942feecSAlberto Garcia         b->max = 2;
442d942feecSAlberto Garcia         b->burst_length = THROTTLE_VALUE_MAX / 2;
443d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
444d942feecSAlberto Garcia 
445d942feecSAlberto Garcia         b->avg = 1;
446d942feecSAlberto Garcia         b->max = 3;
447d942feecSAlberto Garcia         b->burst_length = THROTTLE_VALUE_MAX / 2;
448d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
449d942feecSAlberto Garcia 
450d942feecSAlberto Garcia         b->avg = 1;
451d942feecSAlberto Garcia         b->max = THROTTLE_VALUE_MAX;
452d942feecSAlberto Garcia         b->burst_length = 1;
453d942feecSAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
454d942feecSAlberto Garcia 
455d942feecSAlberto Garcia         b->avg = 1;
456d942feecSAlberto Garcia         b->max = THROTTLE_VALUE_MAX;
457d942feecSAlberto Garcia         b->burst_length = 2;
458d942feecSAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
459d942feecSAlberto Garcia     }
460d942feecSAlberto Garcia }
461d942feecSAlberto Garcia 
46292e11a17SStefan Hajnoczi static void test_max_is_missing_limit(void)
46392e11a17SStefan Hajnoczi {
46492e11a17SStefan Hajnoczi     int i;
46592e11a17SStefan Hajnoczi 
46692e11a17SStefan Hajnoczi     for (i = 0; i < BUCKETS_COUNT; i++) {
4671588ab5dSAlberto Garcia         throttle_config_init(&cfg);
46892e11a17SStefan Hajnoczi         cfg.buckets[i].max = 100;
46992e11a17SStefan Hajnoczi         cfg.buckets[i].avg = 0;
470d5851089SAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
47192e11a17SStefan Hajnoczi 
47292e11a17SStefan Hajnoczi         cfg.buckets[i].max = 0;
47392e11a17SStefan Hajnoczi         cfg.buckets[i].avg = 0;
474d5851089SAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
47592e11a17SStefan Hajnoczi 
47692e11a17SStefan Hajnoczi         cfg.buckets[i].max = 0;
47792e11a17SStefan Hajnoczi         cfg.buckets[i].avg = 100;
478d5851089SAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
4795fc8c052SAlberto Garcia 
4805fc8c052SAlberto Garcia         cfg.buckets[i].max = 30;
4815fc8c052SAlberto Garcia         cfg.buckets[i].avg = 100;
4825fc8c052SAlberto Garcia         g_assert(!throttle_is_valid(&cfg, NULL));
4835fc8c052SAlberto Garcia 
4845fc8c052SAlberto Garcia         cfg.buckets[i].max = 100;
4855fc8c052SAlberto Garcia         cfg.buckets[i].avg = 100;
4865fc8c052SAlberto Garcia         g_assert(throttle_is_valid(&cfg, NULL));
48792e11a17SStefan Hajnoczi     }
48892e11a17SStefan Hajnoczi }
48992e11a17SStefan Hajnoczi 
4908860eabdSStefan Hajnoczi static void test_iops_size_is_missing_limit(void)
4918860eabdSStefan Hajnoczi {
4928860eabdSStefan Hajnoczi     /* A total/read/write iops limit is required */
4938860eabdSStefan Hajnoczi     throttle_config_init(&cfg);
4948860eabdSStefan Hajnoczi     cfg.op_size = 4096;
4958860eabdSStefan Hajnoczi     g_assert(!throttle_is_valid(&cfg, NULL));
4968860eabdSStefan Hajnoczi }
4978860eabdSStefan Hajnoczi 
498f17cfe81SBenoît Canet static void test_have_timer(void)
499f17cfe81SBenoît Canet {
5000e5b0a2dSBenoît Canet     /* zero structures */
501f17cfe81SBenoît Canet     memset(&ts, 0, sizeof(ts));
502c61791fcSManos Pitsidianakis     memset(tt, 0, sizeof(*tt));
503f17cfe81SBenoît Canet 
50473f395faSStefan Weil     /* no timer set should return false */
505c61791fcSManos Pitsidianakis     g_assert(!throttle_timers_are_initialized(tt));
506f17cfe81SBenoît Canet 
5070e5b0a2dSBenoît Canet     /* init structures */
5080e5b0a2dSBenoît Canet     throttle_init(&ts);
509c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
51013af91ebSStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
511f17cfe81SBenoît Canet 
512f17cfe81SBenoît Canet     /* timer set by init should return true */
513c61791fcSManos Pitsidianakis     g_assert(throttle_timers_are_initialized(tt));
514f17cfe81SBenoît Canet 
515c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
516f17cfe81SBenoît Canet }
517f17cfe81SBenoît Canet 
51822524f72SStefan Hajnoczi static void test_detach_attach(void)
51922524f72SStefan Hajnoczi {
5200e5b0a2dSBenoît Canet     /* zero structures */
52122524f72SStefan Hajnoczi     memset(&ts, 0, sizeof(ts));
522c61791fcSManos Pitsidianakis     memset(tt, 0, sizeof(*tt));
52322524f72SStefan Hajnoczi 
52422524f72SStefan Hajnoczi     /* init the structure */
5250e5b0a2dSBenoît Canet     throttle_init(&ts);
526c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
52722524f72SStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
52822524f72SStefan Hajnoczi 
52922524f72SStefan Hajnoczi     /* timer set by init should return true */
530c61791fcSManos Pitsidianakis     g_assert(throttle_timers_are_initialized(tt));
53122524f72SStefan Hajnoczi 
53222524f72SStefan Hajnoczi     /* timer should no longer exist after detaching */
533c61791fcSManos Pitsidianakis     throttle_timers_detach_aio_context(tt);
534c61791fcSManos Pitsidianakis     g_assert(!throttle_timers_are_initialized(tt));
53522524f72SStefan Hajnoczi 
53622524f72SStefan Hajnoczi     /* timer should exist again after attaching */
537c61791fcSManos Pitsidianakis     throttle_timers_attach_aio_context(tt, ctx);
538c61791fcSManos Pitsidianakis     g_assert(throttle_timers_are_initialized(tt));
53922524f72SStefan Hajnoczi 
540c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
54122524f72SStefan Hajnoczi }
54222524f72SStefan Hajnoczi 
543f17cfe81SBenoît Canet static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
544f17cfe81SBenoît Canet                 int size,                   /* size of the operation to do */
545f17cfe81SBenoît Canet                 double avg,                 /* io limit */
546f17cfe81SBenoît Canet                 uint64_t op_size,           /* ideal size of an io */
547f17cfe81SBenoît Canet                 double total_result,
548f17cfe81SBenoît Canet                 double read_result,
549f17cfe81SBenoît Canet                 double write_result)
550f17cfe81SBenoît Canet {
551f17cfe81SBenoît Canet     BucketType to_test[2][3] = { { THROTTLE_BPS_TOTAL,
552f17cfe81SBenoît Canet                                    THROTTLE_BPS_READ,
553f17cfe81SBenoît Canet                                    THROTTLE_BPS_WRITE, },
554f17cfe81SBenoît Canet                                  { THROTTLE_OPS_TOTAL,
555f17cfe81SBenoît Canet                                    THROTTLE_OPS_READ,
556f17cfe81SBenoît Canet                                    THROTTLE_OPS_WRITE, } };
557f17cfe81SBenoît Canet     ThrottleConfig cfg;
558f17cfe81SBenoît Canet     BucketType index;
559f17cfe81SBenoît Canet     int i;
560f17cfe81SBenoît Canet 
561ef0aa6afSAndrey Shinkevich     throttle_config_init(&cfg);
562ef0aa6afSAndrey Shinkevich 
563f17cfe81SBenoît Canet     for (i = 0; i < 3; i++) {
564f17cfe81SBenoît Canet         BucketType index = to_test[is_ops][i];
565f17cfe81SBenoît Canet         cfg.buckets[index].avg = avg;
566f17cfe81SBenoît Canet     }
567f17cfe81SBenoît Canet 
568f17cfe81SBenoît Canet     cfg.op_size = op_size;
569f17cfe81SBenoît Canet 
5700e5b0a2dSBenoît Canet     throttle_init(&ts);
571c61791fcSManos Pitsidianakis     throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
57213af91ebSStefan Hajnoczi                          read_timer_cb, write_timer_cb, &ts);
57327e4cf13SManos Pitsidianakis     throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &cfg);
574f17cfe81SBenoît Canet 
575f17cfe81SBenoît Canet     /* account a read */
576f17cfe81SBenoît Canet     throttle_account(&ts, false, size);
577f17cfe81SBenoît Canet     /* account a write */
578f17cfe81SBenoît Canet     throttle_account(&ts, true, size);
579f17cfe81SBenoît Canet 
580f17cfe81SBenoît Canet     /* check total result */
581f17cfe81SBenoît Canet     index = to_test[is_ops][0];
582f17cfe81SBenoît Canet     if (!double_cmp(ts.cfg.buckets[index].level, total_result)) {
583f17cfe81SBenoît Canet         return false;
584f17cfe81SBenoît Canet     }
585f17cfe81SBenoît Canet 
586f17cfe81SBenoît Canet     /* check read result */
587f17cfe81SBenoît Canet     index = to_test[is_ops][1];
588f17cfe81SBenoît Canet     if (!double_cmp(ts.cfg.buckets[index].level, read_result)) {
589f17cfe81SBenoît Canet         return false;
590f17cfe81SBenoît Canet     }
591f17cfe81SBenoît Canet 
592f17cfe81SBenoît Canet     /* check write result */
593f17cfe81SBenoît Canet     index = to_test[is_ops][2];
594f17cfe81SBenoît Canet     if (!double_cmp(ts.cfg.buckets[index].level, write_result)) {
595f17cfe81SBenoît Canet         return false;
596f17cfe81SBenoît Canet     }
597f17cfe81SBenoît Canet 
598c61791fcSManos Pitsidianakis     throttle_timers_destroy(tt);
599f17cfe81SBenoît Canet 
600f17cfe81SBenoît Canet     return true;
601f17cfe81SBenoît Canet }
602f17cfe81SBenoît Canet 
603f17cfe81SBenoît Canet static void test_accounting(void)
604f17cfe81SBenoît Canet {
605f17cfe81SBenoît Canet     /* tests for bps */
606f17cfe81SBenoît Canet 
607f17cfe81SBenoît Canet     /* op of size 1 */
608f17cfe81SBenoît Canet     g_assert(do_test_accounting(false,
609f17cfe81SBenoît Canet                                 1 * 512,
610f17cfe81SBenoît Canet                                 150,
611f17cfe81SBenoît Canet                                 0,
612f17cfe81SBenoît Canet                                 1024,
613f17cfe81SBenoît Canet                                 512,
614f17cfe81SBenoît Canet                                 512));
615f17cfe81SBenoît Canet 
616f17cfe81SBenoît Canet     /* op of size 2 */
617f17cfe81SBenoît Canet     g_assert(do_test_accounting(false,
618f17cfe81SBenoît Canet                                 2 * 512,
619f17cfe81SBenoît Canet                                 150,
620f17cfe81SBenoît Canet                                 0,
621f17cfe81SBenoît Canet                                 2048,
622f17cfe81SBenoît Canet                                 1024,
623f17cfe81SBenoît Canet                                 1024));
624f17cfe81SBenoît Canet 
625f17cfe81SBenoît Canet     /* op of size 2 and orthogonal parameter change */
626f17cfe81SBenoît Canet     g_assert(do_test_accounting(false,
627f17cfe81SBenoît Canet                                 2 * 512,
628f17cfe81SBenoît Canet                                 150,
629f17cfe81SBenoît Canet                                 17,
630f17cfe81SBenoît Canet                                 2048,
631f17cfe81SBenoît Canet                                 1024,
632f17cfe81SBenoît Canet                                 1024));
633f17cfe81SBenoît Canet 
634f17cfe81SBenoît Canet 
635f17cfe81SBenoît Canet     /* tests for ops */
636f17cfe81SBenoît Canet 
637f17cfe81SBenoît Canet     /* op of size 1 */
638f17cfe81SBenoît Canet     g_assert(do_test_accounting(true,
639f17cfe81SBenoît Canet                                 1 * 512,
640f17cfe81SBenoît Canet                                 150,
641f17cfe81SBenoît Canet                                 0,
642f17cfe81SBenoît Canet                                 2,
643f17cfe81SBenoît Canet                                 1,
644f17cfe81SBenoît Canet                                 1));
645f17cfe81SBenoît Canet 
646f17cfe81SBenoît Canet     /* op of size 2 */
647f17cfe81SBenoît Canet     g_assert(do_test_accounting(true,
648f17cfe81SBenoît Canet                                 2 *  512,
649f17cfe81SBenoît Canet                                 150,
650f17cfe81SBenoît Canet                                 0,
651f17cfe81SBenoît Canet                                 2,
652f17cfe81SBenoît Canet                                 1,
653f17cfe81SBenoît Canet                                 1));
654f17cfe81SBenoît Canet 
655f17cfe81SBenoît Canet     /* jumbo op accounting fragmentation : size 64 with op size of 13 units */
656f17cfe81SBenoît Canet     g_assert(do_test_accounting(true,
657f17cfe81SBenoît Canet                                 64 * 512,
658f17cfe81SBenoît Canet                                 150,
659f17cfe81SBenoît Canet                                 13 * 512,
660f17cfe81SBenoît Canet                                 (64.0 * 2) / 13,
661f17cfe81SBenoît Canet                                 (64.0 / 13),
662f17cfe81SBenoît Canet                                 (64.0 / 13)));
663f17cfe81SBenoît Canet 
664f17cfe81SBenoît Canet     /* same with orthogonal parameters changes */
665f17cfe81SBenoît Canet     g_assert(do_test_accounting(true,
666f17cfe81SBenoît Canet                                 64 * 512,
667f17cfe81SBenoît Canet                                 300,
668f17cfe81SBenoît Canet                                 13 * 512,
669f17cfe81SBenoît Canet                                 (64.0 * 2) / 13,
670f17cfe81SBenoît Canet                                 (64.0 / 13),
671f17cfe81SBenoît Canet                                 (64.0 / 13)));
672f17cfe81SBenoît Canet }
673f17cfe81SBenoît Canet 
6741fee955fSAlberto Garcia static void test_groups(void)
6751fee955fSAlberto Garcia {
6761fee955fSAlberto Garcia     ThrottleConfig cfg1, cfg2;
677a5614993SKevin Wolf     BlockBackend *blk1, *blk2, *blk3;
67827ccdd52SKevin Wolf     BlockBackendPublic *blkp1, *blkp2, *blkp3;
679022cdc9fSManos Pitsidianakis     ThrottleGroupMember *tgm1, *tgm2, *tgm3;
6801fee955fSAlberto Garcia 
6812807c0cdSKevin Wolf     /* No actual I/O is performed on these devices */
682d861ab3aSKevin Wolf     blk1 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
683d861ab3aSKevin Wolf     blk2 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
684d861ab3aSKevin Wolf     blk3 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
685a5614993SKevin Wolf 
68627ccdd52SKevin Wolf     blkp1 = blk_get_public(blk1);
68727ccdd52SKevin Wolf     blkp2 = blk_get_public(blk2);
68827ccdd52SKevin Wolf     blkp3 = blk_get_public(blk3);
68927ccdd52SKevin Wolf 
690022cdc9fSManos Pitsidianakis     tgm1 = &blkp1->throttle_group_member;
691022cdc9fSManos Pitsidianakis     tgm2 = &blkp2->throttle_group_member;
692022cdc9fSManos Pitsidianakis     tgm3 = &blkp3->throttle_group_member;
6931fee955fSAlberto Garcia 
694022cdc9fSManos Pitsidianakis     g_assert(tgm1->throttle_state == NULL);
695022cdc9fSManos Pitsidianakis     g_assert(tgm2->throttle_state == NULL);
696022cdc9fSManos Pitsidianakis     g_assert(tgm3->throttle_state == NULL);
6971fee955fSAlberto Garcia 
698c61791fcSManos Pitsidianakis     throttle_group_register_tgm(tgm1, "bar", blk_get_aio_context(blk1));
699c61791fcSManos Pitsidianakis     throttle_group_register_tgm(tgm2, "foo", blk_get_aio_context(blk2));
700c61791fcSManos Pitsidianakis     throttle_group_register_tgm(tgm3, "bar", blk_get_aio_context(blk3));
7011fee955fSAlberto Garcia 
702022cdc9fSManos Pitsidianakis     g_assert(tgm1->throttle_state != NULL);
703022cdc9fSManos Pitsidianakis     g_assert(tgm2->throttle_state != NULL);
704022cdc9fSManos Pitsidianakis     g_assert(tgm3->throttle_state != NULL);
705022cdc9fSManos Pitsidianakis 
706022cdc9fSManos Pitsidianakis     g_assert(!strcmp(throttle_group_get_name(tgm1), "bar"));
707022cdc9fSManos Pitsidianakis     g_assert(!strcmp(throttle_group_get_name(tgm2), "foo"));
708022cdc9fSManos Pitsidianakis     g_assert(tgm1->throttle_state == tgm3->throttle_state);
7091fee955fSAlberto Garcia 
7101fee955fSAlberto Garcia     /* Setting the config of a group member affects the whole group */
7111588ab5dSAlberto Garcia     throttle_config_init(&cfg1);
7121fee955fSAlberto Garcia     cfg1.buckets[THROTTLE_BPS_READ].avg  = 500000;
7131fee955fSAlberto Garcia     cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000;
7141fee955fSAlberto Garcia     cfg1.buckets[THROTTLE_OPS_READ].avg  = 20000;
7151fee955fSAlberto Garcia     cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000;
716022cdc9fSManos Pitsidianakis     throttle_group_config(tgm1, &cfg1);
7171fee955fSAlberto Garcia 
718022cdc9fSManos Pitsidianakis     throttle_group_get_config(tgm1, &cfg1);
719022cdc9fSManos Pitsidianakis     throttle_group_get_config(tgm3, &cfg2);
7201fee955fSAlberto Garcia     g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
7211fee955fSAlberto Garcia 
7221fee955fSAlberto Garcia     cfg2.buckets[THROTTLE_BPS_READ].avg  = 4547;
7231fee955fSAlberto Garcia     cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349;
7241fee955fSAlberto Garcia     cfg2.buckets[THROTTLE_OPS_READ].avg  = 123;
7251fee955fSAlberto Garcia     cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86;
726022cdc9fSManos Pitsidianakis     throttle_group_config(tgm3, &cfg1);
7271fee955fSAlberto Garcia 
728022cdc9fSManos Pitsidianakis     throttle_group_get_config(tgm1, &cfg1);
729022cdc9fSManos Pitsidianakis     throttle_group_get_config(tgm3, &cfg2);
7301fee955fSAlberto Garcia     g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
7311fee955fSAlberto Garcia 
732022cdc9fSManos Pitsidianakis     throttle_group_unregister_tgm(tgm1);
733022cdc9fSManos Pitsidianakis     throttle_group_unregister_tgm(tgm2);
734022cdc9fSManos Pitsidianakis     throttle_group_unregister_tgm(tgm3);
7351fee955fSAlberto Garcia 
736022cdc9fSManos Pitsidianakis     g_assert(tgm1->throttle_state == NULL);
737022cdc9fSManos Pitsidianakis     g_assert(tgm2->throttle_state == NULL);
738022cdc9fSManos Pitsidianakis     g_assert(tgm3->throttle_state == NULL);
7391fee955fSAlberto Garcia }
7401fee955fSAlberto Garcia 
741f17cfe81SBenoît Canet int main(int argc, char **argv)
742f17cfe81SBenoît Canet {
74373eaa047SMarkus Armbruster     qemu_init_main_loop(&error_fatal);
7441fee955fSAlberto Garcia     ctx = qemu_get_aio_context();
7451fee955fSAlberto Garcia     bdrv_init();
746432d889eSManos Pitsidianakis     module_call_init(MODULE_INIT_QOM);
74713af91ebSStefan Hajnoczi 
748f17cfe81SBenoît Canet     do {} while (g_main_context_iteration(NULL, false));
749f17cfe81SBenoît Canet 
750f17cfe81SBenoît Canet     /* tests in the same order as the header function declarations */
751f17cfe81SBenoît Canet     g_test_init(&argc, &argv, NULL);
752f17cfe81SBenoît Canet     g_test_add_func("/throttle/leak_bucket",        test_leak_bucket);
753f17cfe81SBenoît Canet     g_test_add_func("/throttle/compute_wait",       test_compute_wait);
754f17cfe81SBenoît Canet     g_test_add_func("/throttle/init",               test_init);
755f17cfe81SBenoît Canet     g_test_add_func("/throttle/destroy",            test_destroy);
756f17cfe81SBenoît Canet     g_test_add_func("/throttle/have_timer",         test_have_timer);
75722524f72SStefan Hajnoczi     g_test_add_func("/throttle/detach_attach",      test_detach_attach);
758f17cfe81SBenoît Canet     g_test_add_func("/throttle/config/enabled",     test_enabled);
759f17cfe81SBenoît Canet     g_test_add_func("/throttle/config/conflicting", test_conflicting_config);
760f17cfe81SBenoît Canet     g_test_add_func("/throttle/config/is_valid",    test_is_valid);
761d942feecSAlberto Garcia     g_test_add_func("/throttle/config/ranges",      test_ranges);
76292e11a17SStefan Hajnoczi     g_test_add_func("/throttle/config/max",         test_max_is_missing_limit);
7638860eabdSStefan Hajnoczi     g_test_add_func("/throttle/config/iops_size",
7648860eabdSStefan Hajnoczi                     test_iops_size_is_missing_limit);
765f17cfe81SBenoît Canet     g_test_add_func("/throttle/config_functions",   test_config_functions);
766f17cfe81SBenoît Canet     g_test_add_func("/throttle/accounting",         test_accounting);
7671fee955fSAlberto Garcia     g_test_add_func("/throttle/groups",             test_groups);
768f17cfe81SBenoît Canet     return g_test_run();
769f17cfe81SBenoît Canet }
770f17cfe81SBenoît Canet 
771