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

test: fix flakes in HttpJsonDirectServerStreamingCallableTest #2432

Merged
merged 2 commits into from
Feb 6, 2024

Conversation

meltsufin
Copy link
Member

@meltsufin meltsufin commented Jan 31, 2024

The flakes seem to stem from parallel execution and the resulting race conditions around static member variables, particularly the mockService. Attempting to fix this by using a separate mockService for each test.

Fixes: #1905.
Fixes: #2107.
Fixes: #1876.
Fixes: #2083.
Related: #1842.
Fixes: #1587.
Fixes: #1684.

The flakes seem to stem from parallel execution and the resulting race conditions around static member variables, particularly the `mockService`. Attempting to fix this by using a separate `mockService` for each test.

Fixes: #1905.
Fixes: #2107.
Fixes: #1876.
Fixes: #2083.
Fixes: #1842.
Fixes: #1587.
Fixes: #1684.
@meltsufin meltsufin requested a review from a team as a code owner January 31, 2024 20:49
@product-auto-label product-auto-label bot added the size: m Pull request size is medium. label Jan 31, 2024
@meltsufin meltsufin requested a review from suztomo January 31, 2024 20:49
@suztomo
Copy link
Member

suztomo commented Feb 1, 2024

Picking the 1st issue #1905, would you describe (in PR description) why the assertion (the return value of await being expected to be true) would fail due to the static shared mock object?

Error:  Tests run: 9, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 16.502 s <<< FAILURE! - in com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest
Error:  com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testServerStreamingStart  Time elapsed: 5.148 s  <<< FAILURE!
value of: await(...)
expected to be true
	at com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testServerStreamingStart(HttpJsonDirectServerStreamingCallableTest.java:205)

