/** * This file is part of Graylog. * * Graylog is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Graylog is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Graylog. If not, see <http://www.gnu.org/licenses/>. */ package org.graylog2.indexer.counts; import com.google.common.collect.ImmutableMap; import org.elasticsearch.action.index.IndexResponse; import org.graylog2.AbstractESTest; import org.graylog2.indexer.ElasticsearchException; import org.graylog2.indexer.IndexNotFoundException; import org.graylog2.indexer.IndexSet; import org.graylog2.indexer.IndexSetRegistry; import org.graylog2.indexer.indexset.IndexSetConfig; import org.graylog2.indexer.retention.strategies.DeletionRetentionStrategy; import org.graylog2.indexer.retention.strategies.DeletionRetentionStrategyConfig; import org.graylog2.indexer.rotation.strategies.MessageCountRotationStrategy; import org.graylog2.indexer.rotation.strategies.MessageCountRotationStrategyConfig; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.Map; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class CountsTest extends AbstractESTest { private static final String INDEX_NAME_1 = "index_set_1_counts_test_0"; private static final String INDEX_NAME_2 = "index_set_2_counts_test_0"; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Rule public final ExpectedException expectedException = ExpectedException.none(); @Mock private IndexSetRegistry indexSetRegistry; @Mock private IndexSet indexSet1; @Mock private IndexSet indexSet2; private Counts counts; private IndexSetConfig indexSetConfig1; private IndexSetConfig indexSetConfig2; @Before public void setUp() throws Exception { super.setUp(); final Map<String, Object> settings = ImmutableMap.of( "number_of_shards", 1, "index.number_of_replicas", 0); createIndex(INDEX_NAME_1); createIndex(INDEX_NAME_2); waitForGreenStatus(INDEX_NAME_1, INDEX_NAME_2); counts = new Counts(jestClient(), indexSetRegistry); indexSetConfig1 = IndexSetConfig.builder() .id("id-1") .title("title-1") .indexPrefix("index_set_1_counts_test") .shards(1) .replicas(0) .rotationStrategyClass(MessageCountRotationStrategy.class.getCanonicalName()) .rotationStrategy(MessageCountRotationStrategyConfig.createDefault()) .retentionStrategyClass(DeletionRetentionStrategy.class.getCanonicalName()) .retentionStrategy(DeletionRetentionStrategyConfig.createDefault()) .creationDate(ZonedDateTime.of(2016, 10, 12, 0, 0, 0, 0, ZoneOffset.UTC)) .indexAnalyzer("standard") .indexTemplateName("template-1") .indexOptimizationMaxNumSegments(1) .indexOptimizationDisabled(false) .build(); indexSetConfig2 = IndexSetConfig.builder() .id("id-2") .title("title-2") .indexPrefix("index_set_2_counts_test") .shards(1) .replicas(0) .rotationStrategyClass(MessageCountRotationStrategy.class.getCanonicalName()) .rotationStrategy(MessageCountRotationStrategyConfig.createDefault()) .retentionStrategyClass(DeletionRetentionStrategy.class.getCanonicalName()) .retentionStrategy(DeletionRetentionStrategyConfig.createDefault()) .creationDate(ZonedDateTime.of(2016, 10, 13, 0, 0, 0, 0, ZoneOffset.UTC)) .indexAnalyzer("standard") .indexTemplateName("template-2") .indexOptimizationMaxNumSegments(1) .indexOptimizationDisabled(false) .build(); when(indexSetRegistry.getManagedIndices()).thenReturn(new String[]{INDEX_NAME_1, INDEX_NAME_2}); when(indexSetRegistry.get(indexSetConfig1.id())).thenReturn(Optional.of(indexSet1)); when(indexSetRegistry.get(indexSetConfig2.id())).thenReturn(Optional.of(indexSet2)); when(indexSet1.getManagedIndices()).thenReturn(new String[]{INDEX_NAME_1}); when(indexSet2.getManagedIndices()).thenReturn(new String[]{INDEX_NAME_2}); } @After public void tearDown() throws Exception { deleteIndex(INDEX_NAME_1, INDEX_NAME_2); } @Test public void totalReturnsZeroWithEmptyIndex() throws Exception { assertThat(counts.total()).isEqualTo(0L); assertThat(counts.total(indexSet1)).isEqualTo(0L); assertThat(counts.total(indexSet2)).isEqualTo(0L); } @Test public void totalReturnsZeroWithNoIndices() throws Exception { for (int i = 0; i < 10; i++) { final IndexResponse indexResponse = client().prepareIndex() .setIndex(INDEX_NAME_1) .setRefresh(true) .setType("test") .setSource("foo", "bar", "counter", i) .execute().get(); assumeTrue(indexResponse.isCreated()); } // Simulate no indices for the second index set. when(indexSet2.getManagedIndices()).thenReturn(new String[0]); assertThat(counts.total(indexSet1)).isEqualTo(10L); assertThat(counts.total(indexSet2)).isEqualTo(0L); // Simulate no indices for all index sets. when(indexSetRegistry.getManagedIndices()).thenReturn(new String[0]); assertThat(counts.total()).isEqualTo(0L); } @Test public void totalReturnsNumberOfMessages() throws Exception { final int count1 = 10; final int count2 = 5; for (int i = 0; i < count1; i++) { final IndexResponse indexResponse = client().prepareIndex() .setIndex(INDEX_NAME_1) .setRefresh(true) .setType("test") .setSource("foo", "bar", "counter", i) .execute().get(); assumeTrue(indexResponse.isCreated()); } for (int i = 0; i < count2; i++) { final IndexResponse indexResponse = client().prepareIndex() .setIndex(INDEX_NAME_2) .setRefresh(true) .setType("test") .setSource("foo", "bar", "counter", i) .execute().get(); assumeTrue(indexResponse.isCreated()); } assertThat(counts.total()).isEqualTo(count1 + count2); assertThat(counts.total(indexSet1)).isEqualTo(count1); assertThat(counts.total(indexSet2)).isEqualTo(count2); } @Test public void totalThrowsElasticsearchExceptionIfIndexDoesNotExist() throws Exception { final IndexSet indexSet = mock(IndexSet.class); when(indexSet.getManagedIndices()).thenReturn(new String[]{"does_not_exist"}); try { assertThat(counts.total(indexSet)).isEqualTo(-1L); } catch (IndexNotFoundException e) { final String expectedErrorDetail = "Index not found for query: does_not_exist. Try recalculating your index ranges."; assertThat(e) .hasMessageStartingWith("Fetching message count failed for indices [does_not_exist]") .hasMessageEndingWith(expectedErrorDetail) .hasNoSuppressedExceptions(); assertThat(e.getErrorDetails()).containsExactly(expectedErrorDetail); } catch (Exception e) { fail("Expected IndexNotFoundException to be thrown"); } } }