package org.gbif.checklistbank.service.mybatis.postgres;
import org.gbif.api.model.Constants;
import org.gbif.utils.file.properties.PropertiesUtil;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableMap;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
/**
* A TestRule for Database driven Integration tests executing some dbSetup file beforehand.
*/
public class ClbDbTestRule implements TestRule {
public static final String DEFAULT_PROPERTY_FILE = "checklistbank.properties";
public static final UUID SQUIRRELS_DATASET_KEY = UUID.fromString("109aea14-c252-4a85-96e2-f5f4d5d088f4");
protected final Logger log = LoggerFactory.getLogger(getClass());
private final String tsvFolder;
private final Map<String, Integer> sequenceCounters;
private final Properties properties;
private Connection connection;
/**
* Prepares an empty CLB db before any test is run, truncating tables and resetting sequence counters.
*/
public static ClbDbTestRule empty() {
return new ClbDbTestRule(null, ImmutableMap.<String, Integer>builder()
.put("citation_id_seq", 1)
.put("dataset_metrics_id_seq", 1)
.put("description_id_seq", 1)
.put("distribution_id_seq", 1)
.put("identifier_id_seq", 1)
.put("literature_id_seq", 1)
.put("media_id_seq", 1)
.put("name_usage_id_seq", Constants.NUB_MAXIMUM_KEY + 1)
.put("name_id_seq", 1)
.put("species_info_id_seq", 1)
.put("typification_id_seq", 1)
.put("vernacular_name_id_seq", 1)
.build());
}
/**
* Prepares a squirrels test db before any test is run, adding data and adjusting sequence counters.
*/
public static ClbDbTestRule squirrels() {
return new ClbDbTestRule("squirrels", ImmutableMap.<String, Integer>builder()
.put("citation_id_seq", 32)
.put("dataset_metrics_id_seq", 5)
.put("description_id_seq", 28)
.put("distribution_id_seq", 29)
.put("identifier_id_seq", 106)
.put("literature_id_seq", 23)
.put("media_id_seq", 100021)
.put("name_usage_id_seq", 110000000)
.put("name_id_seq", 200000)
.put("species_info_id_seq", 4)
.put("typification_id_seq", 16)
.put("vernacular_name_id_seq", 100011)
.build());
}
/**
* Prepares a squirrels test db before any test is run, adding data and adjusting sequence counters.
*/
public static ClbDbTestRule puma() {
return new ClbDbTestRule("puma", ImmutableMap.<String, Integer>builder()
.put("citation_id_seq", 32)
.put("dataset_metrics_id_seq", 5)
.put("description_id_seq", 28)
.put("distribution_id_seq", 29)
.put("identifier_id_seq", 106)
.put("literature_id_seq", 23)
.put("media_id_seq", 100021)
.put("name_usage_id_seq", 110000000)
.put("name_id_seq", 200000)
.put("species_info_id_seq", 4)
.put("typification_id_seq", 16)
.put("vernacular_name_id_seq", 100011)
.build());
}
/**
* @param tsvFolder the optional unqualified filename within the dbUnit package to be used in setting up
* the db
*/
private ClbDbTestRule(@Nullable String tsvFolder, Map<String, Integer> sequenceCounters) {
this.tsvFolder = tsvFolder;
this.sequenceCounters = sequenceCounters;
try {
properties = PropertiesUtil.loadProperties(DEFAULT_PROPERTY_FILE);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public Properties getProperties() {
return properties;
}
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
before();
base.evaluate();
} finally {
after();
}
}
};
}
/**
* @return the existing, single db connection. Keep this open, it will be closed by this rule after the tests have run.
*/
public Connection getConnection() {
return connection;
}
public void before() throws Exception {
SLF4JBridgeHandler.install();
connection = DbLoader.connect(properties);
connection.setAutoCommit(false);
if (tsvFolder != null) {
DbLoader.load(connection, tsvFolder, true);
} else {
DbLoader.truncate(connection, "squirrels");
}
updateSequences();
connection.setAutoCommit(true);
}
/**
* Update postgres sequence counters.
*/
private void updateSequences() {
log.debug("Resetting clb sequences");
try {
for (Map.Entry<String, Integer> seq : sequenceCounters.entrySet()) {
try (java.sql.Statement st = connection.createStatement()) {
st.execute("ALTER SEQUENCE " + seq.getKey() + " RESTART " + seq.getValue());
}
}
connection.commit();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void after() throws Exception {
if (connection != null && !connection.isClosed()) {
connection.close();
}
}
}