As per its Javadoc (https://github.com/googleapis/sdk-platform-java/blob/d2fe5203c4db1f8ddfd5a9566e6259b53441348a/gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/testing/MockHttpService.java), MockHttpTransport is thread-safe.

/**
 * Mocks an HTTPTransport. Expected responses and exceptions can be added to a queue from which this
 * mock HttpTransport polls when it relays a response.
 *
 * <p>As required by {@link MockHttpTransport} this implementation is thread-safe, but it is not
 * idempotent (as a typical service would be) and must be used with extra caution. Mocked responses
 * are returned in FIFO order and if multiple threads read from the same MockHttpService
 * simultaneously, they may be getting responses intended for other consumers.
 */
public final class MockHttpService extends MockHttpTransport {

@meltsufin
Copy link
Member Author

@suztomo I don't believe that the thread safety of the MockHttpTransport is relevant. I believe the problem is that the tests call mockService.addResponse() and assume that there is nothing else adding or removing responses from the mockService. However, with parallel execution and the shared mockService that won't be the case.
Similarly for the await() in #1905, mockService is in the picture, and if it's not behaving as expected due to multiple tests interacting with it, the await() can fail.

The main claim I'm making is that parallel execution of tests with a shared mockService is the problem. Do you think otherwise? What's your hypothesis?

@suztomo
Copy link
Member

suztomo commented Feb 5, 2024

with parallel execution

@meltsufin If I remember correctly the test methods in a JUnit test class run sequentially, unless pom.xml specifies the parallel property. We can confirm this by inserting the timestamp at the beginning and the end of each test method.

I believe the (private) MOCK_SERVICE variable is not accessed by other classes the HttpJsonDirectServerStreamingCallableTest.

Based on these, I think the current usage of MOCK_SERVICE serving as a queue (FIFO = first-in, first-out) works as intended.


My memo: testServerStreamingStart (from the main branch)

  @Test
  public void testServerStreamingStart() throws InterruptedException {
    MOCK_SERVICE.addResponse(new Money[] {DEFAULT_RESPONSE});
    CountDownLatch latch = new CountDownLatch(1);
    MoneyObserver moneyObserver = new MoneyObserver(true, latch);

    streamingCallable.call(DEFAULT_REQUEST, moneyObserver);

    Truth.assertThat(moneyObserver.controller).isNotNull();
    // wait for the task to complete, otherwise it may interfere with other tests, since they share
    // the same MockService and unfinished request in this test may start reading messages
    // designated for other tests.
    Truth.assertThat(latch.await(2, TimeUnit.SECONDS)).isTrue();
  }

MockHttpService's javadoc describes it's a queue (FIFO = first-in, first-out):

/**
 * Mocks an HTTPTransport. Expected responses and exceptions can be added to a queue from which this
 * mock HttpTransport polls when it relays a response.
 *
 * <p>As required by {@link MockHttpTransport} this implementation is thread-safe, but it is not
 * idempotent (as a typical service would be) and must be used with extra caution. Mocked responses
 * are returned in FIFO order and if multiple threads read from the same MockHttpService
 * simultaneously, they may be getting responses intended for other consumers.
 */
public final class MockHttpService extends MockHttpTransport {

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html#await-long-java.util.concurrent.TimeUnit-

Returns:
true if the count reached zero and false if the waiting time elapsed before the count reached zero

Why would latch.await(2, TimeUnit.SECONDS) return false? => According to Javadoc, it's because "waiting time elapsed before the count rached zero". I would start with suspecting that this 2 seconds is the culprit (I haven't read the test in details).

@meltsufin
Copy link
Member Author

@suztomo The tests should be written in a way as to support parallel execution, since it's controlled externally from the test itself.

I've tried explicitly enabling parallel execution and running the test in main and I consistently get the kinds of failures in the listed bugs.

gax-java/gax-httpjson/pom.xml:

     <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.2.5</version>
        <configuration>
          <parallel>all</parallel>
          <useUnlimitedThreads>true</useUnlimitedThreads>
        </configuration>
      </plugin>
gax-httpjson$ mvn clean test  -Dcheckstyle.skip -Dtest=HttpJsonDirectServerStreamingCallableTest

Results:

[INFO] -------------------------------------------------------
[INFO] Running com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest
[ERROR] Tests run: 9, Failures: 5, Errors: 1, Skipped: 0, Time elapsed: 10.04 s <<< FAILURE! -- in com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest
[ERROR] com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testManualFlowControl -- Time elapsed: 2.041 s <<< FAILURE!
value of: await(...)
expected to be true
        at com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testManualFlowControl(HttpJsonDirectServerStreamingCallableTest.java:246)

[ERROR] com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testBlockingServerStreaming -- Time elapsed: 0.200 s <<< ERROR!
com.google.api.gax.rpc.UnknownException: java.lang.IllegalArgumentException
        at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:119)
        at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:41)
        at com.google.api.gax.httpjson.HttpJsonApiExceptionFactory.create(HttpJsonApiExceptionFactory.java:67)
        at com.google.api.gax.httpjson.HttpJsonExceptionResponseObserver.onErrorImpl(HttpJsonExceptionResponseObserver.java:82)
        at com.google.api.gax.rpc.StateCheckingResponseObserver.onError(StateCheckingResponseObserver.java:84)
        at com.google.api.gax.httpjson.HttpJsonDirectStreamController$ResponseObserverAdapter.onClose(HttpJsonDirectStreamController.java:125)
        at com.google.api.gax.httpjson.HttpJsonClientCallImpl$OnCloseNotificationTask.call(HttpJsonClientCallImpl.java:530)
        at com.google.api.gax.httpjson.HttpJsonClientCallImpl.notifyListeners(HttpJsonClientCallImpl.java:379)
        at com.google.api.gax.httpjson.HttpJsonClientCallImpl.deliver(HttpJsonClientCallImpl.java:306)
        at com.google.api.gax.httpjson.HttpJsonClientCallImpl.setResult(HttpJsonClientCallImpl.java:156)
        at com.google.api.gax.httpjson.HttpRequestRunnable.run(HttpRequestRunnable.java:149)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)
        Suppressed: java.lang.RuntimeException: Asynchronous task failed
                at com.google.api.gax.rpc.ServerStreamIterator.hasNext(ServerStreamIterator.java:105)
                at com.google.common.collect.Iterators.addAll(Iterators.java:366)
                at com.google.common.collect.Lists.newArrayList(Lists.java:146)
                at com.google.common.collect.Lists.newArrayList(Lists.java:132)
                at com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testBlockingServerStreaming(HttpJsonDirectServerStreamingCallableTest.java:338)
                at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
                at java.base/java.lang.reflect.Method.invoke(Method.java:580)
                at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
                at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
                at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
                at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
                at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
                at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
                at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
                at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
                at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
                at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
                at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
                at org.apache.maven.surefire.junitcore.pc.Scheduler$1.run(Scheduler.java:345)
                at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
                at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
                ... 3 more
