com pftt2: prepare all PHPT tests before running any of them: bin/pftt_workspace.WEW conf/task/stress.groovy conf/t ask/stress_long.groovy
conf/task/stress_more.groovy conf/task/stress_more_long.groovy conf/task/stress _overnight.groovy src/com/mostc/pftt/host/PSCAgentServer .java
src/com/mostc/pftt/host/RemotePhptTestPackRunner.ja va src/com/mostc/pftt/main/PfttMain.java src/com/mostc/pf tt/model/core/PhpBuild.java
src/com/mostc/pftt/model/core/P hpIn

From: Date: Mon, 18 Nov 2013 18:59:57 +0000
Subject: com pftt2: prepare all PHPT tests before running any of them: bin/pftt_workspace.WEW conf/task/stress.groovy conf/t ask/stress_long.groovy
conf/task/stress_more.groovy conf/task/stress_more_long.groovy conf/task/stress _overnight.groovy src/com/mostc/pftt/host/PSCAgentServer .java
src/com/mostc/pftt/host/RemotePhptTestPackRunner.ja va src/com/mostc/pftt/main/PfttMain.java src/com/mostc/pf tt/model/core/PhpBuild.java
src/com/mostc/pftt/model/core/P hpIn
Groups: php.qa 
Request: Send a blank email to php-qa+get-68336@lists.php.net to get a copy of this message
Commit: 12b8407317b4abd66116e9c5ccd1f796d9818096 Author: Matt Ficken <v-mafick@microsoft.com> Mon, 18 Nov 2013 10:59:57 -0800 Parents: cab0d8d13ec2b3ffebef809888dee15e5e502328 Branches: master Link: http://git.php.net/?p=pftt2.git;a=commitdiff;h=12b8407317b4abd66116e9c5ccd1f796d9818096 Log: prepare all PHPT tests before running any of them Former-commit-id: e0b7576f1084c6c3e5b48a6582bf83cbc02e598d Changed paths: M bin/pftt_workspace.WEW M conf/task/stress.groovy M conf/task/stress_long.groovy M conf/task/stress_more.groovy M conf/task/stress_more_long.groovy M conf/task/stress_overnight.groovy M src/com/mostc/pftt/host/PSCAgentServer.java M src/com/mostc/pftt/host/RemotePhptTestPackRunner.java M src/com/mostc/pftt/main/PfttMain.java M src/com/mostc/pftt/model/core/PhpBuild.java M src/com/mostc/pftt/model/core/PhpIni.java M src/com/mostc/pftt/model/core/PhptSourceTestPack.java M src/com/mostc/pftt/model/core/PhptTestCase.java M src/com/mostc/pftt/model/sapi/CliSAPIInstance.java M src/com/mostc/pftt/results/AbstractPhptRW.java M src/com/mostc/pftt/results/AbstractReportGen.groovy M src/com/mostc/pftt/results/ConsoleManager.java M src/com/mostc/pftt/results/LocalConsoleManager.java M src/com/mostc/pftt/results/PhpResultPack.java A src/com/mostc/pftt/results/TextBuilder.java M src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java M src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java M src/com/mostc/pftt/runner/AbstractTestPackRunner.java M src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java M src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java M src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java A src/com/mostc/pftt/runner/PhptTestPreparer.java M src/com/mostc/pftt/ui/PhptDebuggerFrame.java M src/com/mostc/pftt/util/HostEnvUtil.java M src/com/mostc/pftt/util/TimerUtil.java

