/**
* 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.rest.resources.system;
import com.google.common.eventbus.Subscribe;
import org.graylog2.events.ClusterEventBus;
import org.graylog2.grok.GrokPattern;
import org.graylog2.grok.GrokPatternService;
import org.graylog2.grok.GrokPatternsChangedEvent;
import org.graylog2.plugin.database.ValidationException;
import org.graylog2.shared.bindings.GuiceInjectorHolder;
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 javax.ws.rs.core.Response;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class GrokResourceTest {
private static final String[] GROK_LINES = {
"# Comment",
"",
"TEST_PATTERN_0 Foo"
};
@Rule
public final MockitoRule mockitoRule = MockitoJUnit.rule();
@Rule
public final ExpectedException expectedException = ExpectedException.none();
@Mock
private GrokPatternService grokPatternService;
private GrokResource grokResource;
private GrokPatternsChangedEventSubscriber subscriber;
public GrokResourceTest() {
GuiceInjectorHolder.createInjector(Collections.emptyList());
}
@Before
public void setUp() {
final ClusterEventBus clusterBus = new ClusterEventBus();
subscriber = new GrokPatternsChangedEventSubscriber();
clusterBus.registerClusterEventSubscriber(subscriber);
grokResource = new PermittedTestResource(grokPatternService, clusterBus);
}
@Test
public void bulkUpdatePatternsFromTextFileWithLF() throws Exception {
final String patterns = Arrays.stream(GROK_LINES).collect(Collectors.joining("\n"));
final ByteArrayInputStream inputStream = new ByteArrayInputStream(patterns.getBytes(StandardCharsets.UTF_8));
final GrokPattern expectedPattern = GrokPattern.create("TEST_PATTERN_0", "Foo");
when(grokPatternService.validate(expectedPattern)).thenReturn(true);
final Response response = grokResource.bulkUpdatePatternsFromTextFile(inputStream, true);
verify(grokPatternService, times(1)).validate(expectedPattern);
verify(grokPatternService, times(1)).saveAll(Collections.singletonList(expectedPattern), true);
assertThat(response.getStatusInfo()).isEqualTo(Response.Status.ACCEPTED);
assertThat(response.hasEntity()).isFalse();
assertThat(subscriber.events)
.containsOnly(GrokPatternsChangedEvent.create(Collections.emptySet(), Collections.singleton(expectedPattern.name())));
}
@Test
public void bulkUpdatePatternsFromTextFileWithCR() throws Exception {
final String patterns = Arrays.stream(GROK_LINES).collect(Collectors.joining("\r"));
final ByteArrayInputStream inputStream = new ByteArrayInputStream(patterns.getBytes(StandardCharsets.UTF_8));
final GrokPattern expectedPattern = GrokPattern.create("TEST_PATTERN_0", "Foo");
when(grokPatternService.validate(expectedPattern)).thenReturn(true);
final Response response = grokResource.bulkUpdatePatternsFromTextFile(inputStream, true);
verify(grokPatternService, times(1)).validate(expectedPattern);
verify(grokPatternService, times(1)).saveAll(Collections.singletonList(expectedPattern), true);
assertThat(response.getStatusInfo()).isEqualTo(Response.Status.ACCEPTED);
assertThat(response.hasEntity()).isFalse();
assertThat(subscriber.events)
.containsOnly(GrokPatternsChangedEvent.create(Collections.emptySet(), Collections.singleton(expectedPattern.name())));
}
@Test
public void bulkUpdatePatternsFromTextFileWithCRLF() throws Exception {
final String patterns = Arrays.stream(GROK_LINES).collect(Collectors.joining("\r\n"));
final ByteArrayInputStream inputStream = new ByteArrayInputStream(patterns.getBytes(StandardCharsets.UTF_8));
final GrokPattern expectedPattern = GrokPattern.create("TEST_PATTERN_0", "Foo");
when(grokPatternService.validate(expectedPattern)).thenReturn(true);
final Response response = grokResource.bulkUpdatePatternsFromTextFile(inputStream, true);
verify(grokPatternService, times(1)).validate(expectedPattern);
verify(grokPatternService, times(1)).saveAll(Collections.singletonList(expectedPattern), true);
assertThat(response.getStatusInfo()).isEqualTo(Response.Status.ACCEPTED);
assertThat(response.hasEntity()).isFalse();
assertThat(subscriber.events)
.containsOnly(GrokPatternsChangedEvent.create(Collections.emptySet(), Collections.singleton(expectedPattern.name())));
}
@Test
public void bulkUpdatePatternsFromTextFileWithInvalidPattern() throws Exception {
final String patterns = Arrays.stream(GROK_LINES).collect(Collectors.joining("\n"));
final ByteArrayInputStream inputStream = new ByteArrayInputStream(patterns.getBytes(StandardCharsets.UTF_8));
final GrokPattern expectedPattern = GrokPattern.create("TEST_PATTERN_0", "Foo");
when(grokPatternService.validate(expectedPattern)).thenReturn(false);
expectedException.expect(ValidationException.class);
expectedException.expectMessage("Invalid pattern " + expectedPattern + ". Did not save any patterns.");
grokResource.bulkUpdatePatternsFromTextFile(inputStream, true);
}
@Test
public void bulkUpdatePatternsFromTextFileWithNoValidPatterns() throws Exception {
final String patterns = "# Comment\nHAHAHAHA_THIS_IS_NO_GROK_PATTERN!$%ยง";
final ByteArrayInputStream inputStream = new ByteArrayInputStream(patterns.getBytes(StandardCharsets.UTF_8));
final Response response = grokResource.bulkUpdatePatternsFromTextFile(inputStream, true);
verify(grokPatternService, never()).validate(any(GrokPattern.class));
verify(grokPatternService, never()).saveAll(any(), eq(true));
assertThat(response.getStatusInfo()).isEqualTo(Response.Status.ACCEPTED);
assertThat(response.hasEntity()).isFalse();
assertThat(subscriber.events).isEmpty();
}
static class GrokPatternsChangedEventSubscriber {
final List<GrokPatternsChangedEvent> events = new ArrayList<>();
@Subscribe
public void handleEvent(GrokPatternsChangedEvent event) {
events.add(event);
}
}
static class PermittedTestResource extends GrokResource {
PermittedTestResource(GrokPatternService grokPatternService, ClusterEventBus clusterBus) {
super(grokPatternService, clusterBus);
}
@Override
protected boolean isPermitted(String permission) {
return true;
}
}
}