Commit: c111e328b5d7006af11aea6b9d8b4dce94744d9a Author: Matt Ficken <v-maf...@microsoft.com> Fri, 2 Aug 2013 13:10:37 -0700 Parents: 71e2b172e09ca3ee7179d39c9d63df91eecb4dea Branches: master
Link: http://git.php.net/?p=pftt2.git;a=commitdiff;h=c111e328b5d7006af11aea6b9d8b4dce94744d9a Log: mysql scenario create temp datadir Former-commit-id: ac7f535a16ed26872b6f8e47273477f21dd37ab8 Changed paths: M conf/app/wordpress.groovy M src/com/mostc/pftt/main/Config.java M src/com/mostc/pftt/main/PfttMain.java M src/com/mostc/pftt/model/app/DatabasePhpUnitSourceTestPack.java M src/com/mostc/pftt/model/app/PhpUnitSourceTestPack.java M src/com/mostc/pftt/model/app/PhpUnitTestCase.java M src/com/mostc/pftt/model/sapi/IWebServerSetup.java M src/com/mostc/pftt/model/sapi/SimpleWebServerSetup.java M src/com/mostc/pftt/model/ui/UITestRunner.java M src/com/mostc/pftt/results/AbstractReportGen.groovy M src/com/mostc/pftt/results/PhpResultPack.java M src/com/mostc/pftt/results/PhpResultPackReader.java M src/com/mostc/pftt/results/PhpResultPackWriter.java M src/com/mostc/pftt/results/PhptResultReader.java M src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java M src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java M src/com/mostc/pftt/scenario/APCScenario.java M src/com/mostc/pftt/scenario/ApplicationScenario.java M src/com/mostc/pftt/scenario/CodeCacheScenario.java M src/com/mostc/pftt/scenario/DatabaseScenario.java M src/com/mostc/pftt/scenario/EScenarioSetPermutationLayer.java M src/com/mostc/pftt/scenario/FTPScenario.java M src/com/mostc/pftt/scenario/FileSystemScenario.java M src/com/mostc/pftt/scenario/HTTPScenario.java M src/com/mostc/pftt/scenario/IMAPScenario.java M src/com/mostc/pftt/scenario/IScenarioSetup.java M src/com/mostc/pftt/scenario/LDAPScenario.java M src/com/mostc/pftt/scenario/LocalFileSystemScenario.java M src/com/mostc/pftt/scenario/MSAccessScenario.java M src/com/mostc/pftt/scenario/MSSQLODBCScenario.java M src/com/mostc/pftt/scenario/MSSQLScenario.java M src/com/mostc/pftt/scenario/MySQLScenario.java M src/com/mostc/pftt/scenario/NetworkedServiceScenario.java M src/com/mostc/pftt/scenario/NoCodeCacheScenario.java M src/com/mostc/pftt/scenario/NormalPathsScenario.java M src/com/mostc/pftt/scenario/ODBCScenario.java M src/com/mostc/pftt/scenario/OpcacheScenario.java M src/com/mostc/pftt/scenario/OptionScenario.java M src/com/mostc/pftt/scenario/PhpUnitInlineReferencesScenario.java M src/com/mostc/pftt/scenario/PhpUnitReflectionOnlyScenario.java M src/com/mostc/pftt/scenario/PhpUnitReflectionScenario.java M src/com/mostc/pftt/scenario/PlainSocketScenario.java M src/com/mostc/pftt/scenario/PostgresSQLScenario.java M src/com/mostc/pftt/scenario/SMBCSCOptionScenario.java M src/com/mostc/pftt/scenario/SMBScenario.java M src/com/mostc/pftt/scenario/SOAPScenario.java M src/com/mostc/pftt/scenario/SSLSocketScenario.java M src/com/mostc/pftt/scenario/Scenario.java M src/com/mostc/pftt/scenario/ScenarioSet.java M src/com/mostc/pftt/scenario/ScenarioSetSetup.java M src/com/mostc/pftt/scenario/SimpleScenarioSetup.java M src/com/mostc/pftt/scenario/UNCPathsScenario.java M src/com/mostc/pftt/scenario/WebServerScenario.java M src/com/mostc/pftt/scenario/WinCacheScenario.java M src/com/mostc/pftt/scenario/XMLRPCScenario.java M src/com/mostc/pftt/scenario/app/HelloWorldScenario.groovy M src/com/mostc/pftt/scenario/app/ZipApplication.java M src/com/mostc/pftt/scenario/app/ZipDbApplication.java M src/com/mostc/pftt/util/HostEnvUtil.java M src/com/mostc/pftt/util/TimerUtil.java
diff --git a/conf/app/wordpress.groovy b/conf/app/wordpress.groovy index 6b0f969..ff7dc84 100644 --- a/conf/app/wordpress.groovy +++ b/conf/app/wordpress.groovy @@ -89,17 +89,22 @@ class WordpressPhpUnitTestPack extends RequiredDatabasePhpUnitSourceTestPack { // experience has shown that using a separate database per thread is required to get consistent test results // // + final def db_host = database.getHostname(); + final def db_port = database.getPort(); + final def db_username = "wp_test"; + final def db_password = "password01!"; // drop and recreate it from the previous test // (in case previous test messed up the database ... happens using a single database and different table prefixes too) - database.createDatabaseWithUserReplaceOk(db_name, "wp_test", "password01!"); + database.createDatabaseWithUserReplaceOk(db_name, db_username, db_password); + // important: specify the port number! database may be using a non-standard port number. def build_path = build.getPhpExe(); return """ define( 'DB_NAME', '$db_name' ); -define( 'DB_USER', 'wp_test' ); -define( 'DB_PASSWORD', 'password01!' ); -define( 'DB_HOST', 'localhost' ); +define( 'DB_USER', '$db_username' ); +define( 'DB_PASSWORD', '$db_password' ); +define( 'DB_HOST', '$db_host:$db_port' ); define( 'WP_PHP_BINARY', '$build_path' ); \$table_prefix = 'wp_tests_'; diff --git a/src/com/mostc/pftt/main/Config.java b/src/com/mostc/pftt/main/Config.java index 245edee..1cd19f6 100644 --- a/src/com/mostc/pftt/main/Config.java +++ b/src/com/mostc/pftt/main/Config.java @@ -313,7 +313,7 @@ public final class Config implements IENVINIFilter { */ public List<ScenarioSet> getScenarioSets(ConsoleManager cm, EScenarioSetPermutationLayer layer) { if (layer==null) - layer = EScenarioSetPermutationLayer.PHP_CORE; // fallback + layer = EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE; // fallback List<ScenarioSet> this_scenario_sets = permuted_scenario_sets.get(layer); if (this_scenario_sets!=null) diff --git a/src/com/mostc/pftt/main/PfttMain.java b/src/com/mostc/pftt/main/PfttMain.java index 820168f..584b5f4 100644 --- a/src/com/mostc/pftt/main/PfttMain.java +++ b/src/com/mostc/pftt/main/PfttMain.java @@ -58,6 +58,7 @@ import com.mostc.pftt.scenario.ScenarioSetSetup; import com.mostc.pftt.util.AlignedTable; import com.mostc.pftt.util.DownloadUtil; import com.mostc.pftt.util.HostEnvUtil; +import com.mostc.pftt.util.TimerUtil; import com.mostc.pftt.util.WinDebugManager; import com.mostc.pftt.util.WindowsSnapshotDownloadUtil; import com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair; @@ -556,7 +557,7 @@ public class PfttMain { cm.println(EPrintType.IN_PROGRESS, "PhpUnitSourceTestPack", "enumerated test cases."); - for ( ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.WEB_APPLICATION)) { + for ( ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION)) { List<AHost> hosts = config.getHosts(); AHost host = hosts.isEmpty()?this.host:hosts.get(0); @@ -591,7 +592,7 @@ public class PfttMain { cm.println(EPrintType.CLUE, PfttMain.class, "Writing Result-Pack: "+tmgr.getResultPackPath()); - for (ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.WEB_APPLICATION)) { + for (ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION)) { List<AHost> hosts = config.getHosts(); AHost host = hosts.isEmpty()?this.host:hosts.get(0); LocalPhpUnitTestPackRunner r = new LocalPhpUnitTestPackRunner(cm, tmgr, scenario_set, build, host, host); @@ -614,7 +615,7 @@ public class PfttMain { hosts.add(this.host); } for ( int i=0 ; i < cm.getRunTestPack() ; i++ ) { - for ( ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.PHP_CORE) ) { + for ( ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE) ) { if (!cm.isSkipSmokeTests()) { { // TODO test running PHPTs on a build that is missing a DLL that is @@ -676,7 +677,7 @@ public class PfttMain { hosts.add(this.host); } for ( int i=0 ; i < cm.getRunTestPack() ; i++ ) { - for ( ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.PHP_CORE) ) { + for ( ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE) ) { // if (!cm.isSkipSmokeTests()) { { @@ -1506,7 +1507,7 @@ public class PfttMain { // TODO open result-packs and process them } else if (command.equals("app_named")||command.equals("appnamed")||command.equals("an")) { - checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.WEB_APPLICATION); + checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION); PhpBuild[] builds = newBuilds(cm, p.host, args[args_i+1]); @@ -1527,7 +1528,7 @@ public class PfttMain { return; } - checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.WEB_APPLICATION); + checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION); PhpBuild[] builds = newBuilds(cm, p.host, args[args_i+1]); @@ -1549,7 +1550,7 @@ public class PfttMain { return; } - checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.WEB_APPLICATION); + checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION); PhpBuild[] builds = newBuilds(cm, p.host, args[args_i+1]); @@ -1573,7 +1574,7 @@ public class PfttMain { } args_i += 3; // skip over build and test_pack - checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.PHP_CORE); + checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE); // read name fragments from CLI arguments ArrayList<String> names = new ArrayList<String>(args.length-args_i); @@ -1610,7 +1611,7 @@ public class PfttMain { return; } - checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.PHP_CORE); + checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE); LinkedList<String> names = new LinkedList<String>(); readStringListFromFile(names, list_file); @@ -1635,7 +1636,7 @@ public class PfttMain { } cm.println(EPrintType.IN_PROGRESS, "Main", "Testing all PHPTs in test pack..."); - checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.PHP_CORE); + checkUAC(is_uac, false, config, cm, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE); for ( PhpBuild build : builds ) p.coreAll(build, test_pack, config, p.getWriter(build, test_pack)); @@ -1670,7 +1671,7 @@ public class PfttMain { cm.println(EPrintType.CLUE, "PfttMain", "Test not found: "+name); names.add(name); } - for ( ScenarioSet set : getScenarioSets(config, EScenarioSetPermutationLayer.PHP_CORE) ) { + for ( ScenarioSet set : getScenarioSets(config, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE) ) { if (!set.getName().equalsIgnoreCase("Local-FileSystem_CLI")) { cm.println(EPrintType.CANT_CONTINUE, "PfttMain", "run-tests.php only supports the Local-FileSystem_CLI ScenarioSet, not: "+set); cm.println(EPrintType.TIP, "PfttMain", "remove -c console option (so PFTT only tests Local-FileSystem_CLI) and try again"); @@ -1721,15 +1722,15 @@ public class PfttMain { PhpBuild build = newBuild(cm, p.host, args[args_i+1]); - checkUAC(is_uac, true, config, cm, EScenarioSetPermutationLayer.WEB_SERVER); + checkUAC(is_uac, true, config, cm, EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST); PhpIni ini; ScenarioSetSetup scenario_set_setup; - for ( ScenarioSet set : getScenarioSets(config, EScenarioSetPermutationLayer.WEB_SERVER) ) { + for ( ScenarioSet set : getScenarioSets(config, EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST) ) { ini = RequiredExtensionsSmokeTest.createDefaultIniCopy(cm, p.host, build); INIScenario.setupScenarios(cm, p.host, set, build, ini); - scenario_set_setup = ScenarioSetSetup.setupScenarioSet(cm, p.host, build, set, EScenarioSetPermutationLayer.WEB_SERVER); + scenario_set_setup = ScenarioSetSetup.setupScenarioSet(cm, p.host, build, set, EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST); if (scenario_set_setup==null) { cm.println(EPrintType.CANT_CONTINUE, "Stop", "Error opening: "+set.getName()); @@ -1749,16 +1750,16 @@ public class PfttMain { PhpBuild build = newBuild(cm, p.host, args[args_i+1]); - checkUAC(is_uac, true, config, cm, EScenarioSetPermutationLayer.WEB_SERVER); + checkUAC(is_uac, true, config, cm, EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST); // setup all scenarios PhpIni ini; - for ( ScenarioSet set : getScenarioSets(config, EScenarioSetPermutationLayer.WEB_SERVER) ) { + for ( ScenarioSet set : getScenarioSets(config, EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST) ) { ini = RequiredExtensionsSmokeTest.createDefaultIniCopy(cm, p.host, build); INIScenario.setupScenarios(cm, p.host, set, build, ini); - ScenarioSetSetup.setupScenarioSet(cm, p.host, build, set, EScenarioSetPermutationLayer.WEB_SERVER); + ScenarioSetSetup.setupScenarioSet(cm, p.host, build, set, EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST); } } else if (command.equals("release_get")||command.equals("rgn")||command.equals("rgnew")||command.equals("rgnewest")||command.equals("rgp")||command.equals("rgprev")||command.equals("rgprevious")||command.equals("rg")||command.equals("rget")) { @@ -1939,10 +1940,10 @@ public class PfttMain { // TODO install and configure wordpress w = p.getWriter(build); for ( UITestPack test_pack : test_packs ) { - for ( ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.WEB_APPLICATION) ) { + for ( ScenarioSet scenario_set : getScenarioSets(config, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION) ) { for ( AHost host : hosts ) { // XXX move to separate class, method, etc... - ScenarioSetSetup scenario_set_setup = ScenarioSetSetup.setupScenarioSet(cm, host, build, scenario_set, EScenarioSetPermutationLayer.WEB_APPLICATION); + ScenarioSetSetup scenario_set_setup = ScenarioSetSetup.setupScenarioSet(cm, host, build, scenario_set, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION); if (scenario_set_setup==null) continue; @@ -2012,9 +2013,7 @@ public class PfttMain { // // if not: // wait 30 seconds for shutdown hooks, etc... then halt for sure - try { - Thread.sleep(30000); - } catch ( InterruptedException ex ) {} + TimerUtil.trySleepSeconds(30); System.out.println("PFTT: exiting..."); Runtime.getRuntime().halt(0); } diff --git a/src/com/mostc/pftt/model/app/DatabasePhpUnitSourceTestPack.java b/src/com/mostc/pftt/model/app/DatabasePhpUnitSourceTestPack.java index 7ed84df..d7c535f 100644 --- a/src/com/mostc/pftt/model/app/DatabasePhpUnitSourceTestPack.java +++ b/src/com/mostc/pftt/model/app/DatabasePhpUnitSourceTestPack.java @@ -6,6 +6,7 @@ import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.EPrintType; import com.mostc.pftt.scenario.DatabaseScenario; +import com.mostc.pftt.scenario.EScenarioSetPermutationLayer; import com.mostc.pftt.scenario.DatabaseScenario.DatabaseScenarioSetup; import com.mostc.pftt.scenario.ScenarioSet; @@ -30,7 +31,7 @@ public abstract class DatabasePhpUnitSourceTestPack extends PhpUnitSourceTestPac return handleNoDatabaseScenario(cm); } - database = ds.setup(cm, runner_host, build, scenario_set); + database = ds.setup(cm, runner_host, build, scenario_set, EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION); if (database==null) { cm.println(EPrintType.CANT_CONTINUE, getClass(), "Could not setup database scenario"); return handleNoDatabaseScenario(cm); diff --git a/src/com/mostc/pftt/model/app/PhpUnitSourceTestPack.java b/src/com/mostc/pftt/model/app/PhpUnitSourceTestPack.java index b9930cc..4e5facc 100644 --- a/src/com/mostc/pftt/model/app/PhpUnitSourceTestPack.java +++ b/src/com/mostc/pftt/model/app/PhpUnitSourceTestPack.java @@ -7,6 +7,7 @@ import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -202,6 +203,15 @@ public abstract class PhpUnitSourceTestPack implements SourceTestPack<PhpUnitAct doRead(config, cm, test_cases, names); } + protected static void copyTestsNoDuplicates(List<PhpUnitTestCase> src, List<PhpUnitTestCase> dst) { + // multiple PhpUnitDist files may reference the same tests, just run(load) each one time + final HashMap<String,PhpUnitTestCase> by_name = new HashMap<String,PhpUnitTestCase>(); + for ( PhpUnitTestCase test_case : src ) + by_name.put(test_case.getName(), test_case); + dst.clear(); // TODO temp? prevents enumerating each test twice + dst.addAll(by_name.values()); + } + /** reads all the PhpUnitTestCases from this test-pack * * @param config @@ -218,17 +228,17 @@ public abstract class PhpUnitSourceTestPack implements SourceTestPack<PhpUnitAct if (_ref_test_cases!=null) { _test_cases = _ref_test_cases.get(); if (_test_cases!=null) { - test_cases.addAll(_test_cases); + copyTestsNoDuplicates(_test_cases, test_cases); return; } } // - doRead(config, cm, test_cases, null); + _test_cases = new ArrayList<PhpUnitTestCase>(3500); + doRead(config, cm, _test_cases, null); // cache for future use - _test_cases = new ArrayList<PhpUnitTestCase>(test_cases.size()); - _test_cases.addAll(test_cases); + copyTestsNoDuplicates(_test_cases, test_cases); _ref_test_cases = new SoftReference<ArrayList<PhpUnitTestCase>>(_test_cases); // } diff --git a/src/com/mostc/pftt/model/app/PhpUnitTestCase.java b/src/com/mostc/pftt/model/app/PhpUnitTestCase.java index e1a6f0a..c2905a4 100644 --- a/src/com/mostc/pftt/model/app/PhpUnitTestCase.java +++ b/src/com/mostc/pftt/model/app/PhpUnitTestCase.java @@ -121,6 +121,21 @@ public class PhpUnitTestCase extends TestCase { return getName(); } + @Override + public boolean equals(Object o) { + if (o==this) + return true; + else if (o instanceof PhpUnitTestCase) + return o.toString().equals(this.toString()); + else + return false; + } + + @Override + public int hashCode() { + return getName().hashCode(); + } + /** fixes slashes to Posix forward slash /. * * this is case-preserving (to avoid breaking on posix). case is not changed. diff --git a/src/com/mostc/pftt/model/sapi/IWebServerSetup.java b/src/com/mostc/pftt/model/sapi/IWebServerSetup.java index ce720c3..4509bc7 100644 --- a/src/com/mostc/pftt/model/sapi/IWebServerSetup.java +++ b/src/com/mostc/pftt/model/sapi/IWebServerSetup.java @@ -6,4 +6,6 @@ public interface IWebServerSetup extends IScenarioSetup { public String getHostname(); public int getPort(); public String getRootURL(); + @Override + public boolean isRunning(); } diff --git a/src/com/mostc/pftt/model/sapi/SimpleWebServerSetup.java b/src/com/mostc/pftt/model/sapi/SimpleWebServerSetup.java index 0715071..7c5cd3e 100644 --- a/src/com/mostc/pftt/model/sapi/SimpleWebServerSetup.java +++ b/src/com/mostc/pftt/model/sapi/SimpleWebServerSetup.java @@ -9,4 +9,7 @@ public abstract class SimpleWebServerSetup extends SimpleScenarioSetup implement return "http://"+getHostname()+":"+getPort()+"/"; } + @Override + public abstract boolean isRunning(); + } diff --git a/src/com/mostc/pftt/model/ui/UITestRunner.java b/src/com/mostc/pftt/model/ui/UITestRunner.java index de3ebf0..65fe149 100644 --- a/src/com/mostc/pftt/model/ui/UITestRunner.java +++ b/src/com/mostc/pftt/model/ui/UITestRunner.java @@ -45,6 +45,7 @@ import com.mostc.pftt.scenario.EnchantScenario; import com.mostc.pftt.scenario.ScenarioSetSetup; import com.mostc.pftt.util.ErrorUtil; import com.mostc.pftt.util.StringUtil2; +import com.mostc.pftt.util.TimerUtil; /** Runs a UI test-pack * @@ -1267,9 +1268,7 @@ public class UITestRunner implements IUITestBranch { // important: make sure it got typed - part or all of value may be missing (may not have been typed) if (StringUtil.equalsCS(value, getValue(we))) return true; - try { - Thread.sleep(500); - } catch ( InterruptedException ex ) {} + TimerUtil.trySleepMillis(200); } return true; } diff --git a/src/com/mostc/pftt/results/AbstractReportGen.groovy b/src/com/mostc/pftt/results/AbstractReportGen.groovy index 6f32c7e..def10c6 100644 --- a/src/com/mostc/pftt/results/AbstractReportGen.groovy +++ b/src/com/mostc/pftt/results/AbstractReportGen.groovy @@ -1,10 +1,14 @@ package com.mostc.pftt.results +import com.github.mattficken.io.IOUtil; import com.mostc.pftt.host.AHost; import com.mostc.pftt.model.core.EBuildBranch; abstract class AbstractReportGen { - static int ABBREVIATED_MAX_LENGTH = 512*1024; + // don't send large email messages + // keep in mind: you're probably sending both an HTML and a text/plain copy, + // so the actual size of the mail message may be as much as double the size here + static int ABBREVIATED_MAX_LENGTH = IOUtil.HALF_MEGABYTE; abstract void run(ConsoleManager cm, boolean abbreviated); diff --git a/src/com/mostc/pftt/results/PhpResultPack.java b/src/com/mostc/pftt/results/PhpResultPack.java index 72dc4ed..a46ee7b 100644 --- a/src/com/mostc/pftt/results/PhpResultPack.java +++ b/src/com/mostc/pftt/results/PhpResultPack.java @@ -8,6 +8,7 @@ import com.mostc.pftt.model.app.PhpUnitSourceTestPack; import com.mostc.pftt.model.core.EBuildBranch; import com.mostc.pftt.model.core.PhpBuildInfo; import com.mostc.pftt.model.ui.UITestPack; +import com.mostc.pftt.scenario.ScenarioSet; import com.mostc.pftt.scenario.ScenarioSetSetup; /** Manages PHP test results (PHPT, PhpUnit, etc...) @@ -73,8 +74,8 @@ public abstract class PhpResultPack { public abstract Collection<AbstractUITestRW> getUITest(String test_pack_name_and_version); public abstract PhpBuildInfo getBuildInfo(); - public AbstractPhpUnitRW getPhpUnit(AHost host, PhpUnitSourceTestPack test_pack, ScenarioSetSetup scenario_set_setup) { - return getPhpUnit(host, test_pack.getNameAndVersionString(), scenario_set_setup); + public AbstractPhpUnitRW getPhpUnit(AHost host, PhpUnitSourceTestPack test_pack, ScenarioSetSetup scenario_set) { + return getPhpUnit(host, test_pack.getNameAndVersionString(), scenario_set); } public Collection<AbstractPhpUnitRW> getPhpUnit(AHost host, PhpUnitSourceTestPack test_pack) { return getPhpUnit(host, test_pack.getNameAndVersionString()); @@ -100,5 +101,11 @@ public abstract class PhpResultPack { else return ret; } + + public abstract Collection<AHost> getHosts(); + public abstract Collection<String> getPhptTestPacks(AHost host); + public abstract Collection<ScenarioSet> getPhptScenarioSets(AHost host, String phpt_test_pack); + public abstract Collection<String> getPhpUnitTestPacks(AHost host); + public abstract Collection<ScenarioSet> getPhpUnitScenarioSets(AHost host, String phpunit_test_pack); } // end public abstract class PhpResultPack diff --git a/src/com/mostc/pftt/results/PhpResultPackReader.java b/src/com/mostc/pftt/results/PhpResultPackReader.java index 5e1bec2..6e483a9 100644 --- a/src/com/mostc/pftt/results/PhpResultPackReader.java +++ b/src/com/mostc/pftt/results/PhpResultPackReader.java @@ -6,9 +6,12 @@ import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; +import com.github.mattficken.io.ArrayUtil; import com.mostc.pftt.host.AHost; +import com.mostc.pftt.host.SSHHost; import com.mostc.pftt.model.core.EBuildBranch; import com.mostc.pftt.model.core.PhpBuildInfo; +import com.mostc.pftt.scenario.ScenarioSet; import com.mostc.pftt.scenario.ScenarioSetSetup; /** Reads result-pack of a test run completed in the past. @@ -454,4 +457,56 @@ public class PhpResultPackReader extends PhpResultPack { return file; } + @Override + public Collection<AHost> getHosts() { + LinkedList<AHost> hosts = new LinkedList<AHost>(); + for ( File f : file.listFiles() ) { + if (f.isDirectory()) + hosts.add(new SSHHost(f.getName(), "", "")); + } + return hosts; + } + + @Override + public Collection<String> getPhptTestPacks(AHost host) { + return ArrayUtil.toList(new File(file, new File(host.getName(), "PHPT").getName()).list()); + } + + @Override + public Collection<ScenarioSet> getPhptScenarioSets(AHost host, String phpt_test_pack) { + LinkedList<ScenarioSet> out = new LinkedList<ScenarioSet>(); + for ( File f : new File(file, new File(host.getName(), new File("PHPT", phpt_test_pack).getName()).getName()).listFiles() ) { + if (f.isDirectory()) + out.add(ScenarioSet.parse(f.getName())); + } + return out; + } + + @Override + public Collection<String> getPhpUnitTestPacks(AHost host) { + return ArrayUtil.toList(new File(file, new File(host.getName(), "PhpUnit").getName()).list()); + } + + @Override + public Collection<ScenarioSet> getPhpUnitScenarioSets(AHost host, String phpunit_test_pack) { + LinkedList<ScenarioSet> out = new LinkedList<ScenarioSet>(); + for ( File f : new File(file, new File(host.getName(), new File("PhpUnit", phpunit_test_pack).getName()).getName()).listFiles() ) { + if (f.isDirectory()) + out.add(ScenarioSet.parse(f.getName())); + } + return out; + } + + public AbstractPhptRW getPHPT(AHost host, ScenarioSet scenario_set, String test_pack_name) { + return phpt_reader_map.get(host).get(scenario_set).get(test_pack_name); + } + + public AbstractPhpUnitRW getPhpUnit(AHost host, String test_pack_name_and_version, ScenarioSet scenario_set) { + return php_unit_reader_map.get(host).get(test_pack_name_and_version).get(scenario_set); + } + + public AbstractUITestRW getUITest(AHost host, String test_pack_name_and_version, ScenarioSet scenario_set, String web_browser_name_and_version) { + return ui_test_reader_map.get(host).get(test_pack_name_and_version).get(scenario_set).get(web_browser_name_and_version); + } + } // end public class PhpResultPackReader diff --git a/src/com/mostc/pftt/results/PhpResultPackWriter.java b/src/com/mostc/pftt/results/PhpResultPackWriter.java index 03320f0..2aedc7a 100644 --- a/src/com/mostc/pftt/results/PhpResultPackWriter.java +++ b/src/com/mostc/pftt/results/PhpResultPackWriter.java @@ -30,6 +30,7 @@ import com.mostc.pftt.model.ui.UITestPack; import com.mostc.pftt.scenario.ScenarioSet; import com.mostc.pftt.scenario.ScenarioSetSetup; import com.mostc.pftt.util.ErrorUtil; +import com.mostc.pftt.util.TimerUtil; /** Writes the result-pack from a test run. * @@ -710,11 +711,8 @@ public class PhpResultPackWriter extends PhpResultPack implements ITestResultRec results.add(new CloseQueueEntry()); if (block) { while (!results.isEmpty()) { - try { - Thread.sleep(100); - } catch ( InterruptedException ex ) { + if (!TimerUtil.trySleepMillis(100)) break; - } } } } else { @@ -725,11 +723,8 @@ public class PhpResultPackWriter extends PhpResultPack implements ITestResultRec public void wait(AHost host, ScenarioSet scenario_set) { // TODO while (!results.isEmpty()) { - try { - Thread.sleep(100); - } catch ( InterruptedException ex ) { + if (!TimerUtil.trySleepMillis(100)) break; - } } } @@ -987,5 +982,47 @@ public class PhpResultPackWriter extends PhpResultPack implements ITestResultRec ex.printStackTrace(); } } + + @Override + public Collection<AHost> getHosts() { + // TODO combine phpunit_writer_map and uitest_writer_map + return phpt_writer_map.keySet(); + } + + @Override + public Collection<String> getPhptTestPacks(AHost host) { + LinkedList<String> out = new LinkedList<String>(); + for ( HashMap<String,PhptResultWriter> a : phpt_writer_map.get(host).values() ) { + for ( String test_pack : a.keySet() ) { + if (!out.contains(test_pack)) + out.add(test_pack); + } + } + return out; + } + + @Override + public Collection<ScenarioSet> getPhptScenarioSets(AHost host, String phpt_test_pack) { + LinkedList<ScenarioSet> out = new LinkedList<ScenarioSet>(); + for ( ScenarioSetSetup s : phpt_writer_map.get(host).keySet() ) { + HashMap<String,PhptResultWriter> a = phpt_writer_map.get(host).get(s); + if (a.equals(phpt_test_pack)) + out.add(s.getScenarioSet()); + } + return out; + } + + @Override + public Collection<String> getPhpUnitTestPacks(AHost host) { + return phpunit_writer_map.get(host).keySet(); + } + + @Override + public Collection<ScenarioSet> getPhpUnitScenarioSets(AHost host, String phpunit_test_pack) { + LinkedList<ScenarioSet> out = new LinkedList<ScenarioSet>(); + for ( ScenarioSetSetup s : phpunit_writer_map.get(host).get(phpunit_test_pack).map.keySet() ) + out.add(s.getScenarioSet()); + return out; + } } // end public class PhpResultPackWriter diff --git a/src/com/mostc/pftt/results/PhptResultReader.java b/src/com/mostc/pftt/results/PhptResultReader.java index 50038e6..40321e9 100644 --- a/src/com/mostc/pftt/results/PhptResultReader.java +++ b/src/com/mostc/pftt/results/PhptResultReader.java @@ -158,6 +158,7 @@ public class PhptResultReader extends AbstractPhptRW { e.test_names.remove("ext/iconv/tests/ob_iconv_handler.phpt"); e.test_names.remove("ext/mbstring/tests/mb_decode_numericentity.phpt"); e.test_names.remove("ext/standard/tests/strings/explode_bug.phpt"); + e.test_names.remove("tests/lang/bug35176.phpt"); } return e.test_names; } diff --git a/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java b/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java index 0ac64b5..5ee834c 100644 --- a/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java +++ b/src/com/mostc/pftt/runner/LocalPhpUnitTestPackRunner.java @@ -225,7 +225,7 @@ public class LocalPhpUnitTestPackRunner extends AbstractLocalTestPackRunner<PhpU @Override public EScenarioSetPermutationLayer getScenarioSetPermutationLayer() { - return EScenarioSetPermutationLayer.WEB_APPLICATION; + return EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION; } } // end public class LocalPhpUnitTestPackRunner diff --git a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java index 3ae4fa5..952bff7 100644 --- a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java +++ b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java @@ -247,7 +247,7 @@ public class LocalPhptTestPackRunner extends AbstractLocalTestPackRunner<PhptAct @Override public EScenarioSetPermutationLayer getScenarioSetPermutationLayer() { - return EScenarioSetPermutationLayer.PHP_CORE; + return EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE; } } // end public class LocalPhptTestPackRunner diff --git a/src/com/mostc/pftt/scenario/APCScenario.java b/src/com/mostc/pftt/scenario/APCScenario.java index efdeec7..922e01f 100644 --- a/src/com/mostc/pftt/scenario/APCScenario.java +++ b/src/com/mostc/pftt/scenario/APCScenario.java @@ -42,7 +42,7 @@ public class APCScenario extends CodeCacheScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return SETUP_FAILED; } diff --git a/src/com/mostc/pftt/scenario/ApplicationScenario.java b/src/com/mostc/pftt/scenario/ApplicationScenario.java index 0708f77..7c6c788 100644 --- a/src/com/mostc/pftt/scenario/ApplicationScenario.java +++ b/src/com/mostc/pftt/scenario/ApplicationScenario.java @@ -10,7 +10,7 @@ public abstract class ApplicationScenario extends AbstractSerialScenario { public boolean isPlaceholder(EScenarioSetPermutationLayer layer) { if (layer==null) return true; - else if (layer==EScenarioSetPermutationLayer.WEB_APPLICATION||layer==EScenarioSetPermutationLayer.WEB_SERVER||layer==EScenarioSetPermutationLayer.USER_INTERFACE) + else if (layer==EScenarioSetPermutationLayer.FUNCTIONAL_TEST_APPLICATION||layer==EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST) return false; else return true; @@ -31,5 +31,5 @@ public abstract class ApplicationScenario extends AbstractSerialScenario { } @Override - public abstract IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set); + public abstract IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer); } diff --git a/src/com/mostc/pftt/scenario/CodeCacheScenario.java b/src/com/mostc/pftt/scenario/CodeCacheScenario.java index dda3ac0..329c58c 100644 --- a/src/com/mostc/pftt/scenario/CodeCacheScenario.java +++ b/src/com/mostc/pftt/scenario/CodeCacheScenario.java @@ -22,5 +22,5 @@ public abstract class CodeCacheScenario extends INIScenario { public abstract boolean isSupported(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set); @Override - public abstract IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set); + public abstract IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer); } diff --git a/src/com/mostc/pftt/scenario/DatabaseScenario.java b/src/com/mostc/pftt/scenario/DatabaseScenario.java index 78c7515..9cb9c0e 100644 --- a/src/com/mostc/pftt/scenario/DatabaseScenario.java +++ b/src/com/mostc/pftt/scenario/DatabaseScenario.java @@ -5,6 +5,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.LinkedList; import java.util.Map; +import java.util.Random; import com.github.mattficken.Overridable; import com.github.mattficken.io.StringUtil; @@ -15,6 +16,7 @@ import com.mostc.pftt.model.core.PhpIni; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.EPrintType; import com.mostc.pftt.runner.AbstractPhpUnitTestCaseRunner; +import com.mostc.pftt.util.TimerUtil; /** A Scenario that sets up a database service for (an) extension(s) to test. * @@ -24,24 +26,39 @@ import com.mostc.pftt.runner.AbstractPhpUnitTestCaseRunner; public abstract class DatabaseScenario extends NetworkedServiceScenario { protected final AHost host; - protected final int port; protected final String default_username, default_password; protected final LinkedList<DatabaseScenarioSetup> setups; - protected boolean server_started; + protected static final Object production_setup_lock = new Object(); + protected DatabaseScenarioSetup production_setup; - public DatabaseScenario(AHost host, int port, String default_username, String default_password) { + public DatabaseScenario(AHost host, String default_username, String default_password) { this.host = host; - this.port = port; - // TODO GRANT ALL ON *.* to root@'192.168.1.4' IDENTIFIED BY 'your-root-password'; this.default_username = default_username; this.default_password = default_password; setups = new LinkedList<DatabaseScenarioSetup>(); } + public String getDefaultPassword() { + return default_password; + } + + public String getDefaultUsername() { + return default_username; + } + @Override public boolean isPlaceholder(EScenarioSetPermutationLayer layer) { - return true; + if (layer==null) + return true; + switch(layer) { + case FUNCTIONAL_TEST_APPLICATION: + case FUNCTIONAL_TEST_DATABASE: + case PRODUCTION_OR_ALL_UP_TEST: + return false; + default: + return true; + } } @Override @@ -53,10 +70,9 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { public Class<?> getSerialKey(EScenarioSetPermutationLayer layer) { switch(layer) { // IMPORTANT: when running a web application, it can only have 1 database scenario - case WEB_APPLICATION: - case USER_INTERFACE: - case DATABASE: - case PERFORMANCE: + case FUNCTIONAL_TEST_APPLICATION: + case FUNCTIONAL_TEST_DATABASE: + case PRODUCTION_OR_ALL_UP_TEST: return DatabaseScenario.class; default: // whereas, when testing PHP Core, you can run multiple database scenarios at the same time (faster) @@ -73,9 +89,6 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { return true; } - protected abstract boolean startServer(); - protected abstract boolean stopServer(); - protected abstract String getDriverClassName(); protected boolean ensureDriverLoaded() { @@ -88,26 +101,155 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { return false; } - protected synchronized boolean ensureServerStarted(ConsoleManager cm) { - //if (server_started) - //return true; - - //return server_started = startServer(); - startServer(); - return true; + @Override + public DatabaseScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { + final boolean is_production_database_server = layer==EScenarioSetPermutationLayer.PRODUCTION_OR_ALL_UP_TEST; + if (is_production_database_server) { + synchronized(production_setup_lock) { + if (production_setup==null) + return production_setup; + + return production_setup = doSetup(cm, host, layer, is_production_database_server); + } + } else { + // reuse existing setup if one is currently running + if (setups.size() > 0) { + // randomly distribute + Random r = new Random(); + DatabaseScenarioSetup s; + for ( int attempts=0 ; attempts < 5 ; attempts++ ) { + synchronized (setups) { + if (setups.size()<1) + break; + s = setups.get(r.nextInt(setups.size())); + } + if (s.isRunning()) { + cm.println(EPrintType.CLUE, getClass(), "Reusing existing MySQL server"); + // TODO + ProxyDatabaseScenarioSetup p = new ProxyDatabaseScenarioSetup(s); + s.proxies.add(p); + return p; + } + } + } + return doSetup(cm, host, layer, is_production_database_server); + } } - @Override - public DatabaseScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { - DatabaseScenarioSetup setup = createScenarioSetup(); - if (setup==null||!ensureServerStarted(cm)||!ensureDriverLoaded()||!setup.connect(cm)) + protected class ProxyDatabaseScenarioSetup extends DatabaseScenarioSetup { + protected final DatabaseScenarioSetup r; + + public ProxyDatabaseScenarioSetup(DatabaseScenarioSetup r) { + this.r = r; + } + + @Override + public String getNameWithVersionInfo() { + return r.getNameWithVersionInfo(); + } + @Override + public String getName() { + return r.getName(); + } + @Override + protected boolean connect(ConsoleManager cm) { + // doesn't get called + return false; + } + @Override + protected boolean disconnect() { + // don't call r.disconnect ... r.close() will do that if/when it should + return true; + } + @Override + public boolean databaseExists(String db_name) { + return r.databaseExists(db_name); + } + @Override + public boolean isRunning() { + return r.isRunning(); + } + @Override + protected boolean startServer(ConsoleManager cm, boolean is_production_database_server) { + return false; + } + @Override + protected boolean stopServer(ConsoleManager cm, boolean is_production_database_server) { + return false; // doesn't get called + } + @Override + public void prepareINI(ConsoleManager cm, AHost host, PhpBuild build, ScenarioSet scenario_set, PhpIni ini) { + r.prepareINI(cm, host, build, scenario_set, ini); + } + @Override + public String getPdoDbType() { + return r.getPdoDbType(); + } + @Override + public String getPassword() { + return r.getPassword(); + } + @Override + public String getUsername() { + return r.getUsername(); + } + @Override + public String getHostname() { + return r.getHostname(); + } + @Override + public int getPort() { + return r.getPort(); + } + @Override + public String getDataSourceName() { + return r.getDataSourceName(); + } + @Override + public boolean dropDatabase(String db_name) { + return r.dropDatabase(db_name); + } + @Override + public boolean createDatabase(String db_name) { + return r.createDatabase(db_name); + } + @Override + public boolean createDatabaseWithUser(String db_name, String user, String password) { + return r.createDatabaseWithUser(db_name, user, password); + } + @Override + public boolean createDatabaseReplaceOk(String db_name) { + return r.createDatabaseReplaceOk(db_name); + } + @Override + public boolean createDatabaseWithUserReplaceOk(String db_name, String user, String password) { + return r.createDatabaseWithUserReplaceOk(db_name, user, password); + } + @Override + public boolean execute(String sql) { + return r.execute(sql); + } + @Override + public ResultSet executeQuery(String sql) { + return r.executeQuery(sql); + } + } // end protected class ProxyDatabaseScenarioSetup + + protected DatabaseScenarioSetup doSetup(ConsoleManager cm, Host host, 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)) return null; + for ( int i=0 ; i < 30 ; i++ ) { setup.db_name = generateDatabaseName(); if (!setup.databaseExists(setup.db_name)) { if (setup.createDatabase(setup.db_name)) { cm.println(EPrintType.CLUE, getClass(), "Created database: "+setup.db_name); + synchronized(setups) { + setups.add(setup); + } return setup; } } @@ -122,30 +264,27 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { return "pftt_"+getName()+"_"+StringUtil.randomLettersStr(5, 10); } - public String getDefaultPassword() { - return default_password; - } - - public String getDefaultUsername() { - return default_username; - } - - public String getHostname() { - return host.isRemote() ? host.getAddress() : "127.0.0.1"; - } - - public int getPort() { - return port; - } - - protected abstract DatabaseScenarioSetup createScenarioSetup(); + protected abstract DatabaseScenarioSetup createScenarioSetup(boolean is_production_server); public abstract class DefaultDatabaseScenarioSetup extends DatabaseScenarioSetup { protected Connection connection; + protected int port; protected abstract Connection createConnection() throws SQLException; @Override + public boolean isRunning() { + if (server_started && connection != null) { + try { + return !connection.isClosed(); + } catch ( SQLException ex ) { + ex.printStackTrace(); + } + } + return false; + } + + @Override protected boolean connect(ConsoleManager cm) { Exception ex_out = null; for ( int i=0 ; i < 10 ; i++ ) { @@ -182,22 +321,22 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { @Override public String getPassword() { - return DatabaseScenario.this.getDefaultPassword(); + return DatabaseScenario.this.default_password; } @Override public String getUsername() { - return DatabaseScenario.this.getDefaultUsername(); + return DatabaseScenario.this.default_username; } @Override public String getHostname() { - return DatabaseScenario.this.getHostname(); + return host.getLocalhostListenAddress(); } @Override public int getPort() { - return DatabaseScenario.this.getPort(); + return port; } @Override @@ -269,7 +408,9 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { } public abstract class DatabaseScenarioSetup extends SimpleScenarioSetup { + protected LinkedList<ProxyDatabaseScenarioSetup> proxies = new LinkedList<ProxyDatabaseScenarioSetup>(); protected String db_name; + protected boolean server_started; protected abstract boolean connect(ConsoleManager cm); protected abstract boolean disconnect(); @@ -277,23 +418,59 @@ public abstract class DatabaseScenario extends NetworkedServiceScenario { public abstract boolean databaseExists(String db_name); @Override + public abstract boolean isRunning(); + + protected boolean ensureServerStarted(ConsoleManager cm, boolean is_production_database_server) { + if (!server_started && cm != null) + cm.println(EPrintType.CLUE, getClass(), "Starting database server: "+getNameWithVersionInfo()); + return server_started = startServer(cm, is_production_database_server); + } + + protected abstract boolean startServer(ConsoleManager cm, boolean is_production_database_server); + protected abstract boolean stopServer(ConsoleManager cm, boolean is_production_database_server); + + private boolean close_called = false; + @Override public final synchronized void close(ConsoleManager cm) { + if (this instanceof ProxyDatabaseScenarioSetup) { + synchronized(((ProxyDatabaseScenarioSetup)this).r.proxies) { + ((ProxyDatabaseScenarioSetup)this).r.proxies.remove(this); + } + // ask real to close (which it will do if this was the last proxy and it was already asked to close) + ((ProxyDatabaseScenarioSetup)this).r.close(cm); + return; + } + if (close_called && proxies.isEmpty()) { + // now close + } else if (!proxies.isEmpty()) { + // wait for all proxies to be closed + close_called = true; + return; + } + if (!(cm.isDebugAll()||cm.isDebugList()||cm.isPfttDebug())) { - dropDatabase(db_name); + new Thread() { + public void run() { + dropDatabase(db_name); + } + }.start(); + TimerUtil.trySleepSeconds(2); } - disconnect(); - setups.remove(this); - if (setups.isEmpty()) { - cm.println(EPrintType.IN_PROGRESS, getClass(), "Stopping database server..."); - if (stopServer()) { - server_started = false; - cm.println(EPrintType.CLUE, getClass(), "Stopped database server"); - } else { - server_started = true; - cm.println(EPrintType.CLUE, getClass(), "Failed to stop database server"); - } + synchronized(setups) { + setups.remove(this); + } + cm.println(EPrintType.IN_PROGRESS, getClass(), "Stopping database server..."); + if (stopServer(cm, production_setup == this)) { + server_started = false; + cm.println(EPrintType.CLUE, getClass(), "Stopped database server"); + } else { + server_started = true; + cm.println(EPrintType.CLUE, getClass(), "Failed to stop database server"); } + // disconnect after stopping the server: sometimes the disconnect process can fail + // (sometimes tests really mess up the db server) + disconnect(); } @Override diff --git a/src/com/mostc/pftt/scenario/EScenarioSetPermutationLayer.java b/src/com/mostc/pftt/scenario/EScenarioSetPermutationLayer.java index 244e87b..96573e5 100644 --- a/src/com/mostc/pftt/scenario/EScenarioSetPermutationLayer.java +++ b/src/com/mostc/pftt/scenario/EScenarioSetPermutationLayer.java @@ -15,19 +15,19 @@ package com.mostc.pftt.scenario; */ public enum EScenarioSetPermutationLayer { - USER_INTERFACE, /** running PhpUnit, etc... tests */ - WEB_APPLICATION { + FUNCTIONAL_TEST_APPLICATION { + @Override public boolean reject(Scenario scenario) { return scenario instanceof ApplicationScenario; // TODO for wordpress,symfony,joomla } }, /** running PHPT tests against php.exe or php-cgi.exe */ - PHP_CORE, - FILE_SYSTEM, - PERFORMANCE, - DATABASE, - WEB_SERVER; + FUNCTIONAL_TEST_CORE, + FUNCTIONAL_TEST_FILESYSTEM, + FUNCTIONAL_TEST_DATABASE, + FUNCTIONAL_TEST_WEBSERVER_ONLY, + PRODUCTION_OR_ALL_UP_TEST; public boolean reject(Scenario scenario) { return false; diff --git a/src/com/mostc/pftt/scenario/FTPScenario.java b/src/com/mostc/pftt/scenario/FTPScenario.java index 8b7f001..44d4848 100644 --- a/src/com/mostc/pftt/scenario/FTPScenario.java +++ b/src/com/mostc/pftt/scenario/FTPScenario.java @@ -23,7 +23,7 @@ public class FTPScenario extends StreamsScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return null; } diff --git a/src/com/mostc/pftt/scenario/FileSystemScenario.java b/src/com/mostc/pftt/scenario/FileSystemScenario.java index 42cb01f..c9ff05f 100644 --- a/src/com/mostc/pftt/scenario/FileSystemScenario.java +++ b/src/com/mostc/pftt/scenario/FileSystemScenario.java @@ -83,6 +83,8 @@ public abstract class FileSystemScenario extends AbstractSerialScenario { public void close(ConsoleManager cm) { } + @Override + public abstract boolean isRunning(); } public abstract ITestPackStorageDir setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set); diff --git a/src/com/mostc/pftt/scenario/HTTPScenario.java b/src/com/mostc/pftt/scenario/HTTPScenario.java index 8fda475..b8d3de7 100644 --- a/src/com/mostc/pftt/scenario/HTTPScenario.java +++ b/src/com/mostc/pftt/scenario/HTTPScenario.java @@ -70,7 +70,7 @@ public class HTTPScenario extends StreamsScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return new HTTPScenarioSetup(); } diff --git a/src/com/mostc/pftt/scenario/IMAPScenario.java b/src/com/mostc/pftt/scenario/IMAPScenario.java index fe19ffd..ad4a617 100644 --- a/src/com/mostc/pftt/scenario/IMAPScenario.java +++ b/src/com/mostc/pftt/scenario/IMAPScenario.java @@ -4,7 +4,9 @@ import com.mostc.pftt.host.Host; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.results.ConsoleManager; -/** scenario for interacting with IMAP mail servers +/** scenario for interacting with IMAP mail servers. (NOT IMPLEMENTED) + * + * Use with Mail::IMAP PECL/PEAR package or `imap` extension (deprecated). * * @author Matt Ficken * @@ -23,7 +25,7 @@ public class IMAPScenario extends NetworkedServiceScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return null; } diff --git a/src/com/mostc/pftt/scenario/IScenarioSetup.java b/src/com/mostc/pftt/scenario/IScenarioSetup.java index ac61b23..89fc0f4 100644 --- a/src/com/mostc/pftt/scenario/IScenarioSetup.java +++ b/src/com/mostc/pftt/scenario/IScenarioSetup.java @@ -16,4 +16,5 @@ public interface IScenarioSetup extends IClosable { public void setGlobals(Map<String, String> globals); public boolean hasENV(); public void notifyScenarioSetSetup(ScenarioSetSetup setup); + public boolean isRunning(); } \ No newline at end of file diff --git a/src/com/mostc/pftt/scenario/LDAPScenario.java b/src/com/mostc/pftt/scenario/LDAPScenario.java index 40df4da..1f7f196 100644 --- a/src/com/mostc/pftt/scenario/LDAPScenario.java +++ b/src/com/mostc/pftt/scenario/LDAPScenario.java @@ -21,8 +21,8 @@ public class LDAPScenario extends NetworkedServiceScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { - return null; + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { + return SETUP_FAILED; } } diff --git a/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java b/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java index 2e3cb80..3646052 100644 --- a/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java +++ b/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java @@ -21,6 +21,10 @@ public class LocalFileSystemScenario extends FileSystemScenario { return true; } @Override + public boolean isRunning() { + return true; + } + @Override public String getLocalPath(AHost host) { return host.getPhpSdkDir(); } diff --git a/src/com/mostc/pftt/scenario/MSAccessScenario.java b/src/com/mostc/pftt/scenario/MSAccessScenario.java index e14c262..535052c 100644 --- a/src/com/mostc/pftt/scenario/MSAccessScenario.java +++ b/src/com/mostc/pftt/scenario/MSAccessScenario.java @@ -13,12 +13,12 @@ import com.mostc.pftt.host.AHost; public class MSAccessScenario extends ODBCScenario { - public MSAccessScenario(AHost host, int port, String default_username, String default_password) { - super(host, port, default_username, default_password); + public MSAccessScenario(AHost host, String default_username, String default_password) { + super(host, default_username, default_password); } @Override - protected DatabaseScenarioSetup createScenarioSetup() { + protected DatabaseScenarioSetup createScenarioSetup(boolean is_production_server) { return null; } @@ -38,16 +38,4 @@ public class MSAccessScenario extends ODBCScenario { return null; } - @Override - protected boolean startServer() { - // TODO Auto-generated method stub - return false; - } - - @Override - protected boolean stopServer() { - // TODO Auto-generated method stub - return false; - } - } diff --git a/src/com/mostc/pftt/scenario/MSSQLODBCScenario.java b/src/com/mostc/pftt/scenario/MSSQLODBCScenario.java index 05a96aa..a775a5f 100644 --- a/src/com/mostc/pftt/scenario/MSSQLODBCScenario.java +++ b/src/com/mostc/pftt/scenario/MSSQLODBCScenario.java @@ -16,12 +16,12 @@ import com.mostc.pftt.host.AHost; public class MSSQLODBCScenario extends ODBCScenario { - public MSSQLODBCScenario(AHost host, int port, String default_username, String default_password) { - super(host, port, default_username, default_password); + public MSSQLODBCScenario(AHost host, String default_username, String default_password) { + super(host, default_username, default_password); } @Override - protected DatabaseScenarioSetup createScenarioSetup() { + protected DatabaseScenarioSetup createScenarioSetup(boolean is_production_server) { return null; } @@ -41,16 +41,4 @@ public class MSSQLODBCScenario extends ODBCScenario { return null; } - @Override - protected boolean startServer() { - // TODO Auto-generated method stub - return false; - } - - @Override - protected boolean stopServer() { - // TODO Auto-generated method stub - return false; - } - } diff --git a/src/com/mostc/pftt/scenario/MSSQLScenario.java b/src/com/mostc/pftt/scenario/MSSQLScenario.java index 82edbb2..0d43f89 100644 --- a/src/com/mostc/pftt/scenario/MSSQLScenario.java +++ b/src/com/mostc/pftt/scenario/MSSQLScenario.java @@ -10,12 +10,12 @@ import com.mostc.pftt.host.AHost; public class MSSQLScenario extends DatabaseScenario { - public MSSQLScenario(AHost host, int port, String default_username, String default_password) { - super(host, port, default_username, default_password); + public MSSQLScenario(AHost host, String default_username, String default_password) { + super(host, default_username, default_password); } @Override - protected DatabaseScenarioSetup createScenarioSetup() { + protected DatabaseScenarioSetup createScenarioSetup(boolean is_production_server) { return null; } @@ -34,17 +34,5 @@ public class MSSQLScenario extends DatabaseScenario { // TODO Auto-generated method stub return null; } - - @Override - protected boolean startServer() { - // TODO Auto-generated method stub - return false; - } - - @Override - protected boolean stopServer() { - // TODO Auto-generated method stub - return false; - } } diff --git a/src/com/mostc/pftt/scenario/MySQLScenario.java b/src/com/mostc/pftt/scenario/MySQLScenario.java index e9b6471..c841d9f 100644 --- a/src/com/mostc/pftt/scenario/MySQLScenario.java +++ b/src/com/mostc/pftt/scenario/MySQLScenario.java @@ -1,17 +1,18 @@ package com.mostc.pftt.scenario; -import java.net.ConnectException; -import java.net.Socket; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; +import java.sql.Statement; import java.util.Map; import com.mostc.pftt.host.AHost; -import com.mostc.pftt.host.ExecOutput; +import com.mostc.pftt.host.AHost.ExecHandle; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.model.core.PhpIni; +import com.mostc.pftt.model.sapi.WebServerManager; import com.mostc.pftt.results.ConsoleManager; +import com.mostc.pftt.results.EPrintType; /** Sets up a MySQL database and tests the mysql, mysqli and pdo_mysql extensions against it. * @@ -24,20 +25,12 @@ public class MySQLScenario extends DatabaseScenario { public static final String DEFAULT_USERNAME = "root"; public static final String DEFAULT_PASSWORD = "password01!"; - public MySQLScenario(AHost host, int mysql_port, String default_username, String default_password) { - super(host, mysql_port, default_username, default_password); - } - public MySQLScenario(AHost host, String default_username, String default_password) { - this(host, DEFAULT_MYSQL_PORT, default_username, default_password); - } - - public MySQLScenario(AHost host, int mysql_port) { - this(host, mysql_port, DEFAULT_USERNAME, DEFAULT_PASSWORD); + super(host, default_username, default_password); } public MySQLScenario(AHost host) { - this(host, DEFAULT_MYSQL_PORT); + this(host, DEFAULT_USERNAME, DEFAULT_PASSWORD); } @Override @@ -50,12 +43,16 @@ public class MySQLScenario extends DatabaseScenario { return "MySQL"; } - protected MySQLScenarioSetup createScenarioSetup() { + @Override + protected MySQLScenarioSetup createScenarioSetup(boolean is_production_server) { return new MySQLScenarioSetup(); } public class MySQLScenarioSetup extends DefaultDatabaseScenarioSetup { + protected ExecHandle mysqld_handle; + protected String datadir, hostname; + @Override protected Connection createConnection() throws SQLException { String url = "jdbc:mysql://"+getHostname()+":"+getPort()+"/?user="+getUsername()+"&password="+getPassword(); return DriverManager.getConnection(url); @@ -63,7 +60,7 @@ public class MySQLScenario extends DatabaseScenario { @Override public String getNameWithVersionInfo() { - return "MySQL-5.6"; // TODO + return "MySQL-5.6"; // TODO detect } @Override @@ -124,65 +121,130 @@ public class MySQLScenario extends DatabaseScenario { public String getPdoDbType() { return "pdo_mysql"; } + public String getHostname() { + return hostname; + } - } // end public class MySQLScenarioSetup - - @Override - protected String getDriverClassName() { - return "com.mysql.jdbc.Driver"; - } - - protected Object start_lock = new Object(); - @Override - protected boolean startServer() { - synchronized(start_lock) { + @Override + protected boolean startServer(ConsoleManager cm, boolean is_production_server) { try { - ExecOutput eo = ((AHost)host).execElevatedOut("net start MySQL56", AHost.ONE_MINUTE); - if (true) { - // make sure mysql can be connected to - Socket sock; - for ( int i=0 ; i < 20 ; i++ ) { - Thread.sleep(1000*i); - try { - sock = new Socket(getHostname(), getPort()); - if (sock.isConnected()) { - sock.close(); - return true; - } - } catch ( ConnectException ex ) { + if (is_production_server) { + // TODO set tmpdir=C:/ProgramData/MySQL/temp in my.ini + // otherwise will randomly fail to startup + cm.println(EPrintType.IN_PROGRESS, getClass(), "Starting MySQL Windows Service for production use..."); + port = DEFAULT_MYSQL_PORT; + hostname = host.getAddress(); + host.execElevated(cm, getClass(), "net start MySQL56", AHost.ONE_MINUTE); + } else { + // TODO improve comment + // -delete temporary test databases + // -some tests seem to corrupt databases preventing mysql from being started again + // (if using the same data dir, which is what happens with `net start MySQL56`) + String mysql_dir = host.getSystemDrive()+"\\Program Files\\MySQL\\MySQL Server 5.6"; + + cm.println(EPrintType.IN_PROGRESS, getClass(), "Using MySQL install: "+mysql_dir); + cm.println(EPrintType.IN_PROGRESS, getClass(), "Creating temporary MySQL datadir"); + + datadir = host.mktempname(getClass()); + host.mkdirs(datadir); + + cm.println(EPrintType.IN_PROGRESS, getClass(), "Copying template datadir to temporary MySQL datadir "+datadir); + host.copy(mysql_dir+"\\data", datadir); + + hostname = "127.0.0.1"; + boolean chose = false; + for(int i = DEFAULT_MYSQL_PORT+1 ; i < 65535 ; i++ ) { + if (!WebServerManager.isLocalhostTCPPortUsed(i)) { + port = i; + chose = true; + break; } } + if (!chose) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Could not find unused TCP port for MySQL server"); + return false; + } + final String cmd = "\""+mysql_dir+"\\bin\\mysqld\" --standalone --console --bind-address="+hostname+" --port="+port+" --datadir="+datadir; + + cm.println(EPrintType.IN_PROGRESS, getClass(), "Starting MySQL in standalone mode (directly, using default config)..."); + mysqld_handle = ((AHost)host).execThread(cmd); + + // wait for server to output that is running before checking below + while (mysqld_handle.isRunning()) { + if (mysqld_handle.getOutput(50).contains("Server hostname (bind-address)")) + break; + } + } // end if + + cm.println(EPrintType.IN_PROGRESS, getClass(), "Checking if MySQL server is connectable..."); + // make sure mysql can be connected to + if (WebServerManager.isLocalhostTCPPortUsed(port)) { + cm.println(EPrintType.IN_PROGRESS, getClass(), "MySQL server is connectable"); + + if (!is_production_server) { + // TODO comment + cm.println(EPrintType.IN_PROGRESS, getClass(), "Configuring "+getUsername()+" user on MySQL server"); + + String url = "jdbc:mysql://"+getHostname()+":"+getPort()+"/?user="+getUsername(); + + Connection c = DriverManager.getConnection(url); + + Statement s = c.createStatement(); + s.execute("use mysql"); + // TODO update password for specific user? + s.execute("UPDATE user SET password=PASSWORD('"+getPassword()+"')"); + s.execute("flush privileges"); + } + + return true; } + cm.println(EPrintType.CLUE, getClass(), "MySQL server is not connectable"); } catch (Exception ex) { ex.printStackTrace(); + // TODO comment + if (mysqld_handle!=null) + mysqld_handle.close(cm, true); } - } - return false; - } + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Failed to start MySQL server"); + return false; + } // end protected boolean startServer - @Override - protected boolean stopServer() { - synchronized(start_lock) { + @Override + protected boolean stopServer(ConsoleManager cm, boolean is_production_server) { try { - host.execElevated("net stop MySQL56", AHost.ONE_MINUTE); + 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); + + } + // wait until MySQL can't be connected to - Socket sock; - for ( int i=0 ; i < 100 ; i++) { - Thread.sleep(100*(i+1)); - try { - sock = new Socket(getHostname(), getPort()); - if (!sock.isConnected()) - return true; - } catch ( ConnectException ex ) { - return true; + if (!WebServerManager.isLocalhostTCPPortUsed(getPort())) { + if (!is_production_server) { + if (datadir!=null && !cm.isPfttDebug() && (!cm.isDebugAll()||!cm.isDebugList())) { + cm.println(EPrintType.IN_PROGRESS, getClass(), "Deleting temporary MySQL datadir"); + host.delete(datadir); + datadir = null; + } } + cm.println(EPrintType.IN_PROGRESS, getClass(), "Stopped MySQL server"); } return true; } catch (Exception ex) { ex.printStackTrace(); } - } - return false; + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to stop MySQL server"); + return false; + } // end protected boolean stopServer + + } // end public class MySQLScenarioSetup + + @Override + protected String getDriverClassName() { + return "com.mysql.jdbc.Driver"; } } // end public class MySQLScenario diff --git a/src/com/mostc/pftt/scenario/NetworkedServiceScenario.java b/src/com/mostc/pftt/scenario/NetworkedServiceScenario.java index bdce15f..13c2620 100644 --- a/src/com/mostc/pftt/scenario/NetworkedServiceScenario.java +++ b/src/com/mostc/pftt/scenario/NetworkedServiceScenario.java @@ -6,5 +6,5 @@ import com.mostc.pftt.results.ConsoleManager; public abstract class NetworkedServiceScenario extends AbstractParallelScenario { @Override - public abstract IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set); + public abstract IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer); } diff --git a/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java b/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java index 4bd6088..6799005 100644 --- a/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java +++ b/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java @@ -71,7 +71,7 @@ public class NoCodeCacheScenario extends CodeCacheScenario { } // end public boolean setup @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return SETUP_SUCCESS; } diff --git a/src/com/mostc/pftt/scenario/NormalPathsScenario.java b/src/com/mostc/pftt/scenario/NormalPathsScenario.java index 06699ef..4c23db7 100644 --- a/src/com/mostc/pftt/scenario/NormalPathsScenario.java +++ b/src/com/mostc/pftt/scenario/NormalPathsScenario.java @@ -19,7 +19,7 @@ public class NormalPathsScenario extends PathsScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { // TODO Auto-generated method stub return SETUP_FAILED; } diff --git a/src/com/mostc/pftt/scenario/ODBCScenario.java b/src/com/mostc/pftt/scenario/ODBCScenario.java index 182842e..f02e756 100644 --- a/src/com/mostc/pftt/scenario/ODBCScenario.java +++ b/src/com/mostc/pftt/scenario/ODBCScenario.java @@ -4,8 +4,8 @@ import com.mostc.pftt.host.AHost; public abstract class ODBCScenario extends DatabaseScenario { - public ODBCScenario(AHost host, int port, String default_username, String default_password) { - super(host, port, default_username, default_password); + public ODBCScenario(AHost host, String default_username, String default_password) { + super(host, default_username, default_password); } } diff --git a/src/com/mostc/pftt/scenario/OpcacheScenario.java b/src/com/mostc/pftt/scenario/OpcacheScenario.java index 07ab84e..7a412ad 100644 --- a/src/com/mostc/pftt/scenario/OpcacheScenario.java +++ b/src/com/mostc/pftt/scenario/OpcacheScenario.java @@ -240,7 +240,7 @@ public class OpcacheScenario extends CodeCacheScenario { } @Override - public OpcacheSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public OpcacheSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { if (host.isWindows()) { // TODO shouldn't be casting to AHost cleanupBaseAddressFile((AHost)host, build, null); diff --git a/src/com/mostc/pftt/scenario/OptionScenario.java b/src/com/mostc/pftt/scenario/OptionScenario.java index 22f9ea0..7868817 100644 --- a/src/com/mostc/pftt/scenario/OptionScenario.java +++ b/src/com/mostc/pftt/scenario/OptionScenario.java @@ -7,6 +7,6 @@ import com.mostc.pftt.results.ConsoleManager; public abstract class OptionScenario extends AbstractSerialScenario { @Override - public abstract IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set); + public abstract IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer); } diff --git a/src/com/mostc/pftt/scenario/PhpUnitInlineReferencesScenario.java b/src/com/mostc/pftt/scenario/PhpUnitInlineReferencesScenario.java index a562348..ad8c8f8 100644 --- a/src/com/mostc/pftt/scenario/PhpUnitInlineReferencesScenario.java +++ b/src/com/mostc/pftt/scenario/PhpUnitInlineReferencesScenario.java @@ -7,7 +7,7 @@ import com.mostc.pftt.results.ConsoleManager; public class PhpUnitInlineReferencesScenario extends PhpUnitReflectionScenario { @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return SETUP_SUCCESS; } diff --git a/src/com/mostc/pftt/scenario/PhpUnitReflectionOnlyScenario.java b/src/com/mostc/pftt/scenario/PhpUnitReflectionOnlyScenario.java index 8850a75..b6c325f 100644 --- a/src/com/mostc/pftt/scenario/PhpUnitReflectionOnlyScenario.java +++ b/src/com/mostc/pftt/scenario/PhpUnitReflectionOnlyScenario.java @@ -7,7 +7,7 @@ import com.mostc.pftt.results.ConsoleManager; public class PhpUnitReflectionOnlyScenario extends PhpUnitReflectionScenario { @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return SETUP_SUCCESS; } diff --git a/src/com/mostc/pftt/scenario/PhpUnitReflectionScenario.java b/src/com/mostc/pftt/scenario/PhpUnitReflectionScenario.java index 38f4c53..85e8956 100644 --- a/src/com/mostc/pftt/scenario/PhpUnitReflectionScenario.java +++ b/src/com/mostc/pftt/scenario/PhpUnitReflectionScenario.java @@ -4,8 +4,7 @@ public abstract class PhpUnitReflectionScenario extends OptionScenario { @Override public Class<?> getSerialKey(EScenarioSetPermutationLayer layer) { switch(layer) { - case WEB_APPLICATION: - case USER_INTERFACE: + case FUNCTIONAL_TEST_APPLICATION: return PhpUnitReflectionScenario.class; default: // these scenarios only matter for PhpUnit tests diff --git a/src/com/mostc/pftt/scenario/PlainSocketScenario.java b/src/com/mostc/pftt/scenario/PlainSocketScenario.java index 1b56472..207df96 100644 --- a/src/com/mostc/pftt/scenario/PlainSocketScenario.java +++ b/src/com/mostc/pftt/scenario/PlainSocketScenario.java @@ -29,7 +29,7 @@ public class PlainSocketScenario extends SocketScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return SETUP_SUCCESS; } diff --git a/src/com/mostc/pftt/scenario/PostgresSQLScenario.java b/src/com/mostc/pftt/scenario/PostgresSQLScenario.java index 4e21b42..6585de0 100644 --- a/src/com/mostc/pftt/scenario/PostgresSQLScenario.java +++ b/src/com/mostc/pftt/scenario/PostgresSQLScenario.java @@ -17,12 +17,12 @@ import com.mostc.pftt.results.ConsoleManager; public class PostgresSQLScenario extends DatabaseScenario { - public PostgresSQLScenario(AHost host, int port, String default_username, String default_password) { - super(host, port, default_username, default_password); + public PostgresSQLScenario(AHost host, String default_username, String default_password) { + super(host, default_username, default_password); } @Override - protected DatabaseScenarioSetup createScenarioSetup() { + protected DatabaseScenarioSetup createScenarioSetup(boolean is_production_server) { return new PostgresSQLScenarioSetup(); } @@ -61,6 +61,20 @@ public class PostgresSQLScenario extends DatabaseScenario { public String getPdoDbType() { return "pdo_pgsql"; } + + @Override + protected boolean startServer(ConsoleManager cm, + boolean is_production_database_server) { + // TODO Auto-generated method stub + return false; + } + + @Override + protected boolean stopServer(ConsoleManager cm, + boolean is_production_database_server) { + // TODO Auto-generated method stub + return false; + } } // end public class PostgresSQLScenarioSetup @@ -79,16 +93,4 @@ public class PostgresSQLScenario extends DatabaseScenario { return "org.postgres.JDriver"; } - @Override - protected boolean startServer() { - // TODO Auto-generated method stub - return false; - } - - @Override - protected boolean stopServer() { - // TODO Auto-generated method stub - return false; - } - } // end public class PostgresSQLScenario diff --git a/src/com/mostc/pftt/scenario/SMBCSCOptionScenario.java b/src/com/mostc/pftt/scenario/SMBCSCOptionScenario.java index 216f5da..56d2df1 100644 --- a/src/com/mostc/pftt/scenario/SMBCSCOptionScenario.java +++ b/src/com/mostc/pftt/scenario/SMBCSCOptionScenario.java @@ -15,7 +15,7 @@ public abstract class SMBCSCOptionScenario extends OptionScenario { public abstract boolean isEnable(); @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { // XXX linux client support StringBuilder ps_sb = new StringBuilder(); ps_sb.append("$wmi = [wmiclass]\"\\\\localhost\\root\\cimv2:win32_offlinefilescache\""); diff --git a/src/com/mostc/pftt/scenario/SMBScenario.java b/src/com/mostc/pftt/scenario/SMBScenario.java index 9ca3940..6ceacb5 100644 --- a/src/com/mostc/pftt/scenario/SMBScenario.java +++ b/src/com/mostc/pftt/scenario/SMBScenario.java @@ -102,7 +102,7 @@ public abstract class SMBScenario extends RemoteFileSystemScenario { public String getNameWithVersionInfo() { return getName(); } - + @Override public String getName() { return SMBScenario.this.getName(); diff --git a/src/com/mostc/pftt/scenario/SOAPScenario.java b/src/com/mostc/pftt/scenario/SOAPScenario.java index 15f4301..b7f45d9 100644 --- a/src/com/mostc/pftt/scenario/SOAPScenario.java +++ b/src/com/mostc/pftt/scenario/SOAPScenario.java @@ -23,8 +23,8 @@ public class SOAPScenario extends NetworkedServiceScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { - return null; + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { + return SETUP_FAILED; } } diff --git a/src/com/mostc/pftt/scenario/SSLSocketScenario.java b/src/com/mostc/pftt/scenario/SSLSocketScenario.java index a1f1896..5d6fe03 100644 --- a/src/com/mostc/pftt/scenario/SSLSocketScenario.java +++ b/src/com/mostc/pftt/scenario/SSLSocketScenario.java @@ -23,14 +23,14 @@ public class SSLSocketScenario extends SocketScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { // TODO configure HttpPhptTestCaseRunner and HttpPhpUnitTestCaseRunner to use SSL return SETUP_FAILED; } @Override public boolean isSupported(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { - // only work with AbstractWebServerScenario + // only work with web server scenarios return WebServerScenario.getWebServerScenario(scenario_set) != null; } diff --git a/src/com/mostc/pftt/scenario/Scenario.java b/src/com/mostc/pftt/scenario/Scenario.java index a0b0492..b0d2658 100644 --- a/src/com/mostc/pftt/scenario/Scenario.java +++ b/src/com/mostc/pftt/scenario/Scenario.java @@ -3,6 +3,8 @@ package com.mostc.pftt.scenario; import java.io.IOException; import java.util.Collection; +import javax.annotation.Nullable; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -38,11 +40,13 @@ import com.mostc.pftt.results.ITestResultReceiver; public abstract class Scenario { + // TODO @Overridable public boolean willSkip(ConsoleManager cm, ITestResultReceiver twriter, AHost host, ScenarioSetSetup setup, ESAPIType type, PhpBuild build, PhptSourceTestPack src_test_pack, PhptTestCase test_case) throws Exception { return false; } + // TODO @Overridable public Class<?> getSerialKey(EScenarioSetPermutationLayer layer) { return getClass(); @@ -62,13 +66,18 @@ public abstract class Scenario { } + /** does #setup need to be called before this Scenario can be used? + * + * @param layer + * @return + */ @Overridable public boolean setupRequired(EScenarioSetPermutationLayer layer) { return !isPlaceholder(layer); } @Overridable - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return SETUP_SUCCESS; } public static final IScenarioSetup SETUP_SUCCESS = new SimpleScenarioSetup() { @@ -87,11 +96,25 @@ public abstract class Scenario { }; public static final IScenarioSetup SETUP_FAILED = null; + /** TODO + * + * @return + */ public abstract String getName(); + + /** is scenario implemented? if not calling #setup should return SETUP_FAILED + * + * @return + */ public abstract boolean isImplemented(); - @Overridable - public boolean isPlaceholder(EScenarioSetPermutationLayer layer) { + /** TODO + * + * @param layer + * @return + */ + @Overridable + public boolean isPlaceholder(@Nullable EScenarioSetPermutationLayer layer) { return false; } @@ -100,6 +123,11 @@ public abstract class Scenario { return isPlaceholder(layer); } + /** + * + * @param name + * @return + */ @Overridable protected String processNameAndVersionInfo(String name) { return name; @@ -116,11 +144,20 @@ public abstract class Scenario { return false; } + // TODO @Overridable public boolean isUACRequiredForSetup() { return false; } + /** TODO + * + * @param cm + * @param host + * @param build + * @param scenario_set + * @return + */ @Overridable public boolean isSupported(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { return true; diff --git a/src/com/mostc/pftt/scenario/ScenarioSet.java b/src/com/mostc/pftt/scenario/ScenarioSet.java index 78b6656..f6da09c 100644 --- a/src/com/mostc/pftt/scenario/ScenarioSet.java +++ b/src/com/mostc/pftt/scenario/ScenarioSet.java @@ -51,7 +51,7 @@ public class ScenarioSet extends ArrayList<Scenario> { private static Comparator<Scenario> COMPARATOR = new Comparator<Scenario>() { @Override public int compare(Scenario a, Scenario b) { - return a.getSerialKey(EScenarioSetPermutationLayer.PHP_CORE).getName().compareTo(b.getSerialKey(EScenarioSetPermutationLayer.PHP_CORE).getName()); + return a.getSerialKey(EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE).getName().compareTo(b.getSerialKey(EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE).getName()); } }; private synchronized void sort(EScenarioSetPermutationLayer layer) { @@ -311,7 +311,7 @@ public class ScenarioSet extends ArrayList<Scenario> { return scenario_sets; } static { - scenario_sets = permuteScenarioSets(EScenarioSetPermutationLayer.PHP_CORE, Arrays.asList(Scenario.getAllDefaultScenarios())); + scenario_sets = permuteScenarioSets(EScenarioSetPermutationLayer.FUNCTIONAL_TEST_CORE, Arrays.asList(Scenario.getAllDefaultScenarios())); } protected String processNameAndVersionInfo(String name) { @@ -319,5 +319,11 @@ public class ScenarioSet extends ArrayList<Scenario> { name = s.processNameAndVersionInfo(name); return name; } + + public static ScenarioSet parse(String name) { + ScenarioSet s = new ScenarioSet(); + s.str = name; + return s; + } } // end public class ScenarioSet diff --git a/src/com/mostc/pftt/scenario/ScenarioSetSetup.java b/src/com/mostc/pftt/scenario/ScenarioSetSetup.java index fd0f52f..3331ea9 100644 --- a/src/com/mostc/pftt/scenario/ScenarioSetSetup.java +++ b/src/com/mostc/pftt/scenario/ScenarioSetSetup.java @@ -35,7 +35,7 @@ public class ScenarioSetSetup implements IClosable { boolean has_env = false; for ( Scenario scenario : scenario_set ) { if (scenario.setupRequired(layer)) { - setup = scenario.setup(cm, host, build, scenario_set); + setup = scenario.setup(cm, host, build, scenario_set, layer); if (setup==null) { if (cm!=null) { diff --git a/src/com/mostc/pftt/scenario/SimpleScenarioSetup.java b/src/com/mostc/pftt/scenario/SimpleScenarioSetup.java index 75404a6..479732b 100644 --- a/src/com/mostc/pftt/scenario/SimpleScenarioSetup.java +++ b/src/com/mostc/pftt/scenario/SimpleScenarioSetup.java @@ -20,6 +20,11 @@ public abstract class SimpleScenarioSetup implements IScenarioSetup { } @Override + public boolean isRunning() { + return true; + } + + @Override public boolean hasENV() { return false; } diff --git a/src/com/mostc/pftt/scenario/UNCPathsScenario.java b/src/com/mostc/pftt/scenario/UNCPathsScenario.java index 37ca58a..ef18edf 100644 --- a/src/com/mostc/pftt/scenario/UNCPathsScenario.java +++ b/src/com/mostc/pftt/scenario/UNCPathsScenario.java @@ -15,7 +15,7 @@ import com.mostc.pftt.results.ConsoleManager; public class UNCPathsScenario extends PathsScenario { @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { // TODO Auto-generated method stub return SETUP_FAILED; } diff --git a/src/com/mostc/pftt/scenario/WebServerScenario.java b/src/com/mostc/pftt/scenario/WebServerScenario.java index 2ef8f60..198b8c2 100644 --- a/src/com/mostc/pftt/scenario/WebServerScenario.java +++ b/src/com/mostc/pftt/scenario/WebServerScenario.java @@ -96,7 +96,7 @@ public abstract class WebServerScenario extends SAPIScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return smgr.setup(cm, host, build); } diff --git a/src/com/mostc/pftt/scenario/WinCacheScenario.java b/src/com/mostc/pftt/scenario/WinCacheScenario.java index 20a1936..19dd4a1 100644 --- a/src/com/mostc/pftt/scenario/WinCacheScenario.java +++ b/src/com/mostc/pftt/scenario/WinCacheScenario.java @@ -43,7 +43,7 @@ public class WinCacheScenario extends CodeCacheScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return SETUP_FAILED; } diff --git a/src/com/mostc/pftt/scenario/XMLRPCScenario.java b/src/com/mostc/pftt/scenario/XMLRPCScenario.java index 9395b03..7b9d04d 100644 --- a/src/com/mostc/pftt/scenario/XMLRPCScenario.java +++ b/src/com/mostc/pftt/scenario/XMLRPCScenario.java @@ -23,7 +23,7 @@ public class XMLRPCScenario extends NetworkedServiceScenario { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { return null; } diff --git a/src/com/mostc/pftt/scenario/app/HelloWorldScenario.groovy b/src/com/mostc/pftt/scenario/app/HelloWorldScenario.groovy index a1d51b1..debb870 100644 --- a/src/com/mostc/pftt/scenario/app/HelloWorldScenario.groovy +++ b/src/com/mostc/pftt/scenario/app/HelloWorldScenario.groovy @@ -4,6 +4,7 @@ import com.mostc.pftt.host.Host; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.scenario.ApplicationScenario; +import com.mostc.pftt.scenario.EScenarioSetPermutationLayer; import com.mostc.pftt.scenario.IScenarioSetup; import com.mostc.pftt.scenario.ScenarioSet; @@ -16,7 +17,7 @@ import com.mostc.pftt.scenario.ScenarioSet; public class HelloWorldScenario extends ApplicationScenario { @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { def php_code = """ <?php diff --git a/src/com/mostc/pftt/scenario/app/ZipApplication.java b/src/com/mostc/pftt/scenario/app/ZipApplication.java index 9e5f619..c68f30e 100644 --- a/src/com/mostc/pftt/scenario/app/ZipApplication.java +++ b/src/com/mostc/pftt/scenario/app/ZipApplication.java @@ -5,6 +5,7 @@ import com.mostc.pftt.host.Host; import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.EPrintType; +import com.mostc.pftt.scenario.EScenarioSetPermutationLayer; import com.mostc.pftt.scenario.WebServerScenario; import com.mostc.pftt.scenario.ApplicationScenario; import com.mostc.pftt.scenario.IScenarioSetup; @@ -15,7 +16,7 @@ public abstract class ZipApplication extends ApplicationScenario { protected String app_dir; @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { if (true) return SETUP_SUCCESS; // TODO WebServerScenario web = WebServerScenario.getWebServerScenario(scenario_set); diff --git a/src/com/mostc/pftt/scenario/app/ZipDbApplication.java b/src/com/mostc/pftt/scenario/app/ZipDbApplication.java index 54afd7b..4e20dfa 100644 --- a/src/com/mostc/pftt/scenario/app/ZipDbApplication.java +++ b/src/com/mostc/pftt/scenario/app/ZipDbApplication.java @@ -5,6 +5,7 @@ import com.mostc.pftt.model.core.PhpBuild; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.EPrintType; import com.mostc.pftt.scenario.DatabaseScenario; +import com.mostc.pftt.scenario.EScenarioSetPermutationLayer; import com.mostc.pftt.scenario.IScenarioSetup; import com.mostc.pftt.scenario.MySQLScenario; import com.mostc.pftt.scenario.ScenarioSet; @@ -27,12 +28,12 @@ public abstract class ZipDbApplication extends ZipApplication { } @Override - public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { + public IScenarioSetup setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set, EScenarioSetPermutationLayer layer) { if (!scenario_set.contains(DatabaseScenario.class)) { cm.println(EPrintType.SKIP_OPERATION, getClass(), "add a database (ex: local_mysql) to -config console option and try again"); return SETUP_FAILED; } else { - return super.setup(cm, host, build, scenario_set); + return super.setup(cm, host, build, scenario_set, layer); } } diff --git a/src/com/mostc/pftt/util/HostEnvUtil.java b/src/com/mostc/pftt/util/HostEnvUtil.java index 647d80e..1474c3e 100644 --- a/src/com/mostc/pftt/util/HostEnvUtil.java +++ b/src/com/mostc/pftt/util/HostEnvUtil.java @@ -63,15 +63,25 @@ public final class HostEnvUtil { boolean b = regQueryAdd(cm, host, "HKCU\\Software\\Microsoft\\Windows\\Windows Error Reporting", "Disable", wer_value, REG_DWORD); // this 1 disables the 'Instruction 0xNN referenced memory address that could not be read' popup msg (happens on a few PHPTs with remote FS for x64 builds) boolean c = regQueryAdd(cm, host, "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Windows", "ErrorMode", em_value, REG_DWORD); - if ( a || b || c ) { + + if (!enable_debug_prompt) { + regDel(cm, host, "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", "Debugger"); + // IMPORTANT: don't delete this key, change the value otherwise (if windbg installed) werfault.exe will + // still launch windbg... won't if set to 0x2. + regQueryAdd(cm, host, "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", "Auto", "0x2", REG_DWORD); + } + + if ( a || b || c ) { // assume if registry had to be edited, the rest of this has to be done, otherwise assume this is all already done // (avoid doing this if possible because it requires user to approve elevation) cm.println(EPrintType.IN_PROGRESS, HostEnvUtil.class, "disabling Windows Firewall..."); - // LATER edit firewall rules instead (what if on public network, ex: Azure) - host.execElevated(cm, HostEnvUtil.class, "netsh firewall set opmode disable", AHost.ONE_MINUTE); + if (!host.isRemote()) { + // LATER edit firewall rules instead (what if on public network, ex: Azure) + host.execElevated(cm, HostEnvUtil.class, "netsh firewall set opmode disable", AHost.ONE_MINUTE); + } // if (enable_debug_prompt) { @@ -92,11 +102,6 @@ public final class HostEnvUtil { // `windbg -IS` host.execElevated(cm, HostEnvUtil.class, StringUtil.ensureQuoted(win_dbg_exe)+" -IS", AHost.ONE_MINUTE); } - } else { - // edit registry to try to undo windbg -I - // - regDel(cm, host, "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", "Debugger"); - regDel(cm, host, "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", "Auto"); } // diff --git a/src/com/mostc/pftt/util/TimerUtil.java b/src/com/mostc/pftt/util/TimerUtil.java index 16e5d68..adcd47c 100644 --- a/src/com/mostc/pftt/util/TimerUtil.java +++ b/src/com/mostc/pftt/util/TimerUtil.java @@ -4,6 +4,18 @@ import java.util.concurrent.atomic.AtomicBoolean; public final class TimerUtil { + public static boolean trySleepSeconds(int seconds) { + return trySleepMillis(seconds*1000); + } + + public static boolean trySleepMillis(int millis) { + try { + Thread.sleep(millis); + return true; + } catch ( Exception ex ) {} + return false; + } + public interface RepeatingRunnable { public void run(RepeatingThread thread); }