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

Memoize errors #1118

Open
1 task done
fabianmuecke opened this issue Feb 9, 2024 · 0 comments
Open
1 task done

Memoize errors #1118

fabianmuecke opened this issue Feb 9, 2024 · 0 comments

Comments

@fabianmuecke
Copy link
Contributor

fabianmuecke commented Feb 9, 2024

  • I have read CONTRIBUTING and have done my best to follow them.

Note

This is more of a feature request, than a bug report.

I noticed that errors thrown by an expression do not get memoized the way result values do. I believe this would be very simple to change, but before I make a PR for that, I'd like to know, if you'd consider merging that or if such a change in behavior is not desired.

What did you do?

I wrote an extension function which allows to add a failure on timeout of an AsyncExpectation. For this to work properly, the expression needs to be evaluated at least twice - once for the possible timeout failure, and once for all other test conditions. I then used this extension function with an AsyncExpectation that expected an error to be thrown and later checked the call count property of a mock used by this test.

What did you expect to happen?

I expected the call count of the mock to be 6.

What actually happened instead?

I noticed that the call count was 12, so twice as high as I had expected, which lead me to believe, that the error leads to the expression being evaluated twice instead of just once in case of an error. A quick look at the implementations of memoizedClosure in Expression and AsyncExpression confirmed my suspicion. Errors are not cached.

Environment

List the software versions you're using:

  • Quick: none
  • Nimble: 13.2.0
  • Xcode Version: 15.0.1
  • Swift Version: Xcode Default

Please also mention which package manager you used and its version. Delete the
other package managers in this list:

  • Swift Package Manager - Swift 5.9.0

Suggested improvement

My suggestion would be to change e.g. the memoizedClosure function of AsyncExpression like this:

// Memoizes the given closure, only calling the passed
// closure once; even if repeat calls to the returned closure
private func memoizedClosure<T>(_ closure: @escaping () async throws -> T) -> (Bool) async throws -> T {
    var cache: Result<T, Error>?
    return { withoutCaching in
        if withoutCaching || cache == nil {
            cache = Result(catching: { try await closure() })
        }
        return try cache!.get()
    }
}

and the memoizedClosure function of Expression accordingly. If you think that would be a good addition, I'll gladly make a PR for that. 🙏

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

1 participant