|
|
21255d |
From c35ba62cd6f337c4eef64cdc3b9796f988802229 Mon Sep 17 00:00:00 2001
|
|
|
21255d |
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
|
|
21255d |
Date: Mon, 23 Nov 2020 18:04:57 +0100
|
|
|
21255d |
Subject: [PATCH] test: add ratelimiting test
|
|
|
21255d |
|
|
|
21255d |
(Taken from Michal's #17274 by Lennart, and slightly adjusted)
|
|
|
21255d |
|
|
|
21255d |
(cherry picked from commit 68d890651781904a4c762ac866af36e30c4f7ff8)
|
|
|
21255d |
|
|
|
21255d |
Related: #1819868
|
|
|
21255d |
---
|
|
|
21255d |
src/libsystemd/sd-event/test-event.c | 96 ++++++++++++++++++++++++++++
|
|
|
21255d |
1 file changed, 96 insertions(+)
|
|
|
21255d |
|
|
|
21255d |
diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c
|
|
|
21255d |
index bde00cf719..e3ee4cd5c3 100644
|
|
|
21255d |
--- a/src/libsystemd/sd-event/test-event.c
|
|
|
21255d |
+++ b/src/libsystemd/sd-event/test-event.c
|
|
|
21255d |
@@ -482,6 +482,100 @@ static void test_inotify(unsigned n_create_events) {
|
|
|
21255d |
sd_event_unref(e);
|
|
|
21255d |
}
|
|
|
21255d |
|
|
|
21255d |
+
|
|
|
21255d |
+static int ratelimit_io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
|
|
21255d |
+ unsigned *c = (unsigned*) userdata;
|
|
|
21255d |
+ *c += 1;
|
|
|
21255d |
+ return 0;
|
|
|
21255d |
+}
|
|
|
21255d |
+
|
|
|
21255d |
+static int ratelimit_time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
|
|
|
21255d |
+ int r;
|
|
|
21255d |
+
|
|
|
21255d |
+ r = sd_event_source_set_enabled(s, SD_EVENT_ON);
|
|
|
21255d |
+ if (r < 0)
|
|
|
21255d |
+ log_warning_errno(r, "Failed to turn on notify event source: %m");
|
|
|
21255d |
+
|
|
|
21255d |
+ r = sd_event_source_set_time(s, usec + 1000);
|
|
|
21255d |
+ if (r < 0)
|
|
|
21255d |
+ log_error_errno(r, "Failed to restart watchdog event source: %m");
|
|
|
21255d |
+
|
|
|
21255d |
+ unsigned *c = (unsigned*) userdata;
|
|
|
21255d |
+ *c += 1;
|
|
|
21255d |
+
|
|
|
21255d |
+ return 0;
|
|
|
21255d |
+}
|
|
|
21255d |
+
|
|
|
21255d |
+static void test_ratelimit(void) {
|
|
|
21255d |
+ _cleanup_close_pair_ int p[2] = {-1, -1};
|
|
|
21255d |
+ _cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
|
|
21255d |
+ _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
|
|
|
21255d |
+ uint64_t interval;
|
|
|
21255d |
+ unsigned count, burst;
|
|
|
21255d |
+
|
|
|
21255d |
+ assert_se(sd_event_default(&e) >= 0);
|
|
|
21255d |
+ assert_se(pipe2(p, O_CLOEXEC|O_NONBLOCK) >= 0);
|
|
|
21255d |
+
|
|
|
21255d |
+ assert_se(sd_event_add_io(e, &s, p[0], EPOLLIN, ratelimit_io_handler, &count) >= 0);
|
|
|
21255d |
+ assert_se(sd_event_source_set_description(s, "test-ratelimit-io") >= 0);
|
|
|
21255d |
+ assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0);
|
|
|
21255d |
+ assert_se(sd_event_source_get_ratelimit(s, &interval, &burst) >= 0);
|
|
|
21255d |
+ assert_se(interval == 1 * USEC_PER_SEC && burst == 5);
|
|
|
21255d |
+
|
|
|
21255d |
+ assert_se(write(p[1], "1", 1) == 1);
|
|
|
21255d |
+
|
|
|
21255d |
+ count = 0;
|
|
|
21255d |
+ for (unsigned i = 0; i < 10; i++) {
|
|
|
21255d |
+ log_debug("slow loop iteration %u", i);
|
|
|
21255d |
+ assert_se(sd_event_run(e, UINT64_MAX) >= 0);
|
|
|
21255d |
+ assert_se(usleep(250 * USEC_PER_MSEC) >= 0);
|
|
|
21255d |
+ }
|
|
|
21255d |
+
|
|
|
21255d |
+ assert_se(sd_event_source_is_ratelimited(s) == 0);
|
|
|
21255d |
+ assert_se(count == 10);
|
|
|
21255d |
+ log_info("ratelimit_io_handler: called %d times, event source not ratelimited", count);
|
|
|
21255d |
+
|
|
|
21255d |
+ assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0);
|
|
|
21255d |
+ assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0);
|
|
|
21255d |
+
|
|
|
21255d |
+ count = 0;
|
|
|
21255d |
+ for (unsigned i = 0; i < 10; i++) {
|
|
|
21255d |
+ log_debug("fast event loop iteration %u", i);
|
|
|
21255d |
+ assert_se(sd_event_run(e, UINT64_MAX) >= 0);
|
|
|
21255d |
+ assert_se(usleep(10) >= 0);
|
|
|
21255d |
+ }
|
|
|
21255d |
+ log_info("ratelimit_io_handler: called %d times, event source got ratelimited", count);
|
|
|
21255d |
+ assert_se(count < 10);
|
|
|
21255d |
+
|
|
|
21255d |
+ s = sd_event_source_unref(s);
|
|
|
21255d |
+ safe_close_pair(p);
|
|
|
21255d |
+
|
|
|
21255d |
+ count = 0;
|
|
|
21255d |
+
|
|
|
21255d |
+ assert_se(sd_event_add_time(e, &s, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 1000, 0, ratelimit_time_handler, &count) >= 0);
|
|
|
21255d |
+ assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) == 0);
|
|
|
21255d |
+
|
|
|
21255d |
+ do {
|
|
|
21255d |
+ assert_se(sd_event_run(e, UINT64_MAX) >= 0);
|
|
|
21255d |
+ } while (!sd_event_source_is_ratelimited(s));
|
|
|
21255d |
+
|
|
|
21255d |
+ log_info("ratelimit_time_handler: called %d times, event source got ratelimited", count);
|
|
|
21255d |
+ assert_se(count == 10);
|
|
|
21255d |
+
|
|
|
21255d |
+ /* In order to get rid of active rate limit client needs to disable it explicitely */
|
|
|
21255d |
+ assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0);
|
|
|
21255d |
+ assert_se(!sd_event_source_is_ratelimited(s));
|
|
|
21255d |
+
|
|
|
21255d |
+ assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) >= 0);
|
|
|
21255d |
+
|
|
|
21255d |
+ do {
|
|
|
21255d |
+ assert_se(sd_event_run(e, UINT64_MAX) >= 0);
|
|
|
21255d |
+ } while (!sd_event_source_is_ratelimited(s));
|
|
|
21255d |
+
|
|
|
21255d |
+ log_info("ratelimit_time_handler: called 10 more times, event source got ratelimited");
|
|
|
21255d |
+ assert_se(count == 20);
|
|
|
21255d |
+}
|
|
|
21255d |
+
|
|
|
21255d |
int main(int argc, char *argv[]) {
|
|
|
21255d |
|
|
|
21255d |
log_set_max_level(LOG_DEBUG);
|
|
|
21255d |
@@ -494,5 +588,7 @@ int main(int argc, char *argv[]) {
|
|
|
21255d |
test_inotify(100); /* should work without overflow */
|
|
|
21255d |
test_inotify(33000); /* should trigger a q overflow */
|
|
|
21255d |
|
|
|
21255d |
+ test_ratelimit();
|
|
|
21255d |
+
|
|
|
21255d |
return 0;
|
|
|
21255d |
}
|