Commit: f5b9b7627c0a015350b54baec3bc75fc2fb30a51 Author: Matt Ficken <v-maf...@microsoft.com> Sun, 17 Feb 2013 15:21:32 -0800 Parents: 54a9a64e1ab154f9cbe8f318047c34c769212c8b Branches: master
Link: http://git.php.net/?p=pftt2.git;a=commitdiff;h=f5b9b7627c0a015350b54baec3bc75fc2fb30a51 Log: Support for PhpUnit NTS test cases Former-commit-id: 03bd7311110bf3035966300c98cbe93f2a2477f4 Changed paths: M README.mdown M doc/index.html M src/com/mostc/pftt/main/PfttMain.java M src/com/mostc/pftt/model/app/PhpUnitSourceTestPack.java M src/com/mostc/pftt/model/sapi/SharedSAPIInstanceTestCaseGroupKey.java M src/com/mostc/pftt/results/PhpResultPackWriter.java M src/com/mostc/pftt/results/PhpUnitResultWriter.java M src/com/mostc/pftt/results/PhpUnitTestResult.java M src/com/mostc/pftt/results/PhptResultWriter.java M src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java M src/com/mostc/pftt/runner/AbstractPhpUnitTestCaseRunner.java M src/com/mostc/pftt/runner/CliPhpUnitTestCaseRunner.java M src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java M src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java M src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java M src/com/mostc/pftt/scenario/AbstractSAPIScenario.java M src/com/mostc/pftt/scenario/AbstractWebServerScenario.java M src/com/mostc/pftt/scenario/CLIScenario.java A src/com/mostc/pftt/scenario/NormalPathsScenario.java A src/com/mostc/pftt/scenario/PathsScenario.java M src/com/mostc/pftt/scenario/Scenario.java M src/com/mostc/pftt/scenario/ScenarioSet.java A src/com/mostc/pftt/scenario/UNCPathsScenario.java M src/com/mostc/pftt/util/WinDebugManager.java
diff --git a/README.mdown b/README.mdown index 9411b69..109eb1e 100644 --- a/README.mdown +++ b/README.mdown @@ -84,25 +84,25 @@ Download specific release (test-pack and build) Run all PHPTs from the test-pack - > pftt phpt_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 + > pftt core_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 Runs PHPTs only from list in SKIP_list_file (can add comments to lists with a ; or #) - > pftt phpt_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file + > pftt core_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file Runs PHPTs that contain 021 (name fragment) in their name - > pftt phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021 + > pftt core_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021 NOTE: On Windows PFTT will prompt you to elevate it to Administrator privileges for some operations to configure Windows Error Reporting and firewall If build or test-pack not in current directory, automatically checks php-sdk (so you can ommit c:\php-sdk, etc...) - > pftt phpt_all php-5.4.7-win32-vc9-x86 php-test-pack-5.4-r1234567 + > pftt core_all php-5.4.7-win32-vc9-x86 php-test-pack-5.4-r1234567 Opens a GUI to efficiently review large amounts of tests - > pftt -gui phpt_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 pftt -gui -config config_file phpt_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 pftt -gui -config config_file phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 + > pftt -gui core_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 pftt -gui -config config_file core_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 pftt -gui -config config_file core_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 Shows help info (additional commands, etc...) @@ -110,17 +110,17 @@ Shows help info (additional commands, etc...) Run all PHPTs from the test-pack, running each PHPT 3 times - > pftt -stress_each 3 phpt_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 + > pftt -stress_each 3 core_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 ### Functional Build Comparison(FBC) Reports Run one test pass - > pftt phpt_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 Or pftt phpt_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file Or pftt phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021 + > pftt core_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 Or pftt core_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file Or pftt core_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021 Run a second test pass, using a different build and/or test-pack - > pftt pa C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 Or pftt phpt_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 SKIP_list_file Or pftt phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 021 + > pftt pa C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 Or pftt core_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 SKIP_list_file Or pftt core_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 021 PFTT will automatically generate an FBC report and display it using system default web browser @@ -130,7 +130,7 @@ Setup Wordpress (or other ~20 other PHP application), IIS and MySQL Run PHPT tests on Apache (instead of CLI) - > pftt -config apache phpt_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 Or pftt phpt_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file Or pftt phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021 + > pftt -config apache core_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 Or pftt core_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file Or pftt core_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021 ## DEVELOPMENT @@ -174,7 +174,7 @@ If the application uses PHPUnit, implement [PhpUnitAppTestPack](doc/apidoc/com/m ### For crashes that happen every time 1. Create a list of the tests that are crashing or might be crashing -2. Run with -debug_all and phpt_list +2. Run with -debug_all and core_list This will run all the tests in a Debugger (WinDebug for Windows and GDB for Linux). Do 1 first to reduce the number of tests to run since they'll run much slower in a debugger. @@ -182,7 +182,7 @@ When testing with Apache, this will run the Debugger on Apache to help trace Apa ### For tests that crash occasionally -These options may be useful with phpt_list or phpt_all or phpt_named. -run_group_times_all, -run_test_times and -debug_list especially. +These options may be useful with core_list or core_all or core_named. -run_group_times_all, -run_test_times and -debug_list especially. -run_test_times_all <N> - runs each test N times in a row/consecutively -run_test_times_list <N> <list file> - runs tests in that list N times. if used with -run_test_times_all, tests not in list can be run different number of times from tests in list (ex: run listed tests 5 times, run all other tests 2 times). diff --git a/doc/index.html b/doc/index.html index 99355f6..dead982 100644 --- a/doc/index.html +++ b/doc/index.html @@ -97,24 +97,24 @@ For convenience can do</p> <code>pftt rg MASTER TS rc165a0b</code> <p>Run all PHPTs from the test-pack</p> -<code>pftt phpt_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567</code> +<code>pftt core_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567</code> <p>Runs PHPTs only from list in SKIP_list_file (can add comments to lists with a ; or #)</p> -<code>pftt phpt_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file</code> +<code>pftt core_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file</code> <p>Runs PHPTs that contain 021 (name fragment) in their name</p> -<code>pftt phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021</code> +<code>pftt core_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021</code> <p><b>NOTE:</b> On Windows PFTT will prompt you to elevate it to Administrator privileges for some operations to configure Windows Error Reporting and firewall</p> <p>If build or test-pack not in current directory, automatically checks php-sdk (so you can ommit c:\php-sdk, etc...)</p> -<code>pftt phpt_all php-5.4.7-win32-vc9-x86 php-test-pack-5.4-r1234567</code> +<code>pftt core_all php-5.4.7-win32-vc9-x86 php-test-pack-5.4-r1234567</code> <p>Opens a GUI to efficiently review large amounts of tests</p> -<code>pftt -gui phpt_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567</code> -<code>pftt -gui -config config_file phpt_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 </code> -<code>pftt -gui -config config_file phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567</code> +<code>pftt -gui core_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567</code> +<code>pftt -gui -config config_file core_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 </code> +<code>pftt -gui -config config_file core_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567</code> <p><a href="PhptDebuggerFrame1.png" target="_new"><img src="PhptDebuggerFrame1.png" width="640" border="0"/></a></p> @@ -122,26 +122,26 @@ For convenience can do</p> <code>pftt -help</code> <p>Run all PHPTs from the test-pack, running each PHPT 3 times</p> -<code>pftt -stress_each 3 phpt_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567</code> +<code>pftt -stress_each 3 core_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567</code> <h2>Functional Build Comparison(FBC) Reports</h2> <p>Run one test pass</p> <code> -pftt phpt_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 +pftt core_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 <span>Or</span> -pftt phpt_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file +pftt core_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file <span>Or</span> -pftt phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021 +pftt core_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021 </code> <p>Run a second test pass, using a different build and/or test-pack</p> <code> pftt pa C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 <span>Or</span> -pftt phpt_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 SKIP_list_file +pftt core_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 SKIP_list_file <span>Or</span> -pftt phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 021 +pftt core_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234568 021 </code> <p>PFTT will automatically generate an FBC report and display it using system default web browser</p> @@ -150,7 +150,7 @@ pftt phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4- <code>pftt -config iis,wordpress,mysql setup</code> <p>Run PHPT tests on Apache (instead of CLI)</p> -<code>pftt -config apache phpt_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 Or pftt phpt_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file Or pftt phpt_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021</code> +<code>pftt -config apache core_all C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 Or pftt core_list C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 SKIP_list_file Or pftt core_named C:\php-sdk\php-5.4.7-win32-vc9-x86 C:\php-sdk\php-test-pack-5.4-r1234567 021</code> <h1>Development</h1> @@ -209,7 +209,7 @@ That should be it (PFTT comes with eclipse .project and .classpath files which a <ol> <li>Create a list of the tests that are crashing or might be crashing</li> -<li>Run with -debug_all and phpt_list</li> +<li>Run with -debug_all and core_list</li> </ol> <p>This will run all the tests in a Debugger (WinDebug for Windows and GDB for Linux). Do 1 first to reduce the number of tests to run since they'll run much slower in a debugger.</p> @@ -218,7 +218,7 @@ That should be it (PFTT comes with eclipse .project and .classpath files which a <h3>For tests that crash occasionally</h3> -<p>These options may be useful with phpt_list or phpt_all or phpt_named. -run_group_times_all, -run_test_times and -debug_list especially.</p> +<p>These options may be useful with core_list or core_all or core_named. -run_group_times_all, -run_test_times and -debug_list especially.</p> <ul> <li>-run_test_times_all <N> - runs each test N times in a row/consecutively</li> diff --git a/src/com/mostc/pftt/main/PfttMain.java b/src/com/mostc/pftt/main/PfttMain.java index 5b7eace..925ae11 100644 --- a/src/com/mostc/pftt/main/PfttMain.java +++ b/src/com/mostc/pftt/main/PfttMain.java @@ -13,62 +13,35 @@ import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Map; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.HttpVersion; -import org.apache.http.params.HttpParams; -import org.apache.http.params.HttpProtocolParams; -import org.apache.http.params.SyncBasicHttpParams; -import org.apache.http.protocol.HttpProcessor; -import org.apache.http.protocol.HttpRequestExecutor; -import org.apache.http.protocol.ImmutableHttpProcessor; -import org.apache.http.protocol.RequestConnControl; -import org.apache.http.protocol.RequestContent; -import org.apache.http.protocol.RequestExpectContinue; -import org.apache.http.protocol.RequestTargetHost; -import org.apache.http.protocol.RequestUserAgent; import org.codehaus.groovy.tools.shell.Groovysh; import org.codehaus.groovy.tools.shell.IO; import com.github.mattficken.io.StringUtil; import com.mostc.pftt.host.AHost; import com.mostc.pftt.host.LocalHost; -import com.mostc.pftt.host.SSHHost; import com.mostc.pftt.model.app.PhpUnitSourceTestPack; -import com.mostc.pftt.model.app.PhpUnitTestCase; import com.mostc.pftt.model.core.EBuildBranch; import com.mostc.pftt.model.core.EBuildType; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.model.core.PhpDebugPack; import com.mostc.pftt.model.core.PhptSourceTestPack; import com.mostc.pftt.model.core.PhptTestCase; -import com.mostc.pftt.model.sapi.ApacheManager; -import com.mostc.pftt.model.sapi.WebServerInstance; -import com.mostc.pftt.model.sapi.WebServerManager; import com.mostc.pftt.model.smoke.ESmokeTestStatus; import com.mostc.pftt.model.smoke.PhptTestCountsMatchSmokeTest; import com.mostc.pftt.model.smoke.RequiredExtensionsSmokeTest; import com.mostc.pftt.model.smoke.RequiredFeaturesSmokeTest; import com.mostc.pftt.report.AbstractReportGen; import com.mostc.pftt.results.ConsoleManager; -import com.mostc.pftt.results.ITestResultReceiver; import com.mostc.pftt.results.LocalConsoleManager; import com.mostc.pftt.results.PhpResultPackReader; import com.mostc.pftt.results.PhpResultPackWriter; import com.mostc.pftt.results.ConsoleManager.EPrintType; -import com.mostc.pftt.runner.AbstractPhpUnitTestCaseRunner; -import com.mostc.pftt.runner.CliPhpUnitTestCaseRunner; -import com.mostc.pftt.runner.HttpPhpUnitTestCaseRunner; import com.mostc.pftt.runner.LocalPhpUnitTestPackRunner; import com.mostc.pftt.runner.LocalPhptTestPackRunner; import com.mostc.pftt.scenario.AbstractSAPIScenario; -import com.mostc.pftt.scenario.AbstractSMBScenario.SMBStorageDir; -import com.mostc.pftt.scenario.SMBDFSScenario; -import com.mostc.pftt.scenario.SMBDeduplicationScenario; import com.mostc.pftt.scenario.Scenario; import com.mostc.pftt.scenario.ScenarioSet; import com.mostc.pftt.util.DownloadUtil; @@ -83,14 +56,20 @@ import com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair; * * @author Matt Ficken * + * To Learn about the details of PHP Testing, PHPT, PhpUnit, Debugging or Configuration, see these classes: + * -ApacheManager IISManager BuiltinWebServerManager + * -PhptTestCase AbstractPhptTestCaseRunner2 + * -PhpBuild + * -PhpUnitTestCase AbstractPhpUnitTestCaseRunner + * + * */ -// TODO phpunit_list phpunit_all phpunit_named commands // TODO change how ScenarioSets are permuted // can have multiple database scenarios in 1 ScenarioSet for PHPTs // can only have 1 for applications // can only have 1 for PhpUnit -// TODO phpt_all, etc... should display location of result-pack being written +// TODO core_all, etc... should display location of result-pack being written public class PfttMain { protected LocalHost host; @@ -260,10 +239,10 @@ public class PfttMain { System.out.println("Usage: pftt <optional options> <command>"); System.out.println(); System.out.println("Commands:"); - System.out.println("phpt_all <build> <test-pack> - runs all tests in given test pack"); + System.out.println("core_all <build> <test-pack> - runs all tests in given test pack"); System.out.println("phpt_repro <build> <test-pack> <XML result-pack file> - replays .XML file from previous result-pack run"); - System.out.println("phpt_named <build> <test-pack> <test1> <test2> <test name fragment> - runs named tests or tests matching name pattern"); - System.out.println("phpt_list <build> <test-pack> <file> - runs list of tests stored in file"); + System.out.println("core_named <build> <test-pack> <test1> <test2> <test name fragment> - runs named tests or tests matching name pattern"); + System.out.println("core_list <build> <test-pack> <file> - runs list of tests stored in file"); System.out.println("custom <build> - runs PFTT specific functional tests (bugs that can not be tested using PHP testsT)"); System.out.println("aut - runs Application (PHP)Unit Tests"); System.out.println("help"); @@ -370,12 +349,12 @@ public class PfttMain { return config==null?ScenarioSet.getDefaultScenarioSets():config.getScenarioSets(); } - protected static void cmd_phpt_all(PfttMain rt, LocalConsoleManager cm, Config config, PhpBuild build, PhptSourceTestPack test_pack) throws Exception { + protected static void cmd_core_all(PfttMain rt, LocalConsoleManager cm, Config config, PhpBuild build, PhptSourceTestPack test_pack) throws Exception { List<AHost> hosts = config.getHosts(); rt.run_all(cm, build, test_pack, hosts.isEmpty() ? new LocalHost() : hosts.get(0), getScenarioSets(config)); } - protected static void cmd_phpt_list(PfttMain rt, LocalConsoleManager cm, Config config, PhpBuild build, PhptSourceTestPack test_pack, File list_file) throws Exception { + protected static void cmd_core_list(PfttMain rt, LocalConsoleManager cm, Config config, PhpBuild build, PhptSourceTestPack test_pack, File list_file) throws Exception { BufferedReader fr = new BufferedReader(new FileReader(list_file)); LinkedList<String> tests = new LinkedList<String>(); String line; @@ -396,7 +375,7 @@ public class PfttMain { rt.run_named_tests(cm, build, test_pack, hosts.isEmpty() ? new LocalHost() : hosts.get(0), getScenarioSets(config), tests); } - protected static void cmd_phpt_named(PfttMain rt, LocalConsoleManager cm, Config config, PhpBuild build, PhptSourceTestPack test_pack, List<String> names) throws Exception { + protected static void cmd_core_named(PfttMain rt, LocalConsoleManager cm, Config config, PhpBuild build, PhptSourceTestPack test_pack, List<String> names) throws Exception { List<AHost> hosts = config.getHosts(); rt.run_named_tests(cm, build, test_pack, hosts.isEmpty() ? new LocalHost() : hosts.get(0), getScenarioSets(config), names); } @@ -811,11 +790,11 @@ public class PfttMain { // if (command!=null) { - if (command.equals("phpunit_named")||command.equals("phpunitnamed")||command.equals("pun")) { + if (command.equals("app_named")||command.equals("appnamed")||command.equals("an")) { // TODO - } else if (command.equals("phpunit_list")||command.equals("phpunitist")||command.equals("pul")) { + } else if (command.equals("app_list")||command.equals("applist")||command.equals("al")) { // TODO - } else if (command.equals("phpunit_all")||command.equals("phpunitall")||command.equals("pua")) { + } else if (command.equals("app_all")||command.equals("appall")||command.equals("aa")) { // TODO ScenarioSet scenario_set = config.getScenarioSets().get(0); // TODO @@ -830,10 +809,10 @@ public class PfttMain { r.runAllTests(test_pack); tmgr.close(); - } else if (command.equals("phpt_named")||command.equals("phptnamed")||command.equals("phptn")||command.equals("pn")) { + } else if (command.equals("core_named")||command.equals("corenamed")||command.equals("cornamed")||command.equals("coren")||command.equals("cn")) { if (!(args.length > args_i+3)) { System.err.println("User Error: must specify build, test-pack and name(s) and/or name fragment(s)"); - System.out.println("usage: pftt phpt_named <path to PHP build> <path to PHPT test-pack> <test case names or name fragments (separated by spaces)>"); + System.out.println("usage: pftt core_named <path to PHP build> <path to PHPT test-pack> <test case names or name fragments (separated by spaces)>"); System.exit(-255); return; } @@ -864,14 +843,14 @@ public class PfttMain { cm.println(EPrintType.IN_PROGRESS, "Test-Pack", test_pack.toString()); HostEnvUtil.prepareHostEnv(rt.host, cm, build, !cm.isDisableDebugPrompt()); - cmd_phpt_named(rt, cm, config, build, test_pack, names); + cmd_core_named(rt, cm, config, build, test_pack, names); System.out.println("PFTT: finished"); - } else if (command.equals("phpt_list")||command.equals("phptlist")||command.equals("phptl")||command.equals("pl")) { + } else if (command.equals("core_list")||command.equals("corelist")||command.equals("corlist")||command.equals("corel")||command.equals("cl")) { if (!(args.length > args_i+3)) { System.err.println("User Error: must specify build, test-pack and list file"); System.out.println("usage: list file must contain plain-text list names of tests to execute"); - System.out.println("usage: pftt phpt_list <path to PHP build> <path to PHPT test-pack> <list file>"); + System.out.println("usage: pftt core_list <path to PHP build> <path to PHPT test-pack> <list file>"); System.exit(-255); return; } @@ -903,7 +882,7 @@ public class PfttMain { cm.println(EPrintType.IN_PROGRESS, "Test-Pack", test_pack.toString()); HostEnvUtil.prepareHostEnv(rt.host, cm, build, !cm.isDisableDebugPrompt()); - cmd_phpt_list(rt, cm, config, build, test_pack, list_file); + cmd_core_list(rt, cm, config, build, test_pack, list_file); System.out.println("PFTT: finished"); } else if (command.equals("phpt_repro")||command.equals("phpt_replay")||command.equals("phpt_re")||command.equals("phptrepro")||command.equals("phptreplay")||command.equals("phptre")||command.equals("pr")) { @@ -911,10 +890,10 @@ public class PfttMain { // TODO if -c gives config file(s) different from result-pack, show warning - } else if (command.equals("phpt_all")||command.equals("phptall")||command.equals("phpta")||command.equals("pa")) { + } else if (command.equals("core_all")||command.equals("coreall")||command.equals("corall")||command.equals("corea")||command.equals("ca")) { if (!(args.length > args_i+2)) { System.err.println("User Error: must specify build and test-pack"); - System.out.println("usage: pftt phpt_all <path to PHP build> <path to PHPT test-pack>"); + System.out.println("usage: pftt core_all <path to PHP build> <path to PHPT test-pack>"); System.exit(-255); return; } @@ -941,7 +920,7 @@ public class PfttMain { // run all tests HostEnvUtil.prepareHostEnv(rt.host, cm, build, !cm.isDisableDebugPrompt()); - cmd_phpt_all(rt, cm, config, build, test_pack); + cmd_core_all(rt, cm, config, build, test_pack); System.out.println("PFTT: finished"); } else if (command.equals("setup")||command.equals("set")||command.equals("setu")) { diff --git a/src/com/mostc/pftt/model/app/PhpUnitSourceTestPack.java b/src/com/mostc/pftt/model/app/PhpUnitSourceTestPack.java index 3d8ad89..532da92 100644 --- a/src/com/mostc/pftt/model/app/PhpUnitSourceTestPack.java +++ b/src/com/mostc/pftt/model/app/PhpUnitSourceTestPack.java @@ -10,6 +10,8 @@ import java.util.Comparator; import java.util.List; import java.util.Map; +import javax.annotation.Nullable; + import com.caucho.quercus.QuercusContext; import com.caucho.quercus.function.AbstractFunction; import com.caucho.quercus.parser.QuercusParseException; @@ -35,7 +37,12 @@ import com.mostc.pftt.results.ITestResultReceiver; * and provide all the information from the phpunit.dist.xml file. * the Javadoc on the PhpUnitDist methods explains which method matches which XML tag. * 4. provide files and directories to include to PhpUnitSourceTestPack (optional) - * 5. you may provide some additional info to PhpUnitSourceTestPack (optional; mainly, its just doing steps 3 and 4) + * 5. check if any tests are non-thread-safe (NTS) and if so, add their file names or partial file names + * to the list returned by PhpUnitSourceTestPack#getNonThreadSafeTestFileNames + * + * To speed test running, making testing more convenient and thus done more frequently and thoroughly, + * test running is threaded, so multiple tests are run at the same time except for NTS tests. + * 6. you may provide some additional info to PhpUnitSourceTestPack (optional; mainly, its just doing steps 3 and 4) * * @author Matt Ficken * @@ -316,5 +323,23 @@ public abstract class PhpUnitSourceTestPack implements SourceTestPack<PhpUnitAct public abstract String getVersionString(); public abstract boolean open(ConsoleManager cm, AHost host) throws Exception; + + public String getName() { + return getVersionString(); + } + + /** Sometimes there are multiple tests that share a common resource (such as a file directory + * or database) and can not be run at the same time. Such tests are non-thread-safe (NTS). + * + * Return the full or partial filenames of NTS tests here. The returned array is processed in + * order. If any string from the same string array matches, all tests matching that array will + * be run in the same thread. + * + * @return + */ + @Nullable + public String[][] getNonThreadSafeTestFileNames() { + return null; + } } // end public abstract class PhpUnitSourceTestPack diff --git a/src/com/mostc/pftt/model/sapi/SharedSAPIInstanceTestCaseGroupKey.java b/src/com/mostc/pftt/model/sapi/SharedSAPIInstanceTestCaseGroupKey.java index 1edcbe3..6402078 100644 --- a/src/com/mostc/pftt/model/sapi/SharedSAPIInstanceTestCaseGroupKey.java +++ b/src/com/mostc/pftt/model/sapi/SharedSAPIInstanceTestCaseGroupKey.java @@ -23,9 +23,11 @@ public class SharedSAPIInstanceTestCaseGroupKey extends TestCaseGroupKey { } public void setSAPIInstance(ConsoleManager cm, AHost host, SAPIInstance sapi_instance) { + final Thread c = Thread.currentThread(); + SAPIInstance this_sapi_instance; synchronized(sapi_instances) { - this_sapi_instance = sapi_instances.get(Thread.currentThread()); + this_sapi_instance = sapi_instances.get(c); } if (this_sapi_instance!=null&&this_sapi_instance!=sapi_instance) { @@ -33,7 +35,7 @@ public class SharedSAPIInstanceTestCaseGroupKey extends TestCaseGroupKey { this_sapi_instance.close(); } - sapi_instances.put(Thread.currentThread(), sapi_instance); + sapi_instances.put(c, sapi_instance); } public SAPIInstance getSAPIInstance() { diff --git a/src/com/mostc/pftt/results/PhpResultPackWriter.java b/src/com/mostc/pftt/results/PhpResultPackWriter.java index b215174..31e1253 100644 --- a/src/com/mostc/pftt/results/PhpResultPackWriter.java +++ b/src/com/mostc/pftt/results/PhpResultPackWriter.java @@ -11,6 +11,7 @@ import java.util.concurrent.LinkedBlockingQueue; import com.mostc.pftt.host.AHost; import com.mostc.pftt.host.LocalHost; import com.mostc.pftt.model.TestCase; +import com.mostc.pftt.model.app.PhpUnitSourceTestPack; import com.mostc.pftt.model.core.EBuildBranch; import com.mostc.pftt.model.core.EBuildSourceType; import com.mostc.pftt.model.core.ECPUArch; @@ -177,13 +178,13 @@ public class PhpResultPackWriter extends PhpResultPack implements ITestResultRec PhpUnitResultWriter w; if (smap==null) { smap = new HashMap<ScenarioSet,PhpUnitResultWriter>(); - w = new PhpUnitResultWriter(phpunit_telem_dir(this_host, this_scenario_set)); + w = new PhpUnitResultWriter(phpunit_telem_dir(this_host, this_scenario_set, this_result.test_case.php_unit_dist.src_test_pack), this_scenario_set, this_result.test_case.php_unit_dist.src_test_pack); phpunit_writer_map.put(this_host, smap); smap.put(this_scenario_set, w); } else { w = smap.get(this_scenario_set); if (w==null) { - w = new PhpUnitResultWriter(phpunit_telem_dir(this_host, this_scenario_set)); + w = new PhpUnitResultWriter(phpunit_telem_dir(this_host, this_scenario_set, this_result.test_case.php_unit_dist.src_test_pack), this_scenario_set, this_result.test_case.php_unit_dist.src_test_pack); smap.put(this_scenario_set, w); } } @@ -268,8 +269,8 @@ public class PhpResultPackWriter extends PhpResultPack implements ITestResultRec results.add(new PhptResultQueueEntry(this_host, this_scenario_set, result)); } - protected File phpunit_telem_dir(AHost this_host, ScenarioSet this_scenario_set) { - return new File(host.joinIntoOnePath(telem_dir.getAbsolutePath(), this_host.getName(), "PhpUnit", this_scenario_set.toString())); + protected File phpunit_telem_dir(AHost this_host, ScenarioSet this_scenario_set, PhpUnitSourceTestPack test_pack) { + return new File(host.joinIntoOnePath(telem_dir.getAbsolutePath(), this_host.getName(), "PhpUnit", test_pack.getName(), this_scenario_set.toString())); } protected File phpt_telem_dir(AHost this_host, ScenarioSet this_scenario_set) { diff --git a/src/com/mostc/pftt/results/PhpUnitResultWriter.java b/src/com/mostc/pftt/results/PhpUnitResultWriter.java index e3736ba..8a3bce5 100644 --- a/src/com/mostc/pftt/results/PhpUnitResultWriter.java +++ b/src/com/mostc/pftt/results/PhpUnitResultWriter.java @@ -16,8 +16,10 @@ import javax.annotation.concurrent.NotThreadSafe; import org.kxml2.io.KXmlSerializer; +import com.github.mattficken.io.StringUtil; import com.mostc.pftt.model.app.EPhpUnitTestStatus; -import com.mostc.pftt.util.PFTTVersionUtil; +import com.mostc.pftt.model.app.PhpUnitSourceTestPack; +import com.mostc.pftt.scenario.ScenarioSet; /** Writes PhpUnitTestResults from a single test run with a single scenario set on a single host with a single build. * @@ -44,12 +46,12 @@ public class PhpUnitResultWriter { private String last_test_suite_name; private int test_count, percent_total, pass, failure, error, warning, notice, skip, deprecated, not_implemented, unsupported, test_exception, crash, bork, xskip; - public PhpUnitResultWriter(File dir) throws FileNotFoundException, IOException { + public PhpUnitResultWriter(File dir, ScenarioSet scenario_set, PhpUnitSourceTestPack test_pack) throws FileNotFoundException, IOException { this.dir = dir; dir.mkdirs(); - // TODO include hosts or scenario-set in file name because that will make it easier to view a bunch of them in Notepad++ or other MDIs - File file = new File(dir+"/phpunit.xml"); + // include scenario-set in file name to make it easier to view a bunch of them in Notepad++ or other MDIs + File file = new File(dir+"/phpunit_"+test_pack.getName()+"_"+scenario_set.getNameWithVersionInfo()+".xml"); // XXX write host, scenario_set and build to file (do in #writeTally or #close) serial = new KXmlSerializer(); @@ -109,16 +111,15 @@ public class PhpUnitResultWriter { // write file header - String test_suite_name = null; // TODO result.test_case.php_unit_dist.getName(); + String test_suite_name = result.test_case.php_unit_dist!=null && result.test_case.php_unit_dist.path!=null ? result.test_case.php_unit_dist.path.getPath() : null; if (is_first_result) { serial.startDocument("utf-8", null); serial.setPrefix("pftt", "pftt"); serial.startTag(null, "testsuites"); - if (test_suite_name==null) - writeTestSuiteStart(test_suite_name); + writeTestSuiteStart(test_suite_name); is_first_result = false; - } else if (test_suite_name!=null && last_test_suite_name != null && test_suite_name.equals(last_test_suite_name)) { + } else if (test_suite_name!=null && last_test_suite_name != null && !test_suite_name.equals(last_test_suite_name)) { writeTestSuiteEnd(); writeTestSuiteStart(test_suite_name); } @@ -179,7 +180,8 @@ public class PhpUnitResultWriter { private void writeTestSuiteStart(String test_suite_name) throws IllegalArgumentException, IllegalStateException, IOException { serial.startTag(null, "testsuite"); - // TODO serial.attribute(null, "name", test_suite_name); + if (StringUtil.isNotEmpty(test_suite_name)) + serial.attribute(null, "name", test_suite_name); } private void writeTestSuiteEnd() throws IllegalArgumentException, IllegalStateException, IOException { diff --git a/src/com/mostc/pftt/results/PhpUnitTestResult.java b/src/com/mostc/pftt/results/PhpUnitTestResult.java index 423db85..134a3eb 100644 --- a/src/com/mostc/pftt/results/PhpUnitTestResult.java +++ b/src/com/mostc/pftt/results/PhpUnitTestResult.java @@ -1,12 +1,13 @@ package com.mostc.pftt.results; import java.io.IOException; - import org.xmlpull.v1.XmlSerializer; +import com.github.mattficken.io.StringUtil; import com.mostc.pftt.host.Host; import com.mostc.pftt.model.app.EPhpUnitTestStatus; import com.mostc.pftt.model.app.PhpUnitTestCase; +import com.mostc.pftt.model.core.PhpIni; import com.mostc.pftt.scenario.ScenarioSet; /** result of running a PhpUnitTestCase @@ -21,6 +22,9 @@ public class PhpUnitTestResult { public final ScenarioSet scenario_set; public final Host host; public final String output; + public String http_response; + protected String sapi_output; + public PhpIni ini; public PhpUnitTestResult(PhpUnitTestCase test_case, EPhpUnitTestStatus status, ScenarioSet scenario_set, Host host, String output) { this.test_case = test_case; @@ -30,44 +34,100 @@ public class PhpUnitTestResult { this.output = output; } + public PhpUnitTestResult(PhpUnitTestCase test_case, EPhpUnitTestStatus status, ScenarioSet scenario_set, Host host, String output, PhpIni ini, String sapi_output) { + this(test_case, status, scenario_set, host, output); + this.sapi_output = sapi_output; + this.ini = ini; + } + public String getName() { return test_case.getName(); } - // @see PHPUnit/Util/Log/JUnit.php + public String getSAPIOutput() { + return sapi_output; + } + + public static boolean shouldStoreAllInfo(EPhpUnitTestStatus status) { + switch(status) { + case NOT_IMPLEMENTED: + case CRASH: + case ERROR: + case DEPRECATED: + case WARNING: + case NOTICE: + case BORK: + case UNSUPPORTED: + case TEST_EXCEPTION: + case FAILURE: + case SKIP: + return true; + default: + return false; + } + } + public void serial(XmlSerializer serial) throws IllegalArgumentException, IllegalStateException, IOException { + serial(serial, shouldStoreAllInfo(status)); + } + + // @see PHPUnit/Util/Log/JUnit.php + public void serial(XmlSerializer serial, boolean include_all) throws IllegalArgumentException, IllegalStateException, IOException { serial.startTag(null, "testcase"); // count of failures due to assertions - // TODO assertions - /* TODO test_case.getName(); - test_case.getClass(); - test_case.getFileName(); - name - class - file*/ + serial.attribute(null, "name", test_case.methodName); + serial.attribute(null, "class", test_case.className); + serial.attribute(null, "file", test_case.filename); + + serial.attribute("pftt", "status", status.toString()); + switch(status) { case NOT_IMPLEMENTED: case SKIP: case XSKIP: case CRASH: case ERROR: - case TEST_EXCEPTION: + case DEPRECATED: + case WARNING: + case NOTICE: + case BORK: + case UNSUPPORTED: // @see #addIncompleteTest and #addSkippedTest and #addError serial.startTag(null, "error"); - serial.attribute(null, "type", ""); // TODO serial.text(output); serial.endTag(null, "error"); break; + case TEST_EXCEPTION: + serial.startTag("pftt", "testException"); + serial.text(output); + serial.endTag("pftt", "testException"); + break; case FAILURE: // @see #addFailure serial.startTag(null, "failure"); - serial.attribute(null, "type", ""); // TODO serial.text(output); serial.endTag(null, "failure"); break; default: break; } + + // + if (include_all) { + if (StringUtil.isNotEmpty(http_response)) { + serial.startTag("pftt", "httpResponse"); + serial.text(http_response); + serial.endTag("pftt", "httpResponse"); + } + + if (ini!=null) { + serial.startTag("pftt", "ini"); + serial.text(ini.toString()); + serial.endTag("pftt", "ini"); + } + } + // + serial.endTag(null, "testcase"); } // end public void serial diff --git a/src/com/mostc/pftt/results/PhptResultWriter.java b/src/com/mostc/pftt/results/PhptResultWriter.java index 2ee6828..9ac6667 100644 --- a/src/com/mostc/pftt/results/PhptResultWriter.java +++ b/src/com/mostc/pftt/results/PhptResultWriter.java @@ -131,7 +131,7 @@ public class PhptResultWriter { // - if (false) { // TODO store_all || !cm.isNoResultFileForPassSkipXSkip()) { + if (store_all || !cm.isNoResultFileForPassSkipXSkip()) { // may want to skip storing result files for PASS, SKIP or XSKIP tests try { File result_file = new File(dir, test_case_base_name+".xml"); diff --git a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java index 2042a4c..074ff49 100644 --- a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java +++ b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java @@ -19,6 +19,7 @@ import com.mostc.pftt.model.ActiveTestPack; import com.mostc.pftt.model.SourceTestPack; import com.mostc.pftt.model.TestCase; import com.mostc.pftt.model.core.PhpBuild; +import com.mostc.pftt.model.core.PhptTestCase; import com.mostc.pftt.model.sapi.SAPIInstance; import com.mostc.pftt.model.sapi.SharedSAPIInstanceTestCaseGroupKey; import com.mostc.pftt.model.sapi.TestCaseGroupKey; @@ -327,6 +328,26 @@ public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S ex protected abstract boolean handleNTS(TestCaseGroupKey group_key, T test_case); + protected void addNTSTestCase(String[] ext_names, TestCaseGroupKey group_key, T test_case) { + NonThreadSafeExt<T> ext = non_thread_safe_tests.get(ext_names); + if (ext==null) { + ext = new NonThreadSafeExt<T>(ext_names); + non_thread_safe_exts.add(ext); + non_thread_safe_tests.put(ext_names, ext); + } + + ext.test_groups_by_key.get(group_key); + + // + TestCaseGroup<T> group = ext.test_groups_by_key.get(group_key); + if (group==null) { + group = new TestCaseGroup<T>(group_key); + ext.test_groups.add(group); + ext.test_groups_by_key.put(group_key, group); + } + group.test_cases.add(test_case); + } + protected void handleTS(LinkedList<TestCaseGroup<T>> thread_safe_list, TestCaseGroupKey group_key, T test_case) { TestCaseGroup<T> group = thread_safe_tests.get(group_key); if (group==null) { @@ -521,11 +542,6 @@ public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S ex Thread.yield(); } // end while } finally { - if (sa!=null) { - sa.close(); // TODO - sa = null; - } - if (parallel) { // @see HttpTestCaseRunner#http_execute which calls #notifyCrash // make sure a WebServerInstance is still running here, so it will be shared with each diff --git a/src/com/mostc/pftt/runner/AbstractPhpUnitTestCaseRunner.java b/src/com/mostc/pftt/runner/AbstractPhpUnitTestCaseRunner.java index bad1914..4e1ef27 100644 --- a/src/com/mostc/pftt/runner/AbstractPhpUnitTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/AbstractPhpUnitTestCaseRunner.java @@ -13,6 +13,7 @@ import com.mostc.pftt.model.app.EPhpUnitTestStatus; import com.mostc.pftt.model.app.PhpUnitTemplate; import com.mostc.pftt.model.app.PhpUnitTestCase; import com.mostc.pftt.model.core.PhpBuild; +import com.mostc.pftt.model.core.PhpIni; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.ITestResultReceiver; import com.mostc.pftt.results.PhpUnitTestResult; @@ -51,9 +52,10 @@ public abstract class AbstractPhpUnitTestCaseRunner extends AbstractTestCaseRunn protected final PhpBuild build; protected final PhpUnitTestCase test_case; protected final String my_temp_dir; + protected final PhpIni ini; protected boolean is_crashed; - public AbstractPhpUnitTestCaseRunner(ITestResultReceiver tmgr, Map<String, String> globals, Map<String, String> env, ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpUnitTestCase test_case, String my_temp_dir, Map<String,String> constants, String include_path, String[] include_files) { + public AbstractPhpUnitTestCaseRunner(ITestResultReceiver tmgr, Map<String, String> globals, Map<String, String> env, ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpUnitTestCase test_case, String my_temp_dir, Map<String,String> constants, String include_path, String[] include_files, PhpIni ini) { this.tmgr = tmgr; this.globals = globals; this.env = env; @@ -66,6 +68,7 @@ public abstract class AbstractPhpUnitTestCaseRunner extends AbstractTestCaseRunn this.constants = constants; this.include_path = include_path; this.include_files = include_files; + this.ini = ini; } protected static Pattern PAT_CLASS_NOT_FOUND, PAT_REQUIRE_ONCE_FAIL, PAT_SYNTAX_ERROR, PAT_FATAL_ERROR; @@ -132,19 +135,19 @@ public abstract class AbstractPhpUnitTestCaseRunner extends AbstractTestCaseRunn // EPhpUnitTestStatus status; - if (PAT_REQUIRE_ONCE_FAIL.matcher(output).find() || output.contains("404 Not Found")) { // TODO only check 404 w/ Http + if (checkRequireOnceError(output)) { status = EPhpUnitTestStatus.TEST_EXCEPTION; - tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, output)); + tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, output, ini, getCrashedSAPIOutput())); } else if (is_crashed) { if (PAT_CLASS_NOT_FOUND.matcher(output).find()) { status = EPhpUnitTestStatus.UNSUPPORTED; - tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, output)); + tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, output, ini, getCrashedSAPIOutput())); } else if (PAT_FATAL_ERROR.matcher(output).find()) { status = EPhpUnitTestStatus.ERROR; - tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, output)); + tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, output, ini, getCrashedSAPIOutput())); } else { // CRASH may really be a syntax error (BORK), check to make sure final ExecOutput syntax_eo = host.execOut(build.getPhpExe()+" -l "+template_file, Host.ONE_MINUTE, test_case.php_unit_dist.path.getAbsolutePath()); @@ -152,11 +155,11 @@ public abstract class AbstractPhpUnitTestCaseRunner extends AbstractTestCaseRunn // its a syntax error - BORK, as test case can't run status = EPhpUnitTestStatus.BORK; - tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, syntax_eo.output)); + tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, syntax_eo.output, ini, getCrashedSAPIOutput())); } else { status = EPhpUnitTestStatus.CRASH; - tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, output)); + tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, output, ini, getCrashedSAPIOutput())); } } } else { @@ -204,14 +207,22 @@ public abstract class AbstractPhpUnitTestCaseRunner extends AbstractTestCaseRunn if (status.isNotPass()) { final String output_str = StringUtil.join(lines, 1, "\n"); - tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, output_str)); + tmgr.addResult(host, scenario_set, notifyNotPass(new PhpUnitTestResult(test_case, status, scenario_set, host, output_str, ini, getCrashedSAPIOutput()))); } else { - tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, null)); + tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, status, scenario_set, host, null, ini, getCrashedSAPIOutput())); } } host.delete(my_temp_dir); } // end public void runTest + + protected PhpUnitTestResult notifyNotPass(PhpUnitTestResult result) { + return result; + } + + protected boolean checkRequireOnceError(String output) { + return PAT_REQUIRE_ONCE_FAIL.matcher(output).find(); + } /** configures PhpUnit globals to use the given database. * diff --git a/src/com/mostc/pftt/runner/CliPhpUnitTestCaseRunner.java b/src/com/mostc/pftt/runner/CliPhpUnitTestCaseRunner.java index b92d29c..9ead641 100644 --- a/src/com/mostc/pftt/runner/CliPhpUnitTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/CliPhpUnitTestCaseRunner.java @@ -8,6 +8,7 @@ import com.mostc.pftt.host.ExecOutput; import com.mostc.pftt.host.Host; import com.mostc.pftt.model.app.PhpUnitTestCase; import com.mostc.pftt.model.core.PhpBuild; +import com.mostc.pftt.model.core.PhpIni; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.ITestResultReceiver; import com.mostc.pftt.scenario.ScenarioSet; @@ -15,8 +16,8 @@ import com.mostc.pftt.scenario.ScenarioSet; public class CliPhpUnitTestCaseRunner extends AbstractPhpUnitTestCaseRunner { protected ExecOutput eo; - public CliPhpUnitTestCaseRunner(ITestResultReceiver tmgr, Map<String, String> globals, Map<String, String> env, ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpUnitTestCase test_case, String my_temp_dir, Map<String, String> constants, String include_path, String[] include_files) { - super(tmgr, globals, env, cm, host, scenario_set, build, test_case, my_temp_dir, constants, include_path, include_files); + public CliPhpUnitTestCaseRunner(ITestResultReceiver tmgr, Map<String, String> globals, Map<String, String> env, ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpUnitTestCase test_case, String my_temp_dir, Map<String, String> constants, String include_path, String[] include_files, PhpIni ini) { + super(tmgr, globals, env, cm, host, scenario_set, build, test_case, my_temp_dir, constants, include_path, include_files, ini); } @Override diff --git a/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java b/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java index e877d6c..77d3cef 100644 --- a/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java @@ -1,10 +1,10 @@ package com.mostc.pftt.runner; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.net.Socket; import java.util.Map; +import java.util.regex.Pattern; import org.apache.http.Header; import org.apache.http.HttpHost; @@ -19,14 +19,15 @@ import org.apache.http.protocol.HttpRequestExecutor; import com.github.mattficken.io.IOUtil; import com.mostc.pftt.host.AHost; +import com.mostc.pftt.model.app.EPhpUnitTestStatus; import com.mostc.pftt.model.app.PhpUnitTestCase; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.model.core.PhpIni; import com.mostc.pftt.model.sapi.WebServerInstance; import com.mostc.pftt.model.sapi.WebServerManager; -import com.mostc.pftt.model.smoke.RequiredExtensionsSmokeTest; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.ITestResultReceiver; +import com.mostc.pftt.results.PhpUnitTestResult; import com.mostc.pftt.scenario.ScenarioSet; import com.mostc.pftt.util.ErrorUtil; @@ -39,13 +40,12 @@ public class HttpPhpUnitTestCaseRunner extends AbstractPhpUnitTestCaseRunner { protected final HttpParams params; protected final HttpProcessor httpproc; protected final HttpRequestExecutor httpexecutor; - protected final PhpIni ini; public HttpPhpUnitTestCaseRunner(ITestResultReceiver tmgr, HttpParams params, HttpProcessor httpproc, HttpRequestExecutor httpexecutor, WebServerManager smgr, WebServerInstance web, Map<String, String> globals, Map<String, String> env, ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, - PhpUnitTestCase test_case, String my_temp_dir, Map<String, String> constants, String include_path, String[] include_files) { - super(tmgr, globals, env, cm, host, scenario_set, build, test_case, my_temp_dir, constants, include_path, include_files); + PhpUnitTestCase test_case, String my_temp_dir, Map<String, String> constants, String include_path, String[] include_files, PhpIni ini) { + super(tmgr, globals, env, cm, host, scenario_set, build, test_case, my_temp_dir, constants, include_path, include_files, ini); this.params = params; this.httpproc = httpproc; this.httpexecutor = httpexecutor; @@ -54,27 +54,23 @@ public class HttpPhpUnitTestCaseRunner extends AbstractPhpUnitTestCaseRunner { // don't need request_bytes, just doing a really basic HTTP GET this.response_bytes = new ByteArrayOutputStream(); - - ini = RequiredExtensionsSmokeTest.createDefaultIniCopy(host, build); } @Override protected String execute(String template_file) throws IOException, Exception { - // TODO handle INI with test-pack runner - // host.saveTextFile(my_temp_dir+"/php.ini", ini.toString()); - if (web!=null && !new File(web.getDocroot()).equals(new File(my_temp_dir))) - web = null; - - String resp = http_execute("/test.php"); - - /*if (resp.contains("404")) { - System.out.println("404 "+web); - System.exit(0); - }*/ - - //web.close(); + // Note: INI for test case provided in TestCaseGroupKey created in LocalPhpUnitTestPackRunner#createGroupKey - return resp; + return http_execute("/test.php"); + } + + protected static Pattern PAT_404_NOT_FOUND; + static { + PAT_404_NOT_FOUND = Pattern.compile(".*404 Not Found.*"); + } + + @Override + protected boolean checkRequireOnceError(String output) { + return super.checkRequireOnceError(output) || PAT_404_NOT_FOUND.matcher(output).find(); } protected String http_execute(String path) throws Exception { @@ -192,7 +188,18 @@ public class HttpPhpUnitTestCaseRunner extends AbstractPhpUnitTestCaseRunner { protected void markTestAsCrash() { is_crashed = true; - // TODO tmgr.add(new Result(EPhpUnitTestStatus.CRASH)); + tmgr.addResult(host, scenario_set, new PhpUnitTestResult(test_case, EPhpUnitTestStatus.CRASH, scenario_set, host, null)); + } + + @Override + protected PhpUnitTestResult notifyNotPass(PhpUnitTestResult result) { + if (conn==null) + return super.notifyNotPass(result); + + // store the http response used in this test to help user diagnose the failure + result.http_response = response_bytes.toString(); + + return super.notifyNotPass(result); } protected String do_http_get(String path) throws Exception { diff --git a/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java b/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java index 93064d5..710b301 100644 --- a/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java +++ b/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java @@ -19,6 +19,7 @@ import org.apache.http.protocol.RequestExpectContinue; import org.apache.http.protocol.RequestTargetHost; import org.apache.http.protocol.RequestUserAgent; +import com.github.mattficken.io.StringUtil; import com.mostc.pftt.host.AHost; import com.mostc.pftt.model.app.PhpUnitActiveTestPack; import com.mostc.pftt.model.app.PhpUnitSourceTestPack; @@ -27,13 +28,12 @@ import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.model.sapi.ApacheManager; import com.mostc.pftt.model.sapi.SharedSAPIInstanceTestCaseGroupKey; import com.mostc.pftt.model.sapi.TestCaseGroupKey; +import com.mostc.pftt.model.smoke.RequiredExtensionsSmokeTest; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.ITestResultReceiver; import com.mostc.pftt.scenario.AbstractFileSystemScenario.ITestPackStorageDir; import com.mostc.pftt.scenario.ScenarioSet; -// TODO NTS testcase support -// TODO when RESTARTING_AND_RETRYING, should report CRASH public class LocalPhpUnitTestPackRunner extends AbstractLocalTestPackRunner<PhpUnitActiveTestPack, PhpUnitSourceTestPack, PhpUnitTestCase> { final Map<String,String> globals = new HashMap<String,String>(); final Map<String, String> env = new HashMap<String,String>(); @@ -74,11 +74,26 @@ public class LocalPhpUnitTestPackRunner extends AbstractLocalTestPackRunner<PhpU @Override protected TestCaseGroupKey createGroupKey(PhpUnitTestCase test_case, TestCaseGroupKey group_key) throws Exception { - return group_key == null ? new SharedSAPIInstanceTestCaseGroupKey(null, null) : group_key; + return group_key == null ? new SharedSAPIInstanceTestCaseGroupKey( + // CRITICAL: provide the INI to run all PhpUnitTestCases + // unlike PhptTestCases all PhpUnitTestCases share the same INI and environment variables + RequiredExtensionsSmokeTest.createDefaultIniCopy(runner_host, build), + null) : + group_key; } @Override protected boolean handleNTS(TestCaseGroupKey group_key, PhpUnitTestCase test_case) { + final String[][] names = src_test_pack.getNonThreadSafeTestFileNames(); + if (names==null) + return false; + for ( String[] ext_names : names ) { + if (StringUtil.containsAnyIC(test_case.filename, ext_names)) { + addNTSTestCase(ext_names, group_key, test_case); + + return true; + } + } return false; } @@ -98,7 +113,7 @@ public class LocalPhpUnitTestPackRunner extends AbstractLocalTestPackRunner<PhpU @Override protected void runTest(TestCaseGroupKey group_key, PhpUnitTestCase test_case) throws IOException, Exception, Throwable { - AbstractPhpUnitTestCaseRunner r = sapi_scenario.createPhpUnitTestCaseRunner(this, group_key, cm, twriter, globals, env, runner_host, scenario_set, build, test_case, my_temp_dir, constants, test_case.php_unit_dist.getIncludePath(), test_case.php_unit_dist.getIncludeFiles()); + AbstractPhpUnitTestCaseRunner r = sapi_scenario.createPhpUnitTestCaseRunner(this, group_key, cm, twriter, globals, env, runner_host, scenario_set, build, test_case, my_temp_dir, constants, test_case.php_unit_dist.getIncludePath(), test_case.php_unit_dist.getIncludeFiles(), group_key.getPhpIni()); r.runTest(); } diff --git a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java index 188b3cd..702ac50 100644 --- a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java +++ b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java @@ -126,24 +126,7 @@ public class LocalPhptTestPackRunner extends AbstractLocalTestPackRunner<PhptAct protected boolean handleNTS(TestCaseGroupKey group_key, PhptTestCase test_case) { for (String[] ext_names:PhptTestCase.NON_THREAD_SAFE_EXTENSIONS) { if (StringUtil.startsWithAnyIC(test_case.getName(), ext_names)) { - NonThreadSafeExt<PhptTestCase> ext = non_thread_safe_tests.get(ext_names); - if (ext==null) { - ext = new NonThreadSafeExt<PhptTestCase>(ext_names); - non_thread_safe_exts.add(ext); - non_thread_safe_tests.put(ext_names, ext); - } - - ext.test_groups_by_key.get(group_key); - - // - TestCaseGroup<PhptTestCase> group = ext.test_groups_by_key.get(group_key); - if (group==null) { - group = new TestCaseGroup<PhptTestCase>(group_key); - ext.test_groups.add(group); - ext.test_groups_by_key.put(group_key, group); - } - group.test_cases.add(test_case); - // + addNTSTestCase(ext_names, group_key, test_case); return true; } diff --git a/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java b/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java index 30e0b20..fa9167a 100644 --- a/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java +++ b/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java @@ -92,6 +92,6 @@ public abstract class AbstractSAPIScenario extends AbstractSerialScenario { public abstract PhpIni createIniForTest(ConsoleManager cm, AHost host, PhpBuild build, PhptActiveTestPack active_test_pack, ScenarioSet scenario_set); - public abstract AbstractPhpUnitTestCaseRunner createPhpUnitTestCaseRunner(PhpUnitThread thread, TestCaseGroupKey group_key, ConsoleManager cm, ITestResultReceiver twriter, Map<String,String> globals, Map<String,String> env, AHost runner_host, ScenarioSet scenario_set, PhpBuild build, PhpUnitTestCase test_case, String my_temp_dir, Map<String,String> constants, String include_path, String[] include_files); + public abstract AbstractPhpUnitTestCaseRunner createPhpUnitTestCaseRunner(PhpUnitThread thread, TestCaseGroupKey group_key, ConsoleManager cm, ITestResultReceiver twriter, Map<String,String> globals, Map<String,String> env, AHost runner_host, ScenarioSet scenario_set, PhpBuild build, PhpUnitTestCase test_case, String my_temp_dir, Map<String,String> constants, String include_path, String[] include_files, PhpIni ini); } // end public abstract class AbstractSAPIScenario diff --git a/src/com/mostc/pftt/scenario/AbstractWebServerScenario.java b/src/com/mostc/pftt/scenario/AbstractWebServerScenario.java index 444c81f..e56b73e 100644 --- a/src/com/mostc/pftt/scenario/AbstractWebServerScenario.java +++ b/src/com/mostc/pftt/scenario/AbstractWebServerScenario.java @@ -174,8 +174,8 @@ public abstract class AbstractWebServerScenario extends AbstractSAPIScenario { } @Override - public AbstractPhpUnitTestCaseRunner createPhpUnitTestCaseRunner(PhpUnitThread thread, TestCaseGroupKey group_key, ConsoleManager cm, ITestResultReceiver twriter, Map<String,String> globals, Map<String,String> env, AHost runner_host, ScenarioSet scenario_set, PhpBuild build, PhpUnitTestCase test_case, String my_temp_dir, Map<String,String> constants, String include_path, String[] include_files) { - return new HttpPhpUnitTestCaseRunner(twriter, params, httpproc, httpexecutor, smgr, (WebServerInstance) ((SharedSAPIInstanceTestCaseGroupKey)group_key).getSAPIInstance(), globals, env, cm, runner_host, scenario_set, build, test_case, my_temp_dir, constants, include_path, include_files); + public AbstractPhpUnitTestCaseRunner createPhpUnitTestCaseRunner(PhpUnitThread thread, TestCaseGroupKey group_key, ConsoleManager cm, ITestResultReceiver twriter, Map<String,String> globals, Map<String,String> env, AHost runner_host, ScenarioSet scenario_set, PhpBuild build, PhpUnitTestCase test_case, String my_temp_dir, Map<String,String> constants, String include_path, String[] include_files, PhpIni ini) { + return new HttpPhpUnitTestCaseRunner(twriter, params, httpproc, httpexecutor, smgr, (WebServerInstance) ((SharedSAPIInstanceTestCaseGroupKey)group_key).getSAPIInstance(), globals, env, cm, runner_host, scenario_set, build, test_case, my_temp_dir, constants, include_path, include_files, ini); } } // end public abstract class AbstractWebServerScenario diff --git a/src/com/mostc/pftt/scenario/CLIScenario.java b/src/com/mostc/pftt/scenario/CLIScenario.java index 3b81735..1be7c50 100644 --- a/src/com/mostc/pftt/scenario/CLIScenario.java +++ b/src/com/mostc/pftt/scenario/CLIScenario.java @@ -92,8 +92,8 @@ public class CliScenario extends AbstractSAPIScenario { } @Override - public AbstractPhpUnitTestCaseRunner createPhpUnitTestCaseRunner(PhpUnitThread thread, TestCaseGroupKey group_key, ConsoleManager cm, ITestResultReceiver twriter, Map<String, String> globals, Map<String, String> env, AHost runner_host, ScenarioSet scenario_set, PhpBuild build, PhpUnitTestCase test_case, String my_temp_dir, Map<String, String> constants, String include_path, String[] include_files) { - return new CliPhpUnitTestCaseRunner(twriter, globals, env, cm, runner_host, scenario_set, build, test_case, my_temp_dir, constants, test_case.php_unit_dist.getIncludePath(), test_case.php_unit_dist.getIncludeFiles()); + public AbstractPhpUnitTestCaseRunner createPhpUnitTestCaseRunner(PhpUnitThread thread, TestCaseGroupKey group_key, ConsoleManager cm, ITestResultReceiver twriter, Map<String, String> globals, Map<String, String> env, AHost runner_host, ScenarioSet scenario_set, PhpBuild build, PhpUnitTestCase test_case, String my_temp_dir, Map<String, String> constants, String include_path, String[] include_files, PhpIni ini) { + return new CliPhpUnitTestCaseRunner(twriter, globals, env, cm, runner_host, scenario_set, build, test_case, my_temp_dir, constants, test_case.php_unit_dist.getIncludePath(), test_case.php_unit_dist.getIncludeFiles(), ini); } } // end public class CliScenario diff --git a/src/com/mostc/pftt/scenario/NormalPathsScenario.java b/src/com/mostc/pftt/scenario/NormalPathsScenario.java new file mode 100644 index 0000000..ff3f8a2 --- /dev/null +++ b/src/com/mostc/pftt/scenario/NormalPathsScenario.java @@ -0,0 +1,37 @@ +package com.mostc.pftt.scenario; + +import com.mostc.pftt.host.Host; +import com.mostc.pftt.model.core.PhpBuild; +import com.mostc.pftt.results.ConsoleManager; + +/** NOT IMPLEMENTED + * + * @see UNCPathsScenario + * @author Matt Ficken + * + */ + +public class NormalPathsScenario extends PathsScenario { + + @Override + public boolean isPlaceholder() { + return true; + } + + @Override + public boolean setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + // TODO Auto-generated method stub + return false; + } + + @Override + public String getName() { + return "Normal-Paths"; + } + + @Override + public boolean isImplemented() { + return false; + } + +} diff --git a/src/com/mostc/pftt/scenario/PathsScenario.java b/src/com/mostc/pftt/scenario/PathsScenario.java new file mode 100644 index 0000000..0d37359 --- /dev/null +++ b/src/com/mostc/pftt/scenario/PathsScenario.java @@ -0,0 +1,10 @@ +package com.mostc.pftt.scenario; + +public abstract class PathsScenario extends AbstractOptionScenario { + + @Override + public Class<?> getSerialKey() { + return PathsScenario.class; + } + +} diff --git a/src/com/mostc/pftt/scenario/Scenario.java b/src/com/mostc/pftt/scenario/Scenario.java index e064458..a8a09e5 100644 --- a/src/com/mostc/pftt/scenario/Scenario.java +++ b/src/com/mostc/pftt/scenario/Scenario.java @@ -116,7 +116,8 @@ public abstract class Scenario { // (like connecting to a database server that the user would have to setup. those scenarios // have to be in configuration files (in the 'conf' directory)) new MSAccessScenario(), // ignored if MS-Access not installed - new SQLite3Scenario() + new SQLite3Scenario(), + new NormalPathsScenario() }; } // end public static Scenario[] getAllDefaultScenarios diff --git a/src/com/mostc/pftt/scenario/ScenarioSet.java b/src/com/mostc/pftt/scenario/ScenarioSet.java index f3d0698..ff77d06 100644 --- a/src/com/mostc/pftt/scenario/ScenarioSet.java +++ b/src/com/mostc/pftt/scenario/ScenarioSet.java @@ -96,6 +96,8 @@ public class ScenarioSet extends ArrayList<Scenario> { /** returns this ScenarioSet's name and important version info (mainly just for reports) * + * Note: MUST be safe to use as part of a filename! + * * @see #getName - normally, use getName, its shorter. * @return */ @@ -115,6 +117,8 @@ public class ScenarioSet extends ArrayList<Scenario> { /** returns the name of this ScenarioSet (the names of the contained Scenarios) as a String * + * Note: MUST be safe to use as part of a filename! + * * @see #getNameWithVersionInfo - returns a longer string with version info, etc... * @return */ diff --git a/src/com/mostc/pftt/scenario/UNCPathsScenario.java b/src/com/mostc/pftt/scenario/UNCPathsScenario.java new file mode 100644 index 0000000..6c2f1fe --- /dev/null +++ b/src/com/mostc/pftt/scenario/UNCPathsScenario.java @@ -0,0 +1,33 @@ +package com.mostc.pftt.scenario; + +import com.mostc.pftt.host.Host; +import com.mostc.pftt.model.core.PhpBuild; +import com.mostc.pftt.results.ConsoleManager; + +/** Use UNC Paths (on Windows) (paths in the form \\name|ip address\) NOT_IMPLEMENTED. + * + * Normally, on Windows, drive letters are used both for local(ex: C:) and remote file systems (ex: H:) + * + * @author Matt Ficken + * + */ + +public class UNCPathsScenario extends PathsScenario { + + @Override + public boolean setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + // TODO Auto-generated method stub + return false; + } + + @Override + public String getName() { + return "UNC-Paths"; + } + + @Override + public boolean isImplemented() { + return false; + } + +} diff --git a/src/com/mostc/pftt/util/WinDebugManager.java b/src/com/mostc/pftt/util/WinDebugManager.java index 8b70532..c61002b 100644 --- a/src/com/mostc/pftt/util/WinDebugManager.java +++ b/src/com/mostc/pftt/util/WinDebugManager.java @@ -1,6 +1,5 @@ package com.mostc.pftt.util; -import com.github.mattficken.io.IOUtil; import com.github.mattficken.io.StringUtil; import com.mostc.pftt.host.AHost; import com.mostc.pftt.host.AHost.ExecHandle;