diff --git a/bin/pftt_workspace.WEW b/bin/pftt_workspace.WEW index eb8a285..1f3e04d 100644 Binary files a/bin/pftt_workspace.WEW and b/bin/pftt_workspace.WEW differ diff --git a/conf/task/stress.groovy b/conf/task/stress.groovy index 6d5d0ee..16438f8 100644 --- a/conf/task/stress.groovy +++ b/conf/task/stress.groovy @@ -5,7 +5,7 @@ def describe() { def processConsoleOptions(List options) { options.add("-thread_count") - options.add("16") + options.add(Integer.toString(16 * LocalHost.getInstance().getCPUCount())) options.add("-run_test_times_all") options.add("1000") } diff --git a/conf/task/stress_long.groovy b/conf/task/stress_long.groovy index 6238c05..d982cf5 100644 --- a/conf/task/stress_long.groovy +++ b/conf/task/stress_long.groovy @@ -6,7 +6,7 @@ def describe() { def processConsoleOptions(List options) { options.add("-no_thread_safety") options.add("-thread_count") - options.add("16") + options.add(Integer.toString(16 * LocalHost.getInstance().getCPUCount())) options.add("-run_test_times_all") options.add("100000") options.add("-randomize_order") diff --git a/conf/task/stress_more.groovy b/conf/task/stress_more.groovy index c869dcc..f37b7e7 100644 --- a/conf/task/stress_more.groovy +++ b/conf/task/stress_more.groovy @@ -6,7 +6,7 @@ def describe() { def processConsoleOptions(List options) { options.add("-no_thread_safety") options.add("-thread_count") - options.add("64") + options.add(Integer.toString(32 * LocalHost.getInstance().getCPUCount())) options.add("-run_test_times_all") options.add("10000") } diff --git a/conf/task/stress_more_long.groovy b/conf/task/stress_more_long.groovy index e467d63..c77ecb3 100644 --- a/conf/task/stress_more_long.groovy +++ b/conf/task/stress_more_long.groovy @@ -6,7 +6,7 @@ def describe() { def processConsoleOptions(List options) { options.add("-no_thread_safety") options.add("-thread_count") - options.add("64") + options.add(Integer.toString(32 * LocalHost.getInstance().getCPUCount())) options.add("-run_test_times_all") options.add("100000") options.add("-randomize_order") diff --git a/conf/task/stress_overnight.groovy b/conf/task/stress_overnight.groovy index 12a71a3..70f50e7 100644 --- a/conf/task/stress_overnight.groovy +++ b/conf/task/stress_overnight.groovy @@ -6,7 +6,7 @@ def describe() { def processConsoleOptions(List options) { options.add("-no_thread_safety") options.add("-thread_count") - options.add("128") + options.add(Integer.toString(16 * LocalHost.getInstance().getCPUCount())) options.add("-run_test_times_all") options.add("10000000") options.add("-randomize_order") diff --git a/src/com/mostc/pftt/host/PSCAgentServer.java b/src/com/mostc/pftt/host/PSCAgentServer.java index 2ac5d90..2b71ea9 100644 --- a/src/com/mostc/pftt/host/PSCAgentServer.java +++ b/src/com/mostc/pftt/host/PSCAgentServer.java @@ -32,6 +32,7 @@ import com.mostc.pftt.results.PhpUnitTestResult; import com.mostc.pftt.results.PhptTestResult; import com.mostc.pftt.scenario.Scenario; import com.mostc.pftt.scenario.ScenarioSetSetup; +import com.mostc.pftt.util.DebuggerManager; import com.mostc.pftt.util.ErrorUtil; /** @@ -180,6 +181,11 @@ public abstract class PSCAgentServer implements ConsoleManager, ITestResultRecei } @Override + public boolean isIgnoreOutput() { + return false; + } + + @Override public boolean isNonInteractive() { return false; } @@ -566,4 +572,14 @@ public abstract class PSCAgentServer implements ConsoleManager, ITestResultRecei return 0; } + @Override + public String getDebuggerName() { + return null; + } + + @Override + public DebuggerManager getDebuggerManager() { + return null; + } + } // end public abstract class PSCAgentServer diff --git a/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java b/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java index 402647f..1ab4ab7 100644 --- a/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java +++ b/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java @@ -54,7 +54,7 @@ public class RemotePhptTestPackRunner extends AbstractRemoteTestPackRunner<PhptA public static void main(String[] args) throws Exception { LocalHost host = LocalHost.getInstance(); - LocalConsoleManager cm = new LocalConsoleManager(null, null, false, false, false, false, true, false, true, false, false, false, 1, 1, true, 1, 1, 1, null, null, null, null, false, 0, 0, false, false, 0, 0, 0, false, 0, false); + LocalConsoleManager cm = new LocalConsoleManager(null, null, false, false, false, false, true, false, true, false, false, false, 1, 1, true, 1, 1, 1, null, null, null, null, false, 0, 0, false, false, 0, 0, 0, false, 0, false, false, null); Config config = Config.loadConfigFromFiles(cm, "default"); PhpBuild build = new PhpBuild("C:\\php-sdk\\php-5.5-ts-windows-vc11-x64-re3aeb6c"); diff --git a/src/com/mostc/pftt/main/PfttMain.java b/src/com/mostc/pftt/main/PfttMain.java index 810f368..bd86a6b 100644 --- a/src/com/mostc/pftt/main/PfttMain.java +++ b/src/com/mostc/pftt/main/PfttMain.java @@ -92,9 +92,6 @@ import com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair; // // no component should be allowed to run forever(implicitly it will eventually break), always have explicit timeouts -// TODO enchant scenario -// skips on 5.4 cli apache ts -// skips on 5.5 cli apache ts // TODO linux apache support // TODO linux .sh installer // TODO iis support @@ -108,11 +105,6 @@ import com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair; // -don't change PHPT report form though // -for console-args // TODO get custom DLL from custom test-pack -// TODO mssql scenario -// -for both `sql server` and `azure sql`? -// -supply mssql binary using console args (custom_ext task) -// -or include in pftt's cache/dep -// -use mssql PHPTs as a separate PhptTestPack until they are integrated with PhpCore // TODO xdebug only for 5.4-ts // TODO get code coverage data of Symfony demo app (UI?) // -get list of builtin functions @@ -429,7 +421,7 @@ public class PfttMain { System.out.println(" === Crash Debugging ==="); System.out.println(new AlignedTable(2, 85) .addRow("-debug_all", "runs all tests in Debugger") - .addRow("-debugger <gdb|windbg|valgrind>", "specify which Debugger to use (optional, or PFTT will decide)") + .addRow("-debugger <gdb|windbg|TTT|valgrind>", "specify which Debugger to use (optional, or PFTT will decide)") .addRow("-debug_name <name fragments,name2:name3;name4>", "runs named tests in list in Debugger (name fragment)") .addRow("-debug_list <list files>", "runs tests in list in Debugger (exact name)") .addRow("-src_pack <path>", "folder with the source code") @@ -462,6 +454,7 @@ public class PfttMain { System.out.println(); System.out.println(" === Debugging ==="); System.out.println(new AlignedTable(2, 85) + .addRow("-ignore_output", "Ignores test output to speed up test running (to help repro concurrency crashes)") .addRow("-ini_actual_all", "includes INI for all tests (default=only for failures)... SLOW but helps verify") .addRow("-suspend_seconds <seconds>", "suspends test process for <seconds> before running test so you can check the process first (1 minute timeout after resume)") .addRow("-run_count <N>", "runs N number of tests. does not count early SKIP'd tests (whereas -max_test_read_count does)") @@ -659,8 +652,8 @@ public class PfttMain { } AtomicBoolean run_flag = new AtomicBoolean(true); for ( int i=0 ; i < cm.getRunTestPack() ; i++ ) { - if (!smoke(build, config, tmgr)) - break; + // TODO temp if (!smoke(build, config, tmgr)) + //break; for ( ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE) ) { // for ( AHost storage_host : hosts ) { @@ -1293,6 +1286,8 @@ public class PfttMain { * @param runner */ protected static void interactive(final AtomicBoolean run_flag, final AbstractLocalTestPackRunner<?,?,?> runner) { + if (true) + return; // TODO temp new Thread() { public void run() { try { @@ -1345,7 +1340,8 @@ public class PfttMain { int args_i = 0; Config config = null; - boolean is_uac = false, debug = false, randomize_order = false, no_result_file_for_pass_xskip_skip = false, pftt_debug = false, show_gui = false, overwrite = false, disable_debug_prompt = false, results_only = false, dont_cleanup_test_pack = false, phpt_not_in_place = false, thread_safety = true, skip_smoke_tests = false, pause = false, restart_each_test_all = false, no_restart_all = false, ignore_unknown_option = false, ini_actual_all = false, non_interactive = false; + String debugger_name = null; + boolean is_uac = false, debug = false, randomize_order = false, no_result_file_for_pass_xskip_skip = false, pftt_debug = false, show_gui = false, overwrite = false, disable_debug_prompt = false, results_only = false, dont_cleanup_test_pack = false, phpt_not_in_place = false, thread_safety = true, skip_smoke_tests = false, pause = false, restart_each_test_all = false, no_restart_all = false, ignore_unknown_option = false, ini_actual_all = false, non_interactive = false, ignore_output = false; long max_run_time_millis = 0; int run_test_times_all = 1, run_test_pack = 1, delay_between_ms = 0, run_test_times_list_times = 1, run_group_times_all = 1, run_group_times_list_times = 1, max_test_read_count = 0, thread_count = 0, run_count = 0, suspend_seconds = 0; LinkedList<String> debug_list = new LinkedList<String>(); @@ -1446,6 +1442,8 @@ public class PfttMain { no_result_file_for_pass_xskip_skip = true; } else if (args[args_i].equals("-no_result_file_for_pass_xskip_skip")||args[args_i].equals("-q")) { no_result_file_for_pass_xskip_skip = true; + } else if (args[args_i].equals("-ignore_output")) { + ignore_output = true; } else if (args[args_i].equals("-randomize_order")) { randomize_order = true; } else if (args[args_i].equals("-run_test_pack")) { @@ -1526,11 +1524,11 @@ public class PfttMain { // also intercepted and handled by bin/pftt.cmd batch script debug = true; - } else if (args[args_i].startsWith("-debugger")) { + } else if (args[args_i].startsWith("-debugger")||args[args_i].startsWith("-debugger_name")) { // also intercepted and handled by bin/pftt.cmd batch script debug = true; args_i++; - // TODO debugger = args[args_i]; + debugger_name = args[args_i]; } else if (args[args_i].equals("-disable_debug_prompt")||args[args_i].equals("-debug_none")||args[args_i].equals("-d")) { disable_debug_prompt = true; @@ -1602,7 +1600,7 @@ public class PfttMain { cm = new LocalConsoleManager(source_pack, debug_pack, overwrite, debug, results_only, show_gui, disable_debug_prompt, dont_cleanup_test_pack, phpt_not_in_place, pftt_debug, no_result_file_for_pass_xskip_skip, randomize_order, run_test_times_all, run_test_pack, thread_safety, run_test_times_list_times, run_group_times_all, run_group_times_list_times, debug_list, run_test_times_list, run_group_times_list, skip_list, skip_smoke_tests, max_test_read_count, thread_count, restart_each_test_all, no_restart_all, delay_between_ms, - run_count, suspend_seconds, ini_actual_all, max_run_time_millis, non_interactive); + run_count, suspend_seconds, ini_actual_all, max_run_time_millis, non_interactive, ignore_output, debugger_name); p.cm = cm; if (command!=null) { diff --git a/src/com/mostc/pftt/model/core/PhpBuild.java b/src/com/mostc/pftt/model/core/PhpBuild.java index af81f87..ca1e0ac 100644 --- a/src/com/mostc/pftt/model/core/PhpBuild.java +++ b/src/com/mostc/pftt/model/core/PhpBuild.java @@ -711,7 +711,7 @@ public class PhpBuild extends SAPIManager { * @see PHPOutput#cleanup */ public PHPOutput eval(AHost host, PhpIni ini, String code, boolean auto_cleanup) throws Exception { - return eval(host, ini, code, Host.FOUR_HOURS, auto_cleanup); + return eval(host, ini, code, Host.ONE_MINUTE*4, auto_cleanup); } public PHPOutput eval(AHost host, String code, boolean auto_cleanup) throws Exception { diff --git a/src/com/mostc/pftt/model/core/PhpIni.java b/src/com/mostc/pftt/model/core/PhpIni.java index dc4182d..a906784 100644 --- a/src/com/mostc/pftt/model/core/PhpIni.java +++ b/src/com/mostc/pftt/model/core/PhpIni.java @@ -578,11 +578,19 @@ public class PhpIni { if (host.isWindows()) value = StringUtil.replaceAll(PAT_per, "\\%\\%", value); - sb.append(" -d \""); - sb.append(directive); - sb.append("="); - sb.append(value); - sb.append("\""); + // without quoting only when needed, will get parse errors from php (blocking winpopups on Windows) + if (value.contains(" ")) { + sb.append(" -d \""); + sb.append(directive); + sb.append("="); + sb.append(value); + sb.append("\""); + } else { + sb.append(" -d "); + sb.append(directive); + sb.append("="); + sb.append(value); + } } } String cli_arg_str = sb.toString(); diff --git a/src/com/mostc/pftt/model/core/PhptSourceTestPack.java b/src/com/mostc/pftt/model/core/PhptSourceTestPack.java index 991635f..ec7ee08 100644 --- a/src/com/mostc/pftt/model/core/PhptSourceTestPack.java +++ b/src/com/mostc/pftt/model/core/PhptSourceTestPack.java @@ -346,9 +346,13 @@ public class PhptSourceTestPack implements SourceTestPack<PhptActiveTestPack, Ph if (test_name.startsWith("/") || test_name.startsWith("\\")) test_name = test_name.substring(1); - PhptTestCase test_case = PhptTestCase.load(host, this, false, test_name, twriter, redirect_parent); + try { + PhptTestCase test_case = PhptTestCase.load(host, this, false, test_name, twriter, redirect_parent); - add_test_case(config, test_case, test_files, names, cm, twriter, build, redirect_parent, redirect_targets); + add_test_case(config, test_case, test_files, names, cm, twriter, build, redirect_parent, redirect_targets); + } catch ( Exception ex ) { + ex.printStackTrace(); + } } else if (f.isFile()) { String n = f.getName().toLowerCase(); if (!(n.endsWith(".sh") && n.endsWith(".php") && n.endsWith(".diff") && n.endsWith(".out") && n.endsWith(".exp") && n.endsWith(".cmd") && n.endsWith(".stdin"))) { diff --git a/src/com/mostc/pftt/model/core/PhptTestCase.java b/src/com/mostc/pftt/model/core/PhptTestCase.java index e6e6721..1bc1bcb 100644 --- a/src/com/mostc/pftt/model/core/PhptTestCase.java +++ b/src/com/mostc/pftt/model/core/PhptTestCase.java @@ -30,6 +30,7 @@ import com.mostc.pftt.model.TestCase; import com.mostc.pftt.model.core.PhpBuild.PHPOutput; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.ITestResultReceiver; +import com.mostc.pftt.runner.PhptTestPreparer.PreparedPhptTestCase; import com.mostc.pftt.scenario.ScenarioSetSetup; import com.mostc.pftt.util.apache.regexp.RE; import com.mostc.pftt.util.apache.regexp.RECompiler; @@ -126,6 +127,7 @@ public class PhptTestCase extends TestCase { private CharsetICU common_charset; private CharsetEncoder ce; public boolean redo = false; // TODO temp + public PreparedPhptTestCase prep; // TODO temp /** loads the named PHPT test from the given PhptSourceTestPack * diff --git a/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java b/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java index ed89e2c..14a2555 100644 --- a/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java +++ b/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java @@ -11,15 +11,18 @@ import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.model.core.PhpIni; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.scenario.ScenarioSet; -import com.mostc.pftt.util.WinDebugManager; +import com.mostc.pftt.util.DebuggerManager; public class CliSAPIInstance extends SAPIInstance { protected final PhpBuild build; protected String ini_dir; + protected DebuggerManager db_mgr; - public CliSAPIInstance(AHost host, PhpBuild build, PhpIni ini) { + public CliSAPIInstance(ConsoleManager cm, AHost host, PhpBuild build, PhpIni ini) { super(host, ini); this.build = build; + + db_mgr = cm.getDebuggerManager(); } @Override @@ -41,12 +44,14 @@ public class CliSAPIInstance extends SAPIInstance { host.saveTextFile(host.joinIntoOnePath(ini_dir, "php.ini"), ini.toString()); } - public ExecOutput execute(EExecutableType exe_type, String php_filename, String extra_args, Map<String,String> env, int timeout_sec) throws Exception { - return execute(exe_type, php_filename, extra_args, timeout_sec, env, null); + public ExecOutput execute(EExecutableType exe_type, String name, String php_filename, String extra_args, Map<String,String> env, int timeout_sec, boolean debugger_attached) throws Exception { + return execute(exe_type, name, php_filename, extra_args, timeout_sec, env, null, debugger_attached); } - public String createPhpCommand(EExecutableType exe_type, String php_filename, String extra_args) { + public String createPhpCommand(EExecutableType exe_type, String php_filename, String extra_args, boolean debugger_attached) { StringBuilder sb = new StringBuilder(); + + // sb.append(build.getPhpExe(exe_type)); if (exe_type==EExecutableType.CGI) { // -C => important: don't chdir @@ -58,20 +63,24 @@ public class CliSAPIInstance extends SAPIInstance { sb.append(host.fixPath(php_filename)); if (extra_args!=null) sb.append(extra_args); + return sb.toString(); } - public ExecOutput execute(EExecutableType exe_type, String php_filename, String extra_args, int timeout_sec, Map<String,String> env, String chdir) throws Exception { - return host.execOut(createPhpCommand(exe_type, php_filename, extra_args), timeout_sec, env, chdir, true); + public ExecOutput execute(EExecutableType exe_type, String name, String php_filename, String extra_args, int timeout_sec, Map<String,String> env, String chdir, boolean debugger_attached) throws Exception { + return db_mgr == null ? + host.execOut(createPhpCommand(exe_type, php_filename, extra_args, debugger_attached), timeout_sec, env, chdir, true) : + db_mgr.execOut(host, name, createPhpCommand(exe_type, php_filename, extra_args, debugger_attached), timeout_sec, env, chdir, true); } - WinDebugManager db_mgr = new WinDebugManager(); public ExecHandle execThread(ConsoleManager cm, String name, ScenarioSet scenario_set, String cmd, String chdir, Map<String,String> env, byte[] stdin_data, boolean debugger_attached) throws Exception { // TODO use this with CliPhpUnitTestCaseRunner - LocalExecHandle eh = (LocalExecHandle) host.execThread(cmd, env, chdir, stdin_data, !debugger_attached); - if (debugger_attached) { - db_mgr.newDebugger(cm, host, scenario_set, name, build, eh); + ExecHandle eh = db_mgr == null ? + host.execThread(cmd, env, chdir, stdin_data, !debugger_attached) : + db_mgr.execThread(host, name, cmd, env, chdir, stdin_data, !debugger_attached); + if (debugger_attached && eh instanceof LocalExecHandle) { + db_mgr.newDebugger(cm, host, scenario_set, name, build, (LocalExecHandle)eh); } return eh; } diff --git a/src/com/mostc/pftt/results/AbstractPhptRW.java b/src/com/mostc/pftt/results/AbstractPhptRW.java index 6703342..983801e 100644 --- a/src/com/mostc/pftt/results/AbstractPhptRW.java +++ b/src/com/mostc/pftt/results/AbstractPhptRW.java @@ -28,10 +28,35 @@ public abstract class AbstractPhptRW extends AbstractTestResultRW { public abstract String getPath(); protected void check(EPhptTestStatus status, List<String> names) { - if (status==EPhptTestStatus.FAIL) { - // TODO temp - - + /*if (status==EPhptTestStatus.FAIL) { + names.remove("ext/reflection/tests/bug36308.phpt"); + names.remove("ext/zlib/tests/ob_004.phpt"); + names.remove("zend/tests/bug40236.phpt"); + names.remove("ext/curl/tests/curl_curlopt_readdata.phpt"); + names.remove("ext/openssl/tests/openssl_spki_verify.phpt"); + names.remove("ext/zlib/tests/bug55544.phpt"); + names.remove("ext/zlib/tests/bug_52944-darwin.phpt"); + names.remove("zend/tests/bug64720.phpt"); + names.remove("ext/curl/tests/curl_copy_handle_basic_008.phpt"); + names.remove("ext/curl/tests/curl_writeheader_callback.phpt"); + names.remove("ext/filter/tests/bug52209.phpt"); + names.remove("ext/gettext/tests/gettext_basic.phpt"); + names.remove("ext/intl/tests/timezone_getdisplayname_variant3.phpt"); + names.remove("ext/mbstring/tests/mb_http_input.phpt"); + names.remove("ext/pdo_sqlite/tests/bug_63916.phpt"); + names.remove("ext/sqlite3/tests/bug63921-64bit.phpt"); + names.remove("ext/mysqli/tests/mysqli_explain_metadata.phpt"); + names.remove("ext/mysqli/tests/mysqli_fetch_assoc_oo.phpt"); + names.remove("ext/mysqli/tests/mysqli_fetch_all_oo.phpt"); + names.remove("ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt"); + names.remove("ext/mysqli/tests/mysqli_set_charset.phpt"); + names.remove("ext/mysqli/tests/mysqli_stmt_fetch_bit.phpt"); + names.remove("ext/mysqli/tests/mysqli_fetch_array.phpt"); + names.remove("ext/mysqli/tests/mysqli_fetch_array_assoc.phpt"); + names.remove("ext/mysqli/tests/mysqli_options_openbasedir.phpt"); + names.remove("ext/mysqli/tests/mysqli_real_escape_string.phpt"); + names.remove("ext/mysqli/tests/mysqli_stmt_bind_param.phpt"); + names.remove("ext/mysqli/tests/mysqli_stmt_get_result_bit.phpt"); names.remove("ext/bcmath/tests/bcsqrt.phpt"); names.remove("ext/spl/tests/spldoublylinkedlist_offsetset_invalid_parameter.phpt"); names.remove("ext/spl/tests/spldoublylinkedlist_offsetset_one_invalid_parameter.phpt"); @@ -168,6 +193,48 @@ names.remove("ext/standard/tests/file/windows_links/bug48746_2.phpt"); names.remove("ext/phar/tests/tar/phar_commitwrite.phpt"); names.remove("ext/phar/tests/tar/phar_setsignaturealgo2.phpt"); names.remove("ext/phar/tests/zip/phar_commitwrite.phpt"); - } + names.remove("ext/bcmath/tests/bcdiv.phpt"); + names.remove("ext/mysqli/tests/mysqli_multi_query.phpt"); + names.remove("ext/mysqli/tests/mysqli_rollback.phpt"); + names.remove("ext/zlib/tests/zlib_filter_deflate2.phpt"); + names.remove("ext/curl/tests/bug52202.phpt"); + names.remove("ext/curl/tests/curl_basic_008.phpt"); + names.remove("ext/curl/tests/curl_basic_010.phpt"); + names.remove("ext/curl/tests/curl_copy_handle_basic_002.phpt"); + names.remove("ext/curl/tests/curl_multi_segfault.phpt"); + names.remove("ext/curl/tests/curl_write_file.phpt"); + names.remove("ext/date/tests/big_year.phpt"); + names.remove("ext/date/tests/date_diff.phpt"); + names.remove("ext/ereg/tests/sql_regcase_error_001.phpt"); + names.remove("ext/filter/tests/033.phpt"); + names.remove("ext/intl/tests/locale_get_display_language.phpt"); + names.remove("ext/sockets/tests/bug46360.phpt"); + names.remove("ext/standard/tests/array/count_variation3.phpt"); + names.remove("ext/standard/tests/assert/assert_basic6.phpt"); + names.remove("ext/standard/tests/file/file_get_contents_error001.phpt"); + names.remove("ext/standard/tests/file/filetype_variation3.phpt"); + names.remove("ext/standard/tests/file/windows_acls/bug44859.phpt"); + names.remove("ext/standard/tests/file/windows_acls/bug44859_2.phpt"); + names.remove("ext/standard/tests/file/windows_acls/bug44859_3.phpt"); + names.remove("ext/standard/tests/file/windows_acls/bug44859_4.phpt"); + names.remove("ext/standard/tests/math/mt_srand_variation1.phpt"); + names.remove("ext/standard/tests/network/gethostbyname_basic001.phpt"); + names.remove("ext/standard/tests/network/gethostbyname_error004.phpt"); + names.remove("ext/standard/tests/network/http-stream.phpt"); + names.remove("ext/standard/tests/strings/strtok_variation7.phpt"); + names.remove("ext/xmlwriter/tests/002.phpt"); + names.remove("ext/zip/tests/bug51353.phpt"); + names.remove("sapi/cli/tests/php_cli_server_004.phpt"); + names.remove("tests/classes/private_003.phpt"); + names.remove("tests/classes/visibility_001c.phpt"); + names.remove("zend/tests/bug40770.phpt"); + names.remove("ext/mysqli/tests/010.phpt"); + names.remove("ext/mysqli/tests/mysqli_fetch_all.phpt"); + names.remove("ext/mysqli/tests/mysqli_fetch_lengths.phpt"); + names.remove("ext/mysqli/tests/mysqli_query_iterators.phpt"); + names.remove("tests/lang/passbyreference_012.phpt"); + names.remove("tests/lang/returnbyreference.001.phpt"); + names.remove("tests/lang/returnbyreference.003.phpt"); + }*/ } } diff --git a/src/com/mostc/pftt/results/AbstractReportGen.groovy b/src/com/mostc/pftt/results/AbstractReportGen.groovy index def10c6..4401773 100644 --- a/src/com/mostc/pftt/results/AbstractReportGen.groovy +++ b/src/com/mostc/pftt/results/AbstractReportGen.groovy @@ -10,9 +10,20 @@ abstract class AbstractReportGen { // so the actual size of the mail message may be as much as double the size here static int ABBREVIATED_MAX_LENGTH = IOUtil.HALF_MEGABYTE; - abstract void run(ConsoleManager cm, boolean abbreviated); + abstract void run(ConsoleManager cm, boolean abbreviated, BuilderSupport html); - abstract String getHTMLString(ConsoleManager cm, boolean abbreviated); + protected StringWriter sw; + public String getHTMLString(ConsoleManager cm, boolean abbreviated) { + sw = new StringWriter(); + run(cm, abbreviated, new groovy.xml.MarkupBuilder(sw)); + return sw.toString(); + } + + public String getPlainTextString(ConsoleManager cm, boolean abbreviated) { + sw = new StringWriter(); + run(cm, abbreviated, new TextBuilder(sw)); + return sw.toString(); + } String createHTMLTempFile(AHost host) { String html_str = getHTMLString(); diff --git a/src/com/mostc/pftt/results/ConsoleManager.java b/src/com/mostc/pftt/results/ConsoleManager.java index 44a5569..6eac5aa 100644 --- a/src/com/mostc/pftt/results/ConsoleManager.java +++ b/src/com/mostc/pftt/results/ConsoleManager.java @@ -6,6 +6,7 @@ import javax.annotation.Nonnegative; import com.mostc.pftt.model.TestCase; import com.mostc.pftt.model.core.PhpDebugPack; +import com.mostc.pftt.util.DebuggerManager; public interface ConsoleManager { @@ -102,5 +103,8 @@ public interface ConsoleManager { public int getSuspendSeconds(); public boolean isGetActualIniAll(); public long getMaxRunTimeMillis(); + public boolean isIgnoreOutput(); + public String getDebuggerName(); + public DebuggerManager getDebuggerManager(); } // end public class ConsoleManager diff --git a/src/com/mostc/pftt/results/LocalConsoleManager.java b/src/com/mostc/pftt/results/LocalConsoleManager.java index b1ac6bd..5173459 100644 --- a/src/com/mostc/pftt/results/LocalConsoleManager.java +++ b/src/com/mostc/pftt/results/LocalConsoleManager.java @@ -11,6 +11,7 @@ import javax.swing.JFrame; import com.github.mattficken.io.StringUtil; import com.mostc.pftt.host.AHost; import com.mostc.pftt.host.Host; +import com.mostc.pftt.host.LocalHost; import com.mostc.pftt.main.PfttMain; import com.mostc.pftt.model.TestCase; import com.mostc.pftt.model.app.PhpUnitSourceTestPack; @@ -22,12 +23,19 @@ import com.mostc.pftt.runner.LocalPhptTestPackRunner; import com.mostc.pftt.runner.AbstractTestPackRunner.ETestPackRunnerState; import com.mostc.pftt.ui.PhpUnitDebuggerFrame; import com.mostc.pftt.ui.PhptDebuggerFrame; +import com.mostc.pftt.util.DebuggerManager; import com.mostc.pftt.util.ErrorUtil; +import com.mostc.pftt.util.GDBDebugManager; +import com.mostc.pftt.util.TimeTravelTraceDebugManager; +import com.mostc.pftt.util.ValgrindMemoryCheckManager; +import com.mostc.pftt.util.WinDebugManager; public class LocalConsoleManager implements ConsoleManager { - protected final boolean overwrite, debug_all, results_only, show_gui, disable_debug_prompt, dont_cleanup_test_pack, phpt_not_in_place, pftt_debug, no_result_file_for_pass_xskip_skip, randomize_order, thread_safety, skip_smoke_tests, restart_each_test_all, no_restart_all, ini_actual_all, non_interactive; + protected final boolean overwrite, debug_all, results_only, show_gui, disable_debug_prompt, dont_cleanup_test_pack, phpt_not_in_place, pftt_debug, no_result_file_for_pass_xskip_skip, randomize_order, thread_safety, skip_smoke_tests, restart_each_test_all, no_restart_all, ini_actual_all, non_interactive, ignore_output; protected final int run_test_times_all, run_test_pack, run_test_times_list_times, run_group_times, run_group_times_list_times, max_test_read_count, thread_count, delay_between_ms, suspend_seconds, run_count; protected final long max_run_time_millis; + protected final String debugger_name; + protected final DebuggerManager db_mgr; protected String source_pack; protected PhpDebugPack debug_pack; protected PhptDebuggerFrame phpt_gui; @@ -36,10 +44,10 @@ public class LocalConsoleManager implements ConsoleManager { protected List<String> debug_list, run_test_times_list, run_group_times_list, skip_list; public LocalConsoleManager() { - this(null, null, false, false, false, false, true, false, true, false, true, false, 1, 1, true, 1, 1, 1, null, null, null, null, false, 0, 0, false, false, 0, 0, 0, false, 0, false); + this(null, null, false, false, false, false, true, false, true, false, true, false, 1, 1, true, 1, 1, 1, null, null, null, null, false, 0, 0, false, false, 0, 0, 0, false, 0, false, false, null); } - public LocalConsoleManager(String source_pack, PhpDebugPack debug_pack, boolean overwrite, boolean debug_all, boolean results_only, boolean show_gui, boolean disable_debug_prompt, boolean dont_cleanup_test_pack, boolean phpt_not_in_place, boolean pftt_debug, boolean no_result_file_for_pass_xskip_skip, boolean randomize_order, int run_test_times_all, int run_test_pack, boolean thread_safety, int run_test_times_list_times, int run_group_times, int run_group_times_list_times, List<String> debug_list, List<String> run_test_times_list, List<String> run_group_times_list, List<String> skip_list, boolean skip_smoke_tests, int max_test_read_count, int thread_count, boolean restart_each_test_all, boolean no_restart_all, int delay_between_ms, int run_count, int suspend_seconds, boolean ini_actual_all, long max_run_time_millis, boolean non_interactive) { + public LocalConsoleManager(String source_pack, PhpDebugPack debug_pack, boolean overwrite, boolean debug_all, boolean results_only, boolean show_gui, boolean disable_debug_prompt, boolean dont_cleanup_test_pack, boolean phpt_not_in_place, boolean pftt_debug, boolean no_result_file_for_pass_xskip_skip, boolean randomize_order, int run_test_times_all, int run_test_pack, boolean thread_safety, int run_test_times_list_times, int run_group_times, int run_group_times_list_times, List<String> debug_list, List<String> run_test_times_list, List<String> run_group_times_list, List<String> skip_list, boolean skip_smoke_tests, int max_test_read_count, int thread_count, boolean restart_each_test_all, boolean no_restart_all, int delay_between_ms, int run_count, int suspend_seconds, boolean ini_actual_all, long max_run_time_millis, boolean non_interactive, boolean ignore_output, String debugger_name) { this.source_pack = source_pack; this.debug_pack = debug_pack; this.overwrite = overwrite; @@ -73,6 +81,28 @@ public class LocalConsoleManager implements ConsoleManager { this.ini_actual_all = ini_actual_all; this.max_run_time_millis = max_run_time_millis; this.non_interactive = non_interactive; + this.ignore_output = ignore_output; + this.debugger_name = debugger_name; + + if (LocalHost.getInstance().isWindows()) { + if (debugger_name==null) + db_mgr = isDebugAll()||isDebugList() ? new WinDebugManager() : null; + else if (debugger_name.equalsIgnoreCase("windbg")) + db_mgr = new WinDebugManager(); + else if (debugger_name.equalsIgnoreCase("ttt")) + db_mgr = new TimeTravelTraceDebugManager(); + else + db_mgr = null; + } else { + if (debugger_name==null) + db_mgr = isDebugAll()||isDebugList() ? new GDBDebugManager() : null; + else if (debugger_name.equalsIgnoreCase("gdb")) + db_mgr = new GDBDebugManager(); + else if (debugger_name.equalsIgnoreCase("valgrind")) + db_mgr = new ValgrindMemoryCheckManager(); + else + db_mgr = null; + } } public void showGUI(LocalPhptTestPackRunner test_pack_runner) { @@ -129,6 +159,21 @@ public class LocalConsoleManager implements ConsoleManager { } @Override + public String getDebuggerName() { + return debugger_name; + } + + @Override + public DebuggerManager getDebuggerManager() { + return db_mgr; + } + + @Override + public boolean isIgnoreOutput() { + return ignore_output; + } + + @Override public boolean isNonInteractive() { return non_interactive; } diff --git a/src/com/mostc/pftt/results/PhpResultPack.java b/src/com/mostc/pftt/results/PhpResultPack.java index 1d4c2a3..13691cb 100644 --- a/src/com/mostc/pftt/results/PhpResultPack.java +++ b/src/com/mostc/pftt/results/PhpResultPack.java @@ -111,6 +111,15 @@ public abstract class PhpResultPack { else return ret; } + + public static double round1(double value) { + double ret = ( (double) Math.round( value * 10.0f ) ) / 10.0f; + if (ret==100.0f && value<100.0f) + // only show 100% if its really 100% + return 99.9f; + else + return ret; + } public abstract Collection<AHost> getHosts(); public abstract Collection<String> getPhptTestPacks(AHost host); diff --git a/src/com/mostc/pftt/results/TextBuilder.java b/src/com/mostc/pftt/results/TextBuilder.java new file mode 100644 index 0000000..ea6a321 --- /dev/null +++ b/src/com/mostc/pftt/results/TextBuilder.java @@ -0,0 +1,247 @@ +package com.mostc.pftt.results; + +import groovy.util.BuilderSupport; + +import java.io.StringWriter; +import java.util.LinkedList; +import java.util.Map; + +import com.github.mattficken.io.StringUtil; + +/** Drop-in replacement for MarkupBuilder that generates plain text instead + * + * @author Matt Ficken + * + */ + +public class TextBuilder extends BuilderSupport { + protected final StringWriter sw; + protected final LinkedList<Table> tables; + protected Table cur_table; + protected Tr cur_tr; + protected TdTable cur_td; + + public TextBuilder(StringWriter sw) { + this.sw = sw; + + tables = new LinkedList<Table>(); + } + + protected abstract class TdTable { + + public abstract void append(StringWriter sw, int max_len); + public abstract int getLength(); + + } + + protected class Table extends TdTable { + protected final LinkedList<Tr> trs; + protected final boolean toplevel; + + protected Table(boolean toplevel) { + this.toplevel = toplevel; + trs = new LinkedList<Tr>(); + } + + public void add(Tr tr) { + trs.add(tr); + } + + @Override + public int getLength() { + int len = 0; + for ( int max_len : calcMaxLengths() ) { + len += max_len; + } + return len; + } + + protected LinkedList<Integer> calcMaxLengths() { + LinkedList<Integer> max_lengths = new LinkedList<Integer>(); + int col = 0, len, max_len; + for ( Tr tr : trs ) { + col = 0; len = 0; max_len = 0; + for ( TdTable td : tr.tds ) { + len = td.getLength(); + if (col < max_lengths.size()) { + max_len = max_lengths.get(col); + if (len>max_len) { + max_len = len; + max_lengths.set(col, max_len); + } + } else { + max_len = len; + //max_lengths.set(col, max_len); + max_lengths.add(max_len); + } + col++; + } + } + return max_lengths; + } + + @Override + public void append(StringWriter sw, int max_len) { + LinkedList<Integer> max_lengths = calcMaxLengths(); + for ( Tr tr : trs ) { + tr.append(sw, max_lengths); + if (toplevel) + sw.append("\r\n"); + } + } + + } + + protected class Tr { + protected final LinkedList<TdTable> tds; + + protected Tr() { + tds = new LinkedList<TdTable>(); + } + + public void append(StringWriter sw, LinkedList<Integer> max_lengths) { + int col = 0; + for ( TdTable td : tds ) { + sw.append("| "); + td.append(sw, max_lengths.get(col)); + sw.append(" "); + col++; + } + sw.append("\r\n"); + col = 0; + int max_len, i; + for ( TdTable td : tds ) { + sw.append("+-"); + max_len = max_lengths.get(col); + for ( i=0 ; i < max_len ; i++ ) + sw.append("-"); + sw.append("-"); + col++; + } + } + + public void add(TdTable td) { + tds.add(td); + } + + } + + protected class Td extends TdTable { + protected String str; + protected final int colspan; + + protected Td(int colspan, String str) { + this.colspan = colspan; + this.str = str; + } + + @Override + public void append(StringWriter sw, int max_len) { + // TODO indent if there are newline characters + sw.append(StringUtil.padLast(str, max_len, ' ')); + } + + @Override + public int getLength() { + int i = str.indexOf('\n'); + if (i==-1) + i = str.length(); + return i / colspan; + } + + } + + @Override + protected void nodeCompleted(Object parent, Object child) { + final String name_str = child.toString(); + if (name_str.equals("td")) { + cur_tr.add(cur_td); + cur_td = null; + } else if (name_str.equals("tr")) { + cur_table.add(cur_tr); + cur_tr = null; + } else if (name_str.equals("table")) { + if (tables.size()<2) + // important: append child table's contexts to parent + cur_table.append(sw, 0); // 0 => not used + if (tables.isEmpty()) { + sw.append("\r\n"); + cur_table = null; + } else { + cur_table = tables.removeLast(); + } + } else if (ignoreName(name_str)) { + // ignore + } + } + + protected boolean ignoreName(String name_str) { + return name_str.equals("script")||name_str.equals("head")||name_str.equals("title")||name_str.equals("body")||name_str.equals("html")||name_str.equals("meta"); + } + + @Override + protected Object createNode(Object name) { + return createNode(name, null); + } + + @Override + protected Object createNode(Object name, Object value) { + return createNode(name, null, value); + } + + @Override + protected Object createNode(Object name, Map attributes) { + return createNode(name, attributes, null); + } + + protected void append(String value) { + if (cur_td==null||!(cur_td instanceof Td)) + sw.append(value); + else + ((Td)cur_td).str += value; + } + + @Override + protected Object createNode(Object name, Map attributes, Object value) { + final String name_str = name.toString(); + if (name_str.equals("p")||name_str.equals("br")) { + if (value==null) + append("\r\n"); // <br> shouldn't have a value + else + append("\r\n"+StringUtil.toString(value)); + } else if (name_str.equals("td")) { + final int colspan = attributes!=null && attributes.containsKey("colspan") ? Integer.parseInt(attributes.get("colspan").toString()) : 1; + + cur_td = new Td(colspan, value==null?"":StringUtil.toString(value)); + } else if (name_str.equals("tr")) { + cur_tr = new Tr(); + } else if (name_str.equals("table")) { + if (tables.isEmpty()) { + tables.add(cur_table = new Table(true)); + } else { + cur_td = cur_table = new Table(false); + tables.add(cur_table); + } + } else if (name_str.equals("a")) { + if (attributes!=null && attributes.containsKey("href")) + append(attributes.get("href").toString()); + else + append(StringUtil.toString(value)); + } else if (name_str.equals("img")) { + if (attributes!=null && attributes.containsKey("alt")) + append(attributes.get("alt").toString()); + else + append(StringUtil.toString(value)); + } else if (ignoreName(name_str)) { + // ignore + } else if (value!=null) { + append(StringUtil.toString(value)); + } + return getName(name_str); + } + + @Override + protected void setParent(Object arg0, Object arg1) { + } + +} // end public class TextBuilder diff --git a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java index f902f2b..9f4a2bb 100644 --- a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java +++ b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java @@ -11,7 +11,6 @@ import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -599,7 +598,6 @@ public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S ex // run a timer task while the test is running to kill the test if it takes too long // // wait a while before killing it (double the max runtime for the test) - // TODO temp if (!thread.shouldRun()||(test_run_start_time>0&&Math.abs(System.currentTimeMillis()-test_run_start_time)>PhptTestCase.MAX_TEST_TIME_SECONDS*2000)) { // thread running too long if (thread.isDebuggerAttached()) { @@ -680,7 +678,7 @@ public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S ex @Override public void uncaughtException(java.lang.Thread arg0, java.lang.Throwable arg1) { - arg1.printStackTrace(); + //arg1.printStackTrace(); // wait for #executeTestCases to remove this thread from group System.out.println("END_THREAD " +arg1+" "+Thread.currentThread()); if (arg1 instanceof TestTimeoutException) @@ -722,6 +720,8 @@ public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S ex thread_wsi.close(cm); } } + + cm.println(EPrintType.CLUE, getClass(), "Thread Pool: THREAD FINISHED. pool size="+threads.size()); } } // end public void run @@ -796,19 +796,6 @@ public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S ex } } // end protected void runThreadSafe - public void redo(T test_case) { - test_count.decrementAndGet(); // TODO temp - if (ext==null) { - // ts - group.test_cases.add(test_case); - } else { - // nts - group.test_cases.add(test_case); - non_thread_safe_exts.add(ext); - break_nts.set(true); - } - } - @Override public UncaughtExceptionHandler getUncaughtExceptionHandler() { return this; @@ -839,8 +826,8 @@ public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S ex // test_case = null; try { - test_case = jobs.poll(5, TimeUnit.SECONDS); - } catch ( InterruptedException ex ) {} + test_case = jobs.poll();//.poll(5, TimeUnit.SECONDS); + } catch ( Exception ex ) {} if (test_case==null) { if (shouldRun() && !jobs.isEmpty()) continue; @@ -865,7 +852,10 @@ public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S ex group_key.prepare(); // -debug_all and -debug_list and -debug_named console options - final boolean debugger_attached = (cm.isDebugAll() || cm.isInDebugList(test_case)); + final boolean debugger_attached = + //test_case.getName().contains("mkdir") + //|| + (cm.isDebugAll() || cm.isInDebugList(test_case)); if (parallel) { // TODO create better mechanism to send `sa` to each test case runner @@ -922,31 +912,15 @@ public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S ex runTest(group_key, test_case, debugger_attached); // if test took too long OR tests are running fast now - // TODO temp test decreasing threads when getting lots of timeouts - if (//Math.abs(System.currentTimeMillis() - test_run_start_time.get()) > 60 - //|| - Math.abs(System.currentTimeMillis() - test_run_start_time.get()) < sapi_scenario.getFastTestTimeSeconds()*1000 - &&threads.size()>1) { - // scale back down (decrease number of threads) + if ( + ext==null + &&Math.abs(System.currentTimeMillis() - test_run_start_time.get()) < 4*sapi_scenario.getFastTestTimeSeconds()*1000 + &&threads.size()>1 + &&scale_up_threads.contains(Thread.currentThread())) { cm.println(EPrintType.CLUE, getClass(), "Thread Pool: SCALE DOWN"); - Iterator<TestPackThread<T>> it = scale_up_threads.iterator(); - TestPackThread<T> slow; - while (it.hasNext()) { - slow = it.next(); - it.remove(); - if (slow.ext==null) { - // stop after current test case finished - slow.run_thread.set(false); - // remove 1 NTS thread at a time - // (each NTS thread can remove 1 at a time, so several can get removed at same time) - break; - } else { - // don't stop this one because ext has been dequeued - // and would have gotten lost - } - } + this.stopThisThread(); + break; } - } catch ( InterruptedException ex ) { if (cm.isPfttDebug()) ex.printStackTrace(); @@ -991,12 +965,12 @@ public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S ex @Override protected void createNewThread() { // scale up to handle cluster of slower test cases - cm.println(EPrintType.CLUE, getClass(), "Thread Pool: SCALE UP"); try { scale_up_threads.add(start_thread(parallel)); } catch ( Throwable t ) { twriter.addGlobalException(runner_host, ErrorUtil.toString(t)); } + cm.println(EPrintType.CLUE, getClass(), "Thread Pool: SCALE UP. pool size="+threads.size()); } protected abstract void stopRunningCurrentTest(); diff --git a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java index af37817..94b0ce3 100644 --- a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java +++ b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java @@ -15,7 +15,6 @@ import org.incava.util.diff.Diff; import com.github.mattficken.io.StringUtil; import com.mostc.pftt.host.AHost; -import com.mostc.pftt.model.app.PhpUnitTemplate; import com.mostc.pftt.model.core.EPhptSection; import com.mostc.pftt.model.core.EPhptTestStatus; import com.mostc.pftt.model.core.PhpBuild; @@ -29,6 +28,7 @@ import com.mostc.pftt.results.ITestResultReceiver; import com.mostc.pftt.results.PhptTestResult; import com.mostc.pftt.results.TestCaseCodeCoverage; import com.mostc.pftt.runner.LocalPhptTestPackRunner.PhptThread; +import com.mostc.pftt.runner.PhptTestPreparer.PreparedPhptTestCase; import com.mostc.pftt.scenario.SAPIScenario; import com.mostc.pftt.scenario.ScenarioSetSetup; import com.mostc.pftt.util.ErrorUtil; @@ -41,7 +41,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu protected final AHost host; protected final PhpBuild build; protected final PhptSourceTestPack src_test_pack; - protected final PhptTestCase test_case; + protected final PreparedPhptTestCase prep; protected final ScenarioSetSetup scenario_set; protected final PhptThread thread; protected final SAPIScenario sapi_scenario; @@ -50,7 +50,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu protected TestCaseCodeCoverage code_coverage; protected Map<String, String> env; protected byte[] stdin_post; - protected String skipif_file, test_dir, base_file_name, test_file, test_clean, content_type; + protected String base_file_name, content_type; protected PhpIni ini; protected boolean not_crashed = true; // @see HttpTestCaseRunner // if is_timeout, test output is still processed the same, only marked as TIMEOUT if it would have normally been marked FAIL @@ -58,7 +58,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu protected boolean is_timeout = false; public abstract String getIniActual() throws Exception; - + /** runs the test case and reports the results to the PhptTelemetryManager * * @see #willSkip - called by PhptTestPackRunner before #runTest is called @@ -69,81 +69,106 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu if (!prepare()) // test is SKIP BORK EXCEPTION etc... return; - - current_section = EPhptSection.SKIPIF; // @see #getSAPIOutput - if (skipif_file == null || ( !evalSkipIf(executeSkipIf()) && not_crashed && !is_timeout) ) { - current_section = EPhptSection.TEST; // @see #getSAPIOutput - // no SKIPIF section or executed SKIPIF says to execute the TEST section - prepareTest(); - // - String test_output = executeTest(); - // - if (xdebug) { - // read and filter code coverage data from the output - // @see PhpUnitTemplate#renderXDebugPhptTemplate - StringBuilder sb = new StringBuilder(4096); - code_coverage = new TestCaseCodeCoverage(host, test_file); - String filename = test_file; // can assume it starts here - for ( String line : StringUtil.splitLines(test_output)) { - if (line.startsWith("exe=")) { - code_coverage.addExecutedLine(filename, Integer.parseInt(line.substring("exe=".length()))); - } else if (line.startsWith("didnt_exe=")) { - code_coverage.addNotExecutedLine(filename, Integer.parseInt(line.substring("didnt_exe=".length()))); - } else if (line.startsWith("no_exe=")) { - code_coverage.addNonExecutableLine(filename, Integer.parseInt(line.substring("no_exe=".length()))); - } else if (line.startsWith("file=")) { - filename = line.substring("file=".length()); - } else { - sb.append(line); - sb.append('\n'); + if (prep.skipif_file!=null) { + String skipif_code = prep.test_case.get(EPhptSection.SKIPIF).toLowerCase(); + if (!skipif_code.contains("include") && !skipif_code.contains("PHP_SAPI") && !skipif_code.contains("require")) { + if (host.isWindows() && skipif_code.contains("skip not for windows")||skipif_code.contains("not valid for windows")) { + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.SKIP, prep.test_case, skipif_code, null, null, null, ini, null, null, null, null, null, null, null)); + return; + } else if (!host.isX64() && skipif_code.contains("skip this test is for 64bit platform only")) { + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.SKIP, prep.test_case, skipif_code, null, null, null, ini, null, null, null, null, null, null, null)); + return; + } + + // avoid starting PHP process just to call extension_loaded(); + // + // if we got here, SAPIScenario#willSkip was already called for this test case, + // which would have prevented getting here if the extension wasn't loaded + // + // therefore, don't need to start PHP process just to check that again + // + // this has the additional effect that if the extension couldn't be loaded (corrupted DLL, etc...) + // the test case will be shown as a FAIL (so it'll be noticed, otherwise it would just be an increased SKIP count) + if (skipif_code.contains("extension_loaded(")) { + // extension is already loaded + } else { + current_section = EPhptSection.SKIPIF; // @see #getSAPIOutput + if ( evalSkipIf(executeSkipIf()) ) { + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.SKIP, prep.test_case, skipif_code, null, null, null, ini, null, null, null, null, null, null, null)); + return; } } - test_output = sb.toString(); + } else { + current_section = EPhptSection.SKIPIF; // @see #getSAPIOutput + if ( evalSkipIf(executeSkipIf()) ) { + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.SKIP, prep.test_case, skipif_code, null, null, null, ini, null, null, null, null, null, null, null)); + return; + } } - // - if (not_crashed) { - // - evalTest(test_output, test_case.getCommonCharset()); - - // some tests create files/dirs which, which will cause the test to fail again - // if its run in-place from the same test-pack - if (!cm.isPhptNotInPlace()&&test_clean!=null&&!host.isBusy()) { - current_section = EPhptSection.CLEAN; // @see #getSAPIOutput - executeClean(); // #executeClean != #doRunTestClean + } + + + current_section = EPhptSection.TEST; // @see #getSAPIOutput + // no SKIPIF section or executed SKIPIF says to execute the TEST section + prepareTest(); + // + String test_output = executeTest(); + + // + if (xdebug) { + // read and filter code coverage data from the output + // @see PhpUnitTemplate#renderXDebugPhptTemplate + StringBuilder sb = new StringBuilder(4096); + code_coverage = new TestCaseCodeCoverage(host, prep.test_file); + String filename = prep.test_file; // can assume it starts here + for ( String line : StringUtil.splitLines(test_output)) { + if (line.startsWith("exe=")) { + code_coverage.addExecutedLine(filename, Integer.parseInt(line.substring("exe=".length()))); + } else if (line.startsWith("didnt_exe=")) { + code_coverage.addNotExecutedLine(filename, Integer.parseInt(line.substring("didnt_exe=".length()))); + } else if (line.startsWith("no_exe=")) { + code_coverage.addNonExecutableLine(filename, Integer.parseInt(line.substring("no_exe=".length()))); + } else if (line.startsWith("file=")) { + filename = line.substring("file=".length()); + } else { + sb.append(line); + sb.append('\n'); } } + test_output = sb.toString(); + } + // + if (not_crashed) { + // + PhptTestResult result = evalTest(test_output, prep.test_case.getCommonCharset()); + if (result!=null) + twriter.addResult(host, scenario_set, src_test_pack, result); + + // some tests create files/dirs which, which will cause the test to fail again + // if its run in-place from the same test-pack + if (!cm.isPhptNotInPlace()&&prep.test_clean!=null&&!host.isBusy()) { + current_section = EPhptSection.CLEAN; // @see #getSAPIOutput + executeClean(); // #executeClean != #doRunTestClean + } } + if (!host.isBusy()) doRunTestClean(cm); } + protected void redoCrashedTest() throws Exception { + } + protected void doRunTestClean(ConsoleManager cm) throws IllegalStateException, IOException { - if (cm.isPhptNotInPlace() && host.isWindows() && !host.isRemote()) { - // CRITICAL on Windows(remote file systems): PHP opens a file handle for these files. When running large - // amounts of test, this produces many IO requests. If a PHP process needs to be killed, there - // may still be pending IO requests or at least the local Windows client thinks there is - // (server may have dropped them). These pending IO requests prevent the PHP process from being killed. - // - // Even if all the FILE handles of the process are closed (which LocalHost will do), there may - // still be pending IO requests. - // - // by having the Windows DFS client send a delete request (rather than deleting these files through - // SSHHost, etc...), it may cancel those pending IO operations in its scheduler. - // - // This behavior will cause PHP processes to randomly hang even when the DFS activity is - // less than 1% of a 1000Mbit network. This is part of fixing it (the other part is LocalHost's #close) - host.delete(test_file); - host.deleteIfExists(test_file+".tmp"); - // (if DFS or SMB, #isPhptNotInPlace()==true) - } + } - public AbstractPhptTestCaseRunner2(boolean xdebug, SAPIScenario sapi_scenario, PhpIni ini, PhptThread thread, PhptTestCase test_case, ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack) { + public AbstractPhptTestCaseRunner2(boolean xdebug, SAPIScenario sapi_scenario, PhpIni ini, PhptThread thread, PreparedPhptTestCase prep, ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack) { this.xdebug = xdebug; this.sapi_scenario = sapi_scenario; this.ini = ini; this.thread = thread; - this.test_case = test_case; + this.prep = prep; this.cm = cm; this.twriter = twriter; this.host = host; @@ -161,54 +186,21 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu * @throws Exception */ protected boolean prepare() throws IOException, Exception { - if (test_case.hasBorkInfo()) { - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, test_case, test_case.getBorkInfo(), null, null, null, null, null, null, null, null, null, null, null)); + if (prep.test_case.hasBorkInfo()) { + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, prep.test_case, prep.test_case.getBorkInfo(), null, null, null, null, null, null, null, null, null, null, null)); return false; } - if (test_case.hasUnsupportedInfo()) { - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.UNSUPPORTED, test_case, test_case.getUnsupportedInfo(), null, null, null, null, null, null, null, null, null, null, null)); + if (prep.test_case.hasUnsupportedInfo()) { + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.UNSUPPORTED, prep.test_case, prep.test_case.getUnsupportedInfo(), null, null, null, null, null, null, null, null, null, null, null)); return false; } - test_dir = host.joinIntoOnePath(active_test_pack.getStorageDirectory(), AHost.dirname(test_case.getName())); - - // CRITICAL - // TODO must be done for -auto - should be more efficient - host.mkdirs(test_dir); - - base_file_name = createBaseName(); - - // - if (test_case.containsSection(EPhptSection.SKIPIF)) { - skipif_file = host.joinIntoOnePath(test_dir, base_file_name + ".skip.php"); - - host.saveTextFile(skipif_file, test_case.get(EPhptSection.SKIPIF)); - } else { - // clearly flag that skipif isn't to be executed - skipif_file = null; - } - // @see AbstractSAPIScenario#willSkip - skips certain tests before even getting here to #prepare - // - - test_file = host.joinIntoOnePath(test_dir, base_file_name + ".php"); - - if (test_case.containsSection(EPhptSection.CLEAN)) { - test_clean = host.joinIntoOnePath(test_dir, base_file_name + ".clean.php"); - - host.saveTextFile(test_clean, test_case.get(EPhptSection.CLEAN)); - } // else test_clean = null; - - return true; } // end boolean prepare - protected String createBaseName() { - return AHost.basename(test_case.getBaseName()); - } - /** executes SKIPIF section and returns output * * @return @@ -228,7 +220,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu // // find 'skip ' or 'skip...' or 'skip.. ' or 'skip' but ignore '404 error, file not found abc.skip.php' // (don't need to check for multiple occurences of 'skip', just one... finding abc.skip.php would be a TEST_EXCEPTION or FAIL anyway) - if ((is_timeout||lc_output.contains("skip")) && ( !( this instanceof HttpPhptTestCaseRunner ) || !lc_output.contains("404")) ) { + if ((is_timeout||lc_output.contains("skip")||lc_output.contains("error")) && ( !( this instanceof HttpPhptTestCaseRunner ) || !lc_output.contains("404")) ) { // test is to be skipped // decide to mark test SKIP or XSKIP (could test be executed on this OS?) @@ -236,15 +228,15 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu if (host.isWindows()) { if ( (lc_output.contains("only ")&&(lc_output.contains(" linux")||lc_output.contains(" non windows")||lc_output.contains(" non-windows")))||(lc_output.contains("not ")&&lc_output.contains(" windows"))) // can"t run this test on this OS - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.XSKIP, test_case, output, null, null, null, ini, null, null, null, null, null, null, null)); + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.XSKIP, prep.test_case, output, null, null, null, ini, null, null, null, null, null, null, null)); else - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.SKIP, test_case, output, null, null, null, ini, null, null, null, null, null, null, null)); + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.SKIP, prep.test_case, output, null, null, null, ini, null, null, null, null, null, null, null)); } else { if ( (lc_output.contains("only ")&&lc_output.contains(" windows"))||(lc_output.contains("not ")&&lc_output.contains(" linux"))) // can"t run this test on this OS - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.XSKIP, test_case, output, null, null, null, ini, null, null, null, null, null, null, null)); + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.XSKIP, prep.test_case, output, null, null, null, ini, null, null, null, null, null, null, null)); else - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.SKIP, test_case, output, null, null, null, ini, null, null, null, null, null, null, null)); + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.SKIP, prep.test_case, output, null, null, null, ini, null, null, null, null, null, null, null)); } // skip this test @@ -254,14 +246,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu // execute this test, don't skip it return false; } // end protected void evalSkipIf - - protected String preparePhptTestCode(String php_code) { - if (xdebug) - return PhpUnitTemplate.renderXDebugPhptTemplate(php_code); - else - return php_code; - } - + static final Pattern PATTERN_CONTENT_TYPE = Pattern.compile("Content-Type:(.*)"); /** prepares to execute the test after the SKIPIF section is executed (if any) * #prepare prepares only up to that, this does the rest. @@ -270,25 +255,11 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu * @throws Exception */ protected void prepareTest() throws Exception { - if (test_case.containsSection(EPhptSection.FILE_EXTERNAL)) { - // open external file and copy to test_file (binary, no char conversion - which could break it - often this is a PHAR file - which will be broken if charset coversion is done) - - // @see run-test.php:1281 - String src_file = host.joinIntoOnePath( - src_test_pack.getSourceDirectory(), - AHost.dirname(test_case.getName()), - test_case.getTrim(EPhptSection.FILE_EXTERNAL).replaceAll("\\.\\.", "") - ); - host.copy(src_file, test_file); - - } else { - host.saveTextFile(test_file, preparePhptTestCode(test_case.get(EPhptSection.FILE)), test_case.getCommonCharsetEncoder()); - } - // + prep.prepareTest(src_test_pack, host); // copy STDIN to pass (POST, POST_RAW, STDIN, etc...) - if (test_case.containsSection(EPhptSection.POST_RAW)) { - String post = test_case.getTrim(EPhptSection.POST_RAW); + if (prep.test_case.containsSection(EPhptSection.POST_RAW)) { + String post = prep.test_case.getTrim(EPhptSection.POST_RAW); StringBuilder request_sb = new StringBuilder(); @@ -330,15 +301,15 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu setRequestMethod("POST"); if (StringUtil.isEmpty(request)) { - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, test_case, "Request is empty", null, null, null, null, null, null, null, null, null, null, null)); + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, prep.test_case, "Request is empty", null, null, null, null, null, null, null, null, null, null, null)); return; } stdin_post = request.getBytes(); - } else if (test_case.containsSection(EPhptSection.PUT)) { - String post = test_case.getTrim(EPhptSection.PUT); + } else if (prep.test_case.containsSection(EPhptSection.PUT)) { + String post = prep.test_case.getTrim(EPhptSection.PUT); String[] raw_lines = StringUtil.splitLines(post); StringBuilder request_sb = new StringBuilder(); @@ -372,11 +343,11 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu stdin_post = request.getBytes(); - } else if (test_case.containsSection(EPhptSection.POST)) { + } else if (prep.test_case.containsSection(EPhptSection.POST)) { - String post = test_case.getTrim(EPhptSection.POST); + String post = prep.test_case.getTrim(EPhptSection.POST); - if (test_case.containsSection(EPhptSection.GZIP_POST)) { + if (prep.test_case.containsSection(EPhptSection.GZIP_POST)) { // php's gzencode() => gzip compression => java's GZIPOutputStream // post = gzencode(post, 9, FORCE_GZIP); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -385,7 +356,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu d.close(); stdin_post = baos.toByteArray(); setContentEncoding("gzip"); - } else if (test_case.containsSection(EPhptSection.DEFLATE_POST)) { + } else if (prep.test_case.containsSection(EPhptSection.DEFLATE_POST)) { // php's gzcompress() => zlib compression => java's DeflaterOutputStream // post = gzcompress(post, 9); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -449,15 +420,15 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu * @param charset * @throws Throwable */ - protected void evalTest(String output, Charset charset) throws Throwable { + protected PhptTestResult evalTest(String output, Charset charset) throws Throwable { // Windows: line endings are already made consistent by AHost#exec* String expected, preoverride_actual = null; - if (test_case.containsSection(EPhptSection.EXPECTF) || test_case.containsSection(EPhptSection.EXPECTREGEX)) { - if (test_case.containsSection(EPhptSection.EXPECTF)) { - expected = test_case.getTrim(EPhptSection.EXPECTF); + if (prep.test_case.containsSection(EPhptSection.EXPECTF) || prep.test_case.containsSection(EPhptSection.EXPECTREGEX)) { + if (prep.test_case.containsSection(EPhptSection.EXPECTF)) { + expected = prep.test_case.getTrim(EPhptSection.EXPECTF); } else { - expected = test_case.getTrim(EPhptSection.EXPECTREGEX); + expected = prep.test_case.getTrim(EPhptSection.EXPECTREGEX); } boolean expected_re_match; @@ -466,29 +437,24 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu String output_trim = output.trim(); try { - expected_re_match = test_case.getExpectedCompiled(host, scenario_set, twriter, false).match(output_trim); + expected_re_match = prep.test_case.getExpectedCompiled(host, scenario_set, twriter, false).match(output_trim); } catch (Throwable ex) { - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, test_case, ErrorUtil.toString(ex), null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, prep.test_case, ErrorUtil.toString(ex), null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); throw ex; } if (expected_re_match) { - twriter.addResult(host, scenario_set, src_test_pack, notifyPassOrXFail(new PhptTestResult(host, test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage))); - - return; + return notifyPassOrXFail(new PhptTestResult(host, prep.test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, prep.test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); } - if (test_case.expectsWarningOrFatalError()) { + if (prep.test_case.expectsWarningOrFatalError()) { try { - expected_re_match = test_case.getExpectedCompiled(host, scenario_set, twriter, true).match(output_trim); + expected_re_match = prep.test_case.getExpectedCompiled(host, scenario_set, twriter, true).match(output_trim); } catch (Throwable ex) { - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, test_case, ErrorUtil.toString(ex), null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, prep.test_case, ErrorUtil.toString(ex), null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); throw ex; } if (expected_re_match) { - - twriter.addResult(host, scenario_set, src_test_pack, notifyPassOrXFail(new PhptTestResult(host, test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage))); - - return; + return notifyPassOrXFail(new PhptTestResult(host, prep.test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, prep.test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); } } preoverride_actual = output; @@ -502,42 +468,33 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu } else { // compare again try { - expected_re_match = test_case.getExpectedCompiled(host, scenario_set, twriter, false).match(output_trim); + expected_re_match = prep.test_case.getExpectedCompiled(host, scenario_set, twriter, false).match(output_trim); } catch (Throwable ex) { - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, test_case, ErrorUtil.toString(ex), null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, prep.test_case, ErrorUtil.toString(ex), null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); throw ex; } if (expected_re_match) { - - twriter.addResult(host, scenario_set, src_test_pack, notifyPassOrXFail(new PhptTestResult(host, test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage))); - - return; + return notifyPassOrXFail(new PhptTestResult(host, prep.test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, prep.test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); } - if (test_case.expectsWarningOrFatalError()) { + if (prep.test_case.expectsWarningOrFatalError()) { try { - expected_re_match = test_case.getExpectedCompiled(host, scenario_set, twriter, true).match(output_trim); + expected_re_match = prep.test_case.getExpectedCompiled(host, scenario_set, twriter, true).match(output_trim); } catch (Throwable ex) { - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, test_case, ErrorUtil.toString(ex), null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.BORK, prep.test_case, ErrorUtil.toString(ex), null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); throw ex; } if (expected_re_match) { - - twriter.addResult(host, scenario_set, src_test_pack, notifyPassOrXFail(new PhptTestResult(host, test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage))); - - return; + return notifyPassOrXFail(new PhptTestResult(host, prep.test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, prep.test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); } } } - } else if (test_case.containsSection(EPhptSection.EXPECT)) { - expected = test_case.get(EPhptSection.EXPECT); + } else if (prep.test_case.containsSection(EPhptSection.EXPECT)) { + expected = prep.test_case.get(EPhptSection.EXPECT); output = remove_header_from_output(output); - if (equalsNoWS(output, expected)||(test_case.expectsWarningOrFatalError() && equalsNoWS(output, PhptTestCase.removeWarningAndFatalError(expected)))||(output.contains("<html>")&&!output.contains("404"))||(test_case.isNamed("ext/phar/tests/zip/phar_commitwrite.phpt")&&expected.contains(output.substring(50, 60)))||(test_case.isNamed("ext/phar/tests/tar/phar_commitwrite.phpt")&&expected.contains(output.substring(60, 70)))) { - - twriter.addResult(host, scenario_set, src_test_pack, notifyPassOrXFail(new PhptTestResult(host, test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, null, code_coverage))); - - return; + if (equalsNoWS(output, expected)||(prep.test_case.expectsWarningOrFatalError() && equalsNoWS(output, PhptTestCase.removeWarningAndFatalError(expected)))||(output.contains("<html>")&&!output.contains("404"))||(prep.test_case.isNamed("ext/phar/tests/zip/phar_commitwrite.phpt")&&expected.contains(output.substring(50, 60)))||(prep.test_case.isNamed("ext/phar/tests/tar/phar_commitwrite.phpt")&&expected.contains(output.substring(60, 70)))) { + return notifyPassOrXFail(new PhptTestResult(host, prep.test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, prep.test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, null, code_coverage)); } preoverride_actual = output; @@ -551,20 +508,15 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu } else { // compare again if (equalsNoWS(output, expected)) { - - twriter.addResult(host, scenario_set, src_test_pack, notifyPassOrXFail(new PhptTestResult(host, test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage))); - - return; + return notifyPassOrXFail(new PhptTestResult(host, prep.test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, prep.test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); } // end if } - } else if (test_case.containsSection(EPhptSection.EXPECTHEADERS)) { + } else if (prep.test_case.containsSection(EPhptSection.EXPECTHEADERS)) { output = remove_header_from_output(output); String output_trim = output.trim(); if (StringUtil.isEmpty(output_trim)||(this instanceof HttpPhptTestCaseRunner&&output.contains("<html>")&&!output.contains("404"))) { - twriter.addResult(host, scenario_set, src_test_pack, notifyPassOrXFail(new PhptTestResult(host, test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage))); - - return; + return notifyPassOrXFail(new PhptTestResult(host, prep.test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, prep.test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); } } @@ -572,29 +524,29 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu // generate a diff String[] actual_lines = StringUtil.splitLines(output); - String[] expected_lines = StringUtil.splitLines(test_case.getExpected()); + String[] expected_lines = StringUtil.splitLines(prep.test_case.getExpected()); Diff<String> diff = new Diff<String>(expected_lines, actual_lines); String expectf; // generate the EXPECTF section to show the user the regular expression that was actually used (generated from EXPECTF section) to evaluate test output - if (test_case.containsSection(EPhptSection.EXPECTF)) { - expectf = PhptTestCase.prepareExpectF(test_case.getTrim(EPhptSection.EXPECTF)); + if (prep.test_case.containsSection(EPhptSection.EXPECTF)) { + expectf = PhptTestCase.prepareExpectF(prep.test_case.getTrim(EPhptSection.EXPECTF)); } else { expectf = null; } PhptTestResult result; - if (test_case.isXFail()) { - result = notifyNotPass(new PhptTestResult(host, is_timeout?EPhptTestStatus.TIMEOUT:EPhptTestStatus.XFAIL_WORKS, test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); + if (prep.test_case.isXFail()) { + result = notifyNotPass(new PhptTestResult(host, is_timeout?EPhptTestStatus.TIMEOUT:EPhptTestStatus.XFAIL_WORKS, prep.test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage)); } else { - result = notifyNotPass(notifyFail(new PhptTestResult(host, is_timeout?EPhptTestStatus.TIMEOUT:EPhptTestStatus.FAIL, test_case, output, actual_lines, expected_lines, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), diff, expectf, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage))); + result = notifyNotPass(notifyFail(new PhptTestResult(host, is_timeout?EPhptTestStatus.TIMEOUT:EPhptTestStatus.FAIL, prep.test_case, output, actual_lines, expected_lines, charset, ini, env, splitCmdString(), stdin_post, getShellScript(), diff, expectf, preoverride_actual, getSAPIOutput(), getSAPIConfig(), code_coverage))); } if (result==null) - return; // redoing + return null; // redoing // // set result#regex_compiler_dump and result#regex_output dump if test result is FAIL or XFAIL_WORKS and test has an EXPECTF or EXPECTREGEX section - if (!is_timeout && (test_case.containsSection(EPhptSection.EXPECTF) || test_case.containsSection(EPhptSection.EXPECTREGEX))) { + if (!is_timeout && (prep.test_case.containsSection(EPhptSection.EXPECTF) || prep.test_case.containsSection(EPhptSection.EXPECTREGEX))) { // test may be failing due to a bad regular expression in test or bug in regular expression engine // // get a debug dump from the regular expression engine to save with the result @@ -606,15 +558,15 @@ public abstract class AbstractPhptTestCaseRunner2 extends AbstractPhptTestCaseRu PrintWriter dump_pw = new PrintWriter(dump_sw); PrintWriter output_pw = new PrintWriter(output_sw); - test_case.debugExpectedRegularExpression(host, scenario_set, twriter, result.actual, dump_pw, output_pw); + prep.test_case.debugExpectedRegularExpression(host, scenario_set, twriter, result.actual, dump_pw, output_pw); result.regex_compiler_dump = dump_sw.toString(); result.regex_output = output_sw.toString(); } // - twriter.addResult(host, scenario_set, src_test_pack, result); - } // end protected void evalTest + return result; + } // end protected PhptTestResult evalTest protected PhptTestResult notifyPassOrXFail(PhptTestResult result) { if (cm.isGetActualIniAll()) { diff --git a/src/com/mostc/pftt/runner/AbstractTestPackRunner.java b/src/com/mostc/pftt/runner/AbstractTestPackRunner.java index ab2a72e..f6672ea 100644 --- a/src/com/mostc/pftt/runner/AbstractTestPackRunner.java +++ b/src/com/mostc/pftt/runner/AbstractTestPackRunner.java @@ -61,9 +61,9 @@ public abstract class AbstractTestPackRunner<S extends SourceTestPack<?, T>, T e @Override public void notifySlowTest() { - if (canCreateNewThread()) { + /*if (canCreateNewThread()) { createNewThread(); - } + }*/ } diff --git a/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java b/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java index 7a82e66..1a6ffb6 100644 --- a/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java @@ -14,12 +14,12 @@ import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.model.core.PhpIni; import com.mostc.pftt.model.core.PhptActiveTestPack; import com.mostc.pftt.model.core.PhptSourceTestPack; -import com.mostc.pftt.model.core.PhptTestCase; import com.mostc.pftt.model.sapi.WebServerInstance; import com.mostc.pftt.model.sapi.WebServerManager; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.ITestResultReceiver; import com.mostc.pftt.runner.LocalPhptTestPackRunner.PhptThread; +import com.mostc.pftt.runner.PhptTestPreparer.PreparedPhptTestCase; import com.mostc.pftt.scenario.BuiltinWebServerScenario; import com.mostc.pftt.scenario.ScenarioSetSetup; import com.mostc.pftt.util.TimerUtil; @@ -29,12 +29,12 @@ public class BuiltinWebHttpPhptTestCaseRunner extends HttpPhptTestCaseRunner { public BuiltinWebHttpPhptTestCaseRunner(boolean xdebug, BuiltinWebServerScenario sapi_scenario, PhpIni ini, Map<String, String> env, HttpParams params, HttpProcessor httpproc, HttpRequestExecutor httpexecutor, WebServerManager smgr, - WebServerInstance web, PhptThread thread, PhptTestCase test_case, + WebServerInstance web, PhptThread thread, PreparedPhptTestCase prep, ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack) { - super(xdebug, sapi_scenario, ini, env, params, httpproc, httpexecutor, smgr, web, thread, test_case, + super(xdebug, sapi_scenario, ini, env, params, httpproc, httpexecutor, smgr, web, thread, prep, cm, twriter, host, scenario_set_setup, build, src_test_pack, active_test_pack); } @@ -67,12 +67,6 @@ public class BuiltinWebHttpPhptTestCaseRunner extends HttpPhptTestCaseRunner { }); test_socket = null; } - - @Override - protected String createBaseName() { - // some intl tests have + in their name... sending this to the builtin web server breaks it (HTTP 404) - return super.createBaseName().replace("+", ""); - } @Override protected String do_http_get(String path) throws Exception { @@ -116,7 +110,7 @@ public class BuiltinWebHttpPhptTestCaseRunner extends HttpPhptTestCaseRunner { sb.append("PFTT: 3 more attempts, each 1 minute, with 10 seconds between each attempt\n"); sb.append("PFTT: This test case breaks the web server!\n"); sb.append("PFTT: was trying to run ("+section+" section of): "); - sb.append(test_case.getName()); + sb.append(prep.test_case.getName()); sb.append("\n"); sb.append("PFTT: these two lists refer only to second web server (created for specifically for only this test)\n"); web.getActiveTestListString(sb); diff --git a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java index a57e6f5..f65335b 100644 --- a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java @@ -27,6 +27,7 @@ import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.ITestResultReceiver; import com.mostc.pftt.results.PhptTestResult; import com.mostc.pftt.runner.LocalPhptTestPackRunner.PhptThread; +import com.mostc.pftt.runner.PhptTestPreparer.PreparedPhptTestCase; import com.mostc.pftt.scenario.CliScenario; import com.mostc.pftt.scenario.ScenarioSetSetup; @@ -40,13 +41,13 @@ import com.mostc.pftt.scenario.ScenarioSetSetup; public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { protected final CliSAPIInstance sapi; - protected final boolean debugger_attached; + protected boolean debugger_attached; protected EExecutableType exe_type = EExecutableType.CLI; protected ExecOutput output; protected String query_string, shell_script, test_cmd, shell_file; - public CliPhptTestCaseRunner(boolean xdebug, CliScenario sapi_scenario, CliSAPIInstance sapi, PhpIni ini, PhptThread thread, PhptTestCase test_case, ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack, boolean debugger_attached) { - super(xdebug, sapi_scenario, ini, thread, test_case, cm, twriter, host, scenario_set_setup, build, src_test_pack, active_test_pack); + public CliPhptTestCaseRunner(boolean xdebug, CliScenario sapi_scenario, CliSAPIInstance sapi, PhpIni ini, PhptThread thread, PreparedPhptTestCase prep, ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack, boolean debugger_attached) { + super(xdebug, sapi_scenario, ini, thread, prep, cm, twriter, host, scenario_set_setup, build, src_test_pack, active_test_pack); this.sapi = sapi; this.debugger_attached = debugger_attached; } @@ -55,17 +56,17 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { protected boolean prepare() throws IOException, Exception { if (super.prepare()) { /* For GET/POST tests, check if cgi sapi is available and if it is, use it. */ - if (test_case.containsAnySection(EPhptSection.GET, EPhptSection.POST, EPhptSection.PUT, EPhptSection.POST_RAW, EPhptSection.COOKIE, EPhptSection.EXPECTHEADERS)) { + if (prep.test_case.containsAnySection(EPhptSection.GET, EPhptSection.POST, EPhptSection.PUT, EPhptSection.POST_RAW, EPhptSection.COOKIE, EPhptSection.EXPECTHEADERS)) { if (build.hasPhpCgiExe()) { exe_type = EExecutableType.CGI; } else { - twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.XSKIP, test_case, "CGI not available", null, null, null, null, null, null, null, null, null, null, null)); + twriter.addResult(host, scenario_set, src_test_pack, new PhptTestResult(host, EPhptTestStatus.XSKIP, prep.test_case, "CGI not available", null, null, null, null, null, null, null, null, null, null, null)); return false; } } - env = generateENVForTestCase(cm, host, build, scenario_set, test_case); + env = generateENVForTestCase(cm, host, build, scenario_set, prep.test_case); return true; } @@ -81,15 +82,15 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { protected void prepareTest() throws Exception { super.prepareTest(); - // generate cmd string to run test_file with php.exe + // generate cmd string to run prep.test_file with php.exe // { - if (test_case.containsSection(EPhptSection.ARGS)) { + if (prep.test_case.containsSection(EPhptSection.ARGS)) { // copy CLI args to pass query_string = " -- " + - StringUtil.removeLineEnding(test_case.getTrim(EPhptSection.ARGS)); - } else if (test_case.containsSection(EPhptSection.GET)) { - query_string = test_case.getTrim(EPhptSection.GET); + StringUtil.removeLineEnding(prep.test_case.getTrim(EPhptSection.ARGS)); + } else if (prep.test_case.containsSection(EPhptSection.GET)) { + query_string = prep.test_case.getTrim(EPhptSection.GET); String[] query_pairs = query_string.split("\\&"); @@ -103,14 +104,14 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { // - if (test_case.containsSection(EPhptSection.STDIN)) { + if (prep.test_case.containsSection(EPhptSection.STDIN)) { if (host.isWindows()) { // @see Zend/tests/multibyte* ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write(test_case.get(EPhptSection.STDIN).getBytes()); + baos.write(prep.test_case.get(EPhptSection.STDIN).getBytes()); stdin_post = baos.toByteArray(); } else { - stdin_post = test_case.get(EPhptSection.STDIN).getBytes(); + stdin_post = prep.test_case.get(EPhptSection.STDIN).getBytes(); } } @@ -121,12 +122,12 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { env.put(ENV_QUERY_STRING, query_string); // these 2 env vars are critical for some tests (ex: ext/phar) - env.put(ENV_PATH_TRANSLATED, host.fixPath(test_file)); + env.put(ENV_PATH_TRANSLATED, host.fixPath(prep.test_file)); // critical: this is actually how php-cgi gets the script filename (not with -f switch. not sure why run-test uses -f too) - env.put(ENV_SCRIPT_FILENAME, host.fixPath(test_file)); + env.put(ENV_SCRIPT_FILENAME, host.fixPath(prep.test_file)); - if (test_case.containsSection(EPhptSection.COOKIE)) { - env.put(ENV_HTTP_COOKIE, test_case.getTrim(EPhptSection.COOKIE)); + if (prep.test_case.containsSection(EPhptSection.COOKIE)) { + env.put(ENV_HTTP_COOKIE, prep.test_case.getTrim(EPhptSection.COOKIE)); } else if (!env.containsKey(ENV_HTTP_COOKIE)) { env.put(ENV_HTTP_COOKIE, ""); } @@ -152,10 +153,10 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { env.put(AbstractPhptTestCaseRunner.ENV_PFTT_IS, "1"); // generate it now so it can be used in the shell script - test_cmd = sapi.createPhpCommand(exe_type, test_file, query_string); + test_cmd = sapi.createPhpCommand(exe_type, prep.test_file, query_string, debugger_attached); prepareSTDIN(); - createShellScript(); + // TODO temp createShellScript(); } // end protected void prepareTest @Override @@ -190,16 +191,23 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { env.put(ENV_USE_ZEND_ALLOC, "1"); if (!env.containsKey(ENV_PATH_TRANSLATED)) - env.put(ENV_PATH_TRANSLATED, skipif_file); + env.put(ENV_PATH_TRANSLATED, prep.skipif_file); if (!env.containsKey(ENV_SCRIPT_FILENAME)) - env.put(ENV_SCRIPT_FILENAME, skipif_file); + env.put(ENV_SCRIPT_FILENAME, prep.skipif_file); - // execute SKIPIF (60 second timeout) - output = sapi.execute(exe_type, skipif_file, null, AHost.ONE_MINUTE, env, active_test_pack.getStorageDirectory()); + // execute SKIPIF (5 second timeout since its a little bit of PHP code that doesn't do much) + output = sapi.execute(exe_type, prep.base_file_name, prep.skipif_file, null, 5, env, active_test_pack.getStorageDirectory(), debugger_attached); - return output.output; + return output.output; } // end String executeSkipIf + @Override + protected void redoCrashedTest() throws Exception { + test_cmd = sapi.createPhpCommand(exe_type, prep.test_file, query_string, debugger_attached); + ((CliPhptTestCaseRunner)this).debugger_attached = true; + executeTest(); + } + protected ExecHandle running_test_handle; @Override protected void stop(boolean force) { @@ -214,7 +222,7 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { // if test is taking longer than 30 seconds to run, spin up an additional thread to compensate (so other non-slow tests can be executed) running_test_handle = sapi.execThread( cm, - test_case.getBaseName(), + prep.test_case.getBaseName(), scenario_set.getScenarioSet(), test_cmd, active_test_pack.getStorageDirectory(), @@ -227,49 +235,51 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { running_test_handle.run( cm, output_sb, - test_case.isNon8BitCharset()?test_case.getCommonCharset():null, + prep.test_case.isNon8BitCharset()?prep.test_case.getCommonCharset():null, PhptTestCase.MAX_TEST_TIME_SECONDS, thread, sapi_scenario.getSlowTestTimeSeconds(), cm.getSuspendSeconds(), IOUtil.HALF_MEGABYTE ); - - return output_sb.toString(); + String output_str; + if (cm.isIgnoreOutput()) { + output_str = ""; + } else { + output_str = output_sb.toString(); + if (output_str.contains("PHP Warning: Module")) { + output_sb = new StringBuilder(1024); + for ( String line : StringUtil.splitLines(output_str) ) { + if (!line.startsWith("PHP Warning: Module")) { + output_sb.append(line); + output_sb.append('\n'); + } + } + output_str = output_sb.toString(); + } + } + return output_str; } @Override protected String executeTest() throws Exception { String output_str = doExecuteTest(); - if (running_test_handle.isTimedOut() || (running_test_handle.getExitCode()==-1 && exe_type==EExecutableType.CGI)) { + if (running_test_handle!=null&&(running_test_handle.isTimedOut() || (running_test_handle.getExitCode()==-1 && exe_type==EExecutableType.CGI))) { // if test took longer than 1 minute, OR // test is using php-cgi.exe and exited with -1 // (which means file not found, but count it as a timeout) is_timeout = true; } - /*if (output_str.length()==0 - || is_timeout - || (running_test_handle.isCrashed() - && running_test_handle.getExitCode() != -2 - && running_test_handle.getExitCode() != NTStatus.STATUS_ACCESS_VIOLATION - )) { - // try again to be sure - running_test_handle = null; - - output_str = doExecuteTest(); - - if (running_test_handle.isTimedOut() || (running_test_handle.getExitCode()==-1 && exe_type==EExecutableType.CGI)) { - is_timeout = true; - } else { - is_timeout = false; - } - }*/ - if (!is_timeout && running_test_handle.isCrashed()) { + if (!is_timeout && running_test_handle != null && running_test_handle.isCrashed()) { not_crashed = false; // @see #runTest + // TODO temp ((LocalExecHandle)running_test_handle).copyTTT(); + int exit_code = running_test_handle.getExitCode(); - twriter.addResult(host, scenario_set, src_test_pack, notifyNotPass(new PhptTestResult(host, EPhptTestStatus.CRASH, test_case, "PFTT: exit_code="+exit_code+" status="+AHost.guessExitCodeStatus(host, exit_code)+"\n"+output_str, null, null, null, ini, env, null, stdin_post, null, null, null, null, output_str, null))); + twriter.addResult(host, scenario_set, src_test_pack, notifyNotPass(new PhptTestResult(host, EPhptTestStatus.CRASH, prep.test_case, "PFTT: exit_code="+exit_code+" status="+AHost.guessExitCodeStatus(host, exit_code)+"\n"+output_str, null, null, null, ini, env, null, stdin_post, null, null, null, null, output_str, null))); + } else if (running_test_handle!=null) { + // TODO temp ((LocalExecHandle)running_test_handle).deleteTTT(); } running_test_handle = null; @@ -277,25 +287,10 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { return output_str; } // end String executeTest - /*@Override - protected PhptTestResult notifyNotPass(PhptTestResult result) { - // TODO temp - // try FAIL TIMEOUT XFAIL_WORKS - if (result.status!=EPhptTestStatus.CRASH && test_case.redo!=true) { - test_case.redo = true; - this.thread.redo(test_case); - - // signal not to record this attempt - return null; - } else { - return super.notifyNotPass(result); - } - }*/ - @Override protected void executeClean() throws Exception { // execute cleanup script - sapi.execute(exe_type, test_clean, query_string, AHost.ONE_MINUTE, env, active_test_pack.getStorageDirectory()); + sapi.execute(exe_type, prep.base_file_name, prep.test_clean, query_string, AHost.ONE_MINUTE, env, active_test_pack.getStorageDirectory(), debugger_attached); } // end void executeClean @@ -314,7 +309,7 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { // // create a .cmd (Windows batch script) or .sh (shell script) that will actually execute PHP // this enables PHP to be executed like what PFTT does, but using a shell|batch script - shell_file = test_file + (host.isWindows() ? ".cmd" : ".sh" ); + shell_file = prep.test_file + (host.isWindows() ? ".cmd" : ".sh" ); if (shell_file.startsWith(active_test_pack.getStorageDirectory())) { shell_file = shell_file.substring(active_test_pack.getStorageDirectory().length()); if (shell_file.startsWith("/")||shell_file.startsWith("\\")) @@ -328,7 +323,7 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { } else { fw.println("#!/bin/sh"); } - fw.println("cd "+host.fixPath(test_dir)); + fw.println("cd "+host.fixPath(prep.test_dir)); for ( String name : env.keySet()) { String value = env.get(name); if (value==null) @@ -363,7 +358,7 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { } // end protected void createShellScript protected void prepareSTDIN() throws IOException { - String stdin_file = test_file + ".stdin"; + String stdin_file = prep.test_file + ".stdin"; if (stdin_file.startsWith(active_test_pack.getStorageDirectory())) { stdin_file = stdin_file.substring(active_test_pack.getStorageDirectory().length()); if (stdin_file.startsWith("/")||stdin_file.startsWith("\\")) diff --git a/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java b/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java index 3390bfc..6282636 100644 --- a/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java @@ -38,6 +38,7 @@ import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.ITestResultReceiver; import com.mostc.pftt.results.PhptTestResult; import com.mostc.pftt.runner.LocalPhptTestPackRunner.PhptThread; +import com.mostc.pftt.runner.PhptTestPreparer.PreparedPhptTestCase; import com.mostc.pftt.scenario.WebServerScenario; import com.mostc.pftt.scenario.ScenarioSetSetup; import com.mostc.pftt.util.ErrorUtil; @@ -62,8 +63,8 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { protected final HttpRequestExecutor httpexecutor; protected Socket test_socket; - public HttpPhptTestCaseRunner(boolean xdebug, WebServerScenario sapi_scenario, PhpIni ini, Map<String,String> env, HttpParams params, HttpProcessor httpproc, HttpRequestExecutor httpexecutor, WebServerManager smgr, WebServerInstance web, PhptThread thread, PhptTestCase test_case, ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack) { - super(xdebug, sapi_scenario, ini, thread, test_case, cm, twriter, host, scenario_set, build, src_test_pack, active_test_pack); + public HttpPhptTestCaseRunner(boolean xdebug, WebServerScenario sapi_scenario, PhpIni ini, Map<String,String> env, HttpParams params, HttpProcessor httpproc, HttpRequestExecutor httpexecutor, WebServerManager smgr, WebServerInstance web, PhptThread thread, PreparedPhptTestCase prep, ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack) { + super(xdebug, sapi_scenario, ini, thread, prep, cm, twriter, host, scenario_set, build, src_test_pack, active_test_pack); this.params = params; this.httpproc = httpproc; this.httpexecutor = httpexecutor; @@ -75,8 +76,8 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { this.env = new HashMap<String,String>(7); this.env.putAll(env); - this.env.put("TEMP", active_test_pack.getStorageDirectory()+"/"+AHost.dirname(test_case.getName())); - this.env.put("TMP", active_test_pack.getStorageDirectory()+"/"+AHost.dirname(test_case.getName())); + this.env.put("TEMP", active_test_pack.getStorageDirectory()+"/"+AHost.dirname(prep.test_case.getName())); + this.env.put("TMP", active_test_pack.getStorageDirectory()+"/"+AHost.dirname(prep.test_case.getName())); } else { this.env = env; } @@ -92,7 +93,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { protected void prepareTest() throws Exception { super.prepareTest(); - cookie_str = test_case.get(EPhptSection.COOKIE); + cookie_str = prep.test_case.get(EPhptSection.COOKIE); } protected void markTestAsCrash() throws Exception { @@ -102,7 +103,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { return; not_crashed = false; // @see #runTest - twriter.addResult(host, scenario_set, src_test_pack, notifyNotPass(new PhptTestResult(host, EPhptTestStatus.CRASH, test_case, null, null, null, null, ini, env, null, stdin_post, null, null, null, null, web==null?null:web.getSAPIOutput(), web==null?null:web.getSAPIConfig()))); + twriter.addResult(host, scenario_set, src_test_pack, notifyNotPass(new PhptTestResult(host, EPhptTestStatus.CRASH, prep.test_case, null, null, null, null, ini, env, null, stdin_post, null, null, null, null, web==null?null:web.getSAPIOutput(), web==null?null:web.getSAPIConfig()))); } /** executes SKIPIF, TEST or CLEAN over http. @@ -144,7 +145,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { return null; } - cm.restartingAndRetryingTest(test_case); + cm.restartingAndRetryingTest(prep.test_case); // get #do_http_execute to make a new server // this will make a new WebServerInstance that will only be used to run this 1 test @@ -174,7 +175,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { sb.append("PFTT: created new web server only for running this test which did not respond after\n"); sb.append("PFTT: another One Minute timeout. This test case breaks the web server!\n"); sb.append("PFTT: was trying to run ("+section+" section of): "); - sb.append(test_case.getName()); + sb.append(prep.test_case.getName()); sb.append("\n"); sb.append("PFTT: these two lists refer only to second web server (created for specifically for only this test)\n"); web.getActiveTestListString(sb); @@ -208,7 +209,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { path = "/s"+path; // TODO for -phpt_not_in_place else if (!path.startsWith("/")) path = "/" + path; - if (test_case.getName().contains("phar")) { + if (prep.test_case.getName().contains("phar")) { if (!path.startsWith("/ext/phar/")) {// TODO tests/") && !path.startsWith("/ext/phar//tests/") && !path.startsWith("/ext/phar/tests//") && !path.startsWith("/ext/phar//tests//")) { if (!path.startsWith("/tests/")) path = "/tests/" + path; @@ -228,7 +229,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { try { if (web!=null) { synchronized(web) { - WebServerInstance _web = smgr.getWebServerInstance(cm, host, scenario_set.getScenarioSet(), build, ini, env, active_test_pack.getStorageDirectory(), web, false, test_case); + WebServerInstance _web = smgr.getWebServerInstance(cm, host, scenario_set.getScenarioSet(), build, ini, env, active_test_pack.getStorageDirectory(), web, false, prep); if (_web!=this.web) { this.web.close(cm); this.web = _web; @@ -240,7 +241,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { // test will fail (because this(`PFTT: server...`) is the actual output which won't match the expected output) // // return server's crash output and an additional message about this test - return web.getSAPIOutput() + "PFTT: server crashed already (server was created to replace a crashed web server. server was created to run this 1 test and didn't run any other tests before this one), didn't bother trying to execute test: "+test_case.getName(); + return web.getSAPIOutput() + "PFTT: server crashed already (server was created to replace a crashed web server. server was created to run this 1 test and didn't run any other tests before this one), didn't bother trying to execute test: "+prep.test_case.getName(); } } } // end sync @@ -248,7 +249,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { if (web==null) { // test should be a FAIL or CRASH // its certainly the fault of a test (not PFTT) if not this test - this.web = smgr.getWebServerInstance(cm, host, scenario_set.getScenarioSet(), build, ini, env, active_test_pack.getStorageDirectory(), web, false, test_case); + this.web = smgr.getWebServerInstance(cm, host, scenario_set.getScenarioSet(), build, ini, env, active_test_pack.getStorageDirectory(), web, false, prep); if (web==null||web.isCrashedOrDebuggedAndClosed()) { markTestAsCrash(); @@ -258,7 +259,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { } // CRITICAL: keep track of test cases running on web server - web.notifyTestPreRequest(test_case); + web.notifyTestPreRequest(prep.test_case); if (stdin_post==null || section != EPhptSection.TEST) return do_http_get(path); @@ -268,7 +269,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { } finally { // CRITICAL: keep track of test cases running on web server if (web!=null) { - web.notifyTestPostResponse(test_case); + web.notifyTestPostResponse(prep.test_case); if (web.isCrashedOrDebuggedAndClosed()) markTestAsCrash(); @@ -412,8 +413,11 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { break; default: } - - return IOUtil.toString(response.getEntity().getContent(), IOUtil.HALF_MEGABYTE); + if (cm.isIgnoreOutput()) { + return ""; + } else { + return IOUtil.toString(response.getEntity().getContent(), IOUtil.HALF_MEGABYTE); + } } finally { try { if (test_socket!=null) @@ -522,8 +526,11 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { break; default: } - - return IOUtil.toString(response.getEntity().getContent(), IOUtil.HALF_MEGABYTE); + if (cm.isIgnoreOutput()) { + return ""; + } else { + return IOUtil.toString(response.getEntity().getContent(), IOUtil.HALF_MEGABYTE); + } } finally { try { if (test_socket!=null) @@ -551,21 +558,21 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { @Override protected String executeSkipIf() throws Exception { - return http_execute(skipif_file, EPhptSection.SKIPIF); + return http_execute(prep.skipif_file, EPhptSection.SKIPIF); } @SuppressWarnings("deprecation") @Override protected String executeTest() throws Exception { - String request_uri = this.test_file; + String request_uri = prep.test_file; if (env!=null&&env.containsKey("REQUEST_URI")) { // ex: ext/phar/tests/frontcontroller17.phpt request_uri = AHost.dirname(request_uri)+"/"+env.get("REQUEST_URI"); } - if (test_case.containsSection(EPhptSection.GET)) { - String query_string = test_case.getTrim(EPhptSection.GET); + if (prep.test_case.containsSection(EPhptSection.GET)) { + String query_string = prep.test_case.getTrim(EPhptSection.GET); // query_string needs to be added to the GET path if (StringUtil.isNotEmpty(query_string)) { // a good, complex example for this is ext/filter/tests/004.skip.php @@ -588,7 +595,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { query_string_sb.append(URLEncoder.encode(names_and_values[i+1])); } - request_uri = test_file + "?" + query_string_sb; + request_uri = prep.test_file + "?" + query_string_sb; } } // end if containsSection(GET) @@ -597,7 +604,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { @Override protected void executeClean() throws Exception { - http_execute(test_clean, EPhptSection.CLEAN); + http_execute(prep.test_clean, EPhptSection.CLEAN); } @Override diff --git a/src/com/mostc/pftt/runner/PhptTestPreparer.java b/src/com/mostc/pftt/runner/PhptTestPreparer.java new file mode 100644 index 0000000..a66499e --- /dev/null +++ b/src/com/mostc/pftt/runner/PhptTestPreparer.java @@ -0,0 +1,93 @@ +package com.mostc.pftt.runner; + +import java.io.IOException; + +import com.mostc.pftt.host.AHost; +import com.mostc.pftt.model.TestCase; +import com.mostc.pftt.model.app.PhpUnitTemplate; +import com.mostc.pftt.model.core.EPhptSection; +import com.mostc.pftt.model.core.PhptActiveTestPack; +import com.mostc.pftt.model.core.PhptSourceTestPack; +import com.mostc.pftt.model.core.PhptTestCase; + +public class PhptTestPreparer { + protected final boolean xdebug; + + public PhptTestPreparer(boolean xdebug) { + this.xdebug = xdebug; + } + + public PreparedPhptTestCase prepare(PhptTestCase test_case, AHost host, PhptActiveTestPack active_test_pack) throws IllegalStateException, IOException { + PreparedPhptTestCase prep = new PreparedPhptTestCase(test_case); + + prep.test_dir = host.joinIntoOnePath(active_test_pack.getStorageDirectory(), AHost.dirname(test_case.getName())); + + // CRITICAL + // TODO must be done for -auto - should be more efficient + host.mkdirs(prep.test_dir); + + // some intl tests have + in their name... sending this to the builtin web server breaks it (HTTP 404) + prep.base_file_name = AHost.basename(test_case.getBaseName()).replace("+", ""); + + // + if (test_case.containsSection(EPhptSection.SKIPIF)) { + prep.skipif_file = host.joinIntoOnePath(prep.test_dir, prep.base_file_name + ".skip.php"); + + host.saveTextFile(prep.skipif_file, test_case.get(EPhptSection.SKIPIF)); + } else { + // clearly flag that skipif isn't to be executed + prep.skipif_file = null; + } + // @see AbstractSAPIScenario#willSkip - skips certain tests before even getting here to #prepare + // + + prep.test_file = host.joinIntoOnePath(prep.test_dir, prep.base_file_name + ".php"); + + if (test_case.containsSection(EPhptSection.CLEAN)) { + prep.test_clean = host.joinIntoOnePath(prep.test_dir, prep.base_file_name + ".clean.php"); + + host.saveTextFile(prep.test_clean, test_case.get(EPhptSection.CLEAN)); + } // else test_clean = null; + + return prep; + } + + protected String preparePhptTestCode(String php_code) { + if (xdebug) + return PhpUnitTemplate.renderXDebugPhptTemplate(php_code); + else + return php_code; + } + + public class PreparedPhptTestCase extends TestCase { + public final PhptTestCase test_case; + public String base_file_name, skipif_file, test_dir, test_file, test_clean; + + public PreparedPhptTestCase(PhptTestCase test_case) { + this.test_case = test_case; + } + + @Override + public String getName() { + return test_case.getName(); + } + + public void prepareTest(PhptSourceTestPack src_test_pack, AHost host) throws Exception { + if (test_case.containsSection(EPhptSection.FILE_EXTERNAL)) { + // open external file and copy to test_file (binary, no char conversion - which could break it - often this is a PHAR file - which will be broken if charset coversion is done) + + // @see run-test.php:1281 + String src_file = host.joinIntoOnePath( + src_test_pack.getSourceDirectory(), + AHost.dirname(test_case.getName()), + test_case.getTrim(EPhptSection.FILE_EXTERNAL).replaceAll("\\.\\.", "") + ); + host.copy(src_file, test_file); + + } else { + host.saveTextFile(test_file, preparePhptTestCode(test_case.get(EPhptSection.FILE)), test_case.getCommonCharsetEncoder()); + } + } + } + +} diff --git a/src/com/mostc/pftt/ui/PhptDebuggerFrame.java b/src/com/mostc/pftt/ui/PhptDebuggerFrame.java index 47fcee3..fbd8859 100644 --- a/src/com/mostc/pftt/ui/PhptDebuggerFrame.java +++ b/src/com/mostc/pftt/ui/PhptDebuggerFrame.java @@ -66,7 +66,7 @@ public class PhptDebuggerFrame extends JPanel { } // - menubar.add("right", report_button = new JButton("FBC Report")); + menubar.add("right", report_button = new JButton("Report")); menubar.add("right", exit_button = new JButton("Exit")); exit_button.addActionListener(new ActionListener() { diff --git a/src/com/mostc/pftt/util/HostEnvUtil.java b/src/com/mostc/pftt/util/HostEnvUtil.java index 13836ca..6fc8265 100644 --- a/src/com/mostc/pftt/util/HostEnvUtil.java +++ b/src/com/mostc/pftt/util/HostEnvUtil.java @@ -149,11 +149,11 @@ public final class HostEnvUtil { default: // PHP 5.5+ and PHP_Master installVCRT9(cm, host); // just in case - installVCRT(cm, host, "VC10", "msvcr100.dll", "vc10_redist_x86.exe"); - installVCRT(cm, host, "VC11", "msvcr110.dll", "vc11_redist_x86.exe"); + installVCRT(cm, host, "VC10 x86", "msvcr100.dll", "vc10_redist_x86.exe"); + installVCRT(cm, host, "VC11 x86", "msvcr110.dll", "vc11_redist_x86.exe"); if (build.isX64()) { - installVCRT(cm, host, "VC10", "msvcr100.dll", "vc10_redist_x64.exe"); - installVCRT(cm, host, "VC11", "msvcr110.dll", "vc11_redist_x64.exe"); + installVCRT(cm, host, "VC10 x64", "msvcr100.dll", "vc10_redist_x64.exe"); + installVCRT(cm, host, "VC11 x64", "msvcr110.dll", "vc11_redist_x64.exe"); } break; } // end switch diff --git a/src/com/mostc/pftt/util/TimerUtil.java b/src/com/mostc/pftt/util/TimerUtil.java index 1c92452..c5d4c5c 100644 --- a/src/com/mostc/pftt/util/TimerUtil.java +++ b/src/com/mostc/pftt/util/TimerUtil.java @@ -12,7 +12,7 @@ public final class TimerUtil { private static LinkedList<ThreadRunnableProxy> trp_pool = new LinkedList<ThreadRunnableProxy>(); static { - final int pool_size = Math.max(128, LocalHost.getInstance().getCPUCount() * 16); + final int pool_size = Math.min(16, LocalHost.getInstance().getCPUCount() * 2); for ( int i = 0 ; i < pool_size ; i++ ) { ThreadRunnableProxy trp = new ThreadRunnableProxy(); new Thread(trp).start(); @@ -82,6 +82,11 @@ public final class TimerUtil { * @return */ public static Thread runThread(Runnable r) { + try { + Thread t = new Thread(r); + t.start(); + return t; + } catch ( Throwable t ) {} ThreadRunnableProxy trp = null; try { synchronized(trp_pool) { @@ -90,7 +95,10 @@ public final class TimerUtil { } } catch ( NoSuchElementException e ) {} if (trp==null) { - return new Thread(r); + // try again + Thread t = new Thread(r); + t.start(); + return t; } else { trp.setRunnable(r); return trp.thread; @@ -148,13 +156,26 @@ public final class TimerUtil { } protected void block(int seconds) { + int r = 0; + int m = ( seconds * 1000 ); + while (ran && m > r) { + try { + Thread.sleep(100); + } catch ( InterruptedException ex ) { + break; + } + r += 100; + } + m = m - r; + if (m>0) { synchronized(lock) { if (this.ran==false) { try { - lock.wait(seconds*1000); + lock.wait(m); } catch ( Exception ex ) {} } } + } } protected void unlock(boolean ran) {
« previous php.qa (#68336) next »