Commit:    57572767543b8d116466755f855ec09f611b25df
Author:    Matt Ficken <v-maf...@microsoft.com>         Thu, 12 Sep 2013 
15:19:30 -0700
Parents:   fa95ddb2e16f3cebacdd80e81f273bda7d06d375
Branches:  master

Link:       
http://git.php.net/?p=pftt2.git;a=commitdiff;h=57572767543b8d116466755f855ec09f611b25df

Log:
config files in phpt test-packs


Former-commit-id: 2a0a1072e3a13e660c452b6b69d53a2b744ff8f0

Changed paths:
  M  src/com/mostc/pftt/host/PSCAgentServer.java
  M  src/com/mostc/pftt/host/RemotePhptTestPackRunner.java
  M  src/com/mostc/pftt/main/Config.java
  M  src/com/mostc/pftt/main/PfttMain.java
  M  src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
  M  src/com/mostc/pftt/runner/AbstractPhpUnitTestCaseRunner.java
  M  src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
  M  src/com/mostc/pftt/runner/AbstractTestPackRunner.java

diff --git a/src/com/mostc/pftt/host/PSCAgentServer.java 
b/src/com/mostc/pftt/host/PSCAgentServer.java
index 4e39122..38a432a 100644
--- a/src/com/mostc/pftt/host/PSCAgentServer.java
+++ b/src/com/mostc/pftt/host/PSCAgentServer.java
@@ -180,6 +180,11 @@ public abstract class PSCAgentServer implements 
ConsoleManager, ITestResultRecei
        }
        
        @Override
+       public long getMaxRunTimeMillis() {
+               return 0;
+       }
+       
+       @Override
        public void notifyStart(AHost this_host, ScenarioSetSetup 
this_scenario_set, PhptSourceTestPack src_test_pack, PhptTestCase test_case) {
                // TODO Auto-generated method stub
        }
diff --git a/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java 
b/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java
index 4796523..f5d699e 100644
--- a/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java
+++ b/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java
@@ -8,6 +8,7 @@ import java.io.IOException;
 import java.io.PrintStream;
 
 import com.github.mattficken.io.StringUtil;
+import com.mostc.pftt.main.Config;
 import com.mostc.pftt.model.core.PhpBuild;
 import com.mostc.pftt.model.core.PhptActiveTestPack;
 import com.mostc.pftt.model.core.PhptSourceTestPack;
@@ -53,13 +54,14 @@ public class RemotePhptTestPackRunner extends 
AbstractRemoteTestPackRunner<PhptA
        public static void main(String[] args) throws Exception {
                LocalHost host = new LocalHost();
                
-               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);
+               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);
+               Config config = Config.loadConfigFromFiles(cm, "default");
                
                PhpBuild build = new 
PhpBuild("C:\\php-sdk\\php-5.5-ts-windows-vc11-x64-re3aeb6c");
                build.open(cm, host);
                
                PhptSourceTestPack test_pack = new 
PhptSourceTestPack("C:\\php-sdk\\php-test-pack-5.5-ts-windows-vc11-x86-r0704e4b");
-               test_pack.open(cm, host);
+               test_pack.open(cm, config, host);
                
                PhpResultPackWriter tmgr = new PhpResultPackWriter(host, cm, 
new File(host.getPhpSdkDir()), build, test_pack, null);
                
diff --git a/src/com/mostc/pftt/main/Config.java 
b/src/com/mostc/pftt/main/Config.java
index 1cd19f6..ddb3814 100644
--- a/src/com/mostc/pftt/main/Config.java
+++ b/src/com/mostc/pftt/main/Config.java
@@ -38,9 +38,11 @@ import com.mostc.pftt.results.ITestResultReceiver;
 import com.mostc.pftt.results.PhpResultPackWriter;
 import com.mostc.pftt.results.PhpUnitTestResult;
 import com.mostc.pftt.results.PhptTestResult;
+import com.mostc.pftt.runner.AbstractLocalTestPackRunner.TestPackThread;
 import com.mostc.pftt.scenario.EScenarioSetPermutationLayer;
 import com.mostc.pftt.scenario.Scenario;
 import com.mostc.pftt.scenario.ScenarioSet;
+import com.mostc.pftt.scenario.ScenarioSetSetup;
 import com.mostc.pftt.scenario.app.JoomlaScenario;
 
 import groovy.lang.GroovyClassLoader;
