consoleAppender = new ConsoleAppender<>();
65 | consoleAppender.setEncoder(ple);
66 | consoleAppender.setContext(lc);
67 | consoleAppender.start();
68 |
69 | logger.detachAndStopAllAppenders();
70 | logger.setAdditive(false);
71 | logger.addAppender(consoleAppender);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build and test
2 |
3 | on:
4 | push:
5 |
6 | pull_request:
7 | branches: [ develop ]
8 |
9 | workflow_dispatch:
10 |
11 | repository_dispatch:
12 | types: [utPLSQL-build,utPLSQL-java-api-build]
13 |
14 | defaults:
15 | run:
16 | shell: bash
17 |
18 | jobs:
19 | build:
20 | name: Test on JDK ${{ matrix.jdk }} with utPLSQL ${{ matrix.utplsql_version }}
21 | runs-on: ubuntu-latest
22 | env:
23 | ORACLE_VERSION: "gvenzl/oracle-xe:18.4.0-slim"
24 | UTPLSQL_VERSION: ${{matrix.utplsql_version}}
25 | UTPLSQL_FILE: ${{matrix.utplsql_file}}
26 | ORACLE_PASSWORD: oracle
27 | DB_URL: "127.0.0.1:1521:XE"
28 | DB_USER: app
29 | DB_PASS: app
30 |
31 | strategy:
32 | fail-fast: false
33 | matrix:
34 | utplsql_version: ["v3.0.1","v3.0.2","v3.0.3","v3.0.4","v3.1.1","v3.1.2","v3.1.3","v3.1.6","v3.1.7","v3.1.8","v3.1.9","v3.1.10","v3.1.11","develop"]
35 | utplsql_file: ["utPLSQL"]
36 | jdk: ['8']
37 | include:
38 | - utplsql_version: "v3.0.0"
39 | jdk: '8'
40 | utplsql_file: "utPLSQLv3.0.0"
41 | services:
42 | oracle:
43 | image: gvenzl/oracle-xe:18.4.0-slim
44 | env:
45 | ORACLE_PASSWORD: oracle
46 | ports:
47 | - 1521:1521
48 | options: >-
49 | --health-cmd healthcheck.sh
50 | --health-interval 10s
51 | --health-timeout 5s
52 | --health-retries 10
53 | --name oracle
54 |
55 | steps:
56 | - uses: actions/checkout@v2
57 | with:
58 | fetch-depth: 0
59 | - uses: actions/setup-java@v2
60 | with:
61 | distribution: 'adopt'
62 | java-version: ${{matrix.jdk}}
63 |
64 | - name: Install utplsql
65 | run: .travis/install_utplsql.sh
66 |
67 | - name: Install demo project
68 | run: .travis/install_demo_project.sh
69 |
70 | - name: Build and Test
71 | run: mvn verify jar:jar appassembler:assemble
72 |
73 | slack-workflow-status:
74 | if: always()
75 | name: Post Workflow Status To Slack
76 | needs: [ build ]
77 | runs-on: ubuntu-latest
78 | steps:
79 | - name: Slack Workflow Notification
80 | uses: Gamesight/slack-workflow-status@master
81 | with:
82 | repo_token: ${{secrets.GITHUB_TOKEN}}
83 | slack_webhook_url: ${{secrets.SLACK_WEBHOOK_URL}}
84 | name: 'Github Actions[bot]'
85 | icon_url: 'https://octodex.github.com/images/mona-the-rivetertocat.png'
86 |
--------------------------------------------------------------------------------
/src/main/java/org/utplsql/cli/reporters/LocalAssetsCoverageHTMLReporter.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli.reporters;
2 |
3 | import org.utplsql.api.compatibility.CompatibilityProxy;
4 | import org.utplsql.api.reporter.CoverageHTMLReporter;
5 | import org.utplsql.api.reporter.Reporter;
6 | import org.utplsql.api.reporter.ReporterFactory;
7 | import org.utplsql.cli.ReporterOptions;
8 |
9 | import java.nio.file.Path;
10 | import java.nio.file.Paths;
11 | import java.sql.Connection;
12 | import java.sql.SQLException;
13 |
14 | /**
15 | * Simple replacement of the CoverageHTMLReporter which writes the necessary assets to a folder
16 | * named after the Output File's name.
17 | *
18 | * @author pesse
19 | */
20 | public class LocalAssetsCoverageHTMLReporter extends CoverageHTMLReporter implements ReporterOptionsAware {
21 |
22 | private ReporterOptions options;
23 |
24 | public LocalAssetsCoverageHTMLReporter(String selfType, Object[] attributes) {
25 | super(selfType, attributes);
26 | }
27 |
28 | @Override
29 | public Reporter init(Connection con, CompatibilityProxy compatibilityProxy, ReporterFactory reporterFactory) throws SQLException {
30 | super.init(con, compatibilityProxy, reporterFactory);
31 |
32 | if (hasOutputToFile()) {
33 | writeReportAssetsTo(getPhysicalAssetPath());
34 | }
35 |
36 | return this;
37 | }
38 |
39 | private String getNameOfOutputFile() {
40 | Path outputPath = Paths.get(options.getOutputFileName());
41 | return outputPath.getName(outputPath.getNameCount() - 1).toString();
42 | }
43 |
44 | private Path getPhysicalAssetPath() {
45 | Path outputPath = Paths.get(options.getOutputFileName());
46 | if (outputPath.getNameCount() > 1) {
47 | return outputPath.getParent().resolve(getAssetsPath());
48 | } else {
49 | return Paths.get(getAssetsPath());
50 | }
51 | }
52 |
53 | private void setAssetsPathFromOptions() {
54 | if (hasOutputToFile()) {
55 | setAssetsPath(getNameOfOutputFile() + "_assets/");
56 | }
57 | }
58 |
59 | private boolean hasOutputToFile() {
60 | return (options != null && options.outputToFile());
61 | }
62 |
63 | @Override
64 | public void setReporterOptions(ReporterOptions options) {
65 | this.options = options;
66 | setAssetsPathFromOptions();
67 | }
68 |
69 | @Override
70 | protected void setAttributes(Object[] attributes) {
71 | super.setAttributes(attributes);
72 | setAssetsPathFromOptions();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/org/utplsql/cli/RunTestRunnerTask.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.utplsql.api.DBHelper;
6 | import org.utplsql.api.TestRunner;
7 | import org.utplsql.api.exception.OracleCreateStatmenetStuckException;
8 | import org.utplsql.api.exception.SomeTestsFailedException;
9 |
10 | import javax.sql.DataSource;
11 | import java.sql.Connection;
12 | import java.sql.SQLException;
13 | import java.util.concurrent.Callable;
14 | import java.util.concurrent.Executors;
15 |
16 | /**
17 | * Runs the utPLSQL Test-Runner
18 | *
19 | * Takes care of its connection.
20 | * In case of an OracleCreateStatementStuckException it will abort the connection, otherwise close it.
21 | *
22 | * @author pesse
23 | */
24 | public class RunTestRunnerTask implements Callable {
25 |
26 | private static final Logger logger = LoggerFactory.getLogger(RunTestRunnerTask.class);
27 | private DataSource dataSource;
28 | private TestRunner testRunner;
29 | private boolean enableDmbsOutput;
30 |
31 | RunTestRunnerTask(DataSource dataSource, TestRunner testRunner, boolean enableDmbsOutput) {
32 | this.dataSource = dataSource;
33 | this.testRunner = testRunner;
34 | this.enableDmbsOutput = enableDmbsOutput;
35 | }
36 |
37 | @Override
38 | public Boolean call() throws Exception {
39 | Connection conn = null;
40 | try {
41 | conn = dataSource.getConnection();
42 | if (enableDmbsOutput) DBHelper.enableDBMSOutput(conn);
43 | logger.info("Running tests now.");
44 | logger.info("--------------------------------------");
45 | testRunner.run(conn);
46 | } catch (SomeTestsFailedException e) {
47 | throw e;
48 | } catch (OracleCreateStatmenetStuckException e) {
49 | try {
50 | conn.abort(Executors.newSingleThreadExecutor());
51 | conn = null;
52 | } catch (SQLException e1) {
53 | logger.error(e1.getMessage(), e1);
54 | }
55 | throw e;
56 | } catch (SQLException e) {
57 | System.out.println(e.getMessage());
58 | throw e;
59 | } finally {
60 | if (conn != null) {
61 | try {
62 | if (enableDmbsOutput) DBHelper.disableDBMSOutput(conn);
63 | conn.close();
64 | } catch (SQLException e) {
65 | logger.error(e.getMessage(), e);
66 | }
67 | }
68 | }
69 | return true;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/org/utplsql/cli/log/StringBlockFormatter.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli.log;
2 |
3 | public class StringBlockFormatter {
4 |
5 | private String headline;
6 | private final StringBuilder content = new StringBuilder();
7 |
8 | public StringBlockFormatter() {
9 | }
10 |
11 | public StringBlockFormatter(String headline) {
12 | setHeadline(headline);
13 | }
14 |
15 | public void setHeadline(String headline) {
16 | this.headline = headline;
17 | }
18 |
19 | public String getHeadline() {
20 | return headline;
21 | }
22 |
23 | public void append(CharSequence seq) {
24 | content.append(seq);
25 | }
26 |
27 | public void appendLine(CharSequence seq) {
28 | content.append(seq).append("\n");
29 | }
30 |
31 | private int getMaxLength(String[] lines) {
32 | int len = 0;
33 | for (String line : lines) {
34 | if (line.length() > len) {
35 | len = line.length();
36 | }
37 | }
38 |
39 | if (headline.length() > (len + 6)) {
40 | len = headline.length();
41 | }
42 |
43 | return len;
44 | }
45 |
46 | public static String getEncapsulatedLine(String line, int maxLength) {
47 | return String.format("# %-" + maxLength + "s #", line);
48 | }
49 |
50 | public static String getEncapsulatedHeadline(String headline, int maxLength) {
51 | String content = new String(new char[maxLength + 8]).replace("\0", "#");
52 | if (headline == null || headline.isEmpty()) {
53 | return content;
54 | }
55 |
56 | headline = " " + headline + " ";
57 | int start = (int) Math.floor(
58 | (float) content.length() / 2f
59 | - (float) headline.length() / 2f
60 | );
61 | int end = start + headline.length();
62 |
63 | return content.substring(0, start)
64 | + headline
65 | + content.substring(end);
66 | }
67 |
68 | public String toString() {
69 |
70 | String[] lines = content.toString().split("\n");
71 | int maxLen = getMaxLength(lines);
72 |
73 | StringBuilder sb = new StringBuilder();
74 |
75 | sb.append(getEncapsulatedHeadline(headline, maxLen)).append("\n");
76 | sb.append(getEncapsulatedLine("", maxLen)).append("\n");
77 | for (String line : lines) {
78 | sb.append(getEncapsulatedLine(line, maxLen)).append("\n");
79 | }
80 | sb.append(getEncapsulatedLine("", maxLen)).append("\n");
81 | sb.append(getEncapsulatedHeadline("", maxLen));
82 |
83 | return sb.toString();
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/org/utplsql/cli/LocaleInitializer.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.utplsql.api.EnvironmentVariableUtil;
6 |
7 | import java.util.Locale;
8 | import java.util.regex.Matcher;
9 | import java.util.regex.Pattern;
10 |
11 | /**
12 | * This class makes sure the java locale is set according to the environment variables LC_ALL and LANG
13 | * We experienced that, in some cases, the locale was not set as expected, therefore this class implements some clear
14 | * rules:
15 | * 1. If environment variable LC_ALL is set, we try to parse its content and set locale according to its value if valid
16 | * 2. If environment variable LANG is set, we try to parse its content and set locale according to its value if valid
17 | * 3. Otherwise we use default locale
18 | *
19 | * @author pesse
20 | */
21 | class LocaleInitializer {
22 |
23 | private static final Logger logger = LoggerFactory.getLogger(RunAction.class);
24 |
25 | private static final Pattern REGEX_LOCALE = Pattern.compile("^([a-zA-Z]+)[_-]([a-zA-Z]+)"); // We only need the very first part and are pretty forgiving in parsing
26 |
27 | /**
28 | * Sets the default locale according to the rules described above
29 | */
30 | static void initLocale() {
31 |
32 | boolean localeChanged = setDefaultLocale(EnvironmentVariableUtil.getEnvValue("LC_ALL"));
33 | if (!localeChanged) {
34 | localeChanged = setDefaultLocale(EnvironmentVariableUtil.getEnvValue("LANG"));
35 | }
36 | if ( !localeChanged ) {
37 | logger.debug("Java Locale not changed from LC_ALL or LANG environment variable");
38 | }
39 | }
40 |
41 | /**
42 | * Set the default locale from a given string like LC_ALL or LANG environment variable
43 | *
44 | * @param localeString Locale-string from LC_ALL or LANG, e.g "en_US.utf-8"
45 | * @return true if successful, false if not
46 | */
47 | private static boolean setDefaultLocale(String localeString) {
48 | if (localeString == null || localeString.isEmpty()) {
49 | return false;
50 | }
51 |
52 | try {
53 | Matcher m = REGEX_LOCALE.matcher(localeString);
54 | if (m.find()) {
55 | StringBuilder sb = new StringBuilder();
56 | sb.append(m.group(1));
57 | if (m.group(2) != null) {
58 | sb.append("-").append(m.group(2));
59 | }
60 |
61 | Locale l = new Locale.Builder().setLanguageTag(sb.toString()).build();
62 | if (l != null) {
63 | Locale.setDefault(l);
64 | logger.debug("Java Locale changed to {}", l);
65 | return true;
66 | }
67 | }
68 | } catch (Exception e) {
69 | System.out.println("Could not get locale from " + localeString);
70 | }
71 |
72 | return false;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/test/java/org/utplsql/cli/TestHelper.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli;
2 |
3 | import org.utplsql.api.DBHelper;
4 | import org.utplsql.api.EnvironmentVariableUtil;
5 | import org.utplsql.api.Version;
6 | import org.utplsql.cli.config.RunCommandConfig;
7 | import picocli.CommandLine;
8 |
9 | import javax.sql.DataSource;
10 | import java.sql.Connection;
11 | import java.sql.SQLException;
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.List;
15 |
16 | class TestHelper {
17 | private static String sUrl;
18 | private static String sUser;
19 | private static String sPass;
20 |
21 | static {
22 | sUrl = EnvironmentVariableUtil.getEnvValue("DB_URL", "192.168.99.100:1521:XE");
23 | sUser = EnvironmentVariableUtil.getEnvValue("DB_USER", "app");
24 | sPass = EnvironmentVariableUtil.getEnvValue("DB_PASS", "app");
25 | }
26 |
27 | static RunPicocliCommand createPicocliRunCommand(String... args ) {
28 | Object obj = new UtplsqlPicocliCommand();
29 | CommandLine cline = new CommandLine(obj);
30 | cline.setTrimQuotes(true);
31 | List parsed = cline.parse(args);
32 |
33 | return parsed.get(1).getCommand();
34 | }
35 |
36 | static IRunCommand createRunCommand(String... args) {
37 | ArrayList newArgs = new ArrayList<>(args.length+1);
38 | newArgs.add("run");
39 | newArgs.addAll(Arrays.asList(args));
40 | return createPicocliRunCommand(newArgs.toArray(new String[0]));
41 | }
42 |
43 | static RunCommandConfig parseRunConfig(String... args ) throws Exception {
44 | Object obj = new UtplsqlPicocliCommand();
45 | CommandLine cline = new CommandLine(obj);
46 | cline.setTrimQuotes(true);
47 | List parsed = cline.parse(args);
48 |
49 | RunPicocliCommand runCmd = parsed.get(1).getCommand();
50 | return runCmd.getRunCommandConfig();
51 | }
52 |
53 | static RunAction createRunAction(String... args) throws Exception {
54 | ArrayList newArgs = new ArrayList<>(args.length+1);
55 | newArgs.add("run");
56 | newArgs.addAll(Arrays.asList(args));
57 | return new RunAction(parseRunConfig(newArgs.toArray(new String[0])));
58 | }
59 |
60 | static int runApp(String... args) {
61 | return Cli.runPicocliWithExitCode(args);
62 | }
63 |
64 | static Version getFrameworkVersion() throws SQLException {
65 | DataSource ds = DataSourceProvider.getDataSource(TestHelper.getConnectionString(), 1);
66 | try (Connection con = ds.getConnection() ) {
67 | return DBHelper.getDatabaseFrameworkVersion(con);
68 | }
69 | }
70 |
71 | static String getConnectionString() {
72 | return sUser + "/" + sPass + "@" + sUrl;
73 | }
74 |
75 | static String getUser() {
76 | return sUser;
77 | }
78 |
79 | static String getPass() {
80 | return sPass;
81 | }
82 |
83 | static String getUrl() {
84 | return sUrl;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 | language: java
3 |
4 | services:
5 | - docker
6 |
7 | jdk:
8 | - openjdk8
9 |
10 | env:
11 | global:
12 | - DOCKER_CFG=$HOME/.docker
13 | - DOCKER_REPO="utplsqlv3/oracledb"
14 | - CACHE_DIR=$HOME/.cache
15 | - MAVEN_HOME=/usr/local/maven
16 | - MAVEN_CFG=$HOME/.m2
17 | - DB_URL="127.0.0.1:1521:XE"
18 | - DB_USER=app
19 | - DB_PASS=app
20 | - ORACLE_VERSION="11g-r2-xe"
21 | - DOCKER_OPTIONS="--shm-size=1g"
22 | - UTPLSQL_FILE="utPLSQL"
23 | matrix:
24 | - UTPLSQL_VERSION="v3.0.0"
25 | UTPLSQL_FILE="utPLSQLv3.0.0"
26 | - UTPLSQL_VERSION="v3.0.1"
27 | - UTPLSQL_VERSION="v3.0.2"
28 | - UTPLSQL_VERSION="v3.0.3"
29 | - UTPLSQL_VERSION="v3.0.4"
30 | - UTPLSQL_VERSION="v3.1.1"
31 | - UTPLSQL_VERSION="v3.1.2"
32 | - UTPLSQL_VERSION="v3.1.3"
33 | - UTPLSQL_VERSION="v3.1.6"
34 | - UTPLSQL_VERSION="v3.1.7"
35 | - UTPLSQL_VERSION="v3.1.8"
36 | - UTPLSQL_VERSION="develop"
37 | UTPLSQL_FILE="utPLSQL"
38 |
39 | cache:
40 | directories:
41 | - $DOCKER_CFG
42 | - $CACHE_DIR
43 | - $MAVEN_CFG
44 |
45 | install:
46 | - bash .travis/start_db.sh
47 | - bash .travis/install_utplsql.sh
48 | - bash .travis/install_demo_project.sh
49 |
50 | script:
51 | - mvn package -DskipTests
52 | - mvn package verify jar:jar appassembler:assemble
53 |
54 | before_deploy:
55 | - bash .travis/create_release.sh
56 | - if [ ! -z "$TRAVIS_TAG" ]; then VERSION=$(tr -d "/v/" <<<$TRAVIS_TAG); mvn org.codehaus.mojo:versions-maven-plugin:2.1:set -DnewVersion=${VERSION}; fi
57 |
58 | deploy:
59 | - provider: releases
60 | api_key: $GITHUB_API_TOKEN
61 | file:
62 | - utPLSQL-cli.zip
63 | - utPLSQL-cli.zip.md5
64 | skip_cleanup: true
65 | on:
66 | repository: utPLSQL/utPLSQL-cli
67 | tags: true
68 | # Use only first job "#xxx.1" to publish artifacts
69 | condition: "${TRAVIS_JOB_NUMBER} =~ \\.1$"
70 | - provider: bintray
71 | file: bintray.json
72 | user: ${BINTRAY_USER}
73 | key: ${BINTRAY_API_KEY}
74 | dry-run: false
75 | skip_cleanup: true
76 | on:
77 | repository: utPLSQL/utPLSQL-cli
78 | branch: develop
79 | # Use only first job "#xxx.1" to publish artifacts
80 | condition: "${TRAVIS_JOB_NUMBER} =~ \\.1$"
81 |
82 | notifications:
83 | slack:
84 | rooms:
85 | - secure: "jTPq4AcWQdWp1rB175c05ei/1lXZF1DBoqiKl9PPe7f8vqXS2QLPXMwGTEkZ1YnqL2MPZMB+50Gw5RhLKQ+t+9pN7ejLO0D8ULi1e96PDU5ZL5pNvRglH6U/lR5iT1CjELUuraDXDJ98Vu4gluLMiwTtFYQhNrOoA2V84L+8fF7rGjbGl4/zOXA9RQ4YAcOomJesb4vE7BCjhDjUuMW43xjNWg2s0WAiF+fC1HY/tsBMb1CGfpVULnO5ES5bKtUv/aGtySzH0vXilGDUvhZ/8mdaRn6uxpzcqrFdAyW8elSD28CypcYoxy6Myudw3SFiRPs0/Z02VXvm8DQtU/lcFEnaO7dMG+FpFhsWbrEjcRS6R7ve8uc7e/WuaQhtNVzSTOzRe+JFPGP9FOcYN+AcW2NJFILV9yT7+X/MPIB0OMxuwaPmVgtoyx0oec2nw05azmDr76P2e1XLnKtxa8ouwvPx8EMgApnXSR6VmLGu/w8nmtvIWjEAJ88cdGhwBagtyAsn2frzHq8aKpMziDRYvw4ivwGAeHJFsDtdRXzSbxhxmjl6+is3P0g0iAfojQ/Pzd4GugSYwqRQLLE7dUE0FAKXhKAAQAkjRZxik2+w6jgG8PuLuHdR4pm7C9srL+WAX8aFq/RQXE7BoIdqiZ5TMekw8d6eCRTjcRHsa3pPAd0="
86 | on_success: change
87 | on_failure: always
88 |
--------------------------------------------------------------------------------
/src/main/java/org/utplsql/cli/ReportersCommand.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli;
2 |
3 | import org.utplsql.api.exception.DatabaseNotCompatibleException;
4 | import org.utplsql.api.exception.UtPLSQLNotInstalledException;
5 | import org.utplsql.api.reporter.ReporterFactory;
6 | import org.utplsql.api.reporter.inspect.ReporterInfo;
7 | import org.utplsql.api.reporter.inspect.ReporterInspector;
8 | import org.utplsql.cli.exception.DatabaseConnectionFailed;
9 | import picocli.CommandLine.Command;
10 | import picocli.CommandLine.Option;
11 | import picocli.CommandLine.Parameters;
12 |
13 | import javax.sql.DataSource;
14 | import java.io.PrintStream;
15 | import java.sql.Connection;
16 | import java.util.Arrays;
17 | import java.util.Comparator;
18 | import java.util.List;
19 |
20 | @Command(name = "reporters", description = "prints a list of reporters available in the specified database")
21 | public class ReportersCommand implements ICommand {
22 |
23 | @Parameters(description = UtplsqlPicocliCommand.COMMANDLINE_PARAM_DESCRIPTION, arity = "1")
24 | private String connectionString;
25 |
26 | @Option(names = "-h", usageHelp = true, description = "display this help and exit")
27 | boolean help;
28 |
29 | @Override
30 | public int run() {
31 | LoggerConfiguration.configure(LoggerConfiguration.ConfigLevel.NONE);
32 |
33 | try {
34 | DataSource ds = DataSourceProvider.getDataSource(connectionString, 1);
35 | try (Connection con = ds.getConnection()) {
36 |
37 | ReporterFactory reporterFactory = ReporterFactoryProvider.createReporterFactory(con);
38 |
39 | writeReporters(ReporterInspector.create(reporterFactory, con).getReporterInfos(), System.out);
40 | }
41 | } catch (DatabaseNotCompatibleException | UtPLSQLNotInstalledException | DatabaseConnectionFailed | IllegalArgumentException e) {
42 | System.out.println(e.getMessage());
43 | return 1;
44 | } catch (Exception e) {
45 | e.printStackTrace();
46 | return 1;
47 | }
48 |
49 | return 0;
50 | }
51 |
52 | private void writeReporters(List reporterInfos, PrintStream out) {
53 | reporterInfos.stream()
54 | .sorted(Comparator.comparing(ReporterInfo::getName))
55 | .forEach(info -> writeReporter(info, 4, out));
56 | }
57 |
58 | private void writeReporter(ReporterInfo info, int padding, PrintStream out) {
59 |
60 | writeReporterName(info, padding, out);
61 | writeReporterDescription(info, padding, out);
62 |
63 | out.println();
64 | }
65 |
66 | private void writeReporterName(ReporterInfo info, int paddingRight, PrintStream out) {
67 | out.println(info.getName() + ":");
68 |
69 | }
70 |
71 | private void writeReporterDescription(ReporterInfo info, int paddingLeft, PrintStream out) {
72 | String[] lines = info.getDescription().split("\n");
73 | String paddingLeftStr = String.format("%1$" + paddingLeft + "s", "");
74 | Arrays.stream(lines).forEach(line -> out.println(paddingLeftStr + line.trim()));
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/test/java/org/utplsql/cli/util/SystemCapturer.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli.util;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.io.OutputStream;
6 | import java.io.PrintStream;
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | /** All credit to Manasjyoti Sharma: https://stackoverflow.com/a/30665299
11 | */
12 | public abstract class SystemCapturer {
13 |
14 | private ByteArrayOutputStream baos;
15 | private PrintStream previous;
16 | private boolean capturing;
17 |
18 | protected abstract PrintStream getOriginalStream();
19 |
20 | protected abstract void setSystemStream( PrintStream stream );
21 |
22 | public void start() {
23 | if (capturing) {
24 | return;
25 | }
26 |
27 | capturing = true;
28 | previous = getOriginalStream();
29 | baos = new ByteArrayOutputStream();
30 |
31 | OutputStream outputStreamCombiner =
32 | new OutputStreamCombiner(Arrays.asList(previous, baos));
33 | PrintStream custom = new PrintStream(outputStreamCombiner);
34 |
35 | setSystemStream(custom);
36 | }
37 |
38 | public String stop() {
39 | if (!capturing) {
40 | return "";
41 | }
42 |
43 | setSystemStream(previous);
44 |
45 | String capturedValue = baos.toString();
46 |
47 | baos = null;
48 | previous = null;
49 | capturing = false;
50 |
51 | return capturedValue;
52 | }
53 |
54 | private static class OutputStreamCombiner extends OutputStream {
55 | private List outputStreams;
56 |
57 | public OutputStreamCombiner(List outputStreams) {
58 | this.outputStreams = outputStreams;
59 | }
60 |
61 | public void write(int b) throws IOException {
62 | for (OutputStream os : outputStreams) {
63 | os.write(b);
64 | }
65 | }
66 |
67 | public void flush() throws IOException {
68 | for (OutputStream os : outputStreams) {
69 | os.flush();
70 | }
71 | }
72 |
73 | public void close() throws IOException {
74 | for (OutputStream os : outputStreams) {
75 | os.close();
76 | }
77 | }
78 | }
79 |
80 | public static class SystemOutCapturer extends SystemCapturer {
81 |
82 | @Override
83 | protected PrintStream getOriginalStream() {
84 | return System.out;
85 | }
86 |
87 | @Override
88 | protected void setSystemStream(PrintStream stream) {
89 | System.setOut(stream);
90 | }
91 | }
92 |
93 | public static class SystemErrCapturer extends SystemCapturer {
94 |
95 | @Override
96 | protected PrintStream getOriginalStream() {
97 | return System.err;
98 | }
99 |
100 | @Override
101 | protected void setSystemStream(PrintStream stream) {
102 | System.setErr(stream);
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/test/java/org/utplsql/cli/DataSourceProviderIT.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.utplsql.cli.datasource.TestedDataSourceProvider;
5 |
6 | import javax.sql.DataSource;
7 | import java.sql.Connection;
8 | import java.sql.PreparedStatement;
9 | import java.sql.ResultSet;
10 | import java.sql.SQLException;
11 |
12 | import static org.junit.jupiter.api.Assertions.*;
13 |
14 | class DataSourceProviderIT {
15 |
16 | @Test
17 | void connectToDatabase() throws SQLException {
18 | DataSource dataSource = getDataSource();
19 |
20 | assertNotNull(dataSource);
21 | }
22 |
23 | //@Test
24 | void connectAsSysdba() throws SQLException {
25 | ConnectionConfig config = new ConnectionConfig("sys as sysdba/oracle@localhost:1522/ORCLPDB1");
26 | DataSource dataSource = new TestedDataSourceProvider(config, 2).getDataSource();
27 |
28 | assertNotNull(dataSource);
29 | }
30 |
31 | @Test
32 | void initNlsLang() throws SQLException {
33 | System.setProperty("NLS_LANG", "BRAZILIAN PORTUGUESE_BRAZIL.WE8ISO8859P1");
34 | DataSource dataSource = getDataSource();
35 |
36 | assertNotNull(dataSource);
37 | checkNlsSessionParameter(dataSource, "NLS_LANGUAGE", "BRAZILIAN PORTUGUESE");
38 | checkNlsSessionParameter(dataSource, "NLS_TERRITORY", "BRAZIL");
39 | }
40 |
41 | @Test
42 | void initPartialNlsLangTerritory() throws SQLException {
43 | System.setProperty("NLS_LANG", "_SOMALIA");
44 | DataSource dataSource = getDataSource();
45 |
46 | assertNotNull(dataSource);
47 | checkNlsSessionParameter(dataSource, "NLS_TERRITORY", "SOMALIA");
48 | }
49 |
50 | @Test
51 | void initPartialNlsLangLanguage() throws SQLException {
52 | System.setProperty("NLS_LANG", "HINDI");
53 | DataSource dataSource = getDataSource();
54 |
55 | assertNotNull(dataSource);
56 | checkNlsSessionParameter(dataSource, "NLS_LANGUAGE", "HINDI");
57 | }
58 |
59 | @Test
60 | void initNlsLangEmpty() throws SQLException {
61 | System.setProperty("NLS_LANG", "");
62 | DataSource dataSource = getDataSource();
63 |
64 | assertNotNull(dataSource);
65 | }
66 |
67 | private DataSource getDataSource() throws SQLException {
68 | ConnectionConfig config = new ConnectionConfig(TestHelper.getConnectionString());
69 | return new TestedDataSourceProvider(config, 2).getDataSource();
70 | }
71 |
72 | private void checkNlsSessionParameter( DataSource dataSource, String parameterName, String expectedValue ) throws SQLException {
73 | try ( Connection con = dataSource.getConnection() ) {
74 | try (PreparedStatement stmt = con.prepareStatement("select value from nls_session_parameters where parameter = ?")) {
75 | stmt.setString(1, parameterName);
76 | ResultSet rs = stmt.executeQuery();
77 | if ( rs.next() )
78 | assertEquals(expectedValue, rs.getString(1));
79 | else
80 | fail("Could not get NLS Session parameter value for '" + parameterName + "'");
81 | }
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/test/java/org/utplsql/cli/RunCommandArgumentsTest.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli;
2 |
3 | import org.junit.jupiter.api.DisplayName;
4 | import org.junit.jupiter.api.Test;
5 | import org.utplsql.api.TestRunner;
6 |
7 | import java.util.ArrayList;
8 |
9 | import static org.hamcrest.MatcherAssert.assertThat;
10 | import static org.hamcrest.Matchers.contains;
11 |
12 | public class RunCommandArgumentsTest {
13 |
14 | @Test
15 | @DisplayName("All arguments are recognized")
16 | public void allArgumentsAreRecognized() {
17 | IRunCommand runCmd = TestHelper.createRunCommand(TestHelper.getConnectionString(),
18 | "-p=app",
19 | "-f=ut_sonar_test_reporter",
20 | "-o=sonar_result.xml",
21 | "-s",
22 | "--tags=tag1,tag2",
23 | "--coverage-schemes=schema1,some_other_schema",
24 | "-d",
25 | "-c",
26 | "--failure-exit-code=10",
27 | "-scc",
28 | "-t=60",
29 | "-exclude=app.betwnstr",
30 | "-include=app.betwnstr",
31 | "-source_path=src/test/resources/plsql/source",
32 | "-owner=app",
33 | "-regex_expression=\"*\"",
34 | "-type_mapping=\"sql=PACKAGE BODY\"",
35 | "-owner_subexpression=0",
36 | "-type_subexpression=0",
37 | "-name_subexpression=0",
38 | "-test_path=src/test/resources/plsql/test",
39 | "-owner=app",
40 | "-regex_expression=\"*\"",
41 | "-type_mapping=\"sql=PACKAGE BODY\"",
42 | "-owner_subexpression=0",
43 | "-type_subexpression=0",
44 | "-name_subexpression=0",
45 | "--ora-stuck-timeout=2"
46 | );
47 |
48 | TestRunner testRunner = runCmd.newTestRunner(new ArrayList<>());
49 | }
50 |
51 | @Test
52 | void multiplePaths() {
53 | IRunCommand runCmd = TestHelper.createRunCommand(TestHelper.getConnectionString(),
54 | "-p=app.test_betwnstr,app.test_award_bonus"
55 | );
56 |
57 | TestRunner testRunner = runCmd.newTestRunner(new ArrayList<>());
58 | assertThat( testRunner.getOptions().pathList, contains("app.test_betwnstr", "app.test_award_bonus") );
59 |
60 | }
61 |
62 | @Test
63 | void provideTags() {
64 | IRunCommand runCmd = TestHelper.createRunCommand(TestHelper.getConnectionString(),
65 | "--tags=tag1,tag.2"
66 | );
67 |
68 | TestRunner testRunner = runCmd.newTestRunner(new ArrayList<>());
69 | assertThat( testRunner.getOptions().tags, contains("tag1", "tag.2") );
70 | }
71 |
72 | @Test
73 | void provideCoverageSchemes() {
74 | IRunCommand runCmd = TestHelper.createRunCommand(TestHelper.getConnectionString(),
75 | "--coverage-schemes=schema-1,some_other_schema"
76 | );
77 |
78 | TestRunner testRunner = runCmd.newTestRunner(new ArrayList<>());
79 | assertThat( testRunner.getOptions().coverageSchemes, contains("schema-1", "some_other_schema") );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/test/java/org/utplsql/cli/RunCommandIT.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.utplsql.api.compatibility.OptionalFeatures;
5 | import org.utplsql.api.reporter.CoreReporters;
6 |
7 | import java.nio.file.Paths;
8 | import java.sql.SQLException;
9 |
10 | import static org.junit.jupiter.api.Assertions.assertEquals;
11 |
12 | /**
13 | * System tests for run command.
14 | */
15 | class RunCommandIT extends AbstractFileOutputTest {
16 |
17 | private void assertValidReturnCode(int returnCode) throws SQLException {
18 | // Only expect failure-exit-code to work on several framework versions
19 | if (OptionalFeatures.FAIL_ON_ERROR.isAvailableFor(TestHelper.getFrameworkVersion()))
20 | assertEquals(2, returnCode);
21 | else
22 | assertEquals(0, returnCode);
23 | }
24 |
25 | @Test
26 | void run_Default() throws Exception {
27 |
28 | int result = TestHelper.runApp("run",
29 | TestHelper.getConnectionString(),
30 | "-f=ut_documentation_reporter",
31 | "-s",
32 | "-c",
33 | "--failure-exit-code=2");
34 |
35 | assertValidReturnCode(result);
36 | }
37 |
38 | @Test
39 | void run_Debug() throws Exception {
40 |
41 | int result = TestHelper.runApp("run",
42 | TestHelper.getConnectionString(),
43 | "--debug",
44 | "--failure-exit-code=2");
45 |
46 | assertValidReturnCode(result);
47 | }
48 |
49 | @Test
50 | void run_MultipleReporters() throws Exception {
51 |
52 | String outputFileName = "output_" + System.currentTimeMillis() + ".xml";
53 | addTempPath(Paths.get(outputFileName));
54 |
55 | int result = TestHelper.runApp("run",
56 | TestHelper.getConnectionString(),
57 | "-f=ut_documentation_reporter",
58 | "-s",
59 | "-f=" + CoreReporters.UT_SONAR_TEST_REPORTER.name(),
60 | "-o=" + outputFileName,
61 | "-c",
62 | "--failure-exit-code=2");
63 |
64 | assertValidReturnCode(result);
65 | }
66 |
67 |
68 | @Test
69 | void run_withDbmsOutputEnabled() throws Exception {
70 |
71 | int result = TestHelper.runApp("run",
72 | TestHelper.getConnectionString(),
73 | "-D",
74 | "--failure-exit-code=2");
75 |
76 | assertValidReturnCode(result);
77 | }
78 |
79 | @Test
80 | void run_withOutputButNoReporterDefined() throws Exception {
81 |
82 | String outputFileName = "output_" + System.currentTimeMillis() + ".xml";
83 | addTempPath(Paths.get(outputFileName));
84 |
85 | int result = TestHelper.runApp("run",
86 | TestHelper.getConnectionString(),
87 | "-o=" + outputFileName,
88 | "--failure-exit-code=2");
89 |
90 | assertValidReturnCode(result);
91 | }
92 |
93 | @Test
94 | void run_withOraStuckTimeout() throws Exception {
95 | int result = TestHelper.runApp("run",
96 | TestHelper.getConnectionString(),
97 | "--ora-stuck-timeout=2",
98 | "--failure-exit-code=2");
99 |
100 | assertValidReturnCode(result);
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/test/java/org/utplsql/cli/RunCommandCoverageReporterIT.java:
--------------------------------------------------------------------------------
1 | package org.utplsql.cli;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import java.io.File;
6 | import java.nio.file.Files;
7 | import java.nio.file.Path;
8 | import java.nio.file.Paths;
9 | import java.util.regex.Matcher;
10 | import java.util.regex.Pattern;
11 |
12 | import static org.junit.jupiter.api.Assertions.assertFalse;
13 | import static org.junit.jupiter.api.Assertions.assertTrue;
14 |
15 | /**
16 | * System tests for Code Coverage Reporter
17 | *
18 | * @author pesse
19 | */
20 | class RunCommandCoverageReporterIT extends AbstractFileOutputTest {
21 |
22 | private static final Pattern REGEX_COVERAGE_TITLE = Pattern.compile("([a-zA-Z ]+ )?([a-zA-Z0-9\\._]+)<\\/a>");
23 |
24 |
25 | private String getTempCoverageFileName(int counter) {
26 |
27 | return "tmpCoverage_" + System.currentTimeMillis() + "_" + counter + ".html";
28 | }
29 |
30 | /**
31 | * Returns a random filename which does not yet exist on the local path
32 | *
33 | * @return
34 | */
35 | private Path getTempCoverageFilePath() {
36 |
37 | int i = 1;
38 | Path p = Paths.get(getTempCoverageFileName(i));
39 |
40 | while ((Files.exists(p) || tempPathExists(p)) && i < 100)
41 | p = Paths.get(getTempCoverageFileName(i++));
42 |
43 | if (i >= 100)
44 | throw new IllegalStateException("Could not get temporary file for coverage output");
45 |
46 | addTempPath(p);
47 | addTempPath(Paths.get(p.toString()+"_assets"));
48 |
49 | return p;
50 | }
51 |
52 | /**
53 | * Checks Coverage HTML Output if a given packageName is listed
54 | *
55 | * @param content
56 | * @param packageName
57 | * @return
58 | */
59 | private boolean hasCoverageListed(String content, String packageName) {
60 | Matcher m = REGEX_COVERAGE_TITLE.matcher(content);
61 |
62 | while (m.find()) {
63 | if (packageName.equals(m.group(2)))
64 | return true;
65 | }
66 |
67 | return false;
68 | }
69 |
70 | @Test
71 | void run_CodeCoverageWithIncludeAndExclude() throws Exception {
72 |
73 | Path coveragePath = getTempCoverageFilePath();
74 |
75 | int result = TestHelper.runApp("run", TestHelper.getConnectionString(),
76 | "-f=ut_coverage_html_reporter", "-o=" + coveragePath, "-s", "-exclude=app.award_bonus,app.betwnstr");
77 |
78 |
79 | String content = new String(Files.readAllBytes(coveragePath));
80 |
81 | assertTrue(hasCoverageListed(content, "app.remove_rooms_by_name"));
82 | assertFalse(hasCoverageListed(content, "app.award_bonus"));
83 | assertFalse(hasCoverageListed(content, "app.betwnstr"));
84 |
85 | }
86 |
87 | @Test
88 | void coverageReporterWriteAssetsToOutput() throws Exception {
89 | Path coveragePath = getTempCoverageFilePath();
90 | Path coverageAssetsPath = Paths.get(coveragePath.toString() + "_assets");
91 |
92 | TestHelper.runApp("run", TestHelper.getConnectionString(),
93 | "-f=ut_coverage_html_reporter", "-o=" + coveragePath, "-s");
94 |
95 | // Run twice to test overriding of assets
96 | TestHelper.runApp("run", TestHelper.getConnectionString(),
97 | "-f=ut_coverage_html_reporter", "-o=" + coveragePath, "-s");
98 |
99 |
100 | // Check application file exists
101 | File applicationJs = coverageAssetsPath.resolve(Paths.get("application.js")).toFile();
102 | assertTrue(applicationJs.exists());
103 |
104 | // Check correct script-part in HTML source exists
105 | String content = new String(Files.readAllBytes(coveragePath));
106 | assertTrue(content.contains("