Caused by: java.lang.IllegalArgumentException
        at com.google.common.base.Preconditions.checkArgument(Preconditions.java:129)
        at com.google.api.gax.httpjson.testing.MockHttpService.getHttpResponse(MockHttpService.java:131)
        at com.google.api.gax.httpjson.testing.MockHttpService.access$100(MockHttpService.java:60)
        at com.google.api.gax.httpjson.testing.MockHttpService$MockHttpRequest.execute(MockHttpService.java:164)
        at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1012)
        at com.google.api.gax.httpjson.HttpRequestRunnable.run(HttpRequestRunnable.java:115)
        ... 3 more

[ERROR] com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testServerStreaming -- Time elapsed: 10.04 s <<< FAILURE!
value of: await(...)
expected to be true
        at com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testServerStreaming(HttpJsonDirectServerStreamingCallableTest.java:226)

[ERROR] com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testDeadlineExceededServerStreaming -- Time elapsed: 0.230 s <<< FAILURE!
expected instance of: com.google.api.gax.rpc.DeadlineExceededException
but was instance of : com.google.api.gax.rpc.UnknownException
with value          : com.google.api.gax.rpc.UnknownException: java.lang.IllegalArgumentException
        at com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testDeadlineExceededServerStreaming(HttpJsonDirectServerStreamingCallableTest.java:360)
Caused by: com.google.api.gax.rpc.UnknownException: java.lang.IllegalArgumentException
        at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:119)
        at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:41)
        at com.google.api.gax.httpjson.HttpJsonApiExceptionFactory.create(HttpJsonApiExceptionFactory.java:67)
        at com.google.api.gax.httpjson.HttpJsonExceptionResponseObserver.onErrorImpl(HttpJsonExceptionResponseObserver.java:82)
        at com.google.api.gax.rpc.StateCheckingResponseObserver.onError(StateCheckingResponseObserver.java:84)
        at com.google.api.gax.httpjson.HttpJsonDirectStreamController$ResponseObserverAdapter.onClose(HttpJsonDirectStreamController.java:125)
        at com.google.api.gax.httpjson.HttpJsonClientCallImpl$OnCloseNotificationTask.call(HttpJsonClientCallImpl.java:530)
        at com.google.api.gax.httpjson.HttpJsonClientCallImpl.notifyListeners(HttpJsonClientCallImpl.java:379)
        at com.google.api.gax.httpjson.HttpJsonClientCallImpl.deliver(HttpJsonClientCallImpl.java:306)
        at com.google.api.gax.httpjson.HttpJsonClientCallImpl.setResult(HttpJsonClientCallImpl.java:156)
        at com.google.api.gax.httpjson.HttpRequestRunnable.run(HttpRequestRunnable.java:149)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.IllegalArgumentException
        at com.google.common.base.Preconditions.checkArgument(Preconditions.java:129)
        at com.google.api.gax.httpjson.testing.MockHttpService.getHttpResponse(MockHttpService.java:131)
        at com.google.api.gax.httpjson.testing.MockHttpService.access$100(MockHttpService.java:60)
        at com.google.api.gax.httpjson.testing.MockHttpService$MockHttpRequest.execute(MockHttpService.java:164)
        at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1012)
        at com.google.api.gax.httpjson.HttpRequestRunnable.run(HttpRequestRunnable.java:115)
        ... 3 more

[ERROR] com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testObserverErrorCancelsCall -- Time elapsed: 0.232 s <<< FAILURE!
value of: getCode()
expected: CANCELLED
but was : UNKNOWN
        at com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testObserverErrorCancelsCall(HttpJsonDirectServerStreamingCallableTest.java:325)

[ERROR] com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testOnResponseError -- Time elapsed: 0.232 s <<< FAILURE!
value of: getCode()
expected: NOT_FOUND
but was : UNKNOWN
        at com.google.api.gax.httpjson.HttpJsonDirectServerStreamingCallableTest.testOnResponseError(HttpJsonDirectServerStreamingCallableTest.java:280)

