Commit:    09e6f7b2982be21fa9d72e86cdfe548c07f92f33
Author:    Matt Ficken <v-maf...@microsoft.com>         Fri, 18 Oct 2013 
17:31:30 -0700
Parents:   00443ccd7d12429eb88f2d76531105bcde7dc578
Branches:  master

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

Log:
fixing windebug integration

providing symbols (was broken)... adding -debug_named console option


Former-commit-id: 93f5789bb8bed18245685738a43082cc2102cdac

Changed paths:
  M  bin/pftt_workspace.WEW
  M  conf/app/wordpress.groovy
  M  conf/not/not_builtin_web.groovy
  M  src/com/mostc/pftt/host/AHost.java
  M  src/com/mostc/pftt/host/Host.java
  M  src/com/mostc/pftt/host/LocalHost.java
  M  src/com/mostc/pftt/host/PosixLocalHost.java
  M  src/com/mostc/pftt/host/SSHHost.java
  M  src/com/mostc/pftt/host/WindowsLocalHost.java
  M  src/com/mostc/pftt/main/PfttMain.java
  M  src/com/mostc/pftt/model/core/PhpDebugPack.java
  M  src/com/mostc/pftt/model/core/PhptTestCase.java
  M  src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java
  M  src/com/mostc/pftt/model/sapi/CliSAPIInstance.java
  M  src/com/mostc/pftt/model/smoke/RequiredExtensionsSmokeTest.java
  M  src/com/mostc/pftt/results/AbstractPhptRW.java
  M  src/com/mostc/pftt/results/LocalConsoleManager.java
  M  src/com/mostc/pftt/results/PhpResultPackWriter.java
  M  src/com/mostc/pftt/results/PhptResultReader.java
  M  src/com/mostc/pftt/results/PhptResultWriter.java
  M  src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
  M  src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
  M  src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
  M  src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java
  M  src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java
  M  src/com/mostc/pftt/scenario/APCScenario.java
  M  src/com/mostc/pftt/scenario/APCUScenario.java
  M  src/com/mostc/pftt/scenario/ApacheModPHPScenario.java
  M  src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
  M  src/com/mostc/pftt/scenario/CLIScenario.java
  M  src/com/mostc/pftt/scenario/CodeCacheScenario.java
  M  src/com/mostc/pftt/scenario/MSSQLScenario.java
  M  src/com/mostc/pftt/scenario/MySQLScenario.java
  M  src/com/mostc/pftt/scenario/NoCodeCacheScenario.java
  M  src/com/mostc/pftt/scenario/OpcacheScenario.java
  M  src/com/mostc/pftt/scenario/SAPIScenario.java
  M  src/com/mostc/pftt/scenario/SSLSocketScenario.java
  M  src/com/mostc/pftt/scenario/WebServerScenario.java
  M  src/com/mostc/pftt/scenario/WinCacheScenario.java
  M  src/com/mostc/pftt/scenario/WinCacheUScenario.java
  M  src/com/mostc/pftt/util/DebuggerManager.java
  M  src/com/mostc/pftt/util/DllVersion.java
  M  src/com/mostc/pftt/util/HostEnvUtil.java
  M  src/com/mostc/pftt/util/WinDebugManager.java

diff --git a/bin/pftt_workspace.WEW b/bin/pftt_workspace.WEW
index f34077b..eb8a285 100644
Binary files a/bin/pftt_workspace.WEW and b/bin/pftt_workspace.WEW differ
diff --git a/conf/app/wordpress.groovy b/conf/app/wordpress.groovy
index bfd6ce4..7932962 100644
--- a/conf/app/wordpress.groovy
+++ b/conf/app/wordpress.groovy
@@ -78,7 +78,7 @@ class WordpressPhpUnitTestPack extends 
RequiredDatabasePhpUnitSourceTestPack {
        public int getThreadCount(AHost host, ScenarioSet scenario_set, int 
default_thread_count) {
                // Wordpress-Tests install wordpress on every test and do 
all-up tests (instead of propper unit tests)
                // so they're slow... run with fewer threads
-               return default_thread_count / 4;
+               return default_thread_count / 2;
        }
        @Override
        public String getPreBootstrapCode(ConsoleManager cm, AHost host, 
ScenarioSet scenario_set, PhpBuild build) {
diff --git a/conf/not/not_builtin_web.groovy b/conf/not/not_builtin_web.groovy
index d686b1e..d8c2477 100644
--- a/conf/not/not_builtin_web.groovy
+++ b/conf/not/not_builtin_web.groovy
@@ -4,6 +4,26 @@ def describe() {
 }
 
 def notScenarios() {
-       ['Local-FileSystem_Builtin-Web', 'SMB-DFS_Builtin-Web', 
'SMB-CA_Builtin-Web', 'SMB-Basic_Builtin-Web', 'SMB-Deduplication_Builtin-Web',
-               'Opcache_Local-FileSystem_Builtin-Web', 
'Opcache_SMB-DFS_Builtin-Web', 'Opcache_SMB-CA_Builtin-Web', 
'Opcache_SMB-Basic_Builtin-Web', 'Opcache_SMB-Deduplication_Builtin-Web']
+       [
+               'Local-FileSystem_Builtin-Web', 
+               'SMB-DFS_Builtin-Web', 
+               'SMB-CA_Builtin-Web', 
+               'SMB-Basic_Builtin-Web', 
+               'SMB-Deduplication_Builtin-Web',
+               'Opcache_Local-FileSystem_Builtin-Web', 
+               'Opcache_SMB-DFS_Builtin-Web', 
+               'Opcache_SMB-CA_Builtin-Web', 
+               'Opcache_SMB-Basic_Builtin-Web', 
+               'Opcache_SMB-Deduplication_Builtin-Web',
+               'Local-FileSystem_MySQL-5.6_Builtin-Web',
+               'SMB-DFS_MySQL-5.6_Builtin-Web',
+               'SMB-CA_MySQL-5.6_Builtin-Web',
+               'SMB-Basic_MySQL-5.6_Builtin-Web',
+               'SMB-Deduplication_MySQL-5.6_Builtin-Web',
+               'Opcache_MySQL-5.6_Local-FileSystem_Builtin-Web',
+               'Opcache_MySQL-5.6_SMB-DFS_Builtin-Web',
+               'Opcache_MySQL-5.6_SMB-CA_Builtin-Web',
+               'Opcache_MySQL-5.6_SMB-Basic_Builtin-Web',
+               'Opcache_MySQL-5.6_SMB-Deduplication_Builtin-Web'
+       ]
 }
diff --git a/src/com/mostc/pftt/host/AHost.java 
b/src/com/mostc/pftt/host/AHost.java
index 71461e4..e9adfc4 100644
--- a/src/com/mostc/pftt/host/AHost.java
+++ b/src/com/mostc/pftt/host/AHost.java
@@ -70,10 +70,7 @@ public abstract class AHost extends Host implements 
IProgramRunner {
                os_name = os_name.replace("Home", "");
                os_name = os_name.replace("Basic", "");
                //
-               os_name = os_name.replace("  ", " ");
-               os_name = os_name.replace("  ", " ");
-               os_name = os_name.replace("  ", " ");
-               os_name = os_name.replace("  ", " ");
+               os_name = os_name.replaceAll("\\w+", " ");
                return os_name.trim();
        }
        
@@ -150,11 +147,15 @@ public abstract class AHost extends Host implements 
IProgramRunner {
         * @param stdin_post - bytes to pass to program's STDIN
         * @param charset - character set to assume program's output is - 
otherwise it'll autodetect it, which is slower 
         * @param current_dir - current directory for the program
+        * @param wrap_child
         * @return
         * @throws IllegalStateException
         * @throws Exception
         */
-       public abstract ExecOutput execOut(String cmd, int timeout_sec, 
Map<String,String> object, byte[] stdin_post, Charset charset, String 
current_dir) throws IllegalStateException, Exception;
+       public abstract ExecOutput execOut(String cmd, int timeout_sec, 
Map<String,String> object, byte[] stdin_post, Charset charset, String 
current_dir, boolean wrap_child) throws IllegalStateException, Exception;
+       public ExecOutput execOut(String cmd, int timeout_sec, 
Map<String,String> object, byte[] stdin_post, Charset charset, String 
current_dir) throws IllegalStateException, Exception {
+               return execOut(cmd, timeout_sec, object, stdin_post, charset, 
current_dir, false);
+       }
        /** executes the given program. if thread_slow_sec time is exceeded, 
calls TestPackRunnerThread#slowTest so that the TestPackRunner
         * can compensate
         * 
@@ -169,24 +170,48 @@ public abstract class AHost extends Host implements 
IProgramRunner {
         * @return
         * @throws Exception
         */
-       public abstract ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env, byte[] stdin, Charset charset, String chdir, 
TestPackRunnerThread thread, int thread_slow_sec) throws Exception;
-       public ExecOutput execOut(String commandline, int timeout, String 
chdir) throws Exception {
+       public abstract ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env, byte[] stdin, Charset charset, String chdir, 
@SuppressWarnings("rawtypes") TestPackRunnerThread thread, int thread_slow_sec, 
boolean wrap_child) throws Exception;
+       public ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env, byte[] stdin, Charset charset, String chdir, 
@SuppressWarnings("rawtypes") TestPackRunnerThread thread, int thread_slow_sec) 
throws Exception {
+               return execOut(commandline, timeout, env, stdin, charset, 
chdir, thread, thread_slow_sec, false);
+       }
+       public ExecOutput execOut(String commandline, int timeout, String 
chdir, boolean wrap_child) throws Exception {
                return execOut(commandline, timeout, null, null, null, chdir);
        }       
+       public ExecOutput execOut(String commandline, int timeout, String 
chdir) throws Exception {
+               return execOut(commandline, timeout, chdir, false);
+       }
+       public ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env, Charset charset, String chdir, boolean wrap_child) 
throws Exception {
+               return execOut(commandline, timeout, env, null, charset, chdir, 
wrap_child);
+       }
        public ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env, Charset charset, String chdir) throws Exception {
-               return execOut(commandline, timeout, env, null, charset, chdir);
+               return execOut(commandline, timeout, env, null, charset, chdir, 
false);
+       }
+       public ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env, boolean wrap_child) throws Exception {
+               return execOut(commandline, timeout, env, (String)null, 
wrap_child);
        }
        public ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env) throws Exception {
-               return execOut(commandline, timeout, env, (String)null);
+               return execOut(commandline, timeout, env, (String)null, false);
+       }
+       public ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env, String chdir, boolean wrap_child) throws Exception {
+               return execOut(commandline, timeout, env, null, chdir, 
wrap_child);
        }
        public ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env, String chdir) throws Exception {
-               return execOut(commandline, timeout, env, null, chdir);
+               return execOut(commandline, timeout, env, null, chdir, false);
+       }
+       public ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, byte[] stdin_data, Charset charset, String chdir, 
@SuppressWarnings("rawtypes") TestPackRunnerThread test_thread, int 
slow_timeout_sec) throws Exception {
+               return execElevatedOut(cmd, timeout_sec, env, stdin_data, 
charset, chdir, test_thread, slow_timeout_sec, false);
+       }
+       public ExecOutput execElevatedOut(String commandline, int timeout, 
Map<String,String> env, boolean wrap_child) throws Exception {
+               return execElevatedOut(commandline, timeout, env, (String)null, 
wrap_child);
        }
        public ExecOutput execElevatedOut(String commandline, int timeout, 
Map<String,String> env) throws Exception {
-               return execElevatedOut(commandline, timeout, env, (String)null);
+               return execElevatedOut(commandline, timeout, env, (String)null, 
false);
+       }
+       public ExecOutput execElevatedOut(String commandline, int timeout, 
Map<String,String> env, String chdir, boolean wrap_child) throws Exception {
+               return execElevatedOut(commandline, timeout, env, null, chdir, 
wrap_child);
        }
        public ExecOutput execElevatedOut(String commandline, int timeout, 
Map<String,String> env, String chdir) throws Exception {
-               return execElevatedOut(commandline, timeout, env, null, chdir);
+               return execElevatedOut(commandline, timeout, env, null, chdir, 
false);
        }
        /** gets value of environment variable
         * 
@@ -345,19 +370,26 @@ public abstract class AHost extends Host implements 
IProgramRunner {
         * @param chdir
         * @param test_thread
         * @param slow_timeout_sec
+        * @param wrap_child
         * @return
         * @throws Exception
         */
