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

eventually without customization never runs test method #3988

Open
bddckr opened this issue Apr 27, 2024 · 7 comments
Open

eventually without customization never runs test method #3988

bddckr opened this issue Apr 27, 2024 · 7 comments
Assignees

Comments

@bddckr
Copy link

bddckr commented Apr 27, 2024

Using Kotest 5.8.1, the following test

class MyTestClass {
    @Test
    fun myTestMethod() = runTest {
        eventually {
            error("Whoops!")
        }
    }
}

(running in JUnit 4 - Android project)

immediately fails with

java.lang.AssertionError: Block failed after 0ms; attempted 0 time(s)

The test block is never run, and the output is really just the above, giving no further details about what went wrong.


I've dug into this and believe the issue is that the duration of the default EventuallyConfig is set to INFINITE:


which is then added to the start time:

which results in an overflow, I believe. The result is that the check against the end time is immediately failing
fun hasAttemptsRemaining() = timeInMillis() < end && iterations < config.retries


While I initially wanted to raise this as a documentation issue only, I do wonder whether a duration of INFINITE should be handled specifically to mean "retry forever". Currently it basically results in "attempt not even once". To clarify: While the default value could simply be changed, I'm instead suggesting that EventuallyControl should be changed to allow retrying forever.

@mirageoasis
Copy link
Contributor

mirageoasis commented May 1, 2024

I agree I think we have to change

fun hasAttemptsRemaining() = timeInMillis() < end && iterations < config.retries

or maybe

can I write code this issue?

@Kantis
Copy link
Member

Kantis commented May 8, 2024

@mirageoasis I think we could solve it by changing

to

val end = maxOf(Long.MAX_VALUE, start + config.duration.inWholeMilliseconds) // prevent overflow

I think we could also reconsider using infinite duration for eventually as a default for 6.0

@mirageoasis
Copy link
Contributor

@mirageoasis I think we could solve it by changing

to

val end = maxOf(Long.MAX_VALUE, start + config.duration.inWholeMilliseconds) // prevent overflow

I think we could also reconsider using infinite duration for eventually as a default for 6.0

well that case only end up fixing end to Long.MAX_VALUE so I don't think it will be helpful

instead I suggest using code something like this

fun addSafely(a: Long, b: Long): Long {
    val sum = a + b
    if (a > 0 && b > 0 && sum < 0) {
        return Long.MAX_VALUE
    } else if (a < 0 && b < 0 && sum > 0) {
        return Long.MIN_VALUE
    } else {
        return sum
    }
}

kind of prototype code

@Kantis
Copy link
Member

Kantis commented May 9, 2024

Will start ever be negative?

@mirageoasis
Copy link
Contributor

Will start ever be negative?

if config.duration.inWholeMilliseconds value is 5

val end = maxOf(Long.MAX_VALUE, start + 5)

and end value will be Long.MAX_VALUE which I think will cause error

@mirageoasis
Copy link
Contributor

Will start ever be negative?

instead I suggest other solution

fun hasAttemptsRemaining() = timeInMillis() < end && iterations < config.retries

instead fixing hasAttemptRemaing method

like if end value is already minus it makes while infinite loop

what about my idea?

@Kantis
Copy link
Member

Kantis commented May 9, 2024

Feel free to publish a draft for further discussion :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants