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 <glib.h> 17f17cfe81SBenoît Canet #include <math.h> 1813af91ebSStefan Hajnoczi #include "block/aio.h" 19f17cfe81SBenoît Canet #include "qemu/throttle.h" 202f78e491SChrysostomos Nanakos #include "qemu/error-report.h" 211fee955fSAlberto Garcia #include "block/throttle-groups.h" 22f17cfe81SBenoît Canet 23748bfb4eSStefan Weil static AioContext *ctx; 24748bfb4eSStefan Weil static LeakyBucket bkt; 25748bfb4eSStefan Weil static ThrottleConfig cfg; 26748bfb4eSStefan Weil static ThrottleState ts; 270e5b0a2dSBenoît Canet static ThrottleTimers tt; 28f17cfe81SBenoît Canet 2973f395faSStefan Weil /* useful function */ 30f17cfe81SBenoît Canet static bool double_cmp(double x, double y) 31f17cfe81SBenoît Canet { 32f17cfe81SBenoît Canet return fabsl(x - y) < 1e-6; 33f17cfe81SBenoît Canet } 34f17cfe81SBenoît Canet 35f17cfe81SBenoît Canet /* tests for single bucket operations */ 36f17cfe81SBenoît Canet static void test_leak_bucket(void) 37f17cfe81SBenoît Canet { 38*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 39*1588ab5dSAlberto Garcia bkt = cfg.buckets[THROTTLE_BPS_TOTAL]; 40*1588ab5dSAlberto Garcia 41f17cfe81SBenoît Canet /* set initial value */ 42f17cfe81SBenoît Canet bkt.avg = 150; 43f17cfe81SBenoît Canet bkt.max = 15; 44f17cfe81SBenoît Canet bkt.level = 1.5; 45f17cfe81SBenoît Canet 46f17cfe81SBenoît Canet /* leak an op work of time */ 4713566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150); 48f17cfe81SBenoît Canet g_assert(bkt.avg == 150); 49f17cfe81SBenoît Canet g_assert(bkt.max == 15); 50f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0.5)); 51f17cfe81SBenoît Canet 52f17cfe81SBenoît Canet /* leak again emptying the bucket */ 5313566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150); 54f17cfe81SBenoît Canet g_assert(bkt.avg == 150); 55f17cfe81SBenoît Canet g_assert(bkt.max == 15); 56f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0)); 57f17cfe81SBenoît Canet 58f17cfe81SBenoît Canet /* check that the bucket level won't go lower */ 5913566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150); 60f17cfe81SBenoît Canet g_assert(bkt.avg == 150); 61f17cfe81SBenoît Canet g_assert(bkt.max == 15); 62f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0)); 63f17cfe81SBenoît Canet } 64f17cfe81SBenoît Canet 65f17cfe81SBenoît Canet static void test_compute_wait(void) 66f17cfe81SBenoît Canet { 67f17cfe81SBenoît Canet int64_t wait; 68f17cfe81SBenoît Canet int64_t result; 69f17cfe81SBenoît Canet 70*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 71*1588ab5dSAlberto Garcia bkt = cfg.buckets[THROTTLE_BPS_TOTAL]; 72*1588ab5dSAlberto Garcia 73f17cfe81SBenoît Canet /* no operation limit set */ 74f17cfe81SBenoît Canet bkt.avg = 0; 75f17cfe81SBenoît Canet bkt.max = 15; 76f17cfe81SBenoît Canet bkt.level = 1.5; 77f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 78f17cfe81SBenoît Canet g_assert(!wait); 79f17cfe81SBenoît Canet 80f17cfe81SBenoît Canet /* zero delta */ 81f17cfe81SBenoît Canet bkt.avg = 150; 82f17cfe81SBenoît Canet bkt.max = 15; 83f17cfe81SBenoît Canet bkt.level = 15; 84f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 85f17cfe81SBenoît Canet g_assert(!wait); 86f17cfe81SBenoît Canet 87f17cfe81SBenoît Canet /* below zero delta */ 88f17cfe81SBenoît Canet bkt.avg = 150; 89f17cfe81SBenoît Canet bkt.max = 15; 90f17cfe81SBenoît Canet bkt.level = 9; 91f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 92f17cfe81SBenoît Canet g_assert(!wait); 93f17cfe81SBenoît Canet 94f17cfe81SBenoît Canet /* half an operation above max */ 95f17cfe81SBenoît Canet bkt.avg = 150; 96f17cfe81SBenoît Canet bkt.max = 15; 97f17cfe81SBenoît Canet bkt.level = 15.5; 98f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 99f17cfe81SBenoît Canet /* time required to do half an operation */ 10013566fe3SStefan Hajnoczi result = (int64_t) NANOSECONDS_PER_SECOND / 150 / 2; 101f17cfe81SBenoît Canet g_assert(wait == result); 102f17cfe81SBenoît Canet } 103f17cfe81SBenoît Canet 104f17cfe81SBenoît Canet /* functions to test ThrottleState initialization/destroy methods */ 105f17cfe81SBenoît Canet static void read_timer_cb(void *opaque) 106f17cfe81SBenoît Canet { 107f17cfe81SBenoît Canet } 108f17cfe81SBenoît Canet 109f17cfe81SBenoît Canet static void write_timer_cb(void *opaque) 110f17cfe81SBenoît Canet { 111f17cfe81SBenoît Canet } 112f17cfe81SBenoît Canet 113f17cfe81SBenoît Canet static void test_init(void) 114f17cfe81SBenoît Canet { 115f17cfe81SBenoît Canet int i; 116f17cfe81SBenoît Canet 1170e5b0a2dSBenoît Canet /* fill the structures with crap */ 118f17cfe81SBenoît Canet memset(&ts, 1, sizeof(ts)); 1190e5b0a2dSBenoît Canet memset(&tt, 1, sizeof(tt)); 120f17cfe81SBenoît Canet 1210e5b0a2dSBenoît Canet /* init structures */ 1220e5b0a2dSBenoît Canet throttle_init(&ts); 1230e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 12413af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 125f17cfe81SBenoît Canet 126f17cfe81SBenoît Canet /* check initialized fields */ 1270e5b0a2dSBenoît Canet g_assert(tt.clock_type == QEMU_CLOCK_VIRTUAL); 1280e5b0a2dSBenoît Canet g_assert(tt.timers[0]); 1290e5b0a2dSBenoît Canet g_assert(tt.timers[1]); 130f17cfe81SBenoît Canet 131f17cfe81SBenoît Canet /* check other fields where cleared */ 132f17cfe81SBenoît Canet g_assert(!ts.previous_leak); 133f17cfe81SBenoît Canet g_assert(!ts.cfg.op_size); 134f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 135f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].avg); 136f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].max); 137f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].level); 138f17cfe81SBenoît Canet } 139f17cfe81SBenoît Canet 1400e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 141f17cfe81SBenoît Canet } 142f17cfe81SBenoît Canet 143f17cfe81SBenoît Canet static void test_destroy(void) 144f17cfe81SBenoît Canet { 145f17cfe81SBenoît Canet int i; 1460e5b0a2dSBenoît Canet throttle_init(&ts); 1470e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 14813af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 1490e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 150f17cfe81SBenoît Canet for (i = 0; i < 2; i++) { 1510e5b0a2dSBenoît Canet g_assert(!tt.timers[i]); 152f17cfe81SBenoît Canet } 153f17cfe81SBenoît Canet } 154f17cfe81SBenoît Canet 155f17cfe81SBenoît Canet /* function to test throttle_config and throttle_get_config */ 156f17cfe81SBenoît Canet static void test_config_functions(void) 157f17cfe81SBenoît Canet { 158f17cfe81SBenoît Canet int i; 159f17cfe81SBenoît Canet ThrottleConfig orig_cfg, final_cfg; 160f17cfe81SBenoît Canet 161f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_TOTAL].avg = 153; 162f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_READ].avg = 56; 163f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].avg = 1; 164f17cfe81SBenoît Canet 165f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].avg = 150; 166f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].avg = 69; 167f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].avg = 23; 168f17cfe81SBenoît Canet 169f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_TOTAL].max = 0; /* should be corrected */ 170f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_READ].max = 1; /* should not be corrected */ 171f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].max = 120; 172f17cfe81SBenoît Canet 173f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].max = 150; 174f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].max = 400; 175f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].max = 500; 176f17cfe81SBenoît Canet 177f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_TOTAL].level = 45; 178f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_READ].level = 65; 179f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].level = 23; 180f17cfe81SBenoît Canet 181f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].level = 1; 182f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].level = 90; 183f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].level = 75; 184f17cfe81SBenoît Canet 185f17cfe81SBenoît Canet orig_cfg.op_size = 1; 186f17cfe81SBenoît Canet 1870e5b0a2dSBenoît Canet throttle_init(&ts); 1880e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 18913af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 190f17cfe81SBenoît Canet /* structure reset by throttle_init previous_leak should be null */ 191f17cfe81SBenoît Canet g_assert(!ts.previous_leak); 1920e5b0a2dSBenoît Canet throttle_config(&ts, &tt, &orig_cfg); 193f17cfe81SBenoît Canet 194f17cfe81SBenoît Canet /* has previous leak been initialized by throttle_config ? */ 195f17cfe81SBenoît Canet g_assert(ts.previous_leak); 196f17cfe81SBenoît Canet 197f17cfe81SBenoît Canet /* get back the fixed configuration */ 198f17cfe81SBenoît Canet throttle_get_config(&ts, &final_cfg); 199f17cfe81SBenoît Canet 2000e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 201f17cfe81SBenoît Canet 202f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153); 203f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg == 56); 204f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].avg == 1); 205f17cfe81SBenoît Canet 206f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].avg == 150); 207f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_READ].avg == 69); 208f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].avg == 23); 209f17cfe81SBenoît Canet 210f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].max == 15.3);/* fixed */ 211f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_READ].max == 1); /* not fixed */ 212f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].max == 120); 213f17cfe81SBenoît Canet 214f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].max == 150); 215f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_READ].max == 400); 216f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].max == 500); 217f17cfe81SBenoît Canet 218f17cfe81SBenoît Canet g_assert(final_cfg.op_size == 1); 219f17cfe81SBenoît Canet 220f17cfe81SBenoît Canet /* check bucket have been cleared */ 221f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 222f17cfe81SBenoît Canet g_assert(!final_cfg.buckets[i].level); 223f17cfe81SBenoît Canet } 224f17cfe81SBenoît Canet } 225f17cfe81SBenoît Canet 226f17cfe81SBenoît Canet /* functions to test is throttle is enabled by a config */ 227f17cfe81SBenoît Canet static void set_cfg_value(bool is_max, int index, int value) 228f17cfe81SBenoît Canet { 229f17cfe81SBenoît Canet if (is_max) { 230f17cfe81SBenoît Canet cfg.buckets[index].max = value; 2316f9b6d57SAlberto Garcia /* If max is set, avg should never be 0 */ 2326f9b6d57SAlberto Garcia cfg.buckets[index].avg = MAX(cfg.buckets[index].avg, 1); 233f17cfe81SBenoît Canet } else { 234f17cfe81SBenoît Canet cfg.buckets[index].avg = value; 235f17cfe81SBenoît Canet } 236f17cfe81SBenoît Canet } 237f17cfe81SBenoît Canet 238f17cfe81SBenoît Canet static void test_enabled(void) 239f17cfe81SBenoît Canet { 240f17cfe81SBenoît Canet int i; 241f17cfe81SBenoît Canet 242*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 243f17cfe81SBenoît Canet g_assert(!throttle_enabled(&cfg)); 244f17cfe81SBenoît Canet 245f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 246*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 247f17cfe81SBenoît Canet set_cfg_value(false, i, 150); 248f17cfe81SBenoît Canet g_assert(throttle_enabled(&cfg)); 249f17cfe81SBenoît Canet } 250f17cfe81SBenoît Canet 251f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 252*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 253f17cfe81SBenoît Canet set_cfg_value(false, i, -150); 254f17cfe81SBenoît Canet g_assert(!throttle_enabled(&cfg)); 255f17cfe81SBenoît Canet } 256f17cfe81SBenoît Canet } 257f17cfe81SBenoît Canet 258f17cfe81SBenoît Canet /* tests functions for throttle_conflicting */ 259f17cfe81SBenoît Canet 260f17cfe81SBenoît Canet static void test_conflicts_for_one_set(bool is_max, 261f17cfe81SBenoît Canet int total, 262f17cfe81SBenoît Canet int read, 263f17cfe81SBenoît Canet int write) 264f17cfe81SBenoît Canet { 265*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 266d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 267f17cfe81SBenoît Canet 268f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 269f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1); 270d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 271f17cfe81SBenoît Canet 272*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 273f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 274f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1); 275d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 276f17cfe81SBenoît Canet 277*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 278f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 279f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1); 280f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1); 281d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 282f17cfe81SBenoît Canet 283*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 284f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 285d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 286f17cfe81SBenoît Canet 287*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 288f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1); 289f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1); 290d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 291f17cfe81SBenoît Canet } 292f17cfe81SBenoît Canet 293f17cfe81SBenoît Canet static void test_conflicting_config(void) 294f17cfe81SBenoît Canet { 295f17cfe81SBenoît Canet /* bps average conflicts */ 296f17cfe81SBenoît Canet test_conflicts_for_one_set(false, 297f17cfe81SBenoît Canet THROTTLE_BPS_TOTAL, 298f17cfe81SBenoît Canet THROTTLE_BPS_READ, 299f17cfe81SBenoît Canet THROTTLE_BPS_WRITE); 300f17cfe81SBenoît Canet 301f17cfe81SBenoît Canet /* ops average conflicts */ 302f17cfe81SBenoît Canet test_conflicts_for_one_set(false, 303f17cfe81SBenoît Canet THROTTLE_OPS_TOTAL, 304f17cfe81SBenoît Canet THROTTLE_OPS_READ, 305f17cfe81SBenoît Canet THROTTLE_OPS_WRITE); 306f17cfe81SBenoît Canet 307f17cfe81SBenoît Canet /* bps average conflicts */ 308f17cfe81SBenoît Canet test_conflicts_for_one_set(true, 309f17cfe81SBenoît Canet THROTTLE_BPS_TOTAL, 310f17cfe81SBenoît Canet THROTTLE_BPS_READ, 311f17cfe81SBenoît Canet THROTTLE_BPS_WRITE); 312f17cfe81SBenoît Canet /* ops average conflicts */ 313f17cfe81SBenoît Canet test_conflicts_for_one_set(true, 314f17cfe81SBenoît Canet THROTTLE_OPS_TOTAL, 315f17cfe81SBenoît Canet THROTTLE_OPS_READ, 316f17cfe81SBenoît Canet THROTTLE_OPS_WRITE); 317f17cfe81SBenoît Canet } 318f17cfe81SBenoît Canet /* functions to test the throttle_is_valid function */ 319f17cfe81SBenoît Canet static void test_is_valid_for_value(int value, bool should_be_valid) 320f17cfe81SBenoît Canet { 321f17cfe81SBenoît Canet int is_max, index; 322f17cfe81SBenoît Canet for (is_max = 0; is_max < 2; is_max++) { 323f17cfe81SBenoît Canet for (index = 0; index < BUCKETS_COUNT; index++) { 324*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 325f17cfe81SBenoît Canet set_cfg_value(is_max, index, value); 32603ba36c8SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL) == should_be_valid); 327f17cfe81SBenoît Canet } 328f17cfe81SBenoît Canet } 329f17cfe81SBenoît Canet } 330f17cfe81SBenoît Canet 331f17cfe81SBenoît Canet static void test_is_valid(void) 332f17cfe81SBenoît Canet { 333f17cfe81SBenoît Canet /* negative number are invalid */ 334f17cfe81SBenoît Canet test_is_valid_for_value(-1, false); 335f17cfe81SBenoît Canet /* zero are valids */ 336f17cfe81SBenoît Canet test_is_valid_for_value(0, true); 337f17cfe81SBenoît Canet /* positives numers are valids */ 338f17cfe81SBenoît Canet test_is_valid_for_value(1, true); 339f17cfe81SBenoît Canet } 340f17cfe81SBenoît Canet 34192e11a17SStefan Hajnoczi static void test_max_is_missing_limit(void) 34292e11a17SStefan Hajnoczi { 34392e11a17SStefan Hajnoczi int i; 34492e11a17SStefan Hajnoczi 34592e11a17SStefan Hajnoczi for (i = 0; i < BUCKETS_COUNT; i++) { 346*1588ab5dSAlberto Garcia throttle_config_init(&cfg); 34792e11a17SStefan Hajnoczi cfg.buckets[i].max = 100; 34892e11a17SStefan Hajnoczi cfg.buckets[i].avg = 0; 349d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 35092e11a17SStefan Hajnoczi 35192e11a17SStefan Hajnoczi cfg.buckets[i].max = 0; 35292e11a17SStefan Hajnoczi cfg.buckets[i].avg = 0; 353d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 35492e11a17SStefan Hajnoczi 35592e11a17SStefan Hajnoczi cfg.buckets[i].max = 0; 35692e11a17SStefan Hajnoczi cfg.buckets[i].avg = 100; 357d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 35892e11a17SStefan Hajnoczi } 35992e11a17SStefan Hajnoczi } 36092e11a17SStefan Hajnoczi 361f17cfe81SBenoît Canet static void test_have_timer(void) 362f17cfe81SBenoît Canet { 3630e5b0a2dSBenoît Canet /* zero structures */ 364f17cfe81SBenoît Canet memset(&ts, 0, sizeof(ts)); 3650e5b0a2dSBenoît Canet memset(&tt, 0, sizeof(tt)); 366f17cfe81SBenoît Canet 36773f395faSStefan Weil /* no timer set should return false */ 3680e5b0a2dSBenoît Canet g_assert(!throttle_timers_are_initialized(&tt)); 369f17cfe81SBenoît Canet 3700e5b0a2dSBenoît Canet /* init structures */ 3710e5b0a2dSBenoît Canet throttle_init(&ts); 3720e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 37313af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 374f17cfe81SBenoît Canet 375f17cfe81SBenoît Canet /* timer set by init should return true */ 3760e5b0a2dSBenoît Canet g_assert(throttle_timers_are_initialized(&tt)); 377f17cfe81SBenoît Canet 3780e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 379f17cfe81SBenoît Canet } 380f17cfe81SBenoît Canet 38122524f72SStefan Hajnoczi static void test_detach_attach(void) 38222524f72SStefan Hajnoczi { 3830e5b0a2dSBenoît Canet /* zero structures */ 38422524f72SStefan Hajnoczi memset(&ts, 0, sizeof(ts)); 3850e5b0a2dSBenoît Canet memset(&tt, 0, sizeof(tt)); 38622524f72SStefan Hajnoczi 38722524f72SStefan Hajnoczi /* init the structure */ 3880e5b0a2dSBenoît Canet throttle_init(&ts); 3890e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 39022524f72SStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 39122524f72SStefan Hajnoczi 39222524f72SStefan Hajnoczi /* timer set by init should return true */ 3930e5b0a2dSBenoît Canet g_assert(throttle_timers_are_initialized(&tt)); 39422524f72SStefan Hajnoczi 39522524f72SStefan Hajnoczi /* timer should no longer exist after detaching */ 3960e5b0a2dSBenoît Canet throttle_timers_detach_aio_context(&tt); 3970e5b0a2dSBenoît Canet g_assert(!throttle_timers_are_initialized(&tt)); 39822524f72SStefan Hajnoczi 39922524f72SStefan Hajnoczi /* timer should exist again after attaching */ 4000e5b0a2dSBenoît Canet throttle_timers_attach_aio_context(&tt, ctx); 4010e5b0a2dSBenoît Canet g_assert(throttle_timers_are_initialized(&tt)); 40222524f72SStefan Hajnoczi 4030e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 40422524f72SStefan Hajnoczi } 40522524f72SStefan Hajnoczi 406f17cfe81SBenoît Canet static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */ 407f17cfe81SBenoît Canet int size, /* size of the operation to do */ 408f17cfe81SBenoît Canet double avg, /* io limit */ 409f17cfe81SBenoît Canet uint64_t op_size, /* ideal size of an io */ 410f17cfe81SBenoît Canet double total_result, 411f17cfe81SBenoît Canet double read_result, 412f17cfe81SBenoît Canet double write_result) 413f17cfe81SBenoît Canet { 414f17cfe81SBenoît Canet BucketType to_test[2][3] = { { THROTTLE_BPS_TOTAL, 415f17cfe81SBenoît Canet THROTTLE_BPS_READ, 416f17cfe81SBenoît Canet THROTTLE_BPS_WRITE, }, 417f17cfe81SBenoît Canet { THROTTLE_OPS_TOTAL, 418f17cfe81SBenoît Canet THROTTLE_OPS_READ, 419f17cfe81SBenoît Canet THROTTLE_OPS_WRITE, } }; 420f17cfe81SBenoît Canet ThrottleConfig cfg; 421f17cfe81SBenoît Canet BucketType index; 422f17cfe81SBenoît Canet int i; 423f17cfe81SBenoît Canet 424f17cfe81SBenoît Canet for (i = 0; i < 3; i++) { 425f17cfe81SBenoît Canet BucketType index = to_test[is_ops][i]; 426f17cfe81SBenoît Canet cfg.buckets[index].avg = avg; 427f17cfe81SBenoît Canet } 428f17cfe81SBenoît Canet 429f17cfe81SBenoît Canet cfg.op_size = op_size; 430f17cfe81SBenoît Canet 4310e5b0a2dSBenoît Canet throttle_init(&ts); 4320e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 43313af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 4340e5b0a2dSBenoît Canet throttle_config(&ts, &tt, &cfg); 435f17cfe81SBenoît Canet 436f17cfe81SBenoît Canet /* account a read */ 437f17cfe81SBenoît Canet throttle_account(&ts, false, size); 438f17cfe81SBenoît Canet /* account a write */ 439f17cfe81SBenoît Canet throttle_account(&ts, true, size); 440f17cfe81SBenoît Canet 441f17cfe81SBenoît Canet /* check total result */ 442f17cfe81SBenoît Canet index = to_test[is_ops][0]; 443f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, total_result)) { 444f17cfe81SBenoît Canet return false; 445f17cfe81SBenoît Canet } 446f17cfe81SBenoît Canet 447f17cfe81SBenoît Canet /* check read result */ 448f17cfe81SBenoît Canet index = to_test[is_ops][1]; 449f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, read_result)) { 450f17cfe81SBenoît Canet return false; 451f17cfe81SBenoît Canet } 452f17cfe81SBenoît Canet 453f17cfe81SBenoît Canet /* check write result */ 454f17cfe81SBenoît Canet index = to_test[is_ops][2]; 455f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, write_result)) { 456f17cfe81SBenoît Canet return false; 457f17cfe81SBenoît Canet } 458f17cfe81SBenoît Canet 4590e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 460f17cfe81SBenoît Canet 461f17cfe81SBenoît Canet return true; 462f17cfe81SBenoît Canet } 463f17cfe81SBenoît Canet 464f17cfe81SBenoît Canet static void test_accounting(void) 465f17cfe81SBenoît Canet { 466f17cfe81SBenoît Canet /* tests for bps */ 467f17cfe81SBenoît Canet 468f17cfe81SBenoît Canet /* op of size 1 */ 469f17cfe81SBenoît Canet g_assert(do_test_accounting(false, 470f17cfe81SBenoît Canet 1 * 512, 471f17cfe81SBenoît Canet 150, 472f17cfe81SBenoît Canet 0, 473f17cfe81SBenoît Canet 1024, 474f17cfe81SBenoît Canet 512, 475f17cfe81SBenoît Canet 512)); 476f17cfe81SBenoît Canet 477f17cfe81SBenoît Canet /* op of size 2 */ 478f17cfe81SBenoît Canet g_assert(do_test_accounting(false, 479f17cfe81SBenoît Canet 2 * 512, 480f17cfe81SBenoît Canet 150, 481f17cfe81SBenoît Canet 0, 482f17cfe81SBenoît Canet 2048, 483f17cfe81SBenoît Canet 1024, 484f17cfe81SBenoît Canet 1024)); 485f17cfe81SBenoît Canet 486f17cfe81SBenoît Canet /* op of size 2 and orthogonal parameter change */ 487f17cfe81SBenoît Canet g_assert(do_test_accounting(false, 488f17cfe81SBenoît Canet 2 * 512, 489f17cfe81SBenoît Canet 150, 490f17cfe81SBenoît Canet 17, 491f17cfe81SBenoît Canet 2048, 492f17cfe81SBenoît Canet 1024, 493f17cfe81SBenoît Canet 1024)); 494f17cfe81SBenoît Canet 495f17cfe81SBenoît Canet 496f17cfe81SBenoît Canet /* tests for ops */ 497f17cfe81SBenoît Canet 498f17cfe81SBenoît Canet /* op of size 1 */ 499f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 500f17cfe81SBenoît Canet 1 * 512, 501f17cfe81SBenoît Canet 150, 502f17cfe81SBenoît Canet 0, 503f17cfe81SBenoît Canet 2, 504f17cfe81SBenoît Canet 1, 505f17cfe81SBenoît Canet 1)); 506f17cfe81SBenoît Canet 507f17cfe81SBenoît Canet /* op of size 2 */ 508f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 509f17cfe81SBenoît Canet 2 * 512, 510f17cfe81SBenoît Canet 150, 511f17cfe81SBenoît Canet 0, 512f17cfe81SBenoît Canet 2, 513f17cfe81SBenoît Canet 1, 514f17cfe81SBenoît Canet 1)); 515f17cfe81SBenoît Canet 516f17cfe81SBenoît Canet /* jumbo op accounting fragmentation : size 64 with op size of 13 units */ 517f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 518f17cfe81SBenoît Canet 64 * 512, 519f17cfe81SBenoît Canet 150, 520f17cfe81SBenoît Canet 13 * 512, 521f17cfe81SBenoît Canet (64.0 * 2) / 13, 522f17cfe81SBenoît Canet (64.0 / 13), 523f17cfe81SBenoît Canet (64.0 / 13))); 524f17cfe81SBenoît Canet 525f17cfe81SBenoît Canet /* same with orthogonal parameters changes */ 526f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 527f17cfe81SBenoît Canet 64 * 512, 528f17cfe81SBenoît Canet 300, 529f17cfe81SBenoît Canet 13 * 512, 530f17cfe81SBenoît Canet (64.0 * 2) / 13, 531f17cfe81SBenoît Canet (64.0 / 13), 532f17cfe81SBenoît Canet (64.0 / 13))); 533f17cfe81SBenoît Canet } 534f17cfe81SBenoît Canet 5351fee955fSAlberto Garcia static void test_groups(void) 5361fee955fSAlberto Garcia { 5371fee955fSAlberto Garcia ThrottleConfig cfg1, cfg2; 5381fee955fSAlberto Garcia BlockDriverState *bdrv1, *bdrv2, *bdrv3; 5391fee955fSAlberto Garcia 5401fee955fSAlberto Garcia bdrv1 = bdrv_new(); 5411fee955fSAlberto Garcia bdrv2 = bdrv_new(); 5421fee955fSAlberto Garcia bdrv3 = bdrv_new(); 5431fee955fSAlberto Garcia 5441fee955fSAlberto Garcia g_assert(bdrv1->throttle_state == NULL); 5451fee955fSAlberto Garcia g_assert(bdrv2->throttle_state == NULL); 5461fee955fSAlberto Garcia g_assert(bdrv3->throttle_state == NULL); 5471fee955fSAlberto Garcia 5481fee955fSAlberto Garcia throttle_group_register_bs(bdrv1, "bar"); 5491fee955fSAlberto Garcia throttle_group_register_bs(bdrv2, "foo"); 5501fee955fSAlberto Garcia throttle_group_register_bs(bdrv3, "bar"); 5511fee955fSAlberto Garcia 5521fee955fSAlberto Garcia g_assert(bdrv1->throttle_state != NULL); 5531fee955fSAlberto Garcia g_assert(bdrv2->throttle_state != NULL); 5541fee955fSAlberto Garcia g_assert(bdrv3->throttle_state != NULL); 5551fee955fSAlberto Garcia 5561fee955fSAlberto Garcia g_assert(!strcmp(throttle_group_get_name(bdrv1), "bar")); 5571fee955fSAlberto Garcia g_assert(!strcmp(throttle_group_get_name(bdrv2), "foo")); 5581fee955fSAlberto Garcia g_assert(bdrv1->throttle_state == bdrv3->throttle_state); 5591fee955fSAlberto Garcia 5601fee955fSAlberto Garcia /* Setting the config of a group member affects the whole group */ 561*1588ab5dSAlberto Garcia throttle_config_init(&cfg1); 5621fee955fSAlberto Garcia cfg1.buckets[THROTTLE_BPS_READ].avg = 500000; 5631fee955fSAlberto Garcia cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000; 5641fee955fSAlberto Garcia cfg1.buckets[THROTTLE_OPS_READ].avg = 20000; 5651fee955fSAlberto Garcia cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000; 5661fee955fSAlberto Garcia throttle_group_config(bdrv1, &cfg1); 5671fee955fSAlberto Garcia 5681fee955fSAlberto Garcia throttle_group_get_config(bdrv1, &cfg1); 5691fee955fSAlberto Garcia throttle_group_get_config(bdrv3, &cfg2); 5701fee955fSAlberto Garcia g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1))); 5711fee955fSAlberto Garcia 5721fee955fSAlberto Garcia cfg2.buckets[THROTTLE_BPS_READ].avg = 4547; 5731fee955fSAlberto Garcia cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349; 5741fee955fSAlberto Garcia cfg2.buckets[THROTTLE_OPS_READ].avg = 123; 5751fee955fSAlberto Garcia cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86; 5761fee955fSAlberto Garcia throttle_group_config(bdrv3, &cfg1); 5771fee955fSAlberto Garcia 5781fee955fSAlberto Garcia throttle_group_get_config(bdrv1, &cfg1); 5791fee955fSAlberto Garcia throttle_group_get_config(bdrv3, &cfg2); 5801fee955fSAlberto Garcia g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1))); 5811fee955fSAlberto Garcia 5821fee955fSAlberto Garcia throttle_group_unregister_bs(bdrv1); 5831fee955fSAlberto Garcia throttle_group_unregister_bs(bdrv2); 5841fee955fSAlberto Garcia throttle_group_unregister_bs(bdrv3); 5851fee955fSAlberto Garcia 5861fee955fSAlberto Garcia g_assert(bdrv1->throttle_state == NULL); 5871fee955fSAlberto Garcia g_assert(bdrv2->throttle_state == NULL); 5881fee955fSAlberto Garcia g_assert(bdrv3->throttle_state == NULL); 5891fee955fSAlberto Garcia } 5901fee955fSAlberto Garcia 591f17cfe81SBenoît Canet int main(int argc, char **argv) 592f17cfe81SBenoît Canet { 59373eaa047SMarkus Armbruster qemu_init_main_loop(&error_fatal); 5941fee955fSAlberto Garcia ctx = qemu_get_aio_context(); 5951fee955fSAlberto Garcia bdrv_init(); 59613af91ebSStefan Hajnoczi 597f17cfe81SBenoît Canet do {} while (g_main_context_iteration(NULL, false)); 598f17cfe81SBenoît Canet 599f17cfe81SBenoît Canet /* tests in the same order as the header function declarations */ 600f17cfe81SBenoît Canet g_test_init(&argc, &argv, NULL); 601f17cfe81SBenoît Canet g_test_add_func("/throttle/leak_bucket", test_leak_bucket); 602f17cfe81SBenoît Canet g_test_add_func("/throttle/compute_wait", test_compute_wait); 603f17cfe81SBenoît Canet g_test_add_func("/throttle/init", test_init); 604f17cfe81SBenoît Canet g_test_add_func("/throttle/destroy", test_destroy); 605f17cfe81SBenoît Canet g_test_add_func("/throttle/have_timer", test_have_timer); 60622524f72SStefan Hajnoczi g_test_add_func("/throttle/detach_attach", test_detach_attach); 607f17cfe81SBenoît Canet g_test_add_func("/throttle/config/enabled", test_enabled); 608f17cfe81SBenoît Canet g_test_add_func("/throttle/config/conflicting", test_conflicting_config); 609f17cfe81SBenoît Canet g_test_add_func("/throttle/config/is_valid", test_is_valid); 61092e11a17SStefan Hajnoczi g_test_add_func("/throttle/config/max", test_max_is_missing_limit); 611f17cfe81SBenoît Canet g_test_add_func("/throttle/config_functions", test_config_functions); 612f17cfe81SBenoît Canet g_test_add_func("/throttle/accounting", test_accounting); 6131fee955fSAlberto Garcia g_test_add_func("/throttle/groups", test_groups); 614f17cfe81SBenoît Canet return g_test_run(); 615f17cfe81SBenoît Canet } 616f17cfe81SBenoît Canet 617