-       public abstract ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, byte[] stdin_data, Charset charset, String chdir, 
TestPackRunnerThread test_thread, int slow_timeout_sec) throws Exception;
+       public abstract ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, byte[] stdin_data, Charset charset, String chdir, 
@SuppressWarnings("rawtypes") TestPackRunnerThread test_thread, int 
slow_timeout_sec, boolean wrap_child) throws Exception;
        public ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, Charset charset) throws Exception {
                return execElevatedOut(cmd, timeout_sec, env, null, charset, 
null, null, FOUR_HOURS);
        }
-       public ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, Charset charset, String chdir) throws Exception {
+       public ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, Charset charset, String chdir, boolean wrap_child) 
throws Exception {
                return execElevatedOut(cmd, timeout_sec, env, null, charset, 
chdir, null, FOUR_HOURS);
        }
-       public ExecOutput execElevatedOut(String cmd, int timeout_sec, String 
chdir) throws Exception {
+       public ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, Charset charset, String chdir) throws Exception {
+               return execElevatedOut(cmd, timeout_sec, env, charset, chdir, 
false);
+       }
+       public ExecOutput execElevatedOut(String cmd, int timeout_sec, String 
chdir, boolean wrap_child) throws Exception {
                return execElevatedOut(cmd, timeout_sec, null, null, null, 
chdir, null, FOUR_HOURS);
        }
