From e8c0d473db398c11bcafb69fb8b510103572fe07 Mon Sep 17 00:00:00 2001 From: Benjamin Eckstein <13351939+benjamineckstein@users.noreply.github.com> Date: Mon, 9 Dec 2019 13:56:51 +0100 Subject: [PATCH] TSK-967: Refactor Taskana-Data module to merge SampleDataGenerator and TestDataGenerator --- .../test/java/acceptance/AbstractAccTest.java | 5 +- .../report/AbstractReportAccTest.java | 5 +- .../taskana/database/TestDataGenerator.java | 196 ------------------ .../pro/taskana/sampledata/SQLReplacer.java | 123 +++++++++++ .../sampledata/SampleDataGenerator.java | 123 +++++------ .../sampledata/SampleDataProvider.java | 56 +++-- .../sql/monitor-data}/monitor-sample-data.sql | 0 .../resources/sql/test-data}/attachment.sql | 0 .../sql/test-data}/classification.sql | 0 .../sql/test-data}/distribution-targets.sql | 0 .../sql/test-data}/object-reference.sql | 0 .../main/resources/sql/test-data}/task.sql | 0 .../sql/test-data}/workbasket-access-list.sql | 0 .../resources/sql/test-data}/workbasket.sql | 0 .../sampledata/SampleDataGeneratorTest.java | 18 +- .../taskana/jobs/AsyncUpdateJobIntTest.java | 8 +- 16 files changed, 231 insertions(+), 303 deletions(-) delete mode 100644 lib/taskana-core/src/test/java/pro/taskana/database/TestDataGenerator.java create mode 100644 lib/taskana-data/src/main/java/pro/taskana/sampledata/SQLReplacer.java rename lib/{taskana-core/src/test/resources/sql => taskana-data/src/main/resources/sql/monitor-data}/monitor-sample-data.sql (100%) rename lib/{taskana-core/src/test/resources/sql => taskana-data/src/main/resources/sql/test-data}/attachment.sql (100%) rename lib/{taskana-core/src/test/resources/sql => taskana-data/src/main/resources/sql/test-data}/classification.sql (100%) rename lib/{taskana-core/src/test/resources/sql => taskana-data/src/main/resources/sql/test-data}/distribution-targets.sql (100%) rename lib/{taskana-core/src/test/resources/sql => taskana-data/src/main/resources/sql/test-data}/object-reference.sql (100%) rename lib/{taskana-core/src/test/resources/sql => taskana-data/src/main/resources/sql/test-data}/task.sql (100%) rename lib/{taskana-core/src/test/resources/sql => taskana-data/src/main/resources/sql/test-data}/workbasket-access-list.sql (100%) rename lib/{taskana-core/src/test/resources/sql => taskana-data/src/main/resources/sql/test-data}/workbasket.sql (100%) diff --git a/lib/taskana-core/src/test/java/acceptance/AbstractAccTest.java b/lib/taskana-core/src/test/java/acceptance/AbstractAccTest.java index 7a8a3881b..f2d7640b0 100644 --- a/lib/taskana-core/src/test/java/acceptance/AbstractAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/AbstractAccTest.java @@ -22,10 +22,10 @@ import pro.taskana.TaskanaEngine; import pro.taskana.TaskanaEngine.ConnectionManagementMode; import pro.taskana.TimeInterval; import pro.taskana.configuration.TaskanaEngineConfiguration; -import pro.taskana.database.TestDataGenerator; import pro.taskana.exceptions.ClassificationNotFoundException; import pro.taskana.impl.configuration.TaskanaEngineConfigurationTest; import pro.taskana.sampledata.DBCleaner; +import pro.taskana.sampledata.SampleDataGenerator; /** * Base class for all acceptance tests. @@ -34,7 +34,6 @@ public abstract class AbstractAccTest { protected static TaskanaEngineConfiguration taskanaEngineConfiguration; protected static TaskanaEngine taskanaEngine; - protected static TestDataGenerator testDataGenerator = new TestDataGenerator(); @BeforeAll @BeforeClass @@ -55,7 +54,7 @@ public abstract class AbstractAccTest { taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); taskanaEngine.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT); dbCleaner.clearDb(dataSource, schemaName); - testDataGenerator.generateTestData(dataSource, schemaName); + new SampleDataGenerator(dataSource, schemaName).generateTestData(); } protected ObjectReference createObjectReference(String company, String system, String systemInstance, String type, diff --git a/lib/taskana-core/src/test/java/acceptance/report/AbstractReportAccTest.java b/lib/taskana-core/src/test/java/acceptance/report/AbstractReportAccTest.java index d84d1ec2c..5a821da03 100644 --- a/lib/taskana-core/src/test/java/acceptance/report/AbstractReportAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/report/AbstractReportAccTest.java @@ -10,9 +10,9 @@ import org.junit.jupiter.api.BeforeAll; import pro.taskana.TaskanaEngine; import pro.taskana.configuration.TaskanaEngineConfiguration; -import pro.taskana.database.TestDataGenerator; import pro.taskana.impl.configuration.TaskanaEngineConfigurationTest; import pro.taskana.sampledata.DBCleaner; +import pro.taskana.sampledata.SampleDataGenerator; /** * Abstract test class for all report building tests. @@ -42,7 +42,6 @@ public class AbstractReportAccTest { taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); taskanaEngine.setConnectionManagementMode(TaskanaEngine.ConnectionManagementMode.AUTOCOMMIT); cleaner.clearDb(dataSource, schemaName); - TestDataGenerator testDataGenerator = new TestDataGenerator(); - testDataGenerator.generateMonitoringTestData(dataSource); + new SampleDataGenerator(dataSource, schemaName).generateMonitorData(); } } diff --git a/lib/taskana-core/src/test/java/pro/taskana/database/TestDataGenerator.java b/lib/taskana-core/src/test/java/pro/taskana/database/TestDataGenerator.java deleted file mode 100644 index e4fbfb612..000000000 --- a/lib/taskana-core/src/test/java/pro/taskana/database/TestDataGenerator.java +++ /dev/null @@ -1,196 +0,0 @@ -package pro.taskana.database; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.nio.charset.StandardCharsets; -import java.sql.Connection; -import java.sql.SQLException; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import javax.sql.DataSource; - -import org.apache.ibatis.jdbc.ScriptRunner; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import pro.taskana.impl.TaskanaEngineImpl; - -/** - * Generates the test data for integration and acceptance tests. - */ -public class TestDataGenerator { - - private static final Logger LOGGER = LoggerFactory.getLogger(TestDataGenerator.class); - private static final String SQL = "/sql"; - private static final String TASK = SQL + "/task.sql"; - private static final String WORKBASKET = SQL + "/workbasket.sql"; - private static final String DISTRIBUTION_TARGETS = SQL + "/distribution-targets.sql"; - private static final String WORKBASKET_ACCESS_LIST = SQL + "/workbasket-access-list.sql"; - private static final String CLASSIFICATION = SQL + "/classification.sql"; - private static final String OBJECT_REFERENCE = SQL + "/object-reference.sql"; - private static final String ATTACHMENT = SQL + "/attachment.sql"; - private static final String MONITOR_SAMPLE_DATA = SQL + "/monitor-sample-data.sql"; - private static SQLReplacer sqlReplacer; - - private StringWriter outWriter = new StringWriter(); - private PrintWriter logWriter; - private StringWriter errorWriter; - private PrintWriter errorLogWriter; - - public TestDataGenerator() { - this.logWriter = new PrintWriter(this.outWriter); - this.errorWriter = new StringWriter(); - this.errorLogWriter = new PrintWriter(this.errorWriter); - } - - public void generateTestData(DataSource dataSource, String schema) throws SQLException, IOException { - ScriptRunner runner = null; - try { - Connection connection = dataSource.getConnection(); - LOGGER.debug(connection.getMetaData().toString()); - connection.setSchema(schema); - runner = new ScriptRunner(connection); - runner.setStopOnError(true); - runner.setLogWriter(this.logWriter); - runner.setErrorLogWriter(this.errorLogWriter); - runner.setStopOnError(true); - runner.setLogWriter(this.logWriter); - runner.setErrorLogWriter(this.errorLogWriter); - - if (sqlReplacer == null) { - sqlReplacer = new SQLReplacer(connection.getMetaData().getDatabaseProductName()); - } - - Stream.of(sqlReplacer.classificationSql, sqlReplacer.workbasketSql, sqlReplacer.taskSql, - sqlReplacer.workbasketAccessListSql, sqlReplacer.distributionTargetSql, sqlReplacer.objectReferenceSql, - sqlReplacer.attachmentSql) - .map(s -> s.getBytes(StandardCharsets.UTF_8)) - .map(ByteArrayInputStream::new) - .map(InputStreamReader::new) - .forEach(runner::runScript); - - } finally { - if (runner != null) { - runner.closeConnection(); - } - LOGGER.debug(outWriter.toString()); - if (!errorWriter.toString().trim().isEmpty()) { - LOGGER.error(errorWriter.toString()); - } - } - } - - public void generateMonitoringTestData(DataSource dataSource) throws IOException, SQLException { - ScriptRunner runner = null; - try { - Connection connection = dataSource.getConnection(); - LOGGER.debug(connection.getMetaData().toString()); - runner = new ScriptRunner(connection); - runner.setStopOnError(true); - runner.setLogWriter(this.logWriter); - runner.setErrorLogWriter(this.errorLogWriter); - runner.setStopOnError(true); - runner.setLogWriter(this.logWriter); - runner.setErrorLogWriter(this.errorLogWriter); - - if (sqlReplacer == null) { - sqlReplacer = new SQLReplacer(connection.getMetaData().getDatabaseProductName()); - } - - runner.runScript( - new InputStreamReader( - new ByteArrayInputStream( - sqlReplacer.monitoringTestDataSql.getBytes(StandardCharsets.UTF_8)))); - } finally { - if (runner != null) { - runner.closeConnection(); - } - LOGGER.debug(outWriter.toString()); - if (!errorWriter.toString().trim().isEmpty()) { - LOGGER.error(errorWriter.toString()); - } - } - } - - /** - * This class replaces boolean values with int values if the database is db2. - */ - private static final class SQLReplacer { - - private static final String RELATIVE_DATE_REGEX = "RELATIVE_DATE\\((-?\\d+)\\)"; - private static final Pattern RELATIVE_DATE_PATTERN = Pattern.compile(RELATIVE_DATE_REGEX); - private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - - private String classificationSql; - private String workbasketSql; - private String taskSql; - private String workbasketAccessListSql; - private String distributionTargetSql; - private String objectReferenceSql; - private String attachmentSql; - private String monitoringTestDataSql; - - private SQLReplacer(String dbProductName) throws IOException { - boolean isDb2 = TaskanaEngineImpl.isDb2(dbProductName); - LocalDateTime now = LocalDateTime.now(); - classificationSql = parseAndReplace(getClass().getResourceAsStream(CLASSIFICATION), now, isDb2); - workbasketSql = parseAndReplace(getClass().getResourceAsStream(WORKBASKET), now, isDb2); - taskSql = parseAndReplace(getClass().getResourceAsStream(TASK), now, isDb2); - workbasketAccessListSql = parseAndReplace(getClass().getResourceAsStream(WORKBASKET_ACCESS_LIST), now, - isDb2); - distributionTargetSql = parseAndReplace(getClass().getResourceAsStream(DISTRIBUTION_TARGETS), now, isDb2); - objectReferenceSql = parseAndReplace(getClass().getResourceAsStream(OBJECT_REFERENCE), now, isDb2); - attachmentSql = parseAndReplace(getClass().getResourceAsStream(ATTACHMENT), now, isDb2); - monitoringTestDataSql = parseAndReplace(getClass().getResourceAsStream(MONITOR_SAMPLE_DATA), now, isDb2); - } - - /** - * This method resolves the custom sql function defined through this regex: {@value RELATIVE_DATE_REGEX}. - * Its parameter is a digit representing the relative offset of a given starting point date. - *

- * Yes, this can be done as an actual sql function, but that'd lead to a little more complexity - * (and thus we'd have to maintain the code for db compatibility ...) - * Since we're already replacing the boolean attributes of sql files this addition is not a huge computational cost. - * - * @param now anchor for relative date conversion. - * @param sql sql statement which may contain the above declared custom function. - * @return sql statement with the given function resolved, if the 'sql' parameter contained any. - */ - private static String replaceRelativeTimeFunction(LocalDateTime now, String sql) { - Matcher m = RELATIVE_DATE_PATTERN.matcher(sql); - StringBuffer sb = new StringBuffer(sql.length()); - while (m.find()) { - m.appendReplacement(sb, - "'" + now.plusDays(Long.parseLong(m.group(1))).format(DATE_TIME_FORMATTER) + "'"); - } - m.appendTail(sb); - return sb.toString(); - } - - private static String replaceBooleanWithInteger(String sql) { - return sql.replaceAll("(?i)true", "1").replaceAll("(?i)false", "0"); - } - - private static String parseAndReplace(InputStream stream, LocalDateTime now, boolean isDb2) throws IOException { - try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream))) { - String sql = bufferedReader.lines().collect(Collectors.joining(System.lineSeparator())); - if (isDb2) { - sql = replaceBooleanWithInteger(sql); - } - return replaceRelativeTimeFunction(now, sql); - } - } - - } - -} diff --git a/lib/taskana-data/src/main/java/pro/taskana/sampledata/SQLReplacer.java b/lib/taskana-data/src/main/java/pro/taskana/sampledata/SQLReplacer.java new file mode 100644 index 000000000..56ac4d7a4 --- /dev/null +++ b/lib/taskana-data/src/main/java/pro/taskana/sampledata/SQLReplacer.java @@ -0,0 +1,123 @@ +package pro.taskana.sampledata; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * This class replaces boolean values with int values if the database is db2. + */ +final class SQLReplacer { + + static final String RELATIVE_DATE_REGEX = "RELATIVE_DATE\\((-?\\d+)\\)"; + static final Pattern RELATIVE_DATE_PATTERN = Pattern.compile(RELATIVE_DATE_REGEX); + static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + + static String getScriptAsSql(String dbProductName, LocalDateTime now, String scriptPath) { + return parseAndReplace(SQLReplacer.class.getResourceAsStream(scriptPath), now, dbProductName); + } + + private SQLReplacer() { + } + + /** + * This method resolves the custom sql function defined through this regex: {@value RELATIVE_DATE_REGEX}. + * Its parameter is a digit representing the relative offset of a given starting point date. + *

+ * Yes, this can be done as an actual sql function, but that'd lead to a little more complexity + * (and thus we'd have to maintain the code for db compatibility ...) + * Since we're already replacing the boolean attributes of sql files this addition is not a huge computational cost. + * + * @param now anchor for relative date conversion. + * @param sql sql statement which may contain the above declared custom function. + * @return sql statement with the given function resolved, if the 'sql' parameter contained any. + */ + private static String replaceRelativeTimeFunction(LocalDateTime now, String sql) { + Matcher m = RELATIVE_DATE_PATTERN.matcher(sql); + StringBuffer sb = new StringBuffer(sql.length()); + while (m.find()) { + m.appendReplacement(sb, + "'" + now.plusDays(Long.parseLong(m.group(1))).format(DATE_TIME_FORMATTER) + "'"); + } + m.appendTail(sb); + return sb.toString(); + } + + private static String replaceBooleanWithInteger(String sql) { + return sql.replaceAll("(?i)true", "1").replaceAll("(?i)false", "0"); + } + + private static String parseAndReplace(InputStream stream, LocalDateTime now, String dbProductname) { + boolean isDb2 = isDb2(dbProductname); + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream))) { + String sql = bufferedReader.lines().collect(Collectors.joining(System.lineSeparator())); + if (isDb2) { + sql = replaceBooleanWithInteger(sql); + } + return replaceRelativeTimeFunction(now, sql); + } catch (IOException e) { + throw new RuntimeException("Scriptfile not found", e); + } + } + + static boolean isPostgreSQL(String databaseProductName) { + return "PostgreSQL".equals(databaseProductName); + } + + static boolean isDb2(String dbProductName) { + return dbProductName.contains("DB2"); + } + + /** + * This method resolves the custom sql function defined through this regex: {@value RELATIVE_DATE_REGEX}. Its + * parameter is a digit representing the relative offset of a given starting point date. + *

+ * Yes, this can be done as an actual sql function, but that'd lead to a little more complexity (and thus we'd have + * to maintain the code for db compatibility ...) Since we're already replacing the boolean attributes of sql files + * this addition is not a huge computational cost. + * + * @param now + * anchor for relative date conversion. + * @param sql + * sql statement which may contain the above declared custom function. + * @return sql statement with the given function resolved, if the 'sql' parameter contained any. + */ + static String replaceDatePlaceholder(LocalDateTime now, String sql) { + Matcher m = RELATIVE_DATE_PATTERN.matcher(sql); + StringBuffer sb = new StringBuffer(sql.length()); + while (m.find()) { + long daysToShift = Long.parseLong(m.group(1)); + String daysAsStringDate = formatToSqlDate(now, daysToShift); + m.appendReplacement(sb, daysAsStringDate); + } + m.appendTail(sb); + return sb.toString(); + } + + private static String formatToSqlDate(LocalDateTime now, long days) { + return "'" + now.plusDays(days).format(DATE_TIME_FORMATTER) + "'"; + } + + static String parseAndReplace(LocalDateTime now, String script) { + return replaceDatePlaceholder(now, + getScriptAsString(script)); + } + + private static String getScriptAsString(String script) { + return getScriptBufferedStream(script).lines().collect(Collectors.joining(System.lineSeparator())); + } + + static BufferedReader getScriptBufferedStream(String script) { + return Optional.ofNullable(SampleDataGenerator.class.getResourceAsStream(script)).map( + inputStream -> new BufferedReader( + new InputStreamReader(inputStream, StandardCharsets.UTF_8))).orElse(null); + } +} diff --git a/lib/taskana-data/src/main/java/pro/taskana/sampledata/SampleDataGenerator.java b/lib/taskana-data/src/main/java/pro/taskana/sampledata/SampleDataGenerator.java index 4071ecf0f..ca77b4b71 100644 --- a/lib/taskana-data/src/main/java/pro/taskana/sampledata/SampleDataGenerator.java +++ b/lib/taskana-data/src/main/java/pro/taskana/sampledata/SampleDataGenerator.java @@ -1,19 +1,16 @@ package pro.taskana.sampledata; -import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.io.PrintWriter; -import java.io.StringReader; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.SQLException; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Optional; +import java.util.HashMap; +import java.util.List; import java.util.function.Consumer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -32,10 +29,11 @@ public class SampleDataGenerator { private static final String DB_CLEAR_TABLES_SCRIPT = "/sql/clear/clear-db.sql"; private static final String DB_DROP_TABLES_SCRIPT = "/sql/clear/drop-tables.sql"; - - static final String RELATIVE_DATE_REGEX = "RELATIVE_DATE\\((-?\\d+)\\)"; - static final Pattern RELATIVE_DATE_PATTERN = Pattern.compile(RELATIVE_DATE_REGEX); - static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + private static final String CHECK_HISTORY_EVENT_EXIST = "/sql/sample-data/check-history-event-exist.sql"; + public static final String CACHED_TEST = "TEST"; + public static final String CACHED_SAMPLE = "SAMPLE"; + public static final String CACHED_EVENTSAMPLE = "EVENTSAMPLE"; + public static final String CACHED_MONITOR = "MONITOR"; private final DataSource dataSource; private final LocalDateTime now; @@ -46,6 +44,8 @@ public class SampleDataGenerator { */ private final String schema; + private static HashMap> cachedScripts = new HashMap>(); + public SampleDataGenerator(DataSource dataSource, String schema) { this(dataSource, schema, LocalDateTime.now()); } @@ -56,9 +56,8 @@ public class SampleDataGenerator { this.now = now; } - public void runScripts(Consumer consumer) throws SQLException { + public void runScripts(Consumer consumer) { try (Connection connection = dataSource.getConnection()) { - if (LOGGER.isTraceEnabled()) { LOGGER.trace(connection.getMetaData().toString()); } @@ -77,33 +76,69 @@ public class SampleDataGenerator { LOGGER.error(trimmedErrorString); } } + } catch (SQLException e) { + throw new RuntimeException("Failed to execute script.", e); } } public void generateSampleData() throws SQLException { runScripts((runner) -> { clearDb(runner); - executeScripts(runner, SampleDataProvider.getDataProvider(runner)); + Stream scripts; + String cacheKey; + try { + //TODO find a better method of testing if a table exists + runner.runScript(SQLReplacer.getScriptBufferedStream(CHECK_HISTORY_EVENT_EXIST)); + scripts = SampleDataProvider.getScriptsWithEvents(); + cacheKey = CACHED_SAMPLE; + } catch (Exception e) { + scripts = SampleDataProvider.getDefaultScripts(); + cacheKey = CACHED_EVENTSAMPLE; + } + cacheAndExecute(scripts, cacheKey); }); } - private void executeScripts(ScriptRunner runner, Stream scriptsList) { - scriptsList - .map(s -> SampleDataGenerator.parseAndReplace(now, s)) - .map(StringReader::new) - .map(BufferedReader::new) - .forEachOrdered(runner::runScript); + public List parseScripts(Stream scripts) { + try (Connection connection = dataSource.getConnection()) { + String dbProductName = connection.getMetaData().getDatabaseProductName(); + return scripts.map(script -> SQLReplacer.getScriptAsSql(dbProductName, now, script)) + .collect(Collectors.toList()); + } catch (SQLException e) { + throw new RuntimeException("Connection to database failed.", e); + } + } + + public void generateTestData() { + Stream scripts = SampleDataProvider.getTestDataScripts(); + cacheAndExecute(scripts, CACHED_TEST); + } + + public void generateMonitorData() { + Stream scripts = SampleDataProvider.getMonitorDataScripts(); + cacheAndExecute(scripts, CACHED_MONITOR); } public void clearDb(ScriptRunner runner) { runner.setStopOnError(false); - runner.runScript(getScriptBufferedStream(DB_CLEAR_TABLES_SCRIPT)); + runner.runScript(SQLReplacer.getScriptBufferedStream(DB_CLEAR_TABLES_SCRIPT)); runner.setStopOnError(true); } + private void cacheAndExecute(Stream scripts, String cacheKey) { + if (!cachedScripts.containsKey(cacheKey)) { + cachedScripts.put(cacheKey, parseScripts(scripts)); + } + runScripts(runner -> cachedScripts.get(cacheKey).stream() + .map(s -> s.getBytes(StandardCharsets.UTF_8)) + .map(ByteArrayInputStream::new) + .map(InputStreamReader::new) + .forEach(runner::runScript)); + } + public void dropDb(ScriptRunner runner) { runner.setStopOnError(false); - runner.runScript(getScriptBufferedStream(DB_DROP_TABLES_SCRIPT)); + runner.runScript(SQLReplacer.getScriptBufferedStream(DB_DROP_TABLES_SCRIPT)); runner.setStopOnError(true); } @@ -115,55 +150,9 @@ public class SampleDataGenerator { ScriptRunner runner = new ScriptRunner(connection); connection.setSchema(schema); - String databaseProductName = connection.getMetaData().getDatabaseProductName(); - runner.setLogWriter(logWriter); runner.setErrorLogWriter(errorLogWriter); return runner; } - /** - * This method resolves the custom sql function defined through this regex: {@value RELATIVE_DATE_REGEX}. Its - * parameter is a digit representing the relative offset of a given starting point date. - *

- * Yes, this can be done as an actual sql function, but that'd lead to a little more complexity (and thus we'd have - * to maintain the code for db compatibility ...) Since we're already replacing the boolean attributes of sql files - * this addition is not a huge computational cost. - * - * @param now - * anchor for relative date conversion. - * @param sql - * sql statement which may contain the above declared custom function. - * @return sql statement with the given function resolved, if the 'sql' parameter contained any. - */ - static String replaceDatePlaceholder(LocalDateTime now, String sql) { - Matcher m = RELATIVE_DATE_PATTERN.matcher(sql); - StringBuffer sb = new StringBuffer(sql.length()); - while (m.find()) { - long daysToShift = Long.parseLong(m.group(1)); - String daysAsStringDate = formatToSqlDate(now, daysToShift); - m.appendReplacement(sb, daysAsStringDate); - } - m.appendTail(sb); - return sb.toString(); - } - - private static String formatToSqlDate(LocalDateTime now, long days) { - return "'" + now.plusDays(days).format(DATE_TIME_FORMATTER) + "'"; - } - - private static String parseAndReplace(LocalDateTime now, String script) { - return replaceDatePlaceholder(now, - getScriptBufferedStream(script).lines().collect(Collectors.joining(System.lineSeparator()))); - } - - static BufferedReader getScriptBufferedStream(String script) { - return Optional.ofNullable(SampleDataGenerator.class.getResourceAsStream(script)).map( - inputStream -> new BufferedReader( - new InputStreamReader(inputStream, StandardCharsets.UTF_8))).orElse(null); - } - - private static boolean isPostgreSQL(String databaseProductName) { - return "PostgreSQL".equals(databaseProductName); - } } diff --git a/lib/taskana-data/src/main/java/pro/taskana/sampledata/SampleDataProvider.java b/lib/taskana-data/src/main/java/pro/taskana/sampledata/SampleDataProvider.java index ab3f8060f..e4293340a 100644 --- a/lib/taskana-data/src/main/java/pro/taskana/sampledata/SampleDataProvider.java +++ b/lib/taskana-data/src/main/java/pro/taskana/sampledata/SampleDataProvider.java @@ -2,8 +2,6 @@ package pro.taskana.sampledata; import java.util.stream.Stream; -import org.apache.ibatis.jdbc.ScriptRunner; - /** * Provides a sample data set. */ @@ -11,37 +9,51 @@ public final class SampleDataProvider { private static final String CLEAR_HISTORY_EVENTS = "/sql/clear/clear-history-events.sql"; private static final String HISTORY_EVENT = "/sql/sample-data/history-event.sql"; - private static final String CHECK_HISTORY_EVENT_EXIST = "/sql/sample-data/check-history-event-exist.sql"; - private static final String TASK = "/sql/sample-data/task.sql"; - private static final String WORKBASKET = "/sql/sample-data/workbasket.sql"; - private static final String DISTRIBUTION_TARGETS = "/sql/sample-data/distribution-targets.sql"; - private static final String WORKBASKET_ACCESS_LIST = "/sql/sample-data/workbasket-access-list.sql"; - private static final String CLASSIFICATION = "/sql/sample-data/classification.sql"; - private static final String OBJECT_REFERENCE = "/sql/sample-data/object-reference.sql"; - private static final String ATTACHMENT = "/sql/sample-data/attachment.sql"; + private static final String SAMPLE_TASK = "/sql/sample-data/task.sql"; + private static final String SAMPLE_WORKBASKET = "/sql/sample-data/workbasket.sql"; + private static final String SAMPLE_DISTRIBUTION_TARGETS = "/sql/sample-data/distribution-targets.sql"; + private static final String SAMPLE_WORKBASKET_ACCESS_LIST = "/sql/sample-data/workbasket-access-list.sql"; + private static final String SAMPLE_CLASSIFICATION = "/sql/sample-data/classification.sql"; + private static final String SAMPLE_OBJECT_REFERENCE = "/sql/sample-data/object-reference.sql"; + private static final String SAMPLE_ATTACHMENT = "/sql/sample-data/attachment.sql"; + + static final String TASK = "/sql/test-data/task.sql"; + static final String WORKBASKET = "/sql/test-data/workbasket.sql"; + static final String DISTRIBUTION_TARGETS = "/sql/test-data/distribution-targets.sql"; + static final String WORKBASKET_ACCESS_LIST = "/sql/test-data/workbasket-access-list.sql"; + static final String CLASSIFICATION = "/sql/test-data/classification.sql"; + static final String OBJECT_REFERENCE = "/sql/test-data/object-reference.sql"; + static final String ATTACHMENT = "/sql/test-data/attachment.sql"; + + static final String MONITOR_SAMPLE_DATA = "/sql/monitor-data/monitor-sample-data.sql"; private SampleDataProvider() { } - static Stream getScripts() { + static Stream getDefaultScripts() { return Stream.of( - WORKBASKET, DISTRIBUTION_TARGETS, CLASSIFICATION, TASK, ATTACHMENT, WORKBASKET_ACCESS_LIST, - OBJECT_REFERENCE); + SAMPLE_WORKBASKET, SAMPLE_DISTRIBUTION_TARGETS, SAMPLE_CLASSIFICATION, SAMPLE_TASK, SAMPLE_ATTACHMENT, + SAMPLE_WORKBASKET_ACCESS_LIST, + SAMPLE_OBJECT_REFERENCE); } static Stream getScriptsWithEvents() { - return Stream.concat(getScripts(), Stream.of(CLEAR_HISTORY_EVENTS, HISTORY_EVENT)); + return Stream.concat(getDefaultScripts(), Stream.of(CLEAR_HISTORY_EVENTS, HISTORY_EVENT)); } - public static Stream getDataProvider(ScriptRunner runner) { + static Stream getTestDataScripts() { + return Stream.of( + CLASSIFICATION, + WORKBASKET, + TASK, + WORKBASKET_ACCESS_LIST, + DISTRIBUTION_TARGETS, + OBJECT_REFERENCE, + ATTACHMENT); + } - try { - //TODO find a better method of testing if a table exists - runner.runScript(SampleDataGenerator.getScriptBufferedStream(CHECK_HISTORY_EVENT_EXIST)); - return SampleDataProvider.getScriptsWithEvents(); - } catch (Exception e) { - return SampleDataProvider.getScripts(); - } + static Stream getMonitorDataScripts() { + return Stream.of(MONITOR_SAMPLE_DATA); } } diff --git a/lib/taskana-core/src/test/resources/sql/monitor-sample-data.sql b/lib/taskana-data/src/main/resources/sql/monitor-data/monitor-sample-data.sql similarity index 100% rename from lib/taskana-core/src/test/resources/sql/monitor-sample-data.sql rename to lib/taskana-data/src/main/resources/sql/monitor-data/monitor-sample-data.sql diff --git a/lib/taskana-core/src/test/resources/sql/attachment.sql b/lib/taskana-data/src/main/resources/sql/test-data/attachment.sql similarity index 100% rename from lib/taskana-core/src/test/resources/sql/attachment.sql rename to lib/taskana-data/src/main/resources/sql/test-data/attachment.sql diff --git a/lib/taskana-core/src/test/resources/sql/classification.sql b/lib/taskana-data/src/main/resources/sql/test-data/classification.sql similarity index 100% rename from lib/taskana-core/src/test/resources/sql/classification.sql rename to lib/taskana-data/src/main/resources/sql/test-data/classification.sql diff --git a/lib/taskana-core/src/test/resources/sql/distribution-targets.sql b/lib/taskana-data/src/main/resources/sql/test-data/distribution-targets.sql similarity index 100% rename from lib/taskana-core/src/test/resources/sql/distribution-targets.sql rename to lib/taskana-data/src/main/resources/sql/test-data/distribution-targets.sql diff --git a/lib/taskana-core/src/test/resources/sql/object-reference.sql b/lib/taskana-data/src/main/resources/sql/test-data/object-reference.sql similarity index 100% rename from lib/taskana-core/src/test/resources/sql/object-reference.sql rename to lib/taskana-data/src/main/resources/sql/test-data/object-reference.sql diff --git a/lib/taskana-core/src/test/resources/sql/task.sql b/lib/taskana-data/src/main/resources/sql/test-data/task.sql similarity index 100% rename from lib/taskana-core/src/test/resources/sql/task.sql rename to lib/taskana-data/src/main/resources/sql/test-data/task.sql diff --git a/lib/taskana-core/src/test/resources/sql/workbasket-access-list.sql b/lib/taskana-data/src/main/resources/sql/test-data/workbasket-access-list.sql similarity index 100% rename from lib/taskana-core/src/test/resources/sql/workbasket-access-list.sql rename to lib/taskana-data/src/main/resources/sql/test-data/workbasket-access-list.sql diff --git a/lib/taskana-core/src/test/resources/sql/workbasket.sql b/lib/taskana-data/src/main/resources/sql/test-data/workbasket.sql similarity index 100% rename from lib/taskana-core/src/test/resources/sql/workbasket.sql rename to lib/taskana-data/src/main/resources/sql/test-data/workbasket.sql diff --git a/lib/taskana-data/src/test/java/pro/taskana/sampledata/SampleDataGeneratorTest.java b/lib/taskana-data/src/test/java/pro/taskana/sampledata/SampleDataGeneratorTest.java index b35ab869d..72c909b7b 100644 --- a/lib/taskana-data/src/test/java/pro/taskana/sampledata/SampleDataGeneratorTest.java +++ b/lib/taskana-data/src/test/java/pro/taskana/sampledata/SampleDataGeneratorTest.java @@ -1,8 +1,8 @@ package pro.taskana.sampledata; import static org.hamcrest.MatcherAssert.assertThat; -import static pro.taskana.sampledata.SampleDataGenerator.DATE_TIME_FORMATTER; -import static pro.taskana.sampledata.SampleDataGenerator.RELATIVE_DATE_PATTERN; +import static pro.taskana.sampledata.SQLReplacer.DATE_TIME_FORMATTER; +import static pro.taskana.sampledata.SQLReplacer.RELATIVE_DATE_PATTERN; import java.time.LocalDateTime; import java.util.regex.Matcher; @@ -18,20 +18,20 @@ class SampleDataGeneratorTest { @Test void getScriptsNotNull() { - Assertions.assertNotNull(SampleDataProvider.getScripts()); + Assertions.assertNotNull(SampleDataProvider.getDefaultScripts()); Assertions.assertNotNull(SampleDataProvider.getScriptsWithEvents()); } @Test void getScriptsNotEmpty() { - Assertions.assertTrue(SampleDataProvider.getScripts().count() > 0); + Assertions.assertTrue(SampleDataProvider.getDefaultScripts().count() > 0); Assertions.assertTrue(SampleDataProvider.getScriptsWithEvents().count() > 0); } @Test void getScriptsFileExists() { - SampleDataProvider.getScripts() - .map(SampleDataGenerator::getScriptBufferedStream) + SampleDataProvider.getDefaultScripts() + .map(SQLReplacer::getScriptBufferedStream) .forEach(Assertions::assertNotNull); } @@ -39,7 +39,7 @@ class SampleDataGeneratorTest { void replaceRelativeTimeFunctionSameDate() { LocalDateTime now = LocalDateTime.now(); String dateFormatted = now.format(DATE_TIME_FORMATTER); - String sqlStringReplaced = SampleDataGenerator.replaceDatePlaceholder(now, + String sqlStringReplaced = SQLReplacer.replaceDatePlaceholder(now, "... RELATIVE_DATE(0) ..."); assertThat(sqlStringReplaced, CoreMatchers.containsString(dateFormatted)); } @@ -70,7 +70,7 @@ class SampleDataGeneratorTest { void replaceRelativeTimeFunctionPosDate() { LocalDateTime now = LocalDateTime.now(); String dateFormatted = now.plusDays(5).format(DATE_TIME_FORMATTER); - String sqlStringReplaced = SampleDataGenerator.replaceDatePlaceholder(now, + String sqlStringReplaced = SQLReplacer.replaceDatePlaceholder(now, "... RELATIVE_DATE(5) ..."); assertThat(sqlStringReplaced, CoreMatchers.containsString(dateFormatted)); } @@ -79,7 +79,7 @@ class SampleDataGeneratorTest { void replaceRelativeTimeFunctionNegDate() { LocalDateTime now = LocalDateTime.now(); String dateFormatted = now.plusDays(-10).format(DATE_TIME_FORMATTER); - String sqlStringReplaced = SampleDataGenerator.replaceDatePlaceholder(now, + String sqlStringReplaced = SQLReplacer.replaceDatePlaceholder(now, "... RELATIVE_DATE(-10) ..."); assertThat(sqlStringReplaced, CoreMatchers.containsString(dateFormatted)); } diff --git a/rest/taskana-rest-spring-example-common/src/test/java/pro/taskana/jobs/AsyncUpdateJobIntTest.java b/rest/taskana-rest-spring-example-common/src/test/java/pro/taskana/jobs/AsyncUpdateJobIntTest.java index b402e0df3..ffb3990c3 100644 --- a/rest/taskana-rest-spring-example-common/src/test/java/pro/taskana/jobs/AsyncUpdateJobIntTest.java +++ b/rest/taskana-rest-spring-example-common/src/test/java/pro/taskana/jobs/AsyncUpdateJobIntTest.java @@ -132,12 +132,12 @@ class AsyncUpdateJobIntTest { "TKI:000000000000000000000000000000000101", "TKI:000000000000000000000000000000000102", "TKI:000000000000000000000000000000000103")); for (String taskId : affectedTasks) { - verifyTaskIsModifiedAfter(taskId, before); + verifyTaskIsModifiedAfterOrEquals(taskId, before); } } - private void verifyTaskIsModifiedAfter(String taskId, Instant before) + private void verifyTaskIsModifiedAfterOrEquals(String taskId, Instant before) throws InvalidArgumentException { ResponseEntity taskResponse = template.exchange( @@ -149,7 +149,9 @@ class AsyncUpdateJobIntTest { TaskResource taskResource = taskResponse.getBody(); Task task = taskResourceAssembler.toModel(taskResource); - assertFalse("Task " + task.getId() + " has not been refreshed.", before.isAfter(task.getModified())); + Instant modified = task.getModified(); + boolean isAfterOrEquals = before.isAfter(modified) || before.equals(modified); + assertFalse("Task " + task.getId() + " has not been refreshed.", isAfterOrEquals); } }