/**
* 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.indexset;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.eventbus.Subscribe;
import com.lordofthejars.nosqlunit.annotation.UsingDataSet;
import com.lordofthejars.nosqlunit.core.LoadStrategyEnum;
import com.lordofthejars.nosqlunit.mongodb.InMemoryMongoDb;
import org.bson.types.ObjectId;
import org.graylog2.bindings.providers.MongoJackObjectMapperProvider;
import org.graylog2.buffers.processors.fakestreams.FakeStream;
import org.graylog2.cluster.ClusterConfigServiceImpl;
import org.graylog2.database.MongoConnectionRule;
import org.graylog2.events.ClusterEventBus;
import org.graylog2.indexer.indexset.events.IndexSetCreatedEvent;
import org.graylog2.indexer.indexset.events.IndexSetDeletedEvent;
import org.graylog2.indexer.retention.strategies.NoopRetentionStrategy;
import org.graylog2.indexer.retention.strategies.NoopRetentionStrategyConfig;
import org.graylog2.indexer.rotation.strategies.MessageCountRotationStrategy;
import org.graylog2.indexer.rotation.strategies.MessageCountRotationStrategyConfig;
import org.graylog2.plugin.cluster.ClusterConfigService;
import org.graylog2.plugin.system.NodeId;
import org.graylog2.shared.bindings.providers.ObjectMapperProvider;
import org.graylog2.shared.plugins.ChainingClassLoader;
import org.graylog2.streams.StreamService;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mongojack.DBQuery;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import static com.lordofthejars.nosqlunit.mongodb.InMemoryMongoDb.InMemoryMongoRuleBuilder.newInMemoryMongoDbRule;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
public class MongoIndexSetServiceTest {
@ClassRule
public static final InMemoryMongoDb IN_MEMORY_MONGO_DB = newInMemoryMongoDbRule().build();
@Rule
public final MongoConnectionRule mongoRule = MongoConnectionRule.build("index-sets");
@Rule
public final MockitoRule mockitoRule = MockitoJUnit.rule();
private final ObjectMapper objectMapper = new ObjectMapperProvider().get();
private final MongoJackObjectMapperProvider objectMapperProvider = new MongoJackObjectMapperProvider(objectMapper);
private ClusterEventBus clusterEventBus;
private MongoIndexSetService indexSetService;
private ClusterConfigService clusterConfigService;
@Mock
private StreamService streamService;
@Mock
private NodeId nodeId;
@Before
public void setUp() throws Exception {
clusterEventBus = new ClusterEventBus();
clusterConfigService = new ClusterConfigServiceImpl(objectMapperProvider, mongoRule.getMongoConnection(),
nodeId, new ChainingClassLoader(getClass().getClassLoader()), clusterEventBus);
indexSetService = new MongoIndexSetService(mongoRule.getMongoConnection(), objectMapperProvider, streamService, clusterConfigService, clusterEventBus);
}
@Test
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
public void getWithStringId() throws Exception {
final Optional<IndexSetConfig> indexSetConfig = indexSetService.get("57f3d721a43c2d59cb750001");
assertThat(indexSetConfig)
.isPresent()
.contains(
IndexSetConfig.create(
"57f3d721a43c2d59cb750001",
"Test 1",
"This is the index set configuration for Test 1",
true,
"test_1",
4,
1,
MessageCountRotationStrategy.class.getCanonicalName(),
MessageCountRotationStrategyConfig.create(1000),
NoopRetentionStrategy.class.getCanonicalName(),
NoopRetentionStrategyConfig.create(10),
ZonedDateTime.of(2016, 10, 4, 17, 0, 0, 0, ZoneOffset.UTC),
"standard",
"test_1",
1,
false
)
);
}
@Test
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
public void getReturnsExistingIndexSetConfig() throws Exception {
final Optional<IndexSetConfig> indexSetConfig = indexSetService.get(new ObjectId("57f3d721a43c2d59cb750001"));
assertThat(indexSetConfig)
.isPresent()
.contains(
IndexSetConfig.create(
"57f3d721a43c2d59cb750001",
"Test 1",
"This is the index set configuration for Test 1",
true,
"test_1",
4,
1,
MessageCountRotationStrategy.class.getCanonicalName(),
MessageCountRotationStrategyConfig.create(1000),
NoopRetentionStrategy.class.getCanonicalName(),
NoopRetentionStrategyConfig.create(10),
ZonedDateTime.of(2016, 10, 4, 17, 0, 0, 0, ZoneOffset.UTC),
"standard",
"test_1",
1,
false
)
);
}
@Test
@UsingDataSet(loadStrategy = LoadStrategyEnum.DELETE_ALL)
public void getReturnsAbsentOptionalIfIndexSetConfigDoesNotExist() throws Exception {
final Optional<IndexSetConfig> indexSetConfig = indexSetService.get(new ObjectId("57f3d3f0a43c2d595eb0a348"));
assertThat(indexSetConfig).isEmpty();
}
@Test
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
public void getDefault() throws Exception {
clusterConfigService.write(DefaultIndexSetConfig.create("57f3d721a43c2d59cb750002"));
final IndexSetConfig indexSetConfig = indexSetService.getDefault();
assertThat(indexSetConfig).isNotNull();
assertThat(indexSetConfig.id()).isEqualTo("57f3d721a43c2d59cb750002");
}
@Test(expected = IllegalStateException.class)
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
public void getDefaultWithoutDefault() throws Exception {
indexSetService.getDefault();
}
@Test
public void findOne() throws Exception {
final Optional<IndexSetConfig> config3 = indexSetService.findOne(DBQuery.is("title", "Test 2"));
assertThat(config3).isPresent();
assertThat(config3.get().id()).isEqualTo("57f3d721a43c2d59cb750002");
final Optional<IndexSetConfig> config4 = indexSetService.findOne(DBQuery.is("title", "__yolo"));
assertThat(config4).isNotPresent();
}
@Test
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
public void findAll() throws Exception {
final List<IndexSetConfig> configs = indexSetService.findAll();
assertThat(configs)
.isNotEmpty()
.hasSize(2)
.containsExactly(
IndexSetConfig.create(
"57f3d721a43c2d59cb750001",
"Test 1",
"This is the index set configuration for Test 1",
true,
"test_1",
4,
1,
MessageCountRotationStrategy.class.getCanonicalName(),
MessageCountRotationStrategyConfig.create(1000),
NoopRetentionStrategy.class.getCanonicalName(),
NoopRetentionStrategyConfig.create(10),
ZonedDateTime.of(2016, 10, 4, 17, 0, 0, 0, ZoneOffset.UTC),
"standard",
"test_1",
1,
false
),
IndexSetConfig.create(
"57f3d721a43c2d59cb750002",
"Test 2",
null,
true,
"test_2",
1,
0,
MessageCountRotationStrategy.class.getCanonicalName(),
MessageCountRotationStrategyConfig.create(2500),
NoopRetentionStrategy.class.getCanonicalName(),
NoopRetentionStrategyConfig.create(25),
ZonedDateTime.of(2016, 10, 4, 18, 0, 0, 0, ZoneOffset.UTC),
"standard",
"test_2",
1,
false
)
);
}
@Test
@UsingDataSet(loadStrategy = LoadStrategyEnum.DELETE_ALL)
public void save() throws Exception {
final IndexSetCreatedSubscriber subscriber = new IndexSetCreatedSubscriber();
clusterEventBus.registerClusterEventSubscriber(subscriber);
final IndexSetConfig indexSetConfig = IndexSetConfig.create(
"Test 3",
null,
true,
"test_3",
10,
0,
MessageCountRotationStrategy.class.getCanonicalName(),
MessageCountRotationStrategyConfig.create(10000),
NoopRetentionStrategy.class.getCanonicalName(),
NoopRetentionStrategyConfig.create(5),
ZonedDateTime.of(2016, 10, 4, 12, 0, 0, 0, ZoneOffset.UTC),
"standard",
"index-template",
1,
false
);
final IndexSetConfig savedIndexSetConfig = indexSetService.save(indexSetConfig);
final Optional<IndexSetConfig> retrievedIndexSetConfig = indexSetService.get(savedIndexSetConfig.id());
assertThat(retrievedIndexSetConfig)
.isPresent()
.contains(savedIndexSetConfig);
assertThat(subscriber.getEvents())
.hasSize(1)
.containsExactly(IndexSetCreatedEvent.create(savedIndexSetConfig));
}
@Test
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
public void deleteWithStringId() throws Exception {
final IndexSetDeletedSubscriber subscriber = new IndexSetDeletedSubscriber();
clusterEventBus.registerClusterEventSubscriber(subscriber);
final int deletedEntries = indexSetService.delete("57f3d721a43c2d59cb750001");
assertThat(deletedEntries).isEqualTo(1);
assertThat(indexSetService.get("57f3d721a43c2d59cb750001")).isEmpty();
assertThat(subscriber.getEvents())
.hasSize(1)
.containsExactly(IndexSetDeletedEvent.create("57f3d721a43c2d59cb750001"));
}
@Test
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
public void deleteRemovesExistingIndexSetConfig() throws Exception {
final IndexSetDeletedSubscriber subscriber = new IndexSetDeletedSubscriber();
clusterEventBus.registerClusterEventSubscriber(subscriber);
final int deletedEntries = indexSetService.delete(new ObjectId("57f3d721a43c2d59cb750001"));
assertThat(deletedEntries).isEqualTo(1);
assertThat(indexSetService.get("57f3d721a43c2d59cb750001")).isEmpty();
assertThat(subscriber.getEvents())
.hasSize(1)
.containsExactly(IndexSetDeletedEvent.create("57f3d721a43c2d59cb750001"));
}
@Test
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
public void deleteDoesNothingIfIndexSetConfigDoesNotExist() throws Exception {
final IndexSetDeletedSubscriber subscriber = new IndexSetDeletedSubscriber();
clusterEventBus.registerClusterEventSubscriber(subscriber);
final int deletedEntries = indexSetService.delete("57f3d721a43c2d59cb750003");
assertThat(deletedEntries).isEqualTo(0);
assertThat(indexSetService.get("57f3d721a43c2d59cb750001")).isPresent();
assertThat(indexSetService.get("57f3d721a43c2d59cb750003")).isEmpty();
assertThat(indexSetService.findAll()).hasSize(2);
assertThat(subscriber.getEvents()).isEmpty();
}
@Test
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
public void deleteWithAssignedStreams() throws Exception {
final IndexSetDeletedSubscriber subscriber = new IndexSetDeletedSubscriber();
clusterEventBus.registerClusterEventSubscriber(subscriber);
final FakeStream stream1 = new FakeStream("Test stream 1");
final String streamId = "57f3d721a43c2d59cb750001";
stream1.setIndexSetId(streamId);
when(streamService.loadAllWithIndexSet(streamId)).thenReturn(Collections.singletonList(stream1));
final int deletedEntries = indexSetService.delete(streamId);
assertThat(deletedEntries).isEqualTo(0);
assertThat(indexSetService.get(streamId)).isPresent();
assertThat(indexSetService.findAll()).hasSize(2);
assertThat(subscriber.getEvents()).isEmpty();
}
private static class IndexSetCreatedSubscriber {
private final List<IndexSetCreatedEvent> events = new CopyOnWriteArrayList<>();
@Subscribe
public void createdEvent(IndexSetCreatedEvent event) {
events.add(event);
}
public List<IndexSetCreatedEvent> getEvents() {
return events;
}
}
private static class IndexSetDeletedSubscriber {
private final List<IndexSetDeletedEvent> events = new CopyOnWriteArrayList<>();
@Subscribe
public void createdEvent(IndexSetDeletedEvent event) {
events.add(event);
}
public List<IndexSetDeletedEvent> getEvents() {
return events;
}
}
}