/* (c) 2016 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geogig.geoserver.config;
import static org.geogig.geoserver.config.LogEvent.Severity.DEBUG;
import static org.geogig.geoserver.config.LogEvent.Severity.ERROR;
import static org.geogig.geoserver.config.LogEvent.Severity.INFO;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.Writer;
import java.net.URL;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.geogig.geoserver.config.LogEvent.Severity;
import org.geoserver.platform.resource.FileSystemResourceStore;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.ResourceStore;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.springframework.security.core.context.SecurityContextHolder;
import com.google.common.base.Charsets;
import com.google.common.base.Throwables;
import com.google.common.io.CharStreams;
import com.google.common.io.Resources;
public class AbstractLogStoreTest {
@Rule
public TemporaryFolder tmpDir = new TemporaryFolder();
@Rule
public ExpectedException thrown = ExpectedException.none();
protected ResourceStore resourceStore;
protected LogStore logStore;
protected String repoUrl = "file:/home/testuser/repos/myrepo";
@Before
public void before() {
File resourceDirectory = tmpDir.getRoot();
resourceStore = new FileSystemResourceStore(resourceDirectory);
logStore = new LogStore(resourceStore);
SecurityContextHolder.clearContext();
setUpConfigFile();
}
@After
public void after() throws Exception {
if (logStore != null) {
logStore.destroy();
}
}
private void setUpConfigFile() {
Resource dirResource = resourceStore.get(LogStore.CONFIG_DIR_NAME);
File dir = dirResource.dir();
Properties properties = new Properties();
populateConfigProperties(properties, dir);
if (!properties.isEmpty()) {
File configFile = new File(dir, LogStore.CONFIG_FILE_NAME);
try {
if (!configFile.exists()) {
assertTrue(configFile.createNewFile());
}
try (Writer writer = new OutputStreamWriter(new FileOutputStream(configFile),
Charsets.UTF_8)) {
properties.store(writer, "");
}
} catch (Exception e) {
throw Throwables.propagate(e);
}
}
}
protected void populateConfigProperties(Properties properties, File configDirectory) {
// do nothing, override to create a config file for a non default database
}
@Test
public void testLogEntries() throws Exception {
logStore.afterPropertiesSet();
logStore.debug(repoUrl, "debug message");
Throwable ex = new RuntimeException("test exception");
ex.fillInStackTrace();
logStore.error(repoUrl, "error message", ex);
logStore.info(repoUrl, "info message");
List<LogEvent> entries = logStore.getLogEntries(0, 10);
assertNotNull(entries);
assertEquals(3, entries.size());
assertEquals(repoUrl, entries.get(0).getRepositoryURL());
assertEquals(repoUrl, entries.get(1).getRepositoryURL());
assertEquals(repoUrl, entries.get(2).getRepositoryURL());
assertEquals("anonymous", entries.get(0).getUser());
assertEquals("anonymous", entries.get(1).getUser());
assertEquals("anonymous", entries.get(2).getUser());
}
@Test
public void testLogEntriesOrderedByTimestampDecreasingOrder() throws Exception {
logStore.afterPropertiesSet();
logStore.debug(repoUrl, "debug message");
Throwable ex = new RuntimeException("test exception");
ex.fillInStackTrace();
logStore.error(repoUrl, "error message", ex);
logStore.info(repoUrl, "info message");
List<LogEvent> entries = logStore.getLogEntries(0, 10);
assertNotNull(entries);
assertEquals(3, entries.size());
assertEquals("info message", entries.get(0).getMessage());
assertEquals("error message", entries.get(1).getMessage());
assertEquals("debug message", entries.get(2).getMessage());
}
@Test
public void testLogEntriesFilterBySeverity() throws Exception {
logStore.afterPropertiesSet();
Throwable ex = new RuntimeException("test exception");
ex.fillInStackTrace();
logStore.debug(repoUrl, "debug message 1");
logStore.error(repoUrl, "error message 1", ex);
logStore.info(repoUrl, "info message 1");
logStore.debug(repoUrl, "debug message 2");
logStore.error(repoUrl, "error message 2", ex);
logStore.info(repoUrl, "info message 2");
assertEquals(6, logStore.getLogEntries(0, 10, INFO, DEBUG, ERROR).size());
assertEquals(4, logStore.getLogEntries(0, 10, INFO, DEBUG).size());
assertEquals(4, logStore.getLogEntries(0, 10, INFO, ERROR).size());
assertEquals(4, logStore.getLogEntries(0, 10, DEBUG, ERROR).size());
assertEquals(2, logStore.getLogEntries(0, 10, INFO).size());
assertEquals(2, logStore.getLogEntries(0, 10, ERROR).size());
assertEquals(2, logStore.getLogEntries(0, 10, DEBUG).size());
}
@Test
public void testLogEntriesOffsetLimit() throws Exception {
logStore.afterPropertiesSet();
Throwable ex = new RuntimeException("test exception");
ex.fillInStackTrace();
logStore.debug(repoUrl, "debug message 1");
logStore.error(repoUrl, "error message 1", ex);
logStore.info(repoUrl, "info message 1");
logStore.debug(repoUrl, "debug message 2");
logStore.error(repoUrl, "error message 2", ex);
logStore.info(repoUrl, "info message 2");
assertEquals(6, logStore.getLogEntries(0, 10).size());
assertEquals(5, logStore.getLogEntries(0, 5).size());
assertEquals(4, logStore.getLogEntries(2, 5).size());
assertEquals(3, logStore.getLogEntries(2, 3).size());
assertEquals(2, logStore.getLogEntries(0, 10, INFO).size());
assertEquals(1, logStore.getLogEntries(0, 1, INFO, DEBUG).size());
assertEquals(2, logStore.getLogEntries(2, 4, INFO, DEBUG).size());
assertEquals(3, logStore.getLogEntries(0, 3, INFO, DEBUG).size());
}
@Test
public void testGetStackTrace() throws Exception {
logStore.afterPropertiesSet();
Throwable ex = new RuntimeException("test exception");
ex.fillInStackTrace();
logStore.error(repoUrl, "error message 1", ex);
LogEvent event = logStore.getLogEntries(0, 10).get(0);
assertEquals(Severity.ERROR, event.getSeverity());
long eventId = event.getEventId();
String stackTrace = logStore.getStackTrace(eventId);
assertNotNull(stackTrace);
assertTrue(stackTrace, stackTrace.contains("test exception"));
stackTrace = logStore.getStackTrace(eventId + 1);
assertNull(stackTrace);
}
@Test
public void testGetFullSize() throws Exception {
logStore.afterPropertiesSet();
assertEquals(0, logStore.getFullSize());
logStore.debug(repoUrl, "debug message");
assertEquals(1, logStore.getFullSize());
Throwable ex = new RuntimeException("test exception");
ex.fillInStackTrace();
logStore.error(repoUrl, "error message", ex);
assertEquals(2, logStore.getFullSize());
logStore.info(repoUrl, "info message");
assertEquals(3, logStore.getFullSize());
}
protected void runScript(String driverClassName, String jdbcUrl, URL script, String user,
String password) {
List<String> statements = parseStatements(script);
Connection connection;
try {
Driver d = (Driver) Class.forName(driverClassName).newInstance();
connection = DriverManager.getConnection(jdbcUrl, user, password);
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException
| SQLException e) {
throw Throwables.propagate(e);
}
System.err.println("Running script " + script.getFile() + " on db " + jdbcUrl);
for (String sql : statements) {
try (Statement st = connection.createStatement()) {
// System.err.println(sql);
st.execute(sql);
} catch (SQLException e) {
throw Throwables.propagate(e);
}
}
}
private List<String> parseStatements(URL script) {
List<String> lines;
try {
OutputStream to = new ByteArrayOutputStream();
Resources.copy(script, to);
String scriptContents = to.toString();
lines = CharStreams.readLines(new StringReader(scriptContents));
} catch (IOException e) {
throw Throwables.propagate(e);
}
List<String> statements = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
for (String line : lines) {
line = line.trim();
if (line.startsWith("#") || line.startsWith("-") || line.isEmpty()) {
continue;
}
sb.append(line).append('\n');
if (line.endsWith(";")) {
statements.add(sb.toString());
sb.setLength(0);
}
}
return statements;
}
}