[INFO] 
[INFO] Results:
[INFO] 
[ERROR] Failures: 
[ERROR]   HttpJsonDirectServerStreamingCallableTest.testDeadlineExceededServerStreaming:360 expected instance of: com.google.api.gax.rpc.DeadlineExceededException
but was instance of : com.google.api.gax.rpc.UnknownException
with value          : com.google.api.gax.rpc.UnknownException: java.lang.IllegalArgumentException
[ERROR]   HttpJsonDirectServerStreamingCallableTest.testManualFlowControl:246 value of: await(...)
expected to be true
[ERROR]   HttpJsonDirectServerStreamingCallableTest.testObserverErrorCancelsCall:325 value of: getCode()
expected: CANCELLED
but was : UNKNOWN
[ERROR]   HttpJsonDirectServerStreamingCallableTest.testOnResponseError:280 value of: getCode()
expected: NOT_FOUND
but was : UNKNOWN
[ERROR]   HttpJsonDirectServerStreamingCallableTest.testServerStreaming:226 value of: await(...)
expected to be true
[ERROR] Errors: 
[ERROR]   HttpJsonDirectServerStreamingCallableTest.testBlockingServerStreaming » Unknown java.lang.IllegalArgumentException
[INFO] 
[ERROR] Tests run: 9, Failures: 5, Errors: 1, Skipped: 0
[INFO] 

This does not happen when run from the flaky-HttpJsonDirectServerStreamingCallableTest branch.

@suztomo
Copy link
Member

suztomo commented Feb 5, 2024

