-
Notifications
You must be signed in to change notification settings - Fork 16
Feature/new cli library #154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
6717057
Failing test to catch and reproduce #143
pesse 038981f
Merge branch 'develop' into feature/new_cli_library
pesse b21f651
Unit-Test to simulate passing all parameters that should be known
pesse ce849fc
Initial implementation of Picocli usage
pesse 5520562
Some more tests around FileMapping
pesse f9c4cf7
New RunAction which does the logic based on RunCommandConfig
pesse d8cbce2
RunAction tested and functional so far
pesse 3b5e168
Include RunAction into RunCommand
pesse 60997d7
New entry point for Picocli
pesse d13ae5b
Extract functionality to interface
pesse 5e86b01
Adapt tests to IRunCommand and implement necessary functionality
pesse 00f3f5f
Change VersionCommand to Picocli
pesse 2ce4e91
Change ReportersCommand to Picocli
pesse b88d5c5
Fix arity for mapping options and prevent NPE
pesse c80dc8c
Refactor RunCommandTest to cover new approach
pesse 8eec2cb
Implement rules for printToScreen Reporters: Only one can go to screen
pesse ded39d3
Implemented new Picocli help
pesse 6922e52
Removed some now unnecessary stuff
pesse 5aa4c1d
We don't need the old RunCommand anymore, time to get rid of it
pesse 60fcfaf
Improve help and help-tests
pesse a3608b5
Refactor: Remove unnecessary logic
pesse 09bf357
Refactor: extract ReporterConfig -> ReporterOption conversion
pesse 1b65b51
Refactor: getCommand() no longer needed
pesse 77fd752
Refactor: Include only left check-functionality
pesse e443e3c
Refactor: Cleanup ReporterManager a bit
pesse 0bdca7d
Get rid of JCommander dependency
pesse ae0e9c4
Move ConnectionString description to main Utplsql-Command
pesse f47c0de
Fix Typo
pesse bb18ea1
Some Refactorings and make things final
pesse 1a984ff
Merge branch 'develop' into feature/new_cli_library
pesse 81e0953
Reformatting
pesse a8acbb9
Add `-h` option to all commands and cover it with tests
pesse 10bef7b
Adjust documentation to reflect parameter changes
pesse File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
New RunAction which does the logic based on RunCommandConfig
- Loading branch information
commit f9c4cf744e0cd13a325c1eead9dcb9326b377ee4
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,283 @@ | ||
| package org.utplsql.cli; | ||
|
|
||
| import com.beust.jcommander.Parameter; | ||
| import com.beust.jcommander.Parameters; | ||
| import com.zaxxer.hikari.HikariDataSource; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
| import org.utplsql.api.*; | ||
| import org.utplsql.api.compatibility.CompatibilityProxy; | ||
| import org.utplsql.api.compatibility.OptionalFeatures; | ||
| import org.utplsql.api.db.DefaultDatabaseInformation; | ||
| import org.utplsql.api.exception.DatabaseNotCompatibleException; | ||
| import org.utplsql.api.exception.OracleCreateStatmenetStuckException; | ||
| import org.utplsql.api.exception.SomeTestsFailedException; | ||
| import org.utplsql.api.exception.UtPLSQLNotInstalledException; | ||
| import org.utplsql.api.reporter.Reporter; | ||
| import org.utplsql.api.reporter.ReporterFactory; | ||
| import org.utplsql.cli.config.FileMapperConfig; | ||
| import org.utplsql.cli.config.RunCommandConfig; | ||
| import org.utplsql.cli.exception.DatabaseConnectionFailed; | ||
| import org.utplsql.cli.exception.ReporterTimeoutException; | ||
| import org.utplsql.cli.log.StringBlockFormatter; | ||
|
|
||
| import javax.sql.DataSource; | ||
| import javax.xml.crypto.dsig.keyinfo.KeyValue; | ||
| import java.io.File; | ||
| import java.sql.Connection; | ||
| import java.sql.SQLException; | ||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import java.util.concurrent.*; | ||
|
|
||
| /** | ||
| * Starts a test-runner and gathers the results based on the given Configuration | ||
| * | ||
| * @author pesse | ||
| */ | ||
| public class RunAction { | ||
|
|
||
| private static final Logger logger = LoggerFactory.getLogger(RunAction.class); | ||
|
|
||
| private RunCommandConfig config; | ||
|
|
||
| private CompatibilityProxy compatibilityProxy; | ||
| private ReporterFactory reporterFactory; | ||
| private ReporterManager reporterManager; | ||
|
|
||
| public RunAction( RunCommandConfig config ) { | ||
| this.config = config; | ||
| } | ||
|
|
||
| void init() { | ||
| LoggerConfiguration.configure(config.getLogConfigLevel()); | ||
| } | ||
|
|
||
| public int doRun() throws OracleCreateStatmenetStuckException { | ||
| init(); | ||
| outputMainInformation(); | ||
|
|
||
| HikariDataSource dataSource = null; | ||
| int returnCode = 0; | ||
| try { | ||
|
|
||
| final List<Reporter> reporterList; | ||
|
|
||
| dataSource = (HikariDataSource) DataSourceProvider.getDataSource(config.getConnectString(), getReporterManager().getNumberOfReporters() + 2); | ||
|
|
||
| initDatabase(dataSource); | ||
| reporterList = initReporters(dataSource); | ||
|
|
||
| checkForCompatibility(compatibilityProxy.getUtPlsqlVersion()); | ||
|
|
||
| ExecutorService executorService = Executors.newFixedThreadPool(1 + reporterList.size()); | ||
|
|
||
| // Run tests. | ||
| Future<Boolean> future = executorService.submit(new RunTestRunnerTask(dataSource, newTestRunner(reporterList), config.isDbmsOutput())); | ||
|
|
||
| // Gather each reporter results on a separate thread. | ||
| getReporterManager().startReporterGatherers(executorService, dataSource); | ||
|
|
||
| try { | ||
| future.get(config.getTimeoutInMinutes(), TimeUnit.MINUTES); | ||
| } catch (TimeoutException e) { | ||
| executorService.shutdownNow(); | ||
| throw new ReporterTimeoutException(config.getTimeoutInMinutes()); | ||
| } catch (ExecutionException e) { | ||
| if (e.getCause() instanceof SomeTestsFailedException) { | ||
| returnCode = config.getFailureExitCode(); | ||
| } else { | ||
| executorService.shutdownNow(); | ||
| throw e.getCause(); | ||
| } | ||
| } catch (InterruptedException e) { | ||
| executorService.shutdownNow(); | ||
| throw e; | ||
| } | ||
| finally { | ||
| executorService.shutdown(); | ||
| if (!executorService.awaitTermination(config.getTimeoutInMinutes(), TimeUnit.MINUTES)) { | ||
| throw new ReporterTimeoutException(config.getTimeoutInMinutes()); | ||
| } | ||
| } | ||
|
|
||
| logger.info("--------------------------------------"); | ||
| logger.info("All tests done."); | ||
| } catch ( OracleCreateStatmenetStuckException e ) { | ||
| throw e; | ||
| } catch ( DatabaseNotCompatibleException | UtPLSQLNotInstalledException | DatabaseConnectionFailed | ReporterTimeoutException e ) { | ||
| System.out.println(e.getMessage()); | ||
| returnCode = Cli.DEFAULT_ERROR_CODE; | ||
| } catch (Throwable e) { | ||
| e.printStackTrace(); | ||
| returnCode = Cli.DEFAULT_ERROR_CODE; | ||
| } finally { | ||
| if ( dataSource != null ) | ||
| dataSource.close(); | ||
| } | ||
| return returnCode; | ||
| } | ||
|
|
||
| public int run() { | ||
| for ( int i = 1; i<5; i++ ) { | ||
| try { | ||
| return doRun(); | ||
| } catch (OracleCreateStatmenetStuckException e) { | ||
| logger.warn("WARNING: Caught Oracle stuck during creation of Runner-Statement. Retrying ({})", i); | ||
| } | ||
| } | ||
|
|
||
| return Cli.DEFAULT_ERROR_CODE; | ||
| } | ||
|
|
||
| private void checkForCompatibility( Version utPlSqlVersion ) { | ||
| if (!OptionalFeatures.FAIL_ON_ERROR.isAvailableFor(utPlSqlVersion) && config.getFailureExitCode() != null ) { | ||
| System.out.println("You specified option `--failure-exit-code` but your database framework version (" + | ||
| utPlSqlVersion.getNormalizedString() + ") is not able to " + | ||
| "redirect failureCodes. Please upgrade to a newer version if you want to use that feature."); | ||
| } | ||
|
|
||
| if ( !OptionalFeatures.RANDOM_EXECUTION_ORDER.isAvailableFor(utPlSqlVersion) && config.isRandomTestOrder() ) { | ||
| System.out.println("You specified option `-random` but your database framework version (" + | ||
| utPlSqlVersion.getNormalizedString() + ") is not able to " + | ||
| "redirect failureCodes. Please upgrade to a newer version if you want to use that feature."); | ||
| } | ||
|
|
||
| if ( !OptionalFeatures.RANDOM_EXECUTION_ORDER.isAvailableFor(utPlSqlVersion) && config.getRandomTestOrderSeed() != null ) { | ||
| System.out.println("You specified option `-seed` but your database framework version (" + | ||
| utPlSqlVersion.getNormalizedString() + ") is not able to " + | ||
| "redirect failureCodes. Please upgrade to a newer version if you want to use that feature."); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| TestRunner newTestRunner( List<Reporter> reporterList) { | ||
|
|
||
| final File baseDir = new File("").getAbsoluteFile(); | ||
|
|
||
| return new TestRunner() | ||
| .addPathList(Arrays.asList(config.getSuitePaths())) | ||
| .addReporterList(reporterList) | ||
| .sourceMappingOptions(getFileMapperOptionsByParamListItem(config.getSourceMapping(), baseDir)) | ||
| .testMappingOptions(getFileMapperOptionsByParamListItem(config.getTestMapping(), baseDir)) | ||
| .colorConsole(config.isOutputAnsiColor()) | ||
| .failOnErrors(true) | ||
| .skipCompatibilityCheck(config.isSkipCompatibilityCheck()) | ||
| .includeObjects(Arrays.asList(config.getIncludePackages())) | ||
| .excludeObjects(Arrays.asList(config.getExcludePackages())) | ||
| .randomTestOrder(config.isRandomTestOrder()) | ||
| .randomTestOrderSeed(config.getRandomTestOrderSeed()); | ||
| } | ||
|
|
||
| private void outputMainInformation() { | ||
|
|
||
| StringBlockFormatter formatter = new StringBlockFormatter("utPLSQL cli"); | ||
| formatter.appendLine(CliVersionInfo.getInfo()); | ||
| formatter.appendLine(JavaApiVersionInfo.getInfo()); | ||
| formatter.appendLine("Java-Version: " + System.getProperty("java.version")); | ||
| formatter.appendLine("ORACLE_HOME: " + EnvironmentVariableUtil.getEnvValue("ORACLE_HOME")); | ||
| formatter.appendLine("NLS_LANG: " + EnvironmentVariableUtil.getEnvValue("NLS_LANG")); | ||
| formatter.appendLine(""); | ||
| formatter.appendLine("Thanks for testing!"); | ||
|
|
||
| logger.info(formatter.toString()); | ||
| logger.info(""); | ||
| } | ||
|
|
||
| private void initDatabase(DataSource dataSource) throws SQLException { | ||
| try (Connection conn = dataSource.getConnection()) { | ||
|
|
||
| // Check if orai18n exists if database version is 11g | ||
| RunCommandChecker.checkOracleI18nExists(conn); | ||
|
|
||
| // First of all do a compatibility check and fail-fast | ||
| compatibilityProxy = checkFrameworkCompatibility(conn); | ||
|
|
||
| logger.info("Successfully connected to database. UtPLSQL core: {}", compatibilityProxy.getVersionDescription()); | ||
| logger.info("Oracle-Version: {}", new DefaultDatabaseInformation().getOracleVersion(conn)); | ||
| } | ||
| catch (SQLException e) { | ||
| if (e.getErrorCode() == 1017 || e.getErrorCode() == 12514) { | ||
| throw new DatabaseConnectionFailed(e); | ||
| } else { | ||
| throw e; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private List<Reporter> initReporters(DataSource dataSource) throws SQLException { | ||
| try (Connection conn = dataSource.getConnection()) { | ||
| reporterFactory = ReporterFactoryProvider.createReporterFactory(compatibilityProxy); | ||
| return getReporterManager().initReporters(conn, reporterFactory, compatibilityProxy); | ||
| } | ||
| } | ||
|
|
||
| /** Returns FileMapperOptions for the first item of a given param list in a baseDir | ||
| * | ||
| * @param fileMapperConfig | ||
| * @param baseDir | ||
| * @return FileMapperOptions or null | ||
| */ | ||
| private FileMapperOptions getFileMapperOptionsByParamListItem(FileMapperConfig fileMapperConfig, File baseDir ) | ||
| { | ||
| if (fileMapperConfig != null) { | ||
| String sourcePath = fileMapperConfig.getPath(); | ||
|
|
||
| logger.debug("BaseDir: {}", baseDir); | ||
| logger.debug("SourcePath: {}", sourcePath); | ||
|
|
||
| List<String> files = new FileWalker().getFileList(baseDir, sourcePath); | ||
|
|
||
| logger.debug("Getting FileMapperOptions - Files: "); | ||
| files.forEach(logger::debug); | ||
|
|
||
| FileMapperOptions options = new FileMapperOptions(files); | ||
| options.setObjectOwner(fileMapperConfig.getOwner()); | ||
| options.setRegexPattern(fileMapperConfig.getRegexExpression()); | ||
| options.setTypeSubExpression(fileMapperConfig.getTypeSubexpression()); | ||
| options.setOwnerSubExpression(fileMapperConfig.getOwnerSubexpression()); | ||
| options.setNameSubExpression(fileMapperConfig.getNameSubexpression()); | ||
|
|
||
| List<KeyValuePair> mappings = new ArrayList<>(); | ||
| fileMapperConfig.getTypeMapping().forEach((k, v) -> mappings.add(new KeyValuePair(v, k))); | ||
| options.setTypeMappings(mappings); | ||
|
|
||
| return options; | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** Checks whether cli is compatible with the database framework | ||
| * | ||
| * @param conn Active Connection | ||
| * @throws SQLException | ||
| */ | ||
| private CompatibilityProxy checkFrameworkCompatibility(Connection conn) throws SQLException { | ||
|
|
||
| CompatibilityProxy proxy = new CompatibilityProxy(conn, config.isSkipCompatibilityCheck()); | ||
|
|
||
| if ( !config.isSkipCompatibilityCheck() ) { | ||
| proxy.failOnNotCompatible(); | ||
| } | ||
| else { | ||
|
pesse marked this conversation as resolved.
Outdated
|
||
| System.out.println("Skipping Compatibility check with framework version, expecting the latest version " + | ||
| "to be installed in database"); | ||
| } | ||
|
|
||
| return proxy; | ||
| } | ||
|
|
||
| private ReporterManager getReporterManager() { | ||
| ArrayList<String> reporterParams = new ArrayList<>(); | ||
| if ( reporterManager == null ) | ||
| reporterManager = new ReporterManager(reporterParams); | ||
|
|
||
| return reporterManager; | ||
| } | ||
|
|
||
| List<ReporterOptions> getReporterOptionsList() { | ||
| return getReporterManager().getReporterOptionsList(); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please move it to initialization.