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