From dd48fca3a86b68fdd3f7c549dbaac18f500f8352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Mon, 16 Sep 2024 15:13:18 +0200 Subject: [PATCH] test: ignore if the mock server failed to return a row The test uses a trick in the mock server, where the mock server is requested to freeze after returning the first row. However, when the mock server adds the first row to the stream, it is not guaranteed to be readable for the client, which again causes the test to hang on the ResultSet#next() call. The gRPC libraries then execute keep-alive requests to keep the TCP connection alive while waiting for data from the mock server, which will never come. This caused the query to eventually fail with a RESOURCE_EXHAUSTED error. The tests work around this issue by just ignoring the case when the mock server fails to return the first row, as it is something that only very sporadically happens. --- .../CloseSpannerWithOpenResultSetTest.java | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/CloseSpannerWithOpenResultSetTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/CloseSpannerWithOpenResultSetTest.java index 67b14f60a4e..a489a269b22 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/CloseSpannerWithOpenResultSetTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/CloseSpannerWithOpenResultSetTest.java @@ -39,6 +39,8 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -59,6 +61,16 @@ Spanner createSpanner() { .getService(); } + @BeforeClass + public static void setWatchdogTimeout() { + System.setProperty("com.google.cloud.spanner.watchdogTimeoutSeconds", "1"); + } + + @AfterClass + public static void clearWatchdogTimeout() { + System.clearProperty("com.google.cloud.spanner.watchdogTimeoutSeconds"); + } + @After public void cleanup() { mockSpanner.unfreeze(); @@ -75,7 +87,13 @@ public void testBatchClient_closedSpannerWithOpenResultSet_streamsAreCancelled() client.batchReadOnlyTransaction(TimestampBound.strong()); ResultSet resultSet = transaction.executeQuery(SELECT_RANDOM_STATEMENT)) { mockSpanner.freezeAfterReturningNumRows(1); - assertTrue(resultSet.next()); + // This can sometimes fail, as the mock server may not always actually return the first row. + try { + assertTrue(resultSet.next()); + } catch (SpannerException exception) { + assertEquals(ErrorCode.DEADLINE_EXCEEDED, exception.getErrorCode()); + return; + } ((SpannerImpl) spanner).close(1, TimeUnit.MILLISECONDS); // This should return an error as the stream is cancelled. SpannerException exception = assertThrows(SpannerException.class, resultSet::next); @@ -93,7 +111,13 @@ public void testNormalDatabaseClient_closedSpannerWithOpenResultSet_sessionsAreD try (ReadOnlyTransaction transaction = client.readOnlyTransaction(TimestampBound.strong()); ResultSet resultSet = transaction.executeQuery(SELECT_RANDOM_STATEMENT)) { mockSpanner.freezeAfterReturningNumRows(1); - assertTrue(resultSet.next()); + // This can sometimes fail, as the mock server may not always actually return the first row. + try { + assertTrue(resultSet.next()); + } catch (SpannerException exception) { + assertEquals(ErrorCode.DEADLINE_EXCEEDED, exception.getErrorCode()); + return; + } List executeSqlRequests = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream() .filter(request -> request.getSql().equals(SELECT_RANDOM_STATEMENT.getSql()))