/* * Copyright (c) 2016 Frinx s.r.o. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.tsdr.persistence.elasticsearch; import static com.google.common.truth.Truth.assertThat; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.util.concurrent.Service; import com.google.gson.Gson; import io.searchbox.client.JestClient; import io.searchbox.client.JestResultHandler; import io.searchbox.core.Bulk; import io.searchbox.core.BulkResult; import io.searchbox.core.DeleteByQuery; import io.searchbox.core.Search; import io.searchbox.core.SearchResult; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.opendaylight.yang.gen.v1.opendaylight.tsdr.binary.data.rev160325.storetsdrbinaryrecord.input.TSDRBinaryRecord; import org.opendaylight.yang.gen.v1.opendaylight.tsdr.log.data.rev160325.storetsdrlogrecord.input.TSDRLogRecord; import org.opendaylight.yang.gen.v1.opendaylight.tsdr.metric.data.rev160325.storetsdrmetricrecord.input.TSDRMetricRecord; import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.DataCategory; import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.TSDRRecord; /** * Test all methods of {@link ElasticsearchStore} * * @author Lukas Beles(lbeles@frinx.io) */ public class ElasticsearchStoreTest { private static final BulkResult EMPTY_BULK_RESULT = new BulkResult(new Gson()); private static final SearchResult EMPTY_SEARCH_RESULT = new SearchResult(new Gson()); private static final Map<String, String> PROPERTIES = ImmutableMap.of( "startTimeout", "1", "stopTimeout", "1", "syncInterval", "1"); private static final JestClient CLIENT = Mockito.mock(JestClient.class); private static ElasticsearchStore store; /** * Test setUp method, common scenario. * * @throws Exception */ @BeforeClass public static void setUp() throws Exception { store = ElasticsearchStore.create(PROPERTIES, CLIENT); store.startAsync().awaitRunning(1, TimeUnit.SECONDS); } /** * Test tearDown method, common scenario. * * @throws Exception */ @AfterClass public static void tearDown() throws Exception { store.stopAsync().awaitTerminated(1, TimeUnit.SECONDS); } /** * Test store method, where value is {@link TSDRMetricRecord}. Check whether batch contains the value. * * @throws Exception */ @Test public void storeMetricRecord() throws Exception { Mockito.doReturn(EMPTY_BULK_RESULT).when(CLIENT).execute(Mockito.any(Bulk.class)); TSDRMetricRecord record = TsdrRecordFactory.createMetricRecord(); store.store(record); assertThat(store.getBatch()).contains(record); } /** * Test store method, where value is {@link TSDRLogRecord}. Check whether batch contains the value. * * @throws Exception */ @Test public void storeLogRecord() throws Exception { Mockito.doReturn(EMPTY_BULK_RESULT).when(CLIENT).execute(Mockito.any(Bulk.class)); TSDRLogRecord record = TsdrRecordFactory.createLogRecord(); store.store(record); assertThat(store.getBatch()).contains(record); } /** * Test store method, where value is {@link TSDRBinaryRecord}. Check whether batch contains the value. * * @throws Exception */ @Test public void storeBinaryRecord() throws Exception { Mockito.doReturn(EMPTY_BULK_RESULT).when(CLIENT).execute(Mockito.any(Bulk.class)); TSDRBinaryRecord record = TsdrRecordFactory.createBinaryRecord(); store.store(record); assertThat(store.getBatch()).contains(record); } /** * Test store method, where value is null * * @throws Exception */ @Test(expected = NullPointerException.class) public void storeNull() throws Exception { store.store(null); } /** * Test storeAll method. The collection contains one {@link TSDRMetricRecord} and one {@link TSDRLogRecord}. * * @throws Exception */ @Test public void storeAll() throws Exception { ArrayList<TSDRRecord> records = Lists.newArrayList( TsdrRecordFactory.createMetricRecord(), TsdrRecordFactory.createLogRecord()); store.storeAll(records); assertThat(store.getBatch()).isNotEmpty(); assertThat(store.getBatch()).containsAllIn(records); } /** * Test storeAll method, where value is null. * * @throws Exception */ @Test(expected = NullPointerException.class) public void storeAllNullRecord() throws Exception { store.storeAll(null); } /** * Test storeAll method. Collection contains null record. * * @throws Exception */ @Test(expected = NullPointerException.class) public void storeAllRecordListHasNullRecord() throws Exception { List records = Collections.singletonList(null); store.storeAll(records); } /** * Test search method. Test whether result is empty. It is expected. And verify whether method execute of {@link JestClient} was called at least one. * * @throws Exception */ @Test public void search() throws Exception { Mockito.doReturn(EMPTY_SEARCH_RESULT).when(CLIENT).execute(Mockito.any(Search.class)); List<TSDRRecord> result = store.search( ElasticsearchStore.RecordType.METRIC, DataCategory.EXTERNAL.name(), 1L, 0L, 1000); assertThat(result).isEmpty(); result = store.search( ElasticsearchStore.RecordType.METRIC, DataCategory.EXTERNAL.name(), 0L, 0L, 1000); assertThat(result).isEqualTo(Collections.emptyList()); Mockito.verify(CLIENT, Mockito.atLeastOnce()).execute(Mockito.any(Bulk.class)); } /** * Test appendCondition method. Test all possible ways of the condition * * @throws Exception */ @Test public void appendCondition() throws Exception { StringBuffer buffer = new StringBuffer(); store.appendCondition(buffer, "empty1", null); assertThat(buffer.toString()).isEqualTo(""); store.appendCondition(buffer, "empty2", null); assertThat(buffer.toString()).isEqualTo(""); store.appendCondition(buffer, "field1", "value1"); assertThat(buffer.toString()).isEqualTo("field1:\\\"value1\\\""); store.appendCondition(buffer, "field2", "value2"); assertThat(buffer.toString()).isEqualTo("field1:\\\"value1\\\" AND field2:\\\"value2\\\""); } /** * Test of building query String for Binary request * * @throws Exception */ @Test public void buildQueryStringOfBinary() throws Exception { String result = store.buildQueryString(ElasticsearchStore.RecordType.BINARY, "FLOWSTATS"); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY + ":\\\"FLOWSTATS\\\"")).isTrue(); result = store.buildQueryString(ElasticsearchStore.RecordType.BINARY, "[NID=][DC=FLOWSTATS][RK=][MN=]"); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY + ":\\\"FLOWSTATS\\\"")).isTrue(); result = store.buildQueryString(ElasticsearchStore.RecordType.BINARY, "[NID=][DC=FLOWSTATS][RK=][MN=PacketCount]"); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY + ":\\\"FLOWSTATS\\\"")).isTrue(); assertThat(result.contains("PacketCount")).isFalse(); } /** * Test of building query String for Log request * * @throws Exception */ @Test public void buildQueryStringOfLog() throws Exception { String result = store.buildQueryString(ElasticsearchStore.RecordType.LOG, "FLOWSTATS"); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY + ":\\\"FLOWSTATS\\\"")).isTrue(); result = store.buildQueryString(ElasticsearchStore.RecordType.LOG, "[NID=][DC=FLOWSTATS][RK=][MN=]"); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY + ":\\\"FLOWSTATS\\\"")).isTrue(); result = store.buildQueryString(ElasticsearchStore.RecordType.LOG, "[NID=][DC=FLOWSTATS][RK=][MN=PacketCount]"); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY + ":\\\"FLOWSTATS\\\"")).isTrue(); assertThat(result.contains("PacketCount")).isFalse(); result = store.buildQueryString(ElasticsearchStore.RecordType.LOG, "[NID=][DC=FLOWSTATS][RK=][RA=key:value]"); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY + ":\\\"FLOWSTATS\\\"")).isTrue(); assertThat(result.contains(TsdrRecordPayload.ELK_RA_KEY_NAME + ":\\\"key\\\"")).isTrue(); assertThat(result.contains(TsdrRecordPayload.ELK_RA_KEY_VALUE + ":\\\"value\\\"")).isTrue(); } /** * Test of building query String for Metric request * * @throws Exception */ @Test public void buildQueryStringOfMetric() throws Exception { String result = store.buildQueryString(ElasticsearchStore.RecordType.METRIC, "FLOWSTATS"); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY)).isTrue(); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY + ":\\\"FLOWSTATS\\\"")).isTrue(); result = store.buildQueryString(ElasticsearchStore.RecordType.METRIC, "[NID=][DC=FLOWSTATS][RK=][MN=]"); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY + ":\\\"FLOWSTATS\\\"")).isTrue(); result = store.buildQueryString(ElasticsearchStore.RecordType.METRIC, "[NID=node][DC=FLOWSTATS][MN=PacketCount][RK=key:value]"); assertThat(result.contains(TsdrRecordPayload.ELK_DATA_CATEGORY + ":\\\"FLOWSTATS\\\"")).isTrue(); assertThat(result.contains(TsdrRecordPayload.ELK_METRIC_NAME + ":\\\"PacketCount\\\"")).isTrue(); assertThat(result.contains(TsdrRecordPayload.ELK_NODE_ID + ":\\\"node\\\"")).isTrue(); assertThat(result.contains(TsdrRecordPayload.ELK_RK_KEY_NAME + ":\\\"key\\\"")).isTrue(); assertThat(result.contains(TsdrRecordPayload.ELK_RK_KEY_VALUE + ":\\\"value\\\"")).isTrue(); } /** * Test delete method. Verify whether method executeAsync of {@link JestClient} was called at least one. * * @throws Exception */ @Test @SuppressWarnings("unchecked") public void delete() throws Exception { store.delete(DataCategory.EXTERNAL, 0L); Mockito.verify(CLIENT, Mockito.atLeastOnce()).executeAsync( Mockito.any(DeleteByQuery.class), Mockito.any(JestResultHandler.class)); } /** * Test start and then stop service * * @throws Exception */ @Test public void createAndStartAndShutDown() throws Exception { ElasticsearchStore store = ElasticsearchStore.create(PROPERTIES, CLIENT); assertThat(store.state()).isEqualTo(Service.State.NEW); store.startAsync().awaitRunning(2, TimeUnit.SECONDS); assertThat(store.state()).isEqualTo(Service.State.RUNNING); store.stopAsync().awaitTerminated(2, TimeUnit.SECONDS); assertThat(store.state()).isEqualTo(Service.State.TERMINATED); } /** * Test store record and sync method. Verify whether method execute of {@link JestClient} was called at least one. * * @throws Exception */ @Test public void runOneIteration() throws Exception { TSDRMetricRecord record = TsdrRecordFactory.createMetricRecord(); Mockito.doReturn(null).when(CLIENT).execute(Mockito.any(Bulk.class)); store.store(record); store.runOneIteration(); Mockito.verify(CLIENT, Mockito.atLeastOnce()).execute(Mockito.any(Bulk.class)); Mockito.doThrow(IOException.class).when(CLIENT).execute(Mockito.any(Bulk.class)); store.store(record); store.runOneIteration(); Mockito.verify(CLIENT, Mockito.atLeastOnce()).execute(Mockito.any(Bulk.class)); } /** * Test whether scheduler is implemented * * @throws Exception */ @Test public void scheduler() throws Exception { assertThat(store.scheduler()).isNotNull(); } /** * Test service with wrong state * * @throws Exception */ @Test(expected = IllegalStateException.class) public void unknownClientConfiguration() throws Exception { ElasticsearchStore store = ElasticsearchStore.create(PROPERTIES, null); store.startAsync().awaitRunning(); } /** * Test method resolve of {@link org.opendaylight.tsdr.persistence.elasticsearch.ElasticsearchStore.RecordType}, when argument is null * * @throws Exception */ @Test(expected = IllegalArgumentException.class) public void resolveUnknownRecordType() throws Exception { ElasticsearchStore.RecordType.resolve(null); } /** * Test starup service * * @throws Exception */ @Test public void startup() throws Exception { ElasticsearchStore store = Mockito.spy(ElasticsearchStore.class); Mockito.doReturn(null).when(store).createJestClient(); store.startUp(); } }