From 5aef96d41e548ef66817634997dfd73bd06aba5e Mon Sep 17 00:00:00 2001 From: Jacek Date: Wed, 17 May 2017 21:06:42 +0100 Subject: [PATCH] Moved client command line utility from utPLSQL main project. --- .gitignore | 13 ++ README.md | 95 ++++++++++- file_list | 39 +++++ file_list.bat | 44 +++++ ut_run | 17 ++ ut_run.bat | 16 ++ ut_run.sql | 459 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 682 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100755 file_list create mode 100644 file_list.bat create mode 100755 ut_run create mode 100644 ut_run.bat create mode 100644 ut_run.sql diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8dea1b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Created by .ignore support plugin (hsz.mobi) +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 +# User-specific stuff: +.idea/ +.sonar/ +site/ +pages/ +release/ +*.gz +*.zip +node_modules/ diff --git a/README.md b/README.md index 2ad1a98..fb2b736 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,95 @@ # utPLSQL-sql-cli -A bash/windows command-line client for utPLSQL v3 + +Bash & windows command-line client for [utPLSQL v3](https://github.com/utPLSQL/utPLSQL/) + +Provides an easy way of invoking utPLSQL from command-line. +Main features: + +- Provides outputs from first reporter in real-time, so you can see the progress of your test execution +- Ability to run tests with multiple reporters simultaneously +- Ability to save output from every individual reporter to separate output file +- Provides coloured outputs +- Maps project and test files to database objects for reporting purposes +- Allows execution of selected suites, subset of suite + +# Requirements + +The scripts require `sqlplus` to be installed and configured to be in your PATH. + +When using reporters for Sonar or Coveralls the the `ut_run.bat`/`ut_run` script needs to be invoked from project's root directory. + +Number of script parameters cannot exceed 39. + +# Script Invocation + +`ut_run user/password@database [-p=(ut_path|ut_paths)] [-c] [-f=format [-o=output] [-s] ...] [-source_path=path] [-test_path=path]` + +# Parameters + +``` + user - username to connect as + password - password of the user + database - database to connect to + -p=suite_path(s) - A suite path or a comma separated list of suite paths for unit test to be executed. + The path(s) can be in one of the following formats: + schema[.package[.procedure]] + schema:suite[.suite[.suite][...]][.procedure] + Both formats can be mixed in the list. + If only schema is provided, then all suites owner by that schema are executed. + If -p is omitted, the current schema is used. + -f=format - A reporter to be used for reporting. + If no -f option is provided, the default ut_documentation_reporter is used. + Available options: + -f=ut_documentation_reporter + A textual pretty-print of unit test results (usually use for console output) + -f=ut_teamcity_reporter + For reporting live progress of test execution with Teamcity CI. + -f=ut_xunit_reporter + Used for reporting test results with CI servers like Jenkins/Hudson/Teamcity. + -f=ut_coverage_html_reporter + Generates a HTML coverage report with summary and line by line information on code coverage. + Based on open-source simplecov-html coverage reporter for Ruby. + Includes source code in the report. + -f=ut_coveralls_reporter + Generates a JSON coverage report providing information on code coverage with line numbers. + Designed for [Coveralls](https://coveralls.io/). + -f=ut_coverage_sonar_reporter + Generates a JSON coverage report providing information on code coverage with line numbers. + Designed for [SonarQube](https://about.sonarqube.com/) to report coverage. + -f=ut_sonar_test_reporter + Generates a JSON report providing detailed information on test execution. + Designed for [SonarQube](https://about.sonarqube.com/) to report test execution. + + -o=output - Defines file name to save the output from the specified reporter. + If defined, the output is not displayed on screen by default. This can be changed with the -s parameter. + If not defined, then output will be displayed on screen, even if the parameter -s is not specified. + If more than one -o parameter is specified for one -f parameter, the last one is taken into consideration. + -s - Forces putting output to to screen for a given -f parameter. + -source_path=path - Path to project source files. Used by coverage reporters. The path needs to be relative to the projects root directory. + -test_path=path - Path to unit test source files. Used by test reporters. The path needs to be relative to the projects root directory. + -c - If specified, enables printing of test results in colors as defined by ANSICONSOLE standards. + Works only on reporeters that support colors (ut_documentation_reporter) +``` + +Parameters -f, -o, -s are correlated. That is parameters -o and -s are controlling outputs for reporter specified by the preceding -f parameter. + +**Sonar and Coveralls reporter will only provide valid reports, when source_path and/or test_path are provided, and ut_run is executed from your project's root path.** + +Examples: + +`ut_run hr/hr@xe -p=hr_test -f=ut_documentation_reporter -o=run.log -s -f=ut_coverage_html_reporter -o=coverage.html -source_path=source` + +Invokes all Unit tests from schema/package "hr_test" with two reporters: + +- ut_documentation_reporter - will output to screen and save output to file "run.log" +- ut_coverage_html_reporter - will report **only** on database objects that are mapping to file structure from "source" folder and save output to file "coverage.html" + + +`ut_run hr/hr@xe` + +Invokes all unit test suites from schema "hr". +Results are displayed to screen using default `ut_documentation_reporter`. + +**Enabling color outputs on Windows** + +To enable color outputs from SQLPlus on winddows you need to install an open-source utility called [ANSICON](http://adoxa.altervista.org/ansicon/) diff --git a/file_list b/file_list new file mode 100755 index 0000000..4afea92 --- /dev/null +++ b/file_list @@ -0,0 +1,39 @@ +#!/bin/bash +set -e + +# All parameters are required. This way, users can't pass empty string as parameter. +invalidArgs=0 +[ -z "$1" ] && invalidArgs=1 +[ -z "$2" ] && invalidArgs=1 +[ -z "$3" ] && invalidArgs=1 + +if [ $invalidArgs -eq 1 ]; then + echo Usage: ut_run.sh "project_path" "sql_param_name" "output_file" "scan_path" + exit 1 +fi + +# Remove trailing slashes. +projectPath=${1%/} +sqlParamName=$2 +outputFile=$3 +scanPath=$4 + +fullScanPath="$projectPath/$scanPath" + +if [ ! -d "$fullScanPath" ] || [ -z "$4" ]; then + echo "begin" > $outputFile + echo " open :$sqlParamName for select null from dual where 1= 0;" >> $outputFile + echo "end;" >> $outputFile + echo "/" >> $outputFile + exit 0 +fi + +echo "declare" > $outputFile +echo " l_list ut_varchar2_list := ut_varchar2_list();" >> $outputFile +echo "begin" >> $outputFile +for f in $(find $fullScanPath/* -type f | sed "s|$projectPath/||"); do + echo " l_list.extend; l_list(l_list.last) := '$f';" >> $outputFile +done +echo " open :$sqlParamName for select * from table(l_list);" >> $outputFile +echo "end;" >> $outputFile +echo "/" >> $outputFile diff --git a/file_list.bat b/file_list.bat new file mode 100644 index 0000000..5bb22fe --- /dev/null +++ b/file_list.bat @@ -0,0 +1,44 @@ +@echo off +setlocal EnableDelayedExpansion + +REM All parameters are required. This way, users can't pass empty string as parameter. +set invalidArgs=0 +set pathNotProvided=0 +if [%1] == "" set invalidArgs=1 +if [%2] == "" set invalidArgs=1 +if [%3] == "" set invalidArgs=1 + +if %invalidArgs% == 1 ( + echo Usage: ut_run.bat "project_path" "sql_param_name" "output_file" "scan_path" + exit /b 1 +) +REM Expand relative path from parameter to be a full path +set projectPath=%~f1 +set sqlParamName=%~2 +set outputFile=%~3 +set scanPath=%~4 + +REM Remove trailing slashes. +if %projectPath:~-1%==\ set projectPath=%projectPath:~0,-1% +if [%scanPath%] == [] (set pathNotProvided=1) else (set "fullScanPath=%projectPath%\%scanPath%") +if not exist "%fullScanPath%\*" set pathNotProvided=1 + +if %pathNotProvided% == 1 ( + echo begin>%outputFile% + echo ^ open :%sqlParamName% for select null from dual where 1 = 0;>>%outputFile% + echo end;>>%outputFile% + echo />>%outputFile% + exit /b 0 +) + +echo declare>%outputFile% +echo ^ l_list ut_varchar2_list := ut_varchar2_list();>>%outputFile% +echo begin>>%outputFile% +for /f "tokens=* delims= " %%a in ('dir %fullScanPath%\* /B /S /A:-D') do ( + set "filePath=%%a" + set filePath=!filePath:%projectPath%\=! + echo ^ l_list.extend; l_list^(l_list.last^) := '!filePath!^';>>%outputFile% +) +echo ^ open :%sqlParamName% for select * from table(l_list);>>%outputFile% +echo end;>>%outputFile% +echo />>%outputFile% diff --git a/ut_run b/ut_run new file mode 100755 index 0000000..09bbd19 --- /dev/null +++ b/ut_run @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +clientDir="$(dirname "$(readlink -f "$0")")" +projectDir="$(pwd)" + +if [[ "$clientDir" != "${clientDir% *}" ]]; then + echo "Error: ut_run script path cannot have spaces." + exit 1 +fi + +if [[ "$#" -eq 0 ]] ; then + echo "Usage: ut_run user/password@database [options...]" + exit 1 +fi + +sqlplus /nolog @"$clientDir/ut_run.sql" "$clientDir" "$projectDir" "$@" diff --git a/ut_run.bat b/ut_run.bat new file mode 100644 index 0000000..afcf25a --- /dev/null +++ b/ut_run.bat @@ -0,0 +1,16 @@ +@echo off + +set clientDir=%~dp0 +set projectDir=%__CD__% + +if not "%clientDir%" == "%clientDir: =%" ( + echo Error: ut_run script path cannot have spaces. + exit /b 1 +) + +if "%1" == "" ( + echo Usage: ut_run user/password@database [options...] + exit /b 1 +) + +sqlplus /nolog @"%clientDir%\ut_run.sql" '%clientDir%' '%projectDir%' %* diff --git a/ut_run.sql b/ut_run.sql new file mode 100644 index 0000000..9207522 --- /dev/null +++ b/ut_run.sql @@ -0,0 +1,459 @@ +/* + utPLSQL - Version X.X.X.X + Copyright 2016 - 2017 utPLSQL Project + + Licensed under the Apache License, Version 2.0 (the "License"): + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + This script is designed to allow invocation of UTPLSQL with multiple reporters. + It allows saving of outcomes into multiple output files. + It also facilitates displaying on screen unit test results while the execution is still ongoing. + Current limit of script parameters is 39 + +Scrip invocation: + ut_run.sql "client_Path" "project_path" user/password@database [-p=(ut_path|ut_paths)] [-c] [-f=format [-o=output] [-s] ...] [-source_path=path] [-test_path=path] + +Parameters: + client_path - The path where this script is installed. Will be used to find auxiliary scripts and to save temp files. + project_path - The path from where this script is being called. + user - username to connect as + password - password of the user + database - database to connect to + -p=ut_path(s)- A path or a comma separated list of paths to unit test to be executed. + The path can be in one of the following formats: + schema[.package[.procedure]] + schema:suite[.suite[.suite][...]][.procedure] + Both formats can be mixed in the comma separated list. + If only schema is provided, then all suites owner by that schema (user) are executed. + If -p is omitted, the current schema is used. + -f=format - A reporter to be used for reporting. + Available options: + -f=ut_documentation_reporter + A textual pretty-print of unit test results (usually use for console output) + -f=ut_teamcity_reporter + A teamcity Unit Test reporter, that can be used to visualize progress of test execution as the job progresses. + -f=ut_xunit_reporter + A XUnit xml format (as defined at: http://stackoverflow.com/a/9691131 and at https://gist.github.com/kuzuha/232902acab1344d6b578) + Usually used by Continuous Integration servers like Jenkins/Hudson or Teamcity to display test results. + -f=ut_coverage_html_reporter + Generates a HTML coverage report providing summary and detailed information on code coverage. + The html reporter is based on open-source simplecov-html reporter for Ruby. + It includes source code of the code that was covered (if possible). + -f=ut_coveralls_reporter + Generates a JSON coverage report providing detailed information on code coverage with line numbers. + This coverage report is designed to be consumed by cloud services like https://coveralls.io/. + -f=ut_coverage_sonar_reporter + Generates a JSON coverage report providing detailed information on code coverage with line numbers. + This report is designed to be consumed by SonarQube to report code coverage. + -f=ut_sonar_test_reporter + Generates a JSON report providing detailed information on test specifications. + This report is designed to be consumed by SonarQube to report test files. + If no -f option is provided, the ut_documentation_reporter will be used. + + -o=output - file name to save the output provided by the reporter. + If defined, the output is not displayed on screen by default. This can be changed with the -s parameter. + If not defined, then output will be displayed on screen, even if the parameter -s is not specified. + If more than one -o parameter is specified for one -f parameter, the last one is taken into consideration. + -s - Forces putting output to to screen for a given -f parameter. + -source_path=path - Source files path to be used by coverage reporters. + -test_path=path - Test files path to be used by coverage reporters. + -c - If specified, enables printing of test results in colors as defined by ANSICONSOLE standards + + To make coverage reporters work source_path and/or test_path cannot be empty, and ut_run need to be executed from your project's path. + + Parameters -f, -o, -s are correlated. That is parameters -o and -s are defining outputs for -f. + + Examples of invocation using sqlplus from command line: + + sqlplus /nolog @ut_run ~/ut_run_path ~/project/source hr/hr@xe -p=hr_test -f=ut_documentation_reporter -o=run.log -s -f=ut_coverage_html_reporter -o=coverage.html -source_path=source + + All Unit tests from schema/package "hr_test" will be be invoked with two reporters: + - ut_documentation_reporter - will output to screen and save it's output to file "run.log" + - ut_coverage_html_reporter - will read file structure from source folder, and save it's output to file "coverage.html" + + sqlplus /nolog @ut_run hr/hr@xe + + All Unit tests from schema "hr" will be be invoked with ut_documentation_reporter as a format and the results will be printed to screen. + + */ + +whenever sqlerror exit failure +whenever oserror exit failure + +define client_path="&1" +define project_path="&2" +define conn_str="&3" + +conn &conn_str + +set serveroutput on size unlimited format truncated +set trimspool on +set echo off +set termout off +set feedback off +set pagesize 0 +set linesize 30000 +set long 30000 +set longchunksize 30000 +set verify off +set heading off + +column param_list new_value param_list noprint; +/* +* Prepare script to make SQLPlus parameters optional and pass parameters call to param_list variable +*/ +set define # +spool ##client_path/define_params_variable.sql.tmp +declare + l_sql_columns varchar2(4000); + l_params varchar2(4000); +begin + for i in 1 .. 100 loop + dbms_output.put_line('column '||i||' new_value '||i); + l_sql_columns := l_sql_columns ||'null as "'||i||'",'; + l_params := l_params || '''''&&'||i||''''','; + end loop; + dbms_output.put_line('select '||rtrim(l_sql_columns, ',') ||' from dual where rownum = 0;'); + dbms_output.put_line('select '''||rtrim(l_params, ',')||''' as param_list from dual;' ); +end; +/ +spool off +set define & + + +/* +* Make SQLPlus parameters optional and pass parameters call to param_list variable +*/ +@&&client_path/define_params_variable.sql.tmp + + +var l_paths varchar2(4000); +var l_color_enabled varchar2(5); +var l_source_path varchar2(4000); +var l_test_path varchar2(4000); +var l_source_files refcursor; +var l_test_files refcursor; +var l_run_params_cur refcursor; +var l_out_params_cur refcursor; +/* +* Parse parameters and return them as variables +*/ +set termout on +declare + + type t_call_param is record ( + ut_reporter_name varchar2(4000) := 'ut_documentation_reporter', + output_file_name varchar2(4000), + output_to_screen varchar2(3) := 'on', + reporter_id varchar2(250) + ); + + type tt_call_params is table of t_call_param; + + l_input_params ut_varchar2_list := ut_varchar2_list(&¶m_list); + l_call_params tt_call_params; + + l_run_cursor_sql varchar2(32767); + l_out_cursor_sql varchar2(32767); + + function is_reporter(a_reporter_name varchar2) return varchar2 is + l_reporter_name varchar2(4000); + l_dummy integer; + l_owner varchar2(4000); + e_invalid_object exception; + e_not_a_reporter exception; + pragma exception_init (e_invalid_object,-44002); + pragma exception_init (e_not_a_reporter,-6550); + begin + l_reporter_name := upper(dbms_assert.simple_sql_name(a_reporter_name)); + -- a report is a valid reporter if it can be assigned as element of ut_reporters collection + execute immediate + 'declare + r ut_reporters; + begin + r := ut_reporters('||l_reporter_name||'()); + end;'; + return l_reporter_name; + exception + when e_not_a_reporter or e_invalid_object then + raise_application_error(-20000, 'Invalid reporter name specified: '||a_reporter_name); + end; + + function parse_reporting_params(a_params ut_varchar2_list) return tt_call_params is + l_default_call_param t_call_param; + l_call_params tt_call_params := tt_call_params(); + l_force_out_to_screen boolean; + l_param_regex varchar2(20) := '^-([fos])(\=(.*))?$'; + begin + for param in( + select regexp_substr(column_value,l_param_regex,1,1,'c',1) param_type, + regexp_substr(column_value,l_param_regex,1,1,'c',3) param_value + from table(a_params) + where column_value is not null + and regexp_like(column_value,l_param_regex) + ) loop + if param.param_type = 'f' or l_call_params.last is null then + l_call_params.extend; + l_call_params(l_call_params.last) := l_default_call_param; + if param.param_type = 'f' then + l_call_params(l_call_params.last).ut_reporter_name := is_reporter(param.param_value); + end if; + l_force_out_to_screen := false; + end if; + if param.param_type = 'o' then + l_call_params(l_call_params.last).output_file_name := param.param_value; + if not l_force_out_to_screen then + l_call_params(l_call_params.last).output_to_screen := 'off'; + end if; + elsif param.param_type = 's' then + l_call_params(l_call_params.last).output_to_screen := 'on'; + l_force_out_to_screen := true; + end if; + end loop; + if l_call_params.count = 0 then + l_call_params.extend; + l_call_params(1) := l_default_call_param; + end if; + for i in 1 .. cardinality(l_call_params) loop + l_call_params(i).reporter_id := sys_guid(); + end loop; + return l_call_params; + end; + + function parse_suite_paths_param(a_params ut_varchar2_list) return varchar2 is + l_paths varchar2(4000); + begin + begin + select ''''||replace(ut_paths,',',''',''')||'''' + into l_paths + from (select regexp_substr(column_value,'-p\=(.*)',1,1,'c',1) as ut_paths from table(a_params) ) + where ut_paths is not null; + exception + when no_data_found then + l_paths := 'user'; + when too_many_rows then + raise_application_error(-20000, 'Parameter "-p=ut_path(s)" defined more than once. Only one "-p=ut_path(s)" parameter can be used.'); + end; + return l_paths; + end; + + function parse_color_enabled(a_params ut_varchar2_list) return varchar2 is + begin + for i in 1 .. cardinality(a_params) loop + if a_params(i) = '-c' then + return 'true'; + end if; + end loop; + return 'false'; + end; + + function parse_source_files_path_param(a_params ut_varchar2_list, a_param_name varchar2) return varchar2 is + l_path varchar2(4000); + begin + begin + select param_value + into l_path + from (select regexp_substr(column_value,'-'||a_param_name||'\=(.*)',1,1,'c',1) as param_value from table(a_params) ) + where param_value is not null; + exception + when no_data_found then + null; + when too_many_rows then + raise_application_error(-20000, 'Parameter "-'||a_param_name||'='||a_param_name||'" defined more than once. Only one "-'||a_param_name||'='||a_param_name||'" parameter can be used.'); + end; + return l_path; + end; + +begin + l_call_params := parse_reporting_params(l_input_params); + for i in l_call_params.first .. l_call_params.last loop + l_run_cursor_sql := + l_run_cursor_sql || + 'select '''||l_call_params(i).reporter_id||''' as reporter_id,' || + ' '''||l_call_params(i).ut_reporter_name||''' as reporter_name' || + ' from dual'; + l_out_cursor_sql := + l_out_cursor_sql || + 'select '''||l_call_params(i).reporter_id||''' as reporter_id,' || + ' '''||l_call_params(i).output_to_screen||''' as output_to_screen,' || + ' '''||l_call_params(i).output_file_name||''' as output_file_name' || + ' from dual'; + if i < l_call_params.last then + l_run_cursor_sql := l_run_cursor_sql || ' union all '; + l_out_cursor_sql := l_out_cursor_sql || ' union all '; + end if; + end loop; + + :l_paths := parse_suite_paths_param(l_input_params); + :l_color_enabled := parse_color_enabled(l_input_params); + + :l_source_path := parse_source_files_path_param(l_input_params,'source_path'); + :l_test_path := parse_source_files_path_param(l_input_params,'test_path'); + + if l_run_cursor_sql is not null then + open :l_run_params_cur for l_run_cursor_sql; + end if; + if l_out_cursor_sql is not null then + open :l_out_params_cur for l_out_cursor_sql; + end if; + dbms_output.put_line(:l_source_path); +end; +/ +set termout off + + +/** + * Convert paths to substitution variable + */ +column source_path new_value source_path noprint; +select :l_source_path as source_path from dual; +column test_path new_value test_path noprint; +select :l_test_path as test_path from dual; + +--try running on windows +$ "&&client_path\file_list.bat" "&&project_path" "l_source_files" "&&client_path\source_file_list.sql.tmp" "&&source_path" +$ "&&client_path\file_list.bat" "&&project_path" "l_test_files" "&&client_path\test_file_list.sql.tmp" "&&test_path" +--try running on linux/unix +! "&&client_path/file_list" "&&project_path" "l_source_files" "&&client_path/source_file_list.sql.tmp" "&&source_path" +! "&&client_path/file_list" "&&project_path" "l_test_files" "&&client_path/test_file_list.sql.tmp" "&&test_path" + +undef source_path +undef test_path + +/* + * Generate the project source and tests files, saving it into the l_source_files and l_test_files bind variables + */ +@&&client_path/source_file_list.sql.tmp +@&&client_path/test_file_list.sql.tmp + + +/* +* Generate runner script +*/ +spool &&client_path/run_in_background.sql.tmp +declare + l_reporter_id varchar2(250); + l_reporter_name varchar2(250); + l_file_path varchar2(32767); + procedure p(a_text varchar2) is begin dbms_output.put_line(a_text); end; +begin + p('set serveroutput on size unlimited format truncated'); + p('set trimspool on'); + p('set pagesize 0'); + p('set linesize 4000'); + p('spool ut_run.dbms_output.log'); + p('declare'); + p(' v_reporter ut_reporter_base;'); + p(' v_reporters_list ut_reporters := ut_reporters();'); + p(' v_source_files ut_varchar2_list := ut_varchar2_list();'); + p(' v_test_files ut_varchar2_list := ut_varchar2_list();'); + p('begin'); + if :l_run_params_cur%isopen then + loop + fetch :l_run_params_cur into l_reporter_id, l_reporter_name; + exit when :l_run_params_cur%notfound; + p(' v_reporter := '||l_reporter_name||'();'); + p(' v_reporter.reporter_id := '''||l_reporter_id||''';'); + p(' v_reporters_list.extend; v_reporters_list(v_reporters_list.last) := v_reporter;'); + end loop; + close :l_run_params_cur; + end if; + + loop + fetch :l_source_files into l_file_path; + exit when :l_source_files%notfound or l_file_path is null; + p(' v_source_files.extend; v_source_files(v_source_files.last) := '''||l_file_path||''';'); + end loop; + + loop + fetch :l_test_files into l_file_path; + exit when :l_test_files%notfound or l_file_path is null; + p(' v_test_files.extend; v_test_files(v_test_files.last) := '''||l_file_path||''';'); + end loop; + + p(' ut_runner.run( '); + p(' a_paths => ut_varchar2_list('||:l_paths||'),'); + p(' a_reporters => v_reporters_list,'); + p(' a_source_files => v_source_files,'); + p(' a_test_files => v_test_files,'); + p(' a_color_console => '||:l_color_enabled||' );'); + p('end;'); + p('/'); + p('spool off'); + p('exit'); +end; +/ +spool off + + +/* +* Generate output retrieval script +*/ +spool &&client_path/gather_data_from_outputs.sql.tmp +declare + l_reporter_id varchar2(250); + l_output_file_name varchar2(250); + l_output_to_screen varchar2(250); + l_need_spool boolean; + procedure p(a_text varchar2) is begin dbms_output.put_line(a_text); end; +begin + if :l_out_params_cur%isopen then + loop + fetch :l_out_params_cur into l_reporter_id, l_output_to_screen, l_output_file_name; + exit when :l_out_params_cur%notfound; + l_need_spool := (l_output_file_name is not null); + p( 'set termout '||l_output_to_screen); + if l_need_spool then + p( 'spool '||l_output_file_name); + end if; + p( 'select * from table( ut_output_buffer.get_lines('''||l_reporter_id||''') );'); + if l_need_spool then + p('spool off'); + end if; + end loop; + end if; +end; +/ +spool off + + +/* +* Execute runner script in background process +*/ +set define # +--try running on windows +$ start /min sqlplus ##conn_str @##client_path/run_in_background.sql.tmp +--try running on linux/unix +! sqlplus ##conn_str @##client_path/run_in_background.sql.tmp & +set define & +set termout on + + +--make sure we fetch row by row to indicate the progress +set arraysize 1 +/* +* Gather outputs from reporters one by one while runner script executes. +*/ +@&&client_path/gather_data_from_outputs.sql.tmp + +set termout off +/* +* cleanup temporary sql files +*/ +--try running on windows +$ del &&client_path\*.sql.tmp +--try running on linux/unix +! rm &&client_path/*.sql.tmp + +exit