package rocks.inspectit.server.influx.dao; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.influxdb.InfluxDB; import org.influxdb.dto.Point; import org.influxdb.dto.Query; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.slf4j.Logger; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import rocks.inspectit.server.influx.InfluxAvailabilityChecker; import rocks.inspectit.server.influx.util.InfluxClientFactory; import rocks.inspectit.shared.all.externalservice.ExternalServiceStatus; import rocks.inspectit.shared.all.externalservice.ExternalServiceType; import rocks.inspectit.shared.all.testbase.TestBase; /** * Test the {@link InfluxDBDao}. * * @author Marius Oehler * */ public class InfluxDBDaoTest extends TestBase { @InjectMocks InfluxDBDao influxDao; @Mock InfluxClientFactory clientFactory; @Mock Logger log; @Mock ScheduledExecutorService executor; @Mock InfluxAvailabilityChecker availabilityChecker; InfluxDB influxDb; Future<?> future; @BeforeMethod public void setup() { influxDb = mock(InfluxDB.class); when(clientFactory.createClient()).thenReturn(influxDb); future = mock(Future.class); when(executor.submit(any(Runnable.class))).thenAnswer(new Answer<Future<?>>() { @Override public Future<?> answer(InvocationOnMock invocation) throws Throwable { Runnable runnable = (Runnable) invocation.getArguments()[0]; if (runnable != null) { runnable.run(); } return future; } }); } /** * Test the {@link InfluxDBDao#insert(org.influxdb.dto.Point)} method. */ public static class Insert extends InfluxDBDaoTest { @Mock Point dataPoint; @Test public void insertPoint() { influxDao.active = true; influxDao.propertiesUpdated(); influxDao.insert(dataPoint); assertThat(influxDao.isConnected(), is(true)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.CONNECTED)); verify(executor).submit(any(Runnable.class)); verify(influxDb).write(influxDao.database, influxDao.retentionPolicy, dataPoint); verify(influxDb).ping(); verify(influxDb).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(influxDb).describeDatabases(); verify(influxDb).createDatabase(influxDao.database); verify(availabilityChecker).deactivate(); verify(availabilityChecker).setInflux(influxDb); verify(availabilityChecker).activate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(executor, influxDb, availabilityChecker, clientFactory); verifyZeroInteractions(future, dataPoint); } @Test public void insertNull() { influxDao.active = true; influxDao.propertiesUpdated(); influxDao.insert(null); assertThat(influxDao.isConnected(), is(true)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.CONNECTED)); verify(executor).submit(any(Runnable.class)); verify(influxDb).ping(); verify(influxDb).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(influxDb).describeDatabases(); verify(influxDb).createDatabase(influxDao.database); verify(availabilityChecker).deactivate(); verify(availabilityChecker).setInflux(influxDb); verify(availabilityChecker).activate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(executor, influxDb, availabilityChecker, clientFactory); verifyZeroInteractions(future, dataPoint); } @Test public void notConnected() { influxDao.active = true; influxDao.insert(dataPoint); assertThat(influxDao.isConnected(), is(false)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.DISCONNECTED)); verifyZeroInteractions(future, dataPoint, executor, availabilityChecker, clientFactory); } } /** * Test the {@link InfluxDBDao#query(String)} method. */ public static class QueryTest extends InfluxDBDaoTest { @Test public void executeQuery() { influxDao.active = true; influxDao.propertiesUpdated(); influxDao.query("myQuery"); assertThat(influxDao.isConnected(), is(true)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.CONNECTED)); ArgumentCaptor<Query> queryCaptor = ArgumentCaptor.forClass(Query.class); verify(influxDb).query(queryCaptor.capture()); assertThat(queryCaptor.getValue().getCommand(), equalTo("myQuery")); verify(influxDb).ping(); verify(influxDb).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(influxDb).describeDatabases(); verify(influxDb).createDatabase(influxDao.database); verify(executor).submit(any(Runnable.class)); verify(availabilityChecker).deactivate(); verify(availabilityChecker).setInflux(influxDb); verify(availabilityChecker).activate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(clientFactory, availabilityChecker, executor, influxDb); verifyZeroInteractions(future); } @Test public void executeNullQuery() { influxDao.active = true; influxDao.propertiesUpdated(); influxDao.query(null); assertThat(influxDao.isConnected(), is(true)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.CONNECTED)); verify(influxDb).ping(); verify(influxDb).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(influxDb).describeDatabases(); verify(influxDb).createDatabase(influxDao.database); verify(executor).submit(any(Runnable.class)); verify(availabilityChecker).deactivate(); verify(availabilityChecker).setInflux(influxDb); verify(availabilityChecker).activate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(clientFactory, availabilityChecker, executor, influxDb); verifyZeroInteractions(future); } @Test public void notConnected() { influxDao.active = true; influxDao.query("myQuery"); assertThat(influxDao.isConnected(), is(false)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.DISCONNECTED)); verifyZeroInteractions(future, executor, availabilityChecker, clientFactory); } } /** * Test the {@link InfluxDBDao#propertiesUpdated()} method. * */ public static class PropertiesUpdated extends InfluxDBDaoTest { Future<?> future; @BeforeMethod public void beforeMethod() { future = mock(Future.class); when(executor.submit(any(Runnable.class))).thenAnswer(new Answer<Future<?>>() { @Override public Future<?> answer(InvocationOnMock invocation) throws Throwable { Runnable runnable = (Runnable) invocation.getArguments()[0]; runnable.run(); return future; } }); } @Test public void notActive() { influxDao.propertiesUpdated(); verify(availabilityChecker).deactivate(); verifyNoMoreInteractions(availabilityChecker); verifyZeroInteractions(future, executor, clientFactory); } @Test public void enableInflux() { influxDao.active = true; influxDao.propertiesUpdated(); assertThat(influxDao.isConnected(), is(true)); assertThat(influxDao.getServiceType(), is(ExternalServiceType.INFLUXDB)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.CONNECTED)); verify(executor, times(1)).submit(any(Runnable.class)); verify(influxDb).ping(); verify(influxDb).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(influxDb).describeDatabases(); verify(influxDb).createDatabase(influxDao.database); verify(availabilityChecker).deactivate(); verify(availabilityChecker).setInflux(influxDb); verify(availabilityChecker).activate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(influxDb, availabilityChecker, executor, clientFactory); verifyZeroInteractions(future); } @Test @SuppressWarnings("unchecked") public void enableInfluxButNotAvailable() { influxDao.active = true; when(influxDb.ping()).thenThrow(Exception.class); influxDao.propertiesUpdated(); assertThat(influxDao.isConnected(), is(false)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.DISCONNECTED)); verify(executor, times(1)).submit(any(Runnable.class)); verify(influxDb).ping(); verify(influxDb).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(availabilityChecker).deactivate(); verify(availabilityChecker).setInflux(influxDb); verify(availabilityChecker).activate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(influxDb, availabilityChecker, executor, clientFactory); verifyZeroInteractions(future); } @Test public void enableInfluxDatabaseExists() { influxDao.active = true; when(influxDb.describeDatabases()).thenReturn(Arrays.asList(influxDao.database)); influxDao.propertiesUpdated(); assertThat(influxDao.isConnected(), is(true)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.CONNECTED)); verify(executor, times(1)).submit(any(Runnable.class)); verify(influxDb).ping(); verify(influxDb).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(influxDb).describeDatabases(); verify(availabilityChecker).deactivate(); verify(availabilityChecker).setInflux(influxDb); verify(availabilityChecker).activate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(influxDb, availabilityChecker, executor, clientFactory); verifyZeroInteractions(future); } @Test public void disableInfluxConnectionOngoing() { when(future.isDone()).thenReturn(false); when(influxDb.isBatchEnabled()).thenReturn(false, true); influxDao.active = true; influxDao.propertiesUpdated(); influxDao.active = false; influxDao.propertiesUpdated(); assertThat(influxDao.isConnected(), is(false)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.DISABLED)); verify(future).cancel(true); verify(future).isDone(); verify(executor, times(1)).submit(any(Runnable.class)); verify(influxDb).ping(); verify(influxDb, times(2)).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(influxDb).disableBatch(); verify(influxDb).describeDatabases(); verify(influxDb).createDatabase(influxDao.database); verify(availabilityChecker, times(2)).deactivate(); verify(availabilityChecker).setInflux(influxDb); verify(availabilityChecker).activate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(future, influxDb, availabilityChecker, executor, clientFactory); } @Test public void disableInflux() { when(future.isDone()).thenReturn(true); when(influxDb.isBatchEnabled()).thenReturn(false, true); influxDao.active = true; influxDao.propertiesUpdated(); influxDao.active = false; influxDao.propertiesUpdated(); assertThat(influxDao.isConnected(), is(false)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.DISABLED)); verify(future).isDone(); verify(executor, times(1)).submit(any(Runnable.class)); verify(influxDb).ping(); verify(influxDb, times(2)).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(influxDb).disableBatch(); verify(influxDb).describeDatabases(); verify(influxDb).createDatabase(influxDao.database); verify(availabilityChecker, times(2)).deactivate(); verify(availabilityChecker).setInflux(influxDb); verify(availabilityChecker).activate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(future, influxDb, availabilityChecker, executor, clientFactory); } @Test public void clientFactoryReturnsNull() { influxDao.active = true; when(clientFactory.createClient()).thenReturn(null); influxDao.propertiesUpdated(); assertThat(influxDao.isConnected(), is(false)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.DISCONNECTED)); verify(executor, times(1)).submit(any(Runnable.class)); verify(availabilityChecker).deactivate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(influxDb, availabilityChecker, executor, clientFactory); verifyZeroInteractions(future); } @Test @SuppressWarnings("unchecked") public void clientFactoryThrowsException() { influxDao.active = true; when(clientFactory.createClient()).thenThrow(Exception.class); influxDao.propertiesUpdated(); assertThat(influxDao.isConnected(), is(false)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.DISCONNECTED)); verify(executor, times(1)).submit(any(Runnable.class)); verify(availabilityChecker).deactivate(); verify(clientFactory).createClient(); verifyNoMoreInteractions(influxDb, availabilityChecker, executor, clientFactory); verifyZeroInteractions(future); } } /** * Tests the {@link InfluxDBDao#onDisconnection()} method. */ public static class OnDisconnection extends InfluxDBDaoTest { @Mock InfluxDB influxDb; @Test public void disconnected() { influxDao.active = true; when(influxDb.isBatchEnabled()).thenReturn(true); influxDao.onDisconnection(); assertThat(influxDao.isConnected(), is(false)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.DISCONNECTED)); verify(influxDb).isBatchEnabled(); verify(influxDb).disableBatch(); verifyNoMoreInteractions(influxDb); verifyZeroInteractions(future, executor, availabilityChecker, clientFactory); } @Test public void disconnectedBatchDisabled() { influxDao.active = true; when(influxDb.isBatchEnabled()).thenReturn(false); influxDao.onDisconnection(); verify(influxDb).isBatchEnabled(); verifyNoMoreInteractions(influxDb); verifyZeroInteractions(future, executor, availabilityChecker, clientFactory); } } /** * Tests the {@link InfluxDBDao#onDisconnection()} method. */ public static class OnReconnection extends InfluxDBDaoTest { @Mock InfluxDB influxDb; @Test public void reconnected() { influxDao.active = true; when(influxDb.isBatchEnabled()).thenReturn(false); influxDao.onReconnection(); assertThat(influxDao.isConnected(), is(true)); assertThat(influxDao.getServiceStatus(), is(ExternalServiceStatus.CONNECTED)); verify(influxDb).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(influxDb).describeDatabases(); verify(influxDb).createDatabase(influxDao.database); verifyNoMoreInteractions(influxDb); verifyZeroInteractions(future, executor, availabilityChecker, clientFactory); } @Test public void reconnectedBatchEnabled() { influxDao.active = true; when(influxDb.isBatchEnabled()).thenReturn(true); influxDao.onReconnection(); verify(influxDb).isBatchEnabled(); verify(influxDb).describeDatabases(); verify(influxDb).createDatabase(influxDao.database); verifyNoMoreInteractions(influxDb); verifyZeroInteractions(future, executor, availabilityChecker, clientFactory); } @Test public void reconnectedDatabaseExists() { influxDao.active = true; when(influxDb.isBatchEnabled()).thenReturn(false); when(influxDb.describeDatabases()).thenReturn(Arrays.asList(influxDao.database)); influxDao.onReconnection(); verify(influxDb).isBatchEnabled(); verify(influxDb).enableBatch(InfluxDBDao.BATCH_BUFFER_SIZE, InfluxDBDao.BATCH_FLUSH_TIMER, TimeUnit.SECONDS); verify(influxDb).describeDatabases(); verifyNoMoreInteractions(influxDb); verifyZeroInteractions(future, executor, availabilityChecker, clientFactory); } } }