diff --git a/pom.xml b/pom.xml
index 861937c..7e9e21c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,6 +67,22 @@
jaxb-api
2.3.0
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+ 2.9.5
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.9.5
+
+
+ org.apache.commons
+ commons-lang3
+ 3.7
+ test
+
diff --git a/src/main/java/org/utplsql/cli/RunCommand.java b/src/main/java/org/utplsql/cli/RunCommand.java
index 01ecdbd..45cc0a4 100644
--- a/src/main/java/org/utplsql/cli/RunCommand.java
+++ b/src/main/java/org/utplsql/cli/RunCommand.java
@@ -10,8 +10,11 @@
import org.utplsql.api.exception.DatabaseNotCompatibleException;
import org.utplsql.api.exception.SomeTestsFailedException;
import org.utplsql.api.exception.UtPLSQLNotInstalledException;
+import org.utplsql.api.reporter.CoreReporters;
import org.utplsql.api.reporter.Reporter;
import org.utplsql.api.reporter.ReporterFactory;
+import org.utplsql.cli.config.ReporterConfig;
+import org.utplsql.cli.config.TestRunnerConfig;
import org.utplsql.cli.exception.DatabaseConnectionFailed;
import javax.sql.DataSource;
@@ -36,10 +39,10 @@ public class RunCommand implements ICommand {
@Parameter(
required = true,
- converter = ConnectionInfo.ConnectionStringConverter.class,
+ //converter = ConnectionInfo.ConnectionStringConverter.class,
arity = 1,
description = ConnectionInfo.COMMANDLINE_PARAM_DESCRIPTION)
- private List connectionInfoList = new ArrayList<>();
+ private String connectionInfo = "";
@Parameter(
names = {"-p", "--path"},
@@ -100,12 +103,16 @@ public class RunCommand implements ICommand {
private String excludeObjects = null;
+ private ConnectionInfo connectionInfoObj;
private CompatibilityProxy compatibilityProxy;
private ReporterFactory reporterFactory;
private ReporterManager reporterManager;
public ConnectionInfo getConnectionInfo() {
- return connectionInfoList.get(0);
+ if ( connectionInfoObj == null )
+ connectionInfoObj = new ConnectionInfo(connectionInfo);
+
+ return connectionInfoObj;
}
public List getTestPaths() {
@@ -326,4 +333,81 @@ private ReporterManager getReporterManager() {
public List getReporterOptionsList() {
return getReporterManager().getReporterOptionsList();
}
+
+ private List getReporterConfigs() {
+ List reporterConfigs = new ArrayList<>(5);
+
+ String reporterName = null;
+ String outputFile = null;
+ Boolean forceToScreen = null;
+ for (String p : reporterParams) {
+ if (!p.startsWith("-")) {
+ if ( reporterName != null ) {
+ reporterConfigs.add(new ReporterConfig(reporterName, outputFile, forceToScreen));
+ reporterName = null;
+ outputFile = null;
+ forceToScreen = null;
+ }
+ reporterName = p;
+ }
+ else if (p.startsWith("-o="))
+ outputFile = p.substring(3);
+ else if (p.equals("-s"))
+ forceToScreen = true;
+ }
+
+ if ( reporterName != null )
+ reporterConfigs.add(new ReporterConfig(reporterName, outputFile, forceToScreen));
+
+ return reporterConfigs;
+ }
+
+ private String[] getSplitList( String delimitedList ) {
+ if ( delimitedList != null && !delimitedList.isEmpty() )
+ return delimitedList.split(",");
+ else
+ return null;
+ }
+
+ public TestRunnerConfig getConfig() {
+ final List reporterList;
+ List reporterOptionsList = new ArrayList<>();
+ ReporterOptions reporterOptions = null;
+
+ List reporterConfigs = getReporterConfigs();
+
+ // If no reporter parameters were passed, use default reporter.
+ if (reporterOptionsList.isEmpty()) {
+ reporterOptionsList.add(new ReporterOptions(CoreReporters.UT_DOCUMENTATION_REPORTER.name()));
+ }
+ final List testPaths = getTestPaths();
+
+ final File baseDir = new File("").getAbsoluteFile();
+ final FileMapperOptions[] sourceMappingOptions = {null};
+ final FileMapperOptions[] testMappingOptions = {null};
+
+ final int[] returnCode = {0};
+
+ sourceMappingOptions[0] = getFileMapperOptionsByParamListItem(this.sourcePathParams, baseDir);
+ testMappingOptions[0] = getFileMapperOptionsByParamListItem(this.testPathParams, baseDir);
+
+ String[] testPathArr = new String[testPaths.size()];
+ testPathArr = testPaths.toArray(testPathArr);
+
+ ReporterConfig[] reporterConfigArr = new ReporterConfig[reporterConfigs.size()];
+ reporterConfigArr = reporterConfigs.toArray(reporterConfigArr);
+
+ return new TestRunnerConfig(
+ connectionInfo,
+ testPathArr,
+ reporterConfigArr,
+ colorConsole,
+ failureExitCode,
+ skipCompatibilityCheck,
+ getSplitList(includeObjects),
+ getSplitList(excludeObjects),
+ null,
+ null
+ );
+ }
}
diff --git a/src/main/java/org/utplsql/cli/config/ConnectionConfig.java b/src/main/java/org/utplsql/cli/config/ConnectionConfig.java
new file mode 100644
index 0000000..ef0231e
--- /dev/null
+++ b/src/main/java/org/utplsql/cli/config/ConnectionConfig.java
@@ -0,0 +1,18 @@
+package org.utplsql.cli.config;
+
+import java.beans.ConstructorProperties;
+
+public class ConnectionConfig {
+
+ private final String connectString;
+
+ @ConstructorProperties({"connectString"})
+ public ConnectionConfig(String connectString) {
+ this.connectString = connectString;
+ }
+
+ public String getConnectString() {
+ return connectString;
+ }
+
+}
diff --git a/src/main/java/org/utplsql/cli/config/FileMapperConfig.java b/src/main/java/org/utplsql/cli/config/FileMapperConfig.java
new file mode 100644
index 0000000..ec0826e
--- /dev/null
+++ b/src/main/java/org/utplsql/cli/config/FileMapperConfig.java
@@ -0,0 +1,55 @@
+package org.utplsql.cli.config;
+
+import java.beans.ConstructorProperties;
+import java.util.HashMap;
+import java.util.Map;
+
+public class FileMapperConfig {
+
+ private final String path;
+ private final String owner;
+ private final String regexExpression;
+ private final Map typeMapping;
+ private final Integer ownerSubexpression;
+ private final Integer nameSubexpression;
+ private final Integer typeSubexpression;
+
+ @ConstructorProperties({"path", "owner", "regexExpression", "typeMapping", "ownerSubexpression", "nameSubexpression", "typeSubexpression"})
+ public FileMapperConfig(String path, String owner, String regexExpression, Map typeMapping, Integer ownerSubexpression, Integer nameSubexpression, Integer typeSubexpression) {
+ this.path = path;
+ this.owner = owner;
+ this.regexExpression = regexExpression;
+ this.typeMapping = typeMapping;
+ this.ownerSubexpression = ownerSubexpression;
+ this.nameSubexpression = nameSubexpression;
+ this.typeSubexpression = typeSubexpression;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getOwner() {
+ return owner;
+ }
+
+ public String getRegexExpression() {
+ return regexExpression;
+ }
+
+ public Map getTypeMapping() {
+ return typeMapping;
+ }
+
+ public Integer getOwnerSubexpression() {
+ return ownerSubexpression;
+ }
+
+ public Integer getNameSubexpression() {
+ return nameSubexpression;
+ }
+
+ public Integer getTypeSubexpression() {
+ return typeSubexpression;
+ }
+}
diff --git a/src/main/java/org/utplsql/cli/config/ReporterConfig.java b/src/main/java/org/utplsql/cli/config/ReporterConfig.java
new file mode 100644
index 0000000..8729848
--- /dev/null
+++ b/src/main/java/org/utplsql/cli/config/ReporterConfig.java
@@ -0,0 +1,29 @@
+package org.utplsql.cli.config;
+
+import java.beans.ConstructorProperties;
+
+public class ReporterConfig {
+
+ private final String name;
+ private final String output;
+ private boolean screen = false;
+
+ @ConstructorProperties({"name", "output", "screen"})
+ public ReporterConfig( String name, String output, Boolean screen ) {
+ this.name = name;
+ this.output = output;
+ if ( screen != null ) this.screen = screen;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getOutput() {
+ return output;
+ }
+
+ public boolean isScreen() {
+ return screen;
+ }
+}
diff --git a/src/main/java/org/utplsql/cli/config/TestRunnerConfig.java b/src/main/java/org/utplsql/cli/config/TestRunnerConfig.java
new file mode 100644
index 0000000..18f95b8
--- /dev/null
+++ b/src/main/java/org/utplsql/cli/config/TestRunnerConfig.java
@@ -0,0 +1,67 @@
+package org.utplsql.cli.config;
+
+
+import java.beans.ConstructorProperties;
+
+public class TestRunnerConfig extends ConnectionConfig {
+
+ private final String[] suitePaths;
+ private final ReporterConfig[] reporters;
+ private boolean outputAnsiColor = false;
+ private final Integer failureExitCode;
+ private boolean skipCompatibilityCheck = false;
+ private final String[] includePackages;
+ private final String[] excludePackages;
+ private final FileMapperConfig sourceMapping;
+ private final FileMapperConfig testMapping;
+
+ @ConstructorProperties({"connectString", "suitePaths", "reporters", "outputAnsiColor", "failureExitCode", "skipCompatibilityCheck", "includePackages", "excludePackages", "sourceMapping", "testMapping"})
+ public TestRunnerConfig(String connectString, String[] suitePaths, ReporterConfig[] reporters, boolean outputAnsiColor, Integer failureExitCode, boolean skipCompatibilityCheck, String[] includePackages, String[] excludePackages, FileMapperConfig sourceMapping, FileMapperConfig testMapping) {
+ super(connectString);
+ this.suitePaths = suitePaths;
+ this.reporters = reporters;
+ this.outputAnsiColor = outputAnsiColor;
+ this.failureExitCode = failureExitCode;
+ this.skipCompatibilityCheck = skipCompatibilityCheck;
+ this.includePackages = includePackages;
+ this.excludePackages = excludePackages;
+ this.sourceMapping = sourceMapping;
+ this.testMapping = testMapping;
+ }
+
+ public String[] getSuitePaths() {
+ return suitePaths;
+ }
+
+ public ReporterConfig[] getReporters() {
+ return reporters;
+ }
+
+ public boolean isOutputAnsiColor() {
+ return outputAnsiColor;
+ }
+
+ public Integer getFailureExitCode() {
+ return failureExitCode;
+ }
+
+ public boolean isSkipCompatibilityCheck() {
+ return skipCompatibilityCheck;
+ }
+
+ public String[] getIncludePackages() {
+ return includePackages;
+ }
+
+ public String[] getExcludePackages() {
+ return excludePackages;
+ }
+
+ public FileMapperConfig getSourceMapping() {
+ return sourceMapping;
+ }
+
+ public FileMapperConfig getTestMapping() {
+ return testMapping;
+ }
+}
diff --git a/src/test/java/org/utplsql/cli/YmlConfigTest.java b/src/test/java/org/utplsql/cli/YmlConfigTest.java
new file mode 100644
index 0000000..1271cbb
--- /dev/null
+++ b/src/test/java/org/utplsql/cli/YmlConfigTest.java
@@ -0,0 +1,64 @@
+package org.utplsql.cli;
+
+import com.beust.jcommander.JCommander;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.junit.jupiter.api.Test;
+import org.utplsql.cli.config.TestRunnerConfig;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class YmlConfigTest {
+
+ @Test
+ public void letsPlayAround() throws IOException {
+
+ ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
+
+ String testConfigFile = "src/test/resources/test-config.yml";
+
+ TestRunnerConfig config = mapper.readValue(new File(testConfigFile), TestRunnerConfig.class);
+
+ System.out.println(ReflectionToStringBuilder.toString(config, ToStringStyle.MULTI_LINE_STYLE));
+ }
+
+ @Test
+ public void configTest() {
+ JCommander jc = new JCommander();
+ jc.setProgramName("utplsql");
+
+ CommandProvider cmdProvider = new CommandProvider();
+
+ cmdProvider.commands().forEach(cmd -> jc.addCommand(cmd.getCommand(), cmd));
+
+ jc.parse("run", TestHelper.getConnectionString(),
+ "-f=ut_coverage_html_reporter", "-o=test.html",
+ "-f=ut_documentation_reporter", "-s",
+ "-exclude=app.award_bonus,app.betwnstr");
+
+ RunCommand cmd = (RunCommand) cmdProvider.getCommand(jc.getParsedCommand());
+
+ TestRunnerConfig config = cmd.getConfig();
+
+ assertEquals(TestHelper.getConnectionString(), config.getConnectString());
+ assertEquals(2, config.getReporters().length);
+ assertEquals("ut_coverage_html_reporter", config.getReporters()[0].getName());
+ assertEquals("test.html", config.getReporters()[0].getOutput());
+ assertEquals(false, config.getReporters()[0].isScreen());
+ assertEquals("ut_documentation_reporter", config.getReporters()[1].getName());
+ assertNull(config.getReporters()[1].getOutput());
+ assertEquals(true, config.getReporters()[1].isScreen());
+ assertEquals("app.award_bonus", config.getExcludePackages()[0]);
+ assertEquals("app.betwnstr", config.getExcludePackages()[1]);
+
+ }
+
+
+}
diff --git a/src/test/resources/test b/src/test/resources/test
new file mode 100644
index 0000000..abf95a1
--- /dev/null
+++ b/src/test/resources/test
@@ -0,0 +1,26 @@
+utPLSQL-cli/bin/utplsql run test_runner/pass@db_url \
+ -p=hr,app \
+ -f=ut_documentation_reporter \
+ -f=ut_coverage_html_reporter \
+ -o=coverage.html \
+ -f=ut_sonar_test_reporter \
+ -o=sonar.txt \
+ -s \
+ -c \
+ --failure-exit-code=2 \
+ -scc \
+ -include=app.betwnstr,mypackage \
+ -exclude=mypackage.blugg,stuff \
+ -source_path=sources \
+ -regex_expression="/(\w+)/(\w+)/(\w+)\..{3}$" \
+ -type_mapping="packages_bodies=PACKAGE BODY/types_bodies=TYPE BODY/triggers=TRIGGER/procedures=PROCEDURE/functions=FUNCTION" \
+ -owner_subexpression=2 \
+ -name_subexpression=3 \
+ -type_subexpression=4 \
+ -test_path=tests -regex_expression="/(\w+)/(\w+)/(\w+)\..{3}$" \
+ -type_mapping="body=PACKAGE BODY/type_body=TYPE BODY/trigger=TRIGGER" \
+ -owner_subexpression=2 \
+ -name_subexpression=3 \
+ -type_subexpression=4 \
+ -f=ut_coverage_html_reporter -o=coverage.html \
+ -f=ut_sonar_test_reporter -o=test_results.xml
\ No newline at end of file
diff --git a/src/test/resources/test-config.yml b/src/test/resources/test-config.yml
new file mode 100644
index 0000000..f8afb4a
--- /dev/null
+++ b/src/test/resources/test-config.yml
@@ -0,0 +1,44 @@
+# utPLSQL cli Test-Config
+---
+connectString: app/app@localhost:1522/ORCLPDB1
+suitePaths:
+ - app.betwnstr
+ - app
+reporters:
+ - name: ut_documentation_reporter
+ - name: ut_coverage_html_reporter
+ output: coverage.html
+ - name: ut_sonar_test_reporter
+ output: sonar.txt
+ screen: true
+outputAnsiColor: true
+failureExitCode: 2
+skipCompatibilityCheck: true
+includePackages: [app.betwnstr, mypackage]
+excludePackages:
+ - mypackage.blubb
+ - stuff
+sourceMapping:
+ path: path/to/source
+ owner: app
+ regexExpression: /(\w+)/(\w+)/(\w+)\..{3}$
+ typeMapping:
+ packages_bodies: PACKAGE BODY
+ types_bodies: TYPE BODY
+ triggers: TRIGGER
+ procedures: PROCEDURE
+ functions: FUNCTION
+ ownerSubexpression: 1
+ nameSubexpression: 3
+ typeSubexpression: 2
+testMapping:
+ path: path/to/test
+ owner: app
+ regexExpression: /(\w+)/(\w+)/(\w+)\..{3}$
+ typeMapping:
+ body: PACKAGE BODY
+ type_body: TYPE BODY
+ trigger: TRIGGER
+ ownerSubexpression: 1
+ nameSubexpression: 3
+ typeSubexpression: 2
\ No newline at end of file