From 4e634aa76c29d2bde3724244ae6852839756dba6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 8 Nov 2023 13:59:21 +1000 Subject: [PATCH] test: add the ability to add offsets to ei_now() Build a separate libei-eierpecken.so that is identical to libei.so but allows adding an offset to ei_now() for the eierpecken tests. That offset is added to the return value of ei_now(), removing the real-time dependency of the tests. In other words, we can call peck_ei_add_time_offset(peck, s2us(5)) to add 5 seconds to the time and continue the test as if that time has elapsed. --- src/libei-private.h | 2 ++ src/libei.c | 25 ++++++++++----- src/libei.h | 22 +++++++++++-- src/libeis-private.h | 2 ++ src/libeis.c | 26 ++++++++++----- src/libeis.h | 24 ++++++++++++-- test/eierpecken.c | 75 ++++++++++++++++++++++++++++++++++---------- test/eierpecken.h | 6 ++++ 8 files changed, 146 insertions(+), 36 deletions(-) diff --git a/src/libei-private.h b/src/libei-private.h index 8586292..ca0cdbe 100644 --- a/src/libei-private.h +++ b/src/libei-private.h @@ -113,6 +113,8 @@ struct ei { enum ei_log_priority priority; } log; + ei_clock_now_func clock_now; + bool is_sender; }; diff --git a/src/libei.c b/src/libei.c index 99f9fa4..bd2cedb 100644 --- a/src/libei.c +++ b/src/libei.c @@ -896,19 +896,30 @@ ei_configure_name(struct ei *ei, const char *name) ei->name = xstrdup(name); } +_public_ void +ei_clock_set_now_func(struct ei *ei, ei_clock_now_func func) +{ + ei->clock_now = func; +} + _public_ uint64_t ei_now(struct ei *ei) { uint64_t ts = 0; - int rc = now(&ts); - if (rc < 0) { - /* We should probably disconnect here but the chances of this - * happening are so slim it's not worth worrying about. Plus, - * if this fails we're likely to be inside eis_device_frame() - * so we should flush a frame event before disconnecting and... */ - log_error(ei, "clock_gettime failed: %s", strerror(-rc)); + if (ei->clock_now) + ts = ei->clock_now(ei); + else { + int rc = now(&ts); + if (rc < 0) { + /* We should probably disconnect here but the chances of this + * happening are so slim it's not worth worrying about. Plus, + * if this fails we're likely to be inside eis_device_frame() + * so we should flush a frame event before disconnecting and... */ + log_error(ei, "clock_gettime failed: %s", strerror(-rc)); + } } + return ts; } diff --git a/src/libei.h b/src/libei.h index 9a6b06e..27dadc0 100644 --- a/src/libei.h +++ b/src/libei.h @@ -693,6 +693,24 @@ ei_log_set_priority(struct ei *ei, enum ei_log_priority priority); enum ei_log_priority ei_log_get_priority(const struct ei *ei); +/** + * Optional override function for ei_now(). + * + * By default ei_now() returns the current timestamp in CLOCK_MONOTONIC. This + * may be overridden by a caller to provide a different timestamp. + * + * There is rarely a need to override this function. It exists for the libei-internal test suite. + */ +typedef uint64_t (*ei_clock_now_func)(struct ei *ei); + +/** + * Override the function that returns the current time ei_now(). + * + * There is rarely a need to override this function. It exists for the libei-internal test suite. + */ +void +ei_clock_set_now_func(struct ei *, ei_clock_now_func func); + /** * Set the name for this client. This is a suggestion to the * server only and may not be honored. @@ -802,8 +820,8 @@ ei_peek_event(struct ei *ei); * @returns a timestamp in microseconds for the current time to pass into * ei_device_frame(). * - * In the current implementation, the returned timestamp is CLOCK_MONOTONIC - * for compatibility with evdev and libinput. + * By default, the returned timestamp is CLOCK_MONOTONIC for compatibility with + * evdev and libinput. This can be overridden with ei_clock_set_now_func(). */ uint64_t ei_now(struct ei *ei); diff --git a/src/libeis-private.h b/src/libeis-private.h index fcdfb5e..b873633 100644 --- a/src/libeis-private.h +++ b/src/libeis-private.h @@ -72,6 +72,8 @@ struct eis { enum eis_log_priority priority; } log; + eis_clock_now_func clock_now; + const struct eis_proto_requests *requests; }; diff --git a/src/libeis.c b/src/libeis.c index 044599c..315d820 100644 --- a/src/libeis.c +++ b/src/libeis.c @@ -424,18 +424,30 @@ eis_add_client(struct eis *eis, struct eis_client *client) list_append(&eis->clients, &client->link); } +_public_ void +eis_clock_set_now_func(struct eis *eis, eis_clock_now_func func) +{ + eis->clock_now = func; +} + _public_ uint64_t eis_now(struct eis *eis) { uint64_t ts = 0; - int rc = now(&ts); - if (rc < 0) { - /* We should probably disconnect here but the chances of this - * happening are so slim it's not worth worrying about. Plus, - * if this fails we're likely to be inside ei_device_frame() - * so we should flush a frame event before disconnecting and... */ - log_error(eis, "clock_gettime failed: %s", strerror(-rc)); + if (eis->clock_now) + ts = eis->clock_now(eis); + else { + int rc = now(&ts); + + if (rc < 0) { + /* We should probably disconnect here but the chances of this + * happening are so slim it's not worth worrying about. Plus, + * if this fails we're likely to be inside ei_device_frame() + * so we should flush a frame event before disconnecting and... */ + log_error(eis, "clock_gettime failed: %s", strerror(-rc)); + } } + return ts; } diff --git a/src/libeis.h b/src/libeis.h index f53890d..0544855 100644 --- a/src/libeis.h +++ b/src/libeis.h @@ -439,6 +439,24 @@ eis_log_set_priority(struct eis *eis, enum eis_log_priority priority); enum eis_log_priority eis_log_get_priority(const struct eis *eis); +/** + * Optional override function for eis_now(). + * + * By default eis_now() returns the current timestamp in CLOCK_MONOTONIC. This + * may be overridden by a caller to provide a different timestamp. + * + * There is rarely a need to override this function. It exists for the libeis-internal test suite. + */ +typedef uint64_t (*eis_clock_now_func)(struct eis *eis); + +/** + * Override the function that returns the current time eis_now(). + * + * There is rarely a need to override this function. It exists for the libeis-internal test suite. + */ +void +eis_clock_set_now_func(struct eis *, eis_clock_now_func func); + struct eis * eis_ref(struct eis *eis); @@ -1594,11 +1612,11 @@ eis_event_touch_get_y(struct eis_event *event); * @returns a timestamp for the current time to pass into * eis_device_frame(). * - * In the current implementation, the returned timestamp is CLOCK_MONOTONIC - * for compatibility with evdev and libinput. + * By default, the returned timestamp is CLOCK_MONOTONIC for compatibility with + * evdev and libinput. This can be overridden with eis_clock_set_now_func(). */ uint64_t -eis_now(struct eis *ei); +eis_now(struct eis *eis); /** * @} diff --git a/test/eierpecken.c b/test/eierpecken.c index f2011c8..2f2e225 100644 --- a/test/eierpecken.c +++ b/test/eierpecken.c @@ -86,6 +86,9 @@ struct peck { bool ei_fatal_bugs; bool eis_fatal_bugs; + + uint64_t ei_time_offset; + uint64_t eis_time_offset; }; static const uint32_t INDENTATION = 4; @@ -105,6 +108,40 @@ peck_dedent(struct peck *peck) static OBJECT_IMPLEMENT_GETTER(peck, indent, uint32_t); +static uint64_t +peck_ei_now_func(struct ei *ei) +{ + static uint64_t offset = 0; + struct peck *peck = ei_get_user_data(ei); + + if (peck->ei_time_offset != offset) { + offset = peck->ei_time_offset; + log_debug(peck, "Time is now offset by %" PRIu64"us\n", offset); + } + + uint64_t ts = 0; + now(&ts); + + return ts + peck->ei_time_offset; +} + +static uint64_t +peck_eis_now_func(struct eis *eis) +{ + static uint64_t offset = 0; + struct peck *peck = eis_get_user_data(eis); + + if (peck->eis_time_offset != offset) { + offset = peck->eis_time_offset; + log_debug(peck, "Time is now offset by %" PRIu64"us\n", offset); + } + + uint64_t ts = 0; + now(&ts); + + return ts + peck->ei_time_offset; +} + static void peck_destroy(struct peck *peck) { @@ -147,6 +184,20 @@ peck_destroy(struct peck *peck) } } +void +peck_ei_add_time_offset(struct peck *peck, uint64_t us) +{ + log_debug(peck, "Adding ei time offset of %" PRIu64 "us\n", us); + peck->ei_time_offset += us; +} + +void +peck_eis_add_time_offset(struct peck *peck, uint64_t us) +{ + log_debug(peck, "Adding EIS time offset of %" PRIu64 "us\n", us); + peck->eis_time_offset += us; +} + static OBJECT_IMPLEMENT_CREATE(peck); OBJECT_IMPLEMENT_UNREF(peck); @@ -270,32 +321,20 @@ peck_ei_get_default_touch(struct peck *peck) }; /* Ensures that device frames in tests always have an ascending and fixed - * interval. We start with 30 * interval in the past, every event then goes - * forward by 10ms. - * - * Tests that have more than 30 events will run into the future with their - * timestamps, shouldn't be an issue for the test suite though. + * interval. Every time this is called it adds 10ms to the time offset. */ uint64_t peck_ei_now(struct peck *peck) { - const uint32_t interval = ms2us(10); - const uint32_t past_offset = interval * 30; - - peck->now = peck->now == 0 ? ei_now(peck->ei) - past_offset : peck->now + interval; - - return peck->now; + peck_ei_add_time_offset(peck, ms2us(10)); + return ei_now(peck->ei); } uint64_t peck_eis_now(struct peck *peck) { - const uint32_t interval = ms2us(10); - const uint32_t past_offset = interval * 30; - - peck->now = peck->now == 0 ? eis_now(peck->eis) - past_offset : peck->now + interval; - - return peck->now; + peck_eis_add_time_offset(peck, ms2us(10)); + return eis_now(peck->eis); } void @@ -439,6 +478,7 @@ new_context(enum peck_ei_mode ei_mode) struct eis *eis = eis_new(peck); eis_log_set_handler(eis, peck_eis_log_handler); eis_log_set_priority(eis, EIS_LOG_PRIORITY_DEBUG); + eis_clock_set_now_func(eis, peck_eis_now_func); rc = eis_setup_backend_fd(eis); munit_assert_int(rc, ==, 0); fd = eis_backend_fd_add_client(eis); @@ -451,6 +491,7 @@ new_context(enum peck_ei_mode ei_mode) ei_set_user_data(ei, peck); ei_log_set_handler(ei, peck_ei_log_handler); ei_log_set_priority(ei, EI_LOG_PRIORITY_DEBUG); + ei_clock_set_now_func(ei, peck_ei_now_func); ei_configure_name(ei, "eierpecken test context"); rc = ei_setup_backend_fd(ei, fd); munit_assert_int(rc, ==, 0); diff --git a/test/eierpecken.h b/test/eierpecken.h index 5e02a0f..bbe799d 100644 --- a/test/eierpecken.h +++ b/test/eierpecken.h @@ -167,6 +167,12 @@ peck_eis_disable_fatal_bug(struct peck *peck); void peck_eis_enable_fatal_bug(struct peck *peck); +void +peck_ei_add_time_offset(struct peck *peck, uint64_t us); + +void +peck_eis_add_time_offset(struct peck *peck, uint64_t us); + void peck_enable_eis_behavior(struct peck *peck, enum peck_eis_behavior behavior);