Use Guice injector for BlockedThreadsCheck in tests The creation of the BlockedThreadsCheck was never tested and could have led to severe issues left untested and unnoticed like the @Singleton annotation on the BlockedThreadsCheck making the whole check value stateful. Change-Id: Ibd0ebf86c4524e3f8fb232bb4c97d799c0d0ae80
diff --git a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/BlockedThreadsCheckTest.java b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/BlockedThreadsCheckTest.java index d50d12a..641a060 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/BlockedThreadsCheckTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/BlockedThreadsCheckTest.java
@@ -20,13 +20,11 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import com.google.common.util.concurrent.ListeningExecutorService; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; -import com.google.inject.util.Providers; import com.googlesource.gerrit.plugins.healthcheck.check.BlockedThreadsCheck; -import com.googlesource.gerrit.plugins.healthcheck.check.BlockedThreadsConfigurator; +import com.googlesource.gerrit.plugins.healthcheck.check.BlockedThreadsCheck.ThreadBeanProvider; import com.googlesource.gerrit.plugins.healthcheck.check.HealthCheck.Result; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; @@ -40,18 +38,28 @@ @RunWith(MockitoJUnitRunner.class) public class BlockedThreadsCheckTest { + private static final String HEALTHCHECK_CONFIG_BODY_THRESHOLD = + "[healthcheck \"" + BLOCKEDTHREADS + "\"]\n" + " threshold = "; + private static final HealthCheckConfig CONFIG_THRESHOLD_25 = + new HealthCheckConfig(HEALTHCHECK_CONFIG_BODY_THRESHOLD + "25"); + private static final HealthCheckConfig CONFIG_THRESHOLD_33 = + new HealthCheckConfig(HEALTHCHECK_CONFIG_BODY_THRESHOLD + "33"); + @Mock BlockedThreadsCheck.ThreadBeanProvider threadBeanProviderMock; @Mock ThreadMXBean beanMock; + private Injector testInjector; + @Before public void setUp() { when(threadBeanProviderMock.get()).thenReturn(beanMock); + testInjector = createTestInjector(HealthCheckConfig.DEFAULT_CONFIG); } @Test public void shouldPassCheckWhenNoThreadsAreReturned() { - BlockedThreadsCheck objectUnderTest = createCheck(HealthCheckConfig.DEFAULT_CONFIG); + BlockedThreadsCheck objectUnderTest = createCheck(); when(beanMock.getThreadInfo(null, 0)).thenReturn(new ThreadInfo[0]); assertThat(objectUnderTest.run().result).isEqualTo(Result.PASSED); } @@ -88,18 +96,18 @@ public void shouldPassCheckWhenBlockedThreadsAreLessThenThreshold() { int running = 3; int blocked = 1; - HealthCheckConfig config = - new HealthCheckConfig("[healthcheck \"" + BLOCKEDTHREADS + "\"]\n" + " threshold = 25"); - mockThreadsAndCheckResult(running, blocked, Result.PASSED, config); + testInjector = createTestInjector(CONFIG_THRESHOLD_25); + + mockThreadsAndCheckResult(running, blocked, Result.PASSED); } @Test public void shouldFailCheckWhenBlockedThreadsAreAboveTheThreshold() { int running = 1; int blocked = 1; - HealthCheckConfig config = - new HealthCheckConfig("[healthcheck \"" + BLOCKEDTHREADS + "\"]\n" + " threshold = 33"); - mockThreadsAndCheckResult(running, blocked, Result.FAILED, config); + testInjector = createTestInjector(CONFIG_THRESHOLD_33); + + mockThreadsAndCheckResult(running, blocked, Result.FAILED); } @Test @@ -107,10 +115,9 @@ int running = 3; int blocked = 1; String prefix = "blocked-threads-prefix"; - HealthCheckConfig config = - new HealthCheckConfig( - "[healthcheck \"" + BLOCKEDTHREADS + "\"]\n" + " threshold = " + prefix + " = 25"); - mockThreadsAndCheckResult(running, blocked, Result.PASSED, prefix, config); + testInjector = createTestInjector(CONFIG_THRESHOLD_25); + + mockThreadsAndCheckResult(running, blocked, Result.PASSED, prefix); } @Test @@ -118,10 +125,9 @@ int running = 1; int blocked = 1; String prefix = "blocked-threads-prefix"; - HealthCheckConfig config = - new HealthCheckConfig( - "[healthcheck \"" + BLOCKEDTHREADS + "\"]\n" + " threshold = " + prefix + " = 33"); - mockThreadsAndCheckResult(running, blocked, Result.FAILED, prefix, config); + testInjector = createTestInjector(CONFIG_THRESHOLD_33); + + mockThreadsAndCheckResult(running, blocked, Result.FAILED, prefix); } @Test @@ -141,31 +147,27 @@ + "\nthreshold = " + notBlockedPrefix + "=33"); + testInjector = createTestInjector(config); + List<ThreadInfo> infos = new ArrayList<>(running + blocked + running); infos.addAll(nCopies(running, mockInfo(Thread.State.RUNNABLE, blockedPrefix))); infos.addAll(nCopies(blocked, mockInfo(Thread.State.BLOCKED, blockedPrefix))); infos.addAll(nCopies(running, mockInfo(Thread.State.RUNNABLE, notBlockedPrefix))); when(beanMock.getThreadInfo(null, 0)).thenReturn(infos.toArray(new ThreadInfo[infos.size()])); - checkResult(Result.FAILED, config); + checkResult(Result.FAILED); } private void mockThreadsAndCheckResult(int running, int blocked, Result expected) { - mockThreadsAndCheckResult(running, blocked, expected, HealthCheckConfig.DEFAULT_CONFIG); + mockThreadsAndCheckResult(running, blocked, expected, "some-prefix"); } - private void mockThreadsAndCheckResult( - int running, int blocked, Result expected, HealthCheckConfig config) { - mockThreadsAndCheckResult(running, blocked, expected, "some-prefix", config); - } - - private void mockThreadsAndCheckResult( - int running, int blocked, Result expected, String prefix, HealthCheckConfig config) { + private void mockThreadsAndCheckResult(int running, int blocked, Result expected, String prefix) { mockThreads(running, blocked, prefix); - checkResult(expected, config); + checkResult(expected); } - private void checkResult(Result expected, HealthCheckConfig config) { - BlockedThreadsCheck objectUnderTest = createCheck(config); + private void checkResult(Result expected) { + BlockedThreadsCheck objectUnderTest = createCheck(); assertThat(objectUnderTest.run().result).isEqualTo(expected); } @@ -183,8 +185,11 @@ return infoMock; } - private BlockedThreadsCheck createCheck(HealthCheckConfig config) { - DummyHealthCheckMetricsFactory checkMetricsFactory = new DummyHealthCheckMetricsFactory(); + private BlockedThreadsCheck createCheck() { + return testInjector.getInstance(BlockedThreadsCheck.class); + } + + private Injector createTestInjector(HealthCheckConfig config) { Injector injector = Guice.createInjector( new HealthCheckModule(), @@ -192,15 +197,11 @@ @Override protected void configure() { bind(HealthCheckConfig.class).toInstance(config); - bind(HealthCheckMetrics.Factory.class).toInstance(checkMetricsFactory); + bind(HealthCheckMetrics.Factory.class).to(DummyHealthCheckMetricsFactory.class); + bind(ThreadBeanProvider.class).toInstance(threadBeanProviderMock); } }, BlockedThreadsCheck.SUB_CHECKS); - return new BlockedThreadsCheck( - injector.getInstance(ListeningExecutorService.class), - config, - checkMetricsFactory, - threadBeanProviderMock, - Providers.of(injector.getInstance(BlockedThreadsConfigurator.class))); + return injector; } }