com pftt2: dfs, smb, deduplication scenarios (unstable): .gitignore bin/7z.exe doc/ssh_server.fatjar src/com/mostc/pftt/host/ ExecOutput.java
src/com/mostc/pftt/host/Host.java src/c om/mostc/pftt/host/LocalHost.java src/com/mostc/pftt/host/R emoteHost.java
src/com/mostc/pftt/host/RemotePhptTestPackRu nner.java src/com/mostc/pftt/host/SSHHost.java src/com/ mostc/pftt/main/PfttMain.java
src/com/mostc/pftt/model/perf ormance/DrupalPerformanceTest.java src
| From: | Matt Ficken | Date: | Sat, 26 Jan 2013 02:56:44 +0000 |
| Subject: | com pftt2: dfs, smb, deduplication scenarios (unstable): .gitignore bin/7z.exe doc/ssh_server.fatjar src/com/mostc/pftt/host/ ExecOutput.java src/com/mostc/pftt/host/Host.java src/c om/mostc/pftt/host/LocalHost.java src/com/mostc/pftt/host/R emoteHost.java src/com/mostc/pftt/host/RemotePhptTestPackRu nner.java src/com/mostc/pftt/host/SSHHost.java src/com/ mostc/pftt/main/PfttMain.java src/com/mostc/pftt/model/perf ormance/DrupalPerformanceTest.java src |
||
| Groups: | php.qa | ||
| Request: | Send a blank email to php-qa+get-67200@lists.php.net to get a copy of this message | ||
Commit: 9099829b86295609d5a52b123545f120e01d15e6
Author: Matt Ficken <v-mafick@microsoft.com> Fri, 25 Jan 2013 18:56:44 -0800
Parents: 3f4f4643d17c32346430d7d0259ba7be0fd4b4b3
Branches: master
Link: http://git.php.net/?p=pftt2.git;a=commitdiff;h=9099829b86295609d5a52b123545f120e01d15e6
Log:
dfs, smb, deduplication scenarios (unstable)
Changed paths:
M .gitignore
A bin/7z.exe
A doc/ssh_server.fatjar
M src/com/mostc/pftt/host/ExecOutput.java
M src/com/mostc/pftt/host/Host.java
M src/com/mostc/pftt/host/LocalHost.java
M src/com/mostc/pftt/host/RemoteHost.java
M src/com/mostc/pftt/host/RemotePhptTestPackRunner.java
M src/com/mostc/pftt/host/SSHHost.java
M src/com/mostc/pftt/main/PfttMain.java
D src/com/mostc/pftt/model/performance/DrupalPerformanceTest.java
D src/com/mostc/pftt/model/performance/HelloWorldPerformanceTest.java
D src/com/mostc/pftt/model/performance/JoomlaPerformanceTest.java
D src/com/mostc/pftt/model/performance/MediaWikiPerformanceTest.java
A src/com/mostc/pftt/model/performance/WCATDrupalTest.groovy
A src/com/mostc/pftt/model/performance/WCATHelloWorldTest.groovy
A src/com/mostc/pftt/model/performance/WCATJoomlaTest.groovy
A src/com/mostc/pftt/model/performance/WCATMediaWikiTest.groovy
A src/com/mostc/pftt/model/performance/WCATPerformanceTest..groovy
A src/com/mostc/pftt/model/performance/WCATWordpressTest.groovy
D src/com/mostc/pftt/model/performance/WordpressPerformanceTest.java
M src/com/mostc/pftt/model/phpt/PhpBuild.java
M src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java
A src/com/mostc/pftt/model/ui/SeleniumTest.groovy
M src/com/mostc/pftt/model/ui/wordpress.groovy
A src/com/mostc/pftt/report/ABCReportGen.groovy
D src/com/mostc/pftt/report/AUTReportGen.groovy
M src/com/mostc/pftt/report/FBCReportGen.groovy
A src/com/mostc/pftt/report/PBCReportGen.groovy
A src/com/mostc/pftt/report/UBCReportGen.groovy
M src/com/mostc/pftt/results/PhptResultPackWriter.java
M src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
M src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java
M src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java
A src/com/mostc/pftt/scenario/AbstractNetworkedServiceScenario.java
M src/com/mostc/pftt/scenario/AbstractSMBScenario.java
M src/com/mostc/pftt/scenario/AbstractStreamsScenario.java
A src/com/mostc/pftt/scenario/IMAPScenario.java
M src/com/mostc/pftt/scenario/LDAPScenario.java
M src/com/mostc/pftt/scenario/LocalFileSystemScenario.java
M src/com/mostc/pftt/scenario/SMBBasicScenario.java
M src/com/mostc/pftt/scenario/SMBCAScenario.java
D src/com/mostc/pftt/scenario/SMBDFSRScenario.java
A src/com/mostc/pftt/scenario/SMBDFSScenario.java
M src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
M src/com/mostc/pftt/scenario/SOAPScenario.java
M src/com/mostc/pftt/scenario/XMLRPCScenario.java
diff --git a/.gitignore b/.gitignore index fcb3025..2982736 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ build/* conf/internal/* src/com/sshtools/* +hostkeys.txt +ssh_server.jar diff --git a/bin/7z.exe b/bin/7z.exe new file mode 100644 index 0000000..101884c Binary files /dev/null and b/bin/7z.exe differ diff --git a/doc/ssh_server.fatjar b/doc/ssh_server.fatjar new file mode 100644 index 0000000..206137c --- /dev/null +++ b/doc/ssh_server.fatjar @@ -0,0 +1,14 @@ +#Fat Jar Configuration File +#Mon Jan 21 13:10:29 PST 2013 +onejar.license.required=true +manifest.classpath= +manifest.removesigners=true +onejar.checkbox=false +jarname=ssh_server.jar +manifest.mergeall=true +manifest.mainclass=com.mostc.pftt.main.SSHServer +manifest.file=<createnew> +jarname.isextern=false +onejar.expand= +excludes=<jar|htmlcleaner-2.2.jar>;<jar|groovy-1.8.6.jar>;<jar|icu4j-49_1.jar>;<jar|icudata.jar>;<jar|icutzdata.jar>;<jar|jansi-1.7.jar>;<jar|jline-0.9.94.jar>;<jar|selenium-server-standalone-2.19.0.jar>;<jar|xercesImpl.jar>;<jar|xmlpull-1.1.3.1.jar>;<jar|commons-cli-1.2.jar>;<jar|antlr-2.7.7.jar>;<jar|asm-3.2.jar>;<jar|asm-analysis-3.2.jar>;<jar|asm-commons-3.2.jar>;<jar|asm-util-3.2.jar> +includes= diff --git a/src/com/mostc/pftt/host/ExecOutput.java b/src/com/mostc/pftt/host/ExecOutput.java index e571454..64618e7 100644 --- a/src/com/mostc/pftt/host/ExecOutput.java +++ b/src/com/mostc/pftt/host/ExecOutput.java @@ -13,6 +13,7 @@ public class ExecOutput { public Charset charset; /** exit code for program. if 0, program exited successfully */ public int exit_code; + public String cmd; /** returns the output split into lines. * @@ -51,7 +52,7 @@ public class ExecOutput { if (ps!=null && isCrashed()) { String output_str = output.trim(); if (StringUtil.isEmpty(output_str)) - output_str = "<Crash with no output. exit_code="+exit_code+">"; + output_str = "<Crash with no output. exit_code="+exit_code+" cmd="+cmd+">"; ps.println(ctx+": "+output_str); } diff --git a/src/com/mostc/pftt/host/Host.java b/src/com/mostc/pftt/host/Host.java index b56b485..a5433fd 100644 --- a/src/com/mostc/pftt/host/Host.java +++ b/src/com/mostc/pftt/host/Host.java @@ -141,13 +141,28 @@ public abstract class Host { if (os_name!=null) return os_name; - os_name = getOSNameLong(); - - os_name.replaceAll("Windows", "Win"); + os_name = shortenOSName(getOSNameLong()); return os_name; } + public static String shortenOSName(String os_name) { + os_name = os_name.replace("Microsoft", ""); + os_name = os_name.replace("Server", ""); + os_name = os_name.replace("Datacenter", ""); + os_name = os_name.replace("Enterprise", ""); + os_name = os_name.replace("Standard", ""); + os_name = os_name.replace("Professional", ""); + os_name = os_name.replace("Home", ""); + os_name = os_name.replace("Basic", ""); + // + os_name = os_name.replace(" ", " "); + os_name = os_name.replace(" ", " "); + os_name = os_name.replace(" ", " "); + os_name = os_name.replace(" ", " "); + return os_name.trim(); + } + /** returns the OS name with whatever platform specific info in the platform specific format * * @see #getOSName @@ -319,13 +334,21 @@ public abstract class Host { * * This will improve performance for a few large files or a lots of small files. * + * @param cm + * @param ctx_str + * @param src_host * @param src * @param dst * @throws IllegalStateException * @throws IOException * @throws Exception */ - public abstract void downloadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception; + public abstract void downloadCompressWith7Zip(ConsoleManager cm, String ctx_str, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception; + + public void downloadCompressWith7Zip(ConsoleManager cm, Class<?> clazz, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception { + downloadCompressWith7Zip(cm, clazz.getSimpleName(), src_host, src, dst); + } + /** downloads file from remote source to local destination * * @param src @@ -339,13 +362,20 @@ public abstract class Host { * * This will improve performance for a few large files or a lots of small files. * + * @param cm + * @param ctx * @param src + * @param dst_host * @param dst * @throws IllegalStateException * @throws IOException * @throws Exception */ - public abstract void uploadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception; + public abstract void uploadCompressWith7Zip(ConsoleManager cm, String ctx_str, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception; + + public void uploadCompressWith7Zip(ConsoleManager cm, Class<?> ctx, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception { + uploadCompressWith7Zip(cm, ctx.getSimpleName(), src, dst_host, dst); + } /** Uploads file from local source to remote destination * * @param src @@ -656,32 +686,117 @@ public abstract class Host { return StringUtil.replaceAll(PAT_fs, "/", StringUtil.replaceAll(PAT_bs, "/", name)); } + public void upload7ZipAndDecompress(ConsoleManager cm, Class<?> clazz, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception { + upload7ZipAndDecompress(cm, clazz.getSimpleName(), src_host, src, dst); + } + + public void download7ZipAndDecompress(ConsoleManager cm, Class<?> clazz, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception { + download7ZipAndDecompress(cm, clazz.getSimpleName(), src, dst_host, dst); + } + /** uploads a 7zip file from local source to remote destination and decompresses it. * * Assumes local source is already a 7zip file, while #uploadCompressWith7Zip does the compression itself * + * @param cm + * @param ctx_str + * @param src_host * @param src * @param dst * @throws IllegalStateException * @throws IOException * @throws Exception */ - public void upload7ZipAndDecompress(String src, String dst) throws IllegalStateException, IOException, Exception { - // TODO + public void upload7ZipAndDecompress(ConsoleManager cm, String ctx_str, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, src_host); + + String dst_7zip_file = mktempname(ctx_str, ".7z"); + + upload(src, dst_7zip_file); + + decompress(cm, src_host, dst_7zip_file, dst); + + delete(dst_7zip_file); } /** Downloads remote 7Zip file to local destination and decompresses it. * * Assumes remote source is already a 7zip file. * + * @param cm + * @param ctx_str * @param src + * @param dst_host * @param dst * @throws IllegalStateException * @throws IOException * @throws Exception */ - public void download7ZipAndDecompress(String src, String dst) throws IllegalStateException, IOException, Exception { - // TODO + public void download7ZipAndDecompress(ConsoleManager cm, String ctx_str, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, dst_host); + + String dst_7zip_file = dst_host.mktempname(ctx_str, ".7z"); + + download(src, dst_7zip_file); + + dst_host.decompress(cm, this, dst_7zip_file, dst); + + dst_host.delete(dst_7zip_file); + } + + private boolean install_7zip_attempt; + protected void ensure7Zip(ConsoleManager cm, Host ohost) throws Exception { + if (install_7zip_attempt) + return; + install_7zip_attempt = true; + if (ohost.isRemote() == this.isRemote()) { + // no host with 7zip + cm.println(EPrintType.CLUE, getClass(), "No host found with a copy of 7z.exe!"); + } else if (ohost.isRemote()) { + install7Zip(cm, this, ohost); + } else { + install7Zip(cm, ohost, this); + } + } + + private static void install7Zip(ConsoleManager cm, Host src_host, Host dst_host) throws Exception { + final String dst_7z_path = dst_host.getPfttDir()+"\\bin\\7z.exe"; + + if (dst_host.exists(dst_7z_path)) { + cm.println(EPrintType.CLUE, "install7Zip", "7z.exe already installed on: "+dst_host); + return; + } + + final String src_7z_path = src_host.getPfttDir()+"\\bin\\7z.exe"; + if (!src_host.exists(src_7z_path)) { + cm.println(EPrintType.CLUE, "install7Zip", "7z.exe not found on source: "+src_host); + return; + } + + try { + dst_host.upload(src_7z_path, dst_7z_path); + + cm.println(EPrintType.CLUE, "install7Zip", "7z.exe installed on: "+dst_host+" (src="+src_host+")"); + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CLUE, "install7Zip", ex, "Unable to install 7z.exe on dst="+dst_host+" from src="+src_host); + + throw ex; + } + } // end private static void install7Zip + + public void decompress(ConsoleManager cm, Host ohost, String zip7_file, String dst) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, ohost); + + String base_dir = Host.basename(dst); + mkdirs(base_dir); + + exec(getPfttDir()+"\\bin\\7z x -bd -y "+zip7_file, Host.FOUR_HOURS, base_dir); + } + + public void compress(ConsoleManager cm, Host ohost, String src, String zip7_file) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, ohost); + + exec(getPfttDir()+"\\bin\\7z a -bd "+zip7_file+" "+src, Host.FOUR_HOURS, src); } /** gets a string of info about the host @@ -778,40 +893,39 @@ public abstract class Host { if (!isWindows()) return false; String os_name = getOSNameOnWindows(); - return os_name.contains("Windows Vista") || os_name.contains("Windows 2008 ") || os_name.contains("Windows 2008r2") || os_name.contains("Windows 7") || os_name.contains("Windows 8") || os_name.contains("Windows 2012"); + return os_name.contains("Windows Vista") || os_name.contains("Windows 2008") || os_name.contains("Windows 2008") || os_name.contains("Windows 7") || os_name.contains("Windows 8") || os_name.contains("Windows 2012") || os_name.contains("Windows 9"); } public boolean isBeforeVista() { if (!isWindows()) return false; String os_name = getOSNameOnWindows(); - return os_name.contains("Windows XP") || os_name.contains("Windows 2003 ") || os_name.contains("Windows 2000"); + return os_name.contains("Windows XP") || os_name.contains("Windows 2003") || os_name.contains("Windows 2000"); } public boolean isVistaOrBefore() { if (!isWindows()) return false; String os_name = getOSNameOnWindows(); - return os_name.contains("Windows Vista") || os_name.contains("Windows 2008 ") || os_name.contains("Windows 2003") || os_name.contains("Windows XP"); + return os_name.contains("Windows Vista") || os_name.contains("Windows 2008") || os_name.contains("Windows 2003") || os_name.contains("Windows XP"); } public boolean isVistaExact() { if (!isWindows()) return false; - String os_name = getOSNameOnWindows(); + String os_name = getOSName(); // technically Vista SP0 != 2008 RTM but Vista SP1 == 2008 RTM and Vista SP2 == 2008sp2 // thats why 2008 RTM is often referred to as 2008sp1 (1 service pack for 2008 after RTM, which is // 2008sp2, so there are 2 versions of Windows 2008, 2008sp1 and 2008sp2) - return os_name.contains("Windows Vista") || os_name.contains("Windows 2008 "); + return os_name.contains("Windows Vista") || os_name.contains("Windows 2008"); } public boolean isWin8Exact() { if (!isWindows()) return false; - String os_name = getOSNameOnWindows(); + String os_name = getOSName(); return os_name.contains("Windows 8") || os_name.contains("Windows 2012"); } public boolean isWin8OrLater() { if (!isWindows()) return false; - String os_name = getOSNameOnWindows(); - System.out.println(os_name); + String os_name = getOSName(); return os_name.contains("Windows 8") || os_name.contains("Windows 2012") || os_name.contains("Windows 9") || os_name.contains("Windows 2014"); } diff --git a/src/com/mostc/pftt/host/LocalHost.java b/src/com/mostc/pftt/host/LocalHost.java index cacccb0..a379df2 100644 --- a/src/com/mostc/pftt/host/LocalHost.java +++ b/src/com/mostc/pftt/host/LocalHost.java @@ -35,6 +35,7 @@ import com.github.mattficken.io.IOUtil; import com.github.mattficken.io.MultiCharsetByLineReader; import com.github.mattficken.io.NoCharsetByLineReader; import com.mostc.pftt.model.phpt.PhptTestCase; +import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.runner.AbstractTestPackRunner.TestPackRunnerThread; import com.mostc.pftt.util.StringUtil; import com.sun.jna.Pointer; @@ -186,6 +187,7 @@ public class LocalHost extends Host { task.cancel(); ExecOutput out = new ExecOutput(); + out.cmd = commandline; out.output = eh.getOutput(); out.charset = eh.charset; out.exit_code = eh.getExitCode(); @@ -636,7 +638,7 @@ public class LocalHost extends Host { } @Override - public void downloadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception { + public void downloadCompressWith7Zip(ConsoleManager cm, String ctx_str, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception { download(src, dst); } @@ -646,7 +648,7 @@ public class LocalHost extends Host { } @Override - public void uploadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception { + public void uploadCompressWith7Zip(ConsoleManager cm, String ctx_str, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception { upload(src, dst); } diff --git a/src/com/mostc/pftt/host/RemoteHost.java b/src/com/mostc/pftt/host/RemoteHost.java index 9613ce6..29d0aca 100644 --- a/src/com/mostc/pftt/host/RemoteHost.java +++ b/src/com/mostc/pftt/host/RemoteHost.java @@ -2,7 +2,7 @@ package com.mostc.pftt.host; import java.io.IOException; -import com.mostc.pftt.util.StringUtil; +import com.mostc.pftt.results.ConsoleManager; public abstract class RemoteHost extends Host { @@ -14,7 +14,7 @@ public abstract class RemoteHost extends Host { // look for line like: `OS Name: Windows 7 Ultimate` for ( String line : getSystemInfoLines() ) { if (line.startsWith("OS Name:")) { - return StringUtil.join(StringUtil.splitWhitespace(line), 1, " "); + return line.substring("OS Name:".length()).trim(); } } } catch ( Exception ex ) { @@ -36,15 +36,41 @@ public abstract class RemoteHost extends Host { } @Override - public void downloadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception { - // TODO Auto-generated method stub + public void downloadCompressWith7Zip(ConsoleManager cm, String ctx_str, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, src_host); + src_host.ensure7Zip(cm, this); + String src_zip7_file = src_host.mktempname(ctx_str, ".7z"); + + String dst_zip7_file = mktempname(ctx_str, ".7z"); + + src_host.compress(cm, this, src, src_zip7_file); + + upload(src_zip7_file, dst_zip7_file); + + decompress(cm, src_host, dst_zip7_file, dst); + + src_host.delete(src_zip7_file); + delete(dst_zip7_file); } @Override - public void uploadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception { - // TODO Auto-generated method stub + public void uploadCompressWith7Zip(ConsoleManager cm, String ctx_str, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, dst_host); + dst_host.ensure7Zip(cm, this); + + String src_zip7_file = mktempname(ctx_str, ".7z"); + + String dst_zip7_file = dst_host.mktempname(ctx_str, ".7z"); + + compress(cm, dst_host, src, src_zip7_file); + + download(src_zip7_file, dst_zip7_file); + + dst_host.decompress(cm, this, dst_zip7_file, dst); + dst_host.delete(dst_zip7_file); + delete(src_zip7_file); } } // end public abstract class RemoteHost diff --git a/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java b/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java index 3eb59fb..c1b3260 100644 --- a/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java +++ b/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java @@ -158,7 +158,7 @@ public class RemotePhptTestPackRunner extends PhptTestPackRunner { @Override public void runAllTests(PhptSourceTestPack test_pack) throws FileNotFoundException, IOException, Exception { - PhptActiveTestPack active_test_pack = test_pack.install(this.host, remote_host.getPhpSdkDir()+"/Remote"); + PhptActiveTestPack active_test_pack = test_pack.install(tmgr.getConsoleManager(), this.host, remote_host.getPhpSdkDir()+"/Remote"); commonRunStart(); sendTestPack(active_test_pack); diff --git a/src/com/mostc/pftt/host/SSHHost.java b/src/com/mostc/pftt/host/SSHHost.java index 04dd4bb..e4e1372 100644 --- a/src/com/mostc/pftt/host/SSHHost.java +++ b/src/com/mostc/pftt/host/SSHHost.java @@ -82,6 +82,8 @@ import com.sshtools.j2ssh.transport.publickey.SshPublicKey; * */ +// TODO 7zip compress test-pack and upload +// -don't include skip or xskip tests (save bandwidth/time) public class SSHHost extends RemoteHost { private static final Timer timer = new Timer(); protected String address, hostname; @@ -404,10 +406,10 @@ public class SSHHost extends RemoteHost { } // end protected static class SSHExecHandle @Override - public ExecOutput exec(String cmd, int timeout, Map<String, String> env, byte[] stdin_post, Charset charset, String chdir, final TestPackRunnerThread thread, int thread_slow_sec) throws Exception { - ByteArrayIOStream out = new ByteArrayIOStream(1024); + public ExecOutput exec(final String cmd, int timeout, Map<String, String> env, byte[] stdin_post, Charset charset, String chdir, final TestPackRunnerThread thread, int thread_slow_sec) throws Exception { + final ByteArrayIOStream out = new ByteArrayIOStream(1024); - ExecOutput eo = new ExecOutput(); + final ExecOutput eo = new ExecOutput(); // final AtomicBoolean run = new AtomicBoolean(true); @@ -457,6 +459,7 @@ public class SSHHost extends RemoteHost { session.getState().waitForState(ChannelState.CHANNEL_CLOSED); // + eo.cmd = cmd; eo.exit_code = session.getExitCode(); /* TODO if (reader instanceof AbstractDetectingCharsetReader) eo.charset = ((AbstractDetectingCharsetReader)reader).cs; */ diff --git a/src/com/mostc/pftt/main/PfttMain.java b/src/com/mostc/pftt/main/PfttMain.java index 94b8987..6ce019a 100644 --- a/src/com/mostc/pftt/main/PfttMain.java +++ b/src/com/mostc/pftt/main/PfttMain.java @@ -34,7 +34,7 @@ import com.mostc.pftt.model.smoke.ESmokeTestStatus; import com.mostc.pftt.model.smoke.PhptTestCountsMatchSmokeTest; import com.mostc.pftt.model.smoke.RequiredExtensionsSmokeTest; import com.mostc.pftt.model.smoke.RequiredFeaturesSmokeTest; -import com.mostc.pftt.report.AUTReportGen; +import com.mostc.pftt.report.ABCReportGen; import com.mostc.pftt.report.AbstractReportGen; import com.mostc.pftt.report.FBCReportGen; import com.mostc.pftt.results.ConsoleManager; @@ -46,10 +46,11 @@ import com.mostc.pftt.runner.PhpUnitTestPackRunner; import com.mostc.pftt.runner.LocalPhptTestPackRunner; import com.mostc.pftt.runner.PhptTestPackRunner; import com.mostc.pftt.scenario.AbstractSAPIScenario; -import com.mostc.pftt.scenario.SMBDFSRScenario; +import com.mostc.pftt.scenario.SMBDFSScenario; import com.mostc.pftt.scenario.SMBDeduplicationScenario; import com.mostc.pftt.scenario.Scenario; import com.mostc.pftt.scenario.ScenarioSet; +import com.mostc.pftt.scenario.AbstractSMBScenario.SMBStorageDir; import com.mostc.pftt.util.DownloadUtil; import com.mostc.pftt.util.HostEnvUtil; import com.mostc.pftt.util.StringUtil; @@ -66,6 +67,9 @@ import com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair; */ // TODO phpt_all, etc... should display location of result-pack being written +// XXX ? only compress .xml result files that are for FAIL or XFAIL_WORKS or CRASH or TEST_EXPCEPTION +// -then discard if PASS, SKIP or XSKIP +// -would still save list of tests for each status public class PfttMain { protected Host host; @@ -284,6 +288,7 @@ public class PfttMain { } protected static void cmd_aut(ConsoleManager cm, PfttMain rt, Host host, PhpBuild build, Collection<ScenarioSet> scenario_sets) throws IllegalStateException, IOException, Exception { + /* new PhpUnitTestPackRunner(PhpUnitAppTestPack.load("/"), scenario_sets.iterator().next(), build, host); host.upload7ZipAndDecompress(host.getPfttDir()+"/cache/cache.7z", ""); @@ -294,7 +299,8 @@ public class PfttMain { host.getContents(tmp_file); // for now, don't delete tmp_file - rt.show_report(cm, new AUTReportGen(new File(tmp_file), host.getOSName())); + rt.show_report(cm, new ABCReportGen(new File(tmp_file), host.getOSName())); + */ } protected static void cmd_shell_ui() { @@ -723,18 +729,15 @@ public class PfttMain { LocalConsoleManager cm = new LocalConsoleManager(source_pack, debug_pack, force, windebug, results_only, show_gui, disable_debug_prompt, dont_cleanup_test_pack, phpt_not_in_place, pftt_debug); - // TODO + // /* - SSHHost remote_host = new SSHHost("10.200.41.219", "administrator", "password01!"); + SSHHost remote_host = new SSHHost("10.200.48.119", "administrator", "password01!"); System.out.println(remote_host.isWindows()); - System.out.println("729"); - remote_host.exec("systeminfo", Host.ONE_MINUTE); - System.out.println("731"); //SMBDeduplicationScenario d = new SMBDeduplicationScenario(remote_host, "F:"); - SMBDFSRScenario d = new SMBDFSRScenario(remote_host); - System.out.println("731"); - System.out.println(d.notifyPrepareStorageDir(cm, rt.host)); - d.notifyTestPackInstalled(cm, rt.host); + SMBDFSScenario d = new SMBDFSScenario(remote_host); + SMBStorageDir dir = d.createStorageDir(cm, rt.host); + System.out.println(dir.getLocalPath(rt.host)); + System.out.println(dir.notifyTestPackInstalled(cm, rt.host)); System.exit(0); */ diff --git a/src/com/mostc/pftt/model/performance/DrupalPerformanceTest.java b/src/com/mostc/pftt/model/performance/DrupalPerformanceTest.java deleted file mode 100644 index 5920fd2..0000000 --- a/src/com/mostc/pftt/model/performance/DrupalPerformanceTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mostc.pftt.model.performance; - -public class DrupalPerformanceTest extends PerformanceTest { - - @Override - public String getName() { - return "Drupal-PerformanceTest"; - } - -} diff --git a/src/com/mostc/pftt/model/performance/HelloWorldPerformanceTest.java b/src/com/mostc/pftt/model/performance/HelloWorldPerformanceTest.java deleted file mode 100644 index 78f8d7a..0000000 --- a/src/com/mostc/pftt/model/performance/HelloWorldPerformanceTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mostc.pftt.model.performance; - -public class HelloWorldPerformanceTest extends PerformanceTest { - - @Override - public String getName() { - return "HelloWorld-PerformanceTest"; - } - -} diff --git a/src/com/mostc/pftt/model/performance/JoomlaPerformanceTest.java b/src/com/mostc/pftt/model/performance/JoomlaPerformanceTest.java deleted file mode 100644 index ce9e371..0000000 --- a/src/com/mostc/pftt/model/performance/JoomlaPerformanceTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mostc.pftt.model.performance; - -public class JoomlaPerformanceTest extends PerformanceTest { - - @Override - public String getName() { - return "Joomla-Performance"; - } - -} diff --git a/src/com/mostc/pftt/model/performance/MediaWikiPerformanceTest.java b/src/com/mostc/pftt/model/performance/MediaWikiPerformanceTest.java deleted file mode 100644 index 4679727..0000000 --- a/src/com/mostc/pftt/model/performance/MediaWikiPerformanceTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mostc.pftt.model.performance; - -public class MediaWikiPerformanceTest extends PerformanceTest { - - @Override - public String getName() { - return "MediaWiki-PerformanceTest"; - } - -} diff --git a/src/com/mostc/pftt/model/performance/WCATDrupalTest.groovy b/src/com/mostc/pftt/model/performance/WCATDrupalTest.groovy new file mode 100644 index 0000000..e05f198 --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATDrupalTest.groovy @@ -0,0 +1,193 @@ +package com.mostc.pftt.model.performance; + +/** WCAT based performance testing. + * + * Based on AutoCAT (Powershell) + * + * @see https://github.com/OSTC/php-perf + * + */ + +class WCATDrupalTest extends WCATPerformanceTest { + + @Override + public String getName() { + return "WCAT-Drupal"; + } + + @Override + String writeWCATSettings(String scenario_file, int virtual_clients) { +""" +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // clientfile = "test.wcat"; + // server = "131.107.145.189,131.107.145.190"; + // clients = 2; + // virtualclients = 4; + // bind = "131.107.145.189,w2k3-load16"; + // bind = "w2k3-load15,131.107.145.190"; + // + //-------------------------------------------------------------------------- + + virtualclients = $virtual_clients; + clientfile = "$scenario_file"; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} +""" + } // end String writeWCATSettings + + @Override + String writeWCATScenario() { +""" +scenario +{ + name = "Drupal"; + + warmup = 20; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + transaction + { + id = "Web Site Homepage"; + weight = 1; + + request + { + url = "/drupal/index.php"; + statuscode = 200; + //cookies = false; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = ka; + } + } +}""" + } // end String writeWCATScenario + +} // end class WCATDrupalTest diff --git a/src/com/mostc/pftt/model/performance/WCATHelloWorldTest.groovy b/src/com/mostc/pftt/model/performance/WCATHelloWorldTest.groovy new file mode 100644 index 0000000..74c7ad4 --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATHelloWorldTest.groovy @@ -0,0 +1,186 @@ +package com.mostc.pftt.model.performance; + +class WCATHelloWorldTest extends WCATPerformanceTest { + + @Override + public String getName() { + return "WCAT-HelloWorld"; + } + + @Override + String writeWCATScenario() { +""" +scenario +{ + name = "Helloworld"; + + warmup = 20; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + transaction + { + id = "Web Site Homepage"; + weight = 1; + + request + { + url = "/helloworld.php"; + statuscode = 200; + //cookies = false; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = ka; + } + } +} +""" + } // end String writeWCATScenario + + @Override + String writeWCATSettings(String scenario_file, int virtual_clients) { +""" +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // clientfile = "test.wcat"; + // server = "131.107.145.189,131.107.145.190"; + // clients = 2; + // virtualclients = 4; + // bind = "131.107.145.189,w2k3-load16"; + // bind = "w2k3-load15,131.107.145.190"; + // + //-------------------------------------------------------------------------- + + virtualclients = $virtual_clients; + clientfile = "$scenario_file"; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} +""" + } // end String writeWCATSettings + +} // end class WCATHelloWorldTest diff --git a/src/com/mostc/pftt/model/performance/WCATJoomlaTest.groovy b/src/com/mostc/pftt/model/performance/WCATJoomlaTest.groovy new file mode 100644 index 0000000..ee50bb7 --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATJoomlaTest.groovy @@ -0,0 +1,186 @@ +package com.mostc.pftt.model.performance; + +class WCATJoomlaTest extends WCATPerformanceTest { + + @Override + public String getName() { + return "WCAT-Joomla"; + } + + @Override + String writeWCATScenario() { +""" +scenario +{ + name = "Joomla"; + + warmup = 20; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + transaction + { + id = "Web Site Homepage"; + weight = 1; + + request + { + url = "/joomla/index.php"; + statuscode = 200; + //cookies = false; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = ka; + } + } +} +""" + } // end String writeWCATScenario + + @Override + String writeWCATSettings(String scenario_file, int virtual_clients) { +""" +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // clientfile = "test.wcat"; + // server = "131.107.145.189,131.107.145.190"; + // clients = 2; + // virtualclients = 4; + // bind = "131.107.145.189,w2k3-load16"; + // bind = "w2k3-load15,131.107.145.190"; + // + //-------------------------------------------------------------------------- + + virtualclients = $virtual_clients; + clientfile = "$scenario_file"; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} +""" + } // end String writeWCATSettings + +} // end class WCATJoomlaTest diff --git a/src/com/mostc/pftt/model/performance/WCATMediaWikiTest.groovy b/src/com/mostc/pftt/model/performance/WCATMediaWikiTest.groovy new file mode 100644 index 0000000..939e8d7 --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATMediaWikiTest.groovy @@ -0,0 +1,185 @@ +package com.mostc.pftt.model.performance; + +class WCATMediaWikiTest extends WCATPerformanceTest { + + @Override + public String getName() { + return "WCAT-MediaWiki"; + } + + @Override + String writeWCATScenario() { +""" +scenario +{ + name = "Mediawiki"; + + warmup = 20; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + transaction + { + id = "Web Site Homepage"; + weight = 1; + + request + { + url = "/mediawiki/index.php?title=Main_Page"; + statuscode = 200; + //cookies = false; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = ka; + } + } +} +""" + } // end String writeWCATScenario + + @Override + String writeWCATSettings(String scenario_file, int virtual_clients) { +""" +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // clientfile = "test.wcat"; + // server = "131.107.145.189,131.107.145.190"; + // clients = 2; + // virtualclients = 4; + // bind = "php-load01,php-load02"; + // + //-------------------------------------------------------------------------- + + virtualclients = $virtual_clients; + clientfile = "$scenario_file"; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} +""" + } // end String writeWCATSettings + +} // end class WCATMediaWikiTest diff --git a/src/com/mostc/pftt/model/performance/WCATPerformanceTest.groovy b/src/com/mostc/pftt/model/performance/WCATPerformanceTest.groovy new file mode 100644 index 0000000..e11602c --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATPerformanceTest.groovy @@ -0,0 +1,223 @@ +package com.mostc.pftt.model.performance; + +import com.mostc.pftt.host.Host; + +abstract class WCATPerformanceTest extends PerformanceTest { + + protected abstract String writeWCATSettings(String scenario_file, int virtual_clients); + protected abstract String writeWCATScenario(); + + String set_file, scenario_file + void runTest() { + + } + + void prepareWCAT(Host host) { + set_file = host.mktempname(getClass(), ".wcat"); + + scenario_file = host.mktempname(getClass(), ".wcat"); + + writeWCATScenario(); + + writeWCATSettings(scenario_file, 4); // TODO specify virtual clients (4, 8, 16, or 32) + + // TODO write strings to files + } + + void cleanupWCAT() { + + } + + void runWCAT(Host host) { +/* +// hostnames to run wcat clients on +// $CLIENTS = "php-load01,php-load02" +// $SETFILE = writeWCATSettings +// $OUT_FILE = temp file to write summary to +// hostname of target web server +// $SERVER = "php-web01" +// $_ +// + c:\wcat\wcat.wsf -terminate -run -v $_ -clients $CLIENTS -f $SETFILE -s $SERVER -o $OUT_FILE +*/ + } + + void readWCATSummary() { +/* +#%powershell1.0% +# +# File: summarize-results.ps1 +# Description: Summarize the results output by wcat_run.ps1 and output them into an HTML-formatted file. +# +# Example Usage: +# c:\> summarize-results.ps1 -PHP1 5.3.8 -PHP2 5.4.0B2 -VIRTUAL "8,16,32" +# + +Param($PHP1="", $PHP2="", $VIRTUAL="8,16,32") + +Set-Location c:\wcat +$results = 'c:/wcat/results/' +$errlog = "" +$VIRTUAL = $VIRTUAL.split(',') + +Function initvars { + $script:appnames = @("Helloworld", "Drupal", "Mediawiki", "Wordpress", "Joomla") + $script:data = @{} + + Foreach ($app in $appnames) { + $script:data.add($app, "") + $script:data[$app] = @{ "IIS" = + @{ "nocache" = + @{ "php1" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + }; + "php2" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + } + }; + "cache" = + @{ "php1" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + }; + "php2" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + } + } + }; + "Apache" = + @{ "nocache" = + @{ "php1" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + }; + "php2" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + } + }; + + "cachenoigbinary" = + @{ "php1" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + }; + "php2" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + } + }; + + "cachewithigbinary" = + @{ "php1" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + }; + "php2" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + } + } + } + } + } ## End Foreach +} ## End Function + + +## Initialize hash table +## $data[App_Name][Apache|IIS][cache|nocache|cachenoigbinary|cachewithigbinary][php1|php2][tps8|tps16|tps32] +initvars + +Get-ChildItem -recurse $results | Where-Object { $_.Name -match '\.dat' } | ForEach-Object { + + ## Determine web server, cache/nocache and application from file name + ## i.e. Apache-PHP5.4.0B2-Apache-Cache-Drupal.summary.dat + $dname = $_.Name.split("-") + $websvr = $dname[0] + $phpver = $dname[1] -ireplace "PHP", "" + $cache = $dname[3].tolower() + $appname = $dname[4] -ireplace "\.\w+", "" + + if ( $phpver -eq $PHP1 ) { $phpver = "php1" } + elseif ( $phpver -eq $PHP2 ) { $phpver = "php2" } + else { continue } + + $contents = (get-content $_.FullName) + Foreach ( $line in $contents ) { + if ( $line -match "\.xml" ) { + ## tps, kcpt, bpt, cpu, err + ## i.e. php-web01-Apache-2clnt-08vrtu-PHP5.4.0B2-Apache-Cache-Drupal.xml, 40.7, 0.0, 10670, 0.0, 0 + $line = $line.split(",") + $tps = $line[1].trim() + $err = $line[5].trim() + $virt = $line[0].split("-") + $virt = $virt[4] + $virt = $virt -ireplace "vrtu", "" + $virt = $virt -ireplace "^0", "" + + ## write-output "$appname $websvr $cache $phpver tps$virt" + $data[$appname][$websvr][$cache][$phpver]["tps$virt"] = $tps + $data[$appname][$websvr][$cache][$phpver]["err$virt"] = $err + if ( $err -gt 0 ) { + $logfile = "c:/wcat/autocat-log.txt" + $msg = (get-date -format "yyyy-MM-dd HH:mm:ss")+" $appname, $websvr, $cache, $dname[1]`: $err" + $msg | Out-File -Encoding ASCII -Append $logfile + $errlog += "$appname, $websvr, $cache, "+$dname[1]+": $err <br/>`n" + } + } + } +} + + +## Finally, output the results template +. ".\results-template.ps1" + + + + */ + } + +} diff --git a/src/com/mostc/pftt/model/performance/WCATWordpressTest.groovy b/src/com/mostc/pftt/model/performance/WCATWordpressTest.groovy new file mode 100644 index 0000000..ba86b41 --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATWordpressTest.groovy @@ -0,0 +1,186 @@ +package com.mostc.pftt.model.performance; + +class WCATWordpressTest extends WCATPerformanceTest { + + @Override + public String getName() { + return "WCAT-Wordpress"; + } + + @Override + String writeWCATScenario() { +""" +scenario +{ + name = "Wordpress"; + + warmup = 20; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + transaction + { + id = "Web Site Homepage"; + weight = 1; + + request + { + url = "/wordpress/"; + statuscode = 200; + //cookies = false; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = ka; + } + } +} +""" + } // end String writeWCATScenario + + @Override + String writeWCATSettings(String scenario_file, int virtual_clients) { +""" +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // clientfile = "test.wcat"; + // server = "131.107.145.189,131.107.145.190"; + // clients = 2; + // virtualclients = 4; + // bind = "131.107.145.189,w2k3-load16"; + // bind = "w2k3-load15,131.107.145.190"; + // + //-------------------------------------------------------------------------- + + virtualclients = $virtual_clients; + clientfile = "$scenario_file"; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} +""" + } // end String writeWCATSettings + +} // end class WCATWordpressTest diff --git a/src/com/mostc/pftt/model/performance/WordpressPerformanceTest.java b/src/com/mostc/pftt/model/performance/WordpressPerformanceTest.java deleted file mode 100644 index 14cadde..0000000 --- a/src/com/mostc/pftt/model/performance/WordpressPerformanceTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mostc.pftt.model.performance; - -public class WordpressPerformanceTest extends PerformanceTest { - - @Override - public String getName() { - return "Wordpress-PerformanceTest"; - } - -} diff --git a/src/com/mostc/pftt/model/phpt/PhpBuild.java b/src/com/mostc/pftt/model/phpt/PhpBuild.java index 74c731d..da6d686 100644 --- a/src/com/mostc/pftt/model/phpt/PhpBuild.java +++ b/src/com/mostc/pftt/model/phpt/PhpBuild.java @@ -1,5 +1,6 @@ package com.mostc.pftt.model.phpt; +import java.io.FileWriter; import java.io.IOException; import java.io.PrintStream; import java.lang.ref.WeakReference; @@ -705,5 +706,29 @@ public class PhpBuild extends SAPIManager { public String getDefaultExtensionDir() { return build_path.contains("/") ? build_path+"/ext" : build_path+"\\ext"; } + + boolean saved_ini = false; + String ini_dir; + public String prepare(Host host) throws IOException { + if (saved_ini) { + return ini_dir; + } else { + // @see CliScenario#createIniForTest + saved_ini = true; + + ini_dir = host.mktempname(getClass()); + host.mkdirs(ini_dir); + + String ini_file = ini_dir + "/php.ini"; + + PhpIni def_ini = RequiredExtensionsSmokeTest.createDefaultIniCopy(host, this); + + FileWriter fw = new FileWriter(ini_file); + fw.write(def_ini.toString()); + fw.close(); + + return ini_dir; + } + } } // end public class PhpBuild diff --git a/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java b/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java index 9f6309f..0cb7b50 100644 --- a/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java +++ b/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java @@ -244,6 +244,7 @@ public class PhptSourceTestPack extends SourceTestPack { * location can be local or remote. * * @see #read - must have already been called + * @param cm * @param host * @param test_pack_dir * @return @@ -251,23 +252,35 @@ public class PhptSourceTestPack extends SourceTestPack { * @throws IOException * @throws Exception */ - public PhptActiveTestPack install(Host host, String test_pack_dir) throws IllegalStateException, IOException, Exception { + public PhptActiveTestPack install(ConsoleManager cm, Host host, String test_pack_dir) throws IllegalStateException, IOException, Exception { if (!this.host.isRemote() || this.host.equals(host)) { // installing from local host to remote host OR from remote host to itself - host.upload(test_pack, test_pack_dir); + host.uploadCompressWith7Zip(cm, getClass(), test_pack, host, test_pack_dir); } else if (!host.isRemote()) { // installing from remote host to local host - host.download(test_pack, test_pack_dir); + host.download7ZipAndDecompress(cm, getClass(), test_pack, this.host, test_pack_dir); } else { - // installing from 1 remote host to a different remote host + // installing from 1 remote host(src) to a different remote host (dst) LocalHost local_host = new LocalHost(); - String local_dir = local_host.mktempname(getClass()); - this.host.download(test_pack, local_dir); - host.upload(local_dir, test_pack_dir); - local_host.delete(local_dir); + + // decide file names + String local_7zip_file = local_host.mktempname(getClass(), ".7z"); + String src_7zip_file = this.host.mktempname(getClass(), ".7z"); + String dst_7zip_file = host.mktempname(getClass(), ".7z"); + + // compress and download/upload and decompress + this.host.compress(cm, host, test_pack, src_7zip_file); + this.host.download(src_7zip_file, local_7zip_file); + host.upload(local_7zip_file, dst_7zip_file); + host.decompress(cm, this.host, dst_7zip_file, test_pack_dir); + + // cleanup + this.host.delete(dst_7zip_file); + host.delete(src_7zip_file); + local_host.delete(local_7zip_file); } return new PhptActiveTestPack(test_pack_dir); - } + } // end public PhptActiveTestPack install /** installs only the named test cases from test pack into to the given location to actively run it from. * diff --git a/src/com/mostc/pftt/model/ui/SeleniumTest.groovy b/src/com/mostc/pftt/model/ui/SeleniumTest.groovy new file mode 100644 index 0000000..8877e64 --- /dev/null +++ b/src/com/mostc/pftt/model/ui/SeleniumTest.groovy @@ -0,0 +1,5 @@ + +abstract class SeleniumTest { + + +} diff --git a/src/com/mostc/pftt/model/ui/wordpress.groovy b/src/com/mostc/pftt/model/ui/wordpress.groovy index f65e6a6..6523584 100644 --- a/src/com/mostc/pftt/model/ui/wordpress.groovy +++ b/src/com/mostc/pftt/model/ui/wordpress.groovy @@ -1,120 +1,108 @@ package com.mostc.pftt.model.ui; -import com.mostc.pftt.scenario.app.WordpressScenario - -// auto import UITestCase -// cr or case_runner - -// host - -// build - -// middleware - -// host_int - - -install_ctx = cr.install(new WordpressScenario()) - /* -def user_anon_test(prefix='') { - cr.run(new UITestCase("$prefix-View-Content") { - def act() { - - } - }) - - cr.run(new UITestCase("$prefix-Create-Story") { - def act() { - - } - }) +class WordpressTestPack { - cr.run(new UITestCase("$prefix-Post-Comments") { - def act() { - - } - }) -} // end def user_anon_test - -def user_tests(user_info=null, prefix='', suffix='', xfail=false) { - // login new user - if (user_info) { - user_login(user_info, prefix, suffix, xfail) - - // test as new user - user_anon_test(prefix) - - // change settings - cr.run(new UITestCase("$prefix-View-Settings-$suffix")) { + def user_anon_test(prefix='') { + cr.run(new UITestCase("$prefix-View-Content") { + def act() { + + } + }) + + cr.run(new UITestCase("$prefix-Create-Story") { def act() { } - }, xfail) + }) - cr.run(new UITestCase("$prefix-Change-Settings-$suffix")) { + cr.run(new UITestCase("$prefix-Post-Comments") { def act() { } - }, xfail) + }) + } // end def user_anon_test - user_logout(user_info, prefix, xfail) - } else { - // report that these cases can't be tested b/c user wasn't created - cr.bork("$prefix-Login-$suffix") - cr.bork("$prefix-View-Settings-$suffix") - cr.bork("$prefix-Change-Settings-$suffix") - cr.bork("$prefix-Logout-$suffix") - } -} // end def user_tests - -def register_user(suffix='1', xfail=false) { - // TODO -} - -def admin_login(suffix='1', xfail=false, given_password=null) { - // login as administrator - user_login({username = install_ctx.admin_user; password = given_password==null?install_ctx.admin_password:given_password}, 'Admin', suffix, xfail) -} - -def admin_logout(suffix='1') { - // logout administrator - user_logout('Admin', suffix) -} - -def delete_user(user_info, suffix='1') { - // TODO -} - -def user_login(user_info, prefix='', suffix='', xfail=false) { - cr.run(new UITestCase("$prefix-Login-$suffix") { - def act() { - go_home().find_link('Login', 'Signin').click().fill('User', user_info.username).fill('Password', user_info.password).submit() - } - }, xfail); -} - -def user_logout(prefix='', suffix='', xfail=false) { - // logout - cr.run(new UITestCase("$prefix-Logout-$suffix") { - def act() { - // unless go_url() or go_home() called, starts with page left by previous UITestCase - find_link('Logout').click() + def user_tests(user_info=null, prefix='', suffix='', xfail=false) { + // login new user + if (user_info) { + user_login(user_info, prefix, suffix, xfail) + + // test as new user + user_anon_test(prefix) + + // change settings + cr.run(new UITestCase("$prefix-View-Settings-$suffix")) { + def act() { + + } + }, xfail) + + cr.run(new UITestCase("$prefix-Change-Settings-$suffix")) { + def act() { + + } + }, xfail) + + user_logout(user_info, prefix, xfail) + } else { + // report that these cases can't be tested b/c user wasn't created + cr.bork("$prefix-Login-$suffix") + cr.bork("$prefix-View-Settings-$suffix") + cr.bork("$prefix-Change-Settings-$suffix") + cr.bork("$prefix-Logout-$suffix") } - }, xfail); -} - -def xfail_tests(suffix='') { - admin_login(suffix, xfail=true, given_password='wrong_password') + } // end def user_tests - admin_login(suffix) + def register_user(suffix='1', xfail=false) { + // TODO + } - change_password(created_user) - change_password(registered_user) + def admin_login(suffix='1', xfail=false, given_password=null) { + // login as administrator + user_login({username = install_ctx.admin_user; password = given_password==null?install_ctx.admin_password:given_password}, 'Admin', suffix, xfail) + } - admin_logout(suffix) + def admin_logout(suffix='1') { + // logout administrator + user_logout('Admin', suffix) + } - user_login(created_user, xfail=true) - user_login(registered_user, xfail=true) -} - -///////// FIRST TEST CASE HERE //////////// - + def delete_user(user_info, suffix='1') { + // TODO + } + + def user_login(user_info, prefix='', suffix='', xfail=false) { + cr.run(new UITestCase("$prefix-Login-$suffix") { + def act() { + go_home().find_link('Login', 'Signin').click().fill('User', user_info.username).fill('Password', user_info.password).submit() + } + }, xfail); + } + + def user_logout(prefix='', suffix='', xfail=false) { + // logout + cr.run(new UITestCase("$prefix-Logout-$suffix") { + def act() { + // unless go_url() or go_home() called, starts with page left by previous UITestCase + find_link('Logout').click() + } + }, xfail); + } + + def xfail_tests(suffix='') { + admin_login(suffix, xfail=true, given_password='wrong_password') + + admin_login(suffix) + + change_password(created_user) + change_password(registered_user) + + admin_logout(suffix) + + user_login(created_user, xfail=true) + user_login(registered_user, xfail=true) + } // test anonymously user_anon_test('Anonymous') @@ -191,4 +179,7 @@ admin_logout('All-Plugins-2') user_login(created_user, 'All-Plugins', 'Old-Password', xfail=true) user_login(registered_user, 'All-Plugins', 'Old-Password', xfail=true) -*/ + + +} +*/ \ No newline at end of file diff --git a/src/com/mostc/pftt/report/ABCReportGen.groovy b/src/com/mostc/pftt/report/ABCReportGen.groovy new file mode 100644 index 0000000..db7ba55 --- /dev/null +++ b/src/com/mostc/pftt/report/ABCReportGen.groovy @@ -0,0 +1,197 @@ +package com.mostc.pftt.report + +class ABCReportGen extends AbstractReportGen { + final String os_name; + final File tmp_file; + + public ABCReportGen(File tmp_file, String os_name) { + this.tmp_file = tmp_file; + this.os_name = os_name; + } + + @Override + void run() { + + def oses = [os_name] + + def root = new XmlSlurper().parse(tmp_file); + def testcases = root.depthFirst().findAll { it.name() == 'testcase' } + + def sw = new StringWriter() + def html = new groovy.xml.MarkupBuilder(sw) + html.html { + body { + p { + span(style: 'font-size:14.0pt;line-height:115%') { + span("AUT Report") + b("Joomla Platform") + } + } + + p { + b("Joomla Platform") + span(" PHPUnit Test-Pack comparing ") + b("PHP_5_4-r328a3d9") + span(" with ") + b("PHP_5_4-r8cdd6bc") + span(" (using ") + b("Joomla Platform") + span(" PHPUnit Test-Pack from ") + b("Joomla_Platform-12.1") + span(")") + } + + p { + span(style: 'font-size:14.0pt;line-height:115%', 'Summary') + } + + table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { + tr() { + td(valign:'top', style: 'width:1.45in;border:solid windowtext 1.0pt; background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "OS" + ) + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Tests" + ) + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Failures" + ) + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Errors" + ) + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Success Rate" + ) + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Time" + ) + } + + oses.each{ os_name -> + tr(style: 'height:26.05pt') { + td(valign: 'top', style: 'width:1.45in;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt;height:26.05pt', + os_name + ) + td(valign: "top", style: 'width:49.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + testcases.size() + ) + td(valign: 'top', style: 'width:27.0pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "+0" + ) + td(valign: 'top', style: 'width:.75in;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "34" + ) + td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "+0" + ) + td(valign: 'top', style: 'width:45.0pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "158" + ) + td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "+0" + ) + td(valign: 'top', style: 'width:76.5pt;border-top:none;border-left: none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "92%" + ) + td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "+0" + ) + td(valign: 'top', style: 'width:45.9pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "0:08:00" + ) + } + } + } // end table + + p { + span(style: 'font-size:14.0pt;line-height:115%', + "New Failures and Errors" + ) + } + + table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { + oses.each { os_name -> + tr() { + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt', + os_name + ) + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { + testcases.each { + if ( it.getAt("failure").size() > 0 || it.getAt("error").size() > 0 ) { + def test_name = it['@name'] + + p(test_name) + + } + } + } + } + } + } // end table + + p { + span(style: 'font-size:14.0pt;line-height:115%', + "List of Failing and Error Test Cases" + ) + } + + table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { + tr() { + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') + td(valign: 'top', style: 'width:153.0pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Base" + ) + td(valign: 'top', style: 'width:2.95in;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Test" + ) + } + + + + + oses.each { os_name -> + tr() { + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt', + os_name + ) + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { + testcases.each { + if ( it.getAt("failure").size() > 0 || it.getAt("error").size() > 0 ) { + def test_name = it['@name'] + + p(test_name) + } + } + } + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { + testcases.each { + if ( ( it['failure'] || it['error'] ) && it.text() != null && it.text().length() > 0 ) { + def test_name = it['@name'] + + p(test_name) + } + } + } + } + } + } // end table + + } // end body + } // end html + + def f = new File("index.html") + f.write(sw.toString()) + + + } // end void run + + @Override + public String getHTMLString() { + return sw.toString(); + } + +} // end class AUTReportGen diff --git a/src/com/mostc/pftt/report/AUTReportGen.groovy b/src/com/mostc/pftt/report/AUTReportGen.groovy deleted file mode 100644 index f5a1a41..0000000 --- a/src/com/mostc/pftt/report/AUTReportGen.groovy +++ /dev/null @@ -1,197 +0,0 @@ -package com.mostc.pftt.report - -class AUTReportGen extends AbstractReportGen { - final String os_name; - final File tmp_file; - - public AUTReportGen(File tmp_file, String os_name) { - this.tmp_file = tmp_file; - this.os_name = os_name; - } - - @Override - void run() { - - def oses = [os_name] - - def root = new XmlSlurper().parse(tmp_file); - def testcases = root.depthFirst().findAll { it.name() == 'testcase' } - - def sw = new StringWriter() - def html = new groovy.xml.MarkupBuilder(sw) - html.html { - body { - p { - span(style: 'font-size:14.0pt;line-height:115%') { - span("AUT Report") - b("Joomla Platform") - } - } - - p { - b("Joomla Platform") - span(" PHPUnit Test-Pack comparing ") - b("PHP_5_4-r328a3d9") - span(" with ") - b("PHP_5_4-r8cdd6bc") - span(" (using ") - b("Joomla Platform") - span(" PHPUnit Test-Pack from ") - b("Joomla_Platform-12.1") - span(")") - } - - p { - span(style: 'font-size:14.0pt;line-height:115%', 'Summary') - } - - table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { - tr() { - td(valign:'top', style: 'width:1.45in;border:solid windowtext 1.0pt; background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "OS" - ) - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Tests" - ) - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Failures" - ) - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Errors" - ) - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Success Rate" - ) - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Time" - ) - } - - oses.each{ os_name -> - tr(style: 'height:26.05pt') { - td(valign: 'top', style: 'width:1.45in;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt;height:26.05pt', - os_name - ) - td(valign: "top", style: 'width:49.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - testcases.size() - ) - td(valign: 'top', style: 'width:27.0pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "+0" - ) - td(valign: 'top', style: 'width:.75in;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "34" - ) - td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "+0" - ) - td(valign: 'top', style: 'width:45.0pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "158" - ) - td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "+0" - ) - td(valign: 'top', style: 'width:76.5pt;border-top:none;border-left: none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "92%" - ) - td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "+0" - ) - td(valign: 'top', style: 'width:45.9pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "0:08:00" - ) - } - } - } // end table - - p { - span(style: 'font-size:14.0pt;line-height:115%', - "New Failures and Errors" - ) - } - - table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { - oses.each { os_name -> - tr() { - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt', - os_name - ) - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { - testcases.each { - if ( it.getAt("failure").size() > 0 || it.getAt("error").size() > 0 ) { - def test_name = it['@name'] - - p(test_name) - - } - } - } - } - } - } // end table - - p { - span(style: 'font-size:14.0pt;line-height:115%', - "List of Failing and Error Test Cases" - ) - } - - table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { - tr() { - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') - td(valign: 'top', style: 'width:153.0pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Base" - ) - td(valign: 'top', style: 'width:2.95in;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Test" - ) - } - - - - - oses.each { os_name -> - tr() { - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt', - os_name - ) - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { - testcases.each { - if ( it.getAt("failure").size() > 0 || it.getAt("error").size() > 0 ) { - def test_name = it['@name'] - - p(test_name) - } - } - } - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { - testcases.each { - if ( ( it['failure'] || it['error'] ) && it.text() != null && it.text().length() > 0 ) { - def test_name = it['@name'] - - p(test_name) - } - } - } - } - } - } // end table - - } // end body - } // end html - - def f = new File("index.html") - f.write(sw.toString()) - - - } // end void run - - @Override - public String getHTMLString() { - return sw.toString(); - } - -} // end class AUTReportGen diff --git a/src/com/mostc/pftt/report/FBCReportGen.groovy b/src/com/mostc/pftt/report/FBCReportGen.groovy index 071c0f3..43c60db 100644 --- a/src/com/mostc/pftt/report/FBCReportGen.groovy +++ b/src/com/mostc/pftt/report/FBCReportGen.groovy @@ -214,7 +214,7 @@ html.html { td(colspan:2, 'Crashes (Test)') } /* --------------- end headers -------------- */ - /*tr { + tr { td(row++) td(test_telem.getOSName()) td() { @@ -227,7 +227,7 @@ html.html { br(test_name) } } - }*/ + } } // table // new PHPT failures diff --git a/src/com/mostc/pftt/report/PBCReportGen.groovy b/src/com/mostc/pftt/report/PBCReportGen.groovy new file mode 100644 index 0000000..ebab7ed --- /dev/null +++ b/src/com/mostc/pftt/report/PBCReportGen.groovy @@ -0,0 +1,230 @@ +/* +#%powershell1.0% +# +# File: results-template.ps1 +# Description: Output $data into html table. This script is meant to be called from summarize-results.ps1. +# + +Function gaincalc ( $a=0, $b=0 ) { + if ( ($a -ne 0) -and ($b -ne 0) ) { + $c = ($a / $b) - 1 + + switch ($c*100) { + {$_ -ge 0 -and $_ -le 3} {$script:gainclass="none"} + {$_ -gt 3 -and $_ -le 7} {$script:gainclass="gainpossmall"} + {$_ -ge 0 -and $_ -gt 7} {$script:gainclass="gainpos"} + {$_ -lt 0 -and $_ -ge -3} {$script:gainclass="none"} + {$_ -lt -3 -and $_ -ge -7} {$script:gainclass="gainnegsmall"} + {$_ -lt 0 -and $_ -lt -7} {$script:gainclass="gainneg"} + Default { $script:gainclass="none" } + } + + "{0:P2}" -f $c + } + else { + $script:gainclass="none" + } +} + + +write-output " + +<html> +<head> + <style type=text/css> + .data td { border:1px solid black; } + .iis { background-color:#E6B8B7; } + .iiswincache { background-color: #DA9694; } + .apache { background-color: #C5D9F1; } + .apachenoigbinary { background-color: #8DB4E2; } + .apachewithigbinary { background-color: #538DD5; } + .gainpos { background-color: #00A84C; } + .gainpossmall { background-color: #00D661; } + .gainneg { background-color: #FF2929; } + .gainnegsmall { background-color: #DA9694; } + </style> + </head> + +<body> +<table border=0 cellpadding=0 cellspacing=0 width=600> +<tr> +<td> <strong> PHP Performance </strong> </td> +<td> <strong> Hardware & Environment </strong> </td> +</tr><tr> +<td>$PHP1 - $PHP2</td> +<td>Dell R710</td> +</tr><tr> +<td> </td> +<td>CPU - Intel Quad core @ 2.26Ghz (x2) L5520</td> +</tr><tr> +<td> </td> +<td>Memory - 12GB RAM</td> +</tr><tr> +<td> </td> +<td>HD - 147GB SAS RAID 1</td> +</tr><tr> +<td> </td> +<td>NIC - 1Gbps Intel</td> +</tr><tr> +<td> </td> +<td>Windows 2008 R2 - SP1</td> +</tr><tr> +<td> </td> +<td>php-web01.ctac.nttest.microsoft.com</td> +</tr> +<table> +<p> </p> + +<table border=0 cellpadding=0 cellspacing=0 width=1628 class=data> + +<!-- Header Labels --> + <tr> + <td colspan=4></td> + <td colspan=6 class=iis>IIS 7.5</td> + <td colspan=9 class=apache>Apache 2.2</td> + </tr> + + <tr> + <td colspan=4></td> + <td colspan=3 rowspan=2 class=iis>No Cache</td> + <td colspan=3 rowspan=2 class=iiswincache>WinCache</td> + <td colspan=3 rowspan=2 class=apache>No Cache</td> + <td colspan=6 class=apachenoigbinary>APC</td> + </tr> + <tr> + <td></td> + <td colspan=3>Load Agents</td> + <td colspan=3 class=apachenoigbinary>-igbinary</td> + <td colspan=3 class=apachewithigbinary>+igbinary</td> + </tr> + <!-- Header Labels --> + + <tr> + <td>Application</td> + <td>Physical</td> + <td>Virtual</td> + <td></td> + +<!-- IIS No Cache --> + + <td>$PHP1</td> + <td>$PHP2</td> + <td>gain</td> + +<!-- IIS Cache --> + <td>$PHP1</td> + <td>$PHP2</td> + <td>gain</td> + +<!-- Apache No Cache --> + <td>$PHP1</td> + <td>$PHP2</td> + <td>gain</td> + +<!-- Apache Cache -igbinary --> + <td>$PHP1</td> + <td>$PHP2</td> + <td>gain</td> + +<!-- Apache Cache +igbinary --> + <td>$PHP1</td> + <td>$PHP2</td> + <td>gain</td> + </tr> + +<!-- Results --> +" + +Foreach ( $app in $appnames ) { + ## Notes: $data[App_Name][Apache|IIS][cache|nocache|cachenoigbinary|cachewithigbinary][php1|php2][ver|tps8|tps16|tps32] + + write-output " + <tr> + <td rowspan=3>$app</td> + " + + Foreach ( $virt in $VIRTUAL ) { + $gain = "" + $gainclass = "" + if ( $virt -ne "8" ) { + write-output "<tr>" + } + + write-output " + <td>2</td> + <td>$virt</td> + <td> </td> + + <!-- IIS - No Cache --> + <td class=iis>" $data[$app]["IIS"]["nocache"]["php1"]["tps$virt"] "</td> + <td class=iis>" $data[$app]["IIS"]["nocache"]["php2"]["tps$virt"] "</td>" + + $gain = gaincalc $data[$app]["IIS"]["nocache"]["php2"]["tps$virt"] $data[$app]["IIS"]["nocache"]["php1"]["tps$virt"] + write-output " + + <td class=$gainclass> $gain + </td> <!-- Gain --> + + <!-- IIS - Cache --> + <td class=iiswincache>" $data[$app]["IIS"]["cache"]["php1"]["tps$virt"] "</td> + <td class=iiswincache>" $data[$app]["IIS"]["cache"]["php2"]["tps$virt"] "</td>" + + + $gain = gaincalc $data[$app]["IIS"]["cache"]["php2"]["tps$virt"] $data[$app]["IIS"]["cache"]["php1"]["tps$virt"] + write-output " + + <td class=$gainclass> $gain + </td> <!-- Gain --> + + <!-- Apache - No Cache --> + <td class=apache>" $data[$app]["Apache"]["nocache"]["php1"]["tps$virt"] "</td> + <td class=apache>" $data[$app]["Apache"]["nocache"]["php2"]["tps$virt"] "</td>" + + $gain = gaincalc $data[$app]["Apache"]["nocache"]["php2"]["tps$virt"] $data[$app]["Apache"]["nocache"]["php1"]["tps$virt"] + write-output " + + <td class=$gainclass> $gain + </td> <!-- Gain --> + + <!-- Apache - Cache -igbinary --> + <td class=apachenoigbinary>" $data[$app]["Apache"]["cachenoigbinary"]["php1"]["tps$virt"] "</td> + <td class=apachenoigbinary>" $data[$app]["Apache"]["cachenoigbinary"]["php2"]["tps$virt"] "</td>" + + $gain = gaincalc $data[$app]["Apache"]["cachenoigbinary"]["php2"]["tps$virt"] $data[$app]["Apache"]["cachenoigbinary"]["php1"]["tps$virt"] + write-output " + + <td class=$gainclass> $gain + </td> <!-- Gain --> + + <!-- Apache - Cache +igbinary --> + <td class=apachewithigbinary>" $data[$app]["Apache"]["cachewithigbinary"]["php1"]["tps$virt"] "</td> + <td class=apachewithigbinary>" $data[$app]["Apache"]["cachewithigbinary"]["php2"]["tps$virt"] "</td>" + + $gain = gaincalc $data[$app]["Apache"]["cachewithigbinary"]["php2"]["tps$virt"] $data[$app]["Apache"]["cachewithigbinary"]["php1"]["tps$virt"] + write-output " + + <td class=$gainclass> $gain + </td> <!-- Gain --> + </tr> + " + } ## End Foreach +} ## End Foreach + +write-output " +</table> +<p> </p> +<p> </p> +" + +if ( $errlog -ne "" ) { + write-output "<strong>Error Log:</strong> <br/>" + write-output "$errlog" +} + +write-output " +</body> +</html> +" + + +*/ diff --git a/src/com/mostc/pftt/report/UBCReportGen.groovy b/src/com/mostc/pftt/report/UBCReportGen.groovy new file mode 100644 index 0000000..e69de29 diff --git a/src/com/mostc/pftt/results/PhptResultPackWriter.java b/src/com/mostc/pftt/results/PhptResultPackWriter.java index 17761a4..80624a3 100644 --- a/src/com/mostc/pftt/results/PhptResultPackWriter.java +++ b/src/com/mostc/pftt/results/PhptResultPackWriter.java @@ -38,6 +38,8 @@ import com.mostc.pftt.util.StringUtil; * */ +// TODO store consolemanager logs in result-pack +// -including smoke checks from dfs and deduplication scenrios public class PhptResultPackWriter extends PhptResultPack implements IPhptTestResultReceiver { private File telem_dir; protected final HashMap<Host,HashMap<ScenarioSet,HashMap<EPhptTestStatus,PrintWriter>>> status_list_map; diff --git a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java index 0abd429..be2d451 100644 --- a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java @@ -19,7 +19,6 @@ import com.mostc.pftt.model.phpt.PhpIni; import com.mostc.pftt.model.phpt.PhptTestCase; import com.mostc.pftt.model.phpt.PhptSourceTestPack; import com.mostc.pftt.model.phpt.PhptActiveTestPack; -import com.mostc.pftt.model.smoke.RequiredExtensionsSmokeTest; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.IPhptTestResultReceiver; import com.mostc.pftt.results.PhptTestResult; @@ -37,7 +36,7 @@ import com.mostc.pftt.util.StringUtil; public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { protected ExecOutput output; - protected String selected_php_exe, shell_script, test_cmd, skip_cmd, ini_settings, shell_file; + protected String selected_php_exe, shell_script, test_cmd, skip_cmd, ini_settings, shell_file, ini_dir; public static boolean willSkip(ConsoleManager cm, IPhptTestResultReceiver twriter, Host host, ScenarioSet scenario_set, ESAPIType type, PhpBuild build, PhptTestCase test_case) throws Exception { if (AbstractPhptTestCaseRunner2.willSkip(cm, twriter, host, scenario_set, type, build, test_case)) { @@ -123,7 +122,9 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { "ext/standard/tests/file/fgets_socket_variation1.phpt", "ext/standard/tests/network/shutdown.phpt", "ext/standard/tests/file/fgets_socket_variation2.phpt", - "ext/standard/tests/network/tcp4loop.phpt" + "ext/standard/tests/network/tcp4loop.phpt", + "zend/tests/multibyte/multibyte_encoding_003.phpt", + "zend/tests/multibyte/multibyte_encoding_002.phpt" )) { twriter.addResult(host, scenario_set, new PhptTestResult(host, EPhptTestStatus.XSKIP, test_case, "test sometimes randomly fails, ignore it", null, null, null, null, null, null, null, null, null, null, null)); @@ -139,6 +140,8 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { @Override protected boolean prepare() throws IOException, Exception { if (super.prepare()) { + ini_dir = build.prepare(host); + // ini_settings = ini.toCliArgString(host); @@ -147,6 +150,7 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { /* For GET/POST tests, check if cgi sapi is available and if it is, use it. */ if (test_case.containsAnySection(EPhptSection.GET, EPhptSection.POST, EPhptSection.PUT, EPhptSection.POST_RAW, EPhptSection.COOKIE, EPhptSection.EXPECTHEADERS)) { if (build.hasPhpCgiExe()) { + // -C => important: don't chdir selected_php_exe = build.getPhpCgiExe() + " -C "; } else { twriter.addResult(host, scenario_set, new PhptTestResult(host, EPhptTestStatus.XSKIP, test_case, "CGI not available", null, null, null, null, null, null, null, null, null, null, null)); @@ -162,31 +166,10 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { return false; } - static boolean saved_ini = false; - static String ini_dir; - @Override protected void prepareTest() throws Exception { super.prepareTest(); - // - if (!saved_ini) { - // @see CliScenario#createIniForTest - saved_ini = true; - - ini_dir = host.mktempname(getClass()); - host.mkdirs(ini_dir); - - String ini_file = ini_dir + "/php.ini"; - - PhpIni def_ini = RequiredExtensionsSmokeTest.createDefaultIniCopy(host, build); - - FileWriter fw = new FileWriter(ini_file); - fw.write(def_ini.toString()); - fw.close(); - } - // - // generate cmd string to run test_file with php.exe // String query_string = ""; @@ -293,8 +276,8 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { if (skipif_file != null) { env.put(ENV_USE_ZEND_ALLOC, "1"); - // -n => critical: ignores any .ini file with the php build - skip_cmd = selected_php_exe+" -n "+ini_settings+" -f \""+skipif_file+"\""; + // -c => critical, pass php.ini + skip_cmd = selected_php_exe+" -c "+ini_dir+" "+ini_settings+" -f \""+skipif_file+"\""; if (!env.containsKey(ENV_PATH_TRANSLATED)) env.put(ENV_PATH_TRANSLATED, skipif_file); @@ -303,7 +286,7 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { // execute SKIPIF (60 second timeout) output = host.exec(skip_cmd, Host.ONE_MINUTE, env, null, active_test_pack.getDirectory()); - + return output.output; } return null; @@ -327,8 +310,8 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { @Override protected void executeClean() throws Exception { // execute cleanup script - // FUTURE should cleanup script be ignored?? host.exec(selected_php_exe+" "+test_clean, Host.ONE_MINUTE, env, null, active_test_pack.getDirectory()); + } // end void executeClean @Override diff --git a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java index 941782c..d6a7ed4 100644 --- a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java +++ b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java @@ -14,6 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import com.mostc.pftt.host.Host; +import com.mostc.pftt.host.SSHHost; import com.mostc.pftt.model.phpt.PhpBuild; import com.mostc.pftt.model.phpt.PhptTestCase; import com.mostc.pftt.model.phpt.PhptSourceTestPack; @@ -26,8 +27,10 @@ import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.IPhptTestResultReceiver; import com.mostc.pftt.results.ConsoleManager.EPrintType; import com.mostc.pftt.scenario.AbstractFileSystemScenario; +import com.mostc.pftt.scenario.AbstractFileSystemScenario.ITestPackStorageDir; import com.mostc.pftt.scenario.AbstractSAPIScenario; import com.mostc.pftt.scenario.AbstractWebServerScenario; +import com.mostc.pftt.scenario.SMBDeduplicationScenario; import com.mostc.pftt.scenario.Scenario; import com.mostc.pftt.scenario.ScenarioSet; import com.mostc.pftt.util.StringUtil; @@ -105,6 +108,10 @@ public class LocalPhptTestPackRunner extends PhptTestPackRunner { sapi_scenario = AbstractSAPIScenario.getSAPIScenario(scenario_set); file_scenario = AbstractFileSystemScenario.getFileSystemScenario(scenario_set); + // TODO + SSHHost remote_host = new SSHHost("10.200.41.219", "administrator", "password01!"); + file_scenario = new SMBDeduplicationScenario(remote_host, "F:"); + // ensure all scenarios are implemented if (!scenario_set.isImplemented()) { cm.println(EPrintType.SKIP_OPERATION, getClass(), "Scenario Set not implemented: "+scenario_set); @@ -119,25 +126,28 @@ public class LocalPhptTestPackRunner extends PhptTestPackRunner { cm.println(EPrintType.IN_PROGRESS, getClass(), "preparing storage for test-pack..."); // prepare storage - if (!file_scenario.notifyPrepareStorageDir(cm, host)) { + ITestPackStorageDir storage_dir = file_scenario.createStorageDir(cm, host); + if (storage_dir == null) { cm.println(EPrintType.CANT_CONTINUE, getClass(), "unable to prepare storage for test-pack, giving up!"); close(); return; } // - String storage_dir = file_scenario.getTestPackStorageDir(host); // generate name of directory on that storage to store the copy of the test-pack - String test_pack_dir; - long millis = System.currentTimeMillis(); - for ( int i=0 ; ; i++ ) { - // try to include version, branch info etc... from name of test-pack - test_pack_dir = storage_dir + "/PFTT-" + Host.basename(src_test_pack.getSourceDirectory()) + "-" + millis; - if (!host.exists(test_pack_dir)) - break; - millis++; - if (i%100==0) - millis = System.currentTimeMillis(); + String test_pack_dir = null; + { + String local_path = storage_dir.getLocalPath(host); + long millis = System.currentTimeMillis(); + for ( int i=0 ; i < 655535 ; i++ ) { + // try to include version, branch info etc... from name of test-pack + test_pack_dir = local_path + "/PFTT-" + Host.basename(src_test_pack.getSourceDirectory()) + (i==0?"":"-" + millis); + if (!host.exists(test_pack_dir)) + break; + millis++; + if (i%100==0) + millis = System.currentTimeMillis(); + } } // @@ -152,7 +162,7 @@ public class LocalPhptTestPackRunner extends PhptTestPackRunner { active_test_pack = src_test_pack.installInPlace(); else // copy test-pack onto (remote) file system - active_test_pack = src_test_pack.install(host, test_pack_dir); + active_test_pack = src_test_pack.install(cm, host, test_pack_dir); } catch (Exception ex ) { cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "runTestList", ex, "", host, file_scenario, active_test_pack); } @@ -164,7 +174,7 @@ public class LocalPhptTestPackRunner extends PhptTestPackRunner { // // notify storage - if (!file_scenario.notifyTestPackInstalled(cm, host)) { + if (!storage_dir.notifyTestPackInstalled(cm, host)) { cm.println(EPrintType.CANT_CONTINUE, getClass(), "unable to prepare storage for test-pack, giving up!(2)"); close(); return; @@ -218,7 +228,7 @@ public class LocalPhptTestPackRunner extends PhptTestPackRunner { host.delete(active_test_pack.getDirectory()); // cleanup, disconnect storage, etc... - file_scenario.notifyFinishedTestPack(cm, host); + storage_dir.delete(cm, host); } // } finally { diff --git a/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java b/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java index 62d773a..e7fd15b 100644 --- a/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java +++ b/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java @@ -3,6 +3,12 @@ package com.mostc.pftt.scenario; import com.mostc.pftt.host.Host; import com.mostc.pftt.results.ConsoleManager; +/** + * + * @author Matt Ficken + * + */ + public abstract class AbstractFileSystemScenario extends AbstractSerialScenario { public static AbstractFileSystemScenario getFileSystemScenario(ScenarioSet scenario_set) { @@ -13,19 +19,42 @@ public abstract class AbstractFileSystemScenario extends AbstractSerialScenario 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 - } + + public interface ITestPackStorageDir { + /** called once test pack is copied/installed to storage dir. + * + * returns FALSE if shouldn't proceed with using test-pack on storage dir + * + * @param cm + * @param host + * @return + */ + boolean notifyTestPackInstalled(ConsoleManager cm, Host local_host); + + /** returns local path to access storage directory. + * + * this will be a drive that the storage dir is mounted on (if remote) or the actual location of the storage dir (if local) + * + * @param local_host + * @return + */ + String getLocalPath(Host local_host); + + /** returns TRUE if storage dir deleted + * + * @param cm + * @param host + * @return + */ + boolean delete(ConsoleManager cm, Host local_host); + } // end public interface ITestPackStorageDir + + public abstract ITestPackStorageDir createStorageDir(ConsoleManager cm, Host host); /** 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) { - - } -} +} // end public abstract class AbstractFileSystemScenario diff --git a/src/com/mostc/pftt/scenario/AbstractNetworkedServiceScenario.java b/src/com/mostc/pftt/scenario/AbstractNetworkedServiceScenario.java new file mode 100644 index 0000000..53c80b8 --- /dev/null +++ b/src/com/mostc/pftt/scenario/AbstractNetworkedServiceScenario.java @@ -0,0 +1,5 @@ +package com.mostc.pftt.scenario; + +public abstract class AbstractNetworkedServiceScenario extends AbstractParallelScenario { + +} diff --git a/src/com/mostc/pftt/scenario/AbstractSMBScenario.java b/src/com/mostc/pftt/scenario/AbstractSMBScenario.java index fee0b1b..47e6a1c 100644 --- a/src/com/mostc/pftt/scenario/AbstractSMBScenario.java +++ b/src/com/mostc/pftt/scenario/AbstractSMBScenario.java @@ -18,25 +18,22 @@ import com.mostc.pftt.util.StringUtil; public abstract class AbstractSMBScenario extends AbstractRemoteFileSystemScenario { protected final RemoteHost remote_host; protected final String base_file_path, base_share_name; - // file path is path on server where share is stored - // network path is in both UNC and URL format (UNC for Windows, URL for Linux) - protected String share_name, remote_path, unc_path, url_path, local_path; public AbstractSMBScenario(RemoteHost remote_host, String base_file_path, String base_share_name) { this.remote_host = remote_host; // if (StringUtil.isEmpty(base_file_path)) // fallback to a default path, @see SMBDeduplicationScenario - base_file_path = remote_host.isWindows() ? "C:\\PFTT_Share" : "/var/data/PFTT_Share"; + base_file_path = remote_host.isWindows() ? "C:\\PFTT-Share" : "/var/data/PFTT-Share"; else if (StringUtil.isEmpty(Host.basename(base_file_path))) // base_file_path ~= C:\ - base_file_path += "\\PFTT_Share"; + base_file_path += "\\PFTT-Share"; if (StringUtil.isNotEmpty(base_share_name)) base_share_name = base_share_name.trim(); if (StringUtil.isEmpty(base_share_name)) { base_share_name = Host.basename(base_file_path); if (StringUtil.isEmpty(base_share_name)) - base_share_name = "\\PFTT_Share"; + base_share_name = "\\PFTT-Share"; } // this.base_file_path = base_file_path; @@ -59,13 +56,50 @@ public abstract class AbstractSMBScenario extends AbstractRemoteFileSystemScenar * @return TRUE on success, FALSE on failure (can't use this storage if failure) */ @Override - public boolean notifyPrepareStorageDir(ConsoleManager cm, Host local_host) { - return createShare(cm) && connect(cm, local_host); + public SMBStorageDir createStorageDir(ConsoleManager cm, Host host) { + SMBStorageDir dir = newSMBStorageDir(); + + if ( createShare(dir, cm) ) { + if ( connect(dir, cm, host) ) { + return dir; + } + } + + // failed, try cleaning up + dir.delete(cm, host); + + return null; } + protected SMBStorageDir newSMBStorageDir() { + return new SMBStorageDir(); + } + + public class SMBStorageDir implements ITestPackStorageDir { + // file path is path on server where share is stored + // network path is in both UNC and URL format (UNC for Windows, URL for Linux) + protected String share_name, remote_path, unc_path, url_path, local_path; + + @Override + public boolean notifyTestPackInstalled(ConsoleManager cm, Host local_host) { + return true; + } + + @Override + public boolean delete(ConsoleManager cm, Host local_host) { + return disconnect(this, cm, local_host) && deleteShare(this, cm, local_host); + } + + @Override + public String getLocalPath(Host local_host) { + return local_path; // H: I: J: ... Y: + } + + } // end public class SMBStorageDir + @Override public boolean setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { - return createShare(cm); + return createShare(newSMBStorageDir(), cm); } public boolean shareExists(ConsoleManager cm, String share_name) { @@ -82,133 +116,143 @@ public abstract class AbstractSMBScenario extends AbstractRemoteFileSystemScenar return false; } - public boolean createShare(ConsoleManager cm) { + protected void makeShareName(SMBStorageDir dir, ConsoleManager cm) { // make a unique name for the share for ( int i=1 ; i < 65535 ; i++ ) { - remote_path = base_file_path + i; - share_name = base_share_name + i; - if (!remote_host.exists(remote_path)) { + dir.remote_path = base_file_path + "-" + i; + dir.share_name = base_share_name + "-" + i; + if (!remote_host.exists(dir.remote_path)) { // share may still exist, but at a different remote file path (double check to avoid `net share` failure) - if (!shareExists(cm, share_name)) { + if (!shareExists(cm, dir.share_name)) { break; } } } - // - cm.println(EPrintType.IN_PROGRESS, getName(), "Selected share_name="+share_name+" remote_path="+remote_path+" (base: "+base_file_path+" "+base_share_name+")"); + dir.unc_path = "\\\\"+remote_host.getHostname()+"\\"+dir.share_name; // for Windows + dir.url_path = "smb://"+remote_host.getHostname()+"/"+dir.share_name; // for linux + } // end protected void makeShareName + + protected boolean createShare(SMBStorageDir dir, ConsoleManager cm) { + makeShareName(dir, cm); + + cm.println(EPrintType.IN_PROGRESS, getName(), "Selected share_name="+dir.share_name+" remote_path="+dir.remote_path+" (base: "+base_file_path+" "+base_share_name+")"); try { if (remote_host.isWindows()) { - if (!createShareWindows(cm)) + if (!createShareWindows(dir, cm)) return false; - } else if (!createShareSamba()) { + } else if (!createShareSamba(dir, cm)) { return false; } } catch (Exception ex ) { - cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "createShare", ex, "", remote_host, remote_path, share_name); + cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "createShare", ex, "", remote_host, dir.remote_path, dir.share_name); return false; } - unc_path = "\\\\"+remote_host.getHostname()+"\\"+share_name; // for Windows - url_path = "smb://"+remote_host.getHostname()+"/"+share_name; // for linux - - cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Share created: unc="+unc_path+" remote_file="+remote_path+" url="+url_path); + cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Share created: unc="+dir.unc_path+" remote_file="+dir.remote_path+" url="+dir.url_path); return true; - } // end public boolean createShare + } // end protected boolean createShare - protected boolean createShareWindows(ConsoleManager cm) throws Exception { + protected boolean createShareWindows(SMBStorageDir dir, ConsoleManager cm) throws Exception { + return doCreateShareWindows(cm, dir.remote_path, dir.share_name); + } + + protected boolean doCreateShareWindows(ConsoleManager cm, String remote_path, String share_name) throws Exception { + remote_path = remote_path.replace("C", "G"); // TODO + remote_host.mkdirs(remote_path); - return remote_host.execElevated("NET SHARE "+share_name+"="+remote_path+" /Grant:"+remote_host.getUsername()+",Full", Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess(); + String cmd = "NET SHARE "+share_name+"="+remote_path+" /Grant:"+remote_host.getUsername()+",Full"; + System.out.println("cmd "+cmd); + return remote_host.execElevated(cmd, Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess(); } - protected boolean createShareSamba() { + protected boolean createShareSamba(SMBStorageDir dir, ConsoleManager cm) { // XXX return false; } - public boolean connect(ConsoleManager cm, Host local_host) { + protected boolean connect(SMBStorageDir dir, ConsoleManager cm, Host local_host) { if (remote_host.isRemote()) { try { if (remote_host.isWindows()) - return connectFromWindows(cm, local_host); + return connectFromWindows(dir, cm, local_host); else - return connectFromSamba(); + return connectFromSamba(dir, cm); } catch ( Exception ex ) { cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "connect", ex, "", remote_host, local_host); return false; } } else { // host is local, try using a local drive, normal file system operations, not SMB, etc... - local_path = remote_path; + dir.local_path = dir.remote_path; return true; } - } // end public boolean connect + } // end protected boolean connect protected static final String[] DRIVES = new String[]{"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y"}; // 18 - protected boolean connectFromWindows(ConsoleManager cm, Host local_host) throws Exception { - local_path = null; + protected boolean connectFromWindows(SMBStorageDir dir, ConsoleManager cm, Host local_host) throws Exception { + dir.local_path = null; for ( int i=0 ; i < DRIVES.length ; i++ ) { if (!local_host.exists(DRIVES[i] + ":\\")) { - local_path = DRIVES[i] + ":"; + dir.local_path = DRIVES[i] + ":"; break; } } - if (local_path==null) + if (dir.local_path==null) return false; - return local_host.execElevated("NET USE "+unc_path+" "+local_path+" /user:"+remote_host.getUsername()+" /password:"+remote_host.getPassword(), Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess(); + String cmd = "NET USE "+dir.local_path+" "+dir.unc_path+" /user:"+remote_host.getUsername()+" "+remote_host.getPassword(); + + return local_host.execElevated(cmd, Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess(); } - protected boolean connectFromSamba() { + protected boolean connectFromSamba(SMBStorageDir dir, ConsoleManager cm) { // XXX return false; } - @Override - public String getTestPackStorageDir(Host host) { - return local_path; // H: I: J: ... Y: + protected boolean deleteShare(SMBStorageDir dir, ConsoleManager cm, Host host) { + if (doDeleteShareWindows(cm, dir.remote_path)) { + cm.println(EPrintType.IN_PROGRESS, getClass(), "Share deleted: remote_file="+dir.remote_path+" unc="+dir.unc_path+" url="+dir.url_path); + + return true; + } else { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to delete share: remote_file="+dir.remote_path+" unc="+dir.unc_path); + + return false; + } } - public boolean deleteShare(ConsoleManager cm, Host host) { + protected boolean doDeleteShareWindows(ConsoleManager cm, String remote_path) { try { - if (host.execElevated("NET SHARE "+remote_path+" /DELETE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess()) { + if (remote_host.execElevated("NET SHARE "+remote_path+" /DELETE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess()) { try { - host.delete(remote_path); + remote_host.delete(remote_path); - cm.println(EPrintType.IN_PROGRESS, getClass(), "Share deleted: remote_file="+remote_path+" unc="+unc_path+" url="+url_path); + return true; } catch ( Exception ex ) { throw ex; } - - return true; } } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "deleteShare", ex, "", host, remote_path); + cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "deleteShare", ex, "", remote_host, remote_path); } return false; } - public boolean disconnect(ConsoleManager cm, Host host) { + protected boolean disconnect(SMBStorageDir dir, ConsoleManager cm, Host host) { try { - if (host.exec("NET USE "+local_path+" /DELETE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess()) { - cm.println(EPrintType.IN_PROGRESS, getClass(), "Disconnected share: local="+local_path); + if (host.exec("NET USE "+dir.local_path+" /DELETE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess()) { + cm.println(EPrintType.IN_PROGRESS, getClass(), "Disconnected share: local="+dir.local_path); } } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "disconnect", ex, "", host, local_path); + cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "disconnect", ex, "Unable to disconnect: local="+dir.local_path, host, dir.local_path); } return false; } - @Override - public void notifyFinishedTestPack(ConsoleManager cm, Host host) { - if (deleteShare(cm, host) && disconnect(cm, host)) { - // reset - share_name = remote_path = unc_path = url_path = local_path = null; - } - } - } // end public abstract class AbstractSMBScenario diff --git a/src/com/mostc/pftt/scenario/AbstractStreamsScenario.java b/src/com/mostc/pftt/scenario/AbstractStreamsScenario.java index 478019f..95735d9 100644 --- a/src/com/mostc/pftt/scenario/AbstractStreamsScenario.java +++ b/src/com/mostc/pftt/scenario/AbstractStreamsScenario.java @@ -1,5 +1,5 @@ package com.mostc.pftt.scenario; -public abstract class AbstractStreamsScenario extends AbstractParallelScenario { +public abstract class AbstractStreamsScenario extends AbstractNetworkedServiceScenario { } diff --git a/src/com/mostc/pftt/scenario/IMAPScenario.java b/src/com/mostc/pftt/scenario/IMAPScenario.java new file mode 100644 index 0000000..f4049d4 --- /dev/null +++ b/src/com/mostc/pftt/scenario/IMAPScenario.java @@ -0,0 +1,21 @@ +package com.mostc.pftt.scenario; + +/** scenario for interacting with IMAP mail servers + * + * @author Matt Ficken + * + */ + +public class IMAPScenario extends AbstractNetworkedServiceScenario { + + @Override + public String getName() { + return "IMAP"; + } + + @Override + public boolean isImplemented() { + return false; + } + +} diff --git a/src/com/mostc/pftt/scenario/LDAPScenario.java b/src/com/mostc/pftt/scenario/LDAPScenario.java index 998f67b..f2bfca3 100644 --- a/src/com/mostc/pftt/scenario/LDAPScenario.java +++ b/src/com/mostc/pftt/scenario/LDAPScenario.java @@ -4,7 +4,7 @@ package com.mostc.pftt.scenario; * */ -public class LDAPScenario extends AbstractParallelScenario { +public class LDAPScenario extends AbstractNetworkedServiceScenario { @Override public String getName() { diff --git a/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java b/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java index 0cf9780..4572894 100644 --- a/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java +++ b/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java @@ -11,7 +11,22 @@ import com.mostc.pftt.results.ConsoleManager.EPrintType; */ public class LocalFileSystemScenario extends AbstractFileSystemScenario { - + protected static ITestPackStorageDir LOCAL_DIR = new ITestPackStorageDir() { + @Override + public boolean notifyTestPackInstalled(ConsoleManager cm, Host host) { + return true; + } + @Override + public String getLocalPath(Host host) { + return host.getPhpSdkDir(); + } + @Override + public boolean delete(ConsoleManager cm, Host host) { + return true; // don't actually delete php sdk + } + }; + + @Override public String getName() { return "Local-FileSystem"; @@ -28,19 +43,14 @@ public class LocalFileSystemScenario extends AbstractFileSystemScenario { } @Override - public boolean notifyPrepareStorageDir(ConsoleManager cm, Host host) { + public ITestPackStorageDir createStorageDir(ConsoleManager cm, Host host) { try { - host.mkdirs(getTestPackStorageDir(host)); - return true; + host.mkdirs(host.getPhpSdkDir()); + return LOCAL_DIR; } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.CANT_CONTINUE, LocalFileSystemScenario.class, "notifyPrepareStorageDir", ex, ""); - return false; + cm.addGlobalException(EPrintType.CANT_CONTINUE, LocalFileSystemScenario.class, "createStorageDir", ex, ""); + return null; } } - @Override - public String getTestPackStorageDir(Host host) { - return host.getPhpSdkDir(); - } - } // end public class LocalFileSystemScenario diff --git a/src/com/mostc/pftt/scenario/SMBBasicScenario.java b/src/com/mostc/pftt/scenario/SMBBasicScenario.java index cdfafac..990f3f0 100644 --- a/src/com/mostc/pftt/scenario/SMBBasicScenario.java +++ b/src/com/mostc/pftt/scenario/SMBBasicScenario.java @@ -4,6 +4,9 @@ import com.mostc.pftt.host.RemoteHost; /** Tests running a PHP build and its test pack both stored remotely on a basic SMB file share. * + * + * Typically, you'll create 1 instance of this for each remote file server, and each instance can create manage multiple shares at the same time. + * * @author Matt Ficken * */ diff --git a/src/com/mostc/pftt/scenario/SMBCAScenario.java b/src/com/mostc/pftt/scenario/SMBCAScenario.java index 22bf878..4e17064 100644 --- a/src/com/mostc/pftt/scenario/SMBCAScenario.java +++ b/src/com/mostc/pftt/scenario/SMBCAScenario.java @@ -24,8 +24,8 @@ public class SMBCAScenario extends AbstractSMBScenario { } @Override - protected boolean createShareWindows(ConsoleManager cm) throws Exception { - TempFileExecOutput teo = remote_host.powershell(getClass(), cm, "New-SmbShare -Name "+share_name+" -Path "+remote_path+" -Scope "+remote_host.getHostname()+" -FullControl "+remote_host.getHostname()+"\\"+remote_host.getUsername(), Host.ONE_MINUTE); + protected boolean createShareWindows(SMBStorageDir dir, ConsoleManager cm) throws Exception { + TempFileExecOutput teo = remote_host.powershell(getClass(), cm, "New-SmbShare -Name "+dir.share_name+" -Path "+dir.remote_path+" -Scope "+remote_host.getHostname()+" -FullControl "+remote_host.getHostname()+"\\"+remote_host.getUsername(), Host.ONE_MINUTE); teo.printOutputIfCrash(getClass(), cm); return teo.cleanupIfSuccess(remote_host); } diff --git a/src/com/mostc/pftt/scenario/SMBDFSRScenario.java b/src/com/mostc/pftt/scenario/SMBDFSRScenario.java deleted file mode 100644 index e0b8c5c..0000000 --- a/src/com/mostc/pftt/scenario/SMBDFSRScenario.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.mostc.pftt.scenario; - -import com.mostc.pftt.host.Host; -import com.mostc.pftt.host.RemoteHost; -import com.mostc.pftt.host.TempFileExecOutput; -import com.mostc.pftt.model.phpt.PhpBuild; -import com.mostc.pftt.results.ConsoleManager; -import com.mostc.pftt.results.ConsoleManager.EPrintType; - -/** Tests PHP with PHP build and test pack being stored remotely on a group of DFS-R SMB Shares. - * - * Web hosters can setup a share that is physically copied and served by multiple SMB Servers. - * - * According to the MS IIS team, this scenario is commonly used in production IIS deployments (ie they want it tested). - * - * This scenario is functionally similar to the newer Continuous-Availability concept in SMBv3, but presently DFS is more commonly used. - * - * There are two types of DFS, DFS-N and DFS-R, this tests DFS-R. DFS-N is not relevant because it only replicates a namespace(folder structure) - * across servers. DFS-R synchronizes folder contents efficiently between file servers across LANs and even WANs. - * - * @see `dfsutil`, `dfscmd` and `dfsdiag` and `fsutil reparsepoint query <file>` - * @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365511%28v=vs.85%29.aspx - * @author Matt Ficken - * - */ - -public class SMBDFSRScenario extends AbstractSMBScenario { - - // TODO PFTT-NS-1 PFTT-DFS-1 PFTT-TARGET-1 - // TODO use only ip addresses - // -still have problems with netbios name resolution - public SMBDFSRScenario(RemoteHost remote_host) { - this(remote_host, null, null); - } - - public SMBDFSRScenario(RemoteHost remote_host, String base_file_path, String base_share_name) { - super(remote_host, base_file_path, base_share_name); - } - - @Override - public String getName() { - return "SMB-DFSR"; - } - - @Override - public boolean setup(ConsoleManager cm, Host local_host, PhpBuild build, ScenarioSet scenario_set) { - StringBuilder ps_sb = new StringBuilder(); - ps_sb.append("Import-Module ServerManager\n"); - ps_sb.append("Add-WindowsFeature -name File-Services\n"); - ps_sb.append("Add-WindowsFeature -name FS-DFS\n"); - ps_sb.append("Add-WindowsFeature -name FS-DFS-Replication\n"); - - try { - TempFileExecOutput teo = remote_host.powershell(getClass(), cm, ps_sb, Host.FOUR_HOURS); - - if (teo.printOutputIfCrash(getClass(), cm).isSuccess()) { - teo.cleanup(remote_host); - - if (super.setup(cm, remote_host, build, scenario_set)) { - cm.println(EPrintType.COMPLETED_OPERATION, getName(), "DFSR setup successfully: unc="+unc_path+" remote_file="+remote_path); - - return true; - } - } else { - cm.println(EPrintType.OPERATION_FAILED_CONTINUING, getName(), "can't exec powershell script: "+ps_sb); - } - } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "setup", ex, "", remote_host, ps_sb, unc_path); - } - return false; - } - - @Override - public boolean isImplemented() { - return true; - } - -} // end public class SMBDFSRScenario diff --git a/src/com/mostc/pftt/scenario/SMBDFSScenario.java b/src/com/mostc/pftt/scenario/SMBDFSScenario.java new file mode 100644 index 0000000..e31ca95 --- /dev/null +++ b/src/com/mostc/pftt/scenario/SMBDFSScenario.java @@ -0,0 +1,235 @@ +package com.mostc.pftt.scenario; + +import com.mostc.pftt.host.Host; +import com.mostc.pftt.host.RemoteHost; +import com.mostc.pftt.host.TempFileExecOutput; +import com.mostc.pftt.model.phpt.PhpBuild; +import com.mostc.pftt.results.ConsoleManager; +import com.mostc.pftt.results.ConsoleManager.EPrintType; + +/** Tests PHP with PHP build and test pack being stored remotely on a group of DFS SMB Shares. + * + * Web hosters can setup a share that is physically copied and served by multiple SMB Servers. + * + * According to the MS IIS team, this scenario is commonly used in production IIS deployments (ie they want it tested). + * + * This scenario is functionally similar to the newer Continuous-Availability (CA) concept in SMBv3, but presently DFS is more commonly used. + * + * + * Typically, you'll create 1 instance of this for each remote file server, and each instance can create manage multiple shares at the same time. + * + * NOTE: There won't be any reparse points when remotely mounting a DFS share (the namespace, folder or target are not reparsepoints). + * `fsutil reparsepoint query` when run locally on the DFS server will return a reparse tag for the link, but not over the network. + * The DFS and DFSR reparsepoints are not anywhere on a DFS share (they are only used internally on the DFS server's filesystem). + * + * @see `dfsutil`, `dfscmd` and `dfsdiag` + * @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365511%28v=vs.85%29.aspx + * @author Matt Ficken + * + */ + +public class SMBDFSScenario extends AbstractSMBScenario { + protected final String base_namespace, base_remote_namespace, base_folder; + + public SMBDFSScenario(RemoteHost remote_host) { + // default: create PFTT-NS-n(namespace), PFTT-DFS-n(folder) and PFTT-SHARE-n(target) + this(remote_host, null, null, "PFTT-NS", "PFTT-NS", "PFTT-DFS"); + } + + public SMBDFSScenario(RemoteHost remote_host, String base_file_path, String base_share_name, String base_remote_namespace, String base_namespace, String base_folder) { + super(remote_host, base_file_path, base_share_name); + this.base_remote_namespace = base_remote_namespace; + this.base_namespace = base_namespace; + this.base_folder = base_folder; + } + + @Override + public String getName() { + return "SMB-DFS"; + } + + @Override + public boolean setup(ConsoleManager cm, Host local_host, PhpBuild build, ScenarioSet scenario_set) { + return installDFSFeature(cm, local_host) && super.setup(cm, local_host, build, scenario_set); + } + + @Override + public DFSSMBStorageDir createStorageDir(ConsoleManager cm, Host local_host) { + if (!remote_host.isWindows()) { + cm.println(EPrintType.XSKIP_OPERATION, getName(), "Scenario can only be run against a Windows host"); + return null; + } else { + DFSSMBStorageDir dir = (DFSSMBStorageDir) super.createStorageDir(cm, local_host); + if (dir==null) + return dir; // already would've done error msg + + cm.println(EPrintType.COMPLETED_OPERATION, getClass(), "Created DFS Share: unc_path="+dir.unc_path+" url="+dir.url_path+" (namespace="+dir.namespace+" folder="+dir.target+" local="+dir.local_path+")"); + + return dir; + } + } // end public DFSSMBStorageDir createStorageDir + + @Override + protected DFSSMBStorageDir newSMBStorageDir() { + return new DFSSMBStorageDir(); + } + + public class DFSSMBStorageDir extends SMBStorageDir { + // location on remote file system where the Share that stores the Namespace is + protected String remote_namespace; + // name of namespace + protected String namespace; + // target pointed to by folder in namespace (folder is represented by SMBStorageDir#unc_path, etc...) + protected String target; + // UNC path to namespace (including server address) + protected String unc_namespace_path; + // real File share that DFS will send referals pointing to + protected String unc_target; + // URL format + protected String url_namespace_path, url_target; + + @Override + public boolean delete(ConsoleManager cm, Host local_host) { + try { + // delete folder and link + if (!remote_host.execElevated("DFSUTIL LINK REMOVE "+unc_path, Host.ONE_MINUTE*10).printOutputIfCrash(getClass(), cm).isSuccess()) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to remove DFS Link"); + + disconnect(this, cm, local_host); + return false; + } + + // delete namespace + if (!remote_host.execElevated("DFSUTIL ROOT REMOVE "+unc_namespace_path, Host.ONE_MINUTE*10).printOutputIfCrash(getClass(), cm).isSuccess()) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Uanble to remove DFS Namespace"); + + disconnect(this, cm, local_host); + return false; + } + + if (!doDeleteShareWindows(cm, remote_namespace)) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to remove DFS Namespace Share"); + + disconnect(this, cm, local_host); + return false; + } + + // delete target share and disconnect + if (super.delete(cm, local_host)) { + cm.println(EPrintType.COMPLETED_OPERATION, getClass(), "Removed DFS share successfully."); + + return true; + } + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CANT_CONTINUE, getClass(), "delete", ex, "Unable to delete DFS Share"); + } + disconnect(this, cm, local_host); + + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to delete DFS Share! unc="+unc_namespace_path); + return false; + } // end public boolean delete + + } // end public class DFSSMBStorageDir + + @Override + protected void makeShareName(SMBStorageDir dir, ConsoleManager cm) { + DFSSMBStorageDir dfs_dir = (DFSSMBStorageDir) dir; + + // make a unique name for the share and namespace + for ( int i=1 ; i < 65535 ; i++ ) { + dir.remote_path = base_file_path + "-" + i; + dir.share_name = base_share_name + "-" + i; + // TODO getSystemDrive here + dfs_dir.remote_namespace = "G:\\"+base_remote_namespace + "-" + i; + dfs_dir.namespace = base_namespace + i; + dfs_dir.target = base_folder + i; + + if (!remote_host.exists(dir.remote_path) && !remote_host.exists(dfs_dir.remote_namespace)) { + // share may still exist, but at a different remote file path (double check to avoid `net share` failure) + if (!shareExists(cm, dir.share_name)) { + break; + } + } + } // end for + + // IMPORTANT: use IP addresses. there may be problems with name resolution on larger networks (ex: Microsoft CorpNet) + dfs_dir.unc_path = "\\\\"+remote_host.getAddress()+"\\"+dfs_dir.namespace+"\\"+dfs_dir.target; // for Windows + dfs_dir.unc_namespace_path = "\\\\"+remote_host.getAddress()+"\\"+dfs_dir.namespace; + dfs_dir.unc_target = "\\\\"+remote_host.getAddress()+"\\"+dfs_dir.target; + // + dfs_dir.url_path = "smb://"+remote_host.getAddress()+"/"+dfs_dir.namespace+"/"+dfs_dir.target; // for linux + dfs_dir.url_namespace_path = "smb://"+remote_host.getAddress()+"/"+dfs_dir.namespace; + dfs_dir.url_target = "smb://"+remote_host.getAddress()+"/"+dfs_dir.target; + } // end protected void makeShareName + + @Override + protected boolean createShareWindows(SMBStorageDir dir, ConsoleManager cm) throws Exception { + // create target share to create link to + if (!super.createShareWindows(dir, cm)) + return false; + DFSSMBStorageDir dfs_dir = (DFSSMBStorageDir) dir; + + // create namespace + if (!doCreateShareWindows(cm, dfs_dir.remote_namespace, dfs_dir.namespace)) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to create share for namespace!"); + + return false; + } + + if (!remote_host.execElevated("DFSUTIL ROOT ADDSTD "+dfs_dir.unc_namespace_path, Host.ONE_MINUTE*10).printOutputIfCrash(getClass(), cm).isSuccess()) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to create namespace!"); + + return false; + } + + // create 1 link to the 1 target + if (remote_host.execElevated("DFSUTIL LINK ADD "+dfs_dir.unc_path+" "+dfs_dir.unc_target, Host.ONE_MINUTE*10).printOutputIfCrash(getClass(), cm).isSuccess()) { + cm.println(EPrintType.IN_PROGRESS, getClass(), "DFS link created"); + + cm.println(EPrintType.COMPLETED_OPERATION, getClass(), "DFS Share created. Done. unc_path="); + + return true; + } else { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to add DFS link"); + + return false; + } + } // end protected boolean createShareWindows + + private boolean install_attempt, install_ok; + protected boolean installDFSFeature(ConsoleManager cm, Host local_host) { + if (install_attempt) + return install_ok; + install_attempt = true; + + StringBuilder ps_sb = new StringBuilder(); + ps_sb.append("Import-Module ServerManager\n"); + ps_sb.append("Add-WindowsFeature -name File-Services\n"); + ps_sb.append("Add-WindowsFeature -name FS-DFS\n"); + ps_sb.append("Add-WindowsFeature -name FS-DFS-Namespace\n"); + ps_sb.append("Add-WindowsFeature -name FS-DFS-Replication\n"); + + try { + TempFileExecOutput teo = remote_host.powershell(getClass(), cm, ps_sb, Host.FOUR_HOURS); + + if (teo.printOutputIfCrash(getClass(), cm).isSuccess()) { + teo.cleanup(remote_host); + + cm.println(EPrintType.COMPLETED_OPERATION, getName(), "DFS Feature Installed"); + + return install_ok = true; + } else { + cm.println(EPrintType.OPERATION_FAILED_CONTINUING, getName(), "can't exec powershell script: "+ps_sb); + } + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "installDFSFeature", ex, "", remote_host, ps_sb); + } + return install_ok = false; + } // end protected boolean installDFSFeature + + @Override + public boolean isImplemented() { + return true; + } + +} // end public class SMBDFSScenario diff --git a/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java b/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java index 43b54a3..cc8dc4f 100644 --- a/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java +++ b/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java @@ -1,5 +1,6 @@ package com.mostc.pftt.scenario; +import com.mostc.pftt.host.ExecOutput; import com.mostc.pftt.host.Host; import com.mostc.pftt.host.RemoteHost; import com.mostc.pftt.host.TempFileExecOutput; @@ -9,7 +10,10 @@ import com.mostc.pftt.results.ConsoleManager.EPrintType; /** Tests the new Remote Data Deduplication feature of Windows 2012 using SMB. * - * This feature broke PHP in php bug #63241. This scenario will catch that or any other problems Deduplication causes to PHP. + * This feature broke PHP in php bug #63241. This scenario will catch that or any other problems Deduplication causes for PHP. + * + * + * Typically, you'll create 1 instance of this for each remote file server, and each instance can create manage multiple shares at the same time. * * You can check if a file is deduplicated (on Windows) by running * `fsutil reparsepoint query [file]` @@ -28,7 +32,7 @@ public class SMBDeduplicationScenario extends AbstractSMBScenario { */ public SMBDeduplicationScenario(RemoteHost remote_host, String volume) { // making sure that non-null string passed prevents C:\ from being used (@see AbstractSMBScenario#<init>) - // important since the SystemDrive can't have deduplication enabled + // important since the SystemDrive(c:\) can't have deduplication enabled super(remote_host, volume, null); this.volume = volume; } @@ -45,34 +49,97 @@ public class SMBDeduplicationScenario extends AbstractSMBScenario { } @Override - public boolean setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { - return notifyPrepareStorageDir(cm, host); + public boolean setup(ConsoleManager cm, Host local_host, PhpBuild build, ScenarioSet scenario_set) { + return installDeduplicationFeature(cm, local_host) && super.setup(cm, local_host, build, scenario_set); } /** installs and enables deduplication on a remote disk Volume and creates a file share and connects to it. * * test-pack can then be installed on that file share. * - * @see #notifyTestPackInstalled * @param cm * @param local_host - * @return TRUE if success, FALSE if falure + * @return */ @Override - public boolean notifyPrepareStorageDir(ConsoleManager cm, Host local_host) { + public DeduplicatedSMBStorageDir createStorageDir(ConsoleManager cm, Host local_host) { // check that its win8 - System.out.println("64"); - // TODO - if (false) { // TODO !remote_host.isWin8OrLater()) { - System.out.println("66"); + if (!remote_host.isWin8OrLater()) { cm.println(EPrintType.XSKIP_OPERATION, getName(), "Scenario can only be run against a Windows 8/2012+ host"); - return false; + return null; } else if (volume.equals("C:")||remote_host.getSystemDrive().equalsIgnoreCase(volume)) { - System.out.println("70"); cm.println(EPrintType.XSKIP_OPERATION, getName(), "Can not use Deduplication on a Windows System Drive (ex: C:\\)"); + return null; + } + + if (installDeduplicationFeature(cm, local_host)) { + // create share on deduplicated volume + DeduplicatedSMBStorageDir dir = (DeduplicatedSMBStorageDir) super.createStorageDir(cm, local_host); + if (dir!=null) { + + cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Deduplication enabled for Share: unc="+dir.unc_path+" local="+dir.local_path+" url="+dir.url_path); + + return dir; + } + } + return null; + } // end public DeduplicatedSMBStorageDir createStorageDir + + protected DeduplicatedSMBStorageDir newSMBStorageDir() { + return new DeduplicatedSMBStorageDir(); + } + + public class DeduplicatedSMBStorageDir extends SMBStorageDir { + + /** runs a deduplication job after the test-pack is installed, blocking until the deduplication job is done. + * + * @param cm + * @param local_host + */ + @Override + public boolean notifyTestPackInstalled(ConsoleManager cm, Host local_host) { + try { + // run deduplication job (on test-pack) -wait for completion + cm.println(EPrintType.IN_PROGRESS, getName(), "Running deduplication job... unc="+unc_path+" local="+local_path+" remote_file="+remote_path+" url="+url_path); + if (remote_host.powershell(getClass(), cm, "Start-Dedupjob -Volume "+volume+" -Type Optimization", Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess()) { + + // + // log REPARSEPOINT QUERY to show if reparse point/deduplication was really setup + try { + int count = 0; + // pick a few files/folders... doing the share itself won't find a reparsepoint + for ( String file : remote_host.list(remote_path) ) { + ExecOutput out = remote_host.exec("FSUTIL REPARSEPOINT QUERY "+remote_path+"\\"+file, Host.ONE_MINUTE); + cm.println(EPrintType.CLUE, getName(), "REPARSEPOINT QUERY: "+remote_path+"\\"+file+"\n"+out.output); + + if (count++>3) + break; + } + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CLUE, getName(), ex, "reparsepoint query exception. ignoring, continuing..."); + } + // + // + + cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Deduplication completed successfully. unc="+unc_path+" local="+local_path+" remote_file="+remote_path+" url="+url_path); + return true; + } else { + cm.println(EPrintType.OPERATION_FAILED_CONTINUING, getName(), "Deduplication failed"); + } + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CANT_CONTINUE, getName(), ex, "Deduplication failed", remote_host, local_host, volume); + } return false; } - System.out.println("74"); + + } // end public class DeduplicatedSMBStorageDir + + private boolean install_attempt, install_ok; + protected boolean installDeduplicationFeature(ConsoleManager cm, Host local_host) { + if (install_attempt) + return install_ok; + install_attempt = true; + StringBuilder ps_sb = new StringBuilder(128); // install deduplication feature ps_sb.append("Import-Module ServerManager\n"); @@ -81,52 +148,27 @@ public class SMBDeduplicationScenario extends AbstractSMBScenario { ps_sb.append("Import-Module Deduplication\n"); // enable deduplication for volume ps_sb.append("Enable-DedupVolume ");ps_sb.append(volume);ps_sb.append("\n"); - // change min file age (default is 5 days which will prevent testing test-packs now) + // CRITICAL: change min file age (default is 5 days which will prevent testing test-packs NOW) ps_sb.append("Set-DedupVolume ");ps_sb.append(volume);ps_sb.append(" -MinimumFileAgeDays 0\n"); // create PowerShell script to install and enable deduplication try { // - System.out.println("89"); - cm.println(EPrintType.IN_PROGRESS, getName(), "Starting to enable Deduplication on: "+remote_host); + cm.println(EPrintType.IN_PROGRESS, getName(), "Starting to Install Deduplication on: "+remote_host); TempFileExecOutput teo = remote_host.powershell(getClass(), cm, ps_sb, Host.ONE_MINUTE * 10); if (teo.printOutputIfCrash(getClass(), cm).isSuccess()) { // don't delete tmp_file if it failed to help user see why teo.cleanup(remote_host); - } - - // create share on volume - if (super.notifyPrepareStorageDir(cm, local_host)) { - cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Deduplication enabled on share: unc="+unc_path+" local="+local_path+" url="+url_path); - return true; - } - } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.CANT_CONTINUE, getClass(), "notifyPrepareStorageDir", ex, "Unable to enable deduplication", remote_host, ps_sb); - } - return false; - } // end public boolean notifyPrepareStorageDir - - /** runs a deduplication job after the test-pack is installed, blocking until the deduplication job is done. - * - * @param cm - * @param local_host - */ - @Override - public boolean notifyTestPackInstalled(ConsoleManager cm, Host local_host) { - try { - // run deduplication job (on test-pack) -wait for completion - cm.println(EPrintType.IN_PROGRESS, getName(), "Running deduplication job... unc="+unc_path+" local="+local_path+" remote_file="+remote_path+" url="+url_path); - if (remote_host.powershell(getClass(), cm, "Start-Dedupjob -Volume "+volume+" -Type Optimization", Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess()) { - cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Deduplication completed successfully. unc="+unc_path+" local="+local_path+" remote_file="+remote_path+" url="+url_path); - return true; - } else { - cm.println(EPrintType.OPERATION_FAILED_CONTINUING, getName(), "Deduplication failed"); + + cm.println(EPrintType.IN_PROGRESS, getName(), "Deduplication Feature Installed."); + + return install_ok = true; } } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.CANT_CONTINUE, getClass(), "notifyTestPackInstalled", ex, "Deduplication failed", remote_host, local_host, volume); + cm.addGlobalException(EPrintType.CANT_CONTINUE, getName(), ex, "Unable to Install Deduplication feature", remote_host, ps_sb); } - return false; - } // end public boolean notifyTestPackInstalled + return install_ok = false; + } // end protected boolean installDeduplicationFeature @Override public String getName() { diff --git a/src/com/mostc/pftt/scenario/SOAPScenario.java b/src/com/mostc/pftt/scenario/SOAPScenario.java index ce9959e..577fe09 100644 --- a/src/com/mostc/pftt/scenario/SOAPScenario.java +++ b/src/com/mostc/pftt/scenario/SOAPScenario.java @@ -6,7 +6,7 @@ package com.mostc.pftt.scenario; * */ -public class SOAPScenario extends AbstractParallelScenario { +public class SOAPScenario extends AbstractNetworkedServiceScenario { @Override public String getName() { diff --git a/src/com/mostc/pftt/scenario/XMLRPCScenario.java b/src/com/mostc/pftt/scenario/XMLRPCScenario.java index 173d0fa..1947be9 100644 --- a/src/com/mostc/pftt/scenario/XMLRPCScenario.java +++ b/src/com/mostc/pftt/scenario/XMLRPCScenario.java @@ -6,7 +6,7 @@ package com.mostc.pftt.scenario; * */ -public class XMLRPCScenario extends AbstractParallelScenario { +public class XMLRPCScenario extends AbstractNetworkedServiceScenario { @Override public String getName() {
diff --git a/.gitignore b/.gitignore index fcb3025..2982736 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ build/* conf/internal/* src/com/sshtools/* +hostkeys.txt +ssh_server.jar diff --git a/bin/7z.exe b/bin/7z.exe new file mode 100644 index 0000000..101884c Binary files /dev/null and b/bin/7z.exe differ diff --git a/doc/ssh_server.fatjar b/doc/ssh_server.fatjar new file mode 100644 index 0000000..206137c --- /dev/null +++ b/doc/ssh_server.fatjar @@ -0,0 +1,14 @@ +#Fat Jar Configuration File +#Mon Jan 21 13:10:29 PST 2013 +onejar.license.required=true +manifest.classpath= +manifest.removesigners=true +onejar.checkbox=false +jarname=ssh_server.jar +manifest.mergeall=true +manifest.mainclass=com.mostc.pftt.main.SSHServer +manifest.file=<createnew> +jarname.isextern=false +onejar.expand= +excludes=<jar|htmlcleaner-2.2.jar>;<jar|groovy-1.8.6.jar>;<jar|icu4j-49_1.jar>;<jar|icudata.jar>;<jar|icutzdata.jar>;<jar|jansi-1.7.jar>;<jar|jline-0.9.94.jar>;<jar|selenium-server-standalone-2.19.0.jar>;<jar|xercesImpl.jar>;<jar|xmlpull-1.1.3.1.jar>;<jar|commons-cli-1.2.jar>;<jar|antlr-2.7.7.jar>;<jar|asm-3.2.jar>;<jar|asm-analysis-3.2.jar>;<jar|asm-commons-3.2.jar>;<jar|asm-util-3.2.jar> +includes= diff --git a/src/com/mostc/pftt/host/ExecOutput.java b/src/com/mostc/pftt/host/ExecOutput.java index e571454..64618e7 100644 --- a/src/com/mostc/pftt/host/ExecOutput.java +++ b/src/com/mostc/pftt/host/ExecOutput.java @@ -13,6 +13,7 @@ public class ExecOutput { public Charset charset; /** exit code for program. if 0, program exited successfully */ public int exit_code; + public String cmd; /** returns the output split into lines. * @@ -51,7 +52,7 @@ public class ExecOutput { if (ps!=null && isCrashed()) { String output_str = output.trim(); if (StringUtil.isEmpty(output_str)) - output_str = "<Crash with no output. exit_code="+exit_code+">"; + output_str = "<Crash with no output. exit_code="+exit_code+" cmd="+cmd+">"; ps.println(ctx+": "+output_str); } diff --git a/src/com/mostc/pftt/host/Host.java b/src/com/mostc/pftt/host/Host.java index b56b485..a5433fd 100644 --- a/src/com/mostc/pftt/host/Host.java +++ b/src/com/mostc/pftt/host/Host.java @@ -141,13 +141,28 @@ public abstract class Host { if (os_name!=null) return os_name; - os_name = getOSNameLong(); - - os_name.replaceAll("Windows", "Win"); + os_name = shortenOSName(getOSNameLong()); return os_name; } + public static String shortenOSName(String os_name) { + os_name = os_name.replace("Microsoft", ""); + os_name = os_name.replace("Server", ""); + os_name = os_name.replace("Datacenter", ""); + os_name = os_name.replace("Enterprise", ""); + os_name = os_name.replace("Standard", ""); + os_name = os_name.replace("Professional", ""); + os_name = os_name.replace("Home", ""); + os_name = os_name.replace("Basic", ""); + // + os_name = os_name.replace(" ", " "); + os_name = os_name.replace(" ", " "); + os_name = os_name.replace(" ", " "); + os_name = os_name.replace(" ", " "); + return os_name.trim(); + } + /** returns the OS name with whatever platform specific info in the platform specific format * * @see #getOSName @@ -319,13 +334,21 @@ public abstract class Host { * * This will improve performance for a few large files or a lots of small files. * + * @param cm + * @param ctx_str + * @param src_host * @param src * @param dst * @throws IllegalStateException * @throws IOException * @throws Exception */ - public abstract void downloadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception; + public abstract void downloadCompressWith7Zip(ConsoleManager cm, String ctx_str, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception; + + public void downloadCompressWith7Zip(ConsoleManager cm, Class<?> clazz, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception { + downloadCompressWith7Zip(cm, clazz.getSimpleName(), src_host, src, dst); + } + /** downloads file from remote source to local destination * * @param src @@ -339,13 +362,20 @@ public abstract class Host { * * This will improve performance for a few large files or a lots of small files. * + * @param cm + * @param ctx * @param src + * @param dst_host * @param dst * @throws IllegalStateException * @throws IOException * @throws Exception */ - public abstract void uploadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception; + public abstract void uploadCompressWith7Zip(ConsoleManager cm, String ctx_str, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception; + + public void uploadCompressWith7Zip(ConsoleManager cm, Class<?> ctx, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception { + uploadCompressWith7Zip(cm, ctx.getSimpleName(), src, dst_host, dst); + } /** Uploads file from local source to remote destination * * @param src @@ -656,32 +686,117 @@ public abstract class Host { return StringUtil.replaceAll(PAT_fs, "/", StringUtil.replaceAll(PAT_bs, "/", name)); } + public void upload7ZipAndDecompress(ConsoleManager cm, Class<?> clazz, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception { + upload7ZipAndDecompress(cm, clazz.getSimpleName(), src_host, src, dst); + } + + public void download7ZipAndDecompress(ConsoleManager cm, Class<?> clazz, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception { + download7ZipAndDecompress(cm, clazz.getSimpleName(), src, dst_host, dst); + } + /** uploads a 7zip file from local source to remote destination and decompresses it. * * Assumes local source is already a 7zip file, while #uploadCompressWith7Zip does the compression itself * + * @param cm + * @param ctx_str + * @param src_host * @param src * @param dst * @throws IllegalStateException * @throws IOException * @throws Exception */ - public void upload7ZipAndDecompress(String src, String dst) throws IllegalStateException, IOException, Exception { - // TODO + public void upload7ZipAndDecompress(ConsoleManager cm, String ctx_str, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, src_host); + + String dst_7zip_file = mktempname(ctx_str, ".7z"); + + upload(src, dst_7zip_file); + + decompress(cm, src_host, dst_7zip_file, dst); + + delete(dst_7zip_file); } /** Downloads remote 7Zip file to local destination and decompresses it. * * Assumes remote source is already a 7zip file. * + * @param cm + * @param ctx_str * @param src + * @param dst_host * @param dst * @throws IllegalStateException * @throws IOException * @throws Exception */ - public void download7ZipAndDecompress(String src, String dst) throws IllegalStateException, IOException, Exception { - // TODO + public void download7ZipAndDecompress(ConsoleManager cm, String ctx_str, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, dst_host); + + String dst_7zip_file = dst_host.mktempname(ctx_str, ".7z"); + + download(src, dst_7zip_file); + + dst_host.decompress(cm, this, dst_7zip_file, dst); + + dst_host.delete(dst_7zip_file); + } + + private boolean install_7zip_attempt; + protected void ensure7Zip(ConsoleManager cm, Host ohost) throws Exception { + if (install_7zip_attempt) + return; + install_7zip_attempt = true; + if (ohost.isRemote() == this.isRemote()) { + // no host with 7zip + cm.println(EPrintType.CLUE, getClass(), "No host found with a copy of 7z.exe!"); + } else if (ohost.isRemote()) { + install7Zip(cm, this, ohost); + } else { + install7Zip(cm, ohost, this); + } + } + + private static void install7Zip(ConsoleManager cm, Host src_host, Host dst_host) throws Exception { + final String dst_7z_path = dst_host.getPfttDir()+"\\bin\\7z.exe"; + + if (dst_host.exists(dst_7z_path)) { + cm.println(EPrintType.CLUE, "install7Zip", "7z.exe already installed on: "+dst_host); + return; + } + + final String src_7z_path = src_host.getPfttDir()+"\\bin\\7z.exe"; + if (!src_host.exists(src_7z_path)) { + cm.println(EPrintType.CLUE, "install7Zip", "7z.exe not found on source: "+src_host); + return; + } + + try { + dst_host.upload(src_7z_path, dst_7z_path); + + cm.println(EPrintType.CLUE, "install7Zip", "7z.exe installed on: "+dst_host+" (src="+src_host+")"); + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CLUE, "install7Zip", ex, "Unable to install 7z.exe on dst="+dst_host+" from src="+src_host); + + throw ex; + } + } // end private static void install7Zip + + public void decompress(ConsoleManager cm, Host ohost, String zip7_file, String dst) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, ohost); + + String base_dir = Host.basename(dst); + mkdirs(base_dir); + + exec(getPfttDir()+"\\bin\\7z x -bd -y "+zip7_file, Host.FOUR_HOURS, base_dir); + } + + public void compress(ConsoleManager cm, Host ohost, String src, String zip7_file) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, ohost); + + exec(getPfttDir()+"\\bin\\7z a -bd "+zip7_file+" "+src, Host.FOUR_HOURS, src); } /** gets a string of info about the host @@ -778,40 +893,39 @@ public abstract class Host { if (!isWindows()) return false; String os_name = getOSNameOnWindows(); - return os_name.contains("Windows Vista") || os_name.contains("Windows 2008 ") || os_name.contains("Windows 2008r2") || os_name.contains("Windows 7") || os_name.contains("Windows 8") || os_name.contains("Windows 2012"); + return os_name.contains("Windows Vista") || os_name.contains("Windows 2008") || os_name.contains("Windows 2008") || os_name.contains("Windows 7") || os_name.contains("Windows 8") || os_name.contains("Windows 2012") || os_name.contains("Windows 9"); } public boolean isBeforeVista() { if (!isWindows()) return false; String os_name = getOSNameOnWindows(); - return os_name.contains("Windows XP") || os_name.contains("Windows 2003 ") || os_name.contains("Windows 2000"); + return os_name.contains("Windows XP") || os_name.contains("Windows 2003") || os_name.contains("Windows 2000"); } public boolean isVistaOrBefore() { if (!isWindows()) return false; String os_name = getOSNameOnWindows(); - return os_name.contains("Windows Vista") || os_name.contains("Windows 2008 ") || os_name.contains("Windows 2003") || os_name.contains("Windows XP"); + return os_name.contains("Windows Vista") || os_name.contains("Windows 2008") || os_name.contains("Windows 2003") || os_name.contains("Windows XP"); } public boolean isVistaExact() { if (!isWindows()) return false; - String os_name = getOSNameOnWindows(); + String os_name = getOSName(); // technically Vista SP0 != 2008 RTM but Vista SP1 == 2008 RTM and Vista SP2 == 2008sp2 // thats why 2008 RTM is often referred to as 2008sp1 (1 service pack for 2008 after RTM, which is // 2008sp2, so there are 2 versions of Windows 2008, 2008sp1 and 2008sp2) - return os_name.contains("Windows Vista") || os_name.contains("Windows 2008 "); + return os_name.contains("Windows Vista") || os_name.contains("Windows 2008"); } public boolean isWin8Exact() { if (!isWindows()) return false; - String os_name = getOSNameOnWindows(); + String os_name = getOSName(); return os_name.contains("Windows 8") || os_name.contains("Windows 2012"); } public boolean isWin8OrLater() { if (!isWindows()) return false; - String os_name = getOSNameOnWindows(); - System.out.println(os_name); + String os_name = getOSName(); return os_name.contains("Windows 8") || os_name.contains("Windows 2012") || os_name.contains("Windows 9") || os_name.contains("Windows 2014"); } diff --git a/src/com/mostc/pftt/host/LocalHost.java b/src/com/mostc/pftt/host/LocalHost.java index cacccb0..a379df2 100644 --- a/src/com/mostc/pftt/host/LocalHost.java +++ b/src/com/mostc/pftt/host/LocalHost.java @@ -35,6 +35,7 @@ import com.github.mattficken.io.IOUtil; import com.github.mattficken.io.MultiCharsetByLineReader; import com.github.mattficken.io.NoCharsetByLineReader; import com.mostc.pftt.model.phpt.PhptTestCase; +import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.runner.AbstractTestPackRunner.TestPackRunnerThread; import com.mostc.pftt.util.StringUtil; import com.sun.jna.Pointer; @@ -186,6 +187,7 @@ public class LocalHost extends Host { task.cancel(); ExecOutput out = new ExecOutput(); + out.cmd = commandline; out.output = eh.getOutput(); out.charset = eh.charset; out.exit_code = eh.getExitCode(); @@ -636,7 +638,7 @@ public class LocalHost extends Host { } @Override - public void downloadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception { + public void downloadCompressWith7Zip(ConsoleManager cm, String ctx_str, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception { download(src, dst); } @@ -646,7 +648,7 @@ public class LocalHost extends Host { } @Override - public void uploadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception { + public void uploadCompressWith7Zip(ConsoleManager cm, String ctx_str, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception { upload(src, dst); } diff --git a/src/com/mostc/pftt/host/RemoteHost.java b/src/com/mostc/pftt/host/RemoteHost.java index 9613ce6..29d0aca 100644 --- a/src/com/mostc/pftt/host/RemoteHost.java +++ b/src/com/mostc/pftt/host/RemoteHost.java @@ -2,7 +2,7 @@ package com.mostc.pftt.host; import java.io.IOException; -import com.mostc.pftt.util.StringUtil; +import com.mostc.pftt.results.ConsoleManager; public abstract class RemoteHost extends Host { @@ -14,7 +14,7 @@ public abstract class RemoteHost extends Host { // look for line like: `OS Name: Windows 7 Ultimate` for ( String line : getSystemInfoLines() ) { if (line.startsWith("OS Name:")) { - return StringUtil.join(StringUtil.splitWhitespace(line), 1, " "); + return line.substring("OS Name:".length()).trim(); } } } catch ( Exception ex ) { @@ -36,15 +36,41 @@ public abstract class RemoteHost extends Host { } @Override - public void downloadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception { - // TODO Auto-generated method stub + public void downloadCompressWith7Zip(ConsoleManager cm, String ctx_str, Host src_host, String src, String dst) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, src_host); + src_host.ensure7Zip(cm, this); + String src_zip7_file = src_host.mktempname(ctx_str, ".7z"); + + String dst_zip7_file = mktempname(ctx_str, ".7z"); + + src_host.compress(cm, this, src, src_zip7_file); + + upload(src_zip7_file, dst_zip7_file); + + decompress(cm, src_host, dst_zip7_file, dst); + + src_host.delete(src_zip7_file); + delete(dst_zip7_file); } @Override - public void uploadCompressWith7Zip(String src, String dst) throws IllegalStateException, IOException, Exception { - // TODO Auto-generated method stub + public void uploadCompressWith7Zip(ConsoleManager cm, String ctx_str, String src, Host dst_host, String dst) throws IllegalStateException, IOException, Exception { + ensure7Zip(cm, dst_host); + dst_host.ensure7Zip(cm, this); + + String src_zip7_file = mktempname(ctx_str, ".7z"); + + String dst_zip7_file = dst_host.mktempname(ctx_str, ".7z"); + + compress(cm, dst_host, src, src_zip7_file); + + download(src_zip7_file, dst_zip7_file); + + dst_host.decompress(cm, this, dst_zip7_file, dst); + dst_host.delete(dst_zip7_file); + delete(src_zip7_file); } } // end public abstract class RemoteHost diff --git a/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java b/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java index 3eb59fb..c1b3260 100644 --- a/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java +++ b/src/com/mostc/pftt/host/RemotePhptTestPackRunner.java @@ -158,7 +158,7 @@ public class RemotePhptTestPackRunner extends PhptTestPackRunner { @Override public void runAllTests(PhptSourceTestPack test_pack) throws FileNotFoundException, IOException, Exception { - PhptActiveTestPack active_test_pack = test_pack.install(this.host, remote_host.getPhpSdkDir()+"/Remote"); + PhptActiveTestPack active_test_pack = test_pack.install(tmgr.getConsoleManager(), this.host, remote_host.getPhpSdkDir()+"/Remote"); commonRunStart(); sendTestPack(active_test_pack); diff --git a/src/com/mostc/pftt/host/SSHHost.java b/src/com/mostc/pftt/host/SSHHost.java index 04dd4bb..e4e1372 100644 --- a/src/com/mostc/pftt/host/SSHHost.java +++ b/src/com/mostc/pftt/host/SSHHost.java @@ -82,6 +82,8 @@ import com.sshtools.j2ssh.transport.publickey.SshPublicKey; * */ +// TODO 7zip compress test-pack and upload +// -don't include skip or xskip tests (save bandwidth/time) public class SSHHost extends RemoteHost { private static final Timer timer = new Timer(); protected String address, hostname; @@ -404,10 +406,10 @@ public class SSHHost extends RemoteHost { } // end protected static class SSHExecHandle @Override - public ExecOutput exec(String cmd, int timeout, Map<String, String> env, byte[] stdin_post, Charset charset, String chdir, final TestPackRunnerThread thread, int thread_slow_sec) throws Exception { - ByteArrayIOStream out = new ByteArrayIOStream(1024); + public ExecOutput exec(final String cmd, int timeout, Map<String, String> env, byte[] stdin_post, Charset charset, String chdir, final TestPackRunnerThread thread, int thread_slow_sec) throws Exception { + final ByteArrayIOStream out = new ByteArrayIOStream(1024); - ExecOutput eo = new ExecOutput(); + final ExecOutput eo = new ExecOutput(); // final AtomicBoolean run = new AtomicBoolean(true); @@ -457,6 +459,7 @@ public class SSHHost extends RemoteHost { session.getState().waitForState(ChannelState.CHANNEL_CLOSED); // + eo.cmd = cmd; eo.exit_code = session.getExitCode(); /* TODO if (reader instanceof AbstractDetectingCharsetReader) eo.charset = ((AbstractDetectingCharsetReader)reader).cs; */ diff --git a/src/com/mostc/pftt/main/PfttMain.java b/src/com/mostc/pftt/main/PfttMain.java index 94b8987..6ce019a 100644 --- a/src/com/mostc/pftt/main/PfttMain.java +++ b/src/com/mostc/pftt/main/PfttMain.java @@ -34,7 +34,7 @@ import com.mostc.pftt.model.smoke.ESmokeTestStatus; import com.mostc.pftt.model.smoke.PhptTestCountsMatchSmokeTest; import com.mostc.pftt.model.smoke.RequiredExtensionsSmokeTest; import com.mostc.pftt.model.smoke.RequiredFeaturesSmokeTest; -import com.mostc.pftt.report.AUTReportGen; +import com.mostc.pftt.report.ABCReportGen; import com.mostc.pftt.report.AbstractReportGen; import com.mostc.pftt.report.FBCReportGen; import com.mostc.pftt.results.ConsoleManager; @@ -46,10 +46,11 @@ import com.mostc.pftt.runner.PhpUnitTestPackRunner; import com.mostc.pftt.runner.LocalPhptTestPackRunner; import com.mostc.pftt.runner.PhptTestPackRunner; import com.mostc.pftt.scenario.AbstractSAPIScenario; -import com.mostc.pftt.scenario.SMBDFSRScenario; +import com.mostc.pftt.scenario.SMBDFSScenario; import com.mostc.pftt.scenario.SMBDeduplicationScenario; import com.mostc.pftt.scenario.Scenario; import com.mostc.pftt.scenario.ScenarioSet; +import com.mostc.pftt.scenario.AbstractSMBScenario.SMBStorageDir; import com.mostc.pftt.util.DownloadUtil; import com.mostc.pftt.util.HostEnvUtil; import com.mostc.pftt.util.StringUtil; @@ -66,6 +67,9 @@ import com.mostc.pftt.util.WindowsSnapshotDownloadUtil.FindBuildTestPackPair; */ // TODO phpt_all, etc... should display location of result-pack being written +// XXX ? only compress .xml result files that are for FAIL or XFAIL_WORKS or CRASH or TEST_EXPCEPTION +// -then discard if PASS, SKIP or XSKIP +// -would still save list of tests for each status public class PfttMain { protected Host host; @@ -284,6 +288,7 @@ public class PfttMain { } protected static void cmd_aut(ConsoleManager cm, PfttMain rt, Host host, PhpBuild build, Collection<ScenarioSet> scenario_sets) throws IllegalStateException, IOException, Exception { + /* new PhpUnitTestPackRunner(PhpUnitAppTestPack.load("/"), scenario_sets.iterator().next(), build, host); host.upload7ZipAndDecompress(host.getPfttDir()+"/cache/cache.7z", ""); @@ -294,7 +299,8 @@ public class PfttMain { host.getContents(tmp_file); // for now, don't delete tmp_file - rt.show_report(cm, new AUTReportGen(new File(tmp_file), host.getOSName())); + rt.show_report(cm, new ABCReportGen(new File(tmp_file), host.getOSName())); + */ } protected static void cmd_shell_ui() { @@ -723,18 +729,15 @@ public class PfttMain { LocalConsoleManager cm = new LocalConsoleManager(source_pack, debug_pack, force, windebug, results_only, show_gui, disable_debug_prompt, dont_cleanup_test_pack, phpt_not_in_place, pftt_debug); - // TODO + // /* - SSHHost remote_host = new SSHHost("10.200.41.219", "administrator", "password01!"); + SSHHost remote_host = new SSHHost("10.200.48.119", "administrator", "password01!"); System.out.println(remote_host.isWindows()); - System.out.println("729"); - remote_host.exec("systeminfo", Host.ONE_MINUTE); - System.out.println("731"); //SMBDeduplicationScenario d = new SMBDeduplicationScenario(remote_host, "F:"); - SMBDFSRScenario d = new SMBDFSRScenario(remote_host); - System.out.println("731"); - System.out.println(d.notifyPrepareStorageDir(cm, rt.host)); - d.notifyTestPackInstalled(cm, rt.host); + SMBDFSScenario d = new SMBDFSScenario(remote_host); + SMBStorageDir dir = d.createStorageDir(cm, rt.host); + System.out.println(dir.getLocalPath(rt.host)); + System.out.println(dir.notifyTestPackInstalled(cm, rt.host)); System.exit(0); */ diff --git a/src/com/mostc/pftt/model/performance/DrupalPerformanceTest.java b/src/com/mostc/pftt/model/performance/DrupalPerformanceTest.java deleted file mode 100644 index 5920fd2..0000000 --- a/src/com/mostc/pftt/model/performance/DrupalPerformanceTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mostc.pftt.model.performance; - -public class DrupalPerformanceTest extends PerformanceTest { - - @Override - public String getName() { - return "Drupal-PerformanceTest"; - } - -} diff --git a/src/com/mostc/pftt/model/performance/HelloWorldPerformanceTest.java b/src/com/mostc/pftt/model/performance/HelloWorldPerformanceTest.java deleted file mode 100644 index 78f8d7a..0000000 --- a/src/com/mostc/pftt/model/performance/HelloWorldPerformanceTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mostc.pftt.model.performance; - -public class HelloWorldPerformanceTest extends PerformanceTest { - - @Override - public String getName() { - return "HelloWorld-PerformanceTest"; - } - -} diff --git a/src/com/mostc/pftt/model/performance/JoomlaPerformanceTest.java b/src/com/mostc/pftt/model/performance/JoomlaPerformanceTest.java deleted file mode 100644 index ce9e371..0000000 --- a/src/com/mostc/pftt/model/performance/JoomlaPerformanceTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mostc.pftt.model.performance; - -public class JoomlaPerformanceTest extends PerformanceTest { - - @Override - public String getName() { - return "Joomla-Performance"; - } - -} diff --git a/src/com/mostc/pftt/model/performance/MediaWikiPerformanceTest.java b/src/com/mostc/pftt/model/performance/MediaWikiPerformanceTest.java deleted file mode 100644 index 4679727..0000000 --- a/src/com/mostc/pftt/model/performance/MediaWikiPerformanceTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mostc.pftt.model.performance; - -public class MediaWikiPerformanceTest extends PerformanceTest { - - @Override - public String getName() { - return "MediaWiki-PerformanceTest"; - } - -} diff --git a/src/com/mostc/pftt/model/performance/WCATDrupalTest.groovy b/src/com/mostc/pftt/model/performance/WCATDrupalTest.groovy new file mode 100644 index 0000000..e05f198 --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATDrupalTest.groovy @@ -0,0 +1,193 @@ +package com.mostc.pftt.model.performance; + +/** WCAT based performance testing. + * + * Based on AutoCAT (Powershell) + * + * @see https://github.com/OSTC/php-perf + * + */ + +class WCATDrupalTest extends WCATPerformanceTest { + + @Override + public String getName() { + return "WCAT-Drupal"; + } + + @Override + String writeWCATSettings(String scenario_file, int virtual_clients) { +""" +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // clientfile = "test.wcat"; + // server = "131.107.145.189,131.107.145.190"; + // clients = 2; + // virtualclients = 4; + // bind = "131.107.145.189,w2k3-load16"; + // bind = "w2k3-load15,131.107.145.190"; + // + //-------------------------------------------------------------------------- + + virtualclients = $virtual_clients; + clientfile = "$scenario_file"; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} +""" + } // end String writeWCATSettings + + @Override + String writeWCATScenario() { +""" +scenario +{ + name = "Drupal"; + + warmup = 20; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + transaction + { + id = "Web Site Homepage"; + weight = 1; + + request + { + url = "/drupal/index.php"; + statuscode = 200; + //cookies = false; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = ka; + } + } +}""" + } // end String writeWCATScenario + +} // end class WCATDrupalTest diff --git a/src/com/mostc/pftt/model/performance/WCATHelloWorldTest.groovy b/src/com/mostc/pftt/model/performance/WCATHelloWorldTest.groovy new file mode 100644 index 0000000..74c7ad4 --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATHelloWorldTest.groovy @@ -0,0 +1,186 @@ +package com.mostc.pftt.model.performance; + +class WCATHelloWorldTest extends WCATPerformanceTest { + + @Override + public String getName() { + return "WCAT-HelloWorld"; + } + + @Override + String writeWCATScenario() { +""" +scenario +{ + name = "Helloworld"; + + warmup = 20; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + transaction + { + id = "Web Site Homepage"; + weight = 1; + + request + { + url = "/helloworld.php"; + statuscode = 200; + //cookies = false; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = ka; + } + } +} +""" + } // end String writeWCATScenario + + @Override + String writeWCATSettings(String scenario_file, int virtual_clients) { +""" +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // clientfile = "test.wcat"; + // server = "131.107.145.189,131.107.145.190"; + // clients = 2; + // virtualclients = 4; + // bind = "131.107.145.189,w2k3-load16"; + // bind = "w2k3-load15,131.107.145.190"; + // + //-------------------------------------------------------------------------- + + virtualclients = $virtual_clients; + clientfile = "$scenario_file"; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} +""" + } // end String writeWCATSettings + +} // end class WCATHelloWorldTest diff --git a/src/com/mostc/pftt/model/performance/WCATJoomlaTest.groovy b/src/com/mostc/pftt/model/performance/WCATJoomlaTest.groovy new file mode 100644 index 0000000..ee50bb7 --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATJoomlaTest.groovy @@ -0,0 +1,186 @@ +package com.mostc.pftt.model.performance; + +class WCATJoomlaTest extends WCATPerformanceTest { + + @Override + public String getName() { + return "WCAT-Joomla"; + } + + @Override + String writeWCATScenario() { +""" +scenario +{ + name = "Joomla"; + + warmup = 20; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + transaction + { + id = "Web Site Homepage"; + weight = 1; + + request + { + url = "/joomla/index.php"; + statuscode = 200; + //cookies = false; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = ka; + } + } +} +""" + } // end String writeWCATScenario + + @Override + String writeWCATSettings(String scenario_file, int virtual_clients) { +""" +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // clientfile = "test.wcat"; + // server = "131.107.145.189,131.107.145.190"; + // clients = 2; + // virtualclients = 4; + // bind = "131.107.145.189,w2k3-load16"; + // bind = "w2k3-load15,131.107.145.190"; + // + //-------------------------------------------------------------------------- + + virtualclients = $virtual_clients; + clientfile = "$scenario_file"; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} +""" + } // end String writeWCATSettings + +} // end class WCATJoomlaTest diff --git a/src/com/mostc/pftt/model/performance/WCATMediaWikiTest.groovy b/src/com/mostc/pftt/model/performance/WCATMediaWikiTest.groovy new file mode 100644 index 0000000..939e8d7 --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATMediaWikiTest.groovy @@ -0,0 +1,185 @@ +package com.mostc.pftt.model.performance; + +class WCATMediaWikiTest extends WCATPerformanceTest { + + @Override + public String getName() { + return "WCAT-MediaWiki"; + } + + @Override + String writeWCATScenario() { +""" +scenario +{ + name = "Mediawiki"; + + warmup = 20; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + transaction + { + id = "Web Site Homepage"; + weight = 1; + + request + { + url = "/mediawiki/index.php?title=Main_Page"; + statuscode = 200; + //cookies = false; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = ka; + } + } +} +""" + } // end String writeWCATScenario + + @Override + String writeWCATSettings(String scenario_file, int virtual_clients) { +""" +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // clientfile = "test.wcat"; + // server = "131.107.145.189,131.107.145.190"; + // clients = 2; + // virtualclients = 4; + // bind = "php-load01,php-load02"; + // + //-------------------------------------------------------------------------- + + virtualclients = $virtual_clients; + clientfile = "$scenario_file"; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} +""" + } // end String writeWCATSettings + +} // end class WCATMediaWikiTest diff --git a/src/com/mostc/pftt/model/performance/WCATPerformanceTest.groovy b/src/com/mostc/pftt/model/performance/WCATPerformanceTest.groovy new file mode 100644 index 0000000..e11602c --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATPerformanceTest.groovy @@ -0,0 +1,223 @@ +package com.mostc.pftt.model.performance; + +import com.mostc.pftt.host.Host; + +abstract class WCATPerformanceTest extends PerformanceTest { + + protected abstract String writeWCATSettings(String scenario_file, int virtual_clients); + protected abstract String writeWCATScenario(); + + String set_file, scenario_file + void runTest() { + + } + + void prepareWCAT(Host host) { + set_file = host.mktempname(getClass(), ".wcat"); + + scenario_file = host.mktempname(getClass(), ".wcat"); + + writeWCATScenario(); + + writeWCATSettings(scenario_file, 4); // TODO specify virtual clients (4, 8, 16, or 32) + + // TODO write strings to files + } + + void cleanupWCAT() { + + } + + void runWCAT(Host host) { +/* +// hostnames to run wcat clients on +// $CLIENTS = "php-load01,php-load02" +// $SETFILE = writeWCATSettings +// $OUT_FILE = temp file to write summary to +// hostname of target web server +// $SERVER = "php-web01" +// $_ +// + c:\wcat\wcat.wsf -terminate -run -v $_ -clients $CLIENTS -f $SETFILE -s $SERVER -o $OUT_FILE +*/ + } + + void readWCATSummary() { +/* +#%powershell1.0% +# +# File: summarize-results.ps1 +# Description: Summarize the results output by wcat_run.ps1 and output them into an HTML-formatted file. +# +# Example Usage: +# c:\> summarize-results.ps1 -PHP1 5.3.8 -PHP2 5.4.0B2 -VIRTUAL "8,16,32" +# + +Param($PHP1="", $PHP2="", $VIRTUAL="8,16,32") + +Set-Location c:\wcat +$results = 'c:/wcat/results/' +$errlog = "" +$VIRTUAL = $VIRTUAL.split(',') + +Function initvars { + $script:appnames = @("Helloworld", "Drupal", "Mediawiki", "Wordpress", "Joomla") + $script:data = @{} + + Foreach ($app in $appnames) { + $script:data.add($app, "") + $script:data[$app] = @{ "IIS" = + @{ "nocache" = + @{ "php1" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + }; + "php2" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + } + }; + "cache" = + @{ "php1" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + }; + "php2" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + } + } + }; + "Apache" = + @{ "nocache" = + @{ "php1" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + }; + "php2" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + } + }; + + "cachenoigbinary" = + @{ "php1" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + }; + "php2" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + } + }; + + "cachewithigbinary" = + @{ "php1" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + }; + "php2" = + @{ "tps$($VIRTUAL[0])" = [int]0; + "tps$($VIRTUAL[1])" = [int]0; + "tps$($VIRTUAL[2])" = [int]0; + "err$($VIRTUAL[0])" = [int]0; + "err$($VIRTUAL[1])" = [int]0; + "err$($VIRTUAL[2])" = [int]0; + } + } + } + } + } ## End Foreach +} ## End Function + + +## Initialize hash table +## $data[App_Name][Apache|IIS][cache|nocache|cachenoigbinary|cachewithigbinary][php1|php2][tps8|tps16|tps32] +initvars + +Get-ChildItem -recurse $results | Where-Object { $_.Name -match '\.dat' } | ForEach-Object { + + ## Determine web server, cache/nocache and application from file name + ## i.e. Apache-PHP5.4.0B2-Apache-Cache-Drupal.summary.dat + $dname = $_.Name.split("-") + $websvr = $dname[0] + $phpver = $dname[1] -ireplace "PHP", "" + $cache = $dname[3].tolower() + $appname = $dname[4] -ireplace "\.\w+", "" + + if ( $phpver -eq $PHP1 ) { $phpver = "php1" } + elseif ( $phpver -eq $PHP2 ) { $phpver = "php2" } + else { continue } + + $contents = (get-content $_.FullName) + Foreach ( $line in $contents ) { + if ( $line -match "\.xml" ) { + ## tps, kcpt, bpt, cpu, err + ## i.e. php-web01-Apache-2clnt-08vrtu-PHP5.4.0B2-Apache-Cache-Drupal.xml, 40.7, 0.0, 10670, 0.0, 0 + $line = $line.split(",") + $tps = $line[1].trim() + $err = $line[5].trim() + $virt = $line[0].split("-") + $virt = $virt[4] + $virt = $virt -ireplace "vrtu", "" + $virt = $virt -ireplace "^0", "" + + ## write-output "$appname $websvr $cache $phpver tps$virt" + $data[$appname][$websvr][$cache][$phpver]["tps$virt"] = $tps + $data[$appname][$websvr][$cache][$phpver]["err$virt"] = $err + if ( $err -gt 0 ) { + $logfile = "c:/wcat/autocat-log.txt" + $msg = (get-date -format "yyyy-MM-dd HH:mm:ss")+" $appname, $websvr, $cache, $dname[1]`: $err" + $msg | Out-File -Encoding ASCII -Append $logfile + $errlog += "$appname, $websvr, $cache, "+$dname[1]+": $err <br/>`n" + } + } + } +} + + +## Finally, output the results template +. ".\results-template.ps1" + + + + */ + } + +} diff --git a/src/com/mostc/pftt/model/performance/WCATWordpressTest.groovy b/src/com/mostc/pftt/model/performance/WCATWordpressTest.groovy new file mode 100644 index 0000000..ba86b41 --- /dev/null +++ b/src/com/mostc/pftt/model/performance/WCATWordpressTest.groovy @@ -0,0 +1,186 @@ +package com.mostc.pftt.model.performance; + +class WCATWordpressTest extends WCATPerformanceTest { + + @Override + public String getName() { + return "WCAT-Wordpress"; + } + + @Override + String writeWCATScenario() { +""" +scenario +{ + name = "Wordpress"; + + warmup = 20; + duration = 120; + cooldown = 10; + + ///////////////////////////////////////////////////////////////// + // + // All requests inherit the settings from the default request. + // Defaults are overridden if specified in the request itself. + // + ///////////////////////////////////////////////////////////////// + default + { + // send keep-alive header + setheader + { + name = "Connection"; + value = "keep-alive"; + } + + // set the host header + setheader + { + name = "Host"; + value = server(); + } + + // HTTP1.1 request + version = HTTP11; + + // keep the connection alive after the request + close = ka; + } + + transaction + { + id = "Web Site Homepage"; + weight = 1; + + request + { + url = "/wordpress/"; + statuscode = 200; + //cookies = false; + } + + // + // specifically close the connection after both files are requested + // + close + { + method = ka; + } + } +} +""" + } // end String writeWCATScenario + + @Override + String writeWCATSettings(String scenario_file, int virtual_clients) { +""" +settings +{ + //-------------------------------------------------------------------------- + // General controller settings + // + // clientfile - specifies the client file, relative to working dir + // server - host name of the webserver + // virtualclients - number of 'threads' per physical client + // clients - number of physical webcat client machines + // + //-------------------------------------------------------------------------- + // Example: + // clientfile = "test.wcat"; + // server = "131.107.145.189,131.107.145.190"; + // clients = 2; + // virtualclients = 4; + // bind = "131.107.145.189,w2k3-load16"; + // bind = "w2k3-load15,131.107.145.190"; + // + //-------------------------------------------------------------------------- + + virtualclients = $virtual_clients; + clientfile = "$scenario_file"; + + //-------------------------------------------------------------------------- + // Performance counters (pass '-x' option to wcctl.exe to enable) + // + // interval - polling interval in seconds (default=10) + // host - host name of machine to monitor (default=webserver) + // counter - path of counter to monitor + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional machines can be monitored by adding more counters blocks. + // + // Example: + // + // counters { + // host = "sqlserver"; // name of remote machine + // interval = 5; + // counter = "..."; + // } + // + //-------------------------------------------------------------------------- + + counters + { + interval = 10; + + counter = "Processor(_Total)\\% Processor Time"; + counter = "Processor(_Total)\\% Privileged Time"; + counter = "Processor(_Total)\\% User Time"; + counter = "Processor(_Total)\\Interrupts/sec"; + + counter = "Memory\\Available KBytes"; + + counter = "Process(w3wp)\\Working Set"; + + counter = "System\\Context Switches/sec"; + counter = "System\\System Calls/sec"; + + counter = "Web Service(_Total)\\Bytes Received/sec" ; + counter = "Web Service(_Total)\\Bytes Sent/sec" ; + counter = "Web Service(_Total)\\Connection Attempts/sec" ; + counter = "Web Service(_Total)\\Get Requests/sec" ; + } + + //-------------------------------------------------------------------------- + // Registry Key Monitors (pass '-x' option to wcctl.exe to enable) + // + // path - registry path, relative to HKLM + // name - name of registry key + // type - type of value (REG_SZ | REG_DWORD) + // + //-------------------------------------------------------------------------- + // Optional: + // + // Additional registry keys can be monitored on the web server by + // adding more registry blocks to this file. Note that simple strings and + // dwords are all that webcat currently supports. + // + // Example: + // + // registry { + // path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + // name = "DhcpDomain"; + // type = REG_SZ; + // } + // + //-------------------------------------------------------------------------- + + registry + { + path = "System\\CurrentControlSet\\Control\\FileSystem"; + name = "NtfsDisableLastAccessUpdate"; + type = REG_DWORD; + } + + registry + { + path = "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"; + name = "SynAttackProtect"; + type = REG_DWORD; + } +} +""" + } // end String writeWCATSettings + +} // end class WCATWordpressTest diff --git a/src/com/mostc/pftt/model/performance/WordpressPerformanceTest.java b/src/com/mostc/pftt/model/performance/WordpressPerformanceTest.java deleted file mode 100644 index 14cadde..0000000 --- a/src/com/mostc/pftt/model/performance/WordpressPerformanceTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.mostc.pftt.model.performance; - -public class WordpressPerformanceTest extends PerformanceTest { - - @Override - public String getName() { - return "Wordpress-PerformanceTest"; - } - -} diff --git a/src/com/mostc/pftt/model/phpt/PhpBuild.java b/src/com/mostc/pftt/model/phpt/PhpBuild.java index 74c731d..da6d686 100644 --- a/src/com/mostc/pftt/model/phpt/PhpBuild.java +++ b/src/com/mostc/pftt/model/phpt/PhpBuild.java @@ -1,5 +1,6 @@ package com.mostc.pftt.model.phpt; +import java.io.FileWriter; import java.io.IOException; import java.io.PrintStream; import java.lang.ref.WeakReference; @@ -705,5 +706,29 @@ public class PhpBuild extends SAPIManager { public String getDefaultExtensionDir() { return build_path.contains("/") ? build_path+"/ext" : build_path+"\\ext"; } + + boolean saved_ini = false; + String ini_dir; + public String prepare(Host host) throws IOException { + if (saved_ini) { + return ini_dir; + } else { + // @see CliScenario#createIniForTest + saved_ini = true; + + ini_dir = host.mktempname(getClass()); + host.mkdirs(ini_dir); + + String ini_file = ini_dir + "/php.ini"; + + PhpIni def_ini = RequiredExtensionsSmokeTest.createDefaultIniCopy(host, this); + + FileWriter fw = new FileWriter(ini_file); + fw.write(def_ini.toString()); + fw.close(); + + return ini_dir; + } + } } // end public class PhpBuild diff --git a/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java b/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java index 9f6309f..0cb7b50 100644 --- a/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java +++ b/src/com/mostc/pftt/model/phpt/PhptSourceTestPack.java @@ -244,6 +244,7 @@ public class PhptSourceTestPack extends SourceTestPack { * location can be local or remote. * * @see #read - must have already been called + * @param cm * @param host * @param test_pack_dir * @return @@ -251,23 +252,35 @@ public class PhptSourceTestPack extends SourceTestPack { * @throws IOException * @throws Exception */ - public PhptActiveTestPack install(Host host, String test_pack_dir) throws IllegalStateException, IOException, Exception { + public PhptActiveTestPack install(ConsoleManager cm, Host host, String test_pack_dir) throws IllegalStateException, IOException, Exception { if (!this.host.isRemote() || this.host.equals(host)) { // installing from local host to remote host OR from remote host to itself - host.upload(test_pack, test_pack_dir); + host.uploadCompressWith7Zip(cm, getClass(), test_pack, host, test_pack_dir); } else if (!host.isRemote()) { // installing from remote host to local host - host.download(test_pack, test_pack_dir); + host.download7ZipAndDecompress(cm, getClass(), test_pack, this.host, test_pack_dir); } else { - // installing from 1 remote host to a different remote host + // installing from 1 remote host(src) to a different remote host (dst) LocalHost local_host = new LocalHost(); - String local_dir = local_host.mktempname(getClass()); - this.host.download(test_pack, local_dir); - host.upload(local_dir, test_pack_dir); - local_host.delete(local_dir); + + // decide file names + String local_7zip_file = local_host.mktempname(getClass(), ".7z"); + String src_7zip_file = this.host.mktempname(getClass(), ".7z"); + String dst_7zip_file = host.mktempname(getClass(), ".7z"); + + // compress and download/upload and decompress + this.host.compress(cm, host, test_pack, src_7zip_file); + this.host.download(src_7zip_file, local_7zip_file); + host.upload(local_7zip_file, dst_7zip_file); + host.decompress(cm, this.host, dst_7zip_file, test_pack_dir); + + // cleanup + this.host.delete(dst_7zip_file); + host.delete(src_7zip_file); + local_host.delete(local_7zip_file); } return new PhptActiveTestPack(test_pack_dir); - } + } // end public PhptActiveTestPack install /** installs only the named test cases from test pack into to the given location to actively run it from. * diff --git a/src/com/mostc/pftt/model/ui/SeleniumTest.groovy b/src/com/mostc/pftt/model/ui/SeleniumTest.groovy new file mode 100644 index 0000000..8877e64 --- /dev/null +++ b/src/com/mostc/pftt/model/ui/SeleniumTest.groovy @@ -0,0 +1,5 @@ + +abstract class SeleniumTest { + + +} diff --git a/src/com/mostc/pftt/model/ui/wordpress.groovy b/src/com/mostc/pftt/model/ui/wordpress.groovy index f65e6a6..6523584 100644 --- a/src/com/mostc/pftt/model/ui/wordpress.groovy +++ b/src/com/mostc/pftt/model/ui/wordpress.groovy @@ -1,120 +1,108 @@ package com.mostc.pftt.model.ui; -import com.mostc.pftt.scenario.app.WordpressScenario - -// auto import UITestCase -// cr or case_runner - -// host - -// build - -// middleware - -// host_int - - -install_ctx = cr.install(new WordpressScenario()) - /* -def user_anon_test(prefix='') { - cr.run(new UITestCase("$prefix-View-Content") { - def act() { - - } - }) - - cr.run(new UITestCase("$prefix-Create-Story") { - def act() { - - } - }) +class WordpressTestPack { - cr.run(new UITestCase("$prefix-Post-Comments") { - def act() { - - } - }) -} // end def user_anon_test - -def user_tests(user_info=null, prefix='', suffix='', xfail=false) { - // login new user - if (user_info) { - user_login(user_info, prefix, suffix, xfail) - - // test as new user - user_anon_test(prefix) - - // change settings - cr.run(new UITestCase("$prefix-View-Settings-$suffix")) { + def user_anon_test(prefix='') { + cr.run(new UITestCase("$prefix-View-Content") { + def act() { + + } + }) + + cr.run(new UITestCase("$prefix-Create-Story") { def act() { } - }, xfail) + }) - cr.run(new UITestCase("$prefix-Change-Settings-$suffix")) { + cr.run(new UITestCase("$prefix-Post-Comments") { def act() { } - }, xfail) + }) + } // end def user_anon_test - user_logout(user_info, prefix, xfail) - } else { - // report that these cases can't be tested b/c user wasn't created - cr.bork("$prefix-Login-$suffix") - cr.bork("$prefix-View-Settings-$suffix") - cr.bork("$prefix-Change-Settings-$suffix") - cr.bork("$prefix-Logout-$suffix") - } -} // end def user_tests - -def register_user(suffix='1', xfail=false) { - // TODO -} - -def admin_login(suffix='1', xfail=false, given_password=null) { - // login as administrator - user_login({username = install_ctx.admin_user; password = given_password==null?install_ctx.admin_password:given_password}, 'Admin', suffix, xfail) -} - -def admin_logout(suffix='1') { - // logout administrator - user_logout('Admin', suffix) -} - -def delete_user(user_info, suffix='1') { - // TODO -} - -def user_login(user_info, prefix='', suffix='', xfail=false) { - cr.run(new UITestCase("$prefix-Login-$suffix") { - def act() { - go_home().find_link('Login', 'Signin').click().fill('User', user_info.username).fill('Password', user_info.password).submit() - } - }, xfail); -} - -def user_logout(prefix='', suffix='', xfail=false) { - // logout - cr.run(new UITestCase("$prefix-Logout-$suffix") { - def act() { - // unless go_url() or go_home() called, starts with page left by previous UITestCase - find_link('Logout').click() + def user_tests(user_info=null, prefix='', suffix='', xfail=false) { + // login new user + if (user_info) { + user_login(user_info, prefix, suffix, xfail) + + // test as new user + user_anon_test(prefix) + + // change settings + cr.run(new UITestCase("$prefix-View-Settings-$suffix")) { + def act() { + + } + }, xfail) + + cr.run(new UITestCase("$prefix-Change-Settings-$suffix")) { + def act() { + + } + }, xfail) + + user_logout(user_info, prefix, xfail) + } else { + // report that these cases can't be tested b/c user wasn't created + cr.bork("$prefix-Login-$suffix") + cr.bork("$prefix-View-Settings-$suffix") + cr.bork("$prefix-Change-Settings-$suffix") + cr.bork("$prefix-Logout-$suffix") } - }, xfail); -} - -def xfail_tests(suffix='') { - admin_login(suffix, xfail=true, given_password='wrong_password') + } // end def user_tests - admin_login(suffix) + def register_user(suffix='1', xfail=false) { + // TODO + } - change_password(created_user) - change_password(registered_user) + def admin_login(suffix='1', xfail=false, given_password=null) { + // login as administrator + user_login({username = install_ctx.admin_user; password = given_password==null?install_ctx.admin_password:given_password}, 'Admin', suffix, xfail) + } - admin_logout(suffix) + def admin_logout(suffix='1') { + // logout administrator + user_logout('Admin', suffix) + } - user_login(created_user, xfail=true) - user_login(registered_user, xfail=true) -} - -///////// FIRST TEST CASE HERE //////////// - + def delete_user(user_info, suffix='1') { + // TODO + } + + def user_login(user_info, prefix='', suffix='', xfail=false) { + cr.run(new UITestCase("$prefix-Login-$suffix") { + def act() { + go_home().find_link('Login', 'Signin').click().fill('User', user_info.username).fill('Password', user_info.password).submit() + } + }, xfail); + } + + def user_logout(prefix='', suffix='', xfail=false) { + // logout + cr.run(new UITestCase("$prefix-Logout-$suffix") { + def act() { + // unless go_url() or go_home() called, starts with page left by previous UITestCase + find_link('Logout').click() + } + }, xfail); + } + + def xfail_tests(suffix='') { + admin_login(suffix, xfail=true, given_password='wrong_password') + + admin_login(suffix) + + change_password(created_user) + change_password(registered_user) + + admin_logout(suffix) + + user_login(created_user, xfail=true) + user_login(registered_user, xfail=true) + } // test anonymously user_anon_test('Anonymous') @@ -191,4 +179,7 @@ admin_logout('All-Plugins-2') user_login(created_user, 'All-Plugins', 'Old-Password', xfail=true) user_login(registered_user, 'All-Plugins', 'Old-Password', xfail=true) -*/ + + +} +*/ \ No newline at end of file diff --git a/src/com/mostc/pftt/report/ABCReportGen.groovy b/src/com/mostc/pftt/report/ABCReportGen.groovy new file mode 100644 index 0000000..db7ba55 --- /dev/null +++ b/src/com/mostc/pftt/report/ABCReportGen.groovy @@ -0,0 +1,197 @@ +package com.mostc.pftt.report + +class ABCReportGen extends AbstractReportGen { + final String os_name; + final File tmp_file; + + public ABCReportGen(File tmp_file, String os_name) { + this.tmp_file = tmp_file; + this.os_name = os_name; + } + + @Override + void run() { + + def oses = [os_name] + + def root = new XmlSlurper().parse(tmp_file); + def testcases = root.depthFirst().findAll { it.name() == 'testcase' } + + def sw = new StringWriter() + def html = new groovy.xml.MarkupBuilder(sw) + html.html { + body { + p { + span(style: 'font-size:14.0pt;line-height:115%') { + span("AUT Report") + b("Joomla Platform") + } + } + + p { + b("Joomla Platform") + span(" PHPUnit Test-Pack comparing ") + b("PHP_5_4-r328a3d9") + span(" with ") + b("PHP_5_4-r8cdd6bc") + span(" (using ") + b("Joomla Platform") + span(" PHPUnit Test-Pack from ") + b("Joomla_Platform-12.1") + span(")") + } + + p { + span(style: 'font-size:14.0pt;line-height:115%', 'Summary') + } + + table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { + tr() { + td(valign:'top', style: 'width:1.45in;border:solid windowtext 1.0pt; background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "OS" + ) + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Tests" + ) + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Failures" + ) + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Errors" + ) + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Success Rate" + ) + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') + td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Time" + ) + } + + oses.each{ os_name -> + tr(style: 'height:26.05pt') { + td(valign: 'top', style: 'width:1.45in;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt;height:26.05pt', + os_name + ) + td(valign: "top", style: 'width:49.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + testcases.size() + ) + td(valign: 'top', style: 'width:27.0pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "+0" + ) + td(valign: 'top', style: 'width:.75in;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "34" + ) + td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "+0" + ) + td(valign: 'top', style: 'width:45.0pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "158" + ) + td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "+0" + ) + td(valign: 'top', style: 'width:76.5pt;border-top:none;border-left: none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "92%" + ) + td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "+0" + ) + td(valign: 'top', style: 'width:45.9pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', + "0:08:00" + ) + } + } + } // end table + + p { + span(style: 'font-size:14.0pt;line-height:115%', + "New Failures and Errors" + ) + } + + table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { + oses.each { os_name -> + tr() { + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt', + os_name + ) + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { + testcases.each { + if ( it.getAt("failure").size() > 0 || it.getAt("error").size() > 0 ) { + def test_name = it['@name'] + + p(test_name) + + } + } + } + } + } + } // end table + + p { + span(style: 'font-size:14.0pt;line-height:115%', + "List of Failing and Error Test Cases" + ) + } + + table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { + tr() { + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') + td(valign: 'top', style: 'width:153.0pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Base" + ) + td(valign: 'top', style: 'width:2.95in;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', + "Test" + ) + } + + + + + oses.each { os_name -> + tr() { + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt', + os_name + ) + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { + testcases.each { + if ( it.getAt("failure").size() > 0 || it.getAt("error").size() > 0 ) { + def test_name = it['@name'] + + p(test_name) + } + } + } + td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { + testcases.each { + if ( ( it['failure'] || it['error'] ) && it.text() != null && it.text().length() > 0 ) { + def test_name = it['@name'] + + p(test_name) + } + } + } + } + } + } // end table + + } // end body + } // end html + + def f = new File("index.html") + f.write(sw.toString()) + + + } // end void run + + @Override + public String getHTMLString() { + return sw.toString(); + } + +} // end class AUTReportGen diff --git a/src/com/mostc/pftt/report/AUTReportGen.groovy b/src/com/mostc/pftt/report/AUTReportGen.groovy deleted file mode 100644 index f5a1a41..0000000 --- a/src/com/mostc/pftt/report/AUTReportGen.groovy +++ /dev/null @@ -1,197 +0,0 @@ -package com.mostc.pftt.report - -class AUTReportGen extends AbstractReportGen { - final String os_name; - final File tmp_file; - - public AUTReportGen(File tmp_file, String os_name) { - this.tmp_file = tmp_file; - this.os_name = os_name; - } - - @Override - void run() { - - def oses = [os_name] - - def root = new XmlSlurper().parse(tmp_file); - def testcases = root.depthFirst().findAll { it.name() == 'testcase' } - - def sw = new StringWriter() - def html = new groovy.xml.MarkupBuilder(sw) - html.html { - body { - p { - span(style: 'font-size:14.0pt;line-height:115%') { - span("AUT Report") - b("Joomla Platform") - } - } - - p { - b("Joomla Platform") - span(" PHPUnit Test-Pack comparing ") - b("PHP_5_4-r328a3d9") - span(" with ") - b("PHP_5_4-r8cdd6bc") - span(" (using ") - b("Joomla Platform") - span(" PHPUnit Test-Pack from ") - b("Joomla_Platform-12.1") - span(")") - } - - p { - span(style: 'font-size:14.0pt;line-height:115%', 'Summary') - } - - table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { - tr() { - td(valign:'top', style: 'width:1.45in;border:solid windowtext 1.0pt; background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "OS" - ) - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Tests" - ) - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Failures" - ) - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Errors" - ) - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Success Rate" - ) - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') - td(valign: 'top', style: 'width:49.5pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Time" - ) - } - - oses.each{ os_name -> - tr(style: 'height:26.05pt') { - td(valign: 'top', style: 'width:1.45in;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt;height:26.05pt', - os_name - ) - td(valign: "top", style: 'width:49.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - testcases.size() - ) - td(valign: 'top', style: 'width:27.0pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "+0" - ) - td(valign: 'top', style: 'width:.75in;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "34" - ) - td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "+0" - ) - td(valign: 'top', style: 'width:45.0pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "158" - ) - td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "+0" - ) - td(valign: 'top', style: 'width:76.5pt;border-top:none;border-left: none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "92%" - ) - td(valign: 'top', style: 'width:22.5pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "+0" - ) - td(valign: 'top', style: 'width:45.9pt;border-top:none;border-left:none; border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt; height:26.05pt', - "0:08:00" - ) - } - } - } // end table - - p { - span(style: 'font-size:14.0pt;line-height:115%', - "New Failures and Errors" - ) - } - - table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { - oses.each { os_name -> - tr() { - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt', - os_name - ) - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { - testcases.each { - if ( it.getAt("failure").size() > 0 || it.getAt("error").size() > 0 ) { - def test_name = it['@name'] - - p(test_name) - - } - } - } - } - } - } // end table - - p { - span(style: 'font-size:14.0pt;line-height:115%', - "List of Failing and Error Test Cases" - ) - } - - table(border: 1, cellspacing: 0, cellpadding: 0, style: 'border-collapse:collapse;border:none;') { - tr() { - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; background:#A9CAED;padding:0in 5.4pt 0in 5.4pt') - td(valign: 'top', style: 'width:153.0pt;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Base" - ) - td(valign: 'top', style: 'width:2.95in;border:solid windowtext 1.0pt; border-left:none;background:#A9CAED;padding:0in 5.4pt 0in 5.4pt', - "Test" - ) - } - - - - - oses.each { os_name -> - tr() { - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt', - os_name - ) - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { - testcases.each { - if ( it.getAt("failure").size() > 0 || it.getAt("error").size() > 0 ) { - def test_name = it['@name'] - - p(test_name) - } - } - } - td(valign: 'top', style: 'width:113.4pt;border:solid windowtext 1.0pt; border-top:none; background:#ECEEE1;padding:0in 5.4pt 0in 5.4pt') { - testcases.each { - if ( ( it['failure'] || it['error'] ) && it.text() != null && it.text().length() > 0 ) { - def test_name = it['@name'] - - p(test_name) - } - } - } - } - } - } // end table - - } // end body - } // end html - - def f = new File("index.html") - f.write(sw.toString()) - - - } // end void run - - @Override - public String getHTMLString() { - return sw.toString(); - } - -} // end class AUTReportGen diff --git a/src/com/mostc/pftt/report/FBCReportGen.groovy b/src/com/mostc/pftt/report/FBCReportGen.groovy index 071c0f3..43c60db 100644 --- a/src/com/mostc/pftt/report/FBCReportGen.groovy +++ b/src/com/mostc/pftt/report/FBCReportGen.groovy @@ -214,7 +214,7 @@ html.html { td(colspan:2, 'Crashes (Test)') } /* --------------- end headers -------------- */ - /*tr { + tr { td(row++) td(test_telem.getOSName()) td() { @@ -227,7 +227,7 @@ html.html { br(test_name) } } - }*/ + } } // table // new PHPT failures diff --git a/src/com/mostc/pftt/report/PBCReportGen.groovy b/src/com/mostc/pftt/report/PBCReportGen.groovy new file mode 100644 index 0000000..ebab7ed --- /dev/null +++ b/src/com/mostc/pftt/report/PBCReportGen.groovy @@ -0,0 +1,230 @@ +/* +#%powershell1.0% +# +# File: results-template.ps1 +# Description: Output $data into html table. This script is meant to be called from summarize-results.ps1. +# + +Function gaincalc ( $a=0, $b=0 ) { + if ( ($a -ne 0) -and ($b -ne 0) ) { + $c = ($a / $b) - 1 + + switch ($c*100) { + {$_ -ge 0 -and $_ -le 3} {$script:gainclass="none"} + {$_ -gt 3 -and $_ -le 7} {$script:gainclass="gainpossmall"} + {$_ -ge 0 -and $_ -gt 7} {$script:gainclass="gainpos"} + {$_ -lt 0 -and $_ -ge -3} {$script:gainclass="none"} + {$_ -lt -3 -and $_ -ge -7} {$script:gainclass="gainnegsmall"} + {$_ -lt 0 -and $_ -lt -7} {$script:gainclass="gainneg"} + Default { $script:gainclass="none" } + } + + "{0:P2}" -f $c + } + else { + $script:gainclass="none" + } +} + + +write-output " + +<html> +<head> + <style type=text/css> + .data td { border:1px solid black; } + .iis { background-color:#E6B8B7; } + .iiswincache { background-color: #DA9694; } + .apache { background-color: #C5D9F1; } + .apachenoigbinary { background-color: #8DB4E2; } + .apachewithigbinary { background-color: #538DD5; } + .gainpos { background-color: #00A84C; } + .gainpossmall { background-color: #00D661; } + .gainneg { background-color: #FF2929; } + .gainnegsmall { background-color: #DA9694; } + </style> + </head> + +<body> +<table border=0 cellpadding=0 cellspacing=0 width=600> +<tr> +<td> <strong> PHP Performance </strong> </td> +<td> <strong> Hardware & Environment </strong> </td> +</tr><tr> +<td>$PHP1 - $PHP2</td> +<td>Dell R710</td> +</tr><tr> +<td> </td> +<td>CPU - Intel Quad core @ 2.26Ghz (x2) L5520</td> +</tr><tr> +<td> </td> +<td>Memory - 12GB RAM</td> +</tr><tr> +<td> </td> +<td>HD - 147GB SAS RAID 1</td> +</tr><tr> +<td> </td> +<td>NIC - 1Gbps Intel</td> +</tr><tr> +<td> </td> +<td>Windows 2008 R2 - SP1</td> +</tr><tr> +<td> </td> +<td>php-web01.ctac.nttest.microsoft.com</td> +</tr> +<table> +<p> </p> + +<table border=0 cellpadding=0 cellspacing=0 width=1628 class=data> + +<!-- Header Labels --> + <tr> + <td colspan=4></td> + <td colspan=6 class=iis>IIS 7.5</td> + <td colspan=9 class=apache>Apache 2.2</td> + </tr> + + <tr> + <td colspan=4></td> + <td colspan=3 rowspan=2 class=iis>No Cache</td> + <td colspan=3 rowspan=2 class=iiswincache>WinCache</td> + <td colspan=3 rowspan=2 class=apache>No Cache</td> + <td colspan=6 class=apachenoigbinary>APC</td> + </tr> + <tr> + <td></td> + <td colspan=3>Load Agents</td> + <td colspan=3 class=apachenoigbinary>-igbinary</td> + <td colspan=3 class=apachewithigbinary>+igbinary</td> + </tr> + <!-- Header Labels --> + + <tr> + <td>Application</td> + <td>Physical</td> + <td>Virtual</td> + <td></td> + +<!-- IIS No Cache --> + + <td>$PHP1</td> + <td>$PHP2</td> + <td>gain</td> + +<!-- IIS Cache --> + <td>$PHP1</td> + <td>$PHP2</td> + <td>gain</td> + +<!-- Apache No Cache --> + <td>$PHP1</td> + <td>$PHP2</td> + <td>gain</td> + +<!-- Apache Cache -igbinary --> + <td>$PHP1</td> + <td>$PHP2</td> + <td>gain</td> + +<!-- Apache Cache +igbinary --> + <td>$PHP1</td> + <td>$PHP2</td> + <td>gain</td> + </tr> + +<!-- Results --> +" + +Foreach ( $app in $appnames ) { + ## Notes: $data[App_Name][Apache|IIS][cache|nocache|cachenoigbinary|cachewithigbinary][php1|php2][ver|tps8|tps16|tps32] + + write-output " + <tr> + <td rowspan=3>$app</td> + " + + Foreach ( $virt in $VIRTUAL ) { + $gain = "" + $gainclass = "" + if ( $virt -ne "8" ) { + write-output "<tr>" + } + + write-output " + <td>2</td> + <td>$virt</td> + <td> </td> + + <!-- IIS - No Cache --> + <td class=iis>" $data[$app]["IIS"]["nocache"]["php1"]["tps$virt"] "</td> + <td class=iis>" $data[$app]["IIS"]["nocache"]["php2"]["tps$virt"] "</td>" + + $gain = gaincalc $data[$app]["IIS"]["nocache"]["php2"]["tps$virt"] $data[$app]["IIS"]["nocache"]["php1"]["tps$virt"] + write-output " + + <td class=$gainclass> $gain + </td> <!-- Gain --> + + <!-- IIS - Cache --> + <td class=iiswincache>" $data[$app]["IIS"]["cache"]["php1"]["tps$virt"] "</td> + <td class=iiswincache>" $data[$app]["IIS"]["cache"]["php2"]["tps$virt"] "</td>" + + + $gain = gaincalc $data[$app]["IIS"]["cache"]["php2"]["tps$virt"] $data[$app]["IIS"]["cache"]["php1"]["tps$virt"] + write-output " + + <td class=$gainclass> $gain + </td> <!-- Gain --> + + <!-- Apache - No Cache --> + <td class=apache>" $data[$app]["Apache"]["nocache"]["php1"]["tps$virt"] "</td> + <td class=apache>" $data[$app]["Apache"]["nocache"]["php2"]["tps$virt"] "</td>" + + $gain = gaincalc $data[$app]["Apache"]["nocache"]["php2"]["tps$virt"] $data[$app]["Apache"]["nocache"]["php1"]["tps$virt"] + write-output " + + <td class=$gainclass> $gain + </td> <!-- Gain --> + + <!-- Apache - Cache -igbinary --> + <td class=apachenoigbinary>" $data[$app]["Apache"]["cachenoigbinary"]["php1"]["tps$virt"] "</td> + <td class=apachenoigbinary>" $data[$app]["Apache"]["cachenoigbinary"]["php2"]["tps$virt"] "</td>" + + $gain = gaincalc $data[$app]["Apache"]["cachenoigbinary"]["php2"]["tps$virt"] $data[$app]["Apache"]["cachenoigbinary"]["php1"]["tps$virt"] + write-output " + + <td class=$gainclass> $gain + </td> <!-- Gain --> + + <!-- Apache - Cache +igbinary --> + <td class=apachewithigbinary>" $data[$app]["Apache"]["cachewithigbinary"]["php1"]["tps$virt"] "</td> + <td class=apachewithigbinary>" $data[$app]["Apache"]["cachewithigbinary"]["php2"]["tps$virt"] "</td>" + + $gain = gaincalc $data[$app]["Apache"]["cachewithigbinary"]["php2"]["tps$virt"] $data[$app]["Apache"]["cachewithigbinary"]["php1"]["tps$virt"] + write-output " + + <td class=$gainclass> $gain + </td> <!-- Gain --> + </tr> + " + } ## End Foreach +} ## End Foreach + +write-output " +</table> +<p> </p> +<p> </p> +" + +if ( $errlog -ne "" ) { + write-output "<strong>Error Log:</strong> <br/>" + write-output "$errlog" +} + +write-output " +</body> +</html> +" + + +*/ diff --git a/src/com/mostc/pftt/report/UBCReportGen.groovy b/src/com/mostc/pftt/report/UBCReportGen.groovy new file mode 100644 index 0000000..e69de29 diff --git a/src/com/mostc/pftt/results/PhptResultPackWriter.java b/src/com/mostc/pftt/results/PhptResultPackWriter.java index 17761a4..80624a3 100644 --- a/src/com/mostc/pftt/results/PhptResultPackWriter.java +++ b/src/com/mostc/pftt/results/PhptResultPackWriter.java @@ -38,6 +38,8 @@ import com.mostc.pftt.util.StringUtil; * */ +// TODO store consolemanager logs in result-pack +// -including smoke checks from dfs and deduplication scenrios public class PhptResultPackWriter extends PhptResultPack implements IPhptTestResultReceiver { private File telem_dir; protected final HashMap<Host,HashMap<ScenarioSet,HashMap<EPhptTestStatus,PrintWriter>>> status_list_map; diff --git a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java index 0abd429..be2d451 100644 --- a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java +++ b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java @@ -19,7 +19,6 @@ import com.mostc.pftt.model.phpt.PhpIni; import com.mostc.pftt.model.phpt.PhptTestCase; import com.mostc.pftt.model.phpt.PhptSourceTestPack; import com.mostc.pftt.model.phpt.PhptActiveTestPack; -import com.mostc.pftt.model.smoke.RequiredExtensionsSmokeTest; import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.IPhptTestResultReceiver; import com.mostc.pftt.results.PhptTestResult; @@ -37,7 +36,7 @@ import com.mostc.pftt.util.StringUtil; public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { protected ExecOutput output; - protected String selected_php_exe, shell_script, test_cmd, skip_cmd, ini_settings, shell_file; + protected String selected_php_exe, shell_script, test_cmd, skip_cmd, ini_settings, shell_file, ini_dir; public static boolean willSkip(ConsoleManager cm, IPhptTestResultReceiver twriter, Host host, ScenarioSet scenario_set, ESAPIType type, PhpBuild build, PhptTestCase test_case) throws Exception { if (AbstractPhptTestCaseRunner2.willSkip(cm, twriter, host, scenario_set, type, build, test_case)) { @@ -123,7 +122,9 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { "ext/standard/tests/file/fgets_socket_variation1.phpt", "ext/standard/tests/network/shutdown.phpt", "ext/standard/tests/file/fgets_socket_variation2.phpt", - "ext/standard/tests/network/tcp4loop.phpt" + "ext/standard/tests/network/tcp4loop.phpt", + "zend/tests/multibyte/multibyte_encoding_003.phpt", + "zend/tests/multibyte/multibyte_encoding_002.phpt" )) { twriter.addResult(host, scenario_set, new PhptTestResult(host, EPhptTestStatus.XSKIP, test_case, "test sometimes randomly fails, ignore it", null, null, null, null, null, null, null, null, null, null, null)); @@ -139,6 +140,8 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { @Override protected boolean prepare() throws IOException, Exception { if (super.prepare()) { + ini_dir = build.prepare(host); + // ini_settings = ini.toCliArgString(host); @@ -147,6 +150,7 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { /* For GET/POST tests, check if cgi sapi is available and if it is, use it. */ if (test_case.containsAnySection(EPhptSection.GET, EPhptSection.POST, EPhptSection.PUT, EPhptSection.POST_RAW, EPhptSection.COOKIE, EPhptSection.EXPECTHEADERS)) { if (build.hasPhpCgiExe()) { + // -C => important: don't chdir selected_php_exe = build.getPhpCgiExe() + " -C "; } else { twriter.addResult(host, scenario_set, new PhptTestResult(host, EPhptTestStatus.XSKIP, test_case, "CGI not available", null, null, null, null, null, null, null, null, null, null, null)); @@ -162,31 +166,10 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { return false; } - static boolean saved_ini = false; - static String ini_dir; - @Override protected void prepareTest() throws Exception { super.prepareTest(); - // - if (!saved_ini) { - // @see CliScenario#createIniForTest - saved_ini = true; - - ini_dir = host.mktempname(getClass()); - host.mkdirs(ini_dir); - - String ini_file = ini_dir + "/php.ini"; - - PhpIni def_ini = RequiredExtensionsSmokeTest.createDefaultIniCopy(host, build); - - FileWriter fw = new FileWriter(ini_file); - fw.write(def_ini.toString()); - fw.close(); - } - // - // generate cmd string to run test_file with php.exe // String query_string = ""; @@ -293,8 +276,8 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { if (skipif_file != null) { env.put(ENV_USE_ZEND_ALLOC, "1"); - // -n => critical: ignores any .ini file with the php build - skip_cmd = selected_php_exe+" -n "+ini_settings+" -f \""+skipif_file+"\""; + // -c => critical, pass php.ini + skip_cmd = selected_php_exe+" -c "+ini_dir+" "+ini_settings+" -f \""+skipif_file+"\""; if (!env.containsKey(ENV_PATH_TRANSLATED)) env.put(ENV_PATH_TRANSLATED, skipif_file); @@ -303,7 +286,7 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { // execute SKIPIF (60 second timeout) output = host.exec(skip_cmd, Host.ONE_MINUTE, env, null, active_test_pack.getDirectory()); - + return output.output; } return null; @@ -327,8 +310,8 @@ public class CliPhptTestCaseRunner extends AbstractPhptTestCaseRunner2 { @Override protected void executeClean() throws Exception { // execute cleanup script - // FUTURE should cleanup script be ignored?? host.exec(selected_php_exe+" "+test_clean, Host.ONE_MINUTE, env, null, active_test_pack.getDirectory()); + } // end void executeClean @Override diff --git a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java index 941782c..d6a7ed4 100644 --- a/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java +++ b/src/com/mostc/pftt/runner/LocalPhptTestPackRunner.java @@ -14,6 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import com.mostc.pftt.host.Host; +import com.mostc.pftt.host.SSHHost; import com.mostc.pftt.model.phpt.PhpBuild; import com.mostc.pftt.model.phpt.PhptTestCase; import com.mostc.pftt.model.phpt.PhptSourceTestPack; @@ -26,8 +27,10 @@ import com.mostc.pftt.results.ConsoleManager; import com.mostc.pftt.results.IPhptTestResultReceiver; import com.mostc.pftt.results.ConsoleManager.EPrintType; import com.mostc.pftt.scenario.AbstractFileSystemScenario; +import com.mostc.pftt.scenario.AbstractFileSystemScenario.ITestPackStorageDir; import com.mostc.pftt.scenario.AbstractSAPIScenario; import com.mostc.pftt.scenario.AbstractWebServerScenario; +import com.mostc.pftt.scenario.SMBDeduplicationScenario; import com.mostc.pftt.scenario.Scenario; import com.mostc.pftt.scenario.ScenarioSet; import com.mostc.pftt.util.StringUtil; @@ -105,6 +108,10 @@ public class LocalPhptTestPackRunner extends PhptTestPackRunner { sapi_scenario = AbstractSAPIScenario.getSAPIScenario(scenario_set); file_scenario = AbstractFileSystemScenario.getFileSystemScenario(scenario_set); + // TODO + SSHHost remote_host = new SSHHost("10.200.41.219", "administrator", "password01!"); + file_scenario = new SMBDeduplicationScenario(remote_host, "F:"); + // ensure all scenarios are implemented if (!scenario_set.isImplemented()) { cm.println(EPrintType.SKIP_OPERATION, getClass(), "Scenario Set not implemented: "+scenario_set); @@ -119,25 +126,28 @@ public class LocalPhptTestPackRunner extends PhptTestPackRunner { cm.println(EPrintType.IN_PROGRESS, getClass(), "preparing storage for test-pack..."); // prepare storage - if (!file_scenario.notifyPrepareStorageDir(cm, host)) { + ITestPackStorageDir storage_dir = file_scenario.createStorageDir(cm, host); + if (storage_dir == null) { cm.println(EPrintType.CANT_CONTINUE, getClass(), "unable to prepare storage for test-pack, giving up!"); close(); return; } // - String storage_dir = file_scenario.getTestPackStorageDir(host); // generate name of directory on that storage to store the copy of the test-pack - String test_pack_dir; - long millis = System.currentTimeMillis(); - for ( int i=0 ; ; i++ ) { - // try to include version, branch info etc... from name of test-pack - test_pack_dir = storage_dir + "/PFTT-" + Host.basename(src_test_pack.getSourceDirectory()) + "-" + millis; - if (!host.exists(test_pack_dir)) - break; - millis++; - if (i%100==0) - millis = System.currentTimeMillis(); + String test_pack_dir = null; + { + String local_path = storage_dir.getLocalPath(host); + long millis = System.currentTimeMillis(); + for ( int i=0 ; i < 655535 ; i++ ) { + // try to include version, branch info etc... from name of test-pack + test_pack_dir = local_path + "/PFTT-" + Host.basename(src_test_pack.getSourceDirectory()) + (i==0?"":"-" + millis); + if (!host.exists(test_pack_dir)) + break; + millis++; + if (i%100==0) + millis = System.currentTimeMillis(); + } } // @@ -152,7 +162,7 @@ public class LocalPhptTestPackRunner extends PhptTestPackRunner { active_test_pack = src_test_pack.installInPlace(); else // copy test-pack onto (remote) file system - active_test_pack = src_test_pack.install(host, test_pack_dir); + active_test_pack = src_test_pack.install(cm, host, test_pack_dir); } catch (Exception ex ) { cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "runTestList", ex, "", host, file_scenario, active_test_pack); } @@ -164,7 +174,7 @@ public class LocalPhptTestPackRunner extends PhptTestPackRunner { // // notify storage - if (!file_scenario.notifyTestPackInstalled(cm, host)) { + if (!storage_dir.notifyTestPackInstalled(cm, host)) { cm.println(EPrintType.CANT_CONTINUE, getClass(), "unable to prepare storage for test-pack, giving up!(2)"); close(); return; @@ -218,7 +228,7 @@ public class LocalPhptTestPackRunner extends PhptTestPackRunner { host.delete(active_test_pack.getDirectory()); // cleanup, disconnect storage, etc... - file_scenario.notifyFinishedTestPack(cm, host); + storage_dir.delete(cm, host); } // } finally { diff --git a/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java b/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java index 62d773a..e7fd15b 100644 --- a/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java +++ b/src/com/mostc/pftt/scenario/AbstractFileSystemScenario.java @@ -3,6 +3,12 @@ package com.mostc.pftt.scenario; import com.mostc.pftt.host.Host; import com.mostc.pftt.results.ConsoleManager; +/** + * + * @author Matt Ficken + * + */ + public abstract class AbstractFileSystemScenario extends AbstractSerialScenario { public static AbstractFileSystemScenario getFileSystemScenario(ScenarioSet scenario_set) { @@ -13,19 +19,42 @@ public abstract class AbstractFileSystemScenario extends AbstractSerialScenario 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 - } + + public interface ITestPackStorageDir { + /** called once test pack is copied/installed to storage dir. + * + * returns FALSE if shouldn't proceed with using test-pack on storage dir + * + * @param cm + * @param host + * @return + */ + boolean notifyTestPackInstalled(ConsoleManager cm, Host local_host); + + /** returns local path to access storage directory. + * + * this will be a drive that the storage dir is mounted on (if remote) or the actual location of the storage dir (if local) + * + * @param local_host + * @return + */ + String getLocalPath(Host local_host); + + /** returns TRUE if storage dir deleted + * + * @param cm + * @param host + * @return + */ + boolean delete(ConsoleManager cm, Host local_host); + } // end public interface ITestPackStorageDir + + public abstract ITestPackStorageDir createStorageDir(ConsoleManager cm, Host host); /** 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) { - - } -} +} // end public abstract class AbstractFileSystemScenario diff --git a/src/com/mostc/pftt/scenario/AbstractNetworkedServiceScenario.java b/src/com/mostc/pftt/scenario/AbstractNetworkedServiceScenario.java new file mode 100644 index 0000000..53c80b8 --- /dev/null +++ b/src/com/mostc/pftt/scenario/AbstractNetworkedServiceScenario.java @@ -0,0 +1,5 @@ +package com.mostc.pftt.scenario; + +public abstract class AbstractNetworkedServiceScenario extends AbstractParallelScenario { + +} diff --git a/src/com/mostc/pftt/scenario/AbstractSMBScenario.java b/src/com/mostc/pftt/scenario/AbstractSMBScenario.java index fee0b1b..47e6a1c 100644 --- a/src/com/mostc/pftt/scenario/AbstractSMBScenario.java +++ b/src/com/mostc/pftt/scenario/AbstractSMBScenario.java @@ -18,25 +18,22 @@ import com.mostc.pftt.util.StringUtil; public abstract class AbstractSMBScenario extends AbstractRemoteFileSystemScenario { protected final RemoteHost remote_host; protected final String base_file_path, base_share_name; - // file path is path on server where share is stored - // network path is in both UNC and URL format (UNC for Windows, URL for Linux) - protected String share_name, remote_path, unc_path, url_path, local_path; public AbstractSMBScenario(RemoteHost remote_host, String base_file_path, String base_share_name) { this.remote_host = remote_host; // if (StringUtil.isEmpty(base_file_path)) // fallback to a default path, @see SMBDeduplicationScenario - base_file_path = remote_host.isWindows() ? "C:\\PFTT_Share" : "/var/data/PFTT_Share"; + base_file_path = remote_host.isWindows() ? "C:\\PFTT-Share" : "/var/data/PFTT-Share"; else if (StringUtil.isEmpty(Host.basename(base_file_path))) // base_file_path ~= C:\ - base_file_path += "\\PFTT_Share"; + base_file_path += "\\PFTT-Share"; if (StringUtil.isNotEmpty(base_share_name)) base_share_name = base_share_name.trim(); if (StringUtil.isEmpty(base_share_name)) { base_share_name = Host.basename(base_file_path); if (StringUtil.isEmpty(base_share_name)) - base_share_name = "\\PFTT_Share"; + base_share_name = "\\PFTT-Share"; } // this.base_file_path = base_file_path; @@ -59,13 +56,50 @@ public abstract class AbstractSMBScenario extends AbstractRemoteFileSystemScenar * @return TRUE on success, FALSE on failure (can't use this storage if failure) */ @Override - public boolean notifyPrepareStorageDir(ConsoleManager cm, Host local_host) { - return createShare(cm) && connect(cm, local_host); + public SMBStorageDir createStorageDir(ConsoleManager cm, Host host) { + SMBStorageDir dir = newSMBStorageDir(); + + if ( createShare(dir, cm) ) { + if ( connect(dir, cm, host) ) { + return dir; + } + } + + // failed, try cleaning up + dir.delete(cm, host); + + return null; } + protected SMBStorageDir newSMBStorageDir() { + return new SMBStorageDir(); + } + + public class SMBStorageDir implements ITestPackStorageDir { + // file path is path on server where share is stored + // network path is in both UNC and URL format (UNC for Windows, URL for Linux) + protected String share_name, remote_path, unc_path, url_path, local_path; + + @Override + public boolean notifyTestPackInstalled(ConsoleManager cm, Host local_host) { + return true; + } + + @Override + public boolean delete(ConsoleManager cm, Host local_host) { + return disconnect(this, cm, local_host) && deleteShare(this, cm, local_host); + } + + @Override + public String getLocalPath(Host local_host) { + return local_path; // H: I: J: ... Y: + } + + } // end public class SMBStorageDir + @Override public boolean setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { - return createShare(cm); + return createShare(newSMBStorageDir(), cm); } public boolean shareExists(ConsoleManager cm, String share_name) { @@ -82,133 +116,143 @@ public abstract class AbstractSMBScenario extends AbstractRemoteFileSystemScenar return false; } - public boolean createShare(ConsoleManager cm) { + protected void makeShareName(SMBStorageDir dir, ConsoleManager cm) { // make a unique name for the share for ( int i=1 ; i < 65535 ; i++ ) { - remote_path = base_file_path + i; - share_name = base_share_name + i; - if (!remote_host.exists(remote_path)) { + dir.remote_path = base_file_path + "-" + i; + dir.share_name = base_share_name + "-" + i; + if (!remote_host.exists(dir.remote_path)) { // share may still exist, but at a different remote file path (double check to avoid `net share` failure) - if (!shareExists(cm, share_name)) { + if (!shareExists(cm, dir.share_name)) { break; } } } - // - cm.println(EPrintType.IN_PROGRESS, getName(), "Selected share_name="+share_name+" remote_path="+remote_path+" (base: "+base_file_path+" "+base_share_name+")"); + dir.unc_path = "\\\\"+remote_host.getHostname()+"\\"+dir.share_name; // for Windows + dir.url_path = "smb://"+remote_host.getHostname()+"/"+dir.share_name; // for linux + } // end protected void makeShareName + + protected boolean createShare(SMBStorageDir dir, ConsoleManager cm) { + makeShareName(dir, cm); + + cm.println(EPrintType.IN_PROGRESS, getName(), "Selected share_name="+dir.share_name+" remote_path="+dir.remote_path+" (base: "+base_file_path+" "+base_share_name+")"); try { if (remote_host.isWindows()) { - if (!createShareWindows(cm)) + if (!createShareWindows(dir, cm)) return false; - } else if (!createShareSamba()) { + } else if (!createShareSamba(dir, cm)) { return false; } } catch (Exception ex ) { - cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "createShare", ex, "", remote_host, remote_path, share_name); + cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "createShare", ex, "", remote_host, dir.remote_path, dir.share_name); return false; } - unc_path = "\\\\"+remote_host.getHostname()+"\\"+share_name; // for Windows - url_path = "smb://"+remote_host.getHostname()+"/"+share_name; // for linux - - cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Share created: unc="+unc_path+" remote_file="+remote_path+" url="+url_path); + cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Share created: unc="+dir.unc_path+" remote_file="+dir.remote_path+" url="+dir.url_path); return true; - } // end public boolean createShare + } // end protected boolean createShare - protected boolean createShareWindows(ConsoleManager cm) throws Exception { + protected boolean createShareWindows(SMBStorageDir dir, ConsoleManager cm) throws Exception { + return doCreateShareWindows(cm, dir.remote_path, dir.share_name); + } + + protected boolean doCreateShareWindows(ConsoleManager cm, String remote_path, String share_name) throws Exception { + remote_path = remote_path.replace("C", "G"); // TODO + remote_host.mkdirs(remote_path); - return remote_host.execElevated("NET SHARE "+share_name+"="+remote_path+" /Grant:"+remote_host.getUsername()+",Full", Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess(); + String cmd = "NET SHARE "+share_name+"="+remote_path+" /Grant:"+remote_host.getUsername()+",Full"; + System.out.println("cmd "+cmd); + return remote_host.execElevated(cmd, Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess(); } - protected boolean createShareSamba() { + protected boolean createShareSamba(SMBStorageDir dir, ConsoleManager cm) { // XXX return false; } - public boolean connect(ConsoleManager cm, Host local_host) { + protected boolean connect(SMBStorageDir dir, ConsoleManager cm, Host local_host) { if (remote_host.isRemote()) { try { if (remote_host.isWindows()) - return connectFromWindows(cm, local_host); + return connectFromWindows(dir, cm, local_host); else - return connectFromSamba(); + return connectFromSamba(dir, cm); } catch ( Exception ex ) { cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "connect", ex, "", remote_host, local_host); return false; } } else { // host is local, try using a local drive, normal file system operations, not SMB, etc... - local_path = remote_path; + dir.local_path = dir.remote_path; return true; } - } // end public boolean connect + } // end protected boolean connect protected static final String[] DRIVES = new String[]{"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y"}; // 18 - protected boolean connectFromWindows(ConsoleManager cm, Host local_host) throws Exception { - local_path = null; + protected boolean connectFromWindows(SMBStorageDir dir, ConsoleManager cm, Host local_host) throws Exception { + dir.local_path = null; for ( int i=0 ; i < DRIVES.length ; i++ ) { if (!local_host.exists(DRIVES[i] + ":\\")) { - local_path = DRIVES[i] + ":"; + dir.local_path = DRIVES[i] + ":"; break; } } - if (local_path==null) + if (dir.local_path==null) return false; - return local_host.execElevated("NET USE "+unc_path+" "+local_path+" /user:"+remote_host.getUsername()+" /password:"+remote_host.getPassword(), Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess(); + String cmd = "NET USE "+dir.local_path+" "+dir.unc_path+" /user:"+remote_host.getUsername()+" "+remote_host.getPassword(); + + return local_host.execElevated(cmd, Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess(); } - protected boolean connectFromSamba() { + protected boolean connectFromSamba(SMBStorageDir dir, ConsoleManager cm) { // XXX return false; } - @Override - public String getTestPackStorageDir(Host host) { - return local_path; // H: I: J: ... Y: + protected boolean deleteShare(SMBStorageDir dir, ConsoleManager cm, Host host) { + if (doDeleteShareWindows(cm, dir.remote_path)) { + cm.println(EPrintType.IN_PROGRESS, getClass(), "Share deleted: remote_file="+dir.remote_path+" unc="+dir.unc_path+" url="+dir.url_path); + + return true; + } else { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to delete share: remote_file="+dir.remote_path+" unc="+dir.unc_path); + + return false; + } } - public boolean deleteShare(ConsoleManager cm, Host host) { + protected boolean doDeleteShareWindows(ConsoleManager cm, String remote_path) { try { - if (host.execElevated("NET SHARE "+remote_path+" /DELETE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess()) { + if (remote_host.execElevated("NET SHARE "+remote_path+" /DELETE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess()) { try { - host.delete(remote_path); + remote_host.delete(remote_path); - cm.println(EPrintType.IN_PROGRESS, getClass(), "Share deleted: remote_file="+remote_path+" unc="+unc_path+" url="+url_path); + return true; } catch ( Exception ex ) { throw ex; } - - return true; } } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "deleteShare", ex, "", host, remote_path); + cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "deleteShare", ex, "", remote_host, remote_path); } return false; } - public boolean disconnect(ConsoleManager cm, Host host) { + protected boolean disconnect(SMBStorageDir dir, ConsoleManager cm, Host host) { try { - if (host.exec("NET USE "+local_path+" /DELETE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess()) { - cm.println(EPrintType.IN_PROGRESS, getClass(), "Disconnected share: local="+local_path); + if (host.exec("NET USE "+dir.local_path+" /DELETE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess()) { + cm.println(EPrintType.IN_PROGRESS, getClass(), "Disconnected share: local="+dir.local_path); } } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "disconnect", ex, "", host, local_path); + cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "disconnect", ex, "Unable to disconnect: local="+dir.local_path, host, dir.local_path); } return false; } - @Override - public void notifyFinishedTestPack(ConsoleManager cm, Host host) { - if (deleteShare(cm, host) && disconnect(cm, host)) { - // reset - share_name = remote_path = unc_path = url_path = local_path = null; - } - } - } // end public abstract class AbstractSMBScenario diff --git a/src/com/mostc/pftt/scenario/AbstractStreamsScenario.java b/src/com/mostc/pftt/scenario/AbstractStreamsScenario.java index 478019f..95735d9 100644 --- a/src/com/mostc/pftt/scenario/AbstractStreamsScenario.java +++ b/src/com/mostc/pftt/scenario/AbstractStreamsScenario.java @@ -1,5 +1,5 @@ package com.mostc.pftt.scenario; -public abstract class AbstractStreamsScenario extends AbstractParallelScenario { +public abstract class AbstractStreamsScenario extends AbstractNetworkedServiceScenario { } diff --git a/src/com/mostc/pftt/scenario/IMAPScenario.java b/src/com/mostc/pftt/scenario/IMAPScenario.java new file mode 100644 index 0000000..f4049d4 --- /dev/null +++ b/src/com/mostc/pftt/scenario/IMAPScenario.java @@ -0,0 +1,21 @@ +package com.mostc.pftt.scenario; + +/** scenario for interacting with IMAP mail servers + * + * @author Matt Ficken + * + */ + +public class IMAPScenario extends AbstractNetworkedServiceScenario { + + @Override + public String getName() { + return "IMAP"; + } + + @Override + public boolean isImplemented() { + return false; + } + +} diff --git a/src/com/mostc/pftt/scenario/LDAPScenario.java b/src/com/mostc/pftt/scenario/LDAPScenario.java index 998f67b..f2bfca3 100644 --- a/src/com/mostc/pftt/scenario/LDAPScenario.java +++ b/src/com/mostc/pftt/scenario/LDAPScenario.java @@ -4,7 +4,7 @@ package com.mostc.pftt.scenario; * */ -public class LDAPScenario extends AbstractParallelScenario { +public class LDAPScenario extends AbstractNetworkedServiceScenario { @Override public String getName() { diff --git a/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java b/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java index 0cf9780..4572894 100644 --- a/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java +++ b/src/com/mostc/pftt/scenario/LocalFileSystemScenario.java @@ -11,7 +11,22 @@ import com.mostc.pftt.results.ConsoleManager.EPrintType; */ public class LocalFileSystemScenario extends AbstractFileSystemScenario { - + protected static ITestPackStorageDir LOCAL_DIR = new ITestPackStorageDir() { + @Override + public boolean notifyTestPackInstalled(ConsoleManager cm, Host host) { + return true; + } + @Override + public String getLocalPath(Host host) { + return host.getPhpSdkDir(); + } + @Override + public boolean delete(ConsoleManager cm, Host host) { + return true; // don't actually delete php sdk + } + }; + + @Override public String getName() { return "Local-FileSystem"; @@ -28,19 +43,14 @@ public class LocalFileSystemScenario extends AbstractFileSystemScenario { } @Override - public boolean notifyPrepareStorageDir(ConsoleManager cm, Host host) { + public ITestPackStorageDir createStorageDir(ConsoleManager cm, Host host) { try { - host.mkdirs(getTestPackStorageDir(host)); - return true; + host.mkdirs(host.getPhpSdkDir()); + return LOCAL_DIR; } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.CANT_CONTINUE, LocalFileSystemScenario.class, "notifyPrepareStorageDir", ex, ""); - return false; + cm.addGlobalException(EPrintType.CANT_CONTINUE, LocalFileSystemScenario.class, "createStorageDir", ex, ""); + return null; } } - @Override - public String getTestPackStorageDir(Host host) { - return host.getPhpSdkDir(); - } - } // end public class LocalFileSystemScenario diff --git a/src/com/mostc/pftt/scenario/SMBBasicScenario.java b/src/com/mostc/pftt/scenario/SMBBasicScenario.java index cdfafac..990f3f0 100644 --- a/src/com/mostc/pftt/scenario/SMBBasicScenario.java +++ b/src/com/mostc/pftt/scenario/SMBBasicScenario.java @@ -4,6 +4,9 @@ import com.mostc.pftt.host.RemoteHost; /** Tests running a PHP build and its test pack both stored remotely on a basic SMB file share. * + * + * Typically, you'll create 1 instance of this for each remote file server, and each instance can create manage multiple shares at the same time. + * * @author Matt Ficken * */ diff --git a/src/com/mostc/pftt/scenario/SMBCAScenario.java b/src/com/mostc/pftt/scenario/SMBCAScenario.java index 22bf878..4e17064 100644 --- a/src/com/mostc/pftt/scenario/SMBCAScenario.java +++ b/src/com/mostc/pftt/scenario/SMBCAScenario.java @@ -24,8 +24,8 @@ public class SMBCAScenario extends AbstractSMBScenario { } @Override - protected boolean createShareWindows(ConsoleManager cm) throws Exception { - TempFileExecOutput teo = remote_host.powershell(getClass(), cm, "New-SmbShare -Name "+share_name+" -Path "+remote_path+" -Scope "+remote_host.getHostname()+" -FullControl "+remote_host.getHostname()+"\\"+remote_host.getUsername(), Host.ONE_MINUTE); + protected boolean createShareWindows(SMBStorageDir dir, ConsoleManager cm) throws Exception { + TempFileExecOutput teo = remote_host.powershell(getClass(), cm, "New-SmbShare -Name "+dir.share_name+" -Path "+dir.remote_path+" -Scope "+remote_host.getHostname()+" -FullControl "+remote_host.getHostname()+"\\"+remote_host.getUsername(), Host.ONE_MINUTE); teo.printOutputIfCrash(getClass(), cm); return teo.cleanupIfSuccess(remote_host); } diff --git a/src/com/mostc/pftt/scenario/SMBDFSRScenario.java b/src/com/mostc/pftt/scenario/SMBDFSRScenario.java deleted file mode 100644 index e0b8c5c..0000000 --- a/src/com/mostc/pftt/scenario/SMBDFSRScenario.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.mostc.pftt.scenario; - -import com.mostc.pftt.host.Host; -import com.mostc.pftt.host.RemoteHost; -import com.mostc.pftt.host.TempFileExecOutput; -import com.mostc.pftt.model.phpt.PhpBuild; -import com.mostc.pftt.results.ConsoleManager; -import com.mostc.pftt.results.ConsoleManager.EPrintType; - -/** Tests PHP with PHP build and test pack being stored remotely on a group of DFS-R SMB Shares. - * - * Web hosters can setup a share that is physically copied and served by multiple SMB Servers. - * - * According to the MS IIS team, this scenario is commonly used in production IIS deployments (ie they want it tested). - * - * This scenario is functionally similar to the newer Continuous-Availability concept in SMBv3, but presently DFS is more commonly used. - * - * There are two types of DFS, DFS-N and DFS-R, this tests DFS-R. DFS-N is not relevant because it only replicates a namespace(folder structure) - * across servers. DFS-R synchronizes folder contents efficiently between file servers across LANs and even WANs. - * - * @see `dfsutil`, `dfscmd` and `dfsdiag` and `fsutil reparsepoint query <file>` - * @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365511%28v=vs.85%29.aspx - * @author Matt Ficken - * - */ - -public class SMBDFSRScenario extends AbstractSMBScenario { - - // TODO PFTT-NS-1 PFTT-DFS-1 PFTT-TARGET-1 - // TODO use only ip addresses - // -still have problems with netbios name resolution - public SMBDFSRScenario(RemoteHost remote_host) { - this(remote_host, null, null); - } - - public SMBDFSRScenario(RemoteHost remote_host, String base_file_path, String base_share_name) { - super(remote_host, base_file_path, base_share_name); - } - - @Override - public String getName() { - return "SMB-DFSR"; - } - - @Override - public boolean setup(ConsoleManager cm, Host local_host, PhpBuild build, ScenarioSet scenario_set) { - StringBuilder ps_sb = new StringBuilder(); - ps_sb.append("Import-Module ServerManager\n"); - ps_sb.append("Add-WindowsFeature -name File-Services\n"); - ps_sb.append("Add-WindowsFeature -name FS-DFS\n"); - ps_sb.append("Add-WindowsFeature -name FS-DFS-Replication\n"); - - try { - TempFileExecOutput teo = remote_host.powershell(getClass(), cm, ps_sb, Host.FOUR_HOURS); - - if (teo.printOutputIfCrash(getClass(), cm).isSuccess()) { - teo.cleanup(remote_host); - - if (super.setup(cm, remote_host, build, scenario_set)) { - cm.println(EPrintType.COMPLETED_OPERATION, getName(), "DFSR setup successfully: unc="+unc_path+" remote_file="+remote_path); - - return true; - } - } else { - cm.println(EPrintType.OPERATION_FAILED_CONTINUING, getName(), "can't exec powershell script: "+ps_sb); - } - } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "setup", ex, "", remote_host, ps_sb, unc_path); - } - return false; - } - - @Override - public boolean isImplemented() { - return true; - } - -} // end public class SMBDFSRScenario diff --git a/src/com/mostc/pftt/scenario/SMBDFSScenario.java b/src/com/mostc/pftt/scenario/SMBDFSScenario.java new file mode 100644 index 0000000..e31ca95 --- /dev/null +++ b/src/com/mostc/pftt/scenario/SMBDFSScenario.java @@ -0,0 +1,235 @@ +package com.mostc.pftt.scenario; + +import com.mostc.pftt.host.Host; +import com.mostc.pftt.host.RemoteHost; +import com.mostc.pftt.host.TempFileExecOutput; +import com.mostc.pftt.model.phpt.PhpBuild; +import com.mostc.pftt.results.ConsoleManager; +import com.mostc.pftt.results.ConsoleManager.EPrintType; + +/** Tests PHP with PHP build and test pack being stored remotely on a group of DFS SMB Shares. + * + * Web hosters can setup a share that is physically copied and served by multiple SMB Servers. + * + * According to the MS IIS team, this scenario is commonly used in production IIS deployments (ie they want it tested). + * + * This scenario is functionally similar to the newer Continuous-Availability (CA) concept in SMBv3, but presently DFS is more commonly used. + * + * + * Typically, you'll create 1 instance of this for each remote file server, and each instance can create manage multiple shares at the same time. + * + * NOTE: There won't be any reparse points when remotely mounting a DFS share (the namespace, folder or target are not reparsepoints). + * `fsutil reparsepoint query` when run locally on the DFS server will return a reparse tag for the link, but not over the network. + * The DFS and DFSR reparsepoints are not anywhere on a DFS share (they are only used internally on the DFS server's filesystem). + * + * @see `dfsutil`, `dfscmd` and `dfsdiag` + * @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365511%28v=vs.85%29.aspx + * @author Matt Ficken + * + */ + +public class SMBDFSScenario extends AbstractSMBScenario { + protected final String base_namespace, base_remote_namespace, base_folder; + + public SMBDFSScenario(RemoteHost remote_host) { + // default: create PFTT-NS-n(namespace), PFTT-DFS-n(folder) and PFTT-SHARE-n(target) + this(remote_host, null, null, "PFTT-NS", "PFTT-NS", "PFTT-DFS"); + } + + public SMBDFSScenario(RemoteHost remote_host, String base_file_path, String base_share_name, String base_remote_namespace, String base_namespace, String base_folder) { + super(remote_host, base_file_path, base_share_name); + this.base_remote_namespace = base_remote_namespace; + this.base_namespace = base_namespace; + this.base_folder = base_folder; + } + + @Override + public String getName() { + return "SMB-DFS"; + } + + @Override + public boolean setup(ConsoleManager cm, Host local_host, PhpBuild build, ScenarioSet scenario_set) { + return installDFSFeature(cm, local_host) && super.setup(cm, local_host, build, scenario_set); + } + + @Override + public DFSSMBStorageDir createStorageDir(ConsoleManager cm, Host local_host) { + if (!remote_host.isWindows()) { + cm.println(EPrintType.XSKIP_OPERATION, getName(), "Scenario can only be run against a Windows host"); + return null; + } else { + DFSSMBStorageDir dir = (DFSSMBStorageDir) super.createStorageDir(cm, local_host); + if (dir==null) + return dir; // already would've done error msg + + cm.println(EPrintType.COMPLETED_OPERATION, getClass(), "Created DFS Share: unc_path="+dir.unc_path+" url="+dir.url_path+" (namespace="+dir.namespace+" folder="+dir.target+" local="+dir.local_path+")"); + + return dir; + } + } // end public DFSSMBStorageDir createStorageDir + + @Override + protected DFSSMBStorageDir newSMBStorageDir() { + return new DFSSMBStorageDir(); + } + + public class DFSSMBStorageDir extends SMBStorageDir { + // location on remote file system where the Share that stores the Namespace is + protected String remote_namespace; + // name of namespace + protected String namespace; + // target pointed to by folder in namespace (folder is represented by SMBStorageDir#unc_path, etc...) + protected String target; + // UNC path to namespace (including server address) + protected String unc_namespace_path; + // real File share that DFS will send referals pointing to + protected String unc_target; + // URL format + protected String url_namespace_path, url_target; + + @Override + public boolean delete(ConsoleManager cm, Host local_host) { + try { + // delete folder and link + if (!remote_host.execElevated("DFSUTIL LINK REMOVE "+unc_path, Host.ONE_MINUTE*10).printOutputIfCrash(getClass(), cm).isSuccess()) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to remove DFS Link"); + + disconnect(this, cm, local_host); + return false; + } + + // delete namespace + if (!remote_host.execElevated("DFSUTIL ROOT REMOVE "+unc_namespace_path, Host.ONE_MINUTE*10).printOutputIfCrash(getClass(), cm).isSuccess()) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Uanble to remove DFS Namespace"); + + disconnect(this, cm, local_host); + return false; + } + + if (!doDeleteShareWindows(cm, remote_namespace)) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to remove DFS Namespace Share"); + + disconnect(this, cm, local_host); + return false; + } + + // delete target share and disconnect + if (super.delete(cm, local_host)) { + cm.println(EPrintType.COMPLETED_OPERATION, getClass(), "Removed DFS share successfully."); + + return true; + } + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CANT_CONTINUE, getClass(), "delete", ex, "Unable to delete DFS Share"); + } + disconnect(this, cm, local_host); + + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to delete DFS Share! unc="+unc_namespace_path); + return false; + } // end public boolean delete + + } // end public class DFSSMBStorageDir + + @Override + protected void makeShareName(SMBStorageDir dir, ConsoleManager cm) { + DFSSMBStorageDir dfs_dir = (DFSSMBStorageDir) dir; + + // make a unique name for the share and namespace + for ( int i=1 ; i < 65535 ; i++ ) { + dir.remote_path = base_file_path + "-" + i; + dir.share_name = base_share_name + "-" + i; + // TODO getSystemDrive here + dfs_dir.remote_namespace = "G:\\"+base_remote_namespace + "-" + i; + dfs_dir.namespace = base_namespace + i; + dfs_dir.target = base_folder + i; + + if (!remote_host.exists(dir.remote_path) && !remote_host.exists(dfs_dir.remote_namespace)) { + // share may still exist, but at a different remote file path (double check to avoid `net share` failure) + if (!shareExists(cm, dir.share_name)) { + break; + } + } + } // end for + + // IMPORTANT: use IP addresses. there may be problems with name resolution on larger networks (ex: Microsoft CorpNet) + dfs_dir.unc_path = "\\\\"+remote_host.getAddress()+"\\"+dfs_dir.namespace+"\\"+dfs_dir.target; // for Windows + dfs_dir.unc_namespace_path = "\\\\"+remote_host.getAddress()+"\\"+dfs_dir.namespace; + dfs_dir.unc_target = "\\\\"+remote_host.getAddress()+"\\"+dfs_dir.target; + // + dfs_dir.url_path = "smb://"+remote_host.getAddress()+"/"+dfs_dir.namespace+"/"+dfs_dir.target; // for linux + dfs_dir.url_namespace_path = "smb://"+remote_host.getAddress()+"/"+dfs_dir.namespace; + dfs_dir.url_target = "smb://"+remote_host.getAddress()+"/"+dfs_dir.target; + } // end protected void makeShareName + + @Override + protected boolean createShareWindows(SMBStorageDir dir, ConsoleManager cm) throws Exception { + // create target share to create link to + if (!super.createShareWindows(dir, cm)) + return false; + DFSSMBStorageDir dfs_dir = (DFSSMBStorageDir) dir; + + // create namespace + if (!doCreateShareWindows(cm, dfs_dir.remote_namespace, dfs_dir.namespace)) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to create share for namespace!"); + + return false; + } + + if (!remote_host.execElevated("DFSUTIL ROOT ADDSTD "+dfs_dir.unc_namespace_path, Host.ONE_MINUTE*10).printOutputIfCrash(getClass(), cm).isSuccess()) { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to create namespace!"); + + return false; + } + + // create 1 link to the 1 target + if (remote_host.execElevated("DFSUTIL LINK ADD "+dfs_dir.unc_path+" "+dfs_dir.unc_target, Host.ONE_MINUTE*10).printOutputIfCrash(getClass(), cm).isSuccess()) { + cm.println(EPrintType.IN_PROGRESS, getClass(), "DFS link created"); + + cm.println(EPrintType.COMPLETED_OPERATION, getClass(), "DFS Share created. Done. unc_path="); + + return true; + } else { + cm.println(EPrintType.CANT_CONTINUE, getClass(), "Unable to add DFS link"); + + return false; + } + } // end protected boolean createShareWindows + + private boolean install_attempt, install_ok; + protected boolean installDFSFeature(ConsoleManager cm, Host local_host) { + if (install_attempt) + return install_ok; + install_attempt = true; + + StringBuilder ps_sb = new StringBuilder(); + ps_sb.append("Import-Module ServerManager\n"); + ps_sb.append("Add-WindowsFeature -name File-Services\n"); + ps_sb.append("Add-WindowsFeature -name FS-DFS\n"); + ps_sb.append("Add-WindowsFeature -name FS-DFS-Namespace\n"); + ps_sb.append("Add-WindowsFeature -name FS-DFS-Replication\n"); + + try { + TempFileExecOutput teo = remote_host.powershell(getClass(), cm, ps_sb, Host.FOUR_HOURS); + + if (teo.printOutputIfCrash(getClass(), cm).isSuccess()) { + teo.cleanup(remote_host); + + cm.println(EPrintType.COMPLETED_OPERATION, getName(), "DFS Feature Installed"); + + return install_ok = true; + } else { + cm.println(EPrintType.OPERATION_FAILED_CONTINUING, getName(), "can't exec powershell script: "+ps_sb); + } + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(), "installDFSFeature", ex, "", remote_host, ps_sb); + } + return install_ok = false; + } // end protected boolean installDFSFeature + + @Override + public boolean isImplemented() { + return true; + } + +} // end public class SMBDFSScenario diff --git a/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java b/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java index 43b54a3..cc8dc4f 100644 --- a/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java +++ b/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java @@ -1,5 +1,6 @@ package com.mostc.pftt.scenario; +import com.mostc.pftt.host.ExecOutput; import com.mostc.pftt.host.Host; import com.mostc.pftt.host.RemoteHost; import com.mostc.pftt.host.TempFileExecOutput; @@ -9,7 +10,10 @@ import com.mostc.pftt.results.ConsoleManager.EPrintType; /** Tests the new Remote Data Deduplication feature of Windows 2012 using SMB. * - * This feature broke PHP in php bug #63241. This scenario will catch that or any other problems Deduplication causes to PHP. + * This feature broke PHP in php bug #63241. This scenario will catch that or any other problems Deduplication causes for PHP. + * + * + * Typically, you'll create 1 instance of this for each remote file server, and each instance can create manage multiple shares at the same time. * * You can check if a file is deduplicated (on Windows) by running * `fsutil reparsepoint query [file]` @@ -28,7 +32,7 @@ public class SMBDeduplicationScenario extends AbstractSMBScenario { */ public SMBDeduplicationScenario(RemoteHost remote_host, String volume) { // making sure that non-null string passed prevents C:\ from being used (@see AbstractSMBScenario#<init>) - // important since the SystemDrive can't have deduplication enabled + // important since the SystemDrive(c:\) can't have deduplication enabled super(remote_host, volume, null); this.volume = volume; } @@ -45,34 +49,97 @@ public class SMBDeduplicationScenario extends AbstractSMBScenario { } @Override - public boolean setup(ConsoleManager cm, Host host, PhpBuild build, ScenarioSet scenario_set) { - return notifyPrepareStorageDir(cm, host); + public boolean setup(ConsoleManager cm, Host local_host, PhpBuild build, ScenarioSet scenario_set) { + return installDeduplicationFeature(cm, local_host) && super.setup(cm, local_host, build, scenario_set); } /** installs and enables deduplication on a remote disk Volume and creates a file share and connects to it. * * test-pack can then be installed on that file share. * - * @see #notifyTestPackInstalled * @param cm * @param local_host - * @return TRUE if success, FALSE if falure + * @return */ @Override - public boolean notifyPrepareStorageDir(ConsoleManager cm, Host local_host) { + public DeduplicatedSMBStorageDir createStorageDir(ConsoleManager cm, Host local_host) { // check that its win8 - System.out.println("64"); - // TODO - if (false) { // TODO !remote_host.isWin8OrLater()) { - System.out.println("66"); + if (!remote_host.isWin8OrLater()) { cm.println(EPrintType.XSKIP_OPERATION, getName(), "Scenario can only be run against a Windows 8/2012+ host"); - return false; + return null; } else if (volume.equals("C:")||remote_host.getSystemDrive().equalsIgnoreCase(volume)) { - System.out.println("70"); cm.println(EPrintType.XSKIP_OPERATION, getName(), "Can not use Deduplication on a Windows System Drive (ex: C:\\)"); + return null; + } + + if (installDeduplicationFeature(cm, local_host)) { + // create share on deduplicated volume + DeduplicatedSMBStorageDir dir = (DeduplicatedSMBStorageDir) super.createStorageDir(cm, local_host); + if (dir!=null) { + + cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Deduplication enabled for Share: unc="+dir.unc_path+" local="+dir.local_path+" url="+dir.url_path); + + return dir; + } + } + return null; + } // end public DeduplicatedSMBStorageDir createStorageDir + + protected DeduplicatedSMBStorageDir newSMBStorageDir() { + return new DeduplicatedSMBStorageDir(); + } + + public class DeduplicatedSMBStorageDir extends SMBStorageDir { + + /** runs a deduplication job after the test-pack is installed, blocking until the deduplication job is done. + * + * @param cm + * @param local_host + */ + @Override + public boolean notifyTestPackInstalled(ConsoleManager cm, Host local_host) { + try { + // run deduplication job (on test-pack) -wait for completion + cm.println(EPrintType.IN_PROGRESS, getName(), "Running deduplication job... unc="+unc_path+" local="+local_path+" remote_file="+remote_path+" url="+url_path); + if (remote_host.powershell(getClass(), cm, "Start-Dedupjob -Volume "+volume+" -Type Optimization", Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess()) { + + // + // log REPARSEPOINT QUERY to show if reparse point/deduplication was really setup + try { + int count = 0; + // pick a few files/folders... doing the share itself won't find a reparsepoint + for ( String file : remote_host.list(remote_path) ) { + ExecOutput out = remote_host.exec("FSUTIL REPARSEPOINT QUERY "+remote_path+"\\"+file, Host.ONE_MINUTE); + cm.println(EPrintType.CLUE, getName(), "REPARSEPOINT QUERY: "+remote_path+"\\"+file+"\n"+out.output); + + if (count++>3) + break; + } + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CLUE, getName(), ex, "reparsepoint query exception. ignoring, continuing..."); + } + // + // + + cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Deduplication completed successfully. unc="+unc_path+" local="+local_path+" remote_file="+remote_path+" url="+url_path); + return true; + } else { + cm.println(EPrintType.OPERATION_FAILED_CONTINUING, getName(), "Deduplication failed"); + } + } catch ( Exception ex ) { + cm.addGlobalException(EPrintType.CANT_CONTINUE, getName(), ex, "Deduplication failed", remote_host, local_host, volume); + } return false; } - System.out.println("74"); + + } // end public class DeduplicatedSMBStorageDir + + private boolean install_attempt, install_ok; + protected boolean installDeduplicationFeature(ConsoleManager cm, Host local_host) { + if (install_attempt) + return install_ok; + install_attempt = true; + StringBuilder ps_sb = new StringBuilder(128); // install deduplication feature ps_sb.append("Import-Module ServerManager\n"); @@ -81,52 +148,27 @@ public class SMBDeduplicationScenario extends AbstractSMBScenario { ps_sb.append("Import-Module Deduplication\n"); // enable deduplication for volume ps_sb.append("Enable-DedupVolume ");ps_sb.append(volume);ps_sb.append("\n"); - // change min file age (default is 5 days which will prevent testing test-packs now) + // CRITICAL: change min file age (default is 5 days which will prevent testing test-packs NOW) ps_sb.append("Set-DedupVolume ");ps_sb.append(volume);ps_sb.append(" -MinimumFileAgeDays 0\n"); // create PowerShell script to install and enable deduplication try { // - System.out.println("89"); - cm.println(EPrintType.IN_PROGRESS, getName(), "Starting to enable Deduplication on: "+remote_host); + cm.println(EPrintType.IN_PROGRESS, getName(), "Starting to Install Deduplication on: "+remote_host); TempFileExecOutput teo = remote_host.powershell(getClass(), cm, ps_sb, Host.ONE_MINUTE * 10); if (teo.printOutputIfCrash(getClass(), cm).isSuccess()) { // don't delete tmp_file if it failed to help user see why teo.cleanup(remote_host); - } - - // create share on volume - if (super.notifyPrepareStorageDir(cm, local_host)) { - cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Deduplication enabled on share: unc="+unc_path+" local="+local_path+" url="+url_path); - return true; - } - } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.CANT_CONTINUE, getClass(), "notifyPrepareStorageDir", ex, "Unable to enable deduplication", remote_host, ps_sb); - } - return false; - } // end public boolean notifyPrepareStorageDir - - /** runs a deduplication job after the test-pack is installed, blocking until the deduplication job is done. - * - * @param cm - * @param local_host - */ - @Override - public boolean notifyTestPackInstalled(ConsoleManager cm, Host local_host) { - try { - // run deduplication job (on test-pack) -wait for completion - cm.println(EPrintType.IN_PROGRESS, getName(), "Running deduplication job... unc="+unc_path+" local="+local_path+" remote_file="+remote_path+" url="+url_path); - if (remote_host.powershell(getClass(), cm, "Start-Dedupjob -Volume "+volume+" -Type Optimization", Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess()) { - cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Deduplication completed successfully. unc="+unc_path+" local="+local_path+" remote_file="+remote_path+" url="+url_path); - return true; - } else { - cm.println(EPrintType.OPERATION_FAILED_CONTINUING, getName(), "Deduplication failed"); + + cm.println(EPrintType.IN_PROGRESS, getName(), "Deduplication Feature Installed."); + + return install_ok = true; } } catch ( Exception ex ) { - cm.addGlobalException(EPrintType.CANT_CONTINUE, getClass(), "notifyTestPackInstalled", ex, "Deduplication failed", remote_host, local_host, volume); + cm.addGlobalException(EPrintType.CANT_CONTINUE, getName(), ex, "Unable to Install Deduplication feature", remote_host, ps_sb); } - return false; - } // end public boolean notifyTestPackInstalled + return install_ok = false; + } // end protected boolean installDeduplicationFeature @Override public String getName() { diff --git a/src/com/mostc/pftt/scenario/SOAPScenario.java b/src/com/mostc/pftt/scenario/SOAPScenario.java index ce9959e..577fe09 100644 --- a/src/com/mostc/pftt/scenario/SOAPScenario.java +++ b/src/com/mostc/pftt/scenario/SOAPScenario.java @@ -6,7 +6,7 @@ package com.mostc.pftt.scenario; * */ -public class SOAPScenario extends AbstractParallelScenario { +public class SOAPScenario extends AbstractNetworkedServiceScenario { @Override public String getName() { diff --git a/src/com/mostc/pftt/scenario/XMLRPCScenario.java b/src/com/mostc/pftt/scenario/XMLRPCScenario.java index 173d0fa..1947be9 100644 --- a/src/com/mostc/pftt/scenario/XMLRPCScenario.java +++ b/src/com/mostc/pftt/scenario/XMLRPCScenario.java @@ -6,7 +6,7 @@ package com.mostc.pftt.scenario; * */ -public class XMLRPCScenario extends AbstractParallelScenario { +public class XMLRPCScenario extends AbstractNetworkedServiceScenario { @Override public String getName() {