Commit: 6559b74b30ff295f92dc1b94571be138204df75b Author: Matt Ficken <v-maf...@microsoft.com> Wed, 12 Jun 2013 22:33:30 -0700 Parents: eca7d4fc66aaa4f8eaa3cb61e9551c9a7cfbe3ea Branches: master
Link: http://git.php.net/?p=pftt2.git;a=commitdiff;h=6559b74b30ff295f92dc1b94571be138204df75b Log: use HTTP instead of TCP to check web server is ready Former-commit-id: 07941a5e63378102aabecbb8da91a64023c02223 Changed paths: M src/com/mostc/pftt/main/PfttMain.java M src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java M src/com/mostc/pftt/model/sapi/ApacheManager.java M src/com/mostc/pftt/model/sapi/BuiltinWebServerManager.java M src/com/mostc/pftt/model/sapi/IISManager.java M src/com/mostc/pftt/model/sapi/WebServerManager.java M src/com/mostc/pftt/results/PhpUnitResultReader.java M src/com/mostc/pftt/results/PhptResultWriter.java
diff --git a/src/com/mostc/pftt/main/PfttMain.java b/src/com/mostc/pftt/main/PfttMain.java index 3356b6b..3a94984 100644 --- a/src/com/mostc/pftt/main/PfttMain.java +++ b/src/com/mostc/pftt/main/PfttMain.java @@ -79,7 +79,11 @@ import com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair; // doesn't resort to brittle shell scripts // TODO http request to web server to make sure its running (instead of just tcp socket) +// TODO for SKIP and XSKIP tests, include output and sapi-output in result-pack // TODO mysql, postgresql scenario +// TODO create TIMEOUT status for PHPT and phpunit tests +// modify evaluation critieria to mark those tests as TIMEOUT +// add TIMEOUT status to report pages (list at end of report ; highlight summary in yellow if TIMEOUT > 0) // TODO valgrind gdb? // TODO linux installer diff --git a/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java b/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java index bf4c910..b3642f4 100644 --- a/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java +++ b/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java @@ -1,13 +1,17 @@ package com.mostc.pftt.model.sapi; +import java.io.FileNotFoundException; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; +import java.net.URL; +import java.net.URLConnection; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.atomic.AtomicInteger; +import com.github.mattficken.Overridable; import com.mostc.pftt.host.AHost; import com.mostc.pftt.host.LocalHost; import com.mostc.pftt.host.AHost.ExecHandle; @@ -60,26 +64,62 @@ public abstract class AbstractManagedProcessesWebServerManager extends WebServer public int attempts; } - public static CouldConnect canConnect(String listen_address, int port) { + /** makes sure the web server is running and accepting connections. + * + * @param listen_address + * @param port + * @param double_sure - if TRUE, sends HTTP request, if FALSE just does TCP socket. + * TCP (!double_sure) is much faster, HTTP is much slower (only use HTTP when you think it might not work) + * @return + */ + public static CouldConnect canConnect(String listen_address, int port, boolean double_sure) { Socket sock = null; CouldConnect could = new CouldConnect(); could.start_time = System.currentTimeMillis(); - // builtin web server needs many attempts and large timeouts - for ( could.attempts=0 ; could.attempts < 10 ; could.attempts++ ) { - could.connect = false; - try { - sock = new Socket(); - sock.setSoTimeout(Math.max(200, Math.min(60000, 100*((int)(Math.pow(could.attempts+1, could.attempts+1)))))); - sock.connect(new InetSocketAddress(listen_address, port)); - if (sock.isConnected()) { + + if (double_sure) { + for ( could.attempts=0 ; could.attempts < 10 ; could.attempts++ ) { + could.connect = false; + + try { + final int timeout = Math.max(200, Math.min(60000, 100*((int)(Math.pow(could.attempts+1, could.attempts+1))))); + + URL url = new URL("http://"+listen_address+":"+port+"/"); + URLConnection uc = url.openConnection(); + uc.setConnectTimeout(timeout); + uc.setReadTimeout(timeout); + uc.connect(); + uc.getInputStream(); + could.connect = true; return could; + } catch ( FileNotFoundException ex ) { + // got HTTP 404 response from web server - which means its up and responding to HTTP requests + // (regardless of whether or not that page actually exists) + could.connect = true; + return could; + } catch ( IOException ex ) { + // did not get HTTP response (may not have been able to do TCP connect/accept even) } - } catch ( IOException ex ) { - } finally { + } + } else { + // builtin web server needs many attempts and large timeouts + for ( could.attempts=0 ; could.attempts < 10 ; could.attempts++ ) { + could.connect = false; try { - sock.close(); - } catch (IOException e) { + sock = new Socket(); + sock.setSoTimeout(Math.max(200, Math.min(60000, 100*((int)(Math.pow(could.attempts+1, could.attempts+1)))))); + sock.connect(new InetSocketAddress(listen_address, port)); + if (sock.isConnected()) { + could.connect = true; + return could; + } + } catch ( IOException ex ) { + } finally { + try { + sock.close(); + } catch (IOException e) { + } } } } @@ -89,7 +129,7 @@ public abstract class AbstractManagedProcessesWebServerManager extends WebServer static final int MAX_TOTAL_ATTEMPTS = 3; @Override - protected WebServerInstance createWebServerInstance(ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpIni ini, Map<String,String> env, final String docroot, final boolean debugger_attached, final Object server_name) { + protected WebServerInstance createWebServerInstance(ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpIni ini, Map<String,String> env, final String docroot, final boolean debugger_attached, final Object server_name, boolean is_replacement) { String sapi_output = ""; int port_attempts; boolean found_port; @@ -137,7 +177,12 @@ public abstract class AbstractManagedProcessesWebServerManager extends WebServer final AHost.ExecHandle handlef = handle; // ensure server can be connected to - CouldConnect could = canConnect(listen_address, port); + // + // only use HTTP to check, if its a replacement web server + // this makes a real difference in test speed: use TCP only for the first web server + // (since most of the time it will work, web servers that have to be replaced are the ones + // to likely have a problem) + CouldConnect could = _canConnect(listen_address, port, is_replacement); if (!could.connect) { // kill server and try again throw new IOException("Could not socket to web server after it was started. Web server did not respond to socket. Tried "+could.attempts+" times, waiting "+(System.currentTimeMillis()-could.start_time)+" millis total."); @@ -207,6 +252,11 @@ public abstract class AbstractManagedProcessesWebServerManager extends WebServer return new CrashedWebServerInstance(this, ini, env, sapi_output); } // end protected WebServerInstance createWebServerInstance + @Overridable + protected CouldConnect _canConnect(String listen_address, int port, boolean is_replacement) { + return canConnect(listen_address, port, is_replacement); + } + protected abstract ManagedProcessWebServerInstance createManagedProcessWebServerInstance(ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpIni ini, Map<String, String> env, String docroot, String listen_address, int port); public abstract class ManagedProcessWebServerInstance extends WebServerInstance { diff --git a/src/com/mostc/pftt/model/sapi/ApacheManager.java b/src/com/mostc/pftt/model/sapi/ApacheManager.java index dfb987d..0bf9910 100644 --- a/src/com/mostc/pftt/model/sapi/ApacheManager.java +++ b/src/com/mostc/pftt/model/sapi/ApacheManager.java @@ -508,7 +508,7 @@ public class ApacheManager extends AbstractManagedProcessesWebServerManager { EApacheVersion apache_version = decideApacheVersion(cm, host, build, this._apache_version); final String listen_address = "0.0.0.0"; final int port = 80; - CouldConnect could = canConnect(listen_address, port); + CouldConnect could = canConnect(listen_address, port, false); if (could.connect) { cm.println(EPrintType.CLUE, "ApacheManager", "A web server is already running"); cm.println(EPrintType.TIP, "ApacheManager", "Try `stop -c apache "+build.getBuildPath()+"` to stop Apache"); @@ -532,7 +532,7 @@ public class ApacheManager extends AbstractManagedProcessesWebServerManager { cm.addGlobalException(EPrintType.CANT_CONTINUE, getClass(), "start", ex, "Unable to Start Apache after setup", prep.httpd, prep.apache_conf_file); return false; } - if (canConnect(listen_address, port).connect) { + if (canConnect(listen_address, port, false).connect) { cm.println(EPrintType.CLUE, "ApacheManager", "Apache running\nDocument Root: "+docroot+"\nURL: http://"+listen_address+":"+port+"/"); return true; } else { diff --git a/src/com/mostc/pftt/model/sapi/BuiltinWebServerManager.java b/src/com/mostc/pftt/model/sapi/BuiltinWebServerManager.java index eb6d4e3..19b2dd0 100644 --- a/src/com/mostc/pftt/model/sapi/BuiltinWebServerManager.java +++ b/src/com/mostc/pftt/model/sapi/BuiltinWebServerManager.java @@ -34,6 +34,22 @@ public class BuiltinWebServerManager extends AbstractManagedProcessesWebServerMa } @Override + protected CouldConnect _canConnect(String listen_address, int port, boolean is_replacement) { + // process startup is slow (especially on Windows) + // and builtin_web is kind of buggy + // + // give it extra time before we have to give up and try again (kill process and start another)start another process) + CouldConnect c = super._canConnect(listen_address, port, is_replacement); + if (c.connect) + return c; + CouldConnect c2 = super._canConnect(listen_address, port, is_replacement); + if (c2.connect) + return c2; + c.attempts += c2.attempts; // merge time and number of attempts from both for result-pack + return c; + } + + @Override protected ManagedProcessWebServerInstance createManagedProcessWebServerInstance(ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpIni ini, Map<String, String> env, String docroot, String listen_address, int port) { // run `php.exe -S listen_address:NNNN` in docroot String ini_dir; diff --git a/src/com/mostc/pftt/model/sapi/IISManager.java b/src/com/mostc/pftt/model/sapi/IISManager.java index bfdee9c..c10ba90 100644 --- a/src/com/mostc/pftt/model/sapi/IISManager.java +++ b/src/com/mostc/pftt/model/sapi/IISManager.java @@ -165,7 +165,7 @@ public class IISManager extends WebServerManager { } @Override - protected WebServerInstance createWebServerInstance(ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpIni ini, Map<String,String> env, String doc_root, boolean debugger_attached, Object server_name) { + protected WebServerInstance createWebServerInstance(ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpIni ini, Map<String,String> env, String doc_root, boolean debugger_attached, Object server_name, boolean is_replacement) { final String listen_address = host.getLocalhostListenAddress(); final int listen_port = 80; diff --git a/src/com/mostc/pftt/model/sapi/WebServerManager.java b/src/com/mostc/pftt/model/sapi/WebServerManager.java index 65d8526..d1683a7 100644 --- a/src/com/mostc/pftt/model/sapi/WebServerManager.java +++ b/src/com/mostc/pftt/model/sapi/WebServerManager.java @@ -124,12 +124,12 @@ public abstract class WebServerManager extends SAPIManager { } } - assigned.replacement = sapi = createWebServerInstance(cm, host, scenario_set, build, ini, env, docroot, debugger_attached, server_name); + assigned.replacement = sapi = createWebServerInstance(cm, host, scenario_set, build, ini, env, docroot, debugger_attached, server_name, true); synchronized(assigned.active_test_cases) { sapi.active_test_cases.addAll(assigned.active_test_cases); } } else { - sapi = createWebServerInstance(cm, host, scenario_set, build, ini, env, docroot, debugger_attached, server_name); + sapi = createWebServerInstance(cm, host, scenario_set, build, ini, env, docroot, debugger_attached, server_name, false); } if (sapi.isRunning()) { synchronized(instances) { @@ -155,7 +155,7 @@ public abstract class WebServerManager extends SAPIManager { return env; } - protected abstract WebServerInstance createWebServerInstance(ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpIni ini, Map<String,String> env, String docroot, boolean debugger_attached, Object server_name); + protected abstract WebServerInstance createWebServerInstance(ConsoleManager cm, AHost host, ScenarioSet scenario_set, PhpBuild build, PhpIni ini, Map<String,String> env, String docroot, boolean debugger_attached, Object server_name, boolean is_replacement); /** some web servers can only have one active instance at any one time * diff --git a/src/com/mostc/pftt/results/PhpUnitResultReader.java b/src/com/mostc/pftt/results/PhpUnitResultReader.java index c72b4ac..38e32a4 100644 --- a/src/com/mostc/pftt/results/PhpUnitResultReader.java +++ b/src/com/mostc/pftt/results/PhpUnitResultReader.java @@ -170,12 +170,14 @@ public class PhpUnitResultReader extends AbstractPhpUnitRW { @Override public int count(EPhpUnitTestStatus status) { - return status_list_map.get(status).count; + StatusListEntry e = status_list_map.get(status); + return e==null ? 0 : e.count; } @Override public List<String> getTestNames(EPhpUnitTestStatus status) { - return status_list_map.get(status).test_names; + StatusListEntry e = status_list_map.get(status); + return e==null ? new java.util.ArrayList<String>(0) : e.test_names; } @Override diff --git a/src/com/mostc/pftt/results/PhptResultWriter.java b/src/com/mostc/pftt/results/PhptResultWriter.java index f75fb32..19a3533 100644 --- a/src/com/mostc/pftt/results/PhptResultWriter.java +++ b/src/com/mostc/pftt/results/PhptResultWriter.java @@ -148,7 +148,7 @@ public class PhptResultWriter extends AbstractPhptRW { for ( StatusListEntry e : status_list_map.values() ) e.close(); - if (test_count==0) { + if (count==0) { dir.delete(); } } // end public void close