@meltsufin The tests with MockHttpService were written without parallel execution in mind (So it's natural that they fail in parallel execution). I don't think it needs parallel execution.

since it's controlled externally from the test itself.

Would you elaborate this more? I see HttpJsonDirectServerStreamingCallableTest is just a normal JUnit test, something special about this class?

@meltsufin
Copy link
Member Author

@meltsufin The tests with MockHttpService were written without parallel execution in mind (So it's natural that they fail in parallel execution). I don't think it needs parallel execution.

since it's controlled externally from the test itself.

Would you elaborate this more? I see HttpJsonDirectServerStreamingCallableTest is just a normal JUnit test, something special about this class?

There is nothing special about the test other than that it doesn't support parallel execution. What I'm saying is that the test class itself cannot tell the plugin not to run in parallel. I'm not sure where parallel execution is enabled, but it seems like it is. It can be anywhere from the CI run command to the plugin configuration. My point is that it's wrong to make the assumption that the test will never be executed in a parallel manner. The symptoms of the flakes and the repo I mentioned point to the notion that it's the problem.
Do you have a different hypothesis for the reason behind all of these flakes? Note, I'm able to repro the flakes using parallel execution of the test.

@suztomo
Copy link
Member

suztomo commented Feb 5, 2024

Parallel execution, if configured, fails the build but build failure does not mean parallel execution is configured. (mvn help:effective-pom would reveal any parallel execution is enabled or not. I guess parallel execution is not enabled; otherwise we would see more frequent failures)

Do you have a different hypothesis for the reason behind all of these flakes?

My hypothesis is latch.await(2, TimeUnit.SECONDS) was written in a bad assumption that the latch is counted down within 2 seconds. To validate/invalidate this hypothesis, you would need to understand the test and threads (executors) involved.

@meltsufin
Copy link
Member Author

@suztomo As you know, help:effective-pom doesn't tell the full story because additional configuration can be passed through the command-line. For instance we pass -T 1C to enable parallel builds. Even if we assume that the tests are not executed in parallel, the JVMs may be re-used for consequent test executions, and any static variables will not be re-initialized. The safeguards that are already put in might be insufficient. It's just safer not to use static variables in tests. The testing is confirming this.
Why would 2 seconds be insufficient for the latch? Also, please take a look at the other flakes. This class has 7 different observed flakes! Many of them are reproduced by forcing parallel execution. Why is this not sufficient reason to accept the change?

@suztomo
Copy link
Member

suztomo commented Feb 6, 2024

On my Mac, I checked out the flaky-HttpJsonDirectServerStreamingCallableTest branch (342467d) and ran the testServerStreamingStart test via mvn -f gax-java/gax-httpjson/pom.xml test -Dtest='HttpJsonDirectServerStreamingCallableTest#testServerStreamingStart', while running a heavy build in background (mvn clean install -T 4C in google-cloud-java repo). It failed with the same error message as #1905:

Screenshot 2024-02-05 at 9 08 39 PM

Given this observation, I don't think the current flaky-HttpJsonDirectServerStreamingCallableTest branch (342467d) fixes the flakiness problem.

@meltsufin
Copy link
Member Author

@suztomo Maybe this particular one can also benefit from an increased timeout for scenarios like this. Have you tried increasing?
Are you able to reproduce any of the other 6 flakes this way? Thanks!

@meltsufin
Copy link
Member Author

@suztomo Can you run your test again? I've removed that line because it's no longer necessary as the mockService is no longer shared.

Copy link

sonarqubecloud bot commented Feb 6, 2024

Quality Gate Passed Quality Gate passed for 'gapic-generator-java-root'

Kudos, no new issues were introduced!

0 New issues
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

Copy link

sonarqubecloud bot commented Feb 6, 2024

Quality Gate Passed Quality Gate passed for 'java_showcase_integration_tests'

Kudos, no new issues were introduced!

0 New issues
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

@suztomo
Copy link
Member

suztomo commented Feb 6, 2024

Thank you. My local test passes for testServerStreamingStart and the logic (the mock object is no longer shared and thus no need to wait) makes sense.

The testServerStreamingStart fix is for #1905. What about other 6 issues this pull request claims to fix? I checked out the latest commit (1d4508d) and ran mvn -f gax-java/gax-httpjson/pom.xml test -Dtest='HttpJsonDirectServerStreamingCallableTest' with the heavy build running in the background. It failed with HttpJsonDirectServerStreamingCallableTest.testOnResponseError:

Screenshot 2024-02-06 at 9 08 05 AM

This matches the observation of #1842.

@suztomo
Copy link
Member

suztomo commented Feb 6, 2024

@meltsufin Shall we merge this pull request with "Fixes #1905" only, rather than trying to fix other 6 issues? In general, it's a good practice to have fine-grained pull requests.

@meltsufin
Copy link
Member Author

@meltsufin Shall we merge this pull request with "Fixes #1905" only, rather than trying to fix other 6 issues? In general, it's a good practice to have fine-grained pull requests.

Which of the other issues it doesn't fix? It's doing one main thing which is making the mockService not shared.

@suztomo
Copy link
Member

suztomo commented Feb 6, 2024

I want PR authors to provide reasoning that the changes indeed fix the issue. Your "I've removed that line because it's no longer necessary as the mockService is no longer shared." was a great example of that (Thank you). I want similar reasoning for other issues as well, if this pull request claims the issues are fixed by this change.

Which of the other issues it doesn't fix?

At least #1842 is not addressed as below.


I checked out the latest commit (1d4508d) and ran mvn -f gax-java/gax-httpjson/pom.xml test -Dtest='HttpJsonDirectServerStreamingCallableTest' with the heavy build running in the background. It failed with HttpJsonDirectServerStreamingCallableTest.testOnResponseError:

Screenshot 2024-02-06 at 9 08 05 AM

This matches the observation of #1842.

@meltsufin
Copy link
Member Author

@suztomo I removed #1842 from the list of issues being fixed. I'll handle it in a separate PR. Are you seeing any other failures under heavy load?

@suztomo
Copy link
Member

suztomo commented Feb 6, 2024

Are you seeing any other failures under heavy load?

#1684 also recurred

Screenshot 2024-02-06 at 2 58 36 PM

Copy link
Member

@suztomo suztomo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in the call, I'm approving this. When the issues recur, we can reopen them.

@meltsufin meltsufin merged commit 523d6b6 into main Feb 6, 2024
39 checks passed
@meltsufin meltsufin deleted the flaky-HttpJsonDirectServerStreamingCallableTest branch February 6, 2024 21:07
ddixit14 pushed a commit that referenced this pull request Feb 15, 2024
The flakes seem to stem from parallel execution and the resulting race conditions around static member variables, particularly the `mockService`. Attempting to fix this by using a separate `mockService` for each test.

Fixes: #1905.
Fixes: #2107.
Fixes: #1876.
Fixes: #2083.
Fixes: #1587.
Fixes: #1684.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment