Commit:    c11e99d30eccb25a412fc1d92c3dbf5179fecf84
Author:    Matt Ficken <v-maf...@microsoft.com>         Thu, 16 May 2013 
00:35:39 -0700
Parents:   77e1af479f53999ce50b7cf0367bdb09444efaca
Branches:  master

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

Log:
check PHP_SDK environment variable


Former-commit-id: a9455c02e938349e7a08f9c5b92635fc564c6d98

Changed paths:
  M  PFTT-Client.install4j
  M  README.mdown
  M  bin/pftt_shell.cmd
  M  bin/set_env.cmd
  M  src/com/mostc/pftt/host/AHost.java
  M  src/com/mostc/pftt/host/LocalHost.java
  M  src/com/mostc/pftt/host/SSHHost.java
  M  src/com/mostc/pftt/main/PfttMain.java
  M  src/com/mostc/pftt/model/app/PhpUnitTemplate.groovy
  M  src/com/mostc/pftt/model/sapi/SharedSAPIInstancesTestCaseGroupKey.java
  M  src/com/mostc/pftt/results/PhptTestResult.java
  M  src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
  M  src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
  M  src/com/mostc/pftt/runner/AbstractTestPackRunner.java
  M  src/com/mostc/pftt/runner/CliPhpUnitTestCaseRunner.java
  M  src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
  M  src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java
  M  src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java
  M  src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java
  M  src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
  M  src/com/mostc/pftt/scenario/CLIScenario.java
  M  src/com/mostc/pftt/scenario/OpcacheScenario.java
  M  src/com/mostc/pftt/scenario/app/PHPmotionScenario.java
  M  src/com/mostc/pftt/util/ErrorUtil.java

diff --git a/PFTT-Client.install4j b/PFTT-Client.install4j
index c7f04e9..0640cbf 100644
--- a/PFTT-Client.install4j
+++ b/PFTT-Client.install4j
@@ -24,12 +24,8 @@
     <entries>
       <dirEntry mountPoint="22" file="C:/php-sdk/PFTT/current" 
overwriteMode="4" shared="false" fileMode="644" uninstallMode="0" 
overrideFileMode="false" overrideOverwriteMode="false" 
overrideUninstallMode="false" entryMode="direct" subDirectory="current" 
excludeSuffixes="*.install4j" dirMode="755" overrideDirMode="false">
         <exclude>
-          <entry location=".classpath" fileType="regular" />
-          <entry location=".directory" fileType="regular" />
           <entry location=".git" fileType="regular" />
           <entry location=".gitignore" fileType="regular" />
-          <entry location=".project" fileType="regular" />
-          <entry location=".settings" fileType="regular" />
           <entry location="cache/working" fileType="regular" />
           <entry location="hostkeys.txt" fileType="regular" />
           <entry location="javadoc.xml" fileType="regular" />
diff --git a/README.mdown b/README.mdown
index a2a8fe4..dd0ab76 100644
--- a/README.mdown
+++ b/README.mdown
@@ -9,17 +9,20 @@ test what will happen in production.
 1. Download binary from 
