Commit: 623984c0551588670aa414b298fa256957b49bf5 Author: Matt Ficken <v-maf...@microsoft.com> Thu, 12 Sep 2013 15:21:36 -0700 Parents: 57572767543b8d116466755f855ec09f611b25df Branches: master
Link: http://git.php.net/?p=pftt2.git;a=commitdiff;h=623984c0551588670aa414b298fa256957b49bf5 Log: update required-features smoke test Former-commit-id: 8e14ef49b15d9abfa2b1ecc9718126c79df3d0c0 Changed paths: M src/com/mostc/pftt/model/app/PhpUnitDist.java M src/com/mostc/pftt/model/app/PhpUnitTemplate.groovy M src/com/mostc/pftt/model/core/PhpIni.java M src/com/mostc/pftt/model/core/PhpParser.java M src/com/mostc/pftt/model/core/PhptSourceTestPack.java M src/com/mostc/pftt/model/core/PhptTestCase.java M src/com/mostc/pftt/model/sapi/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/CliSAPIInstance.java M src/com/mostc/pftt/model/sapi/CrashedWebServerInstance.java M src/com/mostc/pftt/model/sapi/IISManager.java M src/com/mostc/pftt/model/sapi/SAPIInstance.java M src/com/mostc/pftt/model/sapi/TestCaseGroupKey.java M src/com/mostc/pftt/model/sapi/WebServerInstance.java M src/com/mostc/pftt/model/sapi/WebServerManager.java M src/com/mostc/pftt/model/smoke/RequiredFeaturesSmokeTest.java M src/com/mostc/pftt/results/ConsoleManager.java M src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java M src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java M src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java M src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.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/DatabaseScenario.java M src/com/mostc/pftt/scenario/IScenarioSetup.java M src/com/mostc/pftt/scenario/MSSQLScenario.java M src/com/mostc/pftt/scenario/MySQLScenario.java M src/com/mostc/pftt/scenario/NginxScenario.java M src/com/mostc/pftt/scenario/ODBCScenario.java M src/com/mostc/pftt/scenario/PostgresSQLScenario.java M src/com/mostc/pftt/scenario/ProductionWebServerScenario.java M src/com/mostc/pftt/scenario/SAPIScenario.java M src/com/mostc/pftt/scenario/SimpleScenarioSetup.java M src/com/mostc/pftt/scenario/WebServerScenario.java
diff --git a/src/com/mostc/pftt/model/app/PhpUnitDist.java b/src/com/mostc/pftt/model/app/PhpUnitDist.java index c0b6dc2..66fb61e 100644 --- a/src/com/mostc/pftt/model/app/PhpUnitDist.java +++ b/src/com/mostc/pftt/model/app/PhpUnitDist.java @@ -85,7 +85,7 @@ public class PhpUnitDist { if (_include_path!=null) return _include_path; - String pear_path = host.joinIntoOnePath(host.getPfttDir(), "/cache/util/PEAR/pear"); + String pear_path = host.joinIntoOnePath(host.getPfttCacheDir(), "/util/PEAR/pear"); return _include_path = host.joinMultiplePaths(host.joinMultiplePaths(src_test_pack.include_dirs, pear_path), path.getAbsolutePath()); } diff --git a/src/com/mostc/pftt/model/app/PhpUnitTemplate.groovy b/src/com/mostc/pftt/model/app/PhpUnitTemplate.groovy index 7cc4233..75ccef1 100644 --- a/src/com/mostc/pftt/model/app/PhpUnitTemplate.groovy +++ b/src/com/mostc/pftt/model/app/PhpUnitTemplate.groovy @@ -484,4 +484,29 @@ ob_end_clean(); * */ + public static String renderXDebugPhptTemplate(String php_code) { + // add php code to collect code coverage data and output it + return """<?php +xdebug_start_code_coverage( XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE ); +function dump_coverage() { + echo PHP_EOL; + foreach ( xdebug_get_code_coverage() as \$filename => \$coverage ) { + echo "file=\$filename"; echo PHP_EOL; + foreach ( \$coverage as \$line_num => \$type ) { + if (\$type==1) { + echo "exe=\$line_num"; echo PHP_EOL; + } else if (\$type==-1) { + echo "didnt_exe=\$line_num"; echo PHP_EOL; + } else if (\$type==-2) { + echo "no_exe=\$line_num"; echo PHP_EOL; + } + } + xdebug_stop_code_coverage(TRUE); + } +} +register_shutdown_function('dump_coverage'); +?>""".replace("\r", "").replace("\n", " ") + php_code + // reduce the added php code to 1 extra line (remove \n) + } + } // end class PhpUnitTemplate diff --git a/src/com/mostc/pftt/model/core/PhpIni.java b/src/com/mostc/pftt/model/core/PhpIni.java index fb0803b..dc4182d 100644 --- a/src/com/mostc/pftt/model/core/PhpIni.java +++ b/src/com/mostc/pftt/model/core/PhpIni.java @@ -594,4 +594,12 @@ public class PhpIni { static final Pattern PAT_pipe = Pattern.compile("\\|"); static final Pattern PAT_per = Pattern.compile("\\%"); + public boolean containsAny(String ...directives) { + for ( String d : directives ) { + if (containsKey(d)) + return true; + } + return false; + } + } // end public class PhpIni diff --git a/src/com/mostc/pftt/model/core/PhpParser.java b/src/com/mostc/pftt/model/core/PhpParser.java index 9776bc1..d7b2923 100644 --- a/src/com/mostc/pftt/model/core/PhpParser.java +++ b/src/com/mostc/pftt/model/core/PhpParser.java @@ -153,8 +153,9 @@ public class PhpParser { return new ClassDefinition[]{}; } else { Collection<InterpretedClassDef> clazzes = prog.getClasses(); - ClassDefinition[] defs = new ClassDefinition[clazzes.size()]; + ClassDefinition[] defs = new ClassDefinition[clazzes.size()+1]; int i=0; + defs[i++] = new MainClassDefinition(env, this, prog.getStatement()); for ( InterpretedClassDef clazz : clazzes ) defs[i++] = new ClassDefinition(env, this, clazz); return defs; @@ -687,6 +688,47 @@ public class PhpParser { } // end public static abstract class CodeBlock + public static class MainClassDefinition extends ClassDefinition { + protected final Statement stmt; + protected MainClassDefinition(Env env, PhpScript ps, Statement stmt) { + super(env, ps, null); + this.stmt = stmt; + } + public String getName() { + return "<main>"; + } + public Field[] getFields() { + return new Field[]{}; + } + public FunctionDefinition[] getFunctions() { + return new FunctionDefinition[] { + new FunctionDefinition(env, this, stmt) + }; + } + public boolean isInterface() { + return false; + } + public boolean isAbstract() { + return false; + } + public boolean isFinal() { + return false; + } + @Override + public boolean equals(Object o) { + if (o==this) + return true; + else if (o instanceof MainClassDefinition) + return true; + else + return toString().equals(o.toString()); + } + @Override + public String toString() { + return getName(); + } + } + public static class ClassDefinition extends CodeBlock { protected final ClassDef clazz; protected final PhpScript ps; @@ -887,23 +929,33 @@ public class PhpParser { public static class FunctionDefinition extends CodeBlock { protected final AbstractFunction def; protected final ClassDefinition clazz; + protected final BlockStatement stmt; protected FunctionDefinition(Env env, ClassDefinition clazz, AbstractFunction def) { super(env); this.def = def; this.clazz = clazz; + this.stmt = def instanceof Function && ((Function)def)._statement instanceof BlockStatement ? + ((BlockStatement)((Function)def)._statement) : null; } + public FunctionDefinition(Env env, MainClassDefinition clazz, Statement stmt) { + super(env); + this.def = null; + this.clazz = clazz; + this.stmt = stmt instanceof BlockStatement ? (BlockStatement) stmt : null; + } + public int getLineNumber() { - return def.getLocation().getLineNumber(); + return def==null?0:def.getLocation().getLineNumber(); } public String getClassName() { - return def.getLocation().getClassName(); + return def==null?"":def.getLocation().getClassName(); } public String getFileName() { - return def.getLocation().getFileName(); + return def==null?"":def.getLocation().getFileName(); } public ClassDefinition getClassDefinition() { @@ -916,11 +968,11 @@ public class PhpParser { */ @Override public String getName() { - return def.getName(); + return def==null?"":def.getName(); } public int getArgumentCount() { - return def.getArgs().length; + return def==null?0:def.getArgs().length; } /** returns the arguments this function accepts @@ -928,6 +980,8 @@ public class PhpParser { * @return */ public VariableValue[] getArguments() { + if (def==null) + return new VariableValue[]{}; Arg[] args = def.getArgs(); VariableValue[] val = new VariableValue[args.length]; int i=0; @@ -946,12 +1000,12 @@ public class PhpParser { */ public FunctionCall[] getCalls() { ArrayList<FunctionCall> out = new ArrayList<FunctionCall>(2); - if (def instanceof Function && ((Function)def)._statement instanceof BlockStatement) { + if (stmt != null) { String call_name, class_name; int i; AbstractFunction f; QuercusClass qc; - for ( Statement st : ((BlockStatement)((Function)def)._statement)._statements ) { + for ( Statement st : stmt._statements ) { if (st instanceof ExprStatement) { Expr expr = ((ExprStatement)st)._expr; if (expr instanceof CallExpr) { diff --git a/src/com/mostc/pftt/model/core/PhptSourceTestPack.java b/src/com/mostc/pftt/model/core/PhptSourceTestPack.java index a1c7119..230301d 100644 --- a/src/com/mostc/pftt/model/core/PhptSourceTestPack.java +++ b/src/com/mostc/pftt/model/core/PhptSourceTestPack.java @@ -51,7 +51,11 @@ public class PhptSourceTestPack implements SourceTestPack<PhptActiveTestPack, Ph return getSourceDirectory(); } - public boolean open(ConsoleManager cm, AHost host) { + public String getTestPackConfigFilePath() { + return getSourceDirectory()+"/config.pftt.groovy"; + } + + public boolean open(ConsoleManager cm, Config config, AHost host) { if (StringUtil.endsWithIC(this.test_pack, ".zip")) { // automatically decompress build String zip_file = test_pack; @@ -63,7 +67,20 @@ public class PhptSourceTestPack implements SourceTestPack<PhptActiveTestPack, Ph this.host = host; this.test_pack = host.fixPath(test_pack); - return host.exists(this.test_pack); + if (host.exists(this.test_pack)) { + String config_file = getTestPackConfigFilePath(); + if (host.exists(config_file)) { + try { + config.addConfigFile(cm, new File(config_file)); + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CLUE, getClass(), "open", ex, "Unable to load test-pack configuration"); + } + } + + return true; + } else { + return false; + } } @Override @@ -86,6 +103,8 @@ public class PhptSourceTestPack implements SourceTestPack<PhptActiveTestPack, Ph // these are symlinks(junctions) which may cause an infinite loop // // normally, they are deleted, but if certain tests were interrupted, they may still be there + host.deleteIfExists(test_pack+"/ext/standard/tests/file/a_dir"); + host.deleteIfExists(test_pack+"/ext/standard/tests/file/a_jdir"); host.deleteIfExists(test_pack+"/ext/standard/tests/file/12345"); host.deleteIfExists(test_pack+"/ext/standard/tests/file/clearstatcache_001.php_link1"); host.deleteIfExists(test_pack+"/ext/standard/tests/file/clearstatcache_001.php_link2"); diff --git a/src/com/mostc/pftt/model/core/PhptTestCase.java b/src/com/mostc/pftt/model/core/PhptTestCase.java index 4b47f14..cc06a13 100644 --- a/src/com/mostc/pftt/model/core/PhptTestCase.java +++ b/src/com/mostc/pftt/model/core/PhptTestCase.java @@ -66,6 +66,7 @@ public class PhptTestCase extends TestCase { * * Reminder: if -no-nts console option is used, this list is ignored (that option allows tests to be run on any thread regardless of thread-safety) * */ + // TODO SOMEDAY store this list in the test-pack's PFTT configuration file public static final String[][] NON_THREAD_SAFE_EXTENSIONS = new String[][]{ // split up the ext/standard/tests/file PHPTs // they can be run in 1 thread, but split them into several threads so they'll all finish faster @@ -81,12 +82,13 @@ public class PhptTestCase extends TestCase { new String[]{"ext/standard/tests/file/windows_acls/", "ext/standard/tests/file/windows_links/"}, // note: this array is processed in order, so this entry will catch any remaining /file/ phpts new String[]{"ext/standard/tests/dir/"}, + new String[]{"ext/standard/tests/string/fprint"}, new String[]{"ext/standard/tests/streams/stream_get_"}, new String[]{"ext/standard/tests/streams/stream_set_"}, new String[]{"ext/standard/tests/streams/"}, new String[]{"ext/standard/tests/sockets/", "ext/sockets/"}, new String[]{"ext/mysqli/tests/0", "ext/mysqli/tests/bug"}, - new String[]{"ext/phar/tests/frontcontroller", "ext/phar/tests/cache_list/copyonwrite", "ext/phar/tests/zip/copyonwrite", "ext/phar/tests/tar/copyonwrite", "ext/phar/cache_list/frontcontroller", "ext/phar/zip/frontcontroller", "ext/phar/tar/frontcontroller"}, + new String[]{"ext/mbstring/tests/mb_output_"}, new String[]{"ext/pgsql/"}, new String[]{"ext/pdo_pgsql/"}, // several 61367 tests that aren't thread-safe (temp files) @@ -104,8 +106,10 @@ public class PhptTestCase extends TestCase { new String[]{"ext/soap/"}, new String[]{"ext/fileinfo/"}, new String[]{"ext/ldap/"}, - new String[]{"ext/spl/tests/splfileobject_fputcsv_"}, // TODO - new String[]{"ext/spl/tests/splfileobject_fgetcsv_"} + new String[]{"ext/spl/tests/splfileobject_fputcsv_"}, + new String[]{"ext/spl/tests/splfileobject_fgetcsv_"}, + new String[]{"ext/pdo_sqlsrv/tests/"}, + new String[]{"ext/sqlsrv/tests/"}, }; // PHPT test files end with .phpt public static final String PHPT_FILE_EXTENSION = ".phpt"; @@ -1034,8 +1038,16 @@ public class PhptTestCase extends TestCase { * @return */ public boolean isSlowTest() { - return isExtension("phar") || isExtension("standard/tests/streams") || isNamed(SLOW_TESTS); + return isExtension(SLOW_EXTS) || isNamed(SLOW_TESTS); } + public static Trie SLOW_EXTS = createExtensions( + "tests/security", + "phar", + "ctype", + "spl/tests/spl_autoload_", + "session", + "standard/tests/streams" + ); public static Trie SLOW_TESTS = createNamed( // tests that check the SKIP_SLOW_TESTS env var (ie tests considered slow by their authors) // @@ -1107,6 +1119,67 @@ public class PhptTestCase extends TestCase { "ext/session/tests/020.phpt", "zend/tests/unset_cv05.phpt" ); + public static int hashCode(PhpIni ini) { + if (ini==null) + return 1; + int hc = 1; + for ( String d : DECISIVE_DIRECTIVES ) { + String v = ini.get(d); + if (v!=null) + hc += v.hashCode(); + } + return hc; + } + public static final String[] DECISIVE_DIRECTIVES = new String[]{ + //"filter.default", + //"mbstring.internal_encoding", + //"mbstring.http_output_conv_mimetypes", + //"output_handler", + "output_buffering", + "precision", + "error_reporting", + //"session.serialize_handler", + //"html_errors", + //"open_basedir", + //"unicode.output_encoding", + //"session.save_handler", + //"session.auto_start" + //"phar.require_hash", + "phar.readonly", + //"allow_url_fopen" + }; + /** some INI directives will affect the result of a test case (`the decisive directives`) + * + * This determines if the two PhpInis are either equal (the same) or + * have the `decisive directives` are at least equal. + * + * @param a + * @param b + * @return + */ + public static boolean isEquivalentForTestCase(PhpIni a, PhpIni b) { + if (a==null) + return b==null || !b.containsAny(DECISIVE_DIRECTIVES); + else if (b==null) + return a==null || !a.containsAny(DECISIVE_DIRECTIVES); + else if (a.equals(b)) + return true; + String sa, sb; + for ( String d : DECISIVE_DIRECTIVES ) { + sa = a.get(d); + sb = b.get(d); + if (sa==null) { + if (StringUtil.isNotEmpty(sb)) + return false; + } else if (sb==null) { + if (StringUtil.isNotEmpty(sa)) + return false; + } else if (!sa.equalsIgnoreCase(sb)) { + return false; + } + } + return true; + } public static DefaultCharsetDeciderDecoder newCharsetDeciderDecoder() { return new DefaultCharsetDeciderDecoder(CharsetDeciderDecoder.EXPRESS_RECOGNIZERS); diff --git a/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java b/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java index db1506e..1f0b75e 100644 --- a/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java +++ b/src/com/mostc/pftt/model/sapi/AbstractManagedProcessesWebServerManager.java @@ -228,7 +228,7 @@ public abstract class AbstractManagedProcessesWebServerManager extends WebServer } } finally { // don't need to check any more - thread.cancel(); + thread.close(); } } } // end public void run @@ -249,7 +249,7 @@ public abstract class AbstractManagedProcessesWebServerManager extends WebServer sapi_output = "PFTT: could not start web server instance (after "+total_attempts+" attempts)... giving up.\n" + sapi_output; // return this failure message to client code - return new CrashedWebServerInstance(this, ini, env, sapi_output); + return new CrashedWebServerInstance(host, this, ini, env, sapi_output); } // end protected WebServerInstance createWebServerInstance @Overridable @@ -266,8 +266,8 @@ public abstract class AbstractManagedProcessesWebServerManager extends WebServer protected final String docroot; protected ExecHandle process; - public ManagedProcessWebServerInstance(AbstractManagedProcessesWebServerManager ws_mgr, String docroot, String cmd, PhpIni ini, Map<String,String> env, String hostname, int port) { - super(ws_mgr, LocalHost.splitCmdString(cmd), ini, env); + public ManagedProcessWebServerInstance(AHost host, AbstractManagedProcessesWebServerManager ws_mgr, String docroot, String cmd, PhpIni ini, Map<String,String> env, String hostname, int port) { + super(host, ws_mgr, LocalHost.splitCmdString(cmd), ini, env); this.docroot = docroot; this.cmd = cmd; this.hostname = hostname; diff --git a/src/com/mostc/pftt/model/sapi/ApacheManager.java b/src/com/mostc/pftt/model/sapi/ApacheManager.java index 56a2e59..4f405e7 100644 --- a/src/com/mostc/pftt/model/sapi/ApacheManager.java +++ b/src/com/mostc/pftt/model/sapi/ApacheManager.java @@ -247,16 +247,14 @@ public class ApacheManager extends AbstractManagedProcessesWebServerManager { public class ApacheWebServerInstance extends ManagedProcessWebServerInstance { protected final String conf_dir, apache_conf_file, conf_str, error_log, apache_version_str; - protected final AHost host; protected final PhpBuild build; protected final EApacheVersion apache_version; protected SoftReference<String> log_ref; public ApacheWebServerInstance(EApacheVersion apache_version, PhpBuild build, ApacheManager ws_mgr, String docroot, String cmd, PhpIni ini, Map<String,String> env, String hostname, int port, AHost host, String conf_dir, String apache_conf_file, String error_log, String conf_str, String apache_version_str) { - super(ws_mgr, docroot, cmd, ini, env, hostname, port); + super(host, ws_mgr, docroot, cmd, ini, env, hostname, port); this.build = build; this.apache_version = apache_version; - this.host = host; this.conf_dir = conf_dir; this.apache_conf_file = apache_conf_file; this.error_log = error_log; diff --git a/src/com/mostc/pftt/model/sapi/BuiltinWebServerManager.java b/src/com/mostc/pftt/model/sapi/BuiltinWebServerManager.java index 6ba3279..e3d5d0e 100644 --- a/src/com/mostc/pftt/model/sapi/BuiltinWebServerManager.java +++ b/src/com/mostc/pftt/model/sapi/BuiltinWebServerManager.java @@ -68,11 +68,9 @@ public class BuiltinWebServerManager extends AbstractManagedProcessesWebServerMa public class BuiltinWebServerInstance extends ManagedProcessWebServerInstance { protected final PhpBuild build; - protected final AHost host; public BuiltinWebServerInstance(BuiltinWebServerManager ws_mgr, AHost host, PhpBuild build, String docroot, String cmd, PhpIni ini, Map<String,String> env, String hostname, int port) { - super(ws_mgr, docroot, cmd, ini, env, hostname, port); - this.host = host; + super(host, ws_mgr, docroot, cmd, ini, env, hostname, port); this.build = build; } diff --git a/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java b/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java index 50926af..0843d4c 100644 --- a/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java +++ b/src/com/mostc/pftt/model/sapi/CliSAPIInstance.java @@ -11,15 +11,20 @@ import com.mostc.pftt.model.core.PhpIni; import com.mostc.pftt.results.ConsoleManager; public class CliSAPIInstance extends SAPIInstance { - protected final AHost host; protected final PhpBuild build; - protected final PhpIni ini; protected String ini_dir; public CliSAPIInstance(AHost host, PhpBuild build, PhpIni ini) { - this.host = host; + super(host, ini); this.build = build; - this.ini = ini; + } + + @Override + protected String doGetIniActual(String php_code) throws Exception { + return build.eval(host, php_code) + .printHasFatalError(getClass().getSimpleName(), (ConsoleManager)null) + .cleanupSuccess(host) + .output; } public void prepare() throws Exception { diff --git a/src/com/mostc/pftt/model/sapi/CrashedWebServerInstance.java b/src/com/mostc/pftt/model/sapi/CrashedWebServerInstance.java index 8b2b3e1..1753d79 100644 --- a/src/com/mostc/pftt/model/sapi/CrashedWebServerInstance.java +++ b/src/com/mostc/pftt/model/sapi/CrashedWebServerInstance.java @@ -2,6 +2,7 @@ package com.mostc.pftt.model.sapi; import java.util.Map; +import com.mostc.pftt.host.AHost; import com.mostc.pftt.model.core.PhpIni; import com.mostc.pftt.results.ConsoleManager; @@ -18,12 +19,12 @@ public class CrashedWebServerInstance extends WebServerInstance { protected final String sapi_output; protected final String instance_info; - public CrashedWebServerInstance(WebServerManager ws_mgr, PhpIni ini, Map<String,String> env, String sapi_output) { - this(ws_mgr, ini, env, sapi_output, null); + public CrashedWebServerInstance(AHost host, WebServerManager ws_mgr, PhpIni ini, Map<String,String> env, String sapi_output) { + this(host, ws_mgr, ini, env, sapi_output, null); } - public CrashedWebServerInstance(WebServerManager ws_mgr, PhpIni ini, Map<String,String> env, String sapi_output, String instance_info) { - super(ws_mgr, null, ini, env); + public CrashedWebServerInstance(AHost host, WebServerManager ws_mgr, PhpIni ini, Map<String,String> env, String sapi_output, String instance_info) { + super(host, ws_mgr, null, ini, env); this.sapi_output = sapi_output; this.instance_info = instance_info; } diff --git a/src/com/mostc/pftt/model/sapi/IISManager.java b/src/com/mostc/pftt/model/sapi/IISManager.java index 4c2e71b..fdd5c55 100644 --- a/src/com/mostc/pftt/model/sapi/IISManager.java +++ b/src/com/mostc/pftt/model/sapi/IISManager.java @@ -107,7 +107,7 @@ public class IISManager extends AbstractManagedProcessesWebServerManager { env = prepareENV(env, prep.php_conf_file, build, scenario_set, build.getPhpCgiExe()); - final String cmdline = host.getPfttDir()+"/cache/dep/IIS/IISRunner "+host.fixPath(prep.iis_conf_file); + final String cmdline = host.getPfttCacheDir()+"/dep/IIS/IISRunner "+host.fixPath(prep.iis_conf_file); // @see #createWebServerInstance for where command is executed to create httpd.exe process return new IISWebServerInstance(this, docroot, cmdline, env, ini, listen_address, port, prep, host, build); @@ -115,14 +115,12 @@ public class IISManager extends AbstractManagedProcessesWebServerManager { public class IISWebServerInstance extends ManagedProcessWebServerInstance { protected final PreparedIIS prep; - protected final AHost host; protected final PhpBuild build; protected SoftReference<String> log_ref; public IISWebServerInstance(IISManager ws_mgr, String docroot, String cmd, Map<String,String> env, PhpIni ini, String hostname, int port, PreparedIIS prep, AHost host, PhpBuild build) { - super(ws_mgr, docroot, cmd, ini, env, hostname, port); + super(host, ws_mgr, docroot, cmd, ini, env, hostname, port); this.build = build; - this.host = host; this.prep = prep; } diff --git a/src/com/mostc/pftt/model/sapi/SAPIInstance.java b/src/com/mostc/pftt/model/sapi/SAPIInstance.java index 8541ffa..972306c 100644 --- a/src/com/mostc/pftt/model/sapi/SAPIInstance.java +++ b/src/com/mostc/pftt/model/sapi/SAPIInstance.java @@ -1,5 +1,9 @@ package com.mostc.pftt.model.sapi; +import java.io.IOException; + +import com.mostc.pftt.host.AHost; +import com.mostc.pftt.model.core.PhpIni; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.scenario.SimpleScenarioSetup; @@ -10,9 +14,39 @@ import com.mostc.pftt.scenario.SimpleScenarioSetup; */ public abstract class SAPIInstance extends SimpleScenarioSetup { + protected final AHost host; + protected final PhpIni ini; + protected String ini_actual; + + public SAPIInstance(AHost host, PhpIni ini) { + this.host = host; + this.ini = ini; + } + public abstract String getSAPIOutput(); public abstract boolean isRunning(); public abstract String getInstanceInfo(ConsoleManager cm); public abstract boolean isCrashedOrDebuggedAndClosed(); public abstract String getSAPIConfig(); + protected abstract String doGetIniActual(String php_code) throws IllegalStateException, IOException, Exception; + + public synchronized String getIniActual() { + if (ini_actual!=null) + return ini_actual; + if (host.isBusy()) + // leave ini_actual NULL so we'll check next time + return null; + try { + ini_actual = doGetIniActual("<?php var_dump($argv);\nvar_dump(ini_get_all()); ?>"); + } catch ( Exception ex ) { + ex.printStackTrace(); + } + if (ini_actual==null) + ini_actual = ""; + return ini_actual; + } + + public boolean isBusy() { + return host.isBusy(); + } } diff --git a/src/com/mostc/pftt/model/sapi/TestCaseGroupKey.java b/src/com/mostc/pftt/model/sapi/TestCaseGroupKey.java index 3c89ff1..5a00e58 100644 --- a/src/com/mostc/pftt/model/sapi/TestCaseGroupKey.java +++ b/src/com/mostc/pftt/model/sapi/TestCaseGroupKey.java @@ -1,17 +1,13 @@ package com.mostc.pftt.model.sapi; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; import com.mostc.pftt.model.core.PhpIni; +import com.mostc.pftt.model.core.PhptTestCase; import com.mostc.pftt.results.ConsoleManager; -import com.mostc.pftt.scenario.IScenarioSetup; -import com.mostc.pftt.scenario.ScenarioSet; import com.mostc.pftt.util.IClosable; /** @@ -23,7 +19,6 @@ import com.mostc.pftt.util.IClosable; public class TestCaseGroupKey implements IClosable { protected final Map<String,String> env; protected final PhpIni ini; - protected List<IScenarioSetup> setups; public TestCaseGroupKey( @Nonnull PhpIni ini, @@ -32,14 +27,6 @@ public class TestCaseGroupKey implements IClosable { this.env = env; } - public TestCaseGroupKey( - @Nonnull PhpIni ini, - @Nullable Map<String,String> env, - ScenarioSet scenario_set) { - this(ini, env); - setups = new ArrayList<IScenarioSetup>(scenario_set.size()); - } - @Override public boolean equals(Object o) { if (o==this) { @@ -47,7 +34,7 @@ public class TestCaseGroupKey implements IClosable { } else if (o instanceof TestCaseGroupKey) { TestCaseGroupKey c = (TestCaseGroupKey) o; return (this.env==null?c.env==null||c.env.isEmpty():this.env.equals(c.env)) && - (this.ini==null?c.ini==null||c.ini.isEmpty():this.ini.equals(c.ini)); + PhptTestCase.isEquivalentForTestCase(this.ini, c.ini); } else { return false; } @@ -55,7 +42,7 @@ public class TestCaseGroupKey implements IClosable { @Override public int hashCode() { - return (env==null?1:env.hashCode()) | (ini==null?1:ini.hashCode()); + return (env==null?1:env.hashCode()) | PhptTestCase.hashCode(ini); } @Nullable @@ -73,18 +60,7 @@ public class TestCaseGroupKey implements IClosable { @Override public void close(ConsoleManager cm) { - if (setups==null) - return; - for ( IScenarioSetup setup : setups ) { - setup.close(cm); - } - } - - public void addSetup(IScenarioSetup setup) { - if (setups==null) - setups = new LinkedList<IScenarioSetup>(); - setups.add(setup); } } // end public class TestCaseGroupKey diff --git a/src/com/mostc/pftt/model/sapi/WebServerInstance.java b/src/com/mostc/pftt/model/sapi/WebServerInstance.java index 8d15c75..58d1b0a 100644 --- a/src/com/mostc/pftt/model/sapi/WebServerInstance.java +++ b/src/com/mostc/pftt/model/sapi/WebServerInstance.java @@ -1,5 +1,7 @@ package com.mostc.pftt.model.sapi; +import java.io.IOException; +import java.net.URL; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -7,6 +9,7 @@ import java.util.Map; import javax.annotation.concurrent.ThreadSafe; +import com.github.mattficken.io.IOUtil; import com.github.mattficken.io.StringUtil; import com.mostc.pftt.host.AHost; import com.mostc.pftt.model.TestCase; @@ -32,7 +35,8 @@ public abstract class WebServerInstance extends SAPIInstance implements IWebServ protected final WebServerManager ws_mgr; WebServerInstance replacement; // @see WebServerManager#getWebServerInstance - public WebServerInstance(WebServerManager ws_mgr, String[] cmd_array, PhpIni ini, Map<String,String> env) { + public WebServerInstance(AHost host, WebServerManager ws_mgr, String[] cmd_array, PhpIni ini, Map<String,String> env) { + super(host, ini); this.ws_mgr = ws_mgr; this.cmd_array = cmd_array; this.ini = ini; @@ -231,4 +235,20 @@ public abstract class WebServerInstance extends SAPIInstance implements IWebServ public abstract String getDocroot(); + protected String httpGet(String url_str, String php_code) throws IllegalStateException, IOException { + String temp_file = host.joinIntoOnePath(getDocroot(), url_str); + if (!host.saveTextFile(temp_file, php_code)) + return ""; + + URL url = new URL("http", getHostname(), getPort(), url_str); + String output = IOUtil.toString(url.openStream(), IOUtil.QUARTER_MEGABYTE); + host.delete(temp_file); + return output; + } + + @Override + protected String doGetIniActual(String php_code) throws IllegalStateException, IOException { + return httpGet("ini_get_all.php", php_code); + } + } // end public abstract class WebServerInstance diff --git a/src/com/mostc/pftt/model/sapi/WebServerManager.java b/src/com/mostc/pftt/model/sapi/WebServerManager.java index 63daa54..aa64cdb 100644 --- a/src/com/mostc/pftt/model/sapi/WebServerManager.java +++ b/src/com/mostc/pftt/model/sapi/WebServerManager.java @@ -8,10 +8,12 @@ import java.util.Map; import javax.annotation.concurrent.ThreadSafe; +import com.github.mattficken.io.StringUtil; import com.mostc.pftt.host.AHost; import com.mostc.pftt.host.Host; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.model.core.PhpIni; +import com.mostc.pftt.model.core.PhptTestCase; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.runner.AbstractPhptTestCaseRunner; import com.mostc.pftt.scenario.IScenarioSetup; @@ -68,22 +70,41 @@ public abstract class WebServerManager extends SAPIManager { } private static boolean eq(WebServerInstance c, boolean debugger_attached, PhpIni ini, Map<String,String> env) { - if (c.isRunning()) - return true; // TODO temp 5/30 - - // TODO note - AbstractManagedProcessesWebServerManager, BuiltinWebServerManager and ApacheManager - // all add to `env` which means this `env` might not match (because its missing some extra keys) - // (what about checking just the values of the keys they both have in common?) if (c.isRunning() && (!debugger_attached||c.isDebuggerAttached())) { - if (c.getPhpIni()!=null&&ini!=null&&c.getPhpIni().equals(ini)) + if (PhptTestCase.isEquivalentForTestCase(c.getPhpIni(), ini)) return true; - if (c.getEnv()!=null&&env!=null&&c.getEnv().equals(env)) + // the two ENVs may not be exactly the same. if 1 ENV has some additional + // variables that the other does not, that is ok. Only the variables they both have MUST match. + else if (equalsOrCommonValues(c.getEnv(), env)) return true; - //return true; } return false; } + protected static boolean equalsOrCommonValues(Map<String, String> a, Map<String, String> b) { + if (a==null) + return b == null || b.isEmpty(); + else if (b==null) + return a == null || a.isEmpty(); + else if (a.equals(b)) + return true; + String va, vb; + for ( String key : a.keySet() ) { + va = a.get(key); + vb = b.get(key); + if (va==null) { + if (StringUtil.isNotEmpty(vb)) + return false; + } else if (vb==null) { + if (StringUtil.isNotEmpty(va)) + return false; + } else if (!vb.equals(va)) { + return false; + } + } + return true; + } + /** gets a running WebServerInstance * * if given an existing assigned WebServerInstance that hasn't crashed and is running, @@ -119,6 +140,8 @@ public abstract class WebServerManager extends SAPIManager { synchronized(c) { if (eq(c, debugger_attached, ini, env)) return c; + else + c.close(cm); } } } diff --git a/src/com/mostc/pftt/model/smoke/RequiredFeaturesSmokeTest.java b/src/com/mostc/pftt/model/smoke/RequiredFeaturesSmokeTest.java index 6d21719..e1860a8 100644 --- a/src/com/mostc/pftt/model/smoke/RequiredFeaturesSmokeTest.java +++ b/src/com/mostc/pftt/model/smoke/RequiredFeaturesSmokeTest.java @@ -487,7 +487,7 @@ public class RequiredFeaturesSmokeTest extends SmokeTest { "%s" + "Session Support => enabled%s" + "Registered save handlers => files user %s" + -"Registered serializer handlers => php php_binary wddx%s" + +"Registered serializer handlers => %sphp php_binary wddx%s" + "%s" + "Directive => Local Value => Master Value%s" + "session.auto_start => Off => Off%s" + @@ -1075,7 +1075,7 @@ public class RequiredFeaturesSmokeTest extends SmokeTest { "%s" + "Session Support => enabled%s" + "Registered save handlers => files user %s" + -"Registered serializer handlers => php php_binary wddx%s" + +"Registered serializer handlers => %sphp php_binary wddx%s" + "%s" + "Directive => Local Value => Master Value%s" + "session.auto_start => Off => Off%s" + diff --git a/src/com/mostc/pftt/results/ConsoleManager.java b/src/com/mostc/pftt/results/ConsoleManager.java index 5fb6951..13780da 100644 --- a/src/com/mostc/pftt/results/ConsoleManager.java +++ b/src/com/mostc/pftt/results/ConsoleManager.java @@ -100,5 +100,6 @@ public interface ConsoleManager { public int getRunCount(); public int getSuspendSeconds(); public boolean isGetActualIniAll(); + public long getMaxRunTimeMillis(); } // end public class ConsoleManager diff --git a/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java b/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java index 72d28dd..6f9e8c4 100644 --- a/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java @@ -25,7 +25,7 @@ import com.mostc.pftt.scenario.ScenarioSetSetup; public class BuiltinWebHttpPhptTestCaseRunner extends HttpPhptTestCaseRunner { - public BuiltinWebHttpPhptTestCaseRunner(BuiltinWebServerScenario sapi_scenario, PhpIni ini, + public BuiltinWebHttpPhptTestCaseRunner(boolean xdebug, BuiltinWebServerScenario sapi_scenario, PhpIni ini, Map<String, String> env, HttpParams params, HttpProcessor httpproc, HttpRequestExecutor httpexecutor, WebServerManager smgr, WebServerInstance web, PhptThread thread, PhptTestCase test_case, @@ -33,7 +33,7 @@ public class BuiltinWebHttpPhptTestCaseRunner extends HttpPhptTestCaseRunner { ScenarioSetSetup scenario_set_setup, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack) { - super(sapi_scenario, ini, env, params, httpproc, httpexecutor, smgr, web, thread, test_case, + super(xdebug, sapi_scenario, ini, env, params, httpproc, httpexecutor, smgr, web, thread, test_case, cm, twriter, host, scenario_set_setup, build, src_test_pack, active_test_pack); } diff --git a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java index 9fd871f..579df29 100644 --- a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java @@ -44,8 +44,8 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { protected ExecOutput output; protected String query_string, shell_script, test_cmd, shell_file; - public CliPhptTestCaseRunner(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) { - super(sapi_scenario, ini, thread, test_case, cm, twriter, host, scenario_set_setup, build, src_test_pack, active_test_pack); + public CliPhptTestCaseRunner(boolean xdebug, CliScenario sapi_scenario, CliSAPIInstance sapi, PhpIni ini, PhptThread thread, PhptTestCase test_case, ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack) { + super(xdebug, sapi_scenario, ini, thread, test_case, cm, twriter, host, scenario_set_setup, build, src_test_pack, active_test_pack); this.sapi = sapi; } @@ -72,11 +72,7 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { @Override public String getIniActual() throws Exception { - // @see #prepareTest - - String ini_get_all_path = get_ini_get_all_path(); - - return ini_get_all_path+sapi.execute(exe_type, ini_get_all_path, null, env, AHost.ONE_MINUTE).output; + return sapi.getIniActual(); } @Override diff --git a/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java b/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java index e489060..74a7982 100644 --- a/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/HttpPhpUnitTestCaseRunner.java @@ -325,7 +325,7 @@ public class HttpPhpUnitTestCaseRunner extends AbstractPhpUnitTestCaseRunner { response.setParams(params); httpexecutor.postProcess(response, httpproc, context); - timeout_task.cancel(); + timeout_task.close(); // // support for HTTP redirects diff --git a/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java b/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java index 0794afd..fafcd4f 100644 --- a/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java @@ -62,8 +62,8 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { protected final HttpRequestExecutor httpexecutor; protected Socket test_socket; - public HttpPhptTestCaseRunner(WebServerScenario sapi_scenario, PhpIni ini, Map<String,String> env, HttpParams params, HttpProcessor httpproc, HttpRequestExecutor httpexecutor, WebServerManager smgr, WebServerInstance web, PhptThread thread, PhptTestCase test_case, ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack) { - super(sapi_scenario, ini, thread, test_case, cm, twriter, host, scenario_set, build, src_test_pack, active_test_pack); + public HttpPhptTestCaseRunner(boolean xdebug, WebServerScenario sapi_scenario, PhpIni ini, Map<String,String> env, HttpParams params, HttpProcessor httpproc, HttpRequestExecutor httpexecutor, WebServerManager smgr, WebServerInstance web, PhptThread thread, PhptTestCase test_case, ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup scenario_set, PhpBuild build, PhptSourceTestPack src_test_pack, PhptActiveTestPack active_test_pack) { + super(xdebug, sapi_scenario, ini, thread, test_case, cm, twriter, host, scenario_set, build, src_test_pack, active_test_pack); this.params = params; this.httpproc = httpproc; this.httpexecutor = httpexecutor; @@ -230,6 +230,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { synchronized(web) { WebServerInstance _web = smgr.getWebServerInstance(cm, host, scenario_set.getScenarioSet(), build, ini, env, active_test_pack.getStorageDirectory(), web, false, test_case); if (_web!=this.web) { + this.web.close(cm); this.web = _web; is_replacement = true; @@ -291,24 +292,9 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { return do_http_get(path, 0); } - @Override // TODO - protected String get_ini_get_all_path() throws IllegalStateException, IOException { - // ensure ini_get_all.php exists - // TODO temp 5/15 - should store this once only and delete it later - String ini_get_all_path = host.joinIntoOnePath(active_test_pack.getStorageDirectory(), "ini_get_all.php"); - if (!host.exists(ini_get_all_path)) { - // TODO locking? - host.saveTextFile(ini_get_all_path, "<?php var_dump($argv);\nvar_dump(ini_get_all()); ?>"); - } - return ini_get_all_path; - } - @Override public String getIniActual() throws Exception { - // ensure ini_get_all.php has been created - get_ini_get_all_path(); - - return do_http_get("/ini_get_all.php", 0); + return web == null ? null : web.getIniActual(); } @Override @@ -400,7 +386,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { response.setParams(params); httpexecutor.postProcess(response, httpproc, context); - timeout_task.cancel(); + timeout_task.close(); // // support for HTTP redirects: used by some PHAR tests @@ -514,7 +500,7 @@ public class HttpPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { response.setParams(params); httpexecutor.postProcess(response, httpproc, context); - timeout_task.cancel(); + timeout_task.close(); // // support for HTTP redirects: used by some PHAR tests diff --git a/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java b/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java index 5ee834c..8cc3444 100644 --- a/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java +++ b/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java @@ -23,6 +23,7 @@ import com.mostc.pftt.results.PhpUnitTestResult; import com.mostc.pftt.scenario.CodeCacheScenario; import com.mostc.pftt.scenario.EScenarioSetPermutationLayer; import com.mostc.pftt.scenario.FileSystemScenario.ITestPackStorageDir; +import com.mostc.pftt.scenario.IScenarioSetup; import com.mostc.pftt.scenario.SMBScenario.SMBStorageDir; import com.mostc.pftt.scenario.WebServerScenario; import com.mostc.pftt.scenario.PhpUnitReflectionOnlyScenario; @@ -70,8 +71,10 @@ public class LocalPhpUnitTestPackRunner extends AbstractLocalTestPackRunner<PhpU long millis = System.currentTimeMillis(); for ( int i=0 ; i < 131070 ; i++ ) { // try to include version, branch info etc... from name of test-pack - local_test_pack_dir = local_path + "/PFTT-" + src_test_pack.getName() + (i==0?"":"-" + millis) + "/"; - remote_test_pack_dir = remote_path + "/PFTT-" + src_test_pack.getName() + (i==0?"":"-" + millis) + "/"; + // + // don't want long directory paths or lots of nesting, just put in /php-sdk + local_test_pack_dir = local_path + "/TEMP-" + src_test_pack.getName() + (i==0?"":"-" + millis) + "/"; + remote_test_pack_dir = remote_path + "/TEMP-" + src_test_pack.getName() + (i==0?"":"-" + millis) + "/"; if (!storage_host.exists(remote_test_pack_dir) || !runner_host.exists(local_test_pack_dir)) break; millis++; @@ -103,11 +106,15 @@ public class LocalPhpUnitTestPackRunner extends AbstractLocalTestPackRunner<PhpU } // end protected void setupStorageAndTestPack @Override - protected int decideThreadCount() { - int default_thread_count = super.decideThreadCount() * 2; + protected void decideThreadCount() { + super.decideThreadCount(); + //init_thread_count *= 2; // some test-packs need different numbers of threads - ask - return Math.max(1, src_test_pack.getThreadCount(runner_host, scenario_set, default_thread_count)); + init_thread_count = Math.max(1, src_test_pack.getThreadCount(runner_host, scenario_set, init_thread_count)); + max_thread_count = init_thread_count * 2; + + checkThreadCountLimit(); } @Override @@ -165,6 +172,12 @@ public class LocalPhpUnitTestPackRunner extends AbstractLocalTestPackRunner<PhpU } @Override + protected long getMaxRunTimeMillis() { + // phpunit tests are faster + return super.getMaxRunTimeMillis() / 3; + } + + @Override public void run() { super.run(); @@ -211,6 +224,18 @@ public class LocalPhpUnitTestPackRunner extends AbstractLocalTestPackRunner<PhpU protected void recordSkipped(PhpUnitTestCase test_case) { twriter.addResult(runner_host, scenario_set_setup, new PhpUnitTestResult(test_case, EPhpUnitTestStatus.TIMEOUT, scenario_set_setup, runner_host, null, null, 0, null, "PFTT: Test Timed Out", null)); } + + @Override + protected void prepareExec(TestCaseGroupKey group_key, PhpIni ini, Map<String,String> env, IScenarioSetup s) { + if (!s.isNeededPhpUnitWriter()) + return; + AbstractPhpUnitRW phpunit = ((PhpResultPackWriter)twriter).getPhpUnit( + runner_host, + src_test_pack.getNameAndVersionString(), + scenario_set_setup + ); + s.setPhpUnitWriter(runner_host, scenario_set_setup, build, ini, phpunit); + } } // end public class PhpUnitThread diff --git a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java index 952bff7..045773e 100644 --- a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java +++ b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java @@ -4,16 +4,20 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import javax.annotation.Nullable; import com.mostc.pftt.host.AHost; +import com.mostc.pftt.main.Config; import com.mostc.pftt.main.IENVINIFilter; 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.PhpIni; import com.mostc.pftt.model.core.PhptActiveTestPack; import com.mostc.pftt.model.core.PhptSourceTestPack; import com.mostc.pftt.model.core.PhptTestCase; @@ -26,9 +30,11 @@ import com.mostc.pftt.results.PhpResultPackWriter; import com.mostc.pftt.results.PhptResultWriter; import com.mostc.pftt.results.PhptTestResult; import com.mostc.pftt.scenario.EScenarioSetPermutationLayer; +import com.mostc.pftt.scenario.IScenarioSetup; import com.mostc.pftt.scenario.Scenario; import com.mostc.pftt.scenario.ScenarioSet; import com.mostc.pftt.scenario.FileSystemScenario.ITestPackStorageDir; +import com.mostc.pftt.scenario.XDebugScenario; /** Runs PHPTs from a given PhptTestPack. * @@ -40,10 +46,14 @@ import com.mostc.pftt.scenario.FileSystemScenario.ITestPackStorageDir; public class LocalPhptTestPackRunner extends AbstractLocalTestPackRunner<PhptActiveTestPack, PhptSourceTestPack, PhptTestCase> { protected final IENVINIFilter filter; + protected final boolean xdebug; public LocalPhptTestPackRunner(ConsoleManager cm, ITestResultReceiver twriter, ScenarioSet scenario_set, PhpBuild build, AHost storage_host, AHost runner_host, IENVINIFilter filter) { super(cm, twriter, scenario_set, build, storage_host, runner_host); this.filter = filter; + + // check once if this is using XDebug + xdebug = scenario_set.contains(XDebugScenario.class); } @Override @@ -63,9 +73,11 @@ public class LocalPhptTestPackRunner extends AbstractLocalTestPackRunner<PhptAct long millis = System.currentTimeMillis(); for ( int i=0 ; i < 131070 ; i++ ) { // try to include version, branch info etc... from name of test-pack + // // CRITICAL: that directory paths end with / (@see {PWD} in PhpIni) - local_test_pack_dir = local_path + "/PFTT-" + AHost.basename(src_test_pack.getSourceDirectory()) + (i==0?"":"-" + millis) + "/"; - remote_test_pack_dir = remote_path + "/PFTT-" + AHost.basename(src_test_pack.getSourceDirectory()) + (i==0?"":"-" + millis) + "/"; + // don't want long directory paths or lots of nesting, just put in /php-sdk (breaks some PHPTs) + local_test_pack_dir = local_path + "/TEMP-" + AHost.basename(src_test_pack.getSourceDirectory()) + (i==0?"":"-" + millis) + "/"; + remote_test_pack_dir = remote_path + "/TEMP-" + AHost.basename(src_test_pack.getSourceDirectory()) + (i==0?"":"-" + millis) + "/"; if (!storage_host.exists(remote_test_pack_dir) || !runner_host.exists(local_test_pack_dir)) break; millis++; @@ -105,6 +117,9 @@ public class LocalPhptTestPackRunner extends AbstractLocalTestPackRunner<PhptAct } cm.println(EPrintType.IN_PROGRESS, getClass(), "installed tests("+test_cases.size()+") from test-pack onto storage: local="+local_test_pack_dir+" remote="+remote_test_pack_dir); + + // TODO + ((Config)filter).prepareTestPack(cm, runner_host, scenario_set_setup, build, src_test_pack); } } // end protected void setupStorageAndTestPack @@ -163,13 +178,37 @@ public class LocalPhptTestPackRunner extends AbstractLocalTestPackRunner<PhptAct @Override protected void postGroup(LinkedList<TestCaseGroup<PhptTestCase>> thread_safe_list, List<PhptTestCase> test_cases) { - // run larger groups first - Collections.sort(thread_safe_list, new Comparator<TestCaseGroup<PhptTestCase>>() { - @Override - public int compare(TestCaseGroup<PhptTestCase> a, TestCaseGroup<PhptTestCase> b) { - return b.test_cases.size() - a.test_cases.size(); + // evenly mix up large and small groups + { + HashMap<Integer,LinkedList<TestCaseGroup<PhptTestCase>>> map = new HashMap<Integer,LinkedList<TestCaseGroup<PhptTestCase>>>(); + Integer key; + LinkedList<TestCaseGroup<PhptTestCase>> l; + for ( TestCaseGroup<PhptTestCase> tg : thread_safe_list ) { + key = new Integer(tg.test_cases.size()); + l = map.get(key); + if (l==null) { + l = new LinkedList<TestCaseGroup<PhptTestCase>>(); + map.put(key, l); } - }); + l.add(tg); + } + LinkedList<Integer> c = new LinkedList<Integer>(); + c.addAll(map.keySet()); + Collections.sort(c); + // reverse - run larger groups first + Collections.reverse(c); + thread_safe_list.clear(); + for ( Integer j : c ) + thread_safe_list.addAll(map.get(j)); + for ( Integer k : c ) { + l = map.get(k); + if (l==null) + continue; + thread_safe_list.add(l.removeFirst()); + if (l.isEmpty()) + map.remove(k); + } // end for + } ArrayList<PhptTestCase> buf; for ( TestCaseGroup<PhptTestCase> a : thread_safe_list ) { buf = new ArrayList<PhptTestCase>(a.test_cases.size()); @@ -179,6 +218,21 @@ public class LocalPhptTestPackRunner extends AbstractLocalTestPackRunner<PhptAct for ( PhptTestCase t : buf ) a.test_cases.add(t); } + LinkedList<NonThreadSafeExt<PhptTestCase>> b = new LinkedList<NonThreadSafeExt<PhptTestCase>>(); + b.addAll(non_thread_safe_exts); + Collections.sort(b, new Comparator<NonThreadSafeExt<PhptTestCase>>() { + @Override + public int compare(NonThreadSafeExt<PhptTestCase> a, NonThreadSafeExt<PhptTestCase> b) { + int ca = 0, cb = 0; + for ( TestCaseGroup<PhptTestCase> g : a.test_groups ) + ca += g.test_cases.size(); + for ( TestCaseGroup<PhptTestCase> g : b.test_groups ) + cb += g.test_cases.size(); + return cb - ca; + } + }); + non_thread_safe_exts.clear(); + non_thread_safe_exts.addAll(b); } // end protected void postGroup protected void reportGroups() { @@ -188,7 +242,9 @@ public class LocalPhptTestPackRunner extends AbstractLocalTestPackRunner<PhptAct @Override protected TestPackThread<PhptTestCase> createTestPackThread(boolean parallel) { - return new PhptThread(parallel); + PhptThread thread = new PhptThread(parallel); + ((Config)filter).prepareTestPackPerThread(cm, runner_host, thread, scenario_set_setup, build, src_test_pack); + return thread; } public class PhptThread extends TestPackThread<PhptTestCase> { @@ -200,7 +256,7 @@ 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); + r = sapi_scenario.createPhptTestCaseRunner(this, group_key, test_case, cm, twriter, runner_host, scenario_set_setup, build, src_test_pack, active_test_pack, xdebug); twriter.notifyStart(runner_host, scenario_set_setup, src_test_pack, test_case); r.runTest(cm, this, LocalPhptTestPackRunner.this); } @@ -220,6 +276,18 @@ public class LocalPhptTestPackRunner extends AbstractLocalTestPackRunner<PhptAct protected void recordSkipped(PhptTestCase test_case) { twriter.addResult(runner_host, scenario_set_setup, src_test_pack, new PhptTestResult(runner_host, EPhptTestStatus.TIMEOUT, test_case, "test timed out", null, null, null, null, null, null, null, null, null, null, null)); } + + @Override + protected void prepareExec(TestCaseGroupKey group_key, PhpIni ini, Map<String,String> env, IScenarioSetup s) { + if (!s.isNeededPhptWriter()) + return; + AbstractPhptRW phpt = ((PhpResultPackWriter)twriter).getPHPT( + runner_host, + scenario_set_setup, + src_test_pack.getNameAndVersionString() + ); + s.setPHPTWriter(runner_host, scenario_set_setup, build, ini, phpt); + } } // end public class PhptThread diff --git a/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java b/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java index 0fd5613..287a955 100644 --- a/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java +++ b/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java @@ -63,9 +63,14 @@ public class BuiltinWebServerScenario extends WebServerScenario { } @Override - public int getTestThreadCount(AHost host) { + public int getApprovedInitialThreadPoolSize(AHost host, int threads) { // XXX update this calculation from time to time as this web server's performance improves (probably decrease number) - return 8 * host.getCPUCount(); + return host.getCPUCount() * 6;//8; + } + + @Override + public int getApprovedMaximumThreadPoolSize(AHost host, int threads) { + return host.getCPUCount() * 8;// TODO 10; } @Override @@ -248,8 +253,8 @@ 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) { - return new BuiltinWebHttpPhptTestCaseRunner(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); + 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 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 3a1a597..9b44e97 100644 --- a/src/com/mostc/pftt/scenario/CLIScenario.java +++ b/src/com/mostc/pftt/scenario/CLIScenario.java @@ -52,13 +52,18 @@ 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) { - return new CliPhptTestCaseRunner(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) { + 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); } @Override - public int getTestThreadCount(AHost host) { - return 16 * host.getCPUCount(); + public int getApprovedInitialThreadPoolSize(AHost host, int threads) { + return host.getCPUCount() * 4;// TODO 12; + } + + @Override + public int getApprovedMaximumThreadPoolSize(AHost host, int threads) { + return host.getCPUCount() * 8;//16; } @Override diff --git a/src/com/mostc/pftt/scenario/DatabaseScenario.java b/src/com/mostc/pftt/scenario/DatabaseScenario.java index 9cb9c0e..cf75735 100644 --- a/src/com/mostc/pftt/scenario/DatabaseScenario.java +++ b/src/com/mostc/pftt/scenario/DatabaseScenario.java @@ -17,6 +17,8 @@ import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.EPrintType; import com.mostc.pftt.runner.AbstractPhpUnitTestCaseRunner; import com.mostc.pftt.util.TimerUtil; +import com.mostc.pftt.util.TimerUtil.ObjectRunnable; +import com.mostc.pftt.util.TimerUtil.WaitableRunnable; /** A Scenario that sets up a database service for (an) extension(s) to test. * @@ -28,10 +30,12 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { protected final AHost host; protected final String default_username, default_password; protected final LinkedList<DatabaseScenarioSetup> setups; + protected final IDatabaseVersion version; protected static final Object production_setup_lock = new Object(); protected DatabaseScenarioSetup production_setup; - public DatabaseScenario(AHost host, String default_username, String default_password) { + public DatabaseScenario(IDatabaseVersion version, AHost host, String default_username, String default_password) { + this.version = version; this.host = host; this.default_username = default_username; this.default_password = default_password; @@ -66,13 +70,22 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { return true; } + public IDatabaseVersion getDatabaseVersion() { + return version; + } + + public interface IDatabaseVersion { + public String getNameWithVersionInfo(); + + + } + @Override public Class<?> getSerialKey(EScenarioSetPermutationLayer layer) { switch(layer) { // IMPORTANT: when running a web application, it can only have 1 database scenario - case FUNCTIONAL_TEST_APPLICATION: - case FUNCTIONAL_TEST_DATABASE: case PRODUCTION_OR_ALL_UP_TEST: + case FUNCTIONAL_TEST_DATABASE: return DatabaseScenario.class; default: // whereas, when testing PHP Core, you can run multiple database scenarios at the same time (faster) @@ -80,6 +93,10 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { // which wouldn't/shouldn't be done in production // -however, when changing which DLLs are loaded, problems are only likely introduced when removing a DLL or changing order // so this is ok (trading this for substantial speed increase) + // + // + // this also handles if multiple versions of the same database scenario are being permuted + // ... there will be 1 version for each ScenarioSet return super.getSerialKey(layer); } } @@ -109,7 +126,7 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { if (production_setup==null) return production_setup; - return production_setup = doSetup(cm, host, layer, is_production_database_server); + return production_setup = doSetup(cm, host, build, scenario_set, layer, is_production_database_server); } } else { // reuse existing setup if one is currently running @@ -125,14 +142,14 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { } if (s.isRunning()) { cm.println(EPrintType.CLUE, getClass(), "Reusing existing MySQL server"); - // TODO + // TODO comment ProxyDatabaseScenarioSetup p = new ProxyDatabaseScenarioSetup(s); s.proxies.add(p); return p; } } } - return doSetup(cm, host, layer, is_production_database_server); + return doSetup(cm, host, build, scenario_set, layer, is_production_database_server); } } @@ -233,15 +250,25 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { public ResultSet executeQuery(String sql) { return r.executeQuery(sql); } + + @Override + protected boolean cleanupServerAfterFailedStarted(ConsoleManager cm, boolean is_production_database_server) { + return r.cleanupServerAfterFailedStarted(cm, is_production_database_server); + } + + @Override + public void getENV(Map<String, String> env) { + r.getENV(env); + } + } // end protected class ProxyDatabaseScenarioSetup - protected DatabaseScenarioSetup doSetup(ConsoleManager cm, Host host, EScenarioSetPermutationLayer layer, boolean is_production_database_server) { + protected DatabaseScenarioSetup doSetup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer, boolean is_production_database_server) { DatabaseScenarioSetup setup = createScenarioSetup(is_production_database_server); - if (setup==null||!setup.ensureServerStarted(cm, is_production_database_server)||!ensureDriverLoaded()||!setup.connect(cm)) + if (setup==null||!ensureDriverLoaded()||!setup.ensureServerStarted(cm, host, build, scenario_set, layer, is_production_database_server)||!setup.connect(cm)) return null; - for ( int i=0 ; i < 30 ; i++ ) { setup.db_name = generateDatabaseName(); if (!setup.databaseExists(setup.db_name)) { @@ -261,11 +288,32 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { @Overridable protected String generateDatabaseName() { - return "pftt_"+getName()+"_"+StringUtil.randomLettersStr(5, 10); + return "pftt_"+StringUtil.randomLettersStr(5, 10); } protected abstract DatabaseScenarioSetup createScenarioSetup(boolean is_production_server); + public abstract class DefaultUnmanagedDatabaseScenarioSetup extends DefaultDatabaseScenarioSetup { + + @Override + public abstract int getPort(); + + @Override + protected boolean startServer(ConsoleManager cm, boolean is_production_database_server) { + return true; + } + + @Override + protected boolean stopServer(ConsoleManager cm, boolean is_production_database_server) { + return true; + } + + @Override + protected boolean cleanupServerAfterFailedStarted(ConsoleManager cm, boolean is_production_database_server) { + return true; + } + } + public abstract class DefaultDatabaseScenarioSetup extends DatabaseScenarioSetup { protected Connection connection; protected int port; @@ -273,6 +321,11 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { protected abstract Connection createConnection() throws SQLException; @Override + public String getNameWithVersionInfo() { + return version.getNameWithVersionInfo(); + } + + @Override public boolean isRunning() { if (server_started && connection != null) { try { @@ -305,8 +358,11 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { @Override protected boolean disconnect() { + if (connection==null) + return true; try { connection.close(); + connection = null; return true; } catch (SQLException ex) { ex.printStackTrace(); @@ -340,41 +396,6 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { } @Override - public boolean dropDatabase(String db_name) { - return execute("DROP DATABASE "+db_name); - } - - @Override - public boolean createDatabase(String db_name) { - return execute("CREATE DATABASE "+db_name); - } - - @Override - public boolean databaseExists(String db_name) { - return empty(executeQuery("SHOW DATABASES LIKE '"+db_name+"'")); - } - - @Override - public boolean createDatabaseWithUser(String db_name, String user, String password) { - return createDatabase(db_name) && - execute("GRANT ALL ON "+db_name+".* TO `"+user+"`@`localhost` IDENTIFIED BY '"+password+"'") && - execute("GRANT ALL ON "+db_name+".* TO `"+user+"` IDENTIFIED BY '"+password+"'"); - } - - @Override - public boolean createDatabaseReplaceOk(String db_name) { - execute("DROP DATABASE IF EXISTS "+db_name); - return createDatabase(db_name); - } - - @Override - public boolean createDatabaseWithUserReplaceOk(String db_name, String user, String password) { - return createDatabaseReplaceOk(db_name) && - execute("GRANT ALL ON "+db_name+".* TO `"+user+"`@`localhost` IDENTIFIED BY '"+password+"'") && - execute("GRANT ALL ON "+db_name+".* TO `"+user+"` IDENTIFIED BY '"+password+"'"); - } - - @Override public boolean execute(String sql) { try { connection.createStatement().execute(sql); @@ -420,18 +441,44 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { @Override public abstract boolean isRunning(); - protected boolean ensureServerStarted(ConsoleManager cm, boolean is_production_database_server) { - if (!server_started && cm != null) + protected void setupBuild(ConsoleManager cm, AHost host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) throws IllegalStateException, Exception { + + } + + protected boolean ensureServerStarted(final ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer, final boolean is_production_database_server) { + if (server_started) + return true; + if (cm != null) cm.println(EPrintType.CLUE, getClass(), "Starting database server: "+getNameWithVersionInfo()); - return server_started = startServer(cm, is_production_database_server); + + try { + setupBuild(cm, (AHost)host, build, scenario_set, layer); + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CLUE, getClass(), "ensureServerStarted", ex, "Problem setting up PhpBuild for this database scenario"); + } + + WaitableRunnable<Boolean> starth = TimerUtil.runWaitSeconds("DatabaseServerStart", 60, new ObjectRunnable<Boolean>() { + public Boolean run() { + return server_started = startServer(cm, is_production_database_server); + } + }); + if (!server_started) { + if (starth.getException()!=null) + starth.getException().printStackTrace(); + + // cleanup database server process + cleanupServerAfterFailedStarted(cm, is_production_database_server); + } + return server_started; } protected abstract boolean startServer(ConsoleManager cm, boolean is_production_database_server); protected abstract boolean stopServer(ConsoleManager cm, boolean is_production_database_server); + protected abstract boolean cleanupServerAfterFailedStarted(ConsoleManager cm, boolean is_production_database_server); private boolean close_called = false; @Override - public final synchronized void close(ConsoleManager cm) { + public final synchronized void close(final ConsoleManager cm) { if (this instanceof ProxyDatabaseScenarioSetup) { synchronized(((ProxyDatabaseScenarioSetup)this).r.proxies) { ((ProxyDatabaseScenarioSetup)this).r.proxies.remove(this); @@ -461,7 +508,14 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { setups.remove(this); } cm.println(EPrintType.IN_PROGRESS, getClass(), "Stopping database server..."); - if (stopServer(cm, production_setup == this)) { + final boolean is_production_server = production_setup == this; + // sometimes #stopServer can take too long. call it in thread so it can be timed out if it takes too long + WaitableRunnable<Boolean> r = TimerUtil.runWaitSeconds("DatabaseServerStop", 30, new ObjectRunnable<Boolean>() { + public Boolean run() { + return stopServer(cm, is_production_server); + } + }); + if (r.getResult()) { server_started = false; cm.println(EPrintType.CLUE, getClass(), "Stopped database server"); } else { @@ -480,6 +534,8 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { public boolean hasENV() { return true; } + @Override + public abstract void getENV(Map<String, String> env); @Override public void setGlobals(Map<String, String> globals) { @@ -510,8 +566,12 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { public abstract int getPort(); public abstract String getDataSourceName(); - public abstract boolean dropDatabase(String db_name); - public abstract boolean createDatabase(String db_name); + public boolean dropDatabase(String db_name) { + return execute("DROP DATABASE "+db_name); + } + public boolean createDatabase(String db_name) { + return execute("CREATE DATABASE "+db_name); + } public abstract boolean createDatabaseWithUser(String db_name, String user, String password); public abstract boolean createDatabaseReplaceOk(String db_name); public abstract boolean createDatabaseWithUserReplaceOk(String db_name, String user, String password); diff --git a/src/com/mostc/pftt/scenario/IScenarioSetup.java b/src/com/mostc/pftt/scenario/IScenarioSetup.java index 89fc0f4..e55105c 100644 --- a/src/com/mostc/pftt/scenario/IScenarioSetup.java +++ b/src/com/mostc/pftt/scenario/IScenarioSetup.java @@ -5,6 +5,8 @@ import java.util.Map; import com.mostc.pftt.host.AHost; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.model.core.PhpIni; +import com.mostc.pftt.results.AbstractPhpUnitRW; +import com.mostc.pftt.results.AbstractPhptRW; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.util.IClosable; @@ -17,4 +19,8 @@ public interface IScenarioSetup extends IClosable { public boolean hasENV(); public void notifyScenarioSetSetup(ScenarioSetSetup setup); public boolean isRunning(); -} \ No newline at end of file + public boolean isNeededPhpUnitWriter(); + public void setPhpUnitWriter(AHost runner_host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhpIni ini, AbstractPhpUnitRW phpunit); + public void setPHPTWriter(AHost runner_host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhpIni ini, AbstractPhptRW phpt); + public boolean isNeededPhptWriter(); +} diff --git a/src/com/mostc/pftt/scenario/MSSQLScenario.java b/src/com/mostc/pftt/scenario/MSSQLScenario.java index 0d43f89..3b4df71 100644 --- a/src/com/mostc/pftt/scenario/MSSQLScenario.java +++ b/src/com/mostc/pftt/scenario/MSSQLScenario.java @@ -1,6 +1,18 @@ package com.mostc.pftt.scenario; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Map; + import com.mostc.pftt.host.AHost; +import com.mostc.pftt.host.Host; +import com.mostc.pftt.host.SSHHost; +import com.mostc.pftt.model.core.EBuildBranch; +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; /** Tests the mssql and pdo_mssql extensions against a Microsoft SQL Server. (NOT IMPLEMENTED) * @@ -8,31 +20,203 @@ import com.mostc.pftt.host.AHost; * */ +// TODO need to install sqlncli2008r2-x64.msi or sqlncli2012sp1-x64.msi or -x86 (need -x64 for php-x86 builds on Windows-x64) public class MSSQLScenario extends DatabaseScenario { - - public MSSQLScenario(AHost host, String default_username, String default_password) { - super(host, default_username, default_password); + public static final int DEFAULT_MSSQL_PORT = 1433; + protected final String host_address; + + public MSSQLScenario(EMSSQLVersion version, AHost host, String default_username, String default_password) { + super(version, host, default_username, default_password); + this.host_address = host.getLocalhostListenAddress(); } - + + public MSSQLScenario(EMSSQLVersion version, String host_address, String default_username, String default_password) { + super(version, new SSHHost(host_address, default_username, default_password), default_username, default_password); + this.host_address = host_address; + } + + public static enum EMSSQLVersion implements IDatabaseVersion { + DRIVER10 { + @Override + public String getNameWithVersionInfo() { + return "MSSQL-Driver-10"; + } + @Override + public String getODBCDriverName() { + return "SQL Server Native Client 10.0"; + } + }, + DRIVER11 { + @Override + public String getNameWithVersionInfo() { + return "MSSQL-Driver-11"; + } + @Override + public String getODBCDriverName() { + return "SQL Server Native Client 11.0"; + } + }; + + public abstract String getNameWithVersionInfo(); + public abstract String getODBCDriverName(); + + public String getPhpPdoDllName(EBuildBranch branch, EBuildType type, String base_dir) { + switch(branch) { + case PHP_5_3: + return type == EBuildType.NTS ? "php_pdo_sqlsrv_53_nts.dll" : "php_pdo_sqlsrv_53_ts.dll"; + case PHP_5_4: + return type == EBuildType.NTS ? "php_pdo_sqlsrv_54_nts.dll" : "php_pdo_sqlsrv_54_ts.dll"; + case PHP_5_5: + default: + return type == EBuildType.NTS ? "php_pdo_sqlsrv_55_nts.dll" : "php_pdo_sqlsrv_55_ts.dll"; + } + } + public String getPhpDllName(EBuildBranch branch, EBuildType type, String base_dir) { + switch(branch) { + case PHP_5_3: + return type == EBuildType.NTS ? "php_sqlsrv_53_nts.dll" : "php_sqlsrv_53_ts.dll"; + case PHP_5_4: + return type == EBuildType.NTS ? "php_sqlsrv_54_nts.dll" : "php_sqlsrv_54_ts.dll"; + case PHP_5_5: + default: + return type == EBuildType.NTS ? "php_sqlsrv_55_nts.dll" : "php_sqlsrv_55_ts.dll"; + } + } + } // end public static enum EMSSQLVersion + + @Override + public boolean isSupported(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + // PHP driver for MS SQL currently only supported on Windows + return host.isWindows(); + } + + @Override + public boolean ignoreForShortName(EScenarioSetPermutationLayer layer) { + // make sure version is always included in the name of the ScenarioSet + return false; + } + + public boolean isPlaceholder(EScenarioSetPermutationLayer layer) { + return false; // TODO sometimes should return true? + } + @Override protected DatabaseScenarioSetup createScenarioSetup(boolean is_production_server) { - return null; + return new MSSQLDatabaseScenarioSetup(); } + + public class MSSQLDatabaseScenarioSetup extends DefaultUnmanagedDatabaseScenarioSetup { + + @Override + protected void setupBuild(ConsoleManager cm, AHost host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) throws IllegalStateException, Exception { + String base_dir = host.getPfttCacheDir()+"/dep/MSSQL/"; + + String dll1 = ((EMSSQLVersion)version).getPhpPdoDllName(build.getVersionBranch(cm, host), build.getBuildType(host), base_dir); + String dll2 = ((EMSSQLVersion)version).getPhpDllName(build.getVersionBranch(cm, host), build.getBuildType(host), base_dir); + + host.copy(dll1, build.getDefaultExtensionDir()+"/php_pdo_sqlsrv.dll"); + host.copy(dll2, build.getDefaultExtensionDir()+"/php_sqlsrv.dll"); + } + + @Override + public String getHostname() { + return host_address; + } + + @Override + public int getPort() { + return DEFAULT_MSSQL_PORT; + } + + @Override + public String getName() { + return version.getNameWithVersionInfo(); + } + + @Override + public void getENV(Map<String, String> env) { + // @see ext/pdo_sqlsrv/tests/MsSetup.inc + // @see ext/sqlsrv/tests/MsSetup.inc + env.put("MSSQL_SERVER", getHostname()); + env.put("MSSQL_USER", getUsername()); + env.put("MSSQL_DATABASE_NAME", getDatabaseName()); + env.put("MSSQL_PASSWORD", getPassword()); + env.put("MSSQL_DRIVER_NAME", ((EMSSQLVersion)version).getODBCDriverName()); + if (getPort()!=DEFAULT_MSSQL_PORT) { + throw new IllegalStateException("Non-default port NOT supported!: "+getPort()); + } + } + + @Override + public void prepareINI(ConsoleManager cm, AHost host, PhpBuild build, ScenarioSet scenario_set, PhpIni ini) { + ini.addExtension("php_sqlsrv.dll"); + ini.addExtension("php_pdo_sqlsrv.dll"); + } + + @Override + public String getPdoDbType() { + return "pdo_sqlsrv"; + } + + @Override + public String getDataSourceName() { + return "odbc:Driver={"+((EMSSQLVersion)version).getODBCDriverName()+"};Server="+getHostname(); + } + + @Override + protected Connection createConnection() throws SQLException { + // @see http://jtds.sourceforge.net/faq.html + final String url_str = "jdbc:sqlserver://"+getHostname()+":"+getPort()+";user="+getUsername()+";password="+getPassword()+";integratedSecurity=false"; + System.out.println("url_str "+url_str); + return DriverManager.getConnection(url_str); + } + + @Override + public boolean databaseExists(String db_name) { + return empty(executeQuery("SELECT * FROM sys.databases WHERE name='"+db_name+"'")); + } + + @Override + public boolean createDatabaseWithUser(String db_name, String user, String password) { + return createDatabase(db_name) && createGrantUser(db_name, user, password); + } + + @Override + public boolean createDatabaseReplaceOk(String db_name) { + return dropDatabase(db_name) && createDatabase(db_name); + } + + @Override + public boolean createDatabaseWithUserReplaceOk(String db_name, String user, String password) { + return createDatabase(db_name) && createGrantUser(db_name, user, password); + } + + protected boolean createGrantUser(String db_name, String user, String password) { + executeQuery("IF NOT EXISTS(SELECT * FROM sys.database_principals WHERE name = '"+user+"') CREATE LOGIN "+user+" WITH PASSWORD '"+password+"'"); + executeQuery("IF NOT EXISTS(SELECT * FROM sys.server_principals WHERE name = '"+user+"' ) CREATE USER "+user+" FOR LOGIN "+user); + executeQuery("GRANT ALL ON "+db_name+".* TO "+user); + return true; + } + + } // end public class MSSQLDatabaseScenarioSetup @Override public String getName() { - return "MSSQL"; + // TODO temp DatabaseScenario should do this for all subclasses + return version.getNameWithVersionInfo(); } @Override public boolean isImplemented() { - return false; + return true; } @Override protected String getDriverClassName() { - // TODO Auto-generated method stub - return null; + // @see http://msdn.microsoft.com/en-us/library/ms378623%28v=sql.110%29.aspx + // @see http://msdn.microsoft.com/en-US/data/ff928484 + // @see http://msdn.microsoft.com/en-us/library/ms378914%28v=sql.110%29.aspx + return "com.microsoft.sqlserver.jdbc.SQLServerDriver"; } -} +} // end public class MSSQLScenario diff --git a/src/com/mostc/pftt/scenario/MySQLScenario.java b/src/com/mostc/pftt/scenario/MySQLScenario.java index c841d9f..50d14ba 100644 --- a/src/com/mostc/pftt/scenario/MySQLScenario.java +++ b/src/com/mostc/pftt/scenario/MySQLScenario.java @@ -19,20 +19,36 @@ import com.mostc.pftt.results.EPrintType; * @author Matt Ficken * */ - + public class MySQLScenario extends DatabaseScenario { public static final int DEFAULT_MYSQL_PORT = 3306; public static final String DEFAULT_USERNAME = "root"; public static final String DEFAULT_PASSWORD = "password01!"; + public MySQLScenario(EMySQLVersion version, AHost host, String default_username, String default_password) { + super(version, host, default_username, default_password); + } + + public MySQLScenario(EMySQLVersion version, AHost host) { + this(version, host, DEFAULT_USERNAME, DEFAULT_PASSWORD); + } + public MySQLScenario(AHost host, String default_username, String default_password) { - super(host, default_username, default_password); + this(EMySQLVersion.DEFAULT, host, default_username, default_password); } public MySQLScenario(AHost host) { this(host, DEFAULT_USERNAME, DEFAULT_PASSWORD); } + public static enum EMySQLVersion implements IDatabaseVersion { + DEFAULT { + public String getNameWithVersionInfo() { + return "MySQL-5.6"; // TODO autodetect + } + }; + } + @Override public boolean isImplemented() { return true; @@ -53,14 +69,34 @@ public class MySQLScenario extends DatabaseScenario { protected String datadir, hostname; @Override - protected Connection createConnection() throws SQLException { - String url = "jdbc:mysql://"+getHostname()+":"+getPort()+"/?user="+getUsername()+"&password="+getPassword(); - return DriverManager.getConnection(url); + public boolean databaseExists(String db_name) { + return empty(executeQuery("SHOW DATABASES LIKE '"+db_name+"'")); + } + + @Override + public boolean createDatabaseWithUser(String db_name, String user, String password) { + return createDatabase(db_name) && + execute("GRANT ALL ON "+db_name+".* TO `"+user+"`@`localhost` IDENTIFIED BY '"+password+"'") && + execute("GRANT ALL ON "+db_name+".* TO `"+user+"` IDENTIFIED BY '"+password+"'"); + } + + @Override + public boolean createDatabaseReplaceOk(String db_name) { + execute("DROP DATABASE IF EXISTS "+db_name); + return createDatabase(db_name); + } + + @Override + public boolean createDatabaseWithUserReplaceOk(String db_name, String user, String password) { + return createDatabaseReplaceOk(db_name) && + execute("GRANT ALL ON "+db_name+".* TO `"+user+"`@`localhost` IDENTIFIED BY '"+password+"'") && + execute("GRANT ALL ON "+db_name+".* TO `"+user+"` IDENTIFIED BY '"+password+"'"); } @Override - public String getNameWithVersionInfo() { - return "MySQL-5.6"; // TODO detect + protected Connection createConnection() throws SQLException { + String url = "jdbc:mysql://"+getHostname()+":"+getPort()+"/?user="+getUsername()+"&password="+getPassword(); + return DriverManager.getConnection(url); } @Override @@ -208,18 +244,31 @@ public class MySQLScenario extends DatabaseScenario { cm.println(EPrintType.CANT_CONTINUE, getClass(), "Failed to start MySQL server"); return false; } // end protected boolean startServer - + + protected boolean cleanupServerAfterFailedStarted(ConsoleManager cm, boolean is_production_server) { + try { + stopServerEx(cm, is_production_server); + return true; + } catch ( Exception ex ) { + ex.printStackTrace(); + } + return false; + } + + protected void stopServerEx(ConsoleManager cm, boolean is_production_server) throws Exception { + if (is_production_server) { + 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"); + mysqld_handle.close(cm, true); + } + } + @Override protected boolean stopServer(ConsoleManager cm, boolean is_production_server) { try { - if (is_production_server) { - 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"); - mysqld_handle.close(cm, true); - - } + stopServerEx(cm, is_production_server); // wait until MySQL can't be connected to if (!WebServerManager.isLocalhostTCPPortUsed(getPort())) { diff --git a/src/com/mostc/pftt/scenario/NginxScenario.java b/src/com/mostc/pftt/scenario/NginxScenario.java index b51e4ad..fdf9538 100644 --- a/src/com/mostc/pftt/scenario/NginxScenario.java +++ b/src/com/mostc/pftt/scenario/NginxScenario.java @@ -1,6 +1,5 @@ package com.mostc.pftt.scenario; -import com.mostc.pftt.host.AHost; import com.mostc.pftt.model.core.ESAPIType; import com.mostc.pftt.model.sapi.WebServerManager; @@ -26,12 +25,6 @@ public class NginxScenario extends ProductionWebServerScenario { } @Override - public int getTestThreadCount(AHost host) { - // TODO Auto-generated method stub - return 0; - } - - @Override public ESAPIType getSAPIType() { return ESAPIType.FAST_CGI; } diff --git a/src/com/mostc/pftt/scenario/ODBCScenario.java b/src/com/mostc/pftt/scenario/ODBCScenario.java index f02e756..7d7a731 100644 --- a/src/com/mostc/pftt/scenario/ODBCScenario.java +++ b/src/com/mostc/pftt/scenario/ODBCScenario.java @@ -4,8 +4,20 @@ import com.mostc.pftt.host.AHost; public abstract class ODBCScenario extends DatabaseScenario { + public ODBCScenario(EODBCVersion version, AHost host, String default_username, String default_password) { + super(version, host, default_username, default_password); + } + public ODBCScenario(AHost host, String default_username, String default_password) { - super(host, default_username, default_password); + this(EODBCVersion.DEFAULT, host, default_username, default_password); + } + + public static enum EODBCVersion implements IDatabaseVersion { + DEFAULT { + public String getNameWithVersionInfo() { + return "Default"; + } + }; } } diff --git a/src/com/mostc/pftt/scenario/PostgresSQLScenario.java b/src/com/mostc/pftt/scenario/PostgresSQLScenario.java index 6585de0..41a92e3 100644 --- a/src/com/mostc/pftt/scenario/PostgresSQLScenario.java +++ b/src/com/mostc/pftt/scenario/PostgresSQLScenario.java @@ -17,8 +17,20 @@ import com.mostc.pftt.results.ConsoleManager; public class PostgresSQLScenario extends DatabaseScenario { + public PostgresSQLScenario(EPostgresSQLVersion version, AHost host, String default_username, String default_password) { + super(version, host, default_username, default_password); + } + public PostgresSQLScenario(AHost host, String default_username, String default_password) { - super(host, default_username, default_password); + this(EPostgresSQLVersion.DEFAULT, host, default_username, default_password); + } + + public static enum EPostgresSQLVersion implements IDatabaseVersion { + DEFAULT { + public String getNameWithVersionInfo() { + return "PostgresSQL"; + } + }; } @Override @@ -29,11 +41,6 @@ public class PostgresSQLScenario extends DatabaseScenario { public class PostgresSQLScenarioSetup extends DefaultDatabaseScenarioSetup { @Override - public String getNameWithVersionInfo() { - return getName(); // TODO - } - - @Override public void prepareINI(ConsoleManager cm, AHost host, PhpBuild build, ScenarioSet scenario_set, PhpIni ini) { // TODO Auto-generated method stub @@ -75,6 +82,39 @@ public class PostgresSQLScenario extends DatabaseScenario { // TODO Auto-generated method stub return false; } + + @Override + protected boolean cleanupServerAfterFailedStarted(ConsoleManager cm, + boolean is_production_database_server) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean databaseExists(String db_name) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean createDatabaseWithUser(String db_name, String user, + String password) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean createDatabaseReplaceOk(String db_name) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean createDatabaseWithUserReplaceOk(String db_name, + String user, String password) { + // TODO Auto-generated method stub + return false; + } } // end public class PostgresSQLScenarioSetup diff --git a/src/com/mostc/pftt/scenario/ProductionWebServerScenario.java b/src/com/mostc/pftt/scenario/ProductionWebServerScenario.java index 10045be..d98737d 100644 --- a/src/com/mostc/pftt/scenario/ProductionWebServerScenario.java +++ b/src/com/mostc/pftt/scenario/ProductionWebServerScenario.java @@ -20,18 +20,23 @@ public abstract class ProductionWebServerScenario extends WebServerScenario { } @Override - public int getTestThreadCount(AHost host) { - return 4 * host.getCPUCount(); + public int getApprovedInitialThreadPoolSize(AHost host, int threads) { + return host.getCPUCount() * 8; + } + + @Override + public int getApprovedMaximumThreadPoolSize(AHost host, int threads) { + return host.getCPUCount() * 16; } @Override public int getSlowTestTimeSeconds() { - return 15; + return 12; } @Override public long getFastTestTimeSeconds() { - return 10; + return 8; } @Override @@ -40,8 +45,8 @@ public abstract class ProductionWebServerScenario extends WebServerScenario { Collections.sort(test_cases, new Comparator<PhptTestCase>() { @Override public int compare(PhptTestCase a, PhptTestCase b) { - final boolean as = isSlowTest(a); - final boolean bs = isSlowTest(b); + final boolean as = !isSlowTest(a); + final boolean bs = !isSlowTest(b); return ( as ^ bs ) ? ( as ^ true ? -1 : +1 ) : 0; } }); diff --git a/src/com/mostc/pftt/scenario/SAPIScenario.java b/src/com/mostc/pftt/scenario/SAPIScenario.java index 4198105..7a024bb 100644 --- a/src/com/mostc/pftt/scenario/SAPIScenario.java +++ b/src/com/mostc/pftt/scenario/SAPIScenario.java @@ -80,15 +80,19 @@ public abstract class SAPIScenario extends AbstractSerialScenario { * @param build * @param src_test_pack * @param active_test_pack + * @param xdebug 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); + 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 void close(ConsoleManager cm, boolean debug) { } - public abstract int getTestThreadCount(AHost host); + @Override + public abstract int getApprovedInitialThreadPoolSize(AHost host, int threads); + @Override + public abstract int getApprovedMaximumThreadPoolSize(AHost host, int threads); public abstract ESAPIType getSAPIType(); @@ -163,7 +167,6 @@ public abstract class SAPIScenario extends AbstractSerialScenario { "tests/basic/req60524-win.phpt", "tests/func/011.phpt", "zend/tests/unset_cv10.phpt", - // TODO // "ext/pdo_mysql/tests/pdo_mysql___construct_ini.phpt", "ext/pcre/tests/backtrack_limit.phpt", @@ -171,7 +174,6 @@ public abstract class SAPIScenario extends AbstractSerialScenario { "ext/phar/tests/bug45218_slowtest.phpt", "ext/phar/tests/phar_buildfromdirectory6.phpt", "ext/reflection/tests/015.phpt", - "ext/session/tests/bug60860.phpt", "ext/standard/tests/file/bug24482.phpt", "ext/standard/tests/file/bug41655_1.phpt", "ext/standard/tests/strings/htmlentities10.phpt", @@ -183,7 +185,25 @@ public abstract class SAPIScenario extends AbstractSerialScenario { "ext/standard/tests/network/udp4loop.phpt", "ext/standard/tests/network/udp6loop.phpt", "zend/tests/bug52041.phpt", - "zend/tests/halt_compiler4.phpt" + "tests/func/bug64523.phpt", + "zend/tests/halt_compiler4.phpt", + "ext/filter/tests/004.phpt", + "ext/mbstring/tests/mb_output_handler_pattern-01.phpt", + "ext/mbstring/tests/mb_output_handler_pattern-02.phpt", + "ext/mbstring/tests/mb_output_handler_pattern-03.phpt", + "ext/mbstring/tests/mb_output_handler_pattern-05.phpt", + "ext/mbstring/tests/mb_output_handler_pattern-06.phpt", + "ext/mbstring/tests/mb_output_handler_pattern-07.phpt", + "ext/mbstring/tests/mb_output_handler_pattern-08.phpt", + "ext/mbstring/tests/mb_output_handler_pattern-09.phpt", + "ext/mbstring/tests/mb_output_handler_pattern-11.phpt", + "ext/mbstring/tests/mb_output_handler_pattern-12.phpt", + "ext/mbstring/tests/mb_output_handler_runtime_ini_alteration-01.phpt", + "ext/session/tests/bug60860.phpt", + "ext/standard/tests/strings/htmlentities05.phpt", + "ext/wddx/tests/004.phpt", + "ext/wddx/tests/005.phpt", + "ext/zlib/tests/bug65391.phpt" ); public static Trie NON_WINDOWS_EXTS = PhptTestCase.createExtensions("sysvsem", "sysvmsg", "sysvshm", "gettext", "exif", "readline", "posix", "shmop"); public static Trie SCENARIO_EXTS = PhptTestCase.createExtensions("dba", "sybase", "snmp", "interbase", "ldap", "imap", "oci8", "pcntl", "soap", "xmlrpc", "pdo", "odbc", "pdo_mssql", "mssql", "pdo_pgsql", "sybase_ct", "ftp", "curl"); diff --git a/src/com/mostc/pftt/scenario/SimpleScenarioSetup.java b/src/com/mostc/pftt/scenario/SimpleScenarioSetup.java index 479732b..780724e 100644 --- a/src/com/mostc/pftt/scenario/SimpleScenarioSetup.java +++ b/src/com/mostc/pftt/scenario/SimpleScenarioSetup.java @@ -5,11 +5,33 @@ import java.util.Map; import com.mostc.pftt.host.AHost; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.model.core.PhpIni; +import com.mostc.pftt.results.AbstractPhpUnitRW; +import com.mostc.pftt.results.AbstractPhptRW; import com.mostc.pftt.results.ConsoleManager; public abstract class SimpleScenarioSetup implements IScenarioSetup { @Override + public boolean isNeededPhpUnitWriter() { + return false; + } + + @Override + public void setPhpUnitWriter(AHost runner_host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhpIni ini, AbstractPhpUnitRW phpunit) { + + } + + @Override + public void setPHPTWriter(AHost runner_host, ScenarioSetSetup scenario_set_setup, PhpBuild build, PhpIni ini, AbstractPhptRW phpt) { + + } + + @Override + public boolean isNeededPhptWriter() { + return false; + } + + @Override public void notifyScenarioSetSetup(ScenarioSetSetup setup) { } diff --git a/src/com/mostc/pftt/scenario/WebServerScenario.java b/src/com/mostc/pftt/scenario/WebServerScenario.java index 198b8c2..ef27f62 100644 --- a/src/com/mostc/pftt/scenario/WebServerScenario.java +++ b/src/com/mostc/pftt/scenario/WebServerScenario.java @@ -101,8 +101,8 @@ 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) { - return new HttpPhptTestCaseRunner(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); + 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 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); } @Override