test: add ratelimiting test

(Taken from Michal's #17274 by Lennart, and slightly adjusted)
This commit is contained in:
Michal Sekletár 2020-11-23 18:04:57 +01:00 committed by Lennart Poettering
parent b6d5481b3d
commit 68d8906517
1 changed files with 95 additions and 1 deletions

View File

@ -589,8 +589,100 @@ static void test_pidfd(void) {
sd_event_unref(e);
}
static int ratelimit_io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
unsigned *c = (unsigned*) userdata;
*c += 1;
return 0;
}
static int ratelimit_time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
int r;
r = sd_event_source_set_enabled(s, SD_EVENT_ON);
if (r < 0)
log_warning_errno(r, "Failed to turn on notify event source: %m");
r = sd_event_source_set_time(s, usec + 1000);
if (r < 0)
log_error_errno(r, "Failed to restart watchdog event source: %m");
unsigned *c = (unsigned*) userdata;
*c += 1;
return 0;
}
static void test_ratelimit(void) {
_cleanup_close_pair_ int p[2] = {-1, -1};
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
_cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
uint64_t interval;
unsigned count, burst;
assert_se(sd_event_default(&e) >= 0);
assert_se(pipe2(p, O_CLOEXEC|O_NONBLOCK) >= 0);
assert_se(sd_event_add_io(e, &s, p[0], EPOLLIN, ratelimit_io_handler, &count) >= 0);
assert_se(sd_event_source_set_description(s, "test-ratelimit-io") >= 0);
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0);
assert_se(sd_event_source_get_ratelimit(s, &interval, &burst) >= 0);
assert_se(interval == 1 * USEC_PER_SEC && burst == 5);
assert_se(write(p[1], "1", 1) == 1);
count = 0;
for (unsigned i = 0; i < 10; i++) {
log_debug("slow loop iteration %u", i);
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
assert_se(usleep(250 * USEC_PER_MSEC) >= 0);
}
assert_se(sd_event_source_is_ratelimited(s) == 0);
assert_se(count == 10);
log_info("ratelimit_io_handler: called %d times, event source not ratelimited", count);
assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0);
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0);
count = 0;
for (unsigned i = 0; i < 10; i++) {
log_debug("fast event loop iteration %u", i);
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
assert_se(usleep(10) >= 0);
}
log_info("ratelimit_io_handler: called %d times, event source got ratelimited", count);
assert_se(count < 10);
s = sd_event_source_unref(s);
safe_close_pair(p);
count = 0;
assert_se(sd_event_add_time_relative(e, &s, CLOCK_MONOTONIC, 1000, 1, ratelimit_time_handler, &count) >= 0);
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) == 0);
do {
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
} while (!sd_event_source_is_ratelimited(s));
log_info("ratelimit_time_handler: called %d times, event source got ratelimited", count);
assert_se(count == 10);
/* In order to get rid of active rate limit client needs to disable it explicitely */
assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0);
assert_se(!sd_event_source_is_ratelimited(s));
assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) >= 0);
do {
assert_se(sd_event_run(e, UINT64_MAX) >= 0);
} while (!sd_event_source_is_ratelimited(s));
log_info("ratelimit_time_handler: called 10 more times, event source got ratelimited");
assert_se(count == 20);
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_INFO);
test_setup_logging(LOG_DEBUG);
test_basic(true); /* test with pidfd */
test_basic(false); /* test without pidfd */
@ -603,5 +695,7 @@ int main(int argc, char *argv[]) {
test_pidfd();
test_ratelimit();
return 0;
}