From fe434ff7068b4b618e70379c224e1c5ab88f6ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 21 Apr 2020 14:25:00 +0200 Subject: [PATCH] fix: wait for initialization to finish before test (#161) The flaky test failure was caused by a lower number of base threads being calculated before the test started, and not by an unexpected drop in the number of threads after the test. This is now mitigated by waiting for the initialization to finish before starting the test. Fixes #146 --- .../spanner/it/ITSpannerOptionsTest.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITSpannerOptionsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITSpannerOptionsTest.java index 41afc08958..34e6c43944 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITSpannerOptionsTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITSpannerOptionsTest.java @@ -33,8 +33,8 @@ import java.util.List; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; -import org.junit.After; -import org.junit.Before; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -47,13 +47,13 @@ public class ITSpannerOptionsTest { @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); private static Database db; - @Before - public void setUp() throws Exception { + @BeforeClass + public static void setUp() throws Exception { db = env.getTestHelper().createTestDatabase(); } - @After - public void tearDown() throws Exception { + @AfterClass + public static void tearDown() throws Exception { db.drop(); } @@ -65,9 +65,9 @@ public void tearDown() throws Exception { @Test public void testCloseAllThreadsWhenClosingSpanner() throws InterruptedException { - // The IT environment has already started some worker threads. int baseThreadCount = getNumberOfThreadsWithName(SPANNER_THREAD_NAME); for (int i = 0; i < NUMBER_OF_TEST_RUNS; i++) { + waitForStartup(); assertThat(getNumberOfThreadsWithName(SPANNER_THREAD_NAME)).isAtMost(baseThreadCount); // Create Spanner instance. // We make a copy of the options instance, as SpannerOptions caches any service object @@ -136,6 +136,7 @@ public void testCloseAllThreadsWhenClosingSpanner() throws InterruptedException @Test public void testMultipleSpannersFromSameSpannerOptions() throws InterruptedException { + waitForStartup(); int baseThreadCount = getNumberOfThreadsWithName(SPANNER_THREAD_NAME); SpannerOptions options = env.getTestHelper().getOptions().toBuilder().build(); try (Spanner spanner1 = options.getService()) { @@ -167,6 +168,17 @@ public void testMultipleSpannersFromSameSpannerOptions() throws InterruptedExcep assertThat(getNumberOfThreadsWithName(SPANNER_THREAD_NAME)).isAtMost(baseThreadCount); } + private void waitForStartup() throws InterruptedException { + // Wait until the IT environment has already started all base worker threads. + int threadCount; + Stopwatch watch = Stopwatch.createStarted(); + do { + threadCount = getNumberOfThreadsWithName(SPANNER_THREAD_NAME); + Thread.sleep(100L); + } while (getNumberOfThreadsWithName(SPANNER_THREAD_NAME) > threadCount + && watch.elapsed(TimeUnit.SECONDS) < 5); + } + private int getNumberOfThreadsWithName(String serviceName) { Pattern pattern = Pattern.compile(String.format(THREAD_PATTERN, serviceName)); ThreadGroup group = Thread.currentThread().getThreadGroup();