@@ -133,6 +135,8 @@ public final class Config implements IENVINIFilter {
        public static final String PROCESS_PHPUNIT_TEST_PACK_METHOD_NAME = 
"processPhpUnitTestPack";
        public static final String PROCESS_PHPT_TEST_RESULT_METHOD_NAME = 
"processPhptTestResult";
        public static final String PROCESS_PHP_UNIT_TEST_RESULT_METHOD_NAME = 
"processPhpUnitTestResult";
+       public static final String PREPARE_TEST_PACK_PER_THREAD_METHOD_NAME = 
"prepareTestPackPerThread";
+       public static final String PREPARE_TEST_PACK_METHOD_NAME = 
"prepareTestPack";
        //
        protected final LinkedList<AHost> hosts;
        protected final LinkedList<Scenario> scenarios;
@@ -170,6 +174,26 @@ public final class Config implements IENVINIFilter {
                //      ex: internal_examples - copy to internal
        }
        
+       public void prepareTestPack(ConsoleManager cm, AHost host, 
ScenarioSetSetup setup, PhpBuild build, PhptSourceTestPack test_pack) {
+               ArrayList<MethodImpl> methods = 
by_method_name.get(PREPARE_TEST_PACK_METHOD_NAME);
+               if (methods==null||methods.isEmpty())
+                       return;
+               cm.println(EPrintType.IN_PROGRESS, getClass(), "preparing test 
pack from configuration... "+setup+" "+test_pack);
+               for ( MethodImpl m : methods ) {
+                       invokeMethod(null, null, m.go, 
PREPARE_TEST_PACK_METHOD_NAME, new Object[]{cm, host, setup, build, test_pack}, 
null);
+               }
+       }
+       
+       public void prepareTestPackPerThread(ConsoleManager cm, AHost host, 
TestPackThread test_pack_thread, ScenarioSetSetup setup, PhpBuild build, 
PhptSourceTestPack test_pack) {
+               ArrayList<MethodImpl> methods = 
by_method_name.get(PREPARE_TEST_PACK_PER_THREAD_METHOD_NAME);
+               if (methods==null||methods.isEmpty())
+                       return;
+               cm.println(EPrintType.IN_PROGRESS, getClass(), "preparing test 
pack per thread from configuration... "+test_pack_thread+" "+setup+" 
"+test_pack);
+               for ( MethodImpl m : methods ) {
+                       invokeMethod(null, null, m.go, 
PREPARE_TEST_PACK_PER_THREAD_METHOD_NAME, new Object[]{cm, host, 
test_pack_thread, setup, build, test_pack}, null);
+               }
+       }
+       
        public void processPHPTTestPack(PhptSourceTestPack test_pack, 
PhpResultPackWriter twriter, PhpBuild build) {
                ArrayList<MethodImpl> methods = 
by_method_name.get(PROCESS_PHPT_TEST_PACK_METHOD_NAME);
                if (methods==null)
@@ -279,7 +303,7 @@ public final class Config implements IENVINIFilter {
                while (it.hasNext()) {
                        nv = it.next().getName().toLowerCase();
                        for ( String str : not_scenarios ) {
-                               if (nv.contains(str.toLowerCase())) {
+                               if (nv.equalsIgnoreCase(str)) {
                                        // match, remove it
                                        it.remove();
                                        break;
@@ -321,10 +345,16 @@ public final class Config implements IENVINIFilter {
                
                this_scenario_sets = not(getNotScenarios(cm), 
permuteScenarioSets(cm, layer));
                
+               HashMap<String,ScenarioSet> map = new 
HashMap<String,ScenarioSet>();
+               for ( ScenarioSet s : this_scenario_sets )
+                       map.put(s.toString(), s);
+               ArrayList<ScenarioSet> a = new 
ArrayList<ScenarioSet>(map.size());
+               a.addAll(map.values());
+               
                // cache for next time (this config won't change, so its ok to 
cache)
-               permuted_scenario_sets.put(layer, this_scenario_sets);
+               permuted_scenario_sets.put(layer, a);
                
-               return this_scenario_sets;
+               return a;
        }
                
        public List<ScenarioSet> getScenarioSets(EScenarioSetPermutationLayer 
layer) {
@@ -568,6 +598,12 @@ public final class Config implements IENVINIFilter {
         * @throws IOException
         */
        public static Config loadConfigFromFiles(ConsoleManager cm, File... 
files) throws CompilationFailedException, InstantiationException, 
IllegalAccessException, IOException {
+               Config config = new Config();
+               config.doLoadConfigFromFiles(cm, files);
+               return config;
+       }
+       
+       protected void doLoadConfigFromFiles(ConsoleManager cm, File... files) 
throws InstantiationException, IllegalAccessException, 
CompilationFailedException, FileNotFoundException, IOException {
                GroovyClassLoader loader = new 
GroovyClassLoader(Config.class.getClassLoader());
                
                /*ImportCustomizer ic = new ImportCustomizer();
@@ -577,8 +613,6 @@ public final class Config implements IENVINIFilter {
                cc.addCompilationCustomizers(ic);
                */
                
-               Config config = new Config();
-               
                // don't load default scenarios. configuration file(s) 
completely replace them (not merged)
                LinkedList<Scenario> scenarios = new LinkedList<Scenario>();
                
@@ -591,11 +625,11 @@ public final class Config implements IENVINIFilter {
                        go = (GroovyObject) clazz.newInstance();
                        
                        // call methods in file to get configuration (hosts, 
etc...)
-                       loadObjectToConfig(cm, config, go, scenarios, 
file.getAbsolutePath());
+                       loadObjectToConfig(cm, this, go, scenarios, 
file.getAbsolutePath());
                }
                
-               return loadConfigCommon(cm, scenarios, config);
-       } // end public static Config loadConfigFromFiles
+               loadConfigCommon(cm, scenarios, this);
+       } 
        
        protected static String importString(String filename, String code) {
                // a hack to import common classes for configuration files (XXX 
do this a better way)
@@ -744,6 +778,8 @@ public final class Config implements IENVINIFilter {
                registerMethod(cm, config, go, 
PROCESS_PHPUNIT_TEST_PACK_METHOD_NAME, file_name);
                registerMethod(cm, config, go, 
PROCESS_PHPT_TEST_RESULT_METHOD_NAME, file_name);
                registerMethod(cm, config, go, 
PROCESS_PHP_UNIT_TEST_RESULT_METHOD_NAME, file_name);
+               registerMethod(cm, config, go, 
PREPARE_TEST_PACK_PER_THREAD_METHOD_NAME, file_name);
+               registerMethod(cm, config, go, PREPARE_TEST_PACK_METHOD_NAME, 
file_name);
        } // end protected static void loadObjectToConfig
        
        private static void checkImplemented(ConsoleManager cm, Scenario o) {
@@ -808,5 +844,9 @@ public final class Config implements IENVINIFilter {
                }
                return false;
        }
+
+       public void addConfigFile(ConsoleManager cm, File file) throws 
CompilationFailedException, FileNotFoundException, InstantiationException, 
IllegalAccessException, IOException {
+               doLoadConfigFromFiles(cm, file);
+       }
        
 } // end public final class ConfigUtil
diff --git a/src/com/mostc/pftt/main/PfttMain.java 
b/src/com/mostc/pftt/main/PfttMain.java
index 64ea5c0..f99357d 100644
--- a/src/com/mostc/pftt/main/PfttMain.java
+++ b/src/com/mostc/pftt/main/PfttMain.java
@@ -85,11 +85,7 @@ import 
com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair;
 //     -test the php build
 //     -test the web server build
 //
-/* -rename ostcpftt@ name to `OSTC PFTT Unattended Test System`
-       -name still clear who owns it
-               -plus database field would tell
-       -only `php` is missing from new name, but any 2nd/3rd party who saw the 
name wouldn't care about that
-               -just care about owner*/
+// 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
@@ -113,7 +109,6 @@ import 
com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair;
 //           -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 task/code_coverage store in result-pack
 // TODO get code coverage data of Symfony demo app (UI?)
 //      -get list of builtin functions
 //      -find phpunit tests that use same builtin functions
@@ -156,14 +151,6 @@ import 
com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair;
 //            aa -c dev/symfony-2.3
 //                  dev/ indicates conf/dev for config file
 // TODO include Selenium WebDriver in javadoc
-// TODO WincacheUScenario 
-//     -and APCUScenario
-//       which both extend UserCache (not a code cache) - can use with and 
without opcache or apc or wincache
-//
-//      >  mediawiki can use WinCacheU for its user/object cache
-//           -makes a major performance difference
-//           -make it a point to unit test that!
-//
 // TODO progress indicator for `release_get`
 // TODO soap xmlrpc ftp snmp ldap postgresql curl ftp - including symfony, 
joomla, phpt
 //       pdo_odbc odbc (to mssql??)
@@ -594,6 +581,31 @@ public class PfttMain {
                                cm.println(EPrintType.CLUE, PfttMain.class, 
"Writing Result-Pack: "+tmgr.getResultPackPath());
                                
                                for (ScenarioSet scenario_set : 
getScenarioSets(config, 
EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION)) {
+                                       if (!cm.isSkipSmokeTests()) {
+                                               {
+                                                       // TODO test running 
PHPTs on a build that is missing a DLL that is
+                                                       
RequiredExtensionsSmokeTest test = new RequiredExtensionsSmokeTest();
+                                                       //
+                                                       // on Windows, missing 
.DLLs from a php build will cause a blocking winpop dialog msg to appear
+                                                       // in such a case, the 
test will timeout after 1 minute and then fail (stopping at that point is 
important)
+                                                       // @see 
PhpBuild#getExtensionList
+                                                       if (test.test(build, 
cm, host, SAPIScenario.getSAPIScenario(scenario_set).getSAPIType(), 
tmgr)==ESmokeTestStatus.FAIL) {
+                                                               // if this test 
fails, RequiredFeaturesSmokeTest will fail for sure
+                                                               
cm.println(EPrintType.CANT_CONTINUE, "Main", "Failed smoke test: 
"+test.getName());
+                                                               
+                                                               break;
+                                                       }
+                                               }
+                                               {
+                                                       
RequiredFeaturesSmokeTest test = new RequiredFeaturesSmokeTest();
+                                                       if (test.test(build, 
cm, host, tmgr)==ESmokeTestStatus.FAIL) {
+                                                               
cm.println(EPrintType.CANT_CONTINUE, "Main", "Failed smoke test: 
"+test.getName());
+                                                               
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       
                                        List<AHost> hosts = config.getHosts();
                                        AHost host = 
hosts.isEmpty()?this.host:hosts.get(0);
                                        LocalPhpUnitTestPackRunner r = new 
LocalPhpUnitTestPackRunner(cm, tmgr, scenario_set, build, host, host);
@@ -1143,12 +1155,12 @@ public class PfttMain {
                return (PhpBuild[]) builds.toArray(new PhpBuild[builds.size()]);
        } // end protected static PhpBuild[] newBuilds
        
-       protected static PhptSourceTestPack newTestPack(ConsoleManager cm, 
AHost host, String path) {
+       protected static PhptSourceTestPack newTestPack(ConsoleManager cm, 
Config config, AHost host, String path) {
                PhptSourceTestPack test_pack = new PhptSourceTestPack(path);
-               if (test_pack.open(cm, host))
+               if (test_pack.open(cm, config, host))
                        return test_pack;
                test_pack = new PhptSourceTestPack(host.getPhpSdkDir() + "/" + 
path);
-               if (test_pack.open(cm, host))
+               if (test_pack.open(cm, config, host))
                        return test_pack;
                else
                        return null; // test-pack not found/readable error
@@ -1296,7 +1308,7 @@ public class PfttMain {
                                System.exit(-255);
                        System.out.println("PFTT: Config: loaded 
"+config_files);
                } else {
-                       File default_config_file = new File(new 
LocalHost().getPfttDir()+"/conf/default.groovy");
+                       File default_config_file = new File(new 
LocalHost().getPfttConfDir()+"/default.groovy");
                        config = Config.loadConfigFromFiles(cm, 
default_config_file);
                        System.out.println("PFTT: Config: no config files 
loaded... using default only ("+default_config_file+")");
                }
@@ -1582,7 +1594,7 @@ public class PfttMain {
                                        
                                        PhpBuild[] builds = newBuilds(cm, 
p.host, args[args_i+1]);
                                        
-                                       PhptSourceTestPack test_pack = 
newTestPack(cm, p.host, args[args_i+2]);
+                                       PhptSourceTestPack test_pack = 
newTestPack(cm, config, p.host, args[args_i+2]);
                                        if (test_pack==null) {
                                                System.err.println("IO Error: 
can not open php test pack: "+test_pack);
                                                System.exit(-255);
@@ -1613,7 +1625,7 @@ public class PfttMain {
                                        
                                        PhpBuild[] builds = newBuilds(cm, 
p.host, args[args_i+1]);
                                        
-                                       PhptSourceTestPack test_pack = 
newTestPack(cm, p.host, args[args_i+2]);
+                                       PhptSourceTestPack test_pack = 
newTestPack(cm, config, p.host, args[args_i+2]);
                                        if (test_pack == null) {
                                                System.err.println("IO Error: 
can not open php test pack: "+test_pack);
                                                System.exit(-255);
@@ -1644,7 +1656,7 @@ public class PfttMain {
                                        
                                        PhpBuild[] builds = newBuilds(cm, 
p.host, args[args_i+1]);
                                        
-                                       PhptSourceTestPack test_pack = 
newTestPack(cm, p.host, args[args_i+2]);
+                                       PhptSourceTestPack test_pack = 
newTestPack(cm, config, p.host, args[args_i+2]);
                                        if (test_pack == null) {
                                                System.err.println("IO Error: 
can not open php test pack: "+test_pack);
                                                System.exit(-255);
@@ -1667,7 +1679,7 @@ public class PfttMain {
                                        
                                        PhpBuild[] builds = newBuilds(cm, 
p.host, args[args_i+1]);
                                        
-                                       PhptSourceTestPack test_pack = 
newTestPack(cm, p.host, args[args_i+2]);
+                                       PhptSourceTestPack test_pack = 
newTestPack(cm, config, p.host, args[args_i+2]);
                                        if (test_pack==null) {
                                                System.err.println("IO Error: 
can not open php test pack: "+test_pack);
                                                System.exit(-255);
@@ -1759,7 +1771,7 @@ public class PfttMain {
                                } else if 
(command.equals("setup")||command.equals("set")||command.equals("setu")) {
                                        if (!(args.length > args_i+1)) {
                                                System.err.println("User Error: 
must include build");
-                                               System.out.println("usage: pftt 
[-c config_files ]setup <path to PHP build>");
+                                               System.out.println("usage: pftt 
[-c config_files ]setup <path to PHP build> [optional: PHPT test-pack to 
setup]");
                                                System.exit(-255);
                                                return;
                                        }
@@ -1770,13 +1782,21 @@ public class PfttMain {
                                        
                                        // setup all scenarios
                                        PhpIni ini;
+                                       ScenarioSetSetup setup = null;
                                        for ( ScenarioSet set : 
getScenarioSets(config, EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST) 
) {
                                                
                                                ini = 
RequiredExtensionsSmokeTest.createDefaultIniCopy(cm, p.host, build);
                                                INIScenario.setupScenarios(cm, 
p.host, set, build, ini);
                                                
-                                               
ScenarioSetSetup.setupScenarioSet(cm, p.host, build, set, 
EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST);
+                                               setup = 
ScenarioSetSetup.setupScenarioSet(cm, p.host, build, set, 
EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST);
+                                               
+                                       }
+                                       if (setup != null && args.length > 
args_i+2) {
+                                               // this will load the 
test-pack's configuration script (if present)
+                                               PhptSourceTestPack test_pack = 
PfttMain.newTestPack(cm, config, p.host, args[args_i+2]);
                                                
+                                               // use last ScenarioSetSetup
+                                               config.prepareTestPack(cm, 
p.host, setup, build, test_pack);
                                        }
                                } else if 
(command.equals("release_get")||command.equals("rgn")||command.equals("rgnew")||command.equals("rgnewest")||command.equals("rgp")||command.equals("rgprev")||command.equals("rgprevious")||command.equals("rg")||command.equals("rget"))
 {
                                        EBuildBranch branch = null;
diff --git a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java 
b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
index d0a374a..bbe4a3d 100644
--- a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
@@ -8,6 +8,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -38,8 +39,10 @@ import com.mostc.pftt.results.PhpResultPackWriter;
 import com.mostc.pftt.runner.LocalPhpUnitTestPackRunner.PhpUnitThread;
 import com.mostc.pftt.scenario.EScenarioSetPermutationLayer;
 import com.mostc.pftt.scenario.FileSystemScenario;
+import com.mostc.pftt.scenario.IScenarioSetup;
 import com.mostc.pftt.scenario.RemoteFileSystemScenario;
 import com.mostc.pftt.scenario.SAPIScenario;
+import com.mostc.pftt.scenario.Scenario;
 import com.mostc.pftt.scenario.WebServerScenario;
 import com.mostc.pftt.scenario.ScenarioSet;
 import com.mostc.pftt.scenario.FileSystemScenario.ITestPackStorageDir;
@@ -54,10 +57,11 @@ import com.mostc.pftt.util.ErrorUtil;
  */
 
 public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S 
extends SourceTestPack<A,T>, T extends TestCase> extends 
AbstractTestPackRunner<S, T> {
-       protected static final int MAX_THREAD_COUNT = 128;
+       protected static final int MAX_USER_SPECIFIED_THREAD_COUNT = 192;
        protected S src_test_pack;
        protected final ConsoleManager cm;
        protected final ITestResultReceiver twriter;
+       protected long start_time_millis;
        protected int thread_safe_test_count;
        protected A active_test_pack;
        protected AtomicReference<ETestPackRunnerState> runner_state;
@@ -176,7 +180,7 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                        return null;
                }
                //
-               cm.println(EPrintType.CLUE, getClass(), "Scenario Set: 
"+scenario_set.getName());
+               cm.println(EPrintType.CLUE, getClass(), "Scenario Set: 
"+scenario_set_setup.getNameWithVersionInfo());
                setupStorageAndTestPack(storage_dir, test_cases);
                
                return storage_dir;
@@ -259,11 +263,11 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                        
                        cm.println(EPrintType.IN_PROGRESS, getClass(), "ready 
to go!    scenario_set="+scenario_set+" runner_host="+runner_host+" 
storage_dir="+storage_dir.getClass()+" 
local_path="+storage_dir.getLocalPath(runner_host)+" 
remote_path="+storage_dir.getRemotePath(runner_host));
                        
-                       long start_time = System.currentTimeMillis();
+                       start_time_millis = System.currentTimeMillis();
                        
                        executeTestCases(true); // TODO false);
                        
-                       long run_time = Math.abs(System.currentTimeMillis() - 
start_time);
+                       final long run_time = 
Math.abs(System.currentTimeMillis() - start_time_millis);
                        
                        cm.println(EPrintType.CLUE, getClass(), "Finished test 
run in "+(run_time/1000)+" seconds");
                        
@@ -281,6 +285,7 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                        //
                        
                        showTally();
+                       cm.println(EPrintType.CLUE, getClass(), "Scenario Set: 
"+scenario_set);
                } finally {
                        // be sure all running WebServerInstances, or other 
SAPIInstances are
                        // closed by end of testing (otherwise `php.exe -S` 
will keep on running)
@@ -481,46 +486,63 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                
        }
        
-       protected int decideThreadCount() {
-               // decide number of threads
-               // 1. ask SAPI Scenario
-               // 2. limit to number of thread safe tests + number of NTS 
extensions (extensions with NTS tests)
-               //        -exceed this number and there will be threads that 
won't have any tests to run
-               // 3. if debugging
-               // 4. ask user (-thread_count console option)
-               // 5. limit to MAX_THREAD_COUNT
-               
-               int thread_count = 
sapi_scenario.getTestThreadCount(runner_host);
-               if ((cm.isThreadSafety() || cm.getRunTestTimesAll()<2) && 
thread_count > thread_safe_test_count + non_thread_safe_exts.size()) {
+       protected int init_thread_count, max_thread_count;
+       protected void decideThreadCount() {
+               init_thread_count = runner_host.getCPUCount();
+               if ((cm.isThreadSafety() || cm.getRunTestTimesAll()<2) && 
init_thread_count > thread_safe_groups.size() + non_thread_safe_exts.size()) {
                        // don't start more threads than there will be work for
                        // however, if -no_nts AND -run_test_times_all console 
option used, user wants tests run
                        // as much as possible, so don't do this check (in that 
case, do normal number of threads, not this)
                        //
-                       thread_count = thread_safe_test_count + 
non_thread_safe_exts.size(); 
+                       init_thread_count = thread_safe_test_count + 
non_thread_safe_exts.size(); 
+               }
+               max_thread_count = init_thread_count * 2;
+               // ask scenarios for approval (primarily SAPIScenario and 
WinCacheUScenario)
+               {
+                       // ask sapi scenario first
+                       init_thread_count = 
sapi_scenario.getApprovedInitialThreadPoolSize(runner_host, init_thread_count);
+                       max_thread_count = 
sapi_scenario.getApprovedMaximumThreadPoolSize(runner_host, max_thread_count);
+                       // ask all other scenarios
+                       for ( Scenario s : scenario_set ) {
+                               if (s==sapi_scenario)
+                                       continue;
+                               int a = 
s.getApprovedInitialThreadPoolSize(runner_host, init_thread_count);
+                               int b = 
s.getApprovedMaximumThreadPoolSize(runner_host, max_thread_count);
+                               if (a<init_thread_count)
+                                       init_thread_count = a;
+                               if (b<max_thread_count)
+                                       max_thread_count = b;
+                       }
                }
                if (cm.isDebugAll()) {
                        // run fewer threads b/c we're running WinDebug
                        // (can run WinDebug w/ same number of threads, but UI 
responsiveness will be really SLoow)
-                       thread_count = Math.max(1, thread_count / 4);
+                       init_thread_count = Math.max(1, init_thread_count / 4);
                }
                if (cm.getThreadCount()>0) {
                        // let user override SAPI and debug thread count checks
-                       thread_count = cm.getThreadCount();
-               }
-               if (thread_count > MAX_THREAD_COUNT) {
-                       // safety check: don't run too many threads
-                       thread_count = MAX_THREAD_COUNT;
-               }
-               return thread_count;
-       } // end protected int decideThreadCount
+                       init_thread_count = cm.getThreadCount();
+               } 
+               
+               checkThreadCountLimit();
+       } // end protected void decideThreadCount
+       
+       protected void checkThreadCountLimit() {
+               if (init_thread_count>max_thread_count)
+                       max_thread_count = init_thread_count;
+               if (init_thread_count>MAX_USER_SPECIFIED_THREAD_COUNT)
+                       init_thread_count = MAX_USER_SPECIFIED_THREAD_COUNT;
+               if (max_thread_count>MAX_USER_SPECIFIED_THREAD_COUNT)
+                       max_thread_count = MAX_USER_SPECIFIED_THREAD_COUNT;
+       }
        
        protected void executeTestCases(boolean parallel) throws 
InterruptedException, IllegalStateException, IOException {
-               int thread_count = decideThreadCount();
-               cm.println(EPrintType.IN_PROGRESS, getClass(), "Starting up 
Test Threads: thread_count="+thread_count+" runner_host="+runner_host+" 
sapi_scenario="+sapi_scenario);
+               decideThreadCount();
+               cm.println(EPrintType.IN_PROGRESS, getClass(), "Starting up 
Test Threads: thread_count="+init_thread_count+" max="+max_thread_count+" 
runner_host="+runner_host+" sapi_scenario="+sapi_scenario);
                        
                test_count.set(0);
                
-               for ( int i=0 ; i < thread_count ; i++ ) { 
+               for ( int i=0 ; i < init_thread_count ; i++ ) { 
                        start_thread(parallel);
                }
                
@@ -544,7 +566,7 @@ 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)
-                                       if 
((test_run_start_time>0&&Math.abs(System.currentTimeMillis()-test_run_start_time)>120000))
 {
+                                       if 
(!thread.shouldRun()||(test_run_start_time>0&&Math.abs(System.currentTimeMillis()-test_run_start_time)>120000))
 {
                                                // thread running too long
                                                if 
(thread.isDebuggerAttached()) {
                                                        not_running = false; // 
keep running
@@ -639,7 +661,7 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                        // (if there aren't enough NTS extensions to fill all 
the threads, some threads will only execute thread-safe tests)
                        //
                        try {
-                               while 
(shouldRun()&&!thread_safe_groups.isEmpty()) {
+                               while 
(shouldRun()&&(!thread_safe_groups.isEmpty()||!non_thread_safe_exts.isEmpty())) 
{//thread_safe_test_count==0)) {
                                        try {
                                                runNonThreadSafe();
                                                
@@ -737,23 +759,28 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                        return this;
                }
                
+               protected long getMaxRunTimeMillis() {
+                       return cm.getMaxRunTimeMillis();
+               }
+               
                protected boolean shouldRun() {
-                       return run_thread.get() && 
runner_state.get()==ETestPackRunnerState.RUNNING;
+                       final long max_run_time_millis = getMaxRunTimeMillis();
+                       return run_thread.get() && 
runner_state.get()==ETestPackRunnerState.RUNNING && 
(max_run_time_millis<1000||Math.abs(System.currentTimeMillis() - 
start_time_millis) < max_run_time_millis);
                }
                
+               protected abstract void prepareExec(TestCaseGroupKey group_key, 
PhpIni ini, Map<String,String> env, IScenarioSetup s);
+               
                protected void exec_jobs(TestCaseGroupKey group_key, 
LinkedBlockingQueue<T> jobs) {
                        this.group_key = group_key;
                        LinkedList<T> completed_tests = new LinkedList<T>();
                        this.jobs = jobs;
                        
+                       
+                       for ( IScenarioSetup s :scenario_set_setup.getSetups() 
) {
+                               prepareExec(group_key, group_key.getPhpIni(), 
group_key.getEnv(), s);
+                       }
+                       
                        while (shouldRun()) {
-                               /*if (test_count.get() > 100 ) 
{//cm.getRunCount() > 0 && test_count.get() > cm.getRunCount() ) {
-                                       // run maximum number of tests, don't 
run any more
-                                       System.exit(0);
-                                       
runner_state.set(ETestPackRunnerState.NOT_RUNNING);
-                                       break;
-                               }*/
-                               
                                //
                                test_case = null;
                                try {
@@ -801,28 +828,6 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                                                                        
thread_wsi = null;
                                                                }
                                                                
-                                                               String name = 
test_case.getName();
-                                                               if 
(name.equals("ext/filter/tests/004.phpt")
-                                                                       || 
name.equals("ext/standard/tests/strings/htmlentities05.phpt")
-                                                                       || 
name.equals("ext/wddx/tests/004.phpt")
-                                                                       || 
name.equals("ext/wddx/tests/005.phpt")
-                                                                       || 
name.equals("ext/standard/tests/strings/htmlentities12.phpt")
-                                                                       || 
name.equals("ext/mbstring/tests/mb_ereg_replace_variation1.phpt")
-                                                                       || 
name.equals("ext/mbstring/tests/mb_ereg_replace_variation1.phpt")
-                                                                       || 
name.equals("ext/phar/tests/phar_dotted_path.phpt")
-                                                                       || 
name.equals("ext/session/tests/027.phpt")
-                                                                       || 
name.equals("tests/basic/0")
-                                                                       || 
name.startsWith("ext/mbstring/tests/mb_output")
-                                                                       || 
name.equals("ext/mbstring/tests/mb_ereg_replace_variation1.phpt")
-                                                                       || 
name.equals("ext/phar/tests/cache_list/frontcontroller13.phpt")
-                                                                       || 
name.equals("ext/phar/tests/frontcontroller29.phpt")
-                                                                       || 
name.equals("zend/tests/multibyte/multibyte_encoding_001.phpt")
-                                                                       || 
name.equals("ext/session/tests/009.phpt")) {
-                                                                       
if(thread_wsi!=null)
-                                                                               
thread_wsi.close(cm);
-                                                                       
thread_wsi = null;
-                                                               }
-                                                               
                                                                if 
(thread_wsi==null ||
                                                                                
                                                                                
( !cm.isNoRestartAll()
@@ -862,21 +867,27 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                                                // finally: create the test 
case runner and run the actual test
                                                runTest(group_key, test_case);
                                                
-                                               
-                                               if 
(Math.abs(System.currentTimeMillis() - test_run_start_time.get()) < 
sapi_scenario.getFastTestTimeSeconds()) {
-                                                       // scale back down
+                                               // 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()) {
+                                                       // scale back down 
(decrease number of threads)
                                                        
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);     
+                                                                       
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
                                                                }
-                                                               it.remove();
                                                        }
                                                }
                                                
@@ -917,8 +928,8 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                protected abstract void runTest(TestCaseGroupKey group_key, T 
test_case) throws IOException, Exception, Throwable;
 
                @Override
-               protected boolean slowCreateNewThread() {
-                       return threads.size() < MAX_THREAD_COUNT;
+               protected boolean canCreateNewThread() {
+                       return threads.size() < max_thread_count;
                }
 
                @Override
diff --git a/src/com/mostc/pftt/runner/AbstractPhpUnitTestCaseRunner.java 
b/src/com/mostc/pftt/runner/AbstractPhpUnitTestCaseRunner.java
index 6fb0ba0..8628a06 100644
--- a/src/com/mostc/pftt/runner/AbstractPhpUnitTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/AbstractPhpUnitTestCaseRunner.java
@@ -274,7 +274,7 @@ public abstract class AbstractPhpUnitTestCaseRunner extends 
AbstractTestCaseRunn
                        }
                        //
                        
-                       if (is_timeout) {
+                       if (is_timeout&&status!=EPhpUnitTestStatus.PASS) {
                                status = EPhpUnitTestStatus.TIMEOUT;
                        } else if (status==null) {
                                // if test had a 'Fatal Error', it might not 
have been able to print the status code at all
diff --git a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java 
b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
index 2580f56..31d2cfd 100644
--- a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
+++ b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
@@ -15,6 +15,7 @@ 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;
@@ -26,6 +27,7 @@ import com.mostc.pftt.model.core.PhptTestCase;
 import com.mostc.pftt.results.ConsoleManager;
 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.scenario.SAPIScenario;
 import com.mostc.pftt.scenario.ScenarioSetSetup;
@@ -44,6 +46,8 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
        protected final PhptThread thread;
        protected final SAPIScenario sapi_scenario;
        protected final PhptActiveTestPack active_test_pack;
+       protected final boolean xdebug;
+       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;
@@ -54,18 +58,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
        protected boolean is_timeout = false;
        
        public abstract String getIniActual() throws Exception;
-       
-       protected String get_ini_get_all_path() throws IllegalStateException, 
IOException {
-               // ensure ini_get_all.php exists
-               // TODO temp 5/15 - should store this once only and delete it 
later
-               String ini_get_all_path = host.mktempname(getClass(), 
"ini_get_all.php");
-               if (!host.exists(ini_get_all_path)) {
-                       // TODO locking?
-                       host.saveTextFile(ini_get_all_path, "<?php 
var_dump($argv);\nvar_dump(ini_get_all()); ?>");
-               }
-               return ini_get_all_path;
-       }
-       
+               
        /** runs the test case and reports the results to the 
PhptTelemetryManager
         * 
         * @see #willSkip - called by PhptTestPackRunner before #runTest is 
called
@@ -84,19 +77,44 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                        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');
+                                       }
+                               }
+                               test_output = sb.toString();
+                       }
+                       //
                        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) {
+                               if 
(!cm.isPhptNotInPlace()&&test_clean!=null&&!host.isBusy()) {
                                        current_section = EPhptSection.CLEAN; 
// @see #getSAPIOutput
                                        executeClean(); // #executeClean != 
#doRunTestClean
                                }
                        }
                }
-               doRunTestClean(cm);
+               if (!host.isBusy())
+                       doRunTestClean(cm);
        }
        
        protected void doRunTestClean(ConsoleManager cm) throws 
IllegalStateException, IOException {
@@ -120,7 +138,8 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                }
        }
        
-       public AbstractPhptTestCaseRunner2(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, PhptTestCase test_case, 
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;
@@ -209,7 +228,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 (lc_output.contains("skip") && ( !( this instanceof 
HttpPhptTestCaseRunner ) || !lc_output.contains("404")) ) {
+               if ((is_timeout||lc_output.contains("skip")) && ( !( 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?)
@@ -217,15 +236,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, 
is_timeout?EPhptTestStatus.TIMEOUT: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, 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, 
is_timeout?EPhptTestStatus.TIMEOUT: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, 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, 
is_timeout?EPhptTestStatus.TIMEOUT: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, 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, 
is_timeout?EPhptTestStatus.TIMEOUT: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, test_case, 
output, null, null, null, ini, null, null, null, null, null, null, null));
                        }
                        
                        // skip this test
@@ -237,8 +256,10 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
        } // end protected void evalSkipIf
        
        protected String preparePhptTestCode(String php_code) {
-               // TODO "<? xdebug_() ?>";
-               return php_code;
+               if (xdebug)
+                       return 
PhpUnitTemplate.renderXDebugPhptTemplate(php_code);
+               else
+                       return php_code;
        }
        
        static final Pattern PATTERN_CONTENT_TYPE = 
Pattern.compile("Content-Type:(.*)");
@@ -447,12 +468,12 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                        try {
                                expected_re_match = 
test_case.getExpectedCompiled(host, scenario_set, twriter, 
false).match(output_trim); 
                        } catch (Throwable ex) {
-                               twriter.addTestException(host, scenario_set, 
test_case, ex, expected);
+                               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));
                                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())));
+                               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;
                        } 
@@ -460,12 +481,12 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                                try {
                                        expected_re_match = 
test_case.getExpectedCompiled(host, scenario_set, twriter, 
true).match(output_trim); 
                                } catch (Throwable ex) {
-                                       twriter.addTestException(host, 
scenario_set, test_case, ex, expected);
+                                       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));
                                        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())));
+                                       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;
                                }
@@ -483,12 +504,12 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                                try {
                                        expected_re_match = 
test_case.getExpectedCompiled(host, scenario_set, twriter, 
false).match(output_trim); 
                                } catch (Throwable ex) {
-                                       twriter.addTestException(host, 
scenario_set, test_case, ex, expected);
+                                       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));
                                        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())));
+                                       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;
                                }
@@ -496,12 +517,12 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                                        try {
                                                expected_re_match = 
test_case.getExpectedCompiled(host, scenario_set, twriter, 
true).match(output_trim); 
                                        } catch (Throwable ex) {
-                                               twriter.addTestException(host, 
scenario_set, test_case, ex, expected);
+                                               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));
                                                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())));
+                                               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;
                                        }
@@ -514,7 +535,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                        
                        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)));
+                               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;
                        }
@@ -531,7 +552,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                                // 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())));
+                                       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;
                                } // end if
@@ -541,7 +562,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                        String output_trim = output.trim();
                        
                        if 
(StringUtil.isEmpty(output_trim)||(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())));
+                               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;
                        }
@@ -564,9 +585,9 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
 
                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()));
+                       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));
                } 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())));
+                       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)));
                }
                
                //
diff --git a/src/com/mostc/pftt/runner/AbstractTestPackRunner.java 
b/src/com/mostc/pftt/runner/AbstractTestPackRunner.java
index d3595df..ab2a72e 100644
--- a/src/com/mostc/pftt/runner/AbstractTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/AbstractTestPackRunner.java
@@ -56,12 +56,12 @@ public abstract class AbstractTestPackRunner<S extends 
SourceTestPack<?, T>, T e
        
        public abstract class SlowReplacementTestPackRunnerThread extends 
TestPackRunnerThread {
                
-               protected abstract boolean slowCreateNewThread();
+               protected abstract boolean canCreateNewThread();
                protected abstract void createNewThread();
                
                @Override
                public void notifySlowTest() {
-                       if (slowCreateNewThread()) {
+                       if (canCreateNewThread()) {
                                createNewThread();
                        }
                }

Reply via email to