Commit: 5a47517085698cd53e7b7a3c67a9a172803345ba
Author: Matt Ficken <[email protected]> Mon, 12 Nov 2012
15:42:31 -0800
Parents: d784ea41a3e0a0dad768054bf90ed81de5b92d5e
Branches: master
Link:
http://git.php.net/?p=pftt2.git;a=commitdiff;h=5a47517085698cd53e7b7a3c67a9a172803345ba
Log:
Multi-Scenario configuration, permutation and testing support
Former-commit-id: 76c03a4888ac9e3218af681afafc5adea82078dc
Changed paths:
M README.mdown
A conf/all_databases.groovy
A conf/all_smb.groovy
A conf/other_network_services.groovy
M doc/index.html
M src/com/mostc/pftt/host/Host.java
M src/com/mostc/pftt/host/LocalHost.java
M src/com/mostc/pftt/host/SSHHost.java
A src/com/mostc/pftt/main/Config.java
D src/com/mostc/pftt/main/ConfigUtil.java
M src/com/mostc/pftt/main/PfttMain.java
M src/com/mostc/pftt/model/phpt/PhpBuild.java
M src/com/mostc/pftt/model/phpt/PhpIni.java
M src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java
M src/com/mostc/pftt/model/phpt/PhptTestCase.java
M src/com/mostc/pftt/report/AbstractReportGen.groovy
M src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner.java
M src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
M src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
M src/com/mostc/pftt/runner/HttpTestCaseRunner.java
M src/com/mostc/pftt/runner/PhptTestPackRunner.java
M src/com/mostc/pftt/scenario/AbstractCodeCacheScenario.java
M src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java
M src/com/mostc/pftt/scenario/AbstractParallelScenario.java
M src/com/mostc/pftt/scenario/AbstractSAPIScenario.java
M src/com/mostc/pftt/scenario/AbstractSMBScenario.java
M src/com/mostc/pftt/scenario/AbstractSerialScenario.java
M src/com/mostc/pftt/scenario/AbstractSocketScenario.java
M src/com/mostc/pftt/scenario/CLIScenario.java
M src/com/mostc/pftt/scenario/LocalFileSystemScenario.java
M src/com/mostc/pftt/scenario/SMBCSCOptionScenario.java
M src/com/mostc/pftt/scenario/SMBDFSRScenario.java
M src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
M src/com/mostc/pftt/scenario/Scenario.java
M src/com/mostc/pftt/scenario/ScenarioSet.java
M src/com/mostc/pftt/telemetry/ConsoleManager.java
M src/com/mostc/pftt/telemetry/PhptTestResult.java
M src/com/mostc/pftt/ui/ExpectedActualDiffPHPTDisplay.java
M src/com/mostc/pftt/ui/PhptDebuggerFrame.java
M src/com/mostc/pftt/util/HostEnvUtil.java
diff --git a/README.mdown b/README.mdown
index b4ed406..43734eb 100644
--- a/README.mdown
+++ b/README.mdown
@@ -144,11 +144,11 @@ PFTT will automatically generate an FBC report and
display it using system defau
## Adding Scenarios
-To add any test [Scenario](doc/apidoc/com/mostc/pftt/scenario/Scenario.html),
implement [Scenario](doc/apidoc/com/mostc/pftt/scenario/Scenario.html) and
instantiate it in Scenario#getAllScenarios.
+To add any test [Scenario](doc/apidoc/com/mostc/pftt/scenario/Scenario.html),
implement [Scenario](doc/apidoc/com/mostc/pftt/scenario/Scenario.html) and
instantiate it in Scenario#getAllDefaultScenarios or a config file if it needs
special configuration (like connecting to a remote host, database, etc... that
the user would have to setup).
### Database Scenario
-More specifically, to add a database scenario (MySQL, Firebird, etc...)
implement
[AbstractDatabaseScenario](doc/apidoc/com/mostc/pftt/scenario/AbstractDatabaseScenario.html)
and add it to Scenario#getAllScenarios.
+More specifically, to add a database scenario (MySQL, Firebird, etc...)
implement
[AbstractDatabaseScenario](doc/apidoc/com/mostc/pftt/scenario/AbstractDatabaseScenario.html)
and add it to Scenario#getAllDefaultScenarios or a config file if it needs
special configuration (like connecting to a remote host, database, etc... that
the user would have to setup).
### SAPI Scenario
diff --git a/conf/all_databases.groovy b/conf/all_databases.groovy
new file mode 100644
index 0000000..f8c1ccc
--- /dev/null
+++ b/conf/all_databases.groovy
@@ -0,0 +1,11 @@
+
+def scenarios() {
+[
+ new MSAccessScenario(),
+ new MSSQLODBCScenario(),
+ new MSSQLScenario(),
+ new MySQLScenario(),
+ new PostgresSQLScenario(),
+ new SQLite3Scenario()
+]
+}
diff --git a/conf/all_smb.groovy b/conf/all_smb.groovy
new file mode 100644
index 0000000..cf6f3e4
--- /dev/null
+++ b/conf/all_smb.groovy
@@ -0,0 +1,12 @@
+
+def scenarios() {
+ SSHHost win8_server = new SSHHost("192.168.1.1", "administrator",
"password01!");
+[
+ new SMBBasicScenario(win8_server),
+ new SMBDeduplicationScenario(win8_server, "E:"),
+ /* XXX new SMBDFSScenario(),
+ new SMBCAScenario(),*/
+ // probably don't need to test branch cache, but including it for
completeness
+ //new SMBBranchCacheScenario()
+]
+}
diff --git a/conf/other_network_services.groovy
b/conf/other_network_services.groovy
new file mode 100644
index 0000000..ea8d1f5
--- /dev/null
+++ b/conf/other_network_services.groovy
@@ -0,0 +1,11 @@
+
+def scenarios() {
+[
+ // streams
+ new FTPScenario(),
+ new HTTPScenario(),
+ // web services
+ new SOAPScenario(),
+ new XMLRPCScenario()
+]
+}
diff --git a/doc/index.html b/doc/index.html
index 949fbfc..f704f21 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -180,11 +180,11 @@ That should be it (PFTT comes with eclipse .project and
.classpath files which a
<h2>Adding Scenarios</h2>
-<p>To add any test Scenario, implement <a
href="apidoc/com/mostc/pftt/scenario/Scenario.html">Scenario</a> and
instantiate it in Scenario#getAllScenarios.</p>
+<p>To add any test Scenario, implement <a
href="apidoc/com/mostc/pftt/scenario/Scenario.html">Scenario</a> and
instantiate it in Scenario#getAllDefaultScenarios or a config file if it needs
special configuration (like connecting to a remote host, database, etc... that
the user would have to setup).</p>
<h3>Database Scenario</h3>
-<p>More specifically, to add a database scenario (MySQL, Firebird, etc...)
implement <a
href="apidoc/com/mostc/pftt/scenario/AbstractDatabaseScenario.html">AbstractDatabaseScenario</a>
and add it to Scenario#getAllScenarios.</p>
+<p>More specifically, to add a database scenario (MySQL, Firebird, etc...)
implement <a
href="apidoc/com/mostc/pftt/scenario/AbstractDatabaseScenario.html">AbstractDatabaseScenario</a>
and add it to Scenario#getAllDefaultScenarios or a config file if it needs
special configuration (like connecting to a remote host, database, etc... that
the user would have to setup).</p>
<h3>SAPI Scenario</h3>
diff --git a/src/com/mostc/pftt/host/Host.java
b/src/com/mostc/pftt/host/Host.java
index d5c0790..3860be8 100644
--- a/src/com/mostc/pftt/host/Host.java
+++ b/src/com/mostc/pftt/host/Host.java
@@ -19,7 +19,7 @@ import com.mostc.pftt.util.StringUtil;
/** Abstracts host management so client code doesn't need to care if host is
local or remote(ssh).
*
* @see #exec
- * @see #cmd
+ * @see #test_cmd
* @see Host#DEV
* @see #isRemote
* @see #readFile
@@ -87,7 +87,7 @@ public abstract class Host {
if (path.length() >= 2) {
if (path.charAt(1)==':') {
if (Character.isLetter(path.charAt(0)))
- return path.substring(0, 1);
+ return path.substring(0,
1).toUpperCase();
}
}
return null;
@@ -170,8 +170,8 @@ public abstract class Host {
* @throws IllegalStateException
* @throws IOException
*/
- public abstract void saveFile(String filename, String text) throws
IllegalStateException, IOException;
- public abstract void saveFile(String filename, String text, Charset
charset) throws IllegalStateException, IOException;
+ public abstract void saveTextFile(String filename, String text) throws
IllegalStateException, IOException;
+ public abstract void saveTextFile(String filename, String text, Charset
charset) throws IllegalStateException, IOException;
public abstract void delete(String path) throws IllegalStateException,
IOException;
public void deleteIfExists(String path) {
try {
@@ -752,5 +752,26 @@ public abstract class Host {
}
return 0L;
} // end public long getTotalPhysicalMemoryK
+
+ /** on Windows, returns the directory where windows is stored,
typically C:\Windows.
+ *
+ * on other OSes, it returns /
+ *
+ * @return
+ */
+ public String getSystemRoot() {
+ if (!isWindows())
+ return "/";
+ String sr = getEnvValue("SYSTEMROOT");
+ if (StringUtil.isNotEmpty(sr))
+ return sr;
+ else
+ // fallback
+ return getSystemDrive()+"\\Windows";
+ }
+
+ public abstract boolean dirContainsExact(String path, String name);
+ public abstract boolean dirContainsFragment(String path, String
name_fragment);
+ public abstract String[] list(String path);
} // end public abstract class Host
diff --git a/src/com/mostc/pftt/host/LocalHost.java
b/src/com/mostc/pftt/host/LocalHost.java
index 029ce73..8b87fba 100644
--- a/src/com/mostc/pftt/host/LocalHost.java
+++ b/src/com/mostc/pftt/host/LocalHost.java
@@ -126,12 +126,12 @@ public class LocalHost extends Host {
}
@Override
- public void saveFile(String filename, String text) throws IOException {
- saveFile(filename, text, null);
+ public void saveTextFile(String filename, String text) throws
IOException {
+ saveTextFile(filename, text, null);
}
@Override
- public void saveFile(String filename, String text, Charset charset)
throws IOException {
+ public void saveTextFile(String filename, String text, Charset charset)
throws IOException {
if (text==null)
text = "";
FileOutputStream fos = new FileOutputStream(filename);
@@ -602,5 +602,37 @@ public class LocalHost extends Host {
protected String getOSNameOnWindows() {
return getOSNameLong();
}
+
+ @Override
+ public boolean dirContainsExact(String path, String name) {
+ for ( File file : new File(path).listFiles() ) {
+ if (file.getName().equalsIgnoreCase(name))
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean dirContainsFragment(String path, String name_fragment) {
+ name_fragment = name_fragment.toLowerCase();
+ for ( File file : new File(path).listFiles() ) {
+ if
(file.getName().toLowerCase().contains(name_fragment))
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String[] list(String path) {
+ return new File(path).list();
+ }
+
+ public static String getLocalPfttDir() {
+ if (DEV > 0) {
+ return isLocalhostWindows() ?
"C:\\php-sdk\\PFTT\\Dev-"+DEV+"\\" :
System.getenv("HOME")+"/php-sdk/PFTT/dev-"+DEV+"/";
+ } else {
+ return isLocalhostWindows() ?
"C:\\php-sdk\\PFTT\\Current\\" : System.getenv("HOME")+"/php-sdk/PFTT/current/";
+ }
+ }
} // end public class Host
diff --git a/src/com/mostc/pftt/host/SSHHost.java
b/src/com/mostc/pftt/host/SSHHost.java
index 14bd262..949ee31 100644
--- a/src/com/mostc/pftt/host/SSHHost.java
+++ b/src/com/mostc/pftt/host/SSHHost.java
@@ -14,6 +14,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
@@ -240,7 +241,7 @@ public class SSHHost extends RemoteHost {
}
@Override
- public void saveFile(String filename, String text, Charset charset)
throws IOException {
+ public void saveTextFile(String filename, String text, Charset charset)
throws IOException {
if (text==null)
text = "";
ensureScpOpen();
@@ -249,8 +250,8 @@ public class SSHHost extends RemoteHost {
}
@Override
- public void saveFile(String filename, String text) throws IOException {
- saveFile(filename, text, null);
+ public void saveTextFile(String filename, String text) throws
IOException {
+ saveTextFile(filename, text, null);
}
protected SessionChannelClient do_exec(String cmd, Map<String, String>
env, String chdir, byte[] stdin_post, OutputStream out) throws IOException,
IllegalStateException {
@@ -531,4 +532,35 @@ public class SSHHost extends RemoteHost {
return false;
}
+ @Override
+ public boolean dirContainsExact(String path, String name) {
+ for ( String a : list(path) ) {
+ if (a.equalsIgnoreCase(name))
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean dirContainsFragment(String path, String name_fragment) {
+ for ( String a : list(path) ) {
+ if (a.contains(name_fragment))
+ return true;
+ }
+ return false;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public String[] list(String path) {
+ try {
+ ensureSftpOpen();
+ List list = sftp.ls(path);
+ return (String[]) list.toArray(new String[list.size()]);
+ } catch ( Exception ex ) {
+ ex.printStackTrace();
+ }
+ return StringUtil.EMPTY_ARRAY;
+ }
+
} // end public class SSHHost
diff --git a/src/com/mostc/pftt/main/Config.java
b/src/com/mostc/pftt/main/Config.java
new file mode 100644
index 0000000..ed752fa
--- /dev/null
+++ b/src/com/mostc/pftt/main/Config.java
@@ -0,0 +1,272 @@
+package com.mostc.pftt.main;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.net.ftp.FTPClient;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.columba.ristretto.smtp.SMTPProtocol;
+
+import com.github.mattficken.io.IOUtil;
+import com.mostc.pftt.host.Host;
+import com.mostc.pftt.scenario.Scenario;
+import com.mostc.pftt.scenario.ScenarioSet;
+import com.mostc.pftt.telemetry.ConsoleManager;
+
+import groovy.lang.GroovyClassLoader;
+import groovy.lang.GroovyObject;
+
+/** Handles loading a configuration (hosts, scenarios, credentials, etc...)
from a groovy script.
+ *
+ * This allows for loading scenarios and hosts without creating a special
configuration format, its just executable code.
+ *
+ * @see Config#getHosts
+ * @see Config#loadConfigFromFile
+ *
+ * An example configuration file:
+ * def hosts() {
+ * [
+ * // connect to a host using ssh
+ * //
+ * // can test multiple operating systems, one host for each OS (so
multiple hosts)
+ * new SSHHost("192.168.1.1", "administrator",
"password01!")
+ * ]
+ * }
+ * def scenario_sets() {
+ * [
+ * // provide address of a MySQL server
+ * new MySQLScenario()
+ * ]
+ * }
+ * def configure_smtp(def smtp_client) {
+ * // specify smtp server and credentials
+ * }
+ * def configure_ftp_client(def ftp_client) {
+ * // specify ftp server and credentials
+ * }
+ *
+ * @author Matt Ficken
+ *
+ */
+
+public final class Config {
+ public static final String HOSTS_METHOD = "hosts";
+ public static final String SCENARIO_SETS_METHOD = "scenario_sets";
+ public static final String SCENARIOS_METHOD = "scenarios";
+ public static final String CONFIGURE_SMTP_METHOD = "configure_smtp";
+ public static final String CONFIGURE_FTP_CLIENT_METHOD =
"configure_ftp_client";
+ //
+ protected final LinkedList<Host> hosts;
+ protected final LinkedList<ScenarioSet> scenario_sets;
+ protected GroovyObject configure_smtp_method,
configure_ftp_client_method;
+
+ protected Config() {
+ hosts = new LinkedList<Host>();
+ scenario_sets = new LinkedList<ScenarioSet>();
+ }
+
+ public List<Host> getHosts() {
+ return hosts;
+ }
+
+ public List<ScenarioSet> getScenarioSets() {
+ return scenario_sets;
+ }
+
+ public boolean configureSMTP(SMTPProtocol smtp) {
+ return configureSMTP(null, smtp);
+ }
+
+ public boolean configureSMTP(ConsoleManager cm, SMTPProtocol smtp) {
+ if (configure_smtp_method==null)
+ return false;
+ try {
+
configure_smtp_method.invokeMethod(CONFIGURE_SMTP_METHOD, smtp);
+
+ return true;
+ } catch ( Exception ex ) {
+ if (cm==null)
+ ex.printStackTrace();
+ else
+ cm.printStackTrace(ex);
+ }
+ return false;
+ }
+
+ public boolean configureFTPClient(FTPClient ftp) {
+ return configureFTPClient(null, ftp);
+ }
+
+ public boolean configureFTPClient(ConsoleManager cm, FTPClient ftp) {
+ if (configure_ftp_client_method==null)
+ return false;
+ try {
+
configure_ftp_client_method.invokeMethod(CONFIGURE_FTP_CLIENT_METHOD, ftp);
+
+ return true;
+ } catch ( Exception ex ) {
+ if (cm==null)
+ ex.printStackTrace();
+ else
+ cm.printStackTrace(ex);
+ }
+ return false;
+ }
+
+ public static Config loadConfigFromStreams(ConsoleManager cm,
InputStream... ins) throws CompilationFailedException, InstantiationException,
IllegalAccessException, IOException {
+ GroovyClassLoader loader = new
GroovyClassLoader(Config.class.getClassLoader());
+
+ Config config = new Config();
+
+ LinkedList<Scenario> scenarios = new LinkedList<Scenario>();
+
scenarios.addAll(Arrays.asList(Scenario.getAllDefaultScenarios()));
+
+ // load each configuration streams
+ GroovyObject go;
+ Class<?> clazz;
+ int i=1;
+ for (InputStream in : ins) {
+ clazz =
loader.parseClass(importString(IOUtil.toString(in)));
+
+ go = (GroovyObject) clazz.newInstance();
+
+ // call methods in file to get configuration (hosts,
etc...)
+ loadObjectToConfig(cm, config, go, scenarios,
"InputStream #"+(i++)+" ("+in+")");
+ }
+
+ return loadConfigCommon(cm, scenarios, config);
+ } // end public static Config loadConfigFromStreams
+
+ public static Config loadConfigFromFiles(ConsoleManager cm, File...
files) throws CompilationFailedException, InstantiationException,
IllegalAccessException, IOException {
+ GroovyClassLoader loader = new
GroovyClassLoader(Config.class.getClassLoader());
+
+ Config config = new Config();
+
+ LinkedList<Scenario> scenarios = new LinkedList<Scenario>();
+
scenarios.addAll(Arrays.asList(Scenario.getAllDefaultScenarios()));
+
+ // load each configuration file
+ GroovyObject go;
+ Class<?> clazz;
+ for (File file : files) {
+ clazz =
loader.parseClass(importString(IOUtil.toString(new FileInputStream(file))));
+
+ go = (GroovyObject) clazz.newInstance();
+
+ // call methods in file to get configuration (hosts,
etc...)
+ loadObjectToConfig(cm, config, go, scenarios,
file.getAbsolutePath());
+ }
+
+ return loadConfigCommon(cm, scenarios, config);
+ } // end public static Config loadConfigFromFiles
+
+ protected static String importString(String code) {
+ // a hack to import common classes for configuration files (XXX
do this a better way)
+ StringBuilder sb = new StringBuilder(128+code.length());
+ // import all standard Scenarios and Host types
+ sb.append("import
");sb.append(Scenario.class.getPackage().getName());sb.append(".*;\n");
+ sb.append("import
");sb.append(Host.class.getPackage().getName());sb.append(".*;\n");
+ sb.append("import
");sb.append(SMTPProtocol.class.getName());sb.append(";\n");
+ sb.append("import
");sb.append(FTPClient.class.getName());sb.append(";\n");
+ sb.append(code);
+ return sb.toString();
+ }
+
+ protected static Config loadConfigCommon(ConsoleManager cm,
LinkedList<Scenario> scenarios, Config config) {
+ // configs may specify individual scenarios, in addition or in
place of whole sets
+ //
+ // permute the given individual scenarios and add them to the
list of scenario sets
+ for (ScenarioSet scenario_set :
ScenarioSet.permuteScenarioSets(scenarios) ) {
+ if (!config.scenario_sets.contains(scenario_set))
+ config.scenario_sets.add(scenario_set);
+ }
+ //
+
+ if (cm!=null) {
+ // report progress
+ if (config.hosts.size()>0) {
+ cm.println("Config", "Loaded
"+config.hosts.size()+" hosts");
+ }
+ if (config.scenario_sets.size()>0) {
+ cm.println("Config", "Loaded
"+config.scenario_sets.size()+" Scenario-Sets");
+ }
+ }
+
+
+ return config;
+ } // end protected static Config loadConfigCommon
+
+ protected static void loadObjectToConfig(ConsoleManager cm, Config
config, GroovyObject go, List<Scenario> scenarios, String file_name) {
+ Object ret;
+ try {
+ ret = go.invokeMethod(HOSTS_METHOD, null);
+ if (ret instanceof List) {
+ for (Object o : (List<?>)ret) {
+ if (o instanceof Host) {
+ if (!config.hosts.contains(o))
+
config.hosts.add((Host)o);
+ } else {
+ cm.println("Config", "List
returned by hosts() must only contain Host objects, not: "+o.getClass()+" see:
"+file_name);
+ }
+ }
+ } else {
+ cm.println("Config", "hosts() must return List
of Hosts, not: "+(ret==null?"null":ret.getClass())+" see: "+file_name);
+ }
+ } catch ( Exception ex ) {
+ }
+ try {
+ ret = go.invokeMethod(SCENARIO_SETS_METHOD, null);
+ if (ret instanceof List) {
+ for (Object o : (List<?>)ret) {
+ if (o instanceof ScenarioSet) {
+ if
(!config.scenario_sets.contains(o))
+
config.scenario_sets.add((ScenarioSet)o);
+ } else {
+ cm.println("Config", "List
returned by scenario_sets() must only contain ScenarioSet objects, not:
"+o.getClass()+" see: "+file_name);
+ }
+ }
+ } else {
+ cm.println("Config", "scenario_sets() must
return List of ScenarioSets, not: "+(ret==null?"null":ret.getClass())+" see:
"+file_name);
+ }
+ } catch ( Exception ex ) {
+ }
+ try {
+ ret = go.invokeMethod(SCENARIOS_METHOD, null);
+ if (ret instanceof List) {
+ for (Object o : (List<?>)ret) {
+ if (o instanceof Scenario) {
+ if (!scenarios.contains(o))
+
scenarios.add((Scenario)o);
+ } else {
+ cm.println("Config", "List
returned by scenarios() must only contain Scenario objects, not:
"+o.getClass()+" see: "+file_name);
+ }
+ }
+ } else {
+ cm.println("Config", "scenarios() must return
List of Scenarios, not: "+(ret==null?"null":ret.getClass())+" see: "+file_name);
+ }
+ } catch ( Exception ex ) {
+ }
+ try {
+ if (go.getProperty(CONFIGURE_SMTP_METHOD)!=null) {
+ if (config.configure_smtp_method!=null)
+ cm.println("Config",
CONFIGURE_SMTP_METHOD+"() overriden by : "+file_name);
+ config.configure_smtp_method = go;
+ }
+ } catch ( Exception ex ) {
+ }
+ try {
+ if (go.getProperty(CONFIGURE_FTP_CLIENT_METHOD)!=null) {
+ if (config.configure_ftp_client_method!=null)
+ cm.println("Config",
CONFIGURE_FTP_CLIENT_METHOD+"() overriden by : "+file_name);
+ config.configure_ftp_client_method = go;
+ }
+ } catch ( Exception ex ) {
+ }
+ } // end protected static void loadObjectToConfig
+
+} // end public final class ConfigUtil
diff --git a/src/com/mostc/pftt/main/ConfigUtil.java
b/src/com/mostc/pftt/main/ConfigUtil.java
deleted file mode 100644
index 4d4eece..0000000
--- a/src/com/mostc/pftt/main/ConfigUtil.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.mostc.pftt.main;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-
-import org.apache.commons.net.ftp.FTPClient;
-import org.codehaus.groovy.control.CompilationFailedException;
-import org.columba.ristretto.smtp.SMTPProtocol;
-
-import com.mostc.pftt.host.Host;
-import com.mostc.pftt.scenario.ScenarioSet;
-
-import groovy.lang.GroovyClassLoader;
-import groovy.lang.GroovyObject;
-
-/** Handles loading a configuration (hosts, scenarios, credentials, etc...)
from a groovy script.
- *
- * This allows for loading scenarios and hosts without creating a special
configuration format, its just executable code.
- *
- * @see ConfigUtil#getHosts
- * @see ConfigUtil#loadConfigFromFile
- *
- * An example configuration file:
- * hosts() {
- * [
- * // connect to a host using ssh
- * //
- * // can test multiple operating systems, one host for each OS (so
multiple hosts)
- * new SSHHost("192.168.1.1", "administrator",
"password01!")
- * ]
- * }
- * scenario_sets() {
- * [
- * // provide address of a MySQL server
- * new MySQLScenario()
- * ]
- * }
- * configure_smtp(def smtp_client) {
- * // specify smtp server and credentials
- * }
- * configure_ftp_client(def ftp_client) {
- * // specify ftp server and credentials
- * }
- *
- * @author Matt Ficken
- *
- */
-
-public final class ConfigUtil {
- public static final String HOSTS_METHOD = "hosts";
- public static final String SCENARIO_SETS_METHOD = "scenario_sets";
- public static final String CONFIGURE_SMTP_METHOD = "configure_smtp";
- public static final String CONFIGURE_FTP_CLIENT_METHOD =
"configure_ftp_client";
-
- @SuppressWarnings("unchecked")
- public static List<Host> getHosts(GroovyObject gobj) {
- return (List<Host>) gobj.invokeMethod(HOSTS_METHOD, null);
- }
-
- @SuppressWarnings("unchecked")
- public static List<ScenarioSet> getScenarioSets(GroovyObject gobj) {
- return (List<ScenarioSet>)
gobj.invokeMethod(SCENARIO_SETS_METHOD, null);
- }
-
- public static void configureSMTPProtocol(GroovyObject gobj,
SMTPProtocol smtp) {
- gobj.invokeMethod(CONFIGURE_SMTP_METHOD, smtp);
- }
-
- public static void configureFTPClient(GroovyObject gobj, FTPClient ftp)
{
- gobj.invokeMethod(CONFIGURE_FTP_CLIENT_METHOD, ftp);
- }
-
- @SuppressWarnings("deprecation")
- public static GroovyObject loadConfigFromStream(InputStream in) throws
CompilationFailedException, InstantiationException, IllegalAccessException {
- GroovyClassLoader gcl = new
GroovyClassLoader(ConfigUtil.class.getClassLoader());
- return (GroovyObject) gcl.parseClass(in).newInstance();
- }
-
- public static GroovyObject loadConfigFromFile(File file) throws
CompilationFailedException, InstantiationException, IllegalAccessException,
IOException {
- GroovyClassLoader gcl = new
GroovyClassLoader(ConfigUtil.class.getClassLoader());
- return (GroovyObject) gcl.parseClass(file).newInstance();
- }
-
- private ConfigUtil() {}
-
-} // end public final class ConfigUtil
diff --git a/src/com/mostc/pftt/main/PfttMain.java
b/src/com/mostc/pftt/main/PfttMain.java
index 94965ae..c708bf9 100644
--- a/src/com/mostc/pftt/main/PfttMain.java
+++ b/src/com/mostc/pftt/main/PfttMain.java
@@ -1,7 +1,6 @@
package com.mostc.pftt.main;
import groovy.lang.Binding;
-import groovy.lang.GroovyObject;
import groovy.ui.Console;
import java.awt.Desktop;
@@ -113,26 +112,28 @@ public class PfttMain {
return last_file == null ? null :
PhptTelemetryReader.open(host, last_file);
}
- public void run_all(ConsoleManager cm, PhpBuild build,
PhptSourceTestPack test_pack, ScenarioSet scenario_set) throws Exception {
- LinkedList<PhptTestCase> test_cases = new
LinkedList<PhptTestCase>();
-
- PhptTelemetryWriter tmgr = new PhptTelemetryWriter(host, cm,
telem_dir(), build, test_pack, scenario_set);
- test_pack.cleanup();
- cm.println("PhptTestPack", "enumerating test cases from
test-pack...");
- test_pack.add_test_files(test_cases, tmgr, build);
- cm.println("PhptTestPack", "enumerated test cases.");
-
- PhptTestPackRunner test_pack_runner = new
PhptTestPackRunner(tmgr, test_pack, scenario_set, build, host);
- cm.showGUI(test_pack_runner);
-
- test_pack_runner.runTestList(test_cases);
-
- tmgr.close();
-
- new PhptTestCountsMatchSmokeTest();
-
- phpt_report(tmgr);
- }
+ public void run_all(ConsoleManager cm, PhpBuild build,
PhptSourceTestPack test_pack, List<ScenarioSet> scenario_sets) throws Exception
{
+ for ( ScenarioSet scenario_set : scenario_sets ) {
+ ArrayList<PhptTestCase> test_cases = new
ArrayList<PhptTestCase>(12600);
+
+ PhptTelemetryWriter tmgr = new
PhptTelemetryWriter(host, cm, telem_dir(), build, test_pack, scenario_set);
+ test_pack.cleanup();
+ cm.println("PhptTestPack", "enumerating test cases from
test-pack...");
+ test_pack.read(test_cases, tmgr, build);
+ cm.println("PhptTestPack", "enumerated test cases.");
+
+ PhptTestPackRunner test_pack_runner = new
PhptTestPackRunner(tmgr, test_pack, scenario_set, build, host);
+ cm.showGUI(test_pack_runner);
+
+ test_pack_runner.runTestList(test_cases);
+
+ tmgr.close();
+
+ new PhptTestCountsMatchSmokeTest();
+
+ phpt_report(tmgr);
+ }
+ } // end public void run_all
protected void phpt_report(PhptTelemetryWriter test_telem) throws
FileNotFoundException {
PhptTelemetryReader base_telem = last_telem(test_telem);
@@ -157,25 +158,27 @@ public class PfttMain {
}
}
- public void run_named_tests(ConsoleManager cm, PhpBuild build,
PhptSourceTestPack test_pack, ScenarioSet scenario_set, List<String> names)
throws Exception {
- LinkedList<PhptTestCase> test_cases = new
LinkedList<PhptTestCase>();
-
- PhptTelemetryWriter tmgr = new PhptTelemetryWriter(host, cm,
telem_dir(), build, test_pack, scenario_set);
- test_pack.cleanup();
- cm.println("PhptTestPack", "enumerating test cases from
test-pack...");
- test_pack.add_named_tests(test_cases, names, tmgr, build);
- cm.println("PhptTestPack", "enumerated test cases.");
-
- PhptTestPackRunner test_pack_runner = new
PhptTestPackRunner(tmgr, test_pack, scenario_set, build, host);
- cm.showGUI(test_pack_runner);
-
- test_pack_runner.runTestList(test_cases);
-
- tmgr.close();
-
- new PhptTestCountsMatchSmokeTest();
-
- phpt_report(tmgr);
+ public void run_named_tests(ConsoleManager cm, PhpBuild build,
PhptSourceTestPack test_pack, List<ScenarioSet> scenario_sets, List<String>
names) throws Exception {
+ for ( ScenarioSet scenario_set : scenario_sets ) {
+ LinkedList<PhptTestCase> test_cases = new
LinkedList<PhptTestCase>();
+
+ PhptTelemetryWriter tmgr = new
PhptTelemetryWriter(host, cm, telem_dir(), build, test_pack, scenario_set);
+ test_pack.cleanup();
+ cm.println("PhptTestPack", "enumerating test cases from
test-pack...");
+ test_pack.read(test_cases, names, tmgr, build);
+ cm.println("PhptTestPack", "enumerated test cases.");
+
+ PhptTestPackRunner test_pack_runner = new
PhptTestPackRunner(tmgr, test_pack, scenario_set, build, host);
+ cm.showGUI(test_pack_runner);
+
+ test_pack_runner.runTestList(test_cases);
+
+ tmgr.close();
+
+ new PhptTestCountsMatchSmokeTest();
+
+ phpt_report(tmgr);
+ } // end for
}
/* -------------------------------------------------- */
@@ -205,12 +208,15 @@ public class PfttMain {
System.out.println();
System.out.println("Options:");
System.out.println("-gui - show gui for certain commands");
- System.out.println("-config <file> - configuration file");
+ System.out.println("-config <file1,file2> - load 1+
configuration file(s)");
System.out.println("-force - disables confirmation dialogs and
forces proceeding anyway");
System.out.println("-stress_each <0+> - runs each test-case N
times consecutively");
System.out.println("-stress_all <0+> - runs all tests N times
in loop");
System.out.println("-results_only - displays only test results
and no other information (for automation).");
System.out.println("-disable_debug_prompt - disables asking you
if you want to debug PHP crashes (for automation. default=enabled)");
+ System.out.println("-phpt-not-in-place - copies PHPTs to a
temporary dir and runs PHPTs from there (default=disabled, test in-place)");
+ System.out.println("-dont-cleanup-test-pack - doesn't delete
temp dir created by -phpt-not-in-place or SMB scenario (default=delete)");
+ System.out.println("-auto - changes default options for
automated testing");
System.out.println("(note: stress options not useful against
CLI without code caching)");
System.out.println();
} // end protected static void cmd_help
@@ -263,11 +269,11 @@ public class PfttMain {
console.run();
}
- protected static void cmd_phpt_all(PfttMain rt, ConsoleManager cm,
GroovyObject config_obj, PhpBuild build, PhptSourceTestPack test_pack) throws
Exception {
- rt.run_all(cm, build, test_pack,
ScenarioSet.getScenarioSets().iterator().next());
+ protected static void cmd_phpt_all(PfttMain rt, ConsoleManager cm,
Config config, PhpBuild build, PhptSourceTestPack test_pack) throws Exception {
+ rt.run_all(cm, build, test_pack,
config==null?ScenarioSet.getDefaultScenarioSets():config.getScenarioSets());
}
- protected static void cmd_phpt_list(PfttMain rt, ConsoleManager cm,
GroovyObject config_obj, PhpBuild build, PhptSourceTestPack test_pack, File
list_file) throws Exception {
+ protected static void cmd_phpt_list(PfttMain rt, ConsoleManager cm,
Config config, PhpBuild build, PhptSourceTestPack test_pack, File list_file)
throws Exception {
BufferedReader fr = new BufferedReader(new
FileReader(list_file));
LinkedList<String> tests = new LinkedList<String>();
String line;
@@ -279,11 +285,11 @@ public class PfttMain {
tests.add(line);
}
- rt.run_named_tests(cm, build, test_pack,
ScenarioSet.getScenarioSets().iterator().next(), tests);
+ rt.run_named_tests(cm, build, test_pack,
config==null?ScenarioSet.getDefaultScenarioSets():config.getScenarioSets(),
tests);
}
- protected static void cmd_phpt_named(PfttMain rt, ConsoleManager cm,
GroovyObject config_obj, PhpBuild build, PhptSourceTestPack test_pack,
List<String> names) throws Exception {
- rt.run_named_tests(cm, build, test_pack,
ScenarioSet.getScenarioSets().iterator().next(), names);
+ protected static void cmd_phpt_named(PfttMain rt, ConsoleManager cm,
Config config, PhpBuild build, PhptSourceTestPack test_pack, List<String>
names) throws Exception {
+ rt.run_named_tests(cm, build, test_pack,
config==null?ScenarioSet.getDefaultScenarioSets():config.getScenarioSets(),
names);
}
protected static void cmd_ui() {
@@ -375,7 +381,7 @@ public class PfttMain {
HttpProtocolParams.setUserAgent(params, "Mozilla/5.0 (Windows
NT 6.1; rv:12.0) Gecko/ 20120405 Firefox/14.0.1");
HttpProtocolParams.setUseExpectContinue(params, true);
- HttpProcessor httpproc = new ImmutableHttpProcessor(new
HttpRequestInterceptor[] {// XXX reuse
+ HttpProcessor httpproc = new ImmutableHttpProcessor(new
HttpRequestInterceptor[] {
// Required protocol interceptors
new RequestContent(),
new RequestTargetHost(),
@@ -568,8 +574,9 @@ public class PfttMain {
//
int args_i = 0;
- GroovyObject config_obj = null;
- boolean show_gui = false, force = false, disable_debug_prompt =
false, results_only = false;
+ Config config = null;
+ boolean show_gui = false, force = false, disable_debug_prompt =
false, results_only = false, dont_cleanup_test_pack = false, phpt_not_in_place
= false;
+ LinkedList<File> config_files = new LinkedList<File>();
int stress_all = 0, stress_each = 0;
//
@@ -579,15 +586,46 @@ public class PfttMain {
} else if (args[args_i].equals("-force")) {
force = true;
} else if (args[args_i].equals("-config")) {
- File config_file = new File(args[args_i++]);
- if (!config_file.isFile()) {
- System.err.println("User Error: config
file not found: "+config_file);
- System.exit(-255);
- return;
- }
-
- // load configuration
- config_obj =
ConfigUtil.loadConfigFromFile(config_file);
+ args_i++;
+ for ( String part :
args[args_i].split("[;|:|,]") ) {
+ File config_file = new File(part);
+ if (config_file.exists()) {
+ if
(!config_files.contains(config_file))
+
config_files.add(config_file);
+ } else {
+ config_file = new
File(part+".groovy");
+ if (config_file.exists()) {
+ if
(!config_files.contains(config_file))
+
config_files.add(config_file);
+ } else {
+ config_file = new
File(LocalHost.getLocalPfttDir()+"/conf/"+part);
+ if
(config_file.exists()) {
+ if
(!config_files.contains(config_file))
+
config_files.add(config_file);
+ } else {
+ config_file =
new File(LocalHost.getLocalPfttDir()+"/conf/"+part+".groovy");
+ if
(config_file.exists()) {
+ if
(!config_files.contains(config_file))
+
config_files.add(config_file);
+ } else {
+
System.err.println("User Error: config file not found: "+config_file);
+
System.exit(-255);
+ break;
+ }
+ }
+ }
+ }
+ } // end for
+ } else if (args[args_i].equals("-phpt-not-in-place")) {
+ phpt_not_in_place = false;
+ } else if
(args[args_i].equals("-dont-cleanup-test-pack")) {
+ dont_cleanup_test_pack = true;
+ } else if (args[args_i].equals("-auto")) {
+ // change these defaults for automated testing
+ disable_debug_prompt = true;
+ results_only = false;
+ dont_cleanup_test_pack = false;
+ phpt_not_in_place = true;
} else if (args[args_i].equals("-stress_each")) {
stress_each = Integer.parseInt(args[args_i++]);
} else if (args[args_i].equals("-stress_all")) {
@@ -619,7 +657,9 @@ public class PfttMain {
System.err.println("PFTT: not implemented:
stress_each="+stress_each+" stress_all="+stress_all+" ignored");
}
- ConsoleManager cm = new ConsoleManager(results_only, show_gui,
disable_debug_prompt);
+ ConsoleManager cm = new ConsoleManager(results_only, show_gui,
disable_debug_prompt, dont_cleanup_test_pack, phpt_not_in_place);
+
+ config = Config.loadConfigFromFiles(cm,
(File[])config_files.toArray(new File[config_files.size()]));
if (command!=null) {
if
(command.equals("phpt_named")||command.equals("phptnamed")||command.equals("phptn")||command.equals("pn"))
{
@@ -653,8 +693,8 @@ public class PfttMain {
cm.println("Build", build.toString());
cm.println("Test-Pack", test_pack.toString());
- HostEnvUtil.prepareHostEnv(rt.host, cm,
!disable_debug_prompt);
- cmd_phpt_named(rt, cm, config_obj, build,
test_pack, names);
+ HostEnvUtil.prepareHostEnv(rt.host, cm,
!cm.isDisableDebugPrompt());
+ cmd_phpt_named(rt, cm, config, build,
test_pack, names);
System.out.println("PFTT: finished");
} else if
(command.equals("phpt_list")||command.equals("phptlist")||command.equals("phptl")||command.equals("pl"))
{
@@ -691,7 +731,7 @@ public class PfttMain {
cm.println("Test-Pack", test_pack.toString());
HostEnvUtil.prepareHostEnv(rt.host, cm,
!disable_debug_prompt);
- cmd_phpt_list(rt, cm, config_obj, build,
test_pack, list_file);
+ cmd_phpt_list(rt, cm, config, build, test_pack,
list_file);
System.out.println("PFTT: finished");
} else if
(command.equals("phpt_all")||command.equals("phptall")||command.equals("phpta")||command.equals("pa"))
{
@@ -722,7 +762,7 @@ public class PfttMain {
// run all tests
HostEnvUtil.prepareHostEnv(rt.host, cm,
!disable_debug_prompt);
- cmd_phpt_all(rt, cm, config_obj, build,
test_pack);
+ cmd_phpt_all(rt, cm, config, build, test_pack);
System.out.println("PFTT: finished");
} else if (command.equals("aut")) {
@@ -735,7 +775,7 @@ public class PfttMain {
}
no_show_gui(show_gui, command);
- cmd_aut(cm, rt, rt.host, build,
ScenarioSet.getScenarioSets());
+ cmd_aut(cm, rt, rt.host, build,
config==null?ScenarioSet.getDefaultScenarioSets():config.getScenarioSets());
} else if (command.equals("shell_ui")||(show_gui &&
command.equals("shell"))) {
cmd_shell_ui();
} else if (command.equals("shell")) {
diff --git a/src/com/mostc/pftt/model/phpt/PhpBuild.java
b/src/com/mostc/pftt/model/phpt/PhpBuild.java
index b972d79..7bd1b3f 100644
--- a/src/com/mostc/pftt/model/phpt/PhpBuild.java
+++ b/src/com/mostc/pftt/model/phpt/PhpBuild.java
@@ -261,11 +261,11 @@ public class PhpBuild extends Build {
public void setDefaultPhpIni(Host host, PhpIni ini) throws IOException {
this.php_ini = new WeakReference<PhpIni>(ini);
- host.saveFile(getDefaultPhpIniPath(host), ini.toString());
+ host.saveTextFile(getDefaultPhpIniPath(host), ini.toString());
if (!host.isWindows()) {
- host.saveFile("/etc/php/cli/php.ini", ini.toString());
- host.saveFile("/etc/php/cgi/php.ini", ini.toString());
+ host.saveTextFile("/etc/php/cli/php.ini",
ini.toString());
+ host.saveTextFile("/etc/php/cgi/php.ini",
ini.toString());
}
}
@@ -298,7 +298,7 @@ public class PhpBuild extends Build {
String php_filename = host.mktempname("Build", ".php");
- host.saveFile(php_filename, code);
+ host.saveTextFile(php_filename, code);
PHPOutput output = new PHPOutput(php_filename,
host.exec(php_exe+" "+php_filename, timeout_seconds, new
HashMap<String,String>(), null, Host.dirname(php_filename)));
if (auto_cleanup && !output.hasFatalError())
diff --git a/src/com/mostc/pftt/model/phpt/PhpIni.java
b/src/com/mostc/pftt/model/phpt/PhpIni.java
index 634d7cc..44f042f 100644
--- a/src/com/mostc/pftt/model/phpt/PhpIni.java
+++ b/src/com/mostc/pftt/model/phpt/PhpIni.java
@@ -104,9 +104,7 @@ public class PhpIni extends TestCaseGroupKey {
ini.putMulti(DISABLE_DEFS, StringUtil.EMPTY);
ini.putMulti(OUTPUT_BUFFERING, OFF);
ini.putMulti(ERROR_REPORTING, E_ALL_OR_E_STRICT);
- // IMPORTANT: display_errors=0. doesn't affect test output.
run-tests.php sets display_errors=1
- // but on Windows, that will cause a blocking
Winpopup message (bad)
- ini.putMulti(DISPLAY_ERRORS, 0);
+ ini.putMulti(DISPLAY_ERRORS, 1);
ini.putMulti(DISPLAY_STARTUP_ERRORS, 0);
ini.putMulti(LOG_ERRORS, 0);
ini.putMulti(HTML_ERRORS, 0);
diff --git a/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java
b/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java
index 93a32e0..c47aee8 100644
--- a/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java
+++ b/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java
@@ -53,18 +53,17 @@ public class PhptSourceTestPack extends SourceTestPack {
// 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("ext/standard/tests/file/windows_links/mklink_junction");
-
host.deleteIfExists("ext/standard/tests/file/windows_links/directory");
-
host.deleteIfExists("ext/standard/tests/file/windows_links/mounted_volume");
-
host.deleteIfExists("ext/standard/tests/file/windows_links/mnt");
+
host.deleteIfExists(test_pack+"/ext/standard/tests/file/windows_links/mklink_junction");
+
host.deleteIfExists(test_pack+"/ext/standard/tests/file/windows_links/directory");
+
host.deleteIfExists(test_pack+"/ext/standard/tests/file/windows_links/mounted_volume");
+
host.deleteIfExists(test_pack+"/ext/standard/tests/file/windows_links/mnt");
}
- public void add_named_tests(List<PhptTestCase> test_files, List<String>
names, PhptTelemetryWriter twriter, PhpBuild build) throws
FileNotFoundException, IOException, Exception {
- add_named_tests(test_files, names, twriter, build, false);
+ public void read(List<PhptTestCase> test_files, List<String> names,
PhptTelemetryWriter twriter, PhpBuild build) throws FileNotFoundException,
IOException, Exception {
+ read(test_files, names, twriter, build, false);
}
- // TODO rename this - always call before (only once) before using
PhptTestPack
- public void add_named_tests(List<PhptTestCase> test_files, List<String>
names, PhptTelemetryWriter twriter, PhpBuild build, boolean ignore_missing)
throws FileNotFoundException, IOException, Exception {
+ public void read(List<PhptTestCase> test_files, List<String> names,
PhptTelemetryWriter twriter, PhpBuild build, boolean ignore_missing) throws
FileNotFoundException, IOException, Exception {
test_pack_file = new File(test_pack);
test_pack = test_pack_file.getAbsolutePath(); // normalize path
@@ -114,7 +113,7 @@ public class PhptSourceTestPack extends SourceTestPack {
twriter.setTotalCount(test_files.size());
}
- public void add_test_files(List<PhptTestCase> test_files,
PhptTelemetryWriter twriter, PhpBuild build) throws FileNotFoundException,
IOException, Exception {
+ public void read(List<PhptTestCase> test_files, PhptTelemetryWriter
twriter, PhpBuild build) throws FileNotFoundException, IOException, Exception {
test_pack_file = new File(test_pack);
test_pack = test_pack_file.getAbsolutePath(); // normalize path
add_test_files(test_pack_file.listFiles(), test_files, null,
twriter, build, null, new LinkedList<PhptTestCase>());
@@ -140,9 +139,6 @@ public class PhptSourceTestPack extends SourceTestPack {
if (test_name.startsWith("/") ||
test_name.startsWith("\\"))
test_name = test_name.substring(1);
-// if (test_name.contains("a_dir"))
-// continue; // TODO
-
PhptTestCase test_case =
PhptTestCase.load(host, this, false, test_name, twriter, redirect_parent);
add_test_case(test_case, test_files, names,
twriter, build, redirect_parent, redirect_targets);
@@ -166,12 +162,8 @@ public class PhptSourceTestPack extends SourceTestPack {
add_test_files(dir.listFiles(),
test_files, names, twriter, build, redirect_parent, redirect_targets);
} else {
- // test refers to a specific
test, try to load it
- //try {
- test_case =
PhptTestCase.load(host, this, false, target_test_name, twriter,
redirect_parent);
- /*} catch ( Exception ex ) {
- ex.printStackTrace();
// TODO temp
- }*/
+ // test refers to a specific
test, load it
+ test_case =
PhptTestCase.load(host, this, false, target_test_name, twriter,
redirect_parent);
if
(redirect_targets.contains(test_case))
// can only have 1
level of redirection
@@ -197,6 +189,10 @@ public class PhptSourceTestPack extends SourceTestPack {
public String getContents(Host host, String name) throws IOException {
return host.getContentsDetectCharset(new File(test_pack_file,
name).getAbsolutePath(), PhptTestCase.newCharsetDeciderDecoder());
}
+
+ public PhptActiveTestPack installInPlace() {
+ return new PhptActiveTestPack(this.getSourceDirectory());
+ }
public PhptActiveTestPack install(Host host, String test_pack_dir)
throws IllegalStateException, IOException, Exception {
if (!this.host.isRemote() || this.host.equals(host)) {
diff --git a/src/com/mostc/pftt/model/phpt/PhptTestCase.java
b/src/com/mostc/pftt/model/phpt/PhptTestCase.java
index d50ac6f..c26d93c 100644
--- a/src/com/mostc/pftt/model/phpt/PhptTestCase.java
+++ b/src/com/mostc/pftt/model/phpt/PhptTestCase.java
@@ -537,6 +537,15 @@ public class PhptTestCase extends TestCase {
return name.equals(o);
}
+ public boolean isNamed(String...names) {
+ // XXX someday, do a Trie structure here to speed up checking
+ for (String name:names) {
+ if (this.name.equals(name))
+ return true;
+ }
+ return false;
+ }
+
/** returns the name of this test.
*
* for standardization/normalization, all backslashes(\) in test names
are converted to unix/forwardslashes(/)
@@ -786,64 +795,60 @@ public class PhptTestCase extends TestCase {
* @return
*/
public boolean isSlowTest() {
- // TODO start the slow tests first, so that all tests finish
faster
- return isSlowTest(getName());
- }
- public static boolean isSlowTest(String test_name) {
- // TODO
- return false;
+ return isNamed(
+ "ext/date/tests/date_diff.phpt",
+ "ext/oci8/tests/bug42496_1.phpt",
+ "ext/oci8/tests/bug42496_2.phpt",
+ "ext/oci8/tests/bug43497.phpt",
+ "ext/oci8/tests/bug43497_92.phpt",
+ "ext/oci8/tests/bug44113.phpt",
+ "ext/oci8/tests/conn_attr_4.phpt",
+ "ext/oci8/tests/error2.phpt",
+ "ext/oci8/tests/extauth_01.phpt",
+ "ext/oci8/tests/extauth_02.phpt",
+ "ext/oci8/tests/extauth_03.phpt",
+ "ext/oci8/tests/lob_043.phpt",
+ "ext/oci8/tests/pecl_bug10194.phpt",
+ "ext/oci8/tests/pecl_bug10194_blob.phpt",
+ "ext/oci8/tests/pecl_bug10194_blob_64.phpt",
+ "ext/phar/tests/bug13727.phpt",
+ "ext/phar/tests/bug45218_SLOWTEST.phpt",
+ "ext/phar/tests/bug45218_SLOWTESTU.phpt",
+ "ext/phar/tests/bug46032.phpt",
+ "ext/phar/tests/bug46060.phpt",
+ "ext/standard/tests/file/001.phpt",
+ "ext/standard/tests/file/005_variation.phpt",
+
"ext/standard/tests/file/file_get_contents_error001.phpt",
+ "ext/standard/tests/file/lstat_stat_basic.phpt",
+
"ext/standard/tests/file/lstat_stat_variation10.phpt",
+
"ext/standard/tests/file/lstat_stat_variation11.phpt",
+
"ext/standard/tests/file/lstat_stat_variation12.phpt",
+
"ext/standard/tests/file/lstat_stat_variation13.phpt",
+
"ext/standard/tests/file/lstat_stat_variation15.phpt",
+
"ext/standard/tests/file/lstat_stat_variation16.phpt",
+
"ext/standard/tests/file/lstat_stat_variation17.phpt",
+
"ext/standard/tests/file/lstat_stat_variation21.phpt",
+
"ext/standard/tests/file/lstat_stat_variation4.phpt",
+
"ext/standard/tests/file/lstat_stat_variation5.phpt",
+
"ext/standard/tests/file/lstat_stat_variation6.phpt",
+
"ext/standard/tests/file/lstat_stat_variation8.phpt",
+ "ext/standard/tests/file/touch_basic.phpt",
+
"ext/standard/tests/general_functions/bug39322.phpt",
+
"ext/standard/tests/general_functions/proc_open02.phpt",
+
"ext/standard/tests/general_functions/sleep_basic.phpt",
+
"ext/standard/tests/general_functions/usleep_basic.phpt",
+
"ext/standard/tests/misc/time_nanosleep_basic.phpt",
+
"ext/standard/tests/misc/time_sleep_until_basic.phpt",
+
"ext/standard/tests/network/gethostbyname_basic001.phpt",
+
"ext/standard/tests/network/gethostbyname_error004.phpt",
+ "ext/standard/tests/network/getmxrr.phpt",
+ "ext/standard/tests/network/http-stream.phpt",
+ "tests/func/005a.phpt",
+ "tests/func/010.phpt",
+ "tests/lang/045.phpt",
+ "Zend/tests/bug55509.phpt"
+ );
}
- /* ext/date/tests/date_diff.phpt
-ext/oci8/tests/bug42496_1.phpt
-ext/oci8/tests/bug42496_2.phpt
-ext/oci8/tests/bug43497.phpt
-ext/oci8/tests/bug43497_92.phpt
-ext/oci8/tests/bug44113.phpt
-ext/oci8/tests/conn_attr_4.phpt
-ext/oci8/tests/error2.phpt
-ext/oci8/tests/extauth_01.phpt
-ext/oci8/tests/extauth_02.phpt
-ext/oci8/tests/extauth_03.phpt
-ext/oci8/tests/lob_043.phpt
-ext/oci8/tests/pecl_bug10194.phpt
-ext/oci8/tests/pecl_bug10194_blob.phpt
-ext/oci8/tests/pecl_bug10194_blob_64.phpt
-ext/phar/tests/bug13727.phpt
-ext/phar/tests/bug45218_SLOWTEST.phpt
-ext/phar/tests/bug45218_SLOWTESTU.phpt
-ext/phar/tests/bug46032.phpt
-ext/phar/tests/bug46060.phpt
-ext/standard/tests/file/001.phpt
-ext/standard/tests/file/005_variation.phpt
-ext/standard/tests/file/file_get_contents_error001.phpt
-ext/standard/tests/file/lstat_stat_basic.phpt
-ext/standard/tests/file/lstat_stat_variation10.phpt
-ext/standard/tests/file/lstat_stat_variation11.phpt
-ext/standard/tests/file/lstat_stat_variation12.phpt
-ext/standard/tests/file/lstat_stat_variation13.phpt
-ext/standard/tests/file/lstat_stat_variation15.phpt
-ext/standard/tests/file/lstat_stat_variation16.phpt
-ext/standard/tests/file/lstat_stat_variation17.phpt
-ext/standard/tests/file/lstat_stat_variation21.phpt
-ext/standard/tests/file/lstat_stat_variation4.phpt
-ext/standard/tests/file/lstat_stat_variation5.phpt
-ext/standard/tests/file/lstat_stat_variation6.phpt
-ext/standard/tests/file/lstat_stat_variation8.phpt
-ext/standard/tests/file/touch_basic.phpt
-ext/standard/tests/general_functions/bug39322.phpt
-ext/standard/tests/general_functions/proc_open02.phpt
-ext/standard/tests/general_functions/sleep_basic.phpt
-ext/standard/tests/general_functions/usleep_basic.phpt
-ext/standard/tests/misc/time_nanosleep_basic.phpt
-ext/standard/tests/misc/time_sleep_until_basic.phpt
-ext/standard/tests/network/gethostbyname_basic001.phpt
-ext/standard/tests/network/gethostbyname_error004.phpt
-ext/standard/tests/network/getmxrr.phpt
-ext/standard/tests/network/http-stream.phpt
-tests/func/005a.phpt
-tests/func/010.phpt
-tests/lang/045.phpt
-Zend/tests/bug55509.phpt */
public static DefaultCharsetDeciderDecoder newCharsetDeciderDecoder() {
return new
DefaultCharsetDeciderDecoder(CharsetDeciderDecoder.EXPRESS_RECOGNIZERS);
diff --git a/src/com/mostc/pftt/report/AbstractReportGen.groovy
b/src/com/mostc/pftt/report/AbstractReportGen.groovy
index be0f565..64549a5 100644
--- a/src/com/mostc/pftt/report/AbstractReportGen.groovy
+++ b/src/com/mostc/pftt/report/AbstractReportGen.groovy
@@ -13,7 +13,7 @@ abstract class AbstractReportGen implements Runnable {
System.out.println(html_file);
System.out.println(html_str);
- host.saveFile(html_file, html_str);
+ host.saveTextFile(html_file, html_str);
return html_file;
}
diff --git a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner.java
b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner.java
index 3e806c5..1359a64 100644
--- a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner.java
@@ -55,7 +55,7 @@ public abstract class AbstractPhptTestCaseRunner {
return true;
// TODO openbasedir
- } else if
(test_case.isNamed("tests/security/open_basedir_is_file.phpt")||test_case.isNamed("ext/standard/tests/php_ini_loaded_file.phpt")||test_case.isNamed("tests/run-test/test010.phpt")||test_case.isNamed("ext/standard/tests/misc/time_sleep_until_basic.phpt")
|| test_case.getName().contains("session") ||
test_case.isNamed("ext/standard/tests/misc/time_nanosleep_basic.phpt")) {
+ } else if
(test_case.isNamed("tests/security/open_basedir_is_file.phpt",
"ext/standard/tests/php_ini_loaded_file.phpt", "tests/run-test/test010.phpt",
"ext/standard/tests/misc/time_sleep_until_basic.phpt",
"ext/standard/tests/misc/time_nanosleep_basic.phpt")) {
twriter.addResult(new PhptTestResult(host,
EPhptTestStatus.XSKIP, test_case, "test sometimes randomly fails, ignore it",
null, null, null, null, null, null, null, null, null, null));
return true;
diff --git a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
index a4a7b09..f9cfb7d 100644
--- a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
+++ b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
@@ -1,7 +1,6 @@
package com.mostc.pftt.runner;
import java.io.ByteArrayOutputStream;
-import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Map;
@@ -39,20 +38,14 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
protected final PhptThread thread;
protected final PhptActiveTestPack active_test_pack;
protected byte[] stdin_post;
- // TODO cleanup field names
protected String skipif_file;
- protected String cmd;
- protected String shell_script;
- protected String ini_settings;
- protected String shell_file, selected_php_exe;
- protected String temp_target;
- protected String temp_source;
protected String test_dir;
protected String base_file_name;
protected String test_file;
protected String test_clean;
- protected String tmp_post, content_type;
- protected final PhpIni ini;
+ protected String content_type;
+ protected PhpIni ini;
+ protected String tmp_post; // TODO move this to telemetry manager
/** runs the test case and reports the results to the
PhptTelemetryManager
*
@@ -61,13 +54,10 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
*/
@Override
public void runTest() throws IOException, Exception, Throwable {
- // Default ini settings
-// ini = PhpIni.createDefaultIniCopy(host);
if (!prepare())
+ // test is SKIP BORK EXCEPTION etc...
return;
- // XXX check if prepare() has borked the test -> don't bother
running SKIPIF leads to test_skipif=null -> exception
-
notifyStart();
try {
@@ -120,19 +110,14 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
}
test_dir =
active_test_pack.getDirectory()+host.dirSeparator()+Host.dirname(test_case.getName());
-
- /*if (temp_source!=null && temp_target!=null) {
- // XXX needed??
- test_dir =
StringUtil.replaceAll(Pattern.compile(temp_source), temp_target, test_dir);
- }*/
- base_file_name =
Host.basename(test_case.getName()).replaceAll(".phpt", ""); // TODO clean this
up
+ base_file_name =
Host.basename(Host.removeFileExt(test_case.getName()));
//
if (test_case.containsSection(EPhptSection.SKIPIF)) {
skipif_file = test_dir + host.dirSeparator() +
base_file_name + ".skip.php";
- host.saveFile(skipif_file,
test_case.get(EPhptSection.SKIPIF));
+ host.saveTextFile(skipif_file,
test_case.get(EPhptSection.SKIPIF));
} else {
// clearly flag that skipif isn't to be executed
skipif_file = null;
@@ -144,18 +129,13 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
test_clean = test_dir + host.dirSeparator() + base_file_name +
".clean.php";
tmp_post = test_dir + host.dirSeparator() + base_file_name +
".post.php";
- /*if (temp_source!=null && temp_target!=null) {
- // TODO temp
- String copy_file = test_dir + host.dirSeparator() +
Host.basename(test_case.getName()) + ".phps";
-
- if (!new File(Host.dirname(copy_file)).isDirectory()) {
- new File(Host.dirname(copy_file)).mkdirs();
- }
- }*/
-
-
//
- ini_settings = ini.toCliArgString(host);
+ if (test_case.containsSection(EPhptSection.INI)) {
+ PhpIni ini = test_case.getINI(active_test_pack, host);
+ ini.appendAll(this.ini);
+ this.ini = ini;
+ }
+ //
return true;
} // end boolean prepare
@@ -215,13 +195,9 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
// open external file and copy to test_file (binary, no
char conversion - which could break it - often this is a PHAR file - which will
be broken if charset coversion is done)
host.copy(src_test_pack.getSourceDirectory()+host.dirSeparator()+Host.dirname(test_case.getName())
+ "/" + test_case.get(EPhptSection.FILE_EXTERNAL), test_file);
} else {
- host.saveFile(test_file,
test_case.get(EPhptSection.FILE), test_case.getCommonCharset());
+ host.saveTextFile(test_file,
test_case.get(EPhptSection.FILE), test_case.getCommonCharset());
}
-
- // copy CLI args to pass
- String args = test_case.containsSection(EPhptSection.ARGS) ? "
-- " + test_case.get(EPhptSection.ARGS) : "";
-
-
+
// copy STDIN to pass (POST, POST_RAW, STDIN, etc...)
if (test_case.containsSection(EPhptSection.POST_RAW)) {
String post = test_case.getTrim(EPhptSection.POST_RAW);
@@ -251,10 +227,10 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
request_sb.append(line);
request_sb.append('\n');
}
- } else {
+ } // TODO else {
request_sb.append(line);
request_sb.append('\n');
- }
+ //}
}
String request = request_sb.toString();
@@ -271,12 +247,10 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
return;
}
- host.saveFile(tmp_post, request);
+ host.saveTextFile(tmp_post, request);
stdin_post = request.getBytes();
- cmd = selected_php_exe+" "+ini_settings+" -f
\""+test_file+"\"";
-
} else if (test_case.containsSection(EPhptSection.PUT)) {
String post = test_case.getTrim(EPhptSection.PUT);
String[] raw_lines = StringUtil.splitLines(post);
@@ -311,7 +285,6 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
}
stdin_post = request.getBytes();
- cmd = selected_php_exe+" "+ini_settings+" -f
\""+test_file+"\"";
} else if (test_case.containsSection(EPhptSection.POST)) {
@@ -319,7 +292,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
if (test_case.containsSection(EPhptSection.GZIP_POST)) {
// php's gzencode() => gzip compression =>
java's GZIPOutputStream
- //post = gzencode(post, 9, FORCE_GZIP);
+ // post = gzencode(post, 9, FORCE_GZIP);
ByteArrayOutputStream baos = new
ByteArrayOutputStream();
GZIPOutputStreamLevel d = new
GZIPOutputStreamLevel(baos, 9);
d.write(post.getBytes());
@@ -328,7 +301,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
setContentEncoding("gzip");
} else if
(test_case.containsSection(EPhptSection.DEFLATE_POST)) {
// php's gzcompress() => zlib compression =>
java's DeflaterOutputStream
- //post = gzcompress(post, 9);
+ // post = gzcompress(post, 9);
ByteArrayOutputStream baos = new
ByteArrayOutputStream();
DeflaterOutputStream d = new
DeflaterOutputStream(baos, new Deflater(9));
d.write(post.getBytes());
@@ -346,19 +319,13 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
setContentType("application/x-www-form-urlencoded");
// critical: php-cgi won"t read more bytes than this
(thus some input can go missing)
setContentLength(content_length);
-
- cmd = selected_php_exe+" "+ini_settings+" -f
\""+test_file+"\"";
-
- } else {
+ } else {
setRequestMethod("GET");
if (!hasContentType())
setContentType(StringUtil.EMPTY);
setContentLength(0);
-
- cmd = selected_php_exe+" "+ini_settings+" -f
\""+test_file+"\" "+args;
}
-
} // end void prepareTest
protected void setContentEncoding(String encoding) {
@@ -434,9 +401,9 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
twriter.show_exception(test_case, ex, expected);
throw ex;
}
- if (expected_re_match||check()) {
+ if (expected_re_match) {
- twriter.addResult(new PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, getEnv(), splitCmdString(), stdin_post,
shell_script, null, null, null));
+ twriter.addResult(new PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, getEnv(), splitCmdString(), stdin_post,
getShellScript(), null, null, null));
return;
}
@@ -446,9 +413,9 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
output = remove_header_from_output(output);
output_trim = output.trim();
- if
(output_trim.equals(expected)||output_trim.contains(expected)||expected.contains(output_trim)||check())
{
+ if
(output_trim.equals(expected)||output_trim.contains(expected)||expected.contains(output_trim))
{
- twriter.addResult(new PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, getEnv(), splitCmdString(), stdin_post,
shell_script, null, null, null));
+ twriter.addResult(new PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, getEnv(), splitCmdString(), stdin_post,
getShellScript(), null, null, null));
return;
}
@@ -462,9 +429,9 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
// fall through to failing or xfailing the test
} else {
// compare again
- if
(output_trim.equals(expected)||output_trim.contains(expected)||expected.contains(output_trim)||(output_trim.length()>20&&expected.length()>20&&output_trim.substring(10,
20).equals(expected.substring(10, 20)))||check()) {
+ if
(output_trim.equals(expected)||output_trim.contains(expected)||expected.contains(output_trim)||(output_trim.length()>20&&expected.length()>20&&output_trim.substring(10,
20).equals(expected.substring(10, 20)))) {
- twriter.addResult(new
PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, getEnv(), splitCmdString(), stdin_post,
shell_script, null, null, null));
+ twriter.addResult(new
PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, getEnv(), splitCmdString(), stdin_post,
getShellScript(), null, null, null));
return;
} // end if
@@ -473,8 +440,8 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
output = remove_header_from_output(output);
output_trim = output.trim();
- if (StringUtil.isEmpty(output_trim)||check()) {
- twriter.addResult(new PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, getEnv(), splitCmdString(), stdin_post,
shell_script, null, null, null));
+ if (StringUtil.isEmpty(output_trim)) {
+ twriter.addResult(new PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, getEnv(), splitCmdString(), stdin_post,
getShellScript(), null, null, null));
return;
}
@@ -483,7 +450,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
// if here, test failed!
if (test_case.isXFail()) {
- twriter.addResult(new PhptTestResult(host,
EPhptTestStatus.XFAIL, test_case, output, null, null, charset, getEnv(),
splitCmdString(), stdin_post, shell_script, null, null, preoverride_actual));
+ twriter.addResult(new PhptTestResult(host,
EPhptTestStatus.XFAIL, test_case, output, null, null, charset, getEnv(),
splitCmdString(), stdin_post, getShellScript(), null, null,
preoverride_actual));
} else {
// test is FAIL
@@ -500,18 +467,18 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
expectf = null;
}
- twriter.addResult(new PhptTestResult(host,
EPhptTestStatus.FAIL, test_case, output, actual_lines, expected_lines, charset,
getEnv(), splitCmdString(), stdin_post, shell_script, diff, expectf,
preoverride_actual, getCrashedSAPIOutput()));
+ twriter.addResult(new PhptTestResult(host,
EPhptTestStatus.FAIL, test_case, output, actual_lines, expected_lines, charset,
getEnv(), splitCmdString(), stdin_post, getShellScript(), diff, expectf,
preoverride_actual, getCrashedSAPIOutput()));
}
} // end void evalTest
protected Map<String, String> getEnv() {
return null;
}
- protected boolean check() {
- // TODO temp
- return StringUtil.isEmpty(getCrashedSAPIOutput());
+
+ protected String getShellScript() {
+ return null;
}
-
+
protected abstract String[] splitCmdString();
protected static String remove_header_from_output(String output) {
diff --git a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
index 9b8991b..241652e 100644
--- a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
@@ -37,7 +37,7 @@ import com.mostc.pftt.util.StringUtil;
public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 {
protected ExecOutput output;
protected HashMap<String,String> env;
- protected String skip_cmd;
+ protected String selected_php_exe, shell_script, test_cmd, skip_cmd,
ini_settings, shell_file;
public CliPhptTestCaseRunner(PhpIni ini, PhptThread thread,
PhptTestCase test_case, PhptTelemetryWriter twriter, Host host, ScenarioSet
scenario_set, PhpBuild build, PhptSourceTestPack src_test_pack,
PhptActiveTestPack active_test_pack) {
super(ini, thread, test_case, twriter, host, scenario_set,
build, src_test_pack, active_test_pack);
@@ -48,6 +48,8 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
@Override
protected boolean prepare() throws IOException, Exception {
if (super.prepare()) {
+ ini_settings = ini.toCliArgString(host);
+
// read ENV vars from test, from its parent (if a test
redirected to this test), and merge from scenario
env = test_case.getENV(env,
twriter.getConsoleManager(), host, build);
@@ -77,6 +79,12 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
protected void prepareTest() throws Exception {
super.prepareTest();
+ // copy CLI args to pass
+ String args = test_case.containsSection(EPhptSection.ARGS) ? "
-- " + test_case.get(EPhptSection.ARGS) : "";
+
+ // generate cmd string to run test_file with php.exe
+ test_cmd = selected_php_exe+" "+ini_settings+" -f
\""+test_file+"\""+(args==null?"":" "+args);
+
if (test_case.containsSection(EPhptSection.STDIN)) {
if (host.isWindows()) {
// @see Zend/tests/multibyte*
@@ -145,11 +153,6 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
}
@Override
- protected Map<String, String> getEnv() {
- return this.env;
- }
-
- @Override
protected String executeSkipIf() throws Exception {
// Check if test should be skipped.
if (skipif_file != null) {
@@ -182,7 +185,7 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
@Override
protected void executeClean() throws Exception {
if (test_case.containsSection(EPhptSection.CLEAN)) {
- host.saveFile(test_clean,
test_case.getTrim(EPhptSection.CLEAN), null);
+ host.saveTextFile(test_clean,
test_case.getTrim(EPhptSection.CLEAN), null);
env.remove(ENV_REQUEST_METHOD);
env.remove(ENV_QUERY_STRING);
@@ -245,7 +248,7 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
} else
fw.println("export "+name+"=\""+value+"\"");
}
- fw.println(cmd);
+ fw.println(test_cmd);
fw.close();
shell_script = sw.toString();
FileWriter w = new FileWriter(shell_file);
@@ -279,7 +282,17 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
@Override
protected String[] splitCmdString() {
- return LocalHost.splitCmdString(cmd);
+ return LocalHost.splitCmdString(test_cmd);
+ }
+
+ @Override
+ protected Map<String, String> getEnv() {
+ return env;
+ }
+
+ @Override
+ protected String getShellScript() {
+ return shell_script;
}
} // end public class CliTestCaseRunner
diff --git a/src/com/mostc/pftt/runner/HttpTestCaseRunner.java
b/src/com/mostc/pftt/runner/HttpTestCaseRunner.java
index 7d6aa3e..2d08c9d 100644
--- a/src/com/mostc/pftt/runner/HttpTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/HttpTestCaseRunner.java
@@ -72,6 +72,8 @@ public class HttpTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
twriter.addResult(new PhptTestResult(host,
EPhptTestStatus.XSKIP, test_case, "ENV section not supported for testing
against web servers", null, null, null, null, null, null, null, null, null,
null));
else if (test_case.containsSection(EPhptSection.STDIN))
twriter.addResult(new PhptTestResult(host,
EPhptTestStatus.XSKIP, test_case, "STDIN section not supported for testing
against web servers", null, null, null, null, null, null, null, null, null,
null));
+ else if (test_case.containsSection(EPhptSection.ARGS))
+ twriter.addResult(new PhptTestResult(host,
EPhptTestStatus.XSKIP, test_case, "ARGS section not supported for testing
against web servers", null, null, null, null, null, null, null, null, null,
null));
return false;
}
diff --git a/src/com/mostc/pftt/runner/PhptTestPackRunner.java
b/src/com/mostc/pftt/runner/PhptTestPackRunner.java
index f8aea39..8d73ace 100644
--- a/src/com/mostc/pftt/runner/PhptTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/PhptTestPackRunner.java
@@ -6,6 +6,7 @@ import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
import com.mostc.pftt.host.Host;
import com.mostc.pftt.model.phpt.PhpBuild;
@@ -34,24 +35,32 @@ public class PhptTestPackRunner extends
AbstractTestPackRunner {
protected final PhptSourceTestPack src_test_pack;
protected final PhptTelemetryWriter twriter;
protected PhptActiveTestPack active_test_pack;
- protected ETestPackRunnerState runner_state;
+ protected AtomicReference<ETestPackRunnerState> runner_state;
protected AtomicInteger test_count, active_thread_count;
protected HashMap<TestCaseGroupKey,LinkedBlockingQueue<PhptTestCase>>
thread_safe_tests;
protected
HashMap<String,HashMap<TestCaseGroupKey,LinkedBlockingQueue<PhptTestCase>>>
non_thread_safe_tests;
protected AbstractSAPIScenario sapi_scenario;
+ protected AbstractFileSystemScenario file_scenario;
protected LinkedBlockingQueue<TestCaseGroupKey> group_keys;
public PhptTestPackRunner(PhptTelemetryWriter twriter,
PhptSourceTestPack test_pack, ScenarioSet scenario_set, PhpBuild build, Host
host) {
super(scenario_set, build, host);
this.twriter = twriter;
this.src_test_pack = test_pack;
+
+ runner_state = new AtomicReference<ETestPackRunnerState>();
}
public void runTestList(List<PhptTestCase> test_cases) throws Exception
{
- // XXX if already running, wait
- runner_state = ETestPackRunnerState.RUNNING;
+ // if already running, wait
+ while (runner_state.get()==ETestPackRunnerState.RUNNING) {
+ Thread.sleep(100);
+ }
+ //
+
+ runner_state.set(ETestPackRunnerState.RUNNING);
sapi_scenario = ScenarioSet.getSAPIScenario(scenario_set);
- AbstractFileSystemScenario file_scenario =
ScenarioSet.getFileSystemScenario(scenario_set);
+ file_scenario = ScenarioSet.getFileSystemScenario(scenario_set);
////////////////// install test-pack onto the storage it will
be run from
// for local file system, this is just a file copy. for other
scenarios, its more complicated (let the filesystem scenario deal with it)
@@ -89,10 +98,10 @@ public class PhptTestPackRunner extends
AbstractTestPackRunner {
active_test_pack = null;
try {
// TODO console option (local filesystem scenario only)
to use PhptSourceTestPack as PhptActiveTestPack
- // -phpt-in-place
- // if not -auto and local file system, do in-place
by default
- // if -auto, don't do in-place
- active_test_pack = src_test_pack.install(host,
test_pack_dir);
+ if (twriter.getConsoleManager().isPhptNotInPlace() ||
!file_scenario.allowPhptInPlace())
+ active_test_pack = src_test_pack.install(host,
test_pack_dir);
+ else
+ active_test_pack =
src_test_pack.installInPlace();
} catch (Exception ex ) {
twriter.getConsoleManager().printStackTrace(ex);
}
@@ -121,20 +130,23 @@ public class PhptTestPackRunner extends
AbstractTestPackRunner {
// TODO serialSAPIInstance_executeTestCases();
parallelSAPIInstance_executeTestCases();
- // delete if successful (otherwise leave it behind for
user to analyze the internal exception(s))
- // TODO console option to not cleanup
-
twriter.getConsoleManager().println("PhptTestPackRunner", "deleting up active
test-pack: "+active_test_pack);
- host.delete(active_test_pack.getDirectory());
+ // TODO delete if successful (otherwise leave it behind
for user to analyze the internal exception(s))
+ if
(!twriter.getConsoleManager().isDontCleanupTestPack() &&
!active_test_pack.getDirectory().equals(src_test_pack.getSourceDirectory())) {
+
twriter.getConsoleManager().println("PhptTestPackRunner", "deleting/cleaning-up
active test-pack: "+active_test_pack);
+ host.delete(active_test_pack.getDirectory());
+
+ // cleanup, disconnect storage, etc...
+
file_scenario.notifyFinishedTestPack(twriter.getConsoleManager(), host);
+ }
+ //
} finally {
// be sure all running WebServerInstances, or other
SAPIInstances are
- // closed by end of testing (otherwise php.exe -S will
keep on running)
+ // closed by end of testing (otherwise `php.exe -S`
will keep on running)
close();
}
} // end public void runTestList
public void close() {
- if (sapi_scenario instanceof AbstractWebServerScenario) // TODO
temp
- ((AbstractWebServerScenario)sapi_scenario).smgr.close();
sapi_scenario.close();
}
@@ -360,7 +372,7 @@ public class PhptTestPackRunner extends
AbstractTestPackRunner {
test_case = jobs.poll()
) != null &&
run_thread.get() &&
-
runner_state==ETestPackRunnerState.RUNNING
+
runner_state.get()==ETestPackRunnerState.RUNNING
) {
// CRITICAL: catch exception so thread will
always end normally
try {
@@ -378,8 +390,6 @@ public class PhptTestPackRunner extends
AbstractTestPackRunner {
counter++;
test_count.incrementAndGet();
-
- //Thread.yield()
}
} // end protected void exec_jobs
@@ -405,12 +415,12 @@ public class PhptTestPackRunner extends
AbstractTestPackRunner {
@Override
public void setState(ETestPackRunnerState state) throws
IllegalStateException {
- this.runner_state = state;
+ this.runner_state.set(state);
}
@Override
public ETestPackRunnerState getState() {
- return runner_state;
+ return runner_state.get();
}
} // end public class PhptTestPackRunner
diff --git a/src/com/mostc/pftt/scenario/AbstractCodeCacheScenario.java
b/src/com/mostc/pftt/scenario/AbstractCodeCacheScenario.java
index 69aaef9..3dd3782 100644
--- a/src/com/mostc/pftt/scenario/AbstractCodeCacheScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractCodeCacheScenario.java
@@ -1,5 +1,8 @@
package com.mostc.pftt.scenario;
public abstract class AbstractCodeCacheScenario extends AbstractSerialScenario
{
-
+ @Override
+ public Class<?> getSerialKey() {
+ return AbstractCodeCacheScenario.class;
+ }
}
diff --git a/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java
b/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java
index 58bf174..ae9bf92 100644
--- a/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java
@@ -4,11 +4,23 @@ import com.mostc.pftt.host.Host;
import com.mostc.pftt.telemetry.ConsoleManager;
public abstract class AbstractFileSystemScenario extends
AbstractSerialScenario {
-
+ @Override
+ public Class<?> getSerialKey() {
+ return AbstractFileSystemScenario.class;
+ }
public abstract boolean notifyPrepareStorageDir(ConsoleManager cm, Host
host);
public abstract String getTestPackStorageDir(Host host);
public boolean notifyTestPackInstalled(ConsoleManager cm, Host host) {
return true; // proceed with using test-pack
}
+ /** checks if -phpt-in-place console option can be ignored or not
+ *
+ * @return FALSE - ignore -phpt-in-place, TRUE to follow it (if present)
+ */
+ public abstract boolean allowPhptInPlace();
+ public void notifyFinishedTestPack(ConsoleManager consoleManager, Host
host) {
+
+ }
+
}
diff --git a/src/com/mostc/pftt/scenario/AbstractParallelScenario.java
b/src/com/mostc/pftt/scenario/AbstractParallelScenario.java
index eefa4ab..7e72338 100644
--- a/src/com/mostc/pftt/scenario/AbstractParallelScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractParallelScenario.java
@@ -7,8 +7,5 @@ package com.mostc.pftt.scenario;
*/
public abstract class AbstractParallelScenario extends Scenario {
- @Override
- public boolean rejectOther(Scenario o) {
- return o instanceof AbstractParallelScenario &&
!o.getClass().isInstance(this);
- }
+
}
diff --git a/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java
b/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java
index 5d257f6..c8dc38d 100644
--- a/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java
@@ -24,6 +24,11 @@ import com.mostc.pftt.telemetry.PhptTelemetryWriter;
public abstract class AbstractSAPIScenario extends AbstractSerialScenario {
+ @Override
+ public Class<?> getSerialKey() {
+ return AbstractSAPIScenario.class;
+ }
+
/** creates a runner to run a single PhptTestCase under this SAPI
scenario
*
* @param thread
diff --git a/src/com/mostc/pftt/scenario/AbstractSMBScenario.java
b/src/com/mostc/pftt/scenario/AbstractSMBScenario.java
index 1936eea..898fd6e 100644
--- a/src/com/mostc/pftt/scenario/AbstractSMBScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractSMBScenario.java
@@ -39,6 +39,13 @@ public abstract class AbstractSMBScenario extends
AbstractFileSystemScenario {
this.base_share_name = base_share_name;
}
+ @Override
+ public boolean allowPhptInPlace() {
+ // always make sure test-pack is installed onto SMB Share
+ // otherwise, there wouldn't be a point in testing on SMB
+ return false;
+ }
+
/** creates a File Share and connects to it.
*
* a test-pack can then be installed on that File Share.
@@ -101,7 +108,7 @@ public abstract class AbstractSMBScenario extends
AbstractFileSystemScenario {
return false;
}
} else {
- // XXX
+ // host is local, try using a local drive, normal file
system operations, not SMB, etc...
local_drive = file_path;
return true;
@@ -133,4 +140,34 @@ public abstract class AbstractSMBScenario extends
AbstractFileSystemScenario {
return local_drive; // H: I: J: ... Y:
}
+ public boolean deleteShare(ConsoleManager cm, Host host) {
+ try {
+ if (host.execElevated("NET SHARE "+file_path+"
/DELETE", Host.ONE_MINUTE).isSuccess()) {
+ host.delete(file_path);
+
+ return true;
+ }
+ } catch ( Exception ex ) {
+ cm.printStackTrace(ex);
+ }
+ return false;
+ }
+
+ public boolean disconnect(ConsoleManager cm, Host host) {
+ try {
+ return host.exec("NET USE "+local_drive+" /DELETE",
Host.ONE_MINUTE).isSuccess();
+ } catch ( Exception ex ) {
+ cm.printStackTrace(ex);
+ }
+ return false;
+ }
+
+ @Override
+ public void notifyFinishedTestPack(ConsoleManager cm, Host host) {
+ if (deleteShare(cm, host) && disconnect(cm, host)) {
+ // reset
+ share_name = file_path = unc_path = smb_path =
local_drive = null;
+ }
+ }
+
} // end public abstract class AbstractSMBScenario
diff --git a/src/com/mostc/pftt/scenario/AbstractSerialScenario.java
b/src/com/mostc/pftt/scenario/AbstractSerialScenario.java
index 68b73b3..da8358a 100644
--- a/src/com/mostc/pftt/scenario/AbstractSerialScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractSerialScenario.java
@@ -9,8 +9,7 @@ package com.mostc.pftt.scenario;
*/
public abstract class AbstractSerialScenario extends Scenario {
+
@Override
- public boolean rejectOther(Scenario o) {
- return false;
- }
+ public abstract Class<?> getSerialKey();
}
diff --git a/src/com/mostc/pftt/scenario/AbstractSocketScenario.java
b/src/com/mostc/pftt/scenario/AbstractSocketScenario.java
index 4c0cdc0..5def2a0 100644
--- a/src/com/mostc/pftt/scenario/AbstractSocketScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractSocketScenario.java
@@ -1,5 +1,8 @@
package com.mostc.pftt.scenario;
public abstract class AbstractSocketScenario extends AbstractOptionScenario {
-
+ @Override
+ public Class<?> getSerialKey() {
+ return AbstractSocketScenario.class;
+ }
}
diff --git a/src/com/mostc/pftt/scenario/CLIScenario.java
b/src/com/mostc/pftt/scenario/CLIScenario.java
index ce2b5db..63fa894 100644
--- a/src/com/mostc/pftt/scenario/CLIScenario.java
+++ b/src/com/mostc/pftt/scenario/CLIScenario.java
@@ -40,8 +40,7 @@ public class CliScenario extends AbstractSAPIScenario {
@Override
public int getTestThreadCount(Host host) {
- // 4 => 395
- return 2 * host.getCPUCount();
+ return 4 * host.getCPUCount();
}
} // end public class CliScenario
diff --git a/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java
b/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java
index a555970..06c1c69 100644
--- a/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java
+++ b/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java
@@ -20,6 +20,11 @@ public class LocalFileSystemScenario extends
AbstractFileSystemScenario {
public boolean isImplemented() {
return true;
}
+
+ @Override
+ public boolean allowPhptInPlace() {
+ return false;
+ }
@Override
public boolean notifyPrepareStorageDir(ConsoleManager cm, Host host) {
diff --git a/src/com/mostc/pftt/scenario/SMBCSCOptionScenario.java
b/src/com/mostc/pftt/scenario/SMBCSCOptionScenario.java
index 969c1dd..887289d 100644
--- a/src/com/mostc/pftt/scenario/SMBCSCOptionScenario.java
+++ b/src/com/mostc/pftt/scenario/SMBCSCOptionScenario.java
@@ -5,6 +5,11 @@ import com.mostc.pftt.telemetry.ConsoleManager;
public abstract class SMBCSCOptionScenario extends AbstractOptionScenario {
+ @Override
+ public Class<?> getSerialKey() {
+ return SMBCSCOptionScenario.class;
+ }
+
public abstract boolean isEnable();
@Override
@@ -17,7 +22,7 @@ public abstract class SMBCSCOptionScenario extends
AbstractOptionScenario {
String ps_file = host.mktempname(getName(), "ps1");
try {
- host.saveFile(ps_file, ps_sb.toString());
+ host.saveTextFile(ps_file, ps_sb.toString());
if (host.exec("powershell -File "+ps_file,
Host.ONE_MINUTE).isSuccess()) {
host.delete(ps_file);
diff --git a/src/com/mostc/pftt/scenario/SMBDFSRScenario.java
b/src/com/mostc/pftt/scenario/SMBDFSRScenario.java
index 737571e..24e6f46 100644
--- a/src/com/mostc/pftt/scenario/SMBDFSRScenario.java
+++ b/src/com/mostc/pftt/scenario/SMBDFSRScenario.java
@@ -38,7 +38,7 @@ public class SMBDFSRScenario extends AbstractSMBScenario {
ps_sb.append("Add-WindowsFeature -name FS-DFS-Replication\n");
String tmp_file = host.mktempname(getName(), "ps1");
- host.saveFile(tmp_file, ps_sb.toString());
+ host.saveTextFile(tmp_file, ps_sb.toString());
if (host.exec("Powershell -File "+tmp_file,
Host.NO_TIMEOUT).isSuccess()) {
host.delete(tmp_file);
diff --git a/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
b/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
index 1d57030..8346af2 100644
--- a/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
+++ b/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
@@ -56,7 +56,7 @@ public class SMBDeduplicationScenario extends
AbstractSMBScenario {
if (!remote_host.isWin8OrLater()) {
cm.println(getName(), "Scenario can only be run against
a Windows 8/2012+ host");
return false;
- } else if
(remote_host.getSystemDrive().equalsIgnoreCase(volume)) {
+ } else if
(volume.equals("C:")||remote_host.getSystemDrive().equalsIgnoreCase(volume)) {
cm.println(getName(), "Can not use Deduplication on a
Windows System Drive (ex: C:\\)");
return false;
}
@@ -76,10 +76,10 @@ public class SMBDeduplicationScenario extends
AbstractSMBScenario {
// create PowerShell script to install and enable deduplication
try {
- remote_host.saveFile(tmp_file, ps_sb.toString());
+ remote_host.saveTextFile(tmp_file, ps_sb.toString());
//
- if (remote_host.exec("powershell -File "+tmp_file,
Host.ONE_MINUTE * 10).isSuccess()) {
+ if (remote_host.execElevated("powershell -File
"+tmp_file, Host.ONE_MINUTE * 10).isSuccess()) {
// don't delete tmp_file if it failed to help
user see why
remote_host.delete(tmp_file);
}
@@ -102,12 +102,15 @@ public class SMBDeduplicationScenario extends
AbstractSMBScenario {
public boolean notifyTestPackInstalled(ConsoleManager cm, Host host) {
try {
// run deduplication job (on test-pack) -wait for
completion
- remote_host.exec("powershell -Command {Start-Dedupjob
-Volume "+volume+" -Type Optimization -Wait}", Host.NO_TIMEOUT);
-
- return true;
+ cm.println(getName(), "Running deduplication job...");
+ if (remote_host.exec("powershell -Command
{Start-Dedupjob -Volume "+volume+" -Type Optimization -Wait}",
Host.NO_TIMEOUT).isSuccess()) {
+ cm.println(getName(), "Deduplication completed
successfully.");
+ return true;
+ }
} catch ( Exception ex ) {
cm.printStackTrace(ex);
}
+ cm.println(getName(), "Deduplication failed");
return false;
}
diff --git a/src/com/mostc/pftt/scenario/Scenario.java
b/src/com/mostc/pftt/scenario/Scenario.java
index 92c610e..47e30de 100644
--- a/src/com/mostc/pftt/scenario/Scenario.java
+++ b/src/com/mostc/pftt/scenario/Scenario.java
@@ -19,7 +19,10 @@ import com.mostc.pftt.telemetry.ConsoleManager;
public abstract class Scenario {
- public abstract boolean rejectOther(Scenario o);
+ public Class<?> getSerialKey() {
+ return getClass();
+ }
+
public abstract String getName();
public abstract boolean isImplemented();
@@ -38,59 +41,29 @@ public abstract class Scenario {
public static final AbstractFileSystemScenario
DEFAULT_FILESYSTEM_SCENARIO = LOCALFILESYSTEM_SCENARIO;
// 90 ScenarioSets => (APC, WinCache, No) * (CLI, Buitlin-WWW, Apache,
IIS-Standard, IIS-Express) * ( local filesystem, the 5 types of SMB )
- public static Scenario[][] getAllScenarios() {
- return new Scenario[][] {
+ public static Scenario[] getAllDefaultScenarios() {
+ return new Scenario[]{
// sockets
- new Scenario[] {
new PlainSocketScenario(),
- new SSLSocketScenario()
- },
+ new SSLSocketScenario(),
// code caches
- new Scenario[] {
new NoCodeCacheScenario(),
new APCScenario(),
- new WinCacheScenario()
- },
+ new WinCacheScenario(),
// SAPIs
- new Scenario[]{
- new CliScenario(),
- // TODO new BuiltinWebServerScenario(),
- /* TODO new ApacheModPHPScenario(),
+ CLI_SCENARIO,
+ new BuiltinWebServerScenario(),
+ // if Apache or IIS not installed, will skip
these scenarios
+ new ApacheModPHPScenario(),
new IISExpressFastCGIScenario(),
- new IISStandardFastCGIScenario() */
- },
+ new IISStandardFastCGIScenario(),
// filesystems
- new Scenario[] {
LOCALFILESYSTEM_SCENARIO,
-// new SMBBasicScenario(),
-// new SMBDeduplicationScenario(),
- /* XXX new SMBDFSScenario(),
- new SMBCAScenario(),
- // probably don't need to test branch cache,
but including it for completeness
- new SMBBranchCacheScenario()*/
- },
// options for smb - can be applied to any type
of smb
- new Scenario[] {
- // default is CSC enabled
- new CSCEnableScenario(),
- new CSCDisableScenario(),
- },
- // databases
- new Scenario[]{
- new MSAccessScenario(),
- new MSSQLODBCScenario(),
- new MSSQLScenario(),
- new MySQLScenario(),
- new PostgresSQLScenario(),
- new SQLite3Scenario(),
- // streams
- new FTPScenario(),
- new HTTPScenario(),
- // web services
- new SOAPScenario(),
- new XMLRPCScenario()
- }
+ // default is CSC enabled
+ new CSCEnableScenario(),
+ new CSCDisableScenario(),
};
- }
+ } // end public static Scenario[] getAllDefaultScenarios
} // end public abstract class Scenario
diff --git a/src/com/mostc/pftt/scenario/ScenarioSet.java
b/src/com/mostc/pftt/scenario/ScenarioSet.java
index 15e229d..0b5aa6c 100644
--- a/src/com/mostc/pftt/scenario/ScenarioSet.java
+++ b/src/com/mostc/pftt/scenario/ScenarioSet.java
@@ -2,6 +2,9 @@ package com.mostc.pftt.scenario;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
import com.mostc.pftt.host.Host;
@@ -34,7 +37,7 @@ import com.mostc.pftt.telemetry.ConsoleManager;
* Even so, being able to have fast test runs is critical. PHP builds
couldn't be tested across all that otherwise.
*
* @see #isSupported
- * @see ScenarioSet#getScenarioSets()
+ * @see ScenarioSet#getDefaultScenarioSets()
* @author Matt Ficken
*
*/
@@ -42,6 +45,59 @@ import com.mostc.pftt.telemetry.ConsoleManager;
@SuppressWarnings("serial")
public class ScenarioSet extends ArrayList<Scenario> {
+ private boolean sorted = false, sorting = false;
+ private static Comparator<Scenario> COMPARATOR = new
Comparator<Scenario>() {
+ @Override
+ public int compare(Scenario a, Scenario b) {
+ return
a.getSerialKey().getName().compareTo(b.getSerialKey().getName());
+ }
+ };
+ private synchronized void sort() {
+ if (sorting)
+ return;
+ sorting = true;
+ Collections.sort(this, COMPARATOR);
+ sorting = false;
+ sorted = true;
+ }
+
+ protected void forceSort() {
+ if (sorting)
+ return;
+ sort();
+ }
+
+ protected void ensureSorted() {
+ if (sorted)
+ return;
+ sort();
+ }
+
+ @Override
+ public String toString() {
+ ensureSorted();
+ return super.toString();
+ }
+
+ @Override
+ public boolean add(Scenario s) {
+ super.add(s);
+ forceSort();
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ ensureSorted();
+ return super.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ ensureSorted();
+ return super.hashCode();
+ }
+
/** finds the SAPI Scenario in the ScenarioSet or returns the default
SAPI scenario (CLI) in case the ScenarioSet doesn't specify one.
*
* @see AbstractSAPIScenario
@@ -86,59 +142,69 @@ public class ScenarioSet extends ArrayList<Scenario> {
return (ScenarioSet) super.clone();
}
- /** returns all possible valid ScenarioSets for all Scenarios
+
+ /** calculates all permutations/combinations of given Scenarios and
returns them as ScenarioSets
*
+ * @param scenarios
* @return
*/
- public static List<ScenarioSet> getScenarioSets() {
- return getScenarioSets(Scenario.getAllScenarios());
- }
-
- public static List<ScenarioSet> getScenarioSets(Scenario[][] scenarios)
{
- ArrayList<Scenario[]> s = new ArrayList<Scenario[]>(3);
- s.add(scenarios[0]);
- s.add(scenarios[1]);
- s.add(scenarios[2]);
- List<Scenario> b = Arrays.asList(scenarios[3]);
- ArrayList<ScenarioSet> sets = permute(s);
- for (ScenarioSet set:sets) {
- for (Scenario c: b) {
- if (c.isImplemented())
- set.add(c);
+ public static List<ScenarioSet> permuteScenarioSets(List<Scenario>
scenarios) {
+ HashMap<Class<?>,List<Scenario>> map = new
HashMap<Class<?>,List<Scenario>>();
+ for ( Scenario scenario : scenarios ) {
+ Class<?> clazz = scenario.getSerialKey();
+ //
+ List<Scenario> list = map.get(clazz);
+ if (list==null) {
+ list = new ArrayList<Scenario>(2);
+ map.put(clazz, list);
}
+ list.add(scenario);
}
- return sets.subList(0, 1);// TODO 2); // XXX
+ List<List<Scenario>> remap = new ArrayList<List<Scenario>>();
+ for ( List<Scenario> list : map.values() )
+ remap.add(list);
+ return permute(remap);
}
- protected static ArrayList<ScenarioSet> permute(List<Scenario[]> input)
{
+ protected static ArrayList<ScenarioSet> permute(List<List<Scenario>>
input) {
ArrayList<ScenarioSet> output = new ArrayList<ScenarioSet>();
- if (input.isEmpty()) {
- output.add(new ScenarioSet());
- return output;
- }
- List<Scenario[]> list = new ArrayList<Scenario[]>(input);
- Scenario[] head = list.get(0);
- List<Scenario[]> rest = list.subList(1, list.size());
- for (List<Scenario> permutations : permute(rest)) {
- List<ScenarioSet> subLists = new ArrayList<ScenarioSet>();
- for (int i = 0; i <= permutations.size(); i++) {
- for (int j=0 ; j < head.length; j++) {
- if (!head[j].isImplemented())
- continue; // skip it
- ScenarioSet subList = new ScenarioSet();
- subList.addAll(permutations);
- subList.add(i, head[j]);
- subLists.add(subList);
- }
- }
- output.addAll(subLists);
- }
- return output;
- }
+ if (input.isEmpty()) {
+ output.add(new ScenarioSet());
+ return output;
+ }
+ List<List<Scenario>> list = new
ArrayList<List<Scenario>>(input);
+ List<Scenario> head = list.get(0);
+ List<List<Scenario>> rest = list.subList(1, list.size());
+ for (List<Scenario> permutations : permute(rest)) {
+ List<ScenarioSet> subLists = new
ArrayList<ScenarioSet>();
+ for (int i = 0; i <= permutations.size(); i++) {
+ for (int j=0 ; j < head.size(); j++) {
+ if (!head.get(j).isImplemented())
+ continue; // skip it
+ ScenarioSet subList = new ScenarioSet();
+ subList.addAll(permutations);
+ subList.add(i, head.get(j));
+ if (!subList.contains(subList))
+ subLists.add(subList);
+ }
+ }
+ for ( ScenarioSet a : subLists ) {
+ if (!output.contains(a))
+ output.add(a);
+ }
+ }
+ return output;
+ } // end protected static ArrayList<ScenarioSet> permute
- public static List<ScenarioSet> toList(ScenarioSet set) {
- ArrayList<ScenarioSet> list = new ArrayList<ScenarioSet>(1);
- list.add(set);
- return list;
+ private static List<ScenarioSet> scenario_sets;
+ /** returns all builtin ScenarioSets (ScenarioSets that don't require
special configuration (ex: SMB scenarios require a remote SMB host))
+ *
+ * @return
+ */
+ public static List<ScenarioSet> getDefaultScenarioSets() {
+ return scenario_sets;
+ }
+ static {
+ scenario_sets =
permuteScenarioSets(Arrays.asList(Scenario.getAllDefaultScenarios()));
}
} // end public class ScenarioSet
diff --git a/src/com/mostc/pftt/telemetry/ConsoleManager.java
b/src/com/mostc/pftt/telemetry/ConsoleManager.java
index 56d736c..facd7c7 100644
--- a/src/com/mostc/pftt/telemetry/ConsoleManager.java
+++ b/src/com/mostc/pftt/telemetry/ConsoleManager.java
@@ -12,14 +12,15 @@ import com.mostc.pftt.ui.PhptDebuggerFrame;
import com.mostc.pftt.util.ErrorUtil;
public class ConsoleManager {
- protected final boolean results_only, show_gui, disable_debug_prompt;
+ protected final boolean results_only, show_gui, disable_debug_prompt,
dont_cleanup_test_pack, phpt_not_in_place;
protected PhptDebuggerFrame gui;
- public ConsoleManager(boolean results_only, boolean show_gui, boolean
disable_debug_prompt) {
+ public ConsoleManager(boolean results_only, boolean show_gui, boolean
disable_debug_prompt, boolean dont_cleanup_test_pack, boolean
phpt_not_in_place) {
this.results_only = results_only;
this.show_gui = show_gui;
this.disable_debug_prompt = disable_debug_prompt;
-
+ this.dont_cleanup_test_pack = dont_cleanup_test_pack;
+ this.phpt_not_in_place = phpt_not_in_place;
}
public void showGUI(PhptTestPackRunner test_pack_runner) {
@@ -76,5 +77,13 @@ public class ConsoleManager {
public boolean isResultsOnly() {
return results_only;
}
+
+ public boolean isDontCleanupTestPack() {
+ return dont_cleanup_test_pack;
+ }
+
+ public boolean isPhptNotInPlace() {
+ return phpt_not_in_place;
+ }
} // end public class ConsoleManager
diff --git a/src/com/mostc/pftt/telemetry/PhptTestResult.java
b/src/com/mostc/pftt/telemetry/PhptTestResult.java
index b869268..44613ab 100644
--- a/src/com/mostc/pftt/telemetry/PhptTestResult.java
+++ b/src/com/mostc/pftt/telemetry/PhptTestResult.java
@@ -63,8 +63,6 @@ public class PhptTestResult {
}
public PhptTestResult(Host host, EPhptTestStatus status, PhptTestCase
test_case, String actual, String[] actual_lines, String[] expected_lines,
Charset actual_cs, Map<String,String> env, String[] cmd_array, byte[]
stdin_data, String shell_script, Diff<String> diff, String expectf_output,
String preoverride_actual, String sapi_output) {
- actual = (""+actual_cs)+"\n"+actual; // TODO
-
this.sapi_output = sapi_output;
this.host = host;
diff --git a/src/com/mostc/pftt/ui/ExpectedActualDiffPHPTDisplay.java
b/src/com/mostc/pftt/ui/ExpectedActualDiffPHPTDisplay.java
index 438016d..9727337 100644
--- a/src/com/mostc/pftt/ui/ExpectedActualDiffPHPTDisplay.java
+++ b/src/com/mostc/pftt/ui/ExpectedActualDiffPHPTDisplay.java
@@ -11,11 +11,9 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
-import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
@@ -43,8 +41,6 @@ public class ExpectedActualDiffPHPTDisplay extends
JScrollPane {
protected TextDisplayPanel expected_display, diff_display,
actual_display, test_display;
protected DefaultTableModel env_table_model;
protected JTable env_table;
- protected DefaultListModel cmd_array_list_model;
- protected JList cmd_array_list;
protected JTextArea stdin_data_textarea, shell_script_textarea,
expectf_textarea, pre_override_textarea, sapi_output_textarea;
protected PhptTestResult test;
@@ -102,9 +98,6 @@ public class ExpectedActualDiffPHPTDisplay extends
JScrollPane {
prepared_panel.add(new JScrollPane(env_table = new
JTable(env_table_model = new DefaultTableModel())));
env_table_model.addColumn("Name");
env_table_model.addColumn("Value");
- prepared_panel.add(new JScrollPane(cmd_array_list = new
JList(cmd_array_list_model = new DefaultListModel())));
- vertical_panel.add(prepared_panel);
-
vertical_panel.add(test_display.text_area);
}
@@ -124,12 +117,6 @@ public class ExpectedActualDiffPHPTDisplay extends
JScrollPane {
env_table_model.addRow(new Object[]{name,
test.env.get(name)});
}
}
- cmd_array_list_model.clear();
- if (test.cmd_array!=null) {
- for (String cmd : test.cmd_array ) {
- cmd_array_list_model.addElement(cmd);
- }
- }
if (test.stdin_data!=null)
stdin_data_textarea.setText(new
String(test.stdin_data));
else
diff --git a/src/com/mostc/pftt/ui/PhptDebuggerFrame.java
b/src/com/mostc/pftt/ui/PhptDebuggerFrame.java
index a1d7e9b..b753d29 100644
--- a/src/com/mostc/pftt/ui/PhptDebuggerFrame.java
+++ b/src/com/mostc/pftt/ui/PhptDebuggerFrame.java
@@ -60,7 +60,7 @@ public class PhptDebuggerFrame extends JPanel {
jmb.add(new JMenu("Test:"));
jmb.add(scenario_menu = new JMenu("Scenarios"));
ButtonGroup scenario_bg = new ButtonGroup();
- for ( ScenarioSet set : ScenarioSet.getScenarioSets() ) {
+ for ( ScenarioSet set : ScenarioSet.getDefaultScenarioSets() )
{ // TODO
JRadioButtonMenuItem rb = new
JRadioButtonMenuItem(set.toString());
scenario_bg.add(rb);
scenario_menu.add(rb);
diff --git a/src/com/mostc/pftt/util/HostEnvUtil.java
b/src/com/mostc/pftt/util/HostEnvUtil.java
index 3350657..8fc695c 100644
--- a/src/com/mostc/pftt/util/HostEnvUtil.java
+++ b/src/com/mostc/pftt/util/HostEnvUtil.java
@@ -2,6 +2,7 @@ package com.mostc.pftt.util;
import com.mostc.pftt.host.ExecOutput;
import com.mostc.pftt.host.Host;
+import com.mostc.pftt.host.LocalHost;
import com.mostc.pftt.telemetry.ConsoleManager;
/** Utilities for setting up the test environment and convenience settings on
Hosts
@@ -54,20 +55,34 @@ public final class HostEnvUtil {
cm.println("HostEnvUtil", "disabling Windows
Firewall...");
// LATER edit firewall rules instead (what if on public
network, ex: Azure)
- host.execElevated("netsh firewall set opmode disable",
Host.ONE_MINUTE);
-
-
- cm.println("HostEnvUtil", "creating File Share for
"+host.getPhpSdkDir()+"...");
- // share PHP-SDK over network. this also will share C$, G$,
etc...
- host.execElevated("NET SHARE PHP_SDK="+host.getPhpSdkDir()+"
/Grant:"+host.getUsername()+",Full", Host.ONE_MINUTE);
+ host.execElevated("netsh firewall set opmode disable",
Host.ONE_MINUTE);
+
+
+ cm.println("HostEnvUtil", "creating File Share for
"+host.getPhpSdkDir()+"...");
+ // share PHP-SDK over network. this also will share C$,
G$, etc...
+ host.execElevated("NET SHARE
PHP_SDK="+host.getPhpSdkDir()+" /Grant:"+host.getUsername()+",Full",
Host.ONE_MINUTE);
}
-
-
- if (host.isVistaOrBefore()) {
+
+ if (host.isVistaOrBefore()) {
// install VC9 runtime (win7+ don't need this)
- // TODO
- }
- cm.println("HostEnvUtil", "Windows host prepared to run PHP.");
+ if
(host.dirContainsFragment(host.getSystemRoot()+"\\WinSxS", "vc9")) {
+ cm.println("HostEnvUtil", "VC9 Runtime alread
installed");
+ } else {
+ String local_file =
LocalHost.getLocalPfttDir()+"/bin/vc9_vcredist_x86.exe";
+ String remote_file = null;
+ if (host.isRemote()) {
+ remote_file =
host.mktempname("HostEnvUtil", ".exe");
+
+ cm.println("HostEnvUtil", "Uploading
VC9 Runtime");
+ host.upload(local_file, remote_file);
+ }
+ cm.println("HostEnvUtil", "Installing VC9
Runtime");
+ host.execElevated(remote_file+" /Q",
Host.NO_TIMEOUT);
+ if (remote_file!=null)
+ host.delete(remote_file);
+ }
+ }
+ cm.println("HostEnvUtil", "Windows host prepared to run PHP.");
} // end public static void prepareWindows
public static final String REG_DWORD = "REG_DWORD";