Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor time-based tests to use fake and sharp loop time #881

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

nolar
Copy link
Owner

@nolar nolar commented Dec 26, 2021

Utilise a new library — https://github.com/nolar/looptime — to have a fake time in event loops. The library does a lot of things, but the most important one is the sharp time with predictable steps with no code overhead included, which is typically random.

Everything else goes as a side-effect: e.g. the fast execution of such tests with zero real-time for any fake duration of loop time, convenient looptime fixture for assertions, etc.

This PR also demonstrates how the tests can be rewritten to use the provided looptime's features (and is mentioned in its README).

Fixes #212; related: #338

@nolar nolar added the automation CI/CD: testing, linting, releasing automatically label Dec 26, 2021
@nolar nolar force-pushed the faketime branch 3 times, most recently from e0f78f3 to 9c8ab16 Compare December 31, 2021 21:01
@lgtm-com
Copy link

lgtm-com bot commented Jul 24, 2022

This pull request introduces 1 alert when merging 420fa17 into 7b45690 - view on LGTM.com

new alerts:

  • 1 for Unused import

Otherwise, some tests may populate the cluster-scoped URLs while consuming the namespace-scoped URLs and thus catching errors, which are cryptic and hard to debug.

Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
nolar added 10 commits July 30, 2023 21:06
Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
…lds to the implementation

Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
…h has no meaning

Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
…tervals

The routines that depend only on the internal intervals and durations should use the internal loop time only — which can be later faked by e.g. `looptime`.

If the system or process time is used, these routines fall out of time-faking and might take many more cycles to reach the desired real-world timestamp (just by letting the real time flow naturally).

This does NOT cover the cases with intervals and durations based on the global time (i.e. UTC clock) — e.g. handlers' timeouts, retries, etc.

Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
…topped/delayed)

Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
Utilise a new library — https://github.com/nolar/looptime — to have a fake time in event loops. The library does a lot of things, but the most important one is the sharp time with predictable steps with **no code overhead included**, which is typically random.

Everything else goes as a side-effect: e.g. the fast execution of such tests with zero real-time for any fake duration of loop time, convenient `looptime` fixture for assertions, etc.

Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
await simulate_cycle(event_object)

assert k8s_mocked.sleep.call_count == 0
assert looptime == 1.23 # i.e. no additional sleeps happened

Check warning

Code scanning / CodeQL

Redundant comparison Warning test

Test is always true, because of
this condition
.
await simulate_cycle(event_object)
await dummy.wait_for_daemon_done()

assert k8s_mocked.sleep.call_count == 0
assert looptime == 1.23 + 4.56 # i.e. not additional sleeps happened

Check warning

Code scanning / CodeQL

Redundant comparison Warning test

Test is always true, because of
this condition
.
assert timer.seconds < CODE_OVERHEAD # near-instant
assert mock.call_args[0][0] == 'cancelled'
await scheduler.close()
assert looptime == 0

Check warning

Code scanning / CodeQL

Redundant comparison Warning test

Test is always true, because of
this condition
.
assert mock.call_args[0][0] == 'finished'
await flag2.wait()
assert looptime == 123
assert mock.call_args_list[1][0][0] == 'finished'

Check warning

Code scanning / CodeQL

Unreachable code Warning test

This statement is unreachable.
sleep.return_value = 55 # simulated sleep time left
async with throttled(throttler=throttler, logger=logger, delays=[123, 234], wakeup=wakeup):
raise Exception()

await asyncio.sleep(77)

Check warning

Code scanning / CodeQL

Unreachable code Warning test

This statement is unreachable.
sleep.return_value = 55 # simulated sleep time left
async with throttled(throttler=throttler, logger=logger, delays=[123, 234], wakeup=wakeup):
raise Exception()

await asyncio.sleep(77)

Check warning

Code scanning / CodeQL

Unreachable code Warning test

This statement is unreachable.
sleep.return_value = 55 # simulated sleep time left
async with throttled(throttler=throttler, logger=logger, delays=[123, 234], wakeup=wakeup):
raise Exception()

await asyncio.sleep(1000)

Check warning

Code scanning / CodeQL

Unreachable code Warning test

This statement is unreachable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automation CI/CD: testing, linting, releasing automatically
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Stabilise the time-based tests with asyncio sleeps/timeouts
1 participant