[http://131.107.220.66/PFTT-Results/PFTT/current/](http://131.107.220.66/PFTT-Results/PFTT/current/)
 and run it.
 2. The Install Wizard will install PFTT to your local system.
        a. If you have installed PFTT before, you MUST delete 
c:\php-sdk\PFTT\current so that it does NOT exist before running the installer
+       b. If you set the environment variable PHP_SDK, PFTT will use that 
place of C:\php-sdk (including for c:\php-sdk\PFTT\current)
+               i. You can create a batch script named 
\PFTT\current\bin\internal\set_php_sdk.cmd where you can SET PHP_SDK, which 
will be used whenever you run PFTT instead of the default PHP_SDK value
 3. If you want to test with Apache, currently you�ll need to manually 
decompress/copy it
        a. Look in c:\php-sdk\PFTT\current\cache\dep\Apache (Windows)
-       b. Each of the .7z files is a different Apache build
+       b. Each of the .7z files is a different Apache build (built by 
apachelounge.com)
        c. You�ll need to decompress them to c:\<Apache Build> so you�ll have
                i. C:\Apache244-VC11-OpenSSL1.0.1e-x64\bin\httpd.exe
                ii. C:\Apache244-VC11-OpenSSL1.0.1e-x86\bin\httpd.exe
                iii. C:\Apache244-VC9-OpenSSL0.9.8y-x86\bin\httpd.exe
                iv. C:\ Apache224-VC9-OpenSSL0.9.8y-x86\bin\httpd.exe
        d. PFTT will assume they�re there and fail if they aren�t
-       e. If the system doesn�t have the VC runtimes (ex: VC11 x64) installed, 
see: C:\php-sdk\PFTT\current\cache\dep (Windows)
+       e. If the system doesn�t have the VC runtimes (ex: VC11 x64) installed, 
see: C:\php-sdk\PFTT\current\cache\dep\VCRedist (Windows)
                i. Currently, these also must be manually installed.
+               ii. Note: for Apache-VC11, you must install BOTH the VC10-x64 
and VC11-x64 runtimes
 
 
 ## USAGE
diff --git a/bin/pftt_shell.cmd b/bin/pftt_shell.cmd
index 97a1209..c873ee0 100644
--- a/bin/pftt_shell.cmd
+++ b/bin/pftt_shell.cmd
@@ -26,7 +26,7 @@ ECHO tka_apache    tka_php     tka_windbg     `net use`    
stop
 @ECHO.
 ECHO Useful:
 ECHO ls            `start .`   windbg   npp   clear
-ECHO php_sdk       sleep       pftt
+ECHO php_sdk       sleep       pftt     cat
 @ECHO.
 @ECHO.
 @prompt $t %COMPUTERNAME% $M$p$g
diff --git a/bin/set_env.cmd b/bin/set_env.cmd
index e37ee08..f181e69 100644
--- a/bin/set_env.cmd
+++ b/bin/set_env.cmd
@@ -1,17 +1,32 @@
 @ECHO OFF
 
-REM system drive might not be C:, in such situations,
-REM php-sdk might be on C: or it could be both
-REM assume the one where PFTT is installed is the one to use (in such cases)
-REM
-IF EXIST %SYSTEMDRIVE%\php-sdk\PFTT\current (
-       SET PHP_DRIVE=%SYSTEMDRIVE%
+
+REM user may set custom PHP_SDK instead of %SYSTEMDRIVE%\php-sdk
+IF EXIST %~dp0%\internal\set_php_sdk.cmd (
+       REM this must set PHP_SDK
+       CALL %~dp0%\internal\set_php_sdk.cmd
+       
+       ECHO Custom PHP_SDK: %PHP_SDK%
+       
+       REM get PHP_DRIVE from PHP_SDK
+       SET PHP_DRIVE=%PHP_SDK:~0,2%
+       ECHO Custom PHP_DRIVE: %PHP_DRIVE%
+       
+       REM see: 
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/percent.mspx?mfr=true
+       REM see: 
http://www.dostips.com/DtTipsStringManipulation.php#Snippets.MidString
 ) ELSE (
-       SET PHP_DRIVE=C:
+       REM system drive might not be C:, in such situations,
+       REM php-sdk might be on C: or it could be both
+       REM assume the one where PFTT is installed is the one to use (in such 
cases)
+       REM
+       IF EXIST %SYSTEMDRIVE%\php-sdk\PFTT\current (
+               SET PHP_DRIVE=%SYSTEMDRIVE%
+       ) ELSE (
+               SET PHP_DRIVE=C:
+       )
+       SET PHP_SDK=%PHP_DRIVE%\php-sdk
 )
 
-SET PHP_SDK=%PHP_DRIVE%\php-sdk
-
 SET PFTT_ROOT_DIR=%PHP_SDK%\PFTT
 SET PFTT_HOME=%PHP_SDK%\PFTT\current
 SET PFTT_BIN=%PFTT_HOME%\bin
@@ -29,5 +44,3 @@ SET PFTT_WORKING=%PFTT_CACHE_WORKING%
 
 REM add PFTT to path. and GIT and Notepad++ if present
 SET 
PATH=%PFTT_BIN%;%PFTT_BIN_INTERNAL%;%PATH%;"%ProgramFiles(x86)%\Git\Bin";"%ProgramFiles%\Git\Bin"
-
-
diff --git a/src/com/mostc/pftt/host/AHost.java 
b/src/com/mostc/pftt/host/AHost.java
index 9d78100..973bce1 100644
--- a/src/com/mostc/pftt/host/AHost.java
+++ b/src/com/mostc/pftt/host/AHost.java
@@ -263,12 +263,16 @@ public abstract class AHost extends Host {
        }
        @Override
        public String getSystemDrive() {
-               if (system_drive!=null)
+               if (system_drive!=null) {
                        return system_drive;
-               else if (isWindows())
-                       return system_drive = getEnvValue("SYSTEMDRIVE");
-               else
+               } else if (isWindows()) {
+                       system_drive = getEnvValue("SYSTEMDRIVE");
+                       if (StringUtil.isEmpty(system_drive))
+                               system_drive = "C:"; // CRITICAL, default
+                       return system_drive;
+               } else {
                        return system_drive = "/";
+               }
        }
        @SuppressWarnings("unused")
        @Override
@@ -281,9 +285,12 @@ public abstract class AHost extends Host {
        }
        @Override
        public String getPhpSdkDir() {
-               if (php_sdk_dir!=null)
+               if (StringUtil.isNotEmpty(php_sdk_dir))
+                       return php_sdk_dir;
+               php_sdk_dir = System.getenv("PHP_SDK");
+               if (StringUtil.isNotEmpty(php_sdk_dir))
                        return php_sdk_dir;
-               else if(isWindows())
+               if(isWindows())
                        return php_sdk_dir = getSystemDrive() + "\\php-sdk\\";
                else
                        return php_sdk_dir = getHomeDir() + "/php-sdk/";
@@ -421,7 +428,7 @@ public abstract class AHost extends Host {
                
                
                // TODO
-               public abstract void run(StringBuilder output_sb, Charset 
charset, int timeout_sec, TestPackRunnerThread thread, int slow_sec) throws 
IOException, InterruptedException;
+               public abstract void run(StringBuilder output_sb, Charset 
charset, int timeout_sec, TestPackRunnerThread thread, int slow_sec, boolean 
suspend) throws IOException, InterruptedException;
        } // end public abstract class ExecHandle
        
        /** checks exit code to see if it means process crashed
@@ -675,7 +682,9 @@ public abstract class AHost extends Host {
                        dst_host.reported_7zip_already_installed = true;
                        return;
                }
-               
+
+               System.out.println("src_7z_path "+src_7z_path);
+               System.out.println("dst_7z_path "+dst_7z_path);
                try {
                        dst_host.upload(src_7z_path, dst_7z_path);
                        
diff --git a/src/com/mostc/pftt/host/LocalHost.java 
b/src/com/mostc/pftt/host/LocalHost.java
index e9e8809..058fbf8 100644
--- a/src/com/mostc/pftt/host/LocalHost.java
+++ b/src/com/mostc/pftt/host/LocalHost.java
@@ -190,7 +190,7 @@ public class LocalHost extends AHost {
                        
                StringBuilder output_sb = new StringBuilder(1024);
                
-               eh.run(output_sb, charset, timeout, thread, thread_slow_sec);
+               eh.run(output_sb, charset, timeout, thread, thread_slow_sec, 
false);
                
                
                
@@ -447,10 +447,17 @@ public class LocalHost extends AHost {
                        close_thread.start();
                } // end public void close
                
-               protected void run(StringBuilder output_sb, Charset charset) 
throws IOException, InterruptedException {
+               protected void run(StringBuilder output_sb, Charset charset, 
boolean suspend) throws IOException, InterruptedException {
                        final Process p = process.get();
                        if (p==null)
                                return;
+                       if (suspend) {
+                               final int pid = getWindowsProcessID(p);
+                               
+                               try {
+                                       execOut("pssuspend "+pid, 10);
+                               } catch ( Exception ex ) {}
+                       }
                        exec_copy_lines(output_sb, stdout, charset);
                        // ignores STDERR
                        
@@ -529,7 +536,7 @@ public class LocalHost extends AHost {
                }
 
                @Override
-               public void run(StringBuilder output_sb, Charset charset, int 
timeout_sec, TestPackRunnerThread thread, int thread_slow_sec) throws 
IOException, InterruptedException {
+               public void run(StringBuilder output_sb, Charset charset, int 
timeout_sec, TestPackRunnerThread thread, int thread_slow_sec, boolean suspend) 
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));
@@ -538,9 +545,8 @@ public class LocalHost extends AHost {
                        if (timeout_sec>NO_TIMEOUT) {
                                a = TimerUtil.waitSeconds(timeout_sec, new 
ExitMonitorTask(this));
                        }
-                       
-                       
-                       this.run(output_sb, charset);
+                                               
+                       this.run(output_sb, charset, suspend&&isWindows());
                        
                        if (a!=null)
                                a.cancel();
@@ -726,6 +732,8 @@ public class LocalHost extends AHost {
                        return false;
                if (isWindows()) {
                        File f = new File(path);
+                       if (f.isDirectory())
+                               return true;
                        for ( int i=0 ; i < 3 ; i++ ) {
                                f.mkdirs();
                                if (f.exists())
@@ -734,9 +742,7 @@ public class LocalHost extends AHost {
                                //             make sure it gets created before 
returning.
                                try {
                                        Thread.sleep(50);
-                               } catch ( InterruptedException ex ) {
-                                       break;
-                               }
+                               } catch ( InterruptedException ex ) {}
                        }
                } else {
                        new File(path).mkdirs();
@@ -867,13 +873,17 @@ public class LocalHost extends AHost {
        
        public static String getLocalPfttDir() {
                if (isLocalhostWindows()) {
-                       String sd = System.getenv("SYSTEMDRIVE");
-                       if (StringUtil.isEmpty(sd))
-                               sd = "C:";
+                       String php_sdk_dir = System.getenv("PHP_SDK");
+                       if (null == php_sdk_dir) {
+                               String sd = System.getenv("SYSTEMDRIVE");
+                               if (StringUtil.isEmpty(sd))
+                                       sd = "C:";
+                               php_sdk_dir = sd + "\\php-sdk";
+                       }
                        if (DEV>0)
-                               return sd+"\\php-sdk\\PFTT\\Dev-"+DEV+"\\";
+                               return php_sdk_dir+"\\PFTT\\Dev-"+DEV+"\\";
                        else
-                               return sd+"\\php-sdk\\PFTT\\Current\\";
+                               return php_sdk_dir+"\\PFTT\\Current\\";
                } else if (DEV>0) {
                        return 
System.getenv("HOME")+"/php-sdk/PFTT/dev-"+DEV+"/";
                } else {
diff --git a/src/com/mostc/pftt/host/SSHHost.java 
b/src/com/mostc/pftt/host/SSHHost.java
index 995ec02..f3a43ae 100644
--- a/src/com/mostc/pftt/host/SSHHost.java
+++ b/src/com/mostc/pftt/host/SSHHost.java
@@ -162,10 +162,12 @@ public class SSHHost extends RemoteHost {
        public boolean ensureConnected(ConsoleManager cm) {
                try {
                        ensureSshOpen();
-                       return true;
+                       return isWindows() || exists("/");
                } catch ( Exception ex ) {
                        if (cm!=null)
-                               cm.addGlobalException(EPrintType.WARNING, 
getClass(), "ensureConnected", ex, "can't connect to remote ssh host"); 
+                               cm.addGlobalException(EPrintType.WARNING, 
getClass(), "ensureConnected", ex, "can't connect to remote ssh host");
+                       else
+                               ex.printStackTrace();
                        return false;
                }
        }
@@ -460,7 +462,7 @@ public class SSHHost extends RemoteHost {
                }
 
                @Override
-               public void run(StringBuilder output_sb, Charset charset, int 
timeout_sec, final TestPackRunnerThread thread, int slow_sec) throws 
IOException, InterruptedException {
+               public void run(StringBuilder output_sb, Charset charset, int 
timeout_sec, final TestPackRunnerThread thread, int slow_sec, boolean suspend) 
throws IOException, InterruptedException {
                        do_run(session, charset, timeout_sec, thread, slow_sec);
                        output_sb.append(out.toString());
                }
@@ -586,9 +588,7 @@ public class SSHHost extends RemoteHost {
        public boolean mkdirs(String path) throws IllegalStateException, 
IOException {
                ensureSftpOpen();
                path = normalizePath(path);
-               if (!isSafePath(path))
-                       return false;
-               
+               // dont check #isSafePath here!
                if (isWindows()) {
                        try {
                                sftp.stat(path);
diff --git a/src/com/mostc/pftt/main/PfttMain.java 
b/src/com/mostc/pftt/main/PfttMain.java
index c3273a6..a7c3c3b 100644
--- a/src/com/mostc/pftt/main/PfttMain.java
+++ b/src/com/mostc/pftt/main/PfttMain.java
@@ -78,7 +78,9 @@ import 
com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair;
 // the php test tool that you'd actually want to use
 // doesn't resort to brittle shell scripts
 
-// TODO cleanup LocalHost#close
+// TODO -suspend_seconds
+// TODO -ini_all
+// TODO have config file specify custom INI options
 
 // TODO timing support for phpunit tests
 //    `aa -thread_count cpu -c symfony,apache,opcache,no_code_cache php-5.5`
@@ -169,13 +171,14 @@ import 
com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair;
 // Better-PFTT
 //    get actual version of apache, wordpress, symfony, etc... instead of 
assuming hardcoded value
 //    regular ongoing project/side-project w/ stable, testing branches
+//      -recognition that the SIMPLEST WAY is not the fastest way
+//          -PFTT is complicated, but there is value in that complexity (since 
it actually works)
 //      -unit tests of PFTT
 //       mostly in PHASE 2/3
 //    console option to remove scenarios from permutations
 //    use MXQuery.jar to query each result pack
 //        -pftt open result-pack1, result-pack2, result-pack3
 //          -get console for xqueries (simplified groovy shell)
-//        -@see http://code.google.com/p/sqlite4java/
 //
 //    PUBLISH reports to PHP Web App on windows.php.net
 //           -make it look good (marketing) => use same theme as rest of 
windows.php.net (can have link there to QA/Testing)
@@ -206,6 +209,8 @@ import 
com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair;
 //     it has phpunit tests
 //     see http://github.com/WindowsAzure
 //
+// NGINX-FastCGI - as/more popular than IIS
+//
 // PECL extensions to consider testing:
 //       geoip haru(pdf) http
 //       uploadprogress? xdiff? yaml? pthreads? dio?
@@ -321,6 +326,10 @@ public class PfttMain {
                System.out.println("-src_pack <path> - folder with the source 
code");
                System.out.println("-debug_pack <path> - folder with debugger 
symbols (usually folder with .pdb files)");
                System.out.println();
+               System.out.println("   === Debugging ===");
+               System.out.println("-ini_all - includes INI for all tests 
(default=only for failures)... SLOW but helps verify"); // TODO
+               System.out.println("-suspend <seconds> - suspends test process 
for <seconds> before running test so you can check the process first (1 minute 
timeout starts after resume)"); // TODO
+               System.out.println();
                System.out.println("   === Threading Options ===");
                System.out.println("-no_thread_safety - runs tests in any 
thread, regardless of thread-safety. This can increase load/stress, but may 
lead to false FAILS/ERRORs, especially in file or database tests.");
                System.out.println("-thread_count <N> - sets number of threads 
to run tests in. running in multiple threads is usually a performance boost. by 
default, will run with multiple threads and automatically decide the best 
number of threads to use");
diff --git a/src/com/mostc/pftt/model/app/PhpUnitTemplate.groovy 
b/src/com/mostc/pftt/model/app/PhpUnitTemplate.groovy
index b39c36e..b076a0c 100644
--- a/src/com/mostc/pftt/model/app/PhpUnitTemplate.groovy
+++ b/src/com/mostc/pftt/model/app/PhpUnitTemplate.groovy
@@ -132,6 +132,7 @@ function __phpunit_run_isolated_test()
        \$status = PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED;
        \$status_msg = NULL;
        \$output = NULL;
+       \$run_time = 0;
        try {
                if (!class_exists('$test_case.className')) {
                        require_once '$test_case.abs_filename';
@@ -156,7 +157,9 @@ function __phpunit_run_isolated_test()
                // so PFTT doesn't need to use reflection for PhpUnit tests, 
but users may want it to.
                //
 pw.println("""
+               \$start_time = microtime(TRUE);
                \$test->run(\$result);
+               \$run_time = microtime(TRUE) - \$start_time;
                \$status = \$test->getStatus();
                \$status_msg = \$test->getStatusMessage();""");
        } else {
@@ -167,7 +170,9 @@ pw.println("""
                // if no exception is thrown => it passed
 pw.println("""clearstatcache();
                \$test->pftt_step1();
+               \$start_time = microtime(TRUE);
         \$test->$test_case.methodName();
+               \$run_time = microtime(TRUE) - \$start_time;
         \$test->pftt_step2();
                try {
                        \$test->pftt_step3();
@@ -208,6 +213,7 @@ pw.println("""      } catch ( Exception \$e ) {
        case PHPUnit_Runner_BaseTestRunner::STATUS_PASSED:
                echo "PASS";
                echo PHP_EOL;
+               echo "run time \$run_time micros";echo PHP_EOL;
                break;
        case PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED:
                echo 'SKIP';
diff --git 
a/src/com/mostc/pftt/model/sapi/SharedSAPIInstancesTestCaseGroupKey.java 
b/src/com/mostc/pftt/model/sapi/SharedSAPIInstancesTestCaseGroupKey.java
index 5723066..e1453fc 100644
--- a/src/com/mostc/pftt/model/sapi/SharedSAPIInstancesTestCaseGroupKey.java
+++ b/src/com/mostc/pftt/model/sapi/SharedSAPIInstancesTestCaseGroupKey.java
@@ -39,9 +39,13 @@ public class SharedSAPIInstancesTestCaseGroupKey extends 
TestCaseGroupKey {
        }
        
        public SAPIInstance getSAPIInstance() {
+               return getSAPIInstance(Thread.currentThread());
+       }
+       
+       public SAPIInstance getSAPIInstance(Thread t) {
                SAPIInstance this_sapi_instance;
                synchronized(sapi_instances) {
-                       this_sapi_instance = 
sapi_instances.get(Thread.currentThread());
+                       this_sapi_instance = sapi_instances.get(t);
                }
                return this_sapi_instance;
        }
diff --git a/src/com/mostc/pftt/results/PhptTestResult.java 
b/src/com/mostc/pftt/results/PhptTestResult.java
index 3060c80..dadd54b 100644
--- a/src/com/mostc/pftt/results/PhptTestResult.java
+++ b/src/com/mostc/pftt/results/PhptTestResult.java
@@ -356,6 +356,11 @@ public class PhptTestResult {
                                serial.endTag(null, "regexOutput");
                        }
                        
+               } else if (actual_ini!=null) {
+                       // even if not supposed to store info (@see 
shouldStoreAll), if #actual_ini set, must need to store it
+                       serial.startTag(null, "actualINI");
+                       serial.text(actual_ini);
+                       serial.endTag(null, "actualINI");
                } // end if (status==FAIL, etc...)
                
                // include the exact test case that was run
diff --git a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java 
b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
index d737939..96f501c 100644
--- a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
@@ -13,6 +13,7 @@ import java.util.Timer;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 
 import javax.annotation.Nullable;
@@ -41,8 +42,7 @@ import com.mostc.pftt.scenario.AbstractWebServerScenario;
 import com.mostc.pftt.scenario.Scenario;
 import com.mostc.pftt.scenario.ScenarioSet;
 import com.mostc.pftt.scenario.AbstractFileSystemScenario.ITestPackStorageDir;
-import com.mostc.pftt.util.TimerUtil;
-import com.mostc.pftt.util.TimerUtil.TimerThread;
+import com.mostc.pftt.util.ErrorUtil;
 
 public abstract class AbstractLocalTestPackRunner<A extends ActiveTestPack, S 
extends SourceTestPack<A,T>, T extends TestCase> extends 
AbstractTestPackRunner<S, T> {
        protected static final int MAX_THREAD_COUNT = 256;
@@ -245,6 +245,8 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                
                try {
                        groupTestCases(test_cases);
+                       System.out.println("248 
"+this.non_thread_safe_tests.size());
+                       System.out.println("249 
"+this.thread_safe_tests.size());
                        
                        cm.println(EPrintType.IN_PROGRESS, getClass(), "ready 
to go!    scenario_set="+scenario_set+" runner_host="+runner_host+" 
storage_dir="+storage_dir.getClass()+" 
local_path="+storage_dir.getLocalPath(runner_host)+" 
remote_path="+storage_dir.getRemotePath(runner_host));
                        
@@ -483,38 +485,68 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                }
                
                // block until done
-               boolean not_running;
-               for (;;) {
-                       not_running = true;
-                       for ( TestPackThread<?> t : threads ) {
-                               if (t.jobs!=null&&t.jobs.isEmpty()) {
-                                       // thread has no more jobs to execute
-                                       if (t.isDebuggerAttached()) {
-                                               // don't stop because of this 
thread, its being debugged
-                                               //
-                                               //
+               {
+                       boolean not_running;
+                       Iterator<TestPackThread<T>> thread_it;
+                       TestPackThread<T> thread;
+                       long test_run_start_time;
+                       for (;;) {
+                               not_running = threads.isEmpty();
+                               thread_it = threads.iterator();
+                               while(thread_it.hasNext()) {
+                                       thread = thread_it.next();
+                                       test_run_start_time = 
thread.test_run_start_time.get();
+                                       // TODO 120 seconds => don't hard code 
it here
+                                       //
+                                       // sometimes, some tests can get stuck 
- this is really bad. it totally blocks everything up
+                                       // this is another safety mechanism to 
prevent that:
+                                       //
+                                       // run a timer task while the test is 
running to kill the test if it takes too long
+                                       //
+                                       // wait a while before killing it 
(double the max runtime for the test)
+                                       if 
((test_run_start_time>0&&Math.abs(System.currentTimeMillis()-test_run_start_time)>120000))
 {
+                                               // thread running too long
+                                               if 
(thread.isDebuggerAttached()) {
+                                                       not_running = false; // 
keep running
+                                                       break;
+                                               } else if 
(thread.jobs!=null&&!thread.jobs.isEmpty()||(thread.ext!=null&&!thread.ext.test_groups.isEmpty()))
 {
+                                                       
thread.replaceThisThread();
+                                                       threads.remove(thread);
+                                               } else {
+                                                       // thread not doing 
anything... kill it
+                                                       thread.stopThisThread();
+                                                       threads.remove(thread);
+                                               }
+                                               continue;
+                                       } 
+                                       
+                                       if 
((thread.jobs!=null&&!thread.jobs.isEmpty())||(thread.ext!=null&&!thread.ext.test_groups.isEmpty())||thread.isDebuggerAttached())
 {
+                                               // keep running if a thread
+                                               // 1. is running a test
+                                               // 2. has jobs(tests) to still 
execute
+                                               // 3. has a test that is being 
debugged (windbg, gdb, etc...)
                                                not_running = false;
                                                break;
                                        } else {
-                                               // kill thread
-                                               t.stopThisThread();
+                                               // thread has nothing to do, 
kill it
+                                               thread.stopThisThread();
+                                               threads.remove(thread);
                                        }
-                               } else if (t.isRunningTest()) {
-                                       not_running = false;
+                               }
+                               if (not_running) {
+                                       // no threads have jobs left to do, 
stop waiting
                                        break;
+                               } else {
+                                       // wait a while before checking again
+                                       Thread.sleep(threads.size()>3?1000:50);
                                }
                        }
-                       if (not_running) {
-                               // no threads have jobs left to do, stop waiting
-                               break;
-                       } else {
-                               // wait a while before checking again
-                               Thread.sleep(threads.size()>3?1000:50);
-                       }
+                       // wait for queued results to be written before 
returning
+                       // (this is important as PFTT may close the result-pack 
after returning and we want to 
+                       //  make sure all the results get written first!)
+                       if (twriter instanceof PhpResultPackWriter)
+                               
((PhpResultPackWriter)twriter).wait(runner_host, scenario_set);
                }
-               // wait for queued results to be written before returning
-               if (twriter instanceof PhpResultPackWriter)
-                       ((PhpResultPackWriter)twriter).wait(runner_host, 
scenario_set);
        } // end protected void executeTestCases
                
        protected void start_thread(boolean parallel) throws 
IllegalStateException, IOException {
@@ -531,11 +563,18 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                protected final AtomicBoolean run_thread;
                protected final boolean parallel;
                protected final int run_test_times_all;
+               protected final AtomicLong test_run_start_time;
                protected TestCaseGroupKey group_key;
+               protected NonThreadSafeExt<T> ext;
+               protected TestCaseGroup<T> group;
+               protected LinkedBlockingQueue<T> jobs;
+               protected WebServerInstance thread_wsi;
+               protected T test_case;
                
                protected TestPackThread(boolean parallel) {
                        this.run_thread = new AtomicBoolean(true);
                        this.parallel = parallel;
+                       this.test_run_start_time = new AtomicLong(0L);
                        
                        this.setUncaughtExceptionHandler(this);
                        
@@ -547,11 +586,13 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                @Override
                public void uncaughtException(java.lang.Thread arg0, 
java.lang.Throwable arg1) {
                        arg1.printStackTrace();
+                       // wait for #executeTestCases to remove this thread 
from group
                        System.out.println("END_THREAD " +arg1+" 
"+Thread.currentThread());
-                       threads.remove(Thread.currentThread());
+                       try {
+                               twriter.addGlobalException(runner_host, 
ErrorUtil.toString(arg1));
+                       } catch ( Throwable t ) {}
                }
-               
-                               
+                                               
                @Override
                public void run() {
                        // pick a non-thread-safe(NTS) extension that isn't 
already running then run it
@@ -577,26 +618,59 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                        }
                } // end public void run
                
+               public void replaceThisThread() {
+                       stopThisThread();
+                       
+                       // create new thread to run this thread's jobs
+                       if (ext!=null)
+                               non_thread_safe_exts.add(ext);
+                       createNewThread();
+                       
+                       // don't run test again, it will likely just cause 
another timeout
+                       //
+                       // record that the current test is skipped
+                       recordSkipped(test_case);
+               }
+               
+               public void stopThisThread() {
+                       // don't run any more tests in this thread
+                       run_thread.set(false);
+                       
+                       stopRunningCurrentTest();
+                       
+                       // kill any web server, etc... used only by this thread
+                       if (group_key instanceof 
SharedSAPIInstancesTestCaseGroupKey) {
+                               SAPIInstance sapi = 
((SharedSAPIInstancesTestCaseGroupKey)group_key).getSAPIInstance(TestPackThread.this);
+                               if (sapi!=null)
+                                       sapi.close();
+                       }
+                       // interrupt thread to make it stop
+                       try {
+                               TestPackThread.this.stop(new 
TestTimeoutException());
+                       } catch ( ThreadDeath ex ) {}
+                       TestPackThread.this.interrupt();
+               }
+               
                protected void runNonThreadSafe() {
-                       NonThreadSafeExt<T> ext;
-                       TestCaseGroup<T> group;
                        while(shouldRun()) {
                                ext = non_thread_safe_exts.poll();
                                if (ext==null)
                                        break;
                                
                                while (shouldRun()) {
-                                       group = ext.test_groups.poll();
+                                       // #peek not #poll to leave group in 
ext.test_groups in case thread gets replaced (@see #stopThisThread)
+                                       group = ext.test_groups.peek();
                                        if (group==null)
                                                break;
                                        
                                        exec_jobs(group.group_key, 
group.test_cases, test_count);
+                                       ext.test_groups.remove();
                                }
                        }
+                       ext = null;
                } // end protected void runNonThreadSafe
                
                protected void runThreadSafe() {
-                       TestCaseGroup<T> group;
                        while (shouldRun()) {
                                // thread-safe can share groups between threads
                                // (this allows larger groups to be distributed 
 between threads)
@@ -619,11 +693,9 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                protected boolean shouldRun() {
                        return run_thread.get() && 
runner_state.get()==ETestPackRunnerState.RUNNING;
                }
-               LinkedBlockingQueue<T> jobs;
-               WebServerInstance thread_wsi;
+               
                protected void exec_jobs(TestCaseGroupKey group_key, 
LinkedBlockingQueue<T> jobs, AtomicInteger test_count) {
                        this.group_key = group_key;
-                       T test_case;
                        SAPIInstance sa = null;
                        LinkedList<T> completed_tests = new LinkedList<T>();
                        this.jobs = jobs;
@@ -631,7 +703,7 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                        try {
                                while ( (test_case = jobs.poll()) != null && 
shouldRun() ) {
                                        completed_tests.add(test_case);
-                                       running_test = true;
+                                       
test_run_start_time.set(System.currentTimeMillis());
                                        
                                        int a = run_test_times_all;
                                        
@@ -643,7 +715,6 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                                        for ( int i=0 ; i < a ; i++ ) {
                                                
                                                // CRITICAL: catch exception to 
record with test
-                                               TimerThread task = null;
                                                try {
                                                        group_key.prepare();
                                                        
@@ -652,6 +723,7 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                                                                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
                                                                // make sure a 
WebServerInstance is still running here, so it will be shared with each
                                                                // test runner 
instance (otherwise each test runner will create its own instance, which is 
slow)
@@ -680,28 +752,8 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                                                                }
                                                        } // end if
                                                        
-                                                       //
-                                                       // sometimes, some 
tests can get stuck - this is really bad. it totally blocks everything up
-                                                       // this is another 
safety mechanism to prevent that:
-                                                       //
-                                                       // run a timer task 
while the test is running to kill the test if it takes too long
-                                                       //
-                                                       // wait a while before 
killing it (double the max runtime for the test)
-                                                       // TODO what if/when 3 
attempts are made to run the test?? (ex: builtin web server)
-                                                       task = 
TimerUtil.waitSeconds(getMaxTestRuntimeSeconds() * 2, new Runnable() {
-                                                                       
@Override
-                                                                       public 
void run() {
-                                                                               
new Thread() {
-                                                                               
                @Override
-                                                                               
                public void run() {
-                                                                               
                        stopRunningCurrentTest();
-                                                                               
                        
-                                                                               
                        createNewThread();
-                                                                               
                        stopThisThread();
-                                                                               
                }
-                                                                               
        }.start();
-                                                                       }
-                                                               });
+                                                       
+                                                       
                                                
                                                        // finally: create the 
test case runner and run the actual test
                                                        runTest(group_key, 
test_case);
@@ -714,14 +766,11 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                                                        
twriter.addTestException(storage_host, scenario_set, test_case, ex, sa);
                                                }
                                                
-                                               // test was run
-                                               
-                                               // don't need to stop the test 
if/once here
-                                               if (task!=null)
-                                                       task.cancel();
-                                               
                                                try {
                                                        // -delay_between_ms 
console option
+                                                       //
+                                                       // TODO take this time 
into account when checking max execution time
+                                                       // TODO also count 
number of times test is supposed to be run
                                                        if 
(cm.getDelayBetweenMS()>0) {
                                                                
Thread.sleep(cm.getDelayBetweenMS());
                                                        }
@@ -733,7 +782,7 @@ public abstract class AbstractLocalTestPackRunner<A extends 
ActiveTestPack, S ex
                                                }
                                        } // end for
                                        
-                                       running_test = false;
+                                       test_run_start_time.set(0);
                                        test_count.incrementAndGet();
                                        Thread.yield();
                                } // end while
@@ -761,39 +810,15 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                @Override
                protected void createNewThread() {
                        try {
-                       start_thread(parallel);
-                       } catch ( Exception ex ) {
-                               ex.printStackTrace();
-                       }
-               }
-               
-               private boolean running_test;
-               public boolean isRunningTest() {
-                       return running_test;
-               }
-
-               @Override
-               protected void stopThisThread() {
-                       stopRunningCurrentTest();
-                       
-                       // continue running current CliTestCaseRunner, but 
don't start any more of them
-                       run_thread.set(false);
-                       
-                       // kill any web server, etc... used only by this thread
-                       if (group_key instanceof 
SharedSAPIInstancesTestCaseGroupKey) {
-                               SAPIInstance sapi = 
((SharedSAPIInstancesTestCaseGroupKey)group_key).getSAPIInstance();
-                               if (sapi!=null)
-                                       sapi.close();
+                               start_thread(parallel);
+                       } catch ( Throwable t ) {
+                               twriter.addGlobalException(runner_host, 
ErrorUtil.toString(t));
                        }
-                       threads.remove(TestPackThread.this);
-                       try {
-                               TestPackThread.this.stop(new 
TestTimeoutException());
-                       } catch ( ThreadDeath ex ) {}
-                       TestPackThread.this.interrupt();
                }
                
                protected abstract void stopRunningCurrentTest();
                protected abstract int getMaxTestRuntimeSeconds();
+               protected abstract void recordSkipped(T test_case);
                
                public boolean isDebuggerAttached() {
                        if (group_key instanceof 
SharedSAPIInstancesTestCaseGroupKey) {
diff --git a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java 
b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
index c1b561c..7bcb9b0 100644
--- a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
+++ b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
@@ -52,7 +52,8 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
        
        protected String get_ini_get_all_path() throws IllegalStateException, 
IOException {
                // ensure ini_get_all.php exists
-               String ini_get_all_path = 
host.joinIntoOnePath(active_test_pack.getStorageDirectory(), "ini_get_all.php");
+               // TODO temp 5/15 - should store this once only and delete it 
later
+               String ini_get_all_path = host.mktempname(getClass(), 
"ini_get_all.php");
                if (!host.exists(ini_get_all_path)) {
                        // TODO locking?
                        host.saveTextFile(ini_get_all_path, "<?php 
var_dump($argv);\nvar_dump(ini_get_all()); ?>");
@@ -440,7 +441,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                        }
                        if (expected_re_match) {
 
-                               twriter.addResult(host, scenario_set, new 
PhptTestResult(host, 
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, 
output, null, null, charset, ini, env, splitCmdString(), stdin_post, 
getShellScript(), null, null, null));
+                               twriter.addResult(host, scenario_set, 
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)));
                                                
                                return;
                        } 
@@ -462,7 +463,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                                }
                                if (expected_re_match) {
 
-                                       twriter.addResult(host, scenario_set, 
new PhptTestResult(host, 
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, 
output, null, null, charset, ini, env, splitCmdString(), stdin_post, 
getShellScript(), null, null, null));
+                                       twriter.addResult(host, scenario_set, 
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)));
                                                        
                                        return;
                                }
@@ -474,7 +475,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                        
                        if (equalsNoWS(output, 
expected)||(output.contains("<html>")&&!output.contains("404"))||(test_case.isNamed("ext/phar/tests/zip/phar_commitwrite.phpt")&&expected.contains(output.substring(50,
 
60)))||(test_case.isNamed("ext/phar/tests/tar/phar_commitwrite.phpt")&&expected.contains(output.substring(60,
 70)))) {
                                
-                               twriter.addResult(host, scenario_set, new 
PhptTestResult(host, 
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, 
output, null, null, charset, ini, env, splitCmdString(), stdin_post, 
getShellScript(), null, null, null));
+                               twriter.addResult(host, scenario_set, 
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)));
                                                
                                return;
                        }
@@ -491,7 +492,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                                // compare again
                                if (equalsNoWS(output, expected)) {
                                        
-                                       twriter.addResult(host, scenario_set, 
new PhptTestResult(host, 
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, 
output, null, null, charset, ini, env, splitCmdString(), stdin_post, 
getShellScript(), null, null, null));
+                                       twriter.addResult(host, scenario_set, 
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)));
                                        
                                        return;
                                } // end if
@@ -501,7 +502,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                        String output_trim = output.trim();
                        
                        if 
(StringUtil.isEmpty(output_trim)||(output.contains("<html>")&&!output.contains("404")))
 {
-                               twriter.addResult(host, scenario_set, new 
PhptTestResult(host, 
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case, 
output, null, null, charset, ini, env, splitCmdString(), stdin_post, 
getShellScript(), null, null, null));
+                               twriter.addResult(host, scenario_set, 
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)));
                                
                                return;
                        }
@@ -553,12 +554,22 @@ public abstract class AbstractPhptTestCaseRunner2 extends 
AbstractPhptTestCaseRu
                twriter.addResult(host, scenario_set, result);
        } // end protected void evalTest
        
-       protected PhptTestResult notifyNotPass(PhptTestResult result) {
+       protected PhptTestResult notifyPassOrXFail(PhptTestResult result) {
+               //handleActualIni(result); // TODO temp 5/15
+               
+               return result;
+       }
+       
+       protected void handleActualIni(PhptTestResult result) {
                try {
                        result.actual_ini = getIniActual();
                } catch ( Throwable ex ) {
                        result.actual_ini = ErrorUtil.toString(ex);
                }
+       }
+       
+       protected PhptTestResult notifyNotPass(PhptTestResult result) {
+               handleActualIni(result);
                
                return result;
        }
diff --git a/src/com/mostc/pftt/runner/AbstractTestPackRunner.java 
b/src/com/mostc/pftt/runner/AbstractTestPackRunner.java
index d4352a8..c6bb69f 100644
--- a/src/com/mostc/pftt/runner/AbstractTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/AbstractTestPackRunner.java
@@ -47,7 +47,6 @@ public abstract class AbstractTestPackRunner<S extends 
SourceTestPack, T extends
                
                protected abstract boolean slowCreateNewThread();
                protected abstract void createNewThread();
-               protected abstract void stopThisThread();
                
                @Override
                public void notifySlowTest() {
diff --git a/src/com/mostc/pftt/runner/CliPhpUnitTestCaseRunner.java 
b/src/com/mostc/pftt/runner/CliPhpUnitTestCaseRunner.java
index 1bf0272..bb26474 100644
--- a/src/com/mostc/pftt/runner/CliPhpUnitTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/CliPhpUnitTestCaseRunner.java
@@ -36,7 +36,7 @@ public class CliPhpUnitTestCaseRunner extends 
AbstractPhpUnitTestCaseRunner {
                
                StringBuilder output_sb = new StringBuilder(128);
                
-               running_test_handle.run(output_sb, null, 60, null, 0);
+               running_test_handle.run(output_sb, null, 60, null, 0, false);
                
                output_str = output_sb.toString();
                
diff --git a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java 
b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
index 2887323..9de7e21 100644
--- a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
@@ -74,7 +74,7 @@ public class CliPhptTestCaseRunner extends 
AbstractPhptTestCaseRunner2 {
                
                String ini_get_all_path = get_ini_get_all_path();
                
-               return sapi.execute(exe_type, ini_get_all_path, null, env, 
AHost.ONE_MINUTE).output;
+               return ini_get_all_path+sapi.execute(exe_type, 
ini_get_all_path, null, env, AHost.ONE_MINUTE).output;
        }
        
        @Override
@@ -215,7 +215,8 @@ public class CliPhptTestCaseRunner extends 
AbstractPhptTestCaseRunner2 {
                                );
                StringBuilder output_sb = new StringBuilder(1024);
                
-               running_test_handle.run(output_sb, 
test_case.isNon8BitCharset()?test_case.getCommonCharset():null, 60, thread, 40);
+               // TODO 5/14 false => suspend
+               running_test_handle.run(output_sb, 
test_case.isNon8BitCharset()?test_case.getCommonCharset():null, 60, thread, 40, 
false);
                
                return output_sb.toString();
        }
diff --git a/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java 
b/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java
index cdc49d9..27a4075 100644
--- a/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java
@@ -250,7 +250,6 @@ public class HttpPhpUnitTestCaseRunner extends 
AbstractPhpUnitTestCaseRunner {
                                60, 
                                new Runnable() {
                                        public void run() {
-                                               System.out.println("Http 319");
                                                if (web!=null)
                                                        web.close();
                                        }
diff --git a/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java 
b/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java
index 0e5f76a..80c40ac 100644
--- a/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java
@@ -8,6 +8,7 @@ import java.util.Map;
 import javax.annotation.Nullable;
 
 import com.mostc.pftt.host.AHost;
+import com.mostc.pftt.model.app.EPhpUnitTestStatus;
 import com.mostc.pftt.model.app.PhpUnitActiveTestPack;
 import com.mostc.pftt.model.app.PhpUnitSourceTestPack;
 import com.mostc.pftt.model.app.PhpUnitTestCase;
@@ -18,6 +19,7 @@ import com.mostc.pftt.model.sapi.TestCaseGroupKey;
 import com.mostc.pftt.model.smoke.RequiredExtensionsSmokeTest;
 import com.mostc.pftt.results.ConsoleManager;
 import com.mostc.pftt.results.ITestResultReceiver;
+import com.mostc.pftt.results.PhpUnitTestResult;
 import com.mostc.pftt.results.ConsoleManager.EPrintType;
 import com.mostc.pftt.scenario.AbstractCodeCacheScenario;
 import com.mostc.pftt.scenario.AbstractFileSystemScenario.ITestPackStorageDir;
@@ -194,6 +196,11 @@ public class LocalPhpUnitTestPackRunner extends 
AbstractLocalTestPackRunner<PhpU
                protected int getMaxTestRuntimeSeconds() {
                        return r == null ? 60 : r.getMaxTestRuntimeSeconds();
                }
+
+               @Override
+               protected void recordSkipped(PhpUnitTestCase test_case) {
+                       twriter.addResult(runner_host, scenario_set, new 
PhpUnitTestResult(test_case, EPhpUnitTestStatus.SKIP, scenario_set, 
runner_host, null, null, "PFTT: Test Timed Out", null));
+               }
                
        } // end public class PhpUnitThread
 
diff --git a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java 
b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java
index 7ed6ce5..dfc0f03 100644
--- a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java
@@ -9,6 +9,7 @@ import java.util.List;
 import javax.annotation.Nullable;
 
 import com.mostc.pftt.host.AHost;
+import com.mostc.pftt.model.core.EPhptTestStatus;
 import com.mostc.pftt.model.core.ESAPIType;
 import com.mostc.pftt.model.core.PhpBuild;
 import com.mostc.pftt.model.core.PhptActiveTestPack;
@@ -17,6 +18,7 @@ import com.mostc.pftt.model.core.PhptTestCase;
 import com.mostc.pftt.model.sapi.TestCaseGroupKey;
 import com.mostc.pftt.results.ConsoleManager;
 import com.mostc.pftt.results.ITestResultReceiver;
+import com.mostc.pftt.results.PhptTestResult;
 import com.mostc.pftt.results.ConsoleManager.EPrintType;
 import com.mostc.pftt.scenario.Scenario;
 import com.mostc.pftt.scenario.ScenarioSet;
@@ -197,6 +199,11 @@ public class LocalPhptTestPackRunner extends 
AbstractLocalTestPackRunner<PhptAct
                protected int getMaxTestRuntimeSeconds() {
                        return r == null ? 60 : r.getMaxTestRuntimeSeconds();
                }
+
+               @Override
+               protected void recordSkipped(PhptTestCase test_case) {
+                       twriter.addResult(runner_host, scenario_set, new 
PhptTestResult(runner_host, EPhptTestStatus.SKIP, test_case, "test timed out", 
null, null, null, null, null, null, null, null, null, null, null));
+               }
                
        } // end public class PhptThread
        
diff --git a/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java 
b/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
index b0f13aa..292bd0e 100644
--- a/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
+++ b/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
@@ -89,7 +89,7 @@ public class BuiltinWebServerScenario extends 
AbstractWebServerScenario {
                        return true;
                } else if (test_case.isNamed(NOT_ON_BUILTIN_WEB_SERVER)) {
 
-                       twriter.addResult(host, scenario_set, new 
PhptTestResult(host, EPhptTestStatus.XSKIP, test_case, "test is not valid on 
web servers", null, null, null, null, null, null, null, null, null, null, 
null));
+                       twriter.addResult(host, scenario_set, new 
PhptTestResult(host, EPhptTestStatus.XSKIP, test_case, "test is not valid on 
builtin web server", null, null, null, null, null, null, null, null, null, 
null, null));
                        return true;
                } else {
                        return false;
diff --git a/src/com/mostc/pftt/scenario/CLIScenario.java 
b/src/com/mostc/pftt/scenario/CLIScenario.java
index d84e632..6daf002 100644
--- a/src/com/mostc/pftt/scenario/CLIScenario.java
+++ b/src/com/mostc/pftt/scenario/CLIScenario.java
@@ -68,6 +68,7 @@ public class CliScenario extends AbstractSAPIScenario {
                //
                // this is needed only to collect any custom directives that a 
test case provides
                PhpIni ini = 
RequiredExtensionsSmokeTest.createDefaultIniCopy(cm, host, build); // TODO temp 
5/13
+               //ini.putSingle("sys_temp_dir", 
"c:\\users\\matt\\appdata\\local\\temp");
                AbstractINIScenario.setupScenarios(cm, host, scenario_set, 
build, ini);
                return ini;
        }
diff --git a/src/com/mostc/pftt/scenario/OpcacheScenario.java 
b/src/com/mostc/pftt/scenario/OpcacheScenario.java
index 8fcc3e8..a0bfb0c 100644
--- a/src/com/mostc/pftt/scenario/OpcacheScenario.java
+++ b/src/com/mostc/pftt/scenario/OpcacheScenario.java
@@ -95,9 +95,12 @@ public class OpcacheScenario extends 
AbstractCodeCacheScenario {
        @Override
        public boolean prepare(ConsoleManager cm, AHost host, PhpBuild build, 
ScenarioSet scenario_set, PhptActiveTestPack test_pack) {
                if (host.isWindows()) {
-                       // sometimes OpCache may put the memory mapped file 
here, be sure to delete it
+                       // sometimes OpCache may put the memory mapped file 
here(CWD or TMP), be sure to delete it
                        
host.deleteIfExistsElevated(test_pack.getRunningDirectory()+"\\ZendOptimizer+.MemoryBase@"+host.getUsername());
 
                        
host.deleteIfExistsElevated(test_pack.getStorageDirectory()+"\\ZendOptimizer+.MemoryBase@"+host.getUsername());
+                       
host.deleteIfExistsElevated(build.getBuildPath()+"\\ZendOptimizer+.MemoryBase@"+host.getUsername());
    
+                       
host.deleteIfExistsElevated(host.getPhpSdkDir()+"\\ZendOptimizer+.MemoryBase@"+host.getUsername());
+                       
host.deleteIfExistsElevated(host.getPfttDir()+"\\ZendOptimizer+.MemoryBase@"+host.getUsername());
                }
                return true;
        }
diff --git a/src/com/mostc/pftt/scenario/app/PHPmotionScenario.java 
b/src/com/mostc/pftt/scenario/app/PHPmotionScenario.java
index ff2ab4c..ea3cb96 100644
--- a/src/com/mostc/pftt/scenario/app/PHPmotionScenario.java
+++ b/src/com/mostc/pftt/scenario/app/PHPmotionScenario.java
@@ -18,7 +18,7 @@ import com.mostc.pftt.scenario.app.ZipDbApplication;
  *
  */
 
-public class PhpMotionScenario extends ZipDbApplication {
+public class PhpmotionScenario extends ZipDbApplication {
 
        @Override
        protected String getZipAppFileName() {
diff --git a/src/com/mostc/pftt/util/ErrorUtil.java 
b/src/com/mostc/pftt/util/ErrorUtil.java
index e2d36eb..df1e63e 100644
--- a/src/com/mostc/pftt/util/ErrorUtil.java
+++ b/src/com/mostc/pftt/util/ErrorUtil.java
@@ -6,6 +6,8 @@ import java.io.StringWriter;
 
 import javax.swing.JOptionPane;
 
+import com.github.mattficken.io.StringUtil;
+
 public final class ErrorUtil {
        
        public static void display_error(Component c, String msg) {
@@ -23,7 +25,11 @@ public final class ErrorUtil {
                PrintWriter pw = new PrintWriter(sw);
                ex.printStackTrace(pw);         
                pw.close();
-               return sw.toString();
+               String str = sw.toString();
+               if (StringUtil.isEmpty(str))
+                       // be sure something useful gets returned
+                       str = ex.getClass().toString();
+               return str;
        }
 
        private ErrorUtil() {}

Reply via email to