+       public ExecOutput execElevatedOut(String cmd, int timeout_sec, String 
chdir) throws Exception {
+               return execElevatedOut(cmd, timeout_sec, chdir, false);
+       }
        @ThreadSafe
        public abstract class ExecHandle {
                public abstract InputStream getSTDOUT();
@@ -432,7 +464,7 @@ public abstract class AHost extends Host implements 
IProgramRunner {
                
                
                // TODO
-               public abstract void run(ConsoleManager cm, StringBuilder 
output_sb, Charset charset, int timeout_sec, TestPackRunnerThread thread, int 
slow_sec, int suspend_seconds, int max_chars) throws IOException, 
InterruptedException;
+               public abstract void run(ConsoleManager cm, StringBuilder 
output_sb, Charset charset, int timeout_sec, @SuppressWarnings("rawtypes") 
TestPackRunnerThread thread, int slow_sec, int suspend_seconds, int max_chars) 
throws IOException, InterruptedException;
        } // end public abstract class ExecHandle
        
        /** checks exit code to see if it means process crashed
@@ -503,20 +535,32 @@ public abstract class AHost extends Host implements 
IProgramRunner {
        public ExecHandle execThread(String commandline) throws Exception {
                return execThread(commandline, null, null, null);
        }
+       public ExecHandle execThread(String commandline, byte[] stdin_data, 
boolean wrap_child) throws Exception {
+               return execThread(commandline, null, null, stdin_data, 
wrap_child);
+       }
        public ExecHandle execThread(String commandline, byte[] stdin_data) 
throws Exception {
-               return execThread(commandline, null, null, stdin_data);
+               return execThread(commandline, null, null, stdin_data, false);
        }
        public ExecHandle execThread(String commandline, String chdir) throws 
Exception {
                return execThread(commandline, null, chdir, null);
        }
-       public ExecHandle execThread(String commandline, String chdir, byte[] 
stdin_data) throws Exception {
+       public ExecHandle execThread(String commandline, String chdir, byte[] 
stdin_data, boolean wrap_child) throws Exception {
                return execThread(commandline, null, chdir, stdin_data);
        }
-       public ExecHandle execThread(String commandline, Map<String,String> 
env, byte[] stdin_data) throws Exception {
+       public ExecHandle execThread(String commandline, String chdir, byte[] 
stdin_data) throws Exception {
+               return execThread(commandline, null, chdir, stdin_data, false);
+       }
+       public ExecHandle execThread(String commandline, Map<String,String> 
env, byte[] stdin_data, boolean wrap_child) throws Exception {
                return execThread(commandline, env, null, stdin_data);
        }
+       public ExecHandle execThread(String commandline, Map<String,String> 
env, byte[] stdin_data) throws Exception {
+               return execThread(commandline, env, null, stdin_data, false);
+       }
+       public ExecHandle execThread(String commandline, Map<String,String> 
env, String chdir, boolean wrap_child) throws Exception {
+               return execThread(commandline, env, chdir, null, wrap_child);
+       }
        public ExecHandle execThread(String commandline, Map<String,String> 
env, String chdir) throws Exception {
-               return execThread(commandline, env, chdir, null);
+               return execThread(commandline, env, chdir, null, false);
        }
        /** executes command, returning immediately before it ends, returning a 
handle to asynchronously monitor
         * the process.
@@ -525,10 +569,15 @@ public abstract class AHost extends Host implements 
IProgramRunner {
         * @param env
         * @param chdir
         * @param stdin_data
+        * @param wrap_child - wraps process in another process (so commandline 
is a grandchild process of this)
+        *                   - sometimes needed to reliably kill processes on 
Windows (when running lots of tests, etc... get dangling handles)
         * @return
         * @throws Exception
         */
-       public abstract ExecHandle execThread(String commandline, 
Map<String,String> env, String chdir, byte[] stdin_data) throws Exception;
+       public abstract ExecHandle execThread(String commandline, 
Map<String,String> env, String chdir, byte[] stdin_data, boolean wrap_child) 
throws Exception;
+       public ExecHandle execThread(String commandline, Map<String,String> 
env, String chdir, byte[] stdin_data) throws Exception {
+               return execThread(commandline, env, chdir, stdin_data, false);
+       }
        public ExecOutput execOut(String cmd, int timeout_sec, 
Map<String,String> object, byte[] stdin_post, Charset charset) throws 
IllegalStateException, Exception {
                return execOut(cmd, timeout_sec, object, stdin_post, charset, 
(String)null);
        }
@@ -1085,12 +1134,12 @@ public abstract class AHost extends Host implements 
IProgramRunner {
        }
 
        @Override
-       public boolean exec(ConsoleManager cm, String ctx_str, String 
commandline, int timeout, Map<String, String> env, byte[] stdin, Charset 
charset, String chdir, TestPackRunnerThread thread, int thread_slow_sec) throws 
Exception {
+       public boolean exec(ConsoleManager cm, String ctx_str, String 
commandline, int timeout, Map<String, String> env, byte[] stdin, Charset 
charset, String chdir, @SuppressWarnings("rawtypes") TestPackRunnerThread 
thread, int thread_slow_sec) throws Exception {
                return execOut(commandline, timeout, env, stdin, charset, 
chdir, thread, thread_slow_sec).printOutputIfCrash(ctx_str, cm).isSuccess();
        }
 
        @Override
-       public boolean execElevated(ConsoleManager cm, String ctx_str, String 
cmd, int timeout_sec, Map<String, String> env, byte[] stdin_data, Charset 
charset, String chdir, TestPackRunnerThread test_thread, int slow_timeout_sec) 
throws Exception {
+       public boolean execElevated(ConsoleManager cm, String ctx_str, String 
cmd, int timeout_sec, Map<String, String> env, byte[] stdin_data, Charset 
charset, String chdir, @SuppressWarnings("rawtypes") TestPackRunnerThread 
test_thread, int slow_timeout_sec) throws Exception {
                return execElevatedOut(cmd, timeout_sec, env, stdin_data, 
charset, chdir, test_thread, slow_timeout_sec).printOutputIfCrash(ctx_str, 
cm).isSuccess();
        }
 
diff --git a/src/com/mostc/pftt/host/Host.java 
b/src/com/mostc/pftt/host/Host.java
index 45286f3..bfd6d42 100644
--- a/src/com/mostc/pftt/host/Host.java
+++ b/src/com/mostc/pftt/host/Host.java
@@ -622,12 +622,38 @@ public abstract class Host {
                        return StringUtil.EMPTY;
                
                StringBuilder sb = new StringBuilder(Math.max(1024, 
parts[0].length()*2));
-               sb.append(parts[0]);
+               sb.append(fixPath(parts[0]));
                for ( int i=1 ; i < parts.length ; i++ ) {
                        if (parts[i]==null)
                                continue;
                        sb.append(dirSeparator());
-                       sb.append(parts[i]);
+                       sb.append(fixPath(parts[i]));
+               }
+               return sb.toString();
+       }
+       
+       public String joinIntoOnePath(List<String> parts) {
+               if (parts==null||parts.isEmpty())
+                       return StringUtil.EMPTY;
+               
+               StringBuilder sb = new StringBuilder(Math.max(1024, 
parts.get(0).length()*2));
+               sb.append(fixPath(parts.get(0)));
+               for ( int i=1 ; i < parts.size() ; i++ ) {
+                       sb.append(dirSeparator());
+                       sb.append(fixPath(parts.get(i)));
+               }
+               return sb.toString();
+       }
+       
+       public String joinIntoMultiplePath(List<String> parts) {
+               if (parts==null||parts.isEmpty())
+                       return StringUtil.EMPTY;
+               
+               StringBuilder sb = new StringBuilder(Math.max(1024, 
parts.get(0).length()*2));
+               sb.append(fixPath(parts.get(0)));
+               for ( int i=1 ; i < parts.size() ; i++ ) {
+                       sb.append(pathsSeparator());
+                       sb.append(fixPath(parts.get(i)));
                }
                return sb.toString();
        }
diff --git a/src/com/mostc/pftt/host/LocalHost.java 
b/src/com/mostc/pftt/host/LocalHost.java
index 7c7e8aa..21e26fd 100644
--- a/src/com/mostc/pftt/host/LocalHost.java
+++ b/src/com/mostc/pftt/host/LocalHost.java
@@ -222,18 +222,17 @@ public abstract class LocalHost extends AHost {
        }
 
        @Override
-       public ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env, byte[] stdin, Charset charset, String chdir) throws 
Exception {
-               return execOut(commandline, timeout, env, stdin, charset, 
chdir, null, NO_TIMEOUT);
+       public ExecOutput execOut(String commandline, int timeout, 
Map<String,String> env, byte[] stdin, Charset charset, String chdir, boolean 
wrap_child) throws Exception {
+               return execOut(commandline, timeout, env, stdin, charset, 
chdir, null, NO_TIMEOUT, wrap_child);
        }
        @Override
-       public LocalExecHandle execThread(String commandline, 
Map<String,String> env, String chdir, byte[] stdin_data) throws Exception {
-               return exec_impl(splitCmdString(commandline), env, chdir, 
stdin_data);
+       public LocalExecHandle execThread(String commandline, 
Map<String,String> env, String chdir, byte[] stdin_data, boolean wrap_child) 
throws Exception {
+               return exec_impl(wrapSplitCmdString(wrap_child, commandline), 
env, chdir, stdin_data);
        }
+       @SuppressWarnings("rawtypes")
        @Override
-       public ExecOutput execOut(final String commandline, int timeout, 
Map<String,String> env, byte[] stdin_data, Charset charset, String chdir, 
TestPackRunnerThread thread, int thread_slow_sec) throws Exception {
-               
-
-               LocalExecHandle eh = exec_impl(splitCmdString(commandline), 
env, chdir, stdin_data); 
+       public ExecOutput execOut(final String commandline, int timeout, 
Map<String,String> env, byte[] stdin_data, Charset charset, String chdir, 
TestPackRunnerThread thread, int thread_slow_sec, boolean wrap_child) throws 
Exception {
+               LocalExecHandle eh = exec_impl(wrapSplitCmdString(wrap_child, 
commandline), env, chdir, stdin_data); 
                        
                StringBuilder output_sb = new StringBuilder(1024);
                
@@ -251,9 +250,10 @@ public abstract class LocalHost extends AHost {
        }
        
        protected static class ThreadSlowTask implements Runnable {
+               @SuppressWarnings("rawtypes")
                protected final TestPackRunnerThread thread;
                
-               protected ThreadSlowTask(TestPackRunnerThread thread) {
+               protected ThreadSlowTask(@SuppressWarnings("rawtypes") 
TestPackRunnerThread thread) {
                        this.thread = thread;
                }
                
@@ -529,7 +529,7 @@ public abstract class LocalHost extends AHost {
                }
 
                @Override
-               public void run(ConsoleManager cm, StringBuilder output_sb, 
Charset charset, int timeout_sec, TestPackRunnerThread thread, int 
thread_slow_sec, int suspend_seconds, int max_chars) throws IOException, 
InterruptedException {
+               public void run(ConsoleManager cm, StringBuilder output_sb, 
Charset charset, int timeout_sec, @SuppressWarnings("rawtypes") 
TestPackRunnerThread thread, int thread_slow_sec, int suspend_seconds, int 
max_chars) throws IOException, InterruptedException {
                        TimerThread a = null, b = null;
                        if (thread!=null && thread_slow_sec>NO_TIMEOUT) {
                                b = TimerUtil.waitSeconds(thread_slow_sec, new 
ThreadSlowTask(thread));
@@ -593,18 +593,10 @@ public abstract class LocalHost extends AHost {
                return 0;
        } // end protected static int getWindowsProcessIDReflection
        
+       protected abstract String[] wrapSplitCmdString(boolean wrap_child, 
String command);
+       
        private static final Pattern PAT_QUOTE = Pattern.compile("\\\"");
        public static String[] splitCmdString(String command) {
-               if 
(command.contains("php.exe")||command.contains("php-cgi.exe")||command.contains("httpd.exe"))
 {
-                       // TODO temp
-                       return new String[]{
-                                       "cmd",
-                                       "/S",
-                                       "/C",
-                                       "\""+command+" & EXIT\""
-                       };
-               }
-               
                LinkedList<String> parts = new LinkedList<String>();
                String buf = "";
                char c;
@@ -647,23 +639,6 @@ public abstract class LocalHost extends AHost {
        protected LocalExecHandle exec_impl(String[] cmd_array, 
Map<String,String> env, String chdir, byte[] stdin_data) throws Exception, 
InterruptedException {
                Process process = null;
                {
-                       /*if (cmd_array.length>0&&
-                                       
(cmd_array[0].equals("C:\\php-sdk\\php-5.5.5RC1-nts-Win32-VC11-x86\\php.exe")
-                                                       
||cmd_array[0].equals("C:\\Apache244-VC11-OpenSSL1.0.1e-x86\\bin\\httpd.exe")
-                                                       
||cmd_array[0].equals("C:\\php-sdk\\php-5.5.5RC1-nts-Win32-VC11-x86\\php-cgi.exe")
-                                                       
||cmd_array[0].equals("C:\\php-sdk\\php-5.5.5RC1-Win32-VC11-x86\\php.exe")
-                                                       
||cmd_array[0].equals("C:\\php-sdk\\php-5.5.5RC1-Win32-VC11-x86\\php-cgi.exe")))
 {
-                               // TODO temp
-                               String[] new_cmd_array = new 
String[5+cmd_array.length];
-                               new_cmd_array[0] = "cmd.exe";
-                               new_cmd_array[1] = "/S";
-                               new_cmd_array[2] = "/C";
-                               new_cmd_array[3] = "\"";
-                               System.arraycopy(cmd_array, 0, new_cmd_array, 
4, cmd_array.length);
-                               cmd_array = new_cmd_array;
-                               new_cmd_array[new_cmd_array.length-1] = "\"";
-                       }
-                       System.out.println("791 
"+StringUtil.toString(cmd_array));*/
                        ProcessBuilder builder = new ProcessBuilder(cmd_array);
                        if (env!=null) {
                                //
@@ -727,7 +702,6 @@ public abstract class LocalHost extends AHost {
                
                @Override
                public void run() {
-                       System.out.println("730 
"+getWindowsProcessID(h.process.get()));
                        // go further trying to kill the process
                        //
                        // WindowsLocalHostExecHandle#close checks for 
WerFault.exe blocking on Windows
diff --git a/src/com/mostc/pftt/host/PosixLocalHost.java 
b/src/com/mostc/pftt/host/PosixLocalHost.java
index c6623da..0b14b30 100644
--- a/src/com/mostc/pftt/host/PosixLocalHost.java
+++ b/src/com/mostc/pftt/host/PosixLocalHost.java
@@ -72,9 +72,15 @@ public class PosixLocalHost extends LocalHost {
                }
        }
 
+       @SuppressWarnings("rawtypes")
        @Override
-       public ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, byte[] stdin_data, Charset charset, String chdir, 
TestPackRunnerThread test_thread, int slow_timeout_sec) throws Exception {
-               return execOut(cmd, timeout_sec, env, stdin_data, charset, 
chdir, test_thread, slow_timeout_sec);
+       public ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, byte[] stdin_data, Charset charset, String chdir, 
TestPackRunnerThread test_thread, int slow_timeout_sec, boolean wrap_child) 
throws Exception {
+               return execOut(cmd, timeout_sec, env, stdin_data, charset, 
chdir, test_thread, slow_timeout_sec, wrap_child);
+       }
+       
+       @Override
+       protected String[] wrapSplitCmdString(boolean wrap_child, String 
command) {
+               return splitCmdString(command);
        }
        
        @Override
diff --git a/src/com/mostc/pftt/host/SSHHost.java 
b/src/com/mostc/pftt/host/SSHHost.java
index 44a578e..10134ba 100644
--- a/src/com/mostc/pftt/host/SSHHost.java
+++ b/src/com/mostc/pftt/host/SSHHost.java
@@ -409,7 +409,7 @@ public class SSHHost extends RemoteHost {
        } // end public SessionChannelClient createSessionChannelClient
        
        @Override
-       public ExecHandle execThread(String cmd, Map<String, String> env, 
String chdir, byte[] stdin_post) throws Exception {
+       public ExecHandle execThread(String cmd, Map<String, String> env, 
String chdir, byte[] stdin_post, boolean wrap_child) throws Exception {
                ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
                SessionChannelClient session = createSessionChannelClient(cmd, 
env, chdir, stdin_post, out);
                
@@ -465,7 +465,7 @@ public class SSHHost extends RemoteHost {
                }
 
                @Override
-               public void run(ConsoleManager cm, StringBuilder output_sb, 
Charset charset, int timeout_sec, final TestPackRunnerThread thread, int 
slow_sec, int suspend_seconds, int max_chars) throws IOException, 
InterruptedException {
+               public void run(ConsoleManager cm, StringBuilder output_sb, 
Charset charset, int timeout_sec, @SuppressWarnings("rawtypes") final 
TestPackRunnerThread thread, int slow_sec, int suspend_seconds, int max_chars) 
throws IOException, InterruptedException {
                        do_run(this, session, charset, timeout_sec, thread, 
slow_sec);
                        output_sb.append(out.toString());
                }
@@ -478,7 +478,7 @@ public class SSHHost extends RemoteHost {
        } // end protected class SSHExecHandle
        
        @Override
-       public ExecOutput execOut(final String cmd, int timeout_sec, 
Map<String, String> env, byte[] stdin_post, Charset charset, String chdir, 
final TestPackRunnerThread thread, int slow_sec) throws Exception {
+       public ExecOutput execOut(final String cmd, int timeout_sec, 
Map<String, String> env, byte[] stdin_post, Charset charset, String chdir, 
@SuppressWarnings("rawtypes") final TestPackRunnerThread thread, int slow_sec, 
boolean wrap_child) throws Exception {
                final ByteArrayIOStream out = new ByteArrayIOStream(1024);
                
                final ExecOutput eo = new ExecOutput();
@@ -500,7 +500,7 @@ public class SSHHost extends RemoteHost {
                return eo;
        } // end public ExecOutput execOut
        
-       protected void do_run(final SSHExecHandle h, final SessionChannelClient 
session, Charset charset, int timeout_sec, final TestPackRunnerThread thread, 
int slow_sec) throws InvalidStateException, InterruptedException {
+       protected void do_run(final SSHExecHandle h, final SessionChannelClient 
session, Charset charset, int timeout_sec, @SuppressWarnings("rawtypes") final 
TestPackRunnerThread thread, int slow_sec) throws InvalidStateException, 
InterruptedException {
                final AtomicBoolean run = new AtomicBoolean(true);
                if (timeout_sec>NO_TIMEOUT) {
                        timer.schedule(new TimerTask() {
@@ -550,16 +550,6 @@ public class SSHHost extends RemoteHost {
        }
 
        @Override
-       public ExecOutput execOut(String cmd, int timeout, String chdir) throws 
Exception {
-               return execOut(cmd, timeout, null, null, chdir);
-       }
-
-       @Override
-       public ExecOutput execOut(String cmd, int timeout, Map<String, String> 
env, Charset charset, String chdir) throws Exception {
-               return execOut(cmd, timeout, env, null, charset, chdir);
-       }
-
-       @Override
        public String getUsername() {
                return username;
        }
@@ -665,7 +655,7 @@ public class SSHHost extends RemoteHost {
        }
 
        @Override
-       public ExecOutput execOut(String cmd, int timeout, Map<String, String> 
env, byte[] stdin_post, Charset charset, String chdir) throws Exception {
+       public ExecOutput execOut(String cmd, int timeout, Map<String, String> 
env, byte[] stdin_post, Charset charset, String chdir, boolean wrap_child) 
throws Exception {
                return execOut(cmd, timeout, env, stdin_post, charset, chdir, 
null, FOUR_HOURS);
        }
 
@@ -875,4 +865,12 @@ public class SSHHost extends RemoteHost {
                return false;
        }
 
+       @Override
+       public ExecOutput execElevatedOut(String cmd, int timeout_sec,
+                       Map<String, String> env, byte[] stdin_data, Charset 
charset,
+                       String chdir, @SuppressWarnings("rawtypes") 
TestPackRunnerThread test_thread,
+                       int slow_timeout_sec, boolean wrap_child) throws 
Exception {
+               return execOut(cmd, timeout_sec, env, stdin_data, charset, 
chdir, test_thread, slow_timeout_sec, wrap_child);
+       }
+
 } // end public class SSHHost
diff --git a/src/com/mostc/pftt/host/WindowsLocalHost.java 
b/src/com/mostc/pftt/host/WindowsLocalHost.java
index bcfae6a..0c160bd 100644
--- a/src/com/mostc/pftt/host/WindowsLocalHost.java
+++ b/src/com/mostc/pftt/host/WindowsLocalHost.java
@@ -27,7 +27,7 @@ public class WindowsLocalHost extends LocalHost {
        }
        
        @Override
-       public ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, byte[] stdin_data, Charset charset, String chdir, 
TestPackRunnerThread test_thread, int slow_timeout_sec) throws Exception {
+       public ExecOutput execElevatedOut(String cmd, int timeout_sec, 
Map<String, String> env, byte[] stdin_data, Charset charset, String chdir, 
@SuppressWarnings("rawtypes") TestPackRunnerThread test_thread, int 
slow_timeout_sec, boolean wrap_child) throws Exception {
                if (StringUtil.isEmpty(getEnvValue("PFTT_SHELL"))) {
                        // check if %PFTT_SHELL% is defined then PFTT is 
running in the
                        // PFTT shell which is already elevated, so don't run 
elevate.exe
@@ -48,6 +48,20 @@ public class WindowsLocalHost extends LocalHost {
        }
        
        @Override
+       protected String[] wrapSplitCmdString(boolean wrap_child, String 
command) {
+               if (wrap_child) {
+                       return new String[]{
+                                       "cmd",
+                                       "/S",
+                                       "/C",
+                                       "\""+command+" & EXIT\""
+                               };
+               } else {
+                       return splitCmdString(command);
+               }
+       }
+       
+       @Override
        protected Process guardStart(ProcessBuilder builder) throws Exception, 
InterruptedException {
                Process p = doGuardStart(builder);
                // try twice
diff --git a/src/com/mostc/pftt/main/PfttMain.java 
b/src/com/mostc/pftt/main/PfttMain.java
index d6d2a0c..810f368 100644
--- a/src/com/mostc/pftt/main/PfttMain.java
+++ b/src/com/mostc/pftt/main/PfttMain.java
@@ -430,7 +430,7 @@ public class PfttMain {
                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)")
-                       // TODO support name fragments in -debug_list (more 
consistent with core_name, etc...)
+                       .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")
                        .addRow("-debug_pack <path>", "folder with debugger 
symbols (usually folder with .pdb files)"));
@@ -514,7 +514,7 @@ public class PfttMain {
        protected void ensureLocalhostPrepared(PhpBuild build) throws Exception 
{
                if (prepared==build)
                        return;
-               HostEnvUtil.prepareHostEnv(host, cm, build, 
!cm.isDisableDebugPrompt());
+               HostEnvUtil.prepareHostEnv(host, cm, build, 
!(cm.isDisableDebugPrompt()||cm.isDebugAll()||cm.isDebugList()));
                prepared = build;
        }
        
@@ -579,15 +579,17 @@ public class PfttMain {
                                        // @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());
+                                               
cm.println(EPrintType.CANT_CONTINUE, test.getName(), "Failed smoke test");
                                                
                                                return false;
+                                       } else {
+                                               cm.println(EPrintType.CLUE, 
test.getName(), "Smoke Test Passed");
                                        }
                                }
                                {
                                        TempDirWritableSmokeTest test = new 
TempDirWritableSmokeTest();
                                        if (test.test(build, cm, host, 
SAPIScenario.getSAPIScenario(scenario_set).getSAPIType(), 
tmgr)==ESmokeTestStatus.FAIL) {
-                                               
cm.println(EPrintType.CANT_CONTINUE, "Main", "Failed smoke test: 
"+test.getName());
+                                               
cm.println(EPrintType.CANT_CONTINUE, test.getName(), "Failed smoke test");
                                                
                                                return false;
                                        }
@@ -595,9 +597,11 @@ public class PfttMain {
                                {
                                        RequiredFeaturesSmokeTest test = new 
RequiredFeaturesSmokeTest();
                                        if (test.test(build, cm, host, 
tmgr)==ESmokeTestStatus.FAIL) {
-                                               
cm.println(EPrintType.CANT_CONTINUE, "Main", "Failed smoke test: 
"+test.getName());
+                                               
cm.println(EPrintType.CANT_CONTINUE, test.getName(), "Failed smoke test");
                                                
                                                return false;
+                                       } else {
+                                               cm.println(EPrintType.CLUE, 
test.getName(), "Smoke Test Passed");
                                        }
                                }
                        }
@@ -709,15 +713,17 @@ public class PfttMain {
                                        {
                                                RequiredExtensionsSmokeTest 
test = new RequiredExtensionsSmokeTest();
                                                if (test.test(build, cm, host, 
SAPIScenario.getSAPIScenario(scenario_set).getSAPIType(), 
tmgr)==ESmokeTestStatus.FAIL) {
-                                                       
cm.println(EPrintType.CANT_CONTINUE, "Main", "Failed smoke test: 
"+test.getName());
+                                                       
cm.println(EPrintType.CANT_CONTINUE, test.getName(), "Failed smoke test");
 
                                                        break;
+                                               } else {
+                                                       
cm.println(EPrintType.CLUE, test.getName(), "Smoke Test Passed");
                                                }
                                        }
                                        {
                                                TempDirWritableSmokeTest test = 
new TempDirWritableSmokeTest();
                                                if (test.test(build, cm, host, 
SAPIScenario.getSAPIScenario(scenario_set).getSAPIType(), 
tmgr)==ESmokeTestStatus.FAIL) {
-                                                       
cm.println(EPrintType.CANT_CONTINUE, "Main", "Failed smoke test: 
"+test.getName());
+                                                       
cm.println(EPrintType.CANT_CONTINUE, test.getName(), "Failed smoke test");
 
                                                        break;
                                                }
@@ -725,9 +731,11 @@ public class PfttMain {
                                        {
                                                RequiredFeaturesSmokeTest test 
= new RequiredFeaturesSmokeTest();
                                                if (test.test(build, cm, host, 
tmgr)==ESmokeTestStatus.FAIL) {
-                                                       
cm.println(EPrintType.CANT_CONTINUE, "Main", "Failed smoke test: 
"+test.getName());
+                                                       
cm.println(EPrintType.CANT_CONTINUE, test.getName(), "Failed smoke test");
                                                        
                                                        break;
+                                               } else {
+                                                       
cm.println(EPrintType.CLUE, test.getName(), "Smoke Test Passed");
                                                }
                                        }
                                }
@@ -1314,6 +1322,13 @@ public class PfttMain {
                        }.start();
        }
        
+       protected static void warnDebugAll(ConsoleManager cm) {
+               if (cm.isDebugAll()) {
+                       cm.println(EPrintType.WARNING, PfttMain.class, "You 
should NOT use -debug_all with `core_all` or `app_all`. It causes lots of 
debuggers to be launched!");
+                       cm.println(EPrintType.TIP, PfttMain.class, "Instead, 
use `core_all` or `app_all` (maybe with `-c test_pack5`) to find all the 
crashes (constant and intermittent) then run that list with `core_list` or 
`app_list`");
+               }
+       }
+       
        public static void main(String[] args) throws Throwable {
                // 
                if (args.length > 0 && args[0].equals("sleep")) {
@@ -1494,6 +1509,12 @@ public class PfttMain {
                        } else if (args[args_i].equals("-debug_list")) {
                                args_i++;
                                readStringListFromFile(debug_list, 
args[args_i]);
+                       } else if 
(args[args_i].equals("-debug_name")||args[args_i].equals("-debug_named")) {
+                               args_i++;
+                               
+                               for ( String name : 
args[args_i].split("[\\,\\;\\:]+") ) {
+                                       debug_list.add(name);
+                               }
                        } else if (args[args_i].equals("-skip_list")) {
                                args_i++;
                                readStringListFromFile(skip_list, args[args_i]);
@@ -1525,8 +1546,9 @@ public class PfttMain {
                        } else if (args[args_i].equals("-src_pack")) {
                                source_pack = args[args_i++];
                        } else if (args[args_i].equals("-debug_pack")) {
-                               if (null == ( debug_pack = 
PhpDebugPack.open(p.host, args[args_i++]))) {
-                                       System.err.println("PFTT: debug-pack 
not found: "+args[args_i-1]);
+                               args_i++;
+                               if (null == ( debug_pack = 
PhpDebugPack.open(p.host, args[args_i]))) {
+                                       System.err.println("PFTT: debug-pack 
not found: "+args[args_i]);
                                        System.exit(-250);
                                }
                        } else if 
(args[args_i].equals("-h")||args[args_i].equals("--h")||args[args_i].equals("-help")||args[args_i].equals("--help"))
 {
@@ -1639,6 +1661,7 @@ public class PfttMain {
                                                return;
                                        }
                                        
+                                       warnDebugAll(cm);
                                        checkUAC(is_uac, false, config, cm, 
EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION);
                                        
                                        PhpBuild[] builds = newBuilds(cm, 
p.host, args[args_i+1]);
@@ -1714,6 +1737,7 @@ public class PfttMain {
                                                System.exit(-255);
                                                return;
                                        }
+                                       warnDebugAll(cm);
                                        
                                        PhpBuild[] builds = newBuilds(cm, 
p.host, args[args_i+1]);
                                        
diff --git a/src/com/mostc/pftt/model/core/PhpDebugPack.java 
b/src/com/mostc/pftt/model/core/PhpDebugPack.java
index 55b5dfa..f626281 100644
--- a/src/com/mostc/pftt/model/core/PhpDebugPack.java
+++ b/src/com/mostc/pftt/model/core/PhpDebugPack.java
@@ -1,5 +1,7 @@
 package com.mostc.pftt.model.core;
 
+import java.io.File;
+
 import com.github.mattficken.io.StringUtil;
 import com.mostc.pftt.host.AHost;
 import com.mostc.pftt.model.DebugPack;
@@ -16,6 +18,7 @@ public class PhpDebugPack extends DebugPack {
        }
 
        public static PhpDebugPack open(AHost host, String path) {
+               path = new File(path).getAbsolutePath();
                if (StringUtil.endsWithIC(path, ".zip")) {
                        // automatically decompress
                        String zip_file = path;
diff --git a/src/com/mostc/pftt/model/core/PhptTestCase.java 
b/src/com/mostc/pftt/model/core/PhptTestCase.java
index 69345ac..e6e6721 100644
--- a/src/com/mostc/pftt/model/core/PhptTestCase.java
+++ b/src/com/mostc/pftt/model/core/PhptTestCase.java
@@ -125,7 +125,7 @@ public class PhptTestCase extends TestCase {
        private PhptSourceTestPack test_pack;
        private CharsetICU common_charset;
        private CharsetEncoder ce;
-       public boolean redo; // TODO temp
+       public boolean redo = false; // TODO temp
        
        /** loads the named PHPT test from the given PhptSourceTestPack
         * 
diff --git 
a/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java 
b/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java
index 85cac14..540a864 100644
--- 
a/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java
+++ 
b/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java
@@ -172,7 +172,7 @@ public abstract class 
AbstractManagedProcessesWebServerManager extends WebServer
                                if (web==null)
                                        break; // fall through to returning 
CrashedWebServerInstance
                                
-                               handle = host.execThread(web.getCmdString(), 
web.getEnv(), docroot);
+                               handle = host.execThread(web.getCmdString(), 
web.getEnv(), docroot, false);
                                
                                final AHost.ExecHandle handlef = handle;
                                                                
diff --git a/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java 
b/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java
index 0843d4c..ed89e2c 100644
--- a/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java
+++ b/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java
@@ -5,10 +5,13 @@ import java.util.Map;
 import com.mostc.pftt.host.AHost;
 import com.mostc.pftt.host.AHost.ExecHandle;
 import com.mostc.pftt.host.ExecOutput;
+import com.mostc.pftt.host.LocalHost.LocalExecHandle;
 import com.mostc.pftt.model.core.EExecutableType;
 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;
 
 public class CliSAPIInstance extends SAPIInstance {
        protected final PhpBuild build;
@@ -59,11 +62,18 @@ public class CliSAPIInstance extends SAPIInstance {
        }
 
        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);
+               return host.execOut(createPhpCommand(exe_type, php_filename, 
extra_args), timeout_sec, env, chdir, true);
        }
        
-       public ExecHandle execThread(String cmd, String chdir, 
Map<String,String> env, byte[] stdin_data) throws Exception {
-               return host.execThread(cmd, env, chdir, stdin_data);
+       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);
+               }
+               return eh;
        }
        
        @Override
diff --git a/src/com/mostc/pftt/model/smoke/RequiredExtensionsSmokeTest.java 
b/src/com/mostc/pftt/model/smoke/RequiredExtensionsSmokeTest.java
index 2321200..f1482a8 100644
--- a/src/com/mostc/pftt/model/smoke/RequiredExtensionsSmokeTest.java
+++ b/src/com/mostc/pftt/model/smoke/RequiredExtensionsSmokeTest.java
@@ -3,6 +3,7 @@ package com.mostc.pftt.model.smoke;
 import com.github.mattficken.io.StringUtil;
 import com.mostc.pftt.host.AHost;
 import com.mostc.pftt.host.Host;
+import com.mostc.pftt.model.app.PhpUnitTestCase;
 import com.mostc.pftt.model.core.ESAPIType;
 import com.mostc.pftt.model.core.PhpBuild;
 import com.mostc.pftt.model.core.PhpIni;
@@ -141,7 +142,7 @@ public class RequiredExtensionsSmokeTest extends SmokeTest {
                ini.putMulti(PhpIni.OUTPUT_BUFFERING, PhpIni.ON);
                
                // CRITICAL PhpUnit tests w/ remote fs scenarios
-               ini.putSingle("max_execution_time", 60); // default is 30
+               ini.putSingle("max_execution_time", 
PhpUnitTestCase.MAX_TEST_TIME_SECONDS); // default is 30
                
                //
                // CRITICAL
diff --git a/src/com/mostc/pftt/results/AbstractPhptRW.java 
b/src/com/mostc/pftt/results/AbstractPhptRW.java
index d2edf78..6703342 100644
--- a/src/com/mostc/pftt/results/AbstractPhptRW.java
+++ b/src/com/mostc/pftt/results/AbstractPhptRW.java
@@ -31,6 +31,25 @@ public abstract class AbstractPhptRW extends 
AbstractTestResultRW {
                if (status==EPhptTestStatus.FAIL) {
                        // TODO temp
                        
+
+                       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");
+                       
names.remove("ext/standard/tests/array/array_merge_recursive_variation10.phpt");
+                       
names.remove("ext/standard/tests/array/array_rand_basic2.phpt");
+                       
names.remove("ext/standard/tests/array/current_variation3.phpt");
+                       
names.remove("ext/standard/tests/array/max_variation1.phpt");
+                       names.remove("ext/standard/tests/array/min_basic.phpt");
+                       
names.remove("ext/standard/tests/strings/strncasecmp_variation5.phpt");
+                       
names.remove("ext/standard/tests/strings/strncasecmp_variation8.phpt");
+                       
names.remove("ext/standard/tests/strings/strrchr_variation6.phpt");
+                       names.remove("zend/tests/022.phpt");
+                       names.remove("zend/tests/023.phpt");
+                       names.remove("zend/tests/object_handlers.phpt");
+                       
names.remove("ext/standard/tests/array/sizeof_error.phpt");
+                       
names.remove("ext/standard/tests/network/http-stream.phpt");
+                       names.remove("sapi/cli/tests/bug65633.phpt");
+                       names.remove("tests/lang/bug32924.phpt");
                        names.remove("ext/mbstring/tests/bug43841.phpt");
                        
names.remove("ext/mbstring/tests/mb_strrchr_error2.phpt");
                        
names.remove("ext/mbstring/tests/mb_substr_count_variation1.phpt");
diff --git a/src/com/mostc/pftt/results/LocalConsoleManager.java 
b/src/com/mostc/pftt/results/LocalConsoleManager.java
index 4672cd0..b1ac6bd 100644
--- a/src/com/mostc/pftt/results/LocalConsoleManager.java
+++ b/src/com/mostc/pftt/results/LocalConsoleManager.java
@@ -177,6 +177,7 @@ public class LocalConsoleManager implements ConsoleManager {
        }
        
        private WeakReference<String> last_clue_msg;
+       private EPrintType last_type;
        @Override
        public void println(EPrintType type, String ctx_str, String string) {
                if (results_only)
@@ -186,7 +187,7 @@ public class LocalConsoleManager implements ConsoleManager {
                case SKIP_OPERATION: 
                case CANT_CONTINUE:
                case OPERATION_FAILED_CONTINUING:
-                       doPrintMultiline(type+": "+ctx_str+": ", string);
+                       doPrintMultiline(last_type == EPrintType.CLUE, type+": 
"+ctx_str+": ", string);
                        break;
                case WARNING:
                case CLUE:
@@ -196,17 +197,20 @@ public class LocalConsoleManager implements 
ConsoleManager {
                                if (last_str!=null && last_str.equals(string))
                                        break;
                        }
-                       doPrintMultiline(type+": "+ctx_str+": ", string);
+                       doPrintMultiline(last_type != EPrintType.CLUE, type+": 
"+ctx_str+": ", string);
                        last_clue_msg = new WeakReference<String>(string);
                        break;
                case TIP:
-                       doPrintMultiline("TIP: ", string);
+                       doPrintMultiline(last_type == EPrintType.CLUE, "TIP: ", 
string);
                        break;
                default:
-                       doPrintMultiline("PFTT: "+ctx_str+": ", string);
+                       doPrintMultiline(last_type == EPrintType.CLUE, "PFTT: 
"+ctx_str+": ", string);
                }
+               last_type = type;
        }
-       protected void doPrintMultiline(String pre, String str) {
+       protected void doPrintMultiline(boolean pre_blank, String pre, String 
str) {
+               if (pre_blank)
+                       System.out.println();
                for ( String line : StringUtil.splitLines(str))
                        System.out.println(pre+line);
        }
@@ -317,7 +321,17 @@ public class LocalConsoleManager implements ConsoleManager 
{
 
        @Override
        public boolean isInDebugList(TestCase test_case) {
-               return debug_list != null && 
debug_list.contains(test_case.getName());
+               if (debug_list==null)
+                       return false;
+               final String tc_name = test_case.getName().toLowerCase();
+               if (debug_list.contains(tc_name))
+                       return true;
+               for ( String name : debug_list ) {
+                       if (tc_name.contains(name.toLowerCase())) {
+                               return true;
+                       }
+               }
+               return false;
        }
 
        @Override
diff --git a/src/com/mostc/pftt/results/PhpResultPackWriter.java 
b/src/com/mostc/pftt/results/PhpResultPackWriter.java
index 6169a1d..e7144cb 100644
--- a/src/com/mostc/pftt/results/PhpResultPackWriter.java
+++ b/src/com/mostc/pftt/results/PhpResultPackWriter.java
@@ -48,7 +48,8 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
        protected PrintWriter global_exception_writer;
        protected LocalConsoleManager cm;
        protected PhpBuild build;
-       protected LinkedBlockingQueue<ResultQueueEntry> results;
+       //protected LinkedBlockingQueue<ResultQueueEntry> results;
+       protected LinkedList<ResultQueueEntry> results;
        protected boolean run_writer_thread = true;
        protected final PhpBuildInfo build_info;
        protected final EBuildBranch test_pack_branch;
@@ -145,7 +146,7 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
                        ex.printStackTrace();
                }
                
-               results = new LinkedBlockingQueue<ResultQueueEntry>();
+               results = new LinkedList<ResultQueueEntry>();//new 
LinkedBlockingQueue<ResultQueueEntry>();
                
                global_exception_writer = new PrintWriter(new 
FileWriter(this.telem_dir+"/GLOBAL_EXCEPTIONS.txt"));
                
@@ -156,17 +157,24 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
                                        
                                        while (run_writer_thread || 
!results.isEmpty()) {
                                                try {
-                                                       q = results.take();
+                                                       synchronized(results) {
+                                                               q = 
results.isEmpty() ? null : results.removeFirst();
+                                                       }
                                                } catch ( Exception ex ) {
                                                }
-                                               if (q==null)
+                                               if (q==null) {
+                                                       try {
+                                                               
Thread.sleep(500);
+                                                       } catch 
(InterruptedException e) {
+                                                       }
                                                        continue;
+                                               }
                                                try {
                                                        q.handle();
                                                } catch ( Exception ex ) {
-                                                       ex.printStackTrace();
+                                                       // TODO temp 
ex.printStackTrace();
                                                }
-                                               q = null;
+                                               q = null; // for gc
                                        }
                                }
                        };
@@ -537,17 +545,26 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
        
        @Override
        public void notifyStart(AHost host, ScenarioSetSetup 
scenario_set_setup, PhptSourceTestPack src_test_pack, PhptTestCase test_case) {
-               results.add(new PhptTestStartQueueEntry(host, 
scenario_set_setup, src_test_pack, test_case.getName()));
+               PhptTestStartQueueEntry e = new PhptTestStartQueueEntry(host, 
scenario_set_setup, src_test_pack, test_case.getName());
+               synchronized(results) {
+                       results.add(e);
+               }
        }
        
        @Override
        public void notifyStart(AHost host, ScenarioSetSetup 
scenario_set_setup, PhpUnitSourceTestPack src_test_pack, PhpUnitTestCase 
test_case) {
-               results.add(new PhpUnitTestStartQueueEntry(host, 
scenario_set_setup, src_test_pack, test_case.getName()));
+               PhpUnitTestStartQueueEntry e = new 
PhpUnitTestStartQueueEntry(host, scenario_set_setup, src_test_pack, 
test_case.getName());
+               synchronized(results) {
+                       results.add(e);
+               }
        }
        
        @Override
        public void notifyStart(AHost host, ScenarioSetSetup 
scenario_set_setup, UITestPack test_pack, String web_browser_name_and_version, 
String test_name) {
-               results.add(new UITestStartQueueEntry(host, scenario_set_setup, 
test_pack, web_browser_name_and_version, test_name));
+               UITestStartQueueEntry e = new UITestStartQueueEntry(host, 
scenario_set_setup, test_pack, web_browser_name_and_version, test_name);
+               synchronized(e) {
+                       results.add(e);
+               }
        }
        
        public File getResultPackPath() {
@@ -559,7 +576,10 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
        }
        
        public void addResult(AHost this_host, ScenarioSetSetup 
this_scenario_set_setup, String test_name, String comment, EUITestStatus 
status, String verified_html, byte[] screenshot_png, UITestPack test_pack, 
String web_browser_name_and_version, String sapi_output, String sapi_config) {
-               results.add(new UIResultQueueEntry(this_host, 
this_scenario_set_setup, test_name, comment, status, verified_html, 
screenshot_png, test_pack, web_browser_name_and_version, sapi_output, 
sapi_config));
+               UIResultQueueEntry e = new UIResultQueueEntry(this_host, 
this_scenario_set_setup, test_name, comment, status, verified_html, 
screenshot_png, test_pack, web_browser_name_and_version, sapi_output, 
sapi_config);
+               synchronized(e) {
+                       results.add(e);
+               }
        }
        
        public void addTestException(AHost this_host, ScenarioSetSetup 
this_scenario_set_setup, PhptTestCase test_file, Throwable ex, Object a) {
@@ -591,7 +611,10 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
        @Override
        public void addResult(AHost this_host, ScenarioSetSetup 
this_scenario_set_setup, PhptSourceTestPack src_test_pack, PhptTestResult 
result) {
                // enqueue result to be handled by another thread to avoid 
delaying every phpt thread
-               results.add(new PhptResultQueueEntry(this_host, 
this_scenario_set_setup, src_test_pack, result));
+               PhptResultQueueEntry e = new PhptResultQueueEntry(this_host, 
this_scenario_set_setup, src_test_pack, result);
+               synchronized(results) {
+                       results.add(e);
+               }
        }
        
        // TODO rename these
@@ -630,7 +653,10 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
        
        @Override
        public void addResult(AHost host, ScenarioSetSetup scenario_set_setup, 
PhpUnitTestResult result) {
-               results.add(new PhpUnitResultQueueEntry(host, 
scenario_set_setup, result));
+               PhpUnitResultQueueEntry e = new PhpUnitResultQueueEntry(host, 
scenario_set_setup, result);
+               synchronized(results) {
+                       results.add(e);
+               }
        }
        
        protected class NotifyPhptFinishedEntry extends PhptQueueEntry {
@@ -647,7 +673,10 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
        }
        
        public void notifyPhptFinished(AHost host, ScenarioSetSetup 
scenario_set, PhptSourceTestPack src_test_pack) {
-               results.add(new NotifyPhptFinishedEntry(host, scenario_set, 
src_test_pack));
+               NotifyPhptFinishedEntry e = new NotifyPhptFinishedEntry(host, 
scenario_set, src_test_pack);
+               synchronized(e) {
+                       results.add(e);
+               }
        }
        
        protected class NotifyPhpUnitFinishedEntry extends PhpUnitQueueEntry {
@@ -666,7 +695,10 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
        }
        
        public void notifyPhpUnitFinished(AHost host, ScenarioSetSetup 
scenario_set_setup, PhpUnitSourceTestPack src_test_pack) {
-               results.add(new NotifyPhpUnitFinishedEntry(host, 
scenario_set_setup, src_test_pack));
+               NotifyPhpUnitFinishedEntry e = new 
NotifyPhpUnitFinishedEntry(host, scenario_set_setup, src_test_pack);
+               synchronized(results) {
+                       results.add(e);
+               }
        }
        
        protected class NotifyUITestFinishedEntry extends UIQueueEntry {
@@ -684,7 +716,10 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
        }
        
        public void notifyUITestFinished(AHost host, ScenarioSetSetup 
scenario_set_setup, UITestPack test_pack, String web_browser_name_and_version) {
-               results.add(new NotifyUITestFinishedEntry(host, 
scenario_set_setup, test_pack, web_browser_name_and_version));
+               NotifyUITestFinishedEntry e = new 
NotifyUITestFinishedEntry(host, scenario_set_setup, test_pack, 
web_browser_name_and_version);
+               synchronized(results) {
+                       results.add(e);
+               }
        }
        
        protected class CloseQueueEntry extends ResultQueueEntry {
@@ -703,7 +738,11 @@ public class PhpResultPackWriter extends PhpResultPack 
implements ITestResultRec
        
        public void close(boolean block) {
                if (run_writer_thread) {
-                       results.add(new CloseQueueEntry());
+                       run_writer_thread = false;
+                       CloseQueueEntry e = new CloseQueueEntry();
+                       synchronized(results) {
+                               results.add(e);
+                       }
                        if (block) {
                                while (!results.isEmpty()) {
                                        if (!TimerUtil.trySleepMillis(100))
diff --git a/src/com/mostc/pftt/results/PhptResultReader.java 
b/src/com/mostc/pftt/results/PhptResultReader.java
index 65a8024..6d7cef1 100644
--- a/src/com/mostc/pftt/results/PhptResultReader.java
+++ b/src/com/mostc/pftt/results/PhptResultReader.java
@@ -60,7 +60,7 @@ public class PhptResultReader extends AbstractPhptRW {
        
        protected class StatusListEntry {
                /** count reported in tally file. should match test_names#size 
*/
-               protected int count;
+               protected final int count;
                /** list of tests... test_names#size should == count */
                protected final ArrayList<String> test_names;
                
@@ -83,9 +83,9 @@ public class PhptResultReader extends AbstractPhptRW {
                        if (count!=test_names.size()) {
                                cm.println(EPrintType.WARNING, getClass(), 
"Count does not match list of test names... previous test run interrupted?");
                                
-                               if (count==0)
+                               /* TODO temp if (count==0)
                                        // fallback
-                                       count = test_names.size();
+                                       count = test_names.size(); */
                        }
                }
                
diff --git a/src/com/mostc/pftt/results/PhptResultWriter.java 
b/src/com/mostc/pftt/results/PhptResultWriter.java
index c06bbf8..382a561 100644
--- a/src/com/mostc/pftt/results/PhptResultWriter.java
+++ b/src/com/mostc/pftt/results/PhptResultWriter.java
@@ -203,7 +203,7 @@ public class PhptResultWriter extends AbstractPhptRW {
                                out.close();
                                
                        } catch ( Exception ex ) {
-                               ex.printStackTrace();
+                               // TODO temp ex.printStackTrace();
                                
cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), 
"handleResult", ex, "", dir, test_case_base_name);
                        }
                }
diff --git a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java 
b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
index ac63b3b..f902f2b 100644
--- a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
@@ -239,7 +239,7 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                        cm.println(EPrintType.SKIP_OPERATION, getClass(), 
"Scenario Set not implemented: "+scenario_set_setup.getNameWithVersionInfo());
                        close();
                        return false;
-               } else if (!scenario_set.isSupported(cm, runner_host, build)) {
+               } else if (!scenario_set.isSupported(cm, runner_host, build, 
getScenarioSetPermutationLayer())) {
                        // ex: PHP NTS build can't be run with Apache
                        cm.println(EPrintType.SKIP_OPERATION, getClass(), 
"Scenario Set not supported: "+scenario_set+" host: "+runner_host+" build: 
"+build);
                        close();
@@ -551,13 +551,12 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                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)
-                       init_thread_count = Math.max(1, init_thread_count / 4);
+                       init_thread_count = max_thread_count = Math.max(1, 
init_thread_count / 4);
                }
                if (cm.getThreadCount()>0) {
                        // let user override SAPI and debug thread count checks
-                       init_thread_count = cm.getThreadCount();
+                       init_thread_count = max_thread_count = 
cm.getThreadCount();
                } 
-               
                checkThreadCountLimit();
        } // end protected void decideThreadCount
        
@@ -865,10 +864,9 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                                        try {
                                                group_key.prepare();
                                                
+                                               // -debug_all and -debug_list 
and -debug_named console options
+                                               final boolean debugger_attached 
= (cm.isDebugAll() || cm.isInDebugList(test_case));
                                                if (parallel) {
-                                                       // -debug_all and 
-debug_list console options
-                                                       final boolean 
debugger_attached = (cm.isDebugAll() || cm.isInDebugList(test_case));
-                                                       
                                                        
                                                        // TODO create better 
mechanism to send `sa` to each test case runner
                                                        // @see 
HttpTestCaseRunner#http_execute which calls #notifyCrash
@@ -921,13 +919,14 @@ 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);
+                                               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) {
+                                                               
Math.abs(System.currentTimeMillis() - test_run_start_time.get()) < 
sapi_scenario.getFastTestTimeSeconds()*1000
+                                                               
&&threads.size()>1) {
                                                        // scale back down 
(decrease number of threads)
                                                        
cm.println(EPrintType.CLUE, getClass(), "Thread Pool: SCALE DOWN");
                                                        
Iterator<TestPackThread<T>> it = scale_up_threads.iterator();
@@ -982,7 +981,7 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                        } // end while
                } // end protected void exec_jobs
                
-               protected abstract void runTest(TestCaseGroupKey group_key, T 
test_case) throws IOException, Exception, Throwable;
+               protected abstract void runTest(TestCaseGroupKey group_key, T 
test_case, boolean debugger_attached) throws IOException, Exception, Throwable;
 
                @Override
                protected boolean canCreateNewThread() {
diff --git a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java 
b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
index a3f0e27..af37817 100644
--- a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
+++ b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
@@ -450,11 +450,6 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
         * @throws Throwable
         */
        protected void evalTest(String output, Charset charset) throws 
Throwable {
-               if (true) {
-                       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, getSAPIOutput(), getSAPIConfig(), 
code_coverage)));
-                       
-                       return;
-               }
                // Windows: line endings are already made consistent by 
AHost#exec*
                String expected, preoverride_actual = null;
        
diff --git a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java 
b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
index d7ef6a5..a57e6f5 100644
--- a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
@@ -40,13 +40,15 @@ import com.mostc.pftt.scenario.ScenarioSetSetup;
 
 public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 {
        protected final CliSAPIInstance sapi;
+       protected final 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) {
+       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);
                this.sapi = sapi;
+               this.debugger_attached = debugger_attached;
        }
        
        @Override
@@ -211,10 +213,14 @@ public class CliPhptTestCaseRunner extends 
AbstractPhptTestCaseRunner2 {
                // execute PHP to execute the TEST code ... allow up to 60 
seconds for execution
                //      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(),
+                                       scenario_set.getScenarioSet(),
                                        test_cmd, 
                                        active_test_pack.getStorageDirectory(),
                                        env,
-                                       stdin_post
+                                       stdin_post,
+                                       debugger_attached
                                );
                StringBuilder output_sb = new StringBuilder(1024);
                
@@ -234,7 +240,6 @@ public class CliPhptTestCaseRunner extends 
AbstractPhptTestCaseRunner2 {
        @Override
        protected String executeTest() throws Exception { 
                String output_str = doExecuteTest();
-               System.out.println("237 "+test_case);
                if (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
@@ -272,20 +277,20 @@ public class CliPhptTestCaseRunner extends 
AbstractPhptTestCaseRunner2 {
                return output_str;
        } // end String executeTest
        
-       @Override
+       /*@Override
        protected PhptTestResult notifyNotPass(PhptTestResult result) {
                // TODO temp
                // try FAIL TIMEOUT XFAIL_WORKS
-               /*if (result.status!=EPhptTestStatus.CRASH && 
test_case.redo!=true) {
+               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 {*/
+               } else {
                        return super.notifyNotPass(result);
-               //}
-       }
+               }
+       }*/
        
        @Override
        protected void executeClean() throws Exception {
diff --git a/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java 
b/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java
index 8cc3444..89c434b 100644
--- a/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java
@@ -186,7 +186,7 @@ public class LocalPhpUnitTestPackRunner extends 
AbstractLocalTestPackRunner<PhpU
                }
 
                @Override
-               protected void runTest(TestCaseGroupKey group_key, 
PhpUnitTestCase test_case) throws IOException, Exception, Throwable {
+               protected void runTest(TestCaseGroupKey group_key, 
PhpUnitTestCase test_case, boolean debugger_attached) throws IOException, 
Exception, Throwable {
                        r = sapi_scenario.createPhpUnitTestCaseRunner(
                                        this,
                                        group_key,
diff --git a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java 
b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java
index 5aeb559..12743cf 100644
--- a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java
@@ -255,8 +255,8 @@ public class LocalPhptTestPackRunner extends 
AbstractLocalTestPackRunner<PhptAct
                }
 
                @Override
-               protected void runTest(TestCaseGroupKey group_key, PhptTestCase 
test_case) throws IOException, Exception, Throwable {
-                       r = sapi_scenario.createPhptTestCaseRunner(this, 
group_key, test_case, cm, twriter, runner_host, scenario_set_setup, build, 
src_test_pack, active_test_pack, xdebug);
+               protected void runTest(TestCaseGroupKey group_key, PhptTestCase 
test_case, boolean debugger_attached) throws IOException, Exception, Throwable {
+                       r = sapi_scenario.createPhptTestCaseRunner(this, 
group_key, test_case, cm, twriter, runner_host, scenario_set_setup, build, 
src_test_pack, active_test_pack, xdebug, debugger_attached);
                        twriter.notifyStart(runner_host, scenario_set_setup, 
src_test_pack, test_case);
                        r.runTest(cm, this, LocalPhptTestPackRunner.this);
                }
diff --git a/src/com/mostc/pftt/scenario/APCScenario.java 
b/src/com/mostc/pftt/scenario/APCScenario.java
index 922e01f..694507a 100644
--- a/src/com/mostc/pftt/scenario/APCScenario.java
+++ b/src/com/mostc/pftt/scenario/APCScenario.java
@@ -5,6 +5,7 @@ import com.mostc.pftt.model.core.EAcceleratorType;
 import com.mostc.pftt.model.core.PhpBuild;
 import com.mostc.pftt.model.core.PhpIni;
 import com.mostc.pftt.results.ConsoleManager;
+import com.mostc.pftt.results.EPrintType;
 
 /** tests the APC code cache (NOT IMPLEMENTED)
  * 
@@ -47,8 +48,14 @@ public class APCScenario extends CodeCacheScenario {
        }
        
        @Override
-       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set) {
-               return !scenario_set.contains(IISScenario.class);
+       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) {
+               if (scenario_set.contains(IISScenario.class)) {
+                       if (cm!=null) {
+                               cm.println(EPrintType.CLUE, getClass(), "Can 
NOT run this with IIS Scenario");
+                       }
+                       return false;
+               }
+               return true;
        }
 
 } // end public class APCScenario
diff --git a/src/com/mostc/pftt/scenario/APCUScenario.java 
b/src/com/mostc/pftt/scenario/APCUScenario.java
index 75ec294..fee8128 100644
--- a/src/com/mostc/pftt/scenario/APCUScenario.java
+++ b/src/com/mostc/pftt/scenario/APCUScenario.java
@@ -4,6 +4,7 @@ import com.mostc.pftt.host.Host;
 import com.mostc.pftt.model.core.PhpBuild;
 import com.mostc.pftt.model.core.PhpIni;
 import com.mostc.pftt.results.ConsoleManager;
+import com.mostc.pftt.results.EPrintType;
 
 /** User caching, not code caching component from APC. APCU can be used along 
side Opcache.
  *
@@ -27,8 +28,13 @@ public class APCUScenario extends UserCacheScenario {
        }
        
        @Override
-       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set) {
-               return !scenario_set.contains(IISScenario.class);
+       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) {
+               if (scenario_set.contains(ApacheScenario.class))
+                       return true;
+               if (cm!=null) {
+                       cm.println(EPrintType.CLUE, getClass(), "Must be run 
with Apache Scenario");
+               }
+               return false;
        }
 
 }
diff --git a/src/com/mostc/pftt/scenario/ApacheModPHPScenario.java 
b/src/com/mostc/pftt/scenario/ApacheModPHPScenario.java
index 1d2805b..dae154d 100644
--- a/src/com/mostc/pftt/scenario/ApacheModPHPScenario.java
+++ b/src/com/mostc/pftt/scenario/ApacheModPHPScenario.java
@@ -30,11 +30,14 @@ public class ApacheModPHPScenario extends ApacheScenario {
        }
        
        @Override
-       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set) {
-               if (build.isTS(host)||!host.isWindows())
+       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) {
+               if (!host.isWindows()) 
                        return true;
-               if (cm!=null)
+               if (build.isTS(host))
+                       return true;
+               if (cm!=null) {
                        cm.println(EPrintType.CLUE, getClass(), "Must only use 
a TS build of PHP with Apache");
+               }
                return false;
        }
 
diff --git a/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java 
b/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
index d435de1..198c822 100644
--- a/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
+++ b/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
@@ -19,6 +19,7 @@ import com.mostc.pftt.model.core.PhptTestCase;
 import com.mostc.pftt.model.sapi.BuiltinWebServerManager;
 import com.mostc.pftt.model.sapi.TestCaseGroupKey;
 import com.mostc.pftt.results.ConsoleManager;
+import com.mostc.pftt.results.EPrintType;
 import com.mostc.pftt.results.ITestResultReceiver;
 import com.mostc.pftt.results.PhptTestResult;
 import com.mostc.pftt.runner.AbstractPhpUnitTestCaseRunner;
@@ -48,8 +49,14 @@ public class BuiltinWebServerScenario extends 
WebServerScenario {
         * 
         */
        @Override
-       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set) {
-               return !build.is53(cm, host);
+       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) {
+               if (build.is53(cm, host)) {
+                       if (cm!=null) {
+                               cm.println(EPrintType.CLUE, getClass(), 
"Builtin Web is not supported by PHP 5.3");
+                       }
+                       return false;
+               }
+               return true;
        }
 
        @Override
@@ -263,7 +270,7 @@ public class BuiltinWebServerScenario extends 
WebServerScenario {
        }
        
        @Override
-       public AbstractPhptTestCaseRunner createPhptTestCaseRunner(PhptThread 
thread, TestCaseGroupKey group_key, PhptTestCase test_case, ConsoleManager cm, 
ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set_setup, 
PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack 
active_test_pack, boolean xdebug) {
+       public AbstractPhptTestCaseRunner createPhptTestCaseRunner(PhptThread 
thread, TestCaseGroupKey group_key, PhptTestCase test_case, ConsoleManager cm, 
ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set_setup, 
PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack 
active_test_pack, boolean xdebug, boolean debugger_attached) {
                return new BuiltinWebHttpPhptTestCaseRunner(xdebug, this, 
group_key.getPhpIni(), group_key.getEnv(), params, httpproc, httpexecutor, 
smgr, thread.getThreadWebServerInstance(), thread, test_case, cm, twriter, 
host, scenario_set_setup, build, src_test_pack, active_test_pack);
        }
        
diff --git a/src/com/mostc/pftt/scenario/CLIScenario.java 
b/src/com/mostc/pftt/scenario/CLIScenario.java
index 2041301..89046c7 100644
--- a/src/com/mostc/pftt/scenario/CLIScenario.java
+++ b/src/com/mostc/pftt/scenario/CLIScenario.java
@@ -52,8 +52,8 @@ public class CliScenario extends SAPIScenario {
        public AbstractPhptTestCaseRunner createPhptTestCaseRunner(
                        PhptThread thread, TestCaseGroupKey group_key, 
PhptTestCase test_case,
                        ConsoleManager cm, ITestResultReceiver twriter, AHost 
host, ScenarioSetSetup scenario_set_setup,
-                       PhpBuild build, PhptSourceTestPack src_test_pack, 
PhptActiveTestPack active_test_pack, boolean xdebug) {
-               return new CliPhptTestCaseRunner(xdebug, this, 
((CliTestCaseGroupKey)group_key).getCliSAPIInstance(), group_key.getPhpIni(), 
thread, test_case, cm, twriter, host, scenario_set_setup, build, src_test_pack, 
active_test_pack);
+                       PhpBuild build, PhptSourceTestPack src_test_pack, 
PhptActiveTestPack active_test_pack, boolean xdebug, boolean debugger_attached) 
{
+               return new CliPhptTestCaseRunner(xdebug, this, 
((CliTestCaseGroupKey)group_key).getCliSAPIInstance(), group_key.getPhpIni(), 
thread, test_case, cm, twriter, host, scenario_set_setup, build, src_test_pack, 
active_test_pack, debugger_attached);
        }
        
        @Override
diff --git a/src/com/mostc/pftt/scenario/CodeCacheScenario.java 
b/src/com/mostc/pftt/scenario/CodeCacheScenario.java
index 329c58c..cb9f727 100644
--- a/src/com/mostc/pftt/scenario/CodeCacheScenario.java
+++ b/src/com/mostc/pftt/scenario/CodeCacheScenario.java
@@ -19,7 +19,7 @@ public abstract class CodeCacheScenario extends INIScenario {
        public abstract EAcceleratorType getAcceleratorType();
        
        @Override
-       public abstract boolean isSupported(ConsoleManager cm, Host host, 
PhpBuild build, ScenarioSet scenario_set);
+       public abstract boolean isSupported(ConsoleManager cm, Host host, 
PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer);
        
        @Override
        public abstract IScenarioSetup setup(ConsoleManager cm, Host host, 
PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer);
diff --git a/src/com/mostc/pftt/scenario/MSSQLScenario.java 
b/src/com/mostc/pftt/scenario/MSSQLScenario.java
index 0b51738..e47512b 100644
--- a/src/com/mostc/pftt/scenario/MSSQLScenario.java
+++ b/src/com/mostc/pftt/scenario/MSSQLScenario.java
@@ -13,6 +13,7 @@ import com.mostc.pftt.model.core.EBuildType;
 import com.mostc.pftt.model.core.PhpBuild;
 import com.mostc.pftt.model.core.PhpIni;
 import com.mostc.pftt.results.ConsoleManager;
+import com.mostc.pftt.results.EPrintType;
 
 /** Tests the mssql and pdo_mssql extensions against a Microsoft SQL Server. 
(NOT IMPLEMENTED)
  * 
@@ -92,9 +93,14 @@ public class MSSQLScenario extends DatabaseScenario {
        } // end public static enum EMSSQLVersion
        
        @Override
-       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set) {
+       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) {
                // PHP driver for MS SQL currently only supported on Windows
-               return host.isWindows();
+               if (host.isWindows())
+                       return true;
+               if (cm!=null) {
+                       cm.println(EPrintType.CLUE, getClass(), "Only supported 
on Windows");
+               }
+               return false;
        }
        
        @Override
diff --git a/src/com/mostc/pftt/scenario/MySQLScenario.java 
b/src/com/mostc/pftt/scenario/MySQLScenario.java
index 447c841..3157f01 100644
--- a/src/com/mostc/pftt/scenario/MySQLScenario.java
+++ b/src/com/mostc/pftt/scenario/MySQLScenario.java
@@ -202,7 +202,7 @@ public class MySQLScenario extends DatabaseScenario {
                                        final String cmd = 
"\""+mysql_dir+"\\bin\\mysqld\" --standalone --console 
--bind-address="+hostname+" --port="+port+" --datadir="+datadir;
                                        
                                        cm.println(EPrintType.IN_PROGRESS, 
getClass(), "Starting MySQL in standalone mode (directly, using default 
config)...");
-                                       mysqld_handle = 
((AHost)host).execThread(cmd);
+                                       mysqld_handle = 
((AHost)host).execThread(cmd, null, null, null, true);
                                        
                                        // wait for server to output that is 
running before checking below
                                        while (mysqld_handle.isRunning()) {
@@ -259,7 +259,7 @@ public class MySQLScenario extends DatabaseScenario {
                                cm.println(EPrintType.IN_PROGRESS, getClass(), 
"Stopping production MySQL Windows Service...");
                                host.execElevated(cm, getClass(), "net stop 
MySQL56", AHost.ONE_MINUTE);
                        } else {
-                               cm.println(EPrintType.IN_PROGRESS, getClass(), 
"Stopping MySQL stanadlone process");
+                               cm.println(EPrintType.IN_PROGRESS, getClass(), 
"Stopping MySQL standalone process");
                                mysqld_handle.close(cm, true);
                        }
                }
diff --git a/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java 
b/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java
index 6799005..fe5af4a 100644
--- a/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java
+++ b/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java
@@ -81,7 +81,7 @@ public class NoCodeCacheScenario extends CodeCacheScenario {
        }
 
        @Override
-       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set) {
+       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) {
                return true;
        }
 
diff --git a/src/com/mostc/pftt/scenario/OpcacheScenario.java 
b/src/com/mostc/pftt/scenario/OpcacheScenario.java
index b83782e..8bc7c90 100644
--- a/src/com/mostc/pftt/scenario/OpcacheScenario.java
+++ b/src/com/mostc/pftt/scenario/OpcacheScenario.java
@@ -190,8 +190,14 @@ public class OpcacheScenario extends CodeCacheScenario {
        } // end protected DllVersion getDllPath
        
        @Override
-       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set) {
-               return getDllPath(cm, host, build) != null;
+       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) {
+               if (getDllPath(cm, host, build) == null) {
+                       if (cm!=null) {
+                               cm.println(EPrintType.CLUE, getClass(), "Unable 
to find Opcache DLL or SO. Can NOT run this Scenario.");
+                       }
+                       return false;
+               }
+               return true;
        }
 
        public class OpcacheSetup extends SimpleScenarioSetup {
diff --git a/src/com/mostc/pftt/scenario/SAPIScenario.java 
b/src/com/mostc/pftt/scenario/SAPIScenario.java
index 131ed60..d1ff963 100644
--- a/src/com/mostc/pftt/scenario/SAPIScenario.java
+++ b/src/com/mostc/pftt/scenario/SAPIScenario.java
@@ -81,9 +81,10 @@ public abstract class SAPIScenario extends 
AbstractSerialScenario {
         * @param src_test_pack
         * @param active_test_pack
         * @param xdebug TODO
+        * @param debugger_attached TODO
         * @return
         */
-       public abstract AbstractPhptTestCaseRunner 
createPhptTestCaseRunner(PhptThread thread, TestCaseGroupKey group_key, 
PhptTestCase test_case, ConsoleManager cm, ITestResultReceiver twriter, AHost 
host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhptSourceTestPack 
src_test_pack, PhptActiveTestPack active_test_pack, boolean xdebug);
+       public abstract AbstractPhptTestCaseRunner 
createPhptTestCaseRunner(PhptThread thread, TestCaseGroupKey group_key, 
PhptTestCase test_case, ConsoleManager cm, ITestResultReceiver twriter, AHost 
host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhptSourceTestPack 
src_test_pack, PhptActiveTestPack active_test_pack, boolean xdebug, boolean 
debugger_attached);
        
        public void close(ConsoleManager cm, boolean debug) {
                
diff --git a/src/com/mostc/pftt/scenario/SSLSocketScenario.java 
b/src/com/mostc/pftt/scenario/SSLSocketScenario.java
index 5d6fe03..e1b0a30 100644
--- a/src/com/mostc/pftt/scenario/SSLSocketScenario.java
+++ b/src/com/mostc/pftt/scenario/SSLSocketScenario.java
@@ -3,6 +3,7 @@ package com.mostc.pftt.scenario;
 import com.mostc.pftt.host.Host;
 import com.mostc.pftt.model.core.PhpBuild;
 import com.mostc.pftt.results.ConsoleManager;
+import com.mostc.pftt.results.EPrintType;
 
 /** Scenario for testing AbstractWebServerScenario using encrypted SSL/TLS 
sockets. (NOT IMPLEMENTED)
  *
@@ -29,9 +30,14 @@ public class SSLSocketScenario extends SocketScenario {
        }
        
        @Override
-       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set) {
+       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) {
                // only work with web server scenarios
-               return WebServerScenario.getWebServerScenario(scenario_set) != 
null;
+               if (WebServerScenario.getWebServerScenario(scenario_set) == 
null) {
+                       if (cm!=null) {
+                               cm.println(EPrintType.CLUE, getClass(), "Must 
load a web server scenario. Try adding `apache` to your -config.");
+                       }
+               }
+               return true;
        }
 
 }
diff --git a/src/com/mostc/pftt/scenario/WebServerScenario.java 
b/src/com/mostc/pftt/scenario/WebServerScenario.java
index ef27f62..6391e3c 100644
--- a/src/com/mostc/pftt/scenario/WebServerScenario.java
+++ b/src/com/mostc/pftt/scenario/WebServerScenario.java
@@ -101,7 +101,7 @@ public abstract class WebServerScenario extends 
SAPIScenario {
        }
        
        @Override
-       public AbstractPhptTestCaseRunner createPhptTestCaseRunner(PhptThread 
thread, TestCaseGroupKey group_key, PhptTestCase test_case, ConsoleManager cm, 
ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set_setup, 
PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack 
active_test_pack, boolean xdebug) {
+       public AbstractPhptTestCaseRunner createPhptTestCaseRunner(PhptThread 
thread, TestCaseGroupKey group_key, PhptTestCase test_case, ConsoleManager cm, 
ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set_setup, 
PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack 
active_test_pack, boolean xdebug, boolean debugger_attached) {
                return new HttpPhptTestCaseRunner(xdebug, this, 
group_key.getPhpIni(), group_key.getEnv(), params, httpproc, httpexecutor, 
smgr, thread.getThreadWebServerInstance(), thread, test_case, cm, twriter, 
host, scenario_set_setup, build, src_test_pack, active_test_pack);
        }
        
diff --git a/src/com/mostc/pftt/scenario/WinCacheScenario.java 
b/src/com/mostc/pftt/scenario/WinCacheScenario.java
index 19dd4a1..6a19cc4 100644
--- a/src/com/mostc/pftt/scenario/WinCacheScenario.java
+++ b/src/com/mostc/pftt/scenario/WinCacheScenario.java
@@ -5,6 +5,7 @@ import com.mostc.pftt.model.core.EAcceleratorType;
 import com.mostc.pftt.model.core.PhpBuild;
 import com.mostc.pftt.model.core.PhpIni;
 import com.mostc.pftt.results.ConsoleManager;
+import com.mostc.pftt.results.EPrintType;
 
 /** Tests the WinCache code caching extension (NOT IMPLEMENTED)
  * 
@@ -35,11 +36,17 @@ public class WinCacheScenario extends CodeCacheScenario {
        }
 
        @Override
-       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set) {
+       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) {
                // don't run WinCache on Apache-ModPHP (Apache CGI probably ok)
                //
                // not sure if its supported on scenarios other than CLI or IIS 
(so allow it)
-               return !scenario_set.contains(ApacheModPHPScenario.class);
+               if (scenario_set.contains(ApacheModPHPScenario.class)) {
+                       if (cm!=null) {
+                               cm.println(EPrintType.CLUE, getClass(), "Can 
NOT run with any Apache Scenario");
+                       }
+                       return false;
+               }
+               return true;
        }
 
        @Override
diff --git a/src/com/mostc/pftt/scenario/WinCacheUScenario.java 
b/src/com/mostc/pftt/scenario/WinCacheUScenario.java
index 2b37fe4..255c71d 100644
--- a/src/com/mostc/pftt/scenario/WinCacheUScenario.java
+++ b/src/com/mostc/pftt/scenario/WinCacheUScenario.java
@@ -1,5 +1,7 @@
 package com.mostc.pftt.scenario;
 
+import java.util.Collection;
+
 import com.github.mattficken.Overridable;
 import com.mostc.pftt.host.AHost;
 import com.mostc.pftt.host.Host;
@@ -7,6 +9,7 @@ import com.mostc.pftt.model.core.EBuildBranch;
 import com.mostc.pftt.model.core.PhpBuild;
 import com.mostc.pftt.model.core.PhpIni;
 import com.mostc.pftt.results.ConsoleManager;
+import com.mostc.pftt.results.EPrintType;
 
 /** Using only the user, object and file caching components of WinCache, NOT 
the code caching.
  * Can be used with Opcache just like APCU (but its designed for Windows, so 
for CLI and IIS
@@ -17,10 +20,29 @@ import com.mostc.pftt.results.ConsoleManager;
 
 // TODO http://us.php.net/manual/en/wincache.stats.php
 // TODO mediawiki support
-// TODO windebug integration - wincache includes the .PDB symbol file
 public abstract class WinCacheUScenario extends UserCacheScenario {
        
        @Override
+       public void addToDebugPath(ConsoleManager cm, AHost host, PhpBuild 
build, Collection<String> debug_path) {
+               try {
+                       switch(build.getVersionBranch(cm, host)) {
+                       case PHP_5_3:
+                               debug_path.add( 
host.getPfttCacheDir()+"/dep/wincache/wincache-1.3.4-5.3-nts-vc11-x86/php_wincache.pdb"
 );
+                               break;
+                       case PHP_5_4:
+                               debug_path.add( 
host.getPfttCacheDir()+"/dep/wincache/wincache-1.3.4-5.4-nts-vc11-x86/php_wincache.pdb"
 );
+                               break;
+                       case PHP_5_5:
+                       default:
+                               debug_path.add( 
host.getPfttCacheDir()+"/dep/wincache/wincache-1.3.5-5.5-nts-vc11-x86/php_wincache.pdb"
 );
+                               break;
+                       }
+               } catch ( Exception ex ) {
+                       ex.printStackTrace();
+               }
+       }
+       
+       @Override
        public int getApprovedInitialThreadPoolSize(AHost host, int threads) {
                return host.getCPUCount() * 2;
        }
@@ -78,6 +100,8 @@ public abstract class WinCacheUScenario extends 
UserCacheScenario {
                                ex.printStackTrace();
                                return SETUP_FAILED;
                        }
+                       
+                       cm.println(EPrintType.CLUE, getClass(), "Found WinCache 
in: "+dll_path);
                        first = false;
                }
                
@@ -91,17 +115,48 @@ public abstract class WinCacheUScenario extends 
UserCacheScenario {
                // DISABLE opcode caching (required to use wincacheu with 
opcache scenarios)
                ini.putSingle("wincache.ocenabled", "0");
                
-               return SETUP_SUCCESS;
+               return new WinCacheUScenarioSetup();
        }
        
+       public class WinCacheUScenarioSetup extends SimpleScenarioSetup {
+
+               @Override
+               public String getNameWithVersionInfo() {
+                       return "WinCacheU";
+               }
+
+               @Override
+               public String getName() {
+                       return "WinCacheU";
+               }
+
+               @Override
+               public void close(ConsoleManager cm) {
+                       
+               }
+               
+       } // end public class WinCacheUScenarioSetup
+       
        protected abstract void configure(PhpIni ini);
        
        @Override
-       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set) {
-               return host.isWindows() 
-                               && build.isX86() 
-                               && build.isNTS(host) 
-                               && (
+       public boolean isSupported(ConsoleManager cm, Host host, PhpBuild 
build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) {
+               if (!host.isWindows()) {
+                       if (cm!=null) {
+                               cm.println(EPrintType.CLUE, getClass(), 
"Scenario only supported on Windows.");
+                       }
+                       return false;
+               } else if (!build.isX86()) {
+                       if (cm!=null) {
+                               cm.println(EPrintType.CLUE, getClass(), "Must 
use X86 build for this scenario: "+build.getBuildPath());
+                       }
+                       return false;
+               } else if (!build.isNTS(host)) {
+                       if (cm!=null) {
+                               cm.println(EPrintType.CLUE, getClass(), "Must 
use NTS build for this scenario: "+build.getBuildPath());
+                       }
+                       return false;
+               } else if (!(
                                                // LATER? Apache FastCGI 
support on Windows
                                                
scenario_set.contains(CliScenario.class)
                                                || 
scenario_set.contains(IISScenario.class)
@@ -109,7 +164,14 @@ public abstract class WinCacheUScenario extends 
UserCacheScenario {
                                                //  web developers use 
wincache's user cache in their applications
                                                //  web developers like to use 
the builtin web server to run/test their application
                                                || 
scenario_set.contains(BuiltinWebServerScenario.class)
-                                               );
+                                               )) {
+                       if (cm!=null) {
+                               cm.println(EPrintType.CLUE, getClass(), "Must 
load CLI, IIS or Builtin Web scenario. Try adding `iis` to your -config.");
+                       }
+                       return false;
+               } else {
+                       return true;
+               }
        }
 
        @Override
diff --git a/src/com/mostc/pftt/util/DebuggerManager.java 
b/src/com/mostc/pftt/util/DebuggerManager.java
index cb81036..a717e80 100644
--- a/src/com/mostc/pftt/util/DebuggerManager.java
+++ b/src/com/mostc/pftt/util/DebuggerManager.java
@@ -75,13 +75,13 @@ public abstract class DebuggerManager {
                for ( Scenario s : scenario_set ) {
                        s.addToDebugPath(cm, host, build, paths);
                }
-               if (this.debug_path==null)
-                       this.debug_path = "";
-               for ( String path : paths ) {
-                       if (this.debug_path.length()>0)
-                               this.debug_path += host.dirSeparator();
-                       this.debug_path += path;
+               for ( int i=0 ; i < paths.size() ; i++ ) {
+                       paths.set(i, AHost.dirname(host.fixPath(paths.get(i))));
                }
+               if (StringUtil.isEmpty(this.debug_path))
+                       this.debug_path = host.joinIntoMultiplePath(paths);
+               else
+                       this.debug_path = this.debug_path + 
host.pathsSeparator() + host.joinIntoMultiplePath(paths);
        }
        
        /** guesses the source pack and debug pack locations based on build, 
unless
@@ -98,15 +98,15 @@ public abstract class DebuggerManager {
                this.found_src_debug_pack_build = build; // cache
                if (!host.isWindows()) {
                        // only PHP on Windows has standard conventions for 
naming/locating source and debug packs
-                       this.src_path = cm.getSourcePack();
-                       this.debug_path = cm.getDebugPack().getPath();
+                       this.src_path = cm==null?null:cm.getSourcePack();
+                       this.debug_path = 
cm==null||cm.getDebugPack()==null?null:cm.getDebugPack().getPath();
                        addToDebugPathFromScenarios(cm, host, build, 
scenario_set);
                        return;
                }
                
                // use any source and debug packs given on command line
-               String def_source_path = cm.getSourcePack();
-               String def_debug_path = cm.getDebugPack().getPath();
+               String def_source_path = cm==null?null:cm.getSourcePack();
+               String def_debug_path = 
cm==null||cm.getDebugPack()==null?null:cm.getDebugPack().getPath();
                
                // (in addition to )guessing the source pack and debug pack 
from the build (PHP-on-Windows follows conventions that allow this)
                try {
diff --git a/src/com/mostc/pftt/util/DllVersion.java 
b/src/com/mostc/pftt/util/DllVersion.java
index 523ee9f..dcdddcf 100644
--- a/src/com/mostc/pftt/util/DllVersion.java
+++ b/src/com/mostc/pftt/util/DllVersion.java
@@ -1,11 +1,12 @@
 package com.mostc.pftt.util;
 
 public class DllVersion {
-       protected String path;
-       protected String version;
+       protected final String base, dll_name, pdb_name, version;
        
-       public DllVersion(String path, String version) {
-               this.path = path;
+       public DllVersion(String base, String dll_name, String pdb_name, String 
version) {
+               this.base = base;
+               this.dll_name = dll_name;
+               this.pdb_name = pdb_name;
                this.version = version;
        }
        
@@ -14,6 +15,10 @@ public class DllVersion {
        }
        
        public String getPath() {
-               return path;
+               return base+"/"+dll_name;
+       }
+       
+       public String getDebugPath() {
+               return base+"/"+pdb_name;
        }
 }
diff --git a/src/com/mostc/pftt/util/HostEnvUtil.java 
b/src/com/mostc/pftt/util/HostEnvUtil.java
index 397c780..13836ca 100644
--- a/src/com/mostc/pftt/util/HostEnvUtil.java
+++ b/src/com/mostc/pftt/util/HostEnvUtil.java
@@ -53,7 +53,7 @@ public final class HostEnvUtil {
                        wer_value = "0x0";
                        em_value = "0x0";
                } else {
-                       cm.println(EPrintType.IN_PROGRESS, HostEnvUtil.class, 
"disabling Windows Error Reporting...");
+                       cm.println(EPrintType.IN_PROGRESS, HostEnvUtil.class, 
"disabling Windows Error Reporting and debugging...");
                        wer_value = "0x1";
                        em_value = "0x2";
                }
@@ -72,13 +72,15 @@ public final class HostEnvUtil {
                        regQueryAdd(cm, host, 
"HKCU\\Software\\Microsoft\\Windows\\Windows Error Reporting", "ForceQueue", 
"0x0", REG_DWORD);
                        regQueryAdd(cm, host, 
"HKCU\\Software\\Microsoft\\Windows\\Windows Error Reporting", 
"LoggingDisabled", "0x1", REG_DWORD);
                        
+                       // these keys affect builds for platform (x86 builds on 
x86 Windows; x64 builds on x64 Windows)
                        regDel(cm, host, "HKLM\\Software\\Microsoft\\Windows 
NT\\CurrentVersion\\AeDebug", "Debugger");
-                       // IMPORTANT: don't delete this key, change the value 
otherwise (if windbg installed) werfault.exe will
-                       //            still launch windbg... won't if set to 0x1
-                       regQueryAdd(cm, host, 
"HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", "Auto", 
"0x1", REG_DWORD);
+                       regQueryAdd(cm, host, 
"HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", "Auto", 
"0x0", REG_DWORD);
+                       // Important: these keys are affect x86 builds on x64 
Windows
+                       regDel(cm, host, 
"HKLM\\Software\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", 
"Debugger");
+                       regQueryAdd(cm, host, 
"HKLM\\Software\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", 
"Auto", "0x0", REG_DWORD);
                }
                
-               if ( a || b || c ) {
+               if ( a || b || c || enable_debug_prompt) {
                        // assume if registry had to be edited, the rest of 
this has to be done, otherwise assume this is all already done
                        // (avoid doing this if possible because it requires 
user to approve elevation)
                        
diff --git a/src/com/mostc/pftt/util/WinDebugManager.java 
b/src/com/mostc/pftt/util/WinDebugManager.java
index 94dc9e7..a8fb35c 100644
--- a/src/com/mostc/pftt/util/WinDebugManager.java
+++ b/src/com/mostc/pftt/util/WinDebugManager.java
@@ -54,25 +54,23 @@ public class WinDebugManager extends DebuggerManager {
                ensureFindWinDbgExe(cm, host, build);
                
                WinDebug dbg = null;
-               if (StringUtil.isEmpty(win_dbg_exe)) {
-                       // TODO tell user first time
-               } else {
-                       ensureFindSourceAndDebugPack(cm, host, scenario_set, 
build);
-                       
-                       try {
-                               dbg = new WinDebug(host, win_dbg_exe, 
toServerName(server_name), src_path, debug_path, build.getBuildPath(), 
process_id, process);
-                       } catch ( Exception ex ) {
-                               
cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), 
"newDebugger", ex, "", host, win_dbg_exe);
-                       }
-                       
-                       if (dbg != null && dbg.attached) {
-                               if (!displayed_windbg_tips) {
-                                       displayed_windbg_tips = true;
-                                       
+               ensureFindSourceAndDebugPack(cm, host, scenario_set, build);
+               
+               try {
+                       dbg = new WinDebug(host, win_dbg_exe, 
toServerName(server_name), src_path, debug_path, build.getBuildPath(), 
process_id, process);
+               } catch ( Exception ex ) {
+                       
cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), 
"newDebugger", ex, "", host, win_dbg_exe);
+               }
+               
+               if (dbg != null && dbg.attached) {
+                       if (!displayed_windbg_tips) {
+                               displayed_windbg_tips = true;
+                               
+                               if (cm!=null)
                                        displayWindebugTips(cm);
-                               }
-                       }                       
+                       }
                }
+               
                return dbg;
        }

Reply via email to