Commit: 26701b6fd15e9d5efa8218a60b9af5135959e40e
Author: Matt Ficken <[email protected]> Thu, 24 Jan 2013
00:13:53 -0800
Parents: 602a73184c083b98c83afc29f42dfe2816c7bba0
Branches: master
Link:
http://git.php.net/?p=pftt2.git;a=commitdiff;h=26701b6fd15e9d5efa8218a60b9af5135959e40e
Log:
various bug fixes
Former-commit-id: 3f4f4643d17c32346430d7d0259ba7be0fd4b4b3
Changed paths:
M .classpath
A bin/SetACL.exe
M bin/pftt.cmd
A bin/ssh_server.cmd
D lib/SSHD_fat.jar
A lib/log4j-1.2.17.jar
D lib/slf4j-api-1.6.6.jar
A lib/slf4j-api-1.7.2.jar
A lib/slf4j-log4j12-1.7.2.jar
M src/com/github/mattficken/io/ByteArrayIOStream.java
M src/com/mostc/pftt/host/ExecOutput.java
M src/com/mostc/pftt/host/Host.java
M src/com/mostc/pftt/host/SSHHost.java
A src/com/mostc/pftt/host/TempFileExecOutput.java
M src/com/mostc/pftt/main/PfttMain.java
M src/com/mostc/pftt/main/SSHServer.java
M src/com/mostc/pftt/model/phpt/PhpBuild.java
M src/com/mostc/pftt/model/phpt/PhpIni.java
M src/com/mostc/pftt/model/phpt/PhptTestCase.java
M src/com/mostc/pftt/model/smoke/RequiredExtensionsSmokeTest.java
M src/com/mostc/pftt/model/smoke/RequiredFeaturesSmokeTest.java
M src/com/mostc/pftt/model/ui/wordpress.groovy
M src/com/mostc/pftt/results/PhptResultPack.java
M src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner.java
M src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
M src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
M src/com/mostc/pftt/runner/HttpTestCaseRunner.java
M src/com/mostc/pftt/scenario/AbstractParallelScenario.java
M src/com/mostc/pftt/scenario/AbstractSAPIScenario.java
M src/com/mostc/pftt/scenario/AbstractSMBScenario.java
M src/com/mostc/pftt/scenario/AbstractWebServerScenario.java
M src/com/mostc/pftt/scenario/CLIScenario.java
M src/com/mostc/pftt/scenario/NoCodeCacheScenario.java
M src/com/mostc/pftt/scenario/NoDebugScenario.java
M src/com/mostc/pftt/scenario/PlainSocketScenario.java
M src/com/mostc/pftt/scenario/SMBBasicScenario.java
M src/com/mostc/pftt/scenario/SMBCAScenario.java
M src/com/mostc/pftt/scenario/SMBDFSRScenario.java
M src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
M src/com/mostc/pftt/scenario/Scenario.java
M src/com/mostc/pftt/scenario/ScenarioSet.java
M src/com/mostc/pftt/ui/PhptHostTab.java
M src/com/mostc/pftt/util/StringUtil.java
M src/org/apache/sshd/server/filesystem/NativeSshFile.java
diff --git a/.classpath b/.classpath
index 0df8458..790b3df 100644
--- a/.classpath
+++ b/.classpath
@@ -21,7 +21,6 @@
<classpathentry kind="lib" path="lib/asm-tree-3.2.jar"/>
<classpathentry kind="lib" path="lib/asm-util-3.2.jar"/>
<classpathentry kind="lib" path="lib/winp-1.14.jar"/>
- <classpathentry kind="lib" path="lib/SSHD_fat.jar"/>
<classpathentry kind="lib" path="lib/commons-net-3.1.jar"/>
<classpathentry kind="lib" path="lib/commons-codec-1.6.jar"/>
<classpathentry kind="lib" path="lib/commons-lang-2.6.jar"/>
@@ -29,6 +28,8 @@
<classpathentry kind="lib" path="lib/jzlib-1.1.1.jar"/>
<classpathentry kind="lib" path="lib/mina-core-2.0.7.jar"/>
<classpathentry kind="lib" path="lib/mina-statemachine-2.0.7.jar"/>
- <classpathentry kind="lib" path="lib/slf4j-api-1.6.6.jar"/>
+ <classpathentry kind="lib" path="lib/slf4j-api-1.7.2.jar"/>
+ <classpathentry kind="lib" path="lib/slf4j-log4j12-1.7.2.jar"/>
+ <classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>
<classpathentry kind="output" path="build"/>
</classpath>
diff --git a/bin/SetACL.exe b/bin/SetACL.exe
new file mode 100644
index 0000000..0ac0dfb
Binary files /dev/null and b/bin/SetACL.exe differ
diff --git a/bin/pftt.cmd b/bin/pftt.cmd
index cb97260..43b77d2 100644
--- a/bin/pftt.cmd
+++ b/bin/pftt.cmd
@@ -5,7 +5,7 @@ REM set important env vars
CALL set_env
SET PFTT_LIB=%PFTT_HOME%\lib
-SET
CLASSPATH=%PFTT_HOME%\build;%PFTT_LIB%\winp-1.14.jar;%PFTT_LIB%\htmlcleaner-2.2.jar;%PFTT_LIB%\groovy-1.8.6.jar;%PFTT_LIB%\icu4j-49_1.jar;%PFTT_LIB%\icudata.jar;%PFTT_LIB%\icutzdata.jar;%PFTT_LIB%\j2ssh-common-0.2.9.jar;%PFTT_LIB%\j2ssh-core-0.2.9.jar;%PFTT_LIB%\jansi-1.7.jar;%PFTT_LIB%\jline-0.9.94.jar;%PFTT_LIB%\jzlib-1.0.7.jar;%PFTT_LIB%\selenium-server-standalone-2.19.0.jar;%PFTT_LIB%\xercesImpl.jar;%PFTT_LIB%\xmlpull-1.1.3.1.jar;%PFTT_LIB%\commons-net-3.1.jar;%PFTT_LIB%\commons-cli-1.2.jar;%PFTT_LIB%\antlr-2.7.7.jar;%PFTT_LIB%\asm-3.2.jar;%PFTT_LIB%\asm-analysis-3.2.jar;%PFTT_LIB%\asm-commons-3.2.jar;%PFTT_LIB%\asm-tree-3.2.jar;%PFTT_LIB%\asm-util-3.2.jar
+SET
CLASSPATH=%PFTT_HOME%\build;%PFTT_LIB%\htmlcleaner-2.2.jar;%PFTT_LIB%\groovy-1.8.6.jar;%PFTT_LIB%\icu4j-49_1.jar;%PFTT_LIB%\icudata.jar;%PFTT_LIB%\icutzdata.jar;%PFTT_LIB%\jansi-1.7.jar;%PFTT_LIB%\jline-0.9.94.jar;%PFTT_LIB%\selenium-server-standalone-2.19.0.jar;%PFTT_LIB%\xercesImpl.jar;%PFTT_LIB%\xmlpull-1.1.3.1.jar;%PFTT_LIB%\commons-cli-1.2.jar;%PFTT_LIB%\antlr-2.7.7.jar;%PFTT_LIB%\asm-3.2.jar;%PFTT_LIB%\asm-analysis-3.2.jar;%PFTT_LIB%\asm-commons-3.2.jar;%PFTT_LIB%\asm-tree-3.2.jar;%PFTT_LIB%\asm-util-3.2.jar;%PFTT_LIB%\winp-1.14.jar;%PFTT_LIB%\commons-net-3.1.jar;%PFTT_LIB%\commons-codec-1.6.jar;%PFTT_LIB%\commons-lang-2.6.jar;%PFTT_LIB%\commons-logging-1.1.1.jar;%PFTT_LIB%\jzlib-1.1.1.jar;%PFTT_LIB%\mina-core-2.0.7.jar;%PFTT_LIB%\mina-statemachine-2.0.7.jar;%PFTT_LIB%\slf4j-api-1.7.2.jar;%PFTT_LIB%\slf4j-log4j12-1.7.2.jar
REM if user added -uac or -auto or -windebug console options, run elevated in
UAC
diff --git a/bin/ssh_server.cmd b/bin/ssh_server.cmd
new file mode 100644
index 0000000..34508ad
--- /dev/null
+++ b/bin/ssh_server.cmd
@@ -0,0 +1,62 @@
+@ECHO off
+REM script for running SSH Server on Windows
+
+CALL set_env
+SET PFTT_LIB=%PFTT_HOME%\lib
+
+SET
CLASSPATH=%PFTT_HOME%\build;%PFTT_LIB%\commons-cli-1.2.jar;%PFTT_LIB%\winp-1.14.jar;%PFTT_LIB%\commons-net-3.1.jar;%PFTT_LIB%\commons-codec-1.6.jar;%PFTT_LIB%\commons-lang-2.6.jar;%PFTT_LIB%\commons-logging-1.1.1.jar;%PFTT_LIB%\jzlib-1.1.1.jar;%PFTT_LIB%\mina-core-2.0.7.jar;%PFTT_LIB%\mina-statemachine-2.0.7.jar;%PFTT_LIB%\slf4j-api-1.7.2.jar;%PFTT_LIB%\slf4j-log4j12-1.7.2.jar
+
+
+:run_it
+
+
+REM find java.exe
+IF [%JAVA_EXE%] == [] (
+ IF EXIST "%JAVA_HOME%\lib\tools.jar" (
+ SET JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+ ) ELSE (
+ IF [%JAVA_EXE%] == [] (
+ IF EXIST "%ProgramFiles%\java\jre6\bin\java.exe" (
+ SET
JAVA_EXE="%ProgramFiles%\java\jre6\bin\java.exe"
+ SET JAVA_HOME="%ProgramFiles%\java\jre6"
+ ) ELSE (
+ IF EXIST
"%ProgramFiles(x86)%\java\jre6\bin\java.exe" (
+ SET
JAVA_EXE="%ProgramFiles(x86)%\java\jre6\bin\java.exe"
+ SET
JAVA_HOME="%ProgramFiles(x86)%\java\jre6"
+ ) ELSE (
+ IF EXIST
"%ProgramFiles%\java\jre7\bin\java.exe" (
+ SET
JAVA_EXE="%ProgramFiles%\java\jre7\bin\java.exe"
+ SET
JAVA_HOME="%ProgramFiles%\java\jre7"
+ ) ELSE (
+ IF EXIST
"%ProgramFiles(x86)%\java\jre7\bin\java.exe" (
+ SET
JAVA_EXE="%ProgramFiles(x86)%\java\jre7\bin\java.exe"
+ SET
JAVA_HOME="%ProgramFiles(x86)%\java\jre7"
+ )
+ )
+ )
+ )
+ )
+ )
+)
+
+IF [%JAVA_EXE%] == [] (
+ REM check PATH last. it might find java.exe in \Windows\System32\java
+ REM which elevate.exe can't find/execute for some weird reason
+ WHERE java > pftt_cmd.tmp
+
+ IF %ERRORLEVEL% EQU 0 (
+ REM found java.exe in PATH
+ SET /p JAVA_EXE= < pftt_cmd.tmp
+ ) ELSE (
+ REM can't find java jre
+ ECHO java may not be installed. Must Install Sun Java JRE 6 or
7.
+ ECHO user error set JAVA_HOME or add java to PATH and try again
+ DEL /Q pftt_cmd.tmp
+ EXIT /B 200
+ )
+
+ DEL /Q pftt_cmd.tmp
+)
+
+REM finally execute
+%ELEVATOR% %JAVA_EXE% -classpath %CLASSPATH% com.mostc.pftt.main.SSHServer %*
diff --git a/lib/SSHD_fat.jar b/lib/SSHD_fat.jar
deleted file mode 100644
index 5224f2a..0000000
Binary files a/lib/SSHD_fat.jar and /dev/null differ
diff --git a/lib/log4j-1.2.17.jar b/lib/log4j-1.2.17.jar
new file mode 100644
index 0000000..068867e
Binary files /dev/null and b/lib/log4j-1.2.17.jar differ
diff --git a/lib/slf4j-api-1.6.6.jar b/lib/slf4j-api-1.6.6.jar
deleted file mode 100644
index 4c03fa6..0000000
Binary files a/lib/slf4j-api-1.6.6.jar and /dev/null differ
diff --git a/lib/slf4j-api-1.7.2.jar b/lib/slf4j-api-1.7.2.jar
new file mode 100644
index 0000000..73f38db
Binary files /dev/null and b/lib/slf4j-api-1.7.2.jar differ
diff --git a/lib/slf4j-log4j12-1.7.2.jar b/lib/slf4j-log4j12-1.7.2.jar
new file mode 100644
index 0000000..37a85d7
Binary files /dev/null and b/lib/slf4j-log4j12-1.7.2.jar differ
diff --git a/src/com/github/mattficken/io/ByteArrayIOStream.java
b/src/com/github/mattficken/io/ByteArrayIOStream.java
index 73f8df8..476306a 100644
--- a/src/com/github/mattficken/io/ByteArrayIOStream.java
+++ b/src/com/github/mattficken/io/ByteArrayIOStream.java
@@ -29,6 +29,11 @@ public class ByteArrayIOStream extends OutputStream {
return new ByteArrayInStream();
}
+ @Override
+ public String toString() {
+ return new String(buf, 0, count);
+ }
+
public class ByteArrayInStream extends InputStream {
protected int pos;
diff --git a/src/com/mostc/pftt/host/ExecOutput.java
b/src/com/mostc/pftt/host/ExecOutput.java
index e31a9a4..e571454 100644
--- a/src/com/mostc/pftt/host/ExecOutput.java
+++ b/src/com/mostc/pftt/host/ExecOutput.java
@@ -48,8 +48,13 @@ public class ExecOutput {
return printOutputIfCrash(ctx.getSimpleName(), ps);
}
public ExecOutput printOutputIfCrash(String ctx, PrintStream ps) {
- if (ps!=null && isCrashed())
- ps.println(ctx+": "+output.trim());
+ if (ps!=null && isCrashed()) {
+ String output_str = output.trim();
+ if (StringUtil.isEmpty(output_str))
+ output_str = "<Crash with no output.
exit_code="+exit_code+">";
+
+ ps.println(ctx+": "+output_str);
+ }
return this;
}
} // end public class ExecOutput
diff --git a/src/com/mostc/pftt/host/Host.java
b/src/com/mostc/pftt/host/Host.java
index 9aa99c0..b56b485 100644
--- a/src/com/mostc/pftt/host/Host.java
+++ b/src/com/mostc/pftt/host/Host.java
@@ -448,10 +448,19 @@ public abstract class Host {
public ExecOutput execElevated(String cmd, int timeout_sec, Map<String,
String> env, byte[] stdin_data, Charset charset, String chdir) throws Exception
{
return execElevated(cmd, timeout_sec, env, stdin_data, charset,
chdir, null, FOUR_HOURS);
}
+ private boolean checked_elevate, found_elevate;
public ExecOutput execElevated(String cmd, int timeout_sec, Map<String,
String> env, byte[] stdin_data, Charset charset, String chdir,
TestPackRunnerThread test_thread, int slow_timeout_sec) throws Exception {
- if (isWindows())
- // execute command with this utility that will elevate
the program using Windows UAC
- cmd = getPfttDir() + "\\bin\\elevate "+cmd;
+ if (isWindows()) {
+ if (!checked_elevate) {
+ found_elevate =
exists(getPfttDir()+"\\bin\\elevate.exe");
+
+ checked_elevate = true;
+ }
+ if (found_elevate) {
+ // execute command with this utility that will
elevate the program using Windows UAC
+ cmd = getPfttDir() + "\\bin\\elevate "+cmd;
+ }
+ }
return exec(cmd, timeout_sec, env, stdin_data, charset, chdir,
test_thread, slow_timeout_sec);
}
@@ -802,6 +811,7 @@ public abstract class Host {
if (!isWindows())
return false;
String os_name = getOSNameOnWindows();
+ System.out.println(os_name);
return os_name.contains("Windows 8") ||
os_name.contains("Windows 2012") || os_name.contains("Windows 9") ||
os_name.contains("Windows 2014");
}
@@ -972,4 +982,38 @@ public abstract class Host {
}
}
+ /** executes Powershell code and returns output.
+ *
+ * Takes care of making a temporary file, storing the powershell code,
executing it, then cleaning up.
+ *
+ * @param ctx
+ * @param cm
+ * @param ps_code - powershell code to execute (not filename)
+ * @param timeout - max time to allow powershell to run
+ * @return
+ * @throws Exception
+ */
+ public TempFileExecOutput powershell(Class<?> ctx, ConsoleManager cm,
CharSequence ps_code, int timeout) throws Exception {
+ return powershell(ctx==null?null:ctx.getSimpleName(), cm,
ps_code, timeout);
+ }
+
+ private boolean set_unrestricted;
+ public TempFileExecOutput powershell(String ctx_str, ConsoleManager cm,
CharSequence ps_code, int timeout) throws Exception {
+ if (!isWindows())
+ throw new IllegalStateException("powershell is only
supported on Windows");
+
+ if (!set_unrestricted) {
+ // do this once
+ execElevated("powershell -Command \"set-executionpolicy
unrestricted\"", Host.ONE_MINUTE).printOutputIfCrash(ctx_str, cm);
+
+ set_unrestricted = true;
+ }
+
+ String temp_file = mktempname(ctx_str, ".ps1");
+
+ saveTextFile(temp_file, ps_code.toString());
+
+ return new TempFileExecOutput(temp_file,
execElevated("Powershell -File "+temp_file, timeout));
+ }
+
} // end public abstract class Host
diff --git a/src/com/mostc/pftt/host/SSHHost.java
b/src/com/mostc/pftt/host/SSHHost.java
index d38213a..04dd4bb 100644
--- a/src/com/mostc/pftt/host/SSHHost.java
+++ b/src/com/mostc/pftt/host/SSHHost.java
@@ -1,6 +1,5 @@
package com.mostc.pftt.host;
-import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -17,26 +16,23 @@ import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
-import com.github.mattficken.io.AbstractDetectingCharsetReader;
+import javax.annotation.Nullable;
+
import com.github.mattficken.io.ByLineReader;
import com.github.mattficken.io.ByteArrayIOStream;
import com.github.mattficken.io.CharsetByLineReader;
import com.github.mattficken.io.CharsetDeciderDecoder;
-import com.github.mattficken.io.DefaultCharsetDeciderDecoder;
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.runner.AbstractTestPackRunner.TestPackRunnerThread;
import com.mostc.pftt.util.StringUtil;
-import com.sshtools.j2ssh.ScpClient;
import com.sshtools.j2ssh.SftpClient;
import com.sshtools.j2ssh.SshClient;
import com.sshtools.j2ssh.authentication.AuthenticationProtocolState;
@@ -78,7 +74,9 @@ import com.sshtools.j2ssh.transport.publickey.SshPublicKey;
* -OpenSSH on Linux
* -Apache Mina-SSH on Windows
*
- * SSH Server must support SESSION, SFTP and SCP channels (most do).
+ * SSH Server must support SESSION and SFTP channels (SCP channel not required)
+ *
+ * NOTE: added 1 line to SftpClient#resolveRemotePath to support checking for
[letter]:\ on Windows
*
* @author Matt Ficken
*
@@ -86,13 +84,18 @@ import com.sshtools.j2ssh.transport.publickey.SshPublicKey;
public class SSHHost extends RemoteHost {
private static final Timer timer = new Timer();
- protected final String hostname, username, password;
+ protected String address, hostname;
+ protected final String username, password;
protected final int port;
+ protected final HostKeyVerification verif;
protected boolean closed, login_fail;
- protected String address, os_name_long;
+ @Nullable
+ protected String os_name_long;
+ @Nullable
protected Boolean is_windows;
+ @Nullable
protected SshClient ssh;
- protected ScpClient scp;
+ @Nullable
protected SftpClient sftp;
public SSHHost(String hostname, String username, String password) {
@@ -100,11 +103,32 @@ public class SSHHost extends RemoteHost {
}
public SSHHost(String hostname, int port, String username, String
password) {
+ this(hostname, port, username, password, new
HostKeyVerification() {
+ @Override
+ public boolean verifyHost(String host,
SshPublicKey pk) throws TransportProtocolException {
+ return true;
+ }
+ });
+ }
+
+ public SSHHost(String hostname, String username, String password,
HostKeyVerification verif) {
+ this(hostname, 22, username, password, verif);
+ }
+
+ public SSHHost(String hostname, int port, String username, String
password, HostKeyVerification verif) {
+ this.address = hostname;
+
+ if (hostname.contains(".")||hostname.contains(":")) {
+ // use address instead, then ask actual hostname once
connected
+ // @see #ensureSshOpen
+ hostname = null;
+ }
+
this.hostname = hostname;
this.port = port;
this.username = username;
this.password = password;
- this.address = hostname;
+ this.verif = verif;
}
protected String normalizePath(String path) {
@@ -120,16 +144,13 @@ public class SSHHost extends RemoteHost {
throw new IllegalStateException("SSH connection
administratively/explicitly closed");
do_close(); // ensure any existing ssh, sftp or scp client gets
closed (for gc)
- address = InetAddress.getByName(hostname).getHostAddress();
-
+ if (hostname!=null) {
+ // address isn't IP address (its hostname), resolve it
now @see SSHHost#<init>
+ address =
InetAddress.getByName(hostname).getHostAddress();
+ }
ssh = new SshClient();
- ssh.connect(address, port, new HostKeyVerification() {
- @Override
- public boolean verifyHost(String host,
SshPublicKey pk) throws TransportProtocolException {
- return true;
- }
- });
+ ssh.connect(address, port, verif);
PasswordAuthenticationClient pwd = new
PasswordAuthenticationClient();
@@ -141,14 +162,12 @@ public class SSHHost extends RemoteHost {
login_fail = true; // IllegalStateException below may
get caught/ignored
throw new IllegalStateException("authentication failed.
attempted login as user: "+username+" using password: "+password+" on host:
"+hostname+":"+port+" ("+address+":"+port+")");
}
- }
-
- protected void ensureScpOpen() throws UnknownHostException, IOException
{
- if (!login_fail && scp != null)
- return;
- ensureSshOpen();
- scp = ssh.openScpClient();
- }
+
+ if (hostname==null) {
+ // only have ip address, get hostname
+ hostname = isWindows() ? getEnvValue("COMPUTERNAME") :
getEnvValue("HOSTNAME");
+ }
+ } // end protected void ensureSshOpen
protected void ensureSftpOpen() throws UnknownHostException,
IOException {
if (!login_fail && sftp != null && !sftp.isClosed())
@@ -176,7 +195,6 @@ public class SSHHost extends RemoteHost {
}
sftp = null;
}
- scp = null;
if (ssh!=null) {
ssh.disconnect();
ssh = null;
@@ -227,7 +245,8 @@ public class SSHHost extends RemoteHost {
FileAttributes fa = sftp.stat(normalizePath(path));
return fa.isFile() || fa.isDirectory();
} catch ( Exception ex ) {
- ex.printStackTrace();
+ // throws Exception if it doesn't exist
+ //ex.printStackTrace();
}
return false;
}
@@ -262,8 +281,10 @@ public class SSHHost extends RemoteHost {
@Override
public String getContents(String file) throws IOException {
- ensureScpOpen();
- NoCharsetByLineReader reader = new
NoCharsetByLineReader(scp.get(normalizePath(file)));
+ ensureSftpOpen();
+ ByteArrayIOStream local = new ByteArrayIOStream(1024);
+ sftp.get(normalizePath(file), local);
+ NoCharsetByLineReader reader = new
NoCharsetByLineReader(local.getInputStream());
String str = IOUtil.toString(reader, IOUtil.HALF_MEGABYTE);
reader.close();
return str;
@@ -271,8 +292,10 @@ public class SSHHost extends RemoteHost {
@Override
public String getContentsDetectCharset(String file,
CharsetDeciderDecoder cdd) throws IOException {
- ensureScpOpen();
- MultiCharsetByLineReader reader = new
MultiCharsetByLineReader(scp.get(normalizePath(file)), cdd);
+ ensureSftpOpen();
+ ByteArrayIOStream local = new ByteArrayIOStream(1024);
+ sftp.get(normalizePath(file), local);
+ MultiCharsetByLineReader reader = new
MultiCharsetByLineReader(local.getInputStream(), cdd);
String str = IOUtil.toString(reader, IOUtil.HALF_MEGABYTE);
reader.close();
return str;
@@ -280,14 +303,18 @@ public class SSHHost extends RemoteHost {
@Override
public ByLineReader readFile(String file) throws FileNotFoundException,
IOException {
- ensureScpOpen();
- return new NoCharsetByLineReader(scp.get(normalizePath(file)));
+ ensureSftpOpen();
+ ByteArrayIOStream local = new ByteArrayIOStream(1024);
+ sftp.get(normalizePath(file), local);
+ return new NoCharsetByLineReader(local.getInputStream());
}
@Override
public ByLineReader readFileDetectCharset(String file,
CharsetDeciderDecoder cdd) throws FileNotFoundException, IOException {
- ensureScpOpen();
- return new
MultiCharsetByLineReader(scp.get(normalizePath(file)), cdd);
+ ensureSftpOpen();
+ ByteArrayIOStream local = new ByteArrayIOStream(1024);
+ sftp.get(normalizePath(file), local);
+ return new MultiCharsetByLineReader(local.getInputStream(),
cdd);
}
@Override
@@ -385,7 +412,7 @@ public class SSHHost extends RemoteHost {
//
final AtomicBoolean run = new AtomicBoolean(true);
final SessionChannelClient session = do_exec(cmd, env, chdir,
stdin_post, out);
- if (timeout>FOUR_HOURS) {
+ if (timeout>NO_TIMEOUT) {
timer.schedule(new TimerTask() {
public void run() {
try {
@@ -408,7 +435,7 @@ public class SSHHost extends RemoteHost {
//
// read output from command
- StringBuilder sb = new StringBuilder(1024);
+ /* TODO StringBuilder sb = new StringBuilder(1024);
DefaultCharsetDeciderDecoder d = charset == null ? null :
PhptTestCase.newCharsetDeciderDecoder();
ByLineReader reader = charset == null ? new
NoCharsetByLineReader(out.getInputStream()) : new
MultiCharsetByLineReader(out.getInputStream(), d);
String line;
@@ -424,16 +451,16 @@ public class SSHHost extends RemoteHost {
//ex.printStackTrace();
}
- out.close();
+ out.close();*/
// wait for exit
session.getState().waitForState(ChannelState.CHANNEL_CLOSED);
//
eo.exit_code = session.getExitCode();
- if (reader instanceof AbstractDetectingCharsetReader)
- eo.charset =
((AbstractDetectingCharsetReader)reader).cs;
- eo.output = sb.toString();
+ /* TODO if (reader instanceof AbstractDetectingCharsetReader)
+ eo.charset =
((AbstractDetectingCharsetReader)reader).cs; */
+ eo.output = out.toString();
//
return eo;
@@ -458,7 +485,7 @@ public class SSHHost extends RemoteHost {
public String getEnvValue(String name) {
try {
if (isWindows())
- return cmd("ECHO %"+name+"%",
ONE_MINUTE).output;
+ return StringUtil.chomp(cmd("ECHO %"+name+"%",
ONE_MINUTE).output);
else
return exec("echo $"+name, ONE_MINUTE).output;
} catch ( Exception ex ) {
@@ -492,34 +519,33 @@ public class SSHHost extends RemoteHost {
@Override
public void download(String src, String dst) throws
IllegalStateException, IOException, Exception {
- ensureScpOpen();
- IOUtil.copy(scp.get(normalizePath(src)), new
BufferedOutputStream(new FileOutputStream(dst)), IOUtil.HALF_MEGABYTE);
+ ensureSftpOpen();
+ sftp.get(normalizePath(src), new BufferedOutputStream(new
FileOutputStream(dst)));
}
- protected static void walk(File[] files, LinkedList<String> file_list) {
+ protected void do_upload(String base, File[] files, String dst) throws
IOException {
for (File file : files) {
- if (file.isDirectory())
- walk(file.listFiles(), file_list);
- else
- file_list.add(file.getAbsolutePath());
+ if (file.isDirectory()) {
+ do_upload(base, file.listFiles(), dst);
+ } else {
+ String remote_file_path = joinIntoOnePath(dst,
pathFrom(base, file.getAbsolutePath()));
+
+ sftp.put(file.getAbsolutePath(),
remote_file_path);
+ }
}
}
@Override
- public void upload(String src, String dst) throws
IllegalStateException, IOException, Exception {
- ensureScpOpen();
+ public void upload(String src, String dst) throws
IllegalStateException, IOException {
+ ensureSftpOpen();
dst = normalizePath(dst);
File fsrc = new File(src);
if (fsrc.isDirectory()) {
- LinkedList<String> file_list = new LinkedList<String>();
-
- walk(fsrc.listFiles(), file_list);
-
- scp.put((String[]) file_list.toArray(new
String[file_list.size()]), dst, false);
+ do_upload(src, fsrc.listFiles(), dst);
} else {
// uploading single file
- scp.put(new BufferedInputStream(new
FileInputStream(fsrc)), fsrc.length(), src, dst);
+ sftp.put(fsrc.getAbsolutePath(), dst);
}
}
@@ -636,16 +662,16 @@ public class SSHHost extends RemoteHost {
public void saveTextFile(String filename, String text, CharsetEncoder
ce) throws IllegalStateException, IOException {
if (text==null)
text = "";
- ensureScpOpen();
+ ensureSftpOpen();
filename = normalizePath(filename);
if (ce==null) {
byte[] text_bytes = text.getBytes();
- scp.put(new ByteArrayInputStream(text_bytes),
text_bytes.length, filename, filename);
+ sftp.put(new ByteArrayInputStream(text_bytes),
filename);
} else {
ByteBuffer bbuf =
ByteBuffer.allocate(50+text.length()*2);
ce.encode(CharBuffer.wrap(text.toCharArray()), bbuf,
true);
- scp.put(new ByteBufferInputStream(bbuf),
bbuf.capacity() - bbuf.remaining(), filename, filename);
+ sftp.put(new ByteBufferInputStream(bbuf), filename);
}
}
diff --git a/src/com/mostc/pftt/host/TempFileExecOutput.java
b/src/com/mostc/pftt/host/TempFileExecOutput.java
new file mode 100644
index 0000000..33b8218
--- /dev/null
+++ b/src/com/mostc/pftt/host/TempFileExecOutput.java
@@ -0,0 +1,31 @@
+package com.mostc.pftt.host;
+
+public class TempFileExecOutput extends ExecOutput {
+ public String temp_file;
+
+ public TempFileExecOutput() {
+
+ }
+
+ public TempFileExecOutput(String temp_file, ExecOutput eo) {
+ this.charset = eo.charset;
+ this.exit_code = eo.exit_code;
+ this.output = eo.output;
+ this.temp_file = temp_file;
+ }
+
+ public boolean cleanupIfSuccess(Host host) {
+ if (isSuccess()) {
+ cleanup(host);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void cleanup(Host host) {
+ try {
+ host.delete(temp_file);
+ } catch ( Exception ex ) {}
+ }
+}
diff --git a/src/com/mostc/pftt/main/PfttMain.java
b/src/com/mostc/pftt/main/PfttMain.java
index 3bdb785..94b8987 100644
--- a/src/com/mostc/pftt/main/PfttMain.java
+++ b/src/com/mostc/pftt/main/PfttMain.java
@@ -22,6 +22,7 @@ import org.codehaus.groovy.tools.shell.IO;
import com.mostc.pftt.host.ExecOutput;
import com.mostc.pftt.host.Host;
import com.mostc.pftt.host.LocalHost;
+import com.mostc.pftt.host.SSHHost;
import com.mostc.pftt.model.app.PhpUnitAppTestPack;
import com.mostc.pftt.model.phpt.EBuildBranch;
import com.mostc.pftt.model.phpt.EBuildType;
@@ -45,6 +46,8 @@ 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.SMBDeduplicationScenario;
import com.mostc.pftt.scenario.Scenario;
import com.mostc.pftt.scenario.ScenarioSet;
import com.mostc.pftt.util.DownloadUtil;
@@ -571,7 +574,7 @@ public class PfttMain {
int args_i = 0;
Config config = null;
- boolean is_uac = false, windebug = false, pftt_debug = false,
show_gui = false, force = false, disable_debug_prompt = true, results_only =
false, dont_cleanup_test_pack = false, phpt_not_in_place = false;
+ boolean is_uac = false, windebug = false, pftt_debug = false,
show_gui = false, force = false, disable_debug_prompt = false, results_only =
false, dont_cleanup_test_pack = false, phpt_not_in_place = false;
String source_pack = null;
PhpDebugPack debug_pack = null;
LinkedList<File> config_files = new LinkedList<File>();
@@ -720,6 +723,23 @@ 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!");
+ 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);
+
+ System.exit(0);
+ */
+ //
+
if (config_files.size()>0) {
config = Config.loadConfigFromFiles(cm,
(File[])config_files.toArray(new File[config_files.size()]));
System.out.println("PFTT: Config: loaded
"+config_files);
@@ -853,7 +873,7 @@ public class PfttMain {
checkUAC(is_uac, false, config, cm);
// run all tests
- HostEnvUtil.prepareHostEnv(rt.host, cm,
!!cm.isDisableDebugPrompt());
+ HostEnvUtil.prepareHostEnv(rt.host, cm,
!cm.isDisableDebugPrompt());
cmd_phpt_all(rt, cm, config, build, test_pack);
System.out.println("PFTT: finished");
diff --git a/src/com/mostc/pftt/main/SSHServer.java
b/src/com/mostc/pftt/main/SSHServer.java
index a41154a..4639b8a 100644
--- a/src/com/mostc/pftt/main/SSHServer.java
+++ b/src/com/mostc/pftt/main/SSHServer.java
@@ -3,7 +3,10 @@ package com.mostc.pftt.main;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumSet;
+import java.util.LinkedList;
+import java.util.regex.Pattern;
+import org.apache.log4j.BasicConfigurator;
import org.apache.sshd.SshServer;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.server.Command;
@@ -14,52 +17,96 @@ import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.apache.sshd.server.shell.ProcessShellFactory;
-import com.mostc.pftt.host.LocalHost;
+import com.mostc.pftt.util.StringUtil;
+
+// NOTE: modified NativeSshFile#getPhysicalName to check for [letter]:\ on
Windows
+// and NativeSshFile#<init>
public class SSHServer {
- public static void main(String[] args) throws IOException {
- SshServer sshd = SshServer.setUpDefaultServer();
+
+ public static void main(String[] args) throws IOException {
+ BasicConfigurator.configure();
+
+ SshServer sshd = SshServer.setUpDefaultServer();
- ArrayList<NamedFactory<Command>> f = new
ArrayList<NamedFactory<Command>>(1);
- f.add(new SftpSubsystem.Factory());
- sshd.setSubsystemFactories(f);
+ ArrayList<NamedFactory<Command>> f = new
ArrayList<NamedFactory<Command>>(1);
+ f.add(new SftpSubsystem.Factory());
+ sshd.setSubsystemFactories(f);
- if (System.getProperty("os.name").contains("Windows"))
- sshd.setShellFactory(psf("cmd.exe"));
- else
- sshd.setShellFactory(psf("bash"));
+ if (System.getProperty("os.name").contains("Windows"))
+ sshd.setShellFactory(psf("cmd.exe"));
+ else
+ sshd.setShellFactory(psf("bash"));
- sshd.setCommandFactory(new CommandFactory() {
- public Command createCommand(String command) {
- return psf(command).create();
- }
- });
- sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
- public boolean authenticate(String username, String password,
ServerSession session) {
- return (username.equals("administrator")) &&
(password.equals("password01!"));
- }
- });
- sshd.setPort(22);
- sshd.setReuseAddress(true);
- sshd.setKeyPairProvider(new
SimpleGeneratorHostKeyProvider("hostkeys.txt"));
- sshd.start();
- }
+ sshd.setCommandFactory(new CommandFactory() {
+ public Command createCommand(String command) {
+ return psf(command).create();
+ }
+ });
+ sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
+ public boolean authenticate(String username, String
password, ServerSession session) {
+ return (username.equals("administrator")) &&
(password.equals("password01!"));
+ }
+ });
+ sshd.setPort(22);
+ sshd.setReuseAddress(true);
+ sshd.setKeyPairProvider(new
SimpleGeneratorHostKeyProvider("hostkeys.txt"));
+ sshd.start();
+ }
+
+ public static String[] splitCmdString(String command) {
+ LinkedList<String> parts = new LinkedList<String>();
+ String buf = "";
+ char c;
+ boolean in_quote = false;
+ for ( int i=0 ; i < command.length() ; i++ ) {
+ c = command.charAt(i);
+ if (c=='\"' && (i==0||command.charAt(i-1) != '\\')) {
+ in_quote = !in_quote;
+ }
+ if (c == ' ' && !in_quote) {
+ buf = buf.trim();
+ if (buf.length() > 0) {
+ buf = StringUtil.unquote(buf);
+
+ buf = StringUtil.replaceAll(PAT_QUOTE,
"\"", buf);
+
+ parts.add(buf);
+ }
+ buf = "";
+ continue;
+ }
+ buf += c;
+ }
+ buf = buf.trim();
+ if (buf.length() > 0) {
+ if (buf.startsWith("\"")) {
+ buf = buf.substring(1, buf.length()-1);
+
+ buf = StringUtil.replaceAll(PAT_QUOTE, "\"",
buf);
+ }
+ parts.add(buf);
+ }
+
+ return (String[])parts.toArray(new String[]{});
+ } // end public static String[] splitCmdString
+ private static final Pattern PAT_QUOTE = Pattern.compile("\\\"");
+
+ private static ProcessShellFactory psf(String command) {
+ String[] commands;
+ if (command.contains(" ")) {
+ commands = splitCmdString(command);
+ } else {
+ commands = new String[] { command };
+ }
- private static ProcessShellFactory psf(String command) {
- String[] commands;
- if (command.contains(" ")) {
- commands = LocalHost.splitCmdString(command);
- } else
- commands = new String[] { command };
-
- if (System.getProperty("os.name").contains("Windows")) {
+ if (System.getProperty("os.name").contains("Windows")) {
+ return new ProcessShellFactory(
+ commands,
+
EnumSet.of(ProcessShellFactory.TtyOptions.Echo,
ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr));
+ }
- return new ProcessShellFactory(
- commands,
- EnumSet.of(ProcessShellFactory.TtyOptions.Echo,
ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr));
- }
+ return new ProcessShellFactory(commands);
+ }
- return new ProcessShellFactory(commands);
- }
-
} // end public class SSHServer
diff --git a/src/com/mostc/pftt/model/phpt/PhpBuild.java
b/src/com/mostc/pftt/model/phpt/PhpBuild.java
index 6fd2a06..74c731d 100644
--- a/src/com/mostc/pftt/model/phpt/PhpBuild.java
+++ b/src/com/mostc/pftt/model/phpt/PhpBuild.java
@@ -11,7 +11,9 @@ import javax.annotation.Nullable;
import com.mostc.pftt.host.ExecOutput;
import com.mostc.pftt.host.Host;
+import com.mostc.pftt.host.TempFileExecOutput;
import com.mostc.pftt.model.sapi.SAPIManager;
+import com.mostc.pftt.model.smoke.RequiredExtensionsSmokeTest;
import com.mostc.pftt.results.ConsoleManager;
import com.mostc.pftt.results.ConsoleManager.EPrintType;
import com.mostc.pftt.util.StringUtil;
@@ -306,7 +308,7 @@ public class PhpBuild extends SAPIManager {
if (host.exists(path))
ini = new PhpIni(host.getContents(path), build_path);
else
- ini = PhpIni.createDefaultIniCopy(host, this);
+ ini =
RequiredExtensionsSmokeTest.createDefaultIniCopy(host, this);
this.php_ini = new WeakReference<PhpIni>(ini);
return ini;
@@ -614,17 +616,13 @@ public class PhpBuild extends SAPIManager {
return eval(host, null, code, timeout_seconds, auto_cleanup);
}
- public static class PHPOutput extends ExecOutput {
+ public static class PHPOutput extends TempFileExecOutput {
/** the filename that the code was stored in for execution
*
*/
- public String php_filename;
protected PHPOutput(String php_filename, ExecOutput output) {
- this.charset = output.charset;
- this.exit_code = output.exit_code;
- this.output = output.output;
- this.php_filename = php_filename;
+ super(php_filename, output);
}
public boolean hasFatalError() {
@@ -638,18 +636,17 @@ public class PhpBuild extends SAPIManager {
}
public PHPOutput printHasFatalError(String ctx, PrintStream ps)
{
if (hasFatalError()) {
- ps.println(ctx+": "+output.trim());
+ String output_str = output.trim();
+ if (StringUtil.isEmpty(output_str))
+ output_str = "<PHP Crashed with no
output. exit_code = "+exit_code+">";
+
+ ps.println(ctx+": "+output_str);
return this;
} else {
return printOutputIfCrash(ctx, ps);
}
}
- public void cleanup(Host host) {
- try {
- host.delete(php_filename);
- } catch ( Exception ex ) {}
- }
@Override
public PHPOutput printOutputIfCrash(String ctx, ConsoleManager
cm) {
return (PHPOutput) super.printOutputIfCrash(ctx, cm);
@@ -706,7 +703,7 @@ public class PhpBuild extends SAPIManager {
* @return
*/
public String getDefaultExtensionDir() {
- return build_path+"/ext";
+ return build_path.contains("/") ? build_path+"/ext" :
build_path+"\\ext";
}
} // end public class PhpBuild
diff --git a/src/com/mostc/pftt/model/phpt/PhpIni.java
b/src/com/mostc/pftt/model/phpt/PhpIni.java
index 515c67e..c464006 100644
--- a/src/com/mostc/pftt/model/phpt/PhpIni.java
+++ b/src/com/mostc/pftt/model/phpt/PhpIni.java
@@ -63,7 +63,7 @@ public class PhpIni {
public static final String ISO_8859_1 = "ISO-8859-1";
public static final String U_INVALID_SUBSTITUTE =
"U_INVALID_SUBSTITUTE";
public static final String DOT_HTML = ".html";
- public static final String E_ALL_OR_E_STRICT = "E_ALL|E_STRICT";
+ public static final String E_ALL_NOTICE_WARNING = "E_ALL | E_NOTICE |
E_WARNING";
//
private static String dllName(String name) {
// FUTURE macos x and solaris support
@@ -97,94 +97,12 @@ public class PhpIni {
public static final String EXT_TIDY = dllName("tidy");
public static final String EXT_XMLRPC = dllName("xmlrpc");
public static final String EXT_XSL = dllName("xsl");
- public static PhpIni createDefaultIniCopy(Host host, PhpBuild build) {
- PhpIni ini = new PhpIni();
- ini.putSingle("default_mimetype", "text/plain");
- ini.putMulti(OUTPUT_HANDLER, StringUtil.EMPTY);
- ini.putMulti(OPEN_BASEDIR, StringUtil.EMPTY);
- ini.putMulti(SAFE_MODE, 0);
- ini.putMulti(DISABLE_DEFS, OFF);
- ini.putMulti(OUTPUT_BUFFERING, ON);
- ini.putMulti("engine", "On");
- ini.putMulti("zend.enable_gc", "On");
- ini.putMulti("expose_php ", "On");
- //
- // CRITICAL
- ini.putMulti(ERROR_REPORTING, "E_ALL | E_NOTICE | E_WARNING");
// TODO E_ALL_OR_E_STRICT);
- // CRITICAL
- ini.putMulti(DISPLAY_ERRORS, "On");//1);
- // CRITICAL
- ini.putMulti(DISPLAY_STARTUP_ERRORS, "On");//0);
- // CRITICAL
- ini.putMulti(LOG_ERRORS, "On");//0);
- // CRITICAL
- ini.putMulti(HTML_ERRORS, "On");//0);
- // CRITICAL
- ini.putMulti(TRACK_ERRORS, "On");//1);
- //
- ini.putMulti(REPORT_MEMLEAKS, "On");
- ini.putMulti(REPORT_ZEND_DEBUG, 0);
- ini.putMulti(DOCREF_ROOT, StringUtil.EMPTY);
- ini.putMulti(DOCREF_EXT, DOT_HTML);
- ini.putMulti(ERROR_PREPEND_STRING, StringUtil.EMPTY);
- ini.putMulti(ERROR_APPEND_STRING, StringUtil.EMPTY);
- ini.putMulti(AUTO_PREPEND_FILE, StringUtil.EMPTY);
- ini.putMulti(AUTO_APPEND_FILE, StringUtil.EMPTY);
- ini.putMulti(MAGIC_QUOTES_RUNTIME, 0);
- ini.putMulti(IGNORE_REPEATED_ERRORS, 0);
- ini.putMulti(PRECISION, 14);
- ini.putMulti(UNICODE_RUNTIME_ENCODING, ISO_8859_1);
- ini.putMulti(UNICODE_SCRIPT_ENCODING, UTF_8);
- ini.putMulti(UNICODE_OUTPUT_ENCODING, UTF_8);
- ini.putMulti(UNICODE_FROM_ERROR_MODE, U_INVALID_SUBSTITUTE);
- ini.putMulti(SESSION_AUTO_START, 0);
-
- // default php.ini has these extensions on Windows
- // NOTE: this is validated by RequiredExtensionsSmokeTest.
similar/same info is both there and here
- // b/c that needs it for validation and its here because
its in the default php.ini
- if (host.isWindows()) {
- ini.setExtensionDir(build.getDefaultExtensionDir());
- /*ini.addExtensions(
- EXT_BZ2,
- EXT_COM_DOTNET,
- EXT_CURL,
- EXT_FILEINFO,
- EXT_GD2,
- EXT_GETTEXT,
- EXT_GMP,
- EXT_INTL,
- EXT_IMAP,
- EXT_LDAP,
- EXT_MBSTRING,
- EXT_EXIF,
- EXT_MYSQL,
- EXT_MYSQLI,
- EXT_OPENSSL,
- EXT_PDO_MYSQL,
- EXT_PDO_PGSQL,
- EXT_PDO_SQLITE,
- EXT_PDO_ODBC,
- EXT_PGSQL,
- EXT_SHMOP,
- EXT_SOAP,
- EXT_SOCKETS,
- EXT_SQLITE3,
- EXT_TIDY,
- EXT_XMLRPC,
- EXT_XSL
- );*/
- }
-
- // TIMING: do this after all calls to #putMulti, etc... b/c
that sets is_default = false
- ini.is_default = true;
- return ini;
- } // end public static PhpIni createDefaultIniCopy
//
//
private final HashMap<String, ArrayList<String>> ini_map;
private WeakReference<PhpIni> ext_ini;
private WeakReference<String> ini_str, cli_arg;
- private boolean is_default = false;
+ public boolean is_default = false;
public PhpIni() {
ini_map = new HashMap<String, ArrayList<String>>();
@@ -216,15 +134,9 @@ public class PhpIni {
public PhpIni(String ini_str, String pwd) {
this();
if (pwd!=null&&ini_str.contains("{PWD}")) {
- // TODO important to use \\\\
- if (pwd.contains("cache_list")) {
-
pwd="C:/php-sdk/php-test-pack-5.4-ts-windows-vc9-x86-r811cd76/ext/phar/tests/cache_list";
- }
- //pwd =
"C:\\\\php-sdk\\\\php-test-pack-5.4-ts-windows-vc9-x86-r811cd76\\\\"; // TODO
temp
ini_str = StringUtil.replaceAll(PAT_PWD, pwd, ini_str);
- // BN: ensure that correct \\s are used for paths on
Windows
- // TODO ini_str = StringUtil.replaceAll(PAT_FS, "\\\\",
ini_str);
+ // CRITICAL: ensure that correct \\s are used for paths
on Windows
}
// read ini string, line by line
for (String line : StringUtil.splitLines(ini_str)) {
diff --git a/src/com/mostc/pftt/model/phpt/PhptTestCase.java
b/src/com/mostc/pftt/model/phpt/PhptTestCase.java
index adf22ef..4028047 100644
--- a/src/com/mostc/pftt/model/phpt/PhptTestCase.java
+++ b/src/com/mostc/pftt/model/phpt/PhptTestCase.java
@@ -64,28 +64,23 @@ public class PhptTestCase extends TestCase {
new String[]{"ext/standard/tests/file/symlink_"},
new
String[]{"ext/standard/tests/file/file_get_contents_",
"ext/standard/tests/file/file_put_contents_"},
new String[]{"ext/standard/tests/file/windows_acls/",
"ext/standard/tests/file/windows_links/"},
- //new String[]{"ext/standard/tests/file/0"},
// note: this array is processed in order, so this
entry will catch any remaining /file/ phpts
- //new String[]{"ext/standard/tests/file/"},
new String[]{"ext/standard/tests/dir/"},
- // TODO
new
String[]{"ext/standard/tests/streams/stream_get_meta_data_socket_variation1.phpt"},
new
String[]{"ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt"},
new
String[]{"ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt"},
new
String[]{"ext/standard/tests/streams/stream_get_meta_data_socket_variation4.phpt"},
new String[]{"ext/standard/tests/sockets/",
"ext/sockets/"},
- // TODO new String[]{"tests/security/"},
// the bug38450* tests fail randomly under apache if
run on apache instance
// with other tests - run them (serially) on their own
apache instance
new String[]{"ext/standard/tests/file/bug38450"},
new String[]{"ext/standard/tests/network/"},
- // TODO new String[]{"ext/session",
"tests/basic/bug20539.phpt"},
new String[]{"ext/mysql/", "ext/pdo_mysql/",
"ext/mysqli/"},
new String[]{"ext/pgsql/", "ext/pdo_pgsql/"},
// several 61367 tests that aren't thread-safe (temp
files)
new String[]{"ext/libxml/tests/bug61367"},
new String[]{"sapi/cli/tests/php_cli_server_"},
- // TODO new String[]{"sapi/cgi/"},
+ new String[]{"ext/standard/tests/strings/vprintf_"},
new String[]{"ext/firebird/", "ext/pdo_firebird/"},
new String[]{"ext/sybase/"},
new String[]{"ext/interbase/", "ext/pdo_interbase/"},
@@ -725,7 +720,7 @@ public class PhptTestCase extends TestCase {
ArrayList<String> test_names = new ArrayList<String>(2);
if (!output.hasFatalError()) {
- String base_dir = Host.dirname(output.php_filename);
+ String base_dir = Host.dirname(output.temp_file);
for (String line : output.getLines()) {
// code may use __DIR__ to get its current
directory => strip off current directory(/tmp, etc...)
if (line.startsWith(base_dir)) {
@@ -737,6 +732,9 @@ public class PhptTestCase extends TestCase {
continue;
test_names.add(line);
}
+
+ // delete temporary file
+ output.cleanup(host);
}
return test_names.toArray(new String[test_names.size()]);
diff --git a/src/com/mostc/pftt/model/smoke/RequiredExtensionsSmokeTest.java
b/src/com/mostc/pftt/model/smoke/RequiredExtensionsSmokeTest.java
index bef7684..e54b116 100644
--- a/src/com/mostc/pftt/model/smoke/RequiredExtensionsSmokeTest.java
+++ b/src/com/mostc/pftt/model/smoke/RequiredExtensionsSmokeTest.java
@@ -3,8 +3,10 @@ package com.mostc.pftt.model.smoke;
import com.mostc.pftt.host.Host;
import com.mostc.pftt.model.phpt.ESAPIType;
import com.mostc.pftt.model.phpt.PhpBuild;
+import com.mostc.pftt.model.phpt.PhpIni;
import com.mostc.pftt.results.ConsoleManager;
import com.mostc.pftt.results.ConsoleManager.EPrintType;
+import com.mostc.pftt.util.StringUtil;
/** Smoke test that verifies a PHP Build has all the required extensions.
*
@@ -103,5 +105,93 @@ public class RequiredExtensionsSmokeTest extends SmokeTest
{
public String getName() {
return "Required-Extensions";
}
+
+ /** creates a PhpIni with default configuration, default extensions
loaded etc...
+ *
+ * A PhpBuild using this PhpIni should pass this test.
+ *
+ * @param host
+ * @param build
+ * @return
+ */
+ public static PhpIni createDefaultIniCopy(Host host, PhpBuild build) {
+ PhpIni ini = new PhpIni();
+ ini.putSingle("default_mimetype", "text/plain");
+ ini.putMulti(PhpIni.OUTPUT_HANDLER, StringUtil.EMPTY);
+ ini.putMulti(PhpIni.OPEN_BASEDIR, StringUtil.EMPTY);
+ ini.putMulti(PhpIni.SAFE_MODE, 0);
+ ini.putMulti(PhpIni.DISABLE_DEFS, PhpIni.OFF);
+ ini.putMulti(PhpIni.OUTPUT_BUFFERING, PhpIni.ON);
+ //
+ // CRITICAL
+ ini.putMulti(PhpIni.ERROR_REPORTING,
PhpIni.E_ALL_NOTICE_WARNING);
+ // CRITICAL
+ ini.putMulti(PhpIni.DISPLAY_ERRORS, PhpIni.ON);
+ // CRITICAL
+ ini.putMulti(PhpIni.DISPLAY_STARTUP_ERRORS, PhpIni.OFF);
+ // CRITICAL
+ ini.putMulti(PhpIni.LOG_ERRORS, PhpIni.ON);
+ // CRITICAL
+ ini.putMulti(PhpIni.HTML_ERRORS, PhpIni.OFF);
+ // CRITICAL
+ ini.putMulti(PhpIni.TRACK_ERRORS, PhpIni.ON);
+ //
+ ini.putMulti(PhpIni.REPORT_MEMLEAKS, PhpIni.ON);
+ ini.putMulti(PhpIni.REPORT_ZEND_DEBUG, PhpIni.OFF);
+ ini.putMulti(PhpIni.DOCREF_ROOT, StringUtil.EMPTY);
+ ini.putMulti(PhpIni.DOCREF_EXT, PhpIni.DOT_HTML);
+ ini.putMulti(PhpIni.ERROR_PREPEND_STRING, StringUtil.EMPTY);
+ ini.putMulti(PhpIni.ERROR_APPEND_STRING, StringUtil.EMPTY);
+ ini.putMulti(PhpIni.AUTO_PREPEND_FILE, StringUtil.EMPTY);
+ ini.putMulti(PhpIni.AUTO_APPEND_FILE, StringUtil.EMPTY);
+ ini.putMulti(PhpIni.MAGIC_QUOTES_RUNTIME, PhpIni.OFF);
+ ini.putMulti(PhpIni.IGNORE_REPEATED_ERRORS, PhpIni.OFF);
+ ini.putMulti(PhpIni.PRECISION, 14);
+ ini.putMulti(PhpIni.UNICODE_RUNTIME_ENCODING,
PhpIni.ISO_8859_1);
+ ini.putMulti(PhpIni.UNICODE_SCRIPT_ENCODING, PhpIni.UTF_8);
+ ini.putMulti(PhpIni.UNICODE_OUTPUT_ENCODING, PhpIni.UTF_8);
+ ini.putMulti(PhpIni.UNICODE_FROM_ERROR_MODE,
PhpIni.U_INVALID_SUBSTITUTE);
+ ini.putMulti(PhpIni.SESSION_AUTO_START, PhpIni.OFF);
+
+ // default php.ini has these extensions on Windows
+ // NOTE: this is validated by RequiredExtensionsSmokeTest.
similar/same info is both there and here
+ // b/c that needs it for validation and its here because
its in the default php.ini
+ if (host.isWindows()) {
+ ini.setExtensionDir(build.getDefaultExtensionDir());
+ ini.addExtensions(
+ PhpIni.EXT_BZ2,
+ PhpIni.EXT_COM_DOTNET,
+ PhpIni.EXT_CURL,
+ PhpIni.EXT_FILEINFO,
+ PhpIni.EXT_GD2,
+ PhpIni.EXT_GETTEXT,
+ PhpIni.EXT_GMP,
+ PhpIni.EXT_INTL,
+ PhpIni.EXT_IMAP,
+ PhpIni.EXT_LDAP,
+ PhpIni.EXT_MBSTRING,
+ PhpIni.EXT_EXIF,
+ PhpIni.EXT_MYSQL,
+ PhpIni.EXT_MYSQLI,
+ PhpIni.EXT_OPENSSL,
+ PhpIni.EXT_PDO_MYSQL,
+ PhpIni.EXT_PDO_PGSQL,
+ PhpIni.EXT_PDO_SQLITE,
+ PhpIni.EXT_PDO_ODBC,
+ PhpIni.EXT_PGSQL,
+ PhpIni.EXT_SHMOP,
+ PhpIni.EXT_SOAP,
+ PhpIni.EXT_SOCKETS,
+ PhpIni.EXT_SQLITE3,
+ PhpIni.EXT_TIDY,
+ PhpIni.EXT_XMLRPC,
+ PhpIni.EXT_XSL
+ );
+ }
+
+ // TIMING: do this after all calls to #putMulti, etc... b/c
that sets is_default = false
+ ini.is_default = true;
+ return ini;
+ } // end public static PhpIni createDefaultIniCopy
} // end public class RequiredExtensionsSmokeTest
diff --git a/src/com/mostc/pftt/model/smoke/RequiredFeaturesSmokeTest.java
b/src/com/mostc/pftt/model/smoke/RequiredFeaturesSmokeTest.java
index d31e617..7621bc5 100644
--- a/src/com/mostc/pftt/model/smoke/RequiredFeaturesSmokeTest.java
+++ b/src/com/mostc/pftt/model/smoke/RequiredFeaturesSmokeTest.java
@@ -258,7 +258,7 @@ public class RequiredFeaturesSmokeTest extends SmokeTest {
"Collecting statistics => Yes%s" +
"Collecting memory statistics => No%s" +
"Tracing => n/a%s" +
-"Loaded plugins =>
mysqlnd,example,debug_trace,auth_plugin_mysql_native_password,auth_plugin_mysql_clear_password%s"
+
+"Loaded plugins => %s" +
"API Extensions => %s" +
"%s" +
"mysqlnd statistics =>%s" +
@@ -423,10 +423,6 @@ public class RequiredFeaturesSmokeTest extends SmokeTest {
"bytes_received_real_data_normal => 0%s" +
"bytes_received_real_data_ps => 0%s" +
"%s" +
-"example statistics => %s" +
-"stat1 => 0%s" +
-"stat2 => 0%s" +
-"%s" +
"odbc%s" +
"%s" +
"ODBC Support => enabled%s" +
@@ -850,7 +846,7 @@ public class RequiredFeaturesSmokeTest extends SmokeTest {
"Collecting statistics => Yes%s" +
"Collecting memory statistics => No%s" +
"Tracing => n/a%s" +
-"Loaded plugins =>
mysqlnd,example,debug_trace,auth_plugin_mysql_native_password,auth_plugin_mysql_clear_password%s"
+
+"Loaded plugins => %s" +
"API Extensions => %s" +
"%s" +
"mysqlnd statistics =>%s" +
@@ -1015,10 +1011,6 @@ public class RequiredFeaturesSmokeTest extends SmokeTest
{
"bytes_received_real_data_normal => 0%s" +
"bytes_received_real_data_ps => 0%s" +
"%s" +
-"example statistics => %s" +
-"stat1 => 0%s" +
-"stat2 => 0%s" +
-"%s" +
"odbc%s" +
"%s" +
"ODBC Support => enabled%s" +
diff --git a/src/com/mostc/pftt/model/ui/wordpress.groovy
b/src/com/mostc/pftt/model/ui/wordpress.groovy
index 23aa1d5..f65e6a6 100644
--- a/src/com/mostc/pftt/model/ui/wordpress.groovy
+++ b/src/com/mostc/pftt/model/ui/wordpress.groovy
@@ -1,6 +1,6 @@
package com.mostc.pftt.model.ui;
-import com.mostc.pftt.scenario.WordpressScenario
+import com.mostc.pftt.scenario.app.WordpressScenario
// auto import UITestCase
// cr or case_runner -
diff --git a/src/com/mostc/pftt/results/PhptResultPack.java
b/src/com/mostc/pftt/results/PhptResultPack.java
index 5d0da0d..f2d0a0c 100644
--- a/src/com/mostc/pftt/results/PhptResultPack.java
+++ b/src/com/mostc/pftt/results/PhptResultPack.java
@@ -50,10 +50,10 @@ public abstract class PhptResultPack {
}
public static float round1(float value) {
- float ret = (float) Math.round( ( value * 10000.0d)/100.0d );
- if (ret==100.0f && value!=100.0f)
+ float ret = ( (float) Math.round( value * 10.0f ) ) / 10.0f;
+ if (ret==100.0f && value<100.0f)
// only show 100% if its really 100%
- return 99.99f;
+ return 99.9f;
else
return ret;
}
diff --git a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner.java
b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner.java
index f650587..43a66e0 100644
--- a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner.java
@@ -10,12 +10,9 @@ import com.mostc.pftt.model.phpt.ESAPIType;
import com.mostc.pftt.model.phpt.PhpBuild;
import com.mostc.pftt.model.phpt.PhpIni;
import com.mostc.pftt.model.phpt.PhptTestCase;
-import com.mostc.pftt.model.phpt.PhptActiveTestPack;
import com.mostc.pftt.results.ConsoleManager;
import com.mostc.pftt.results.IPhptTestResultReceiver;
import com.mostc.pftt.results.PhptTestResult;
-import com.mostc.pftt.scenario.AbstractINIScenario;
-import com.mostc.pftt.scenario.Scenario;
import com.mostc.pftt.scenario.ScenarioSet;
public abstract class AbstractPhptTestCaseRunner {
@@ -34,18 +31,6 @@ public abstract class AbstractPhptTestCaseRunner {
public abstract void runTest() throws IOException, Exception, Throwable;
- public static PhpIni createIniForTest(ConsoleManager cm, Host host,
PhpBuild build, PhptActiveTestPack active_test_pack, ScenarioSet scenario_set) {
- PhpIni ini = PhpIni.createDefaultIniCopy(host, build); // TODO
- //_ini.replaceAll(test_case.getINI(active_test_pack, host));
- for ( Scenario scenario : scenario_set ) {
- if (scenario instanceof AbstractINIScenario) {
- ((AbstractINIScenario)scenario).setup(cm, host,
build, ini);
- }
- }
- ini.addToIncludePath(host, active_test_pack.getDirectory());
- return ini;
- }
-
public static Map<String, String> generateENVForTestCase(ConsoleManager
cm, Host host, PhpBuild build, ScenarioSet scenario_set, PhptTestCase
test_case) throws Exception {
// read ENV vars from test, from its parent (if a test
redirected to this test), and merge from scenario
//
@@ -101,7 +86,7 @@ public abstract class AbstractPhptTestCaseRunner {
return true;
} else if
(test_case.getName().contains("dba")||test_case.getName().contains("sybase")||test_case.getName().contains("snmp")||test_case.getName().contains("interbase")||test_case.getName().contains("ldap")||test_case.getName().contains("imap")||test_case.getName().contains("ftp")||test_case.getName().contains("curl")||test_case.getName().contains("sql")||test_case.getName().contains("enchant")||test_case.getName().contains("oci")||test_case.getName().contains("pcntl")||test_case.getName().contains("soap")||test_case.getName().contains("xmlrpc")||test_case.getName().contains("pdo")||test_case.getName().contains("odbc"))
{
- // TODO temp - don't run these SKIPIFs without the
scenario loaded
+ // TODO don't run these SKIPIFs without the scenario
loaded
twriter.addResult(host, scenario_set, new
PhptTestResult(host, EPhptTestStatus.SKIP, test_case, "test would've been
skipped", null, null, null, null, null, null, null, null, null, null, null));
return true;
diff --git a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
index 0353429..d5aa2ce 100644
--- a/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
+++ b/src/com/mostc/pftt/runner/AbstractPhptTestCaseRunner2.java
@@ -133,11 +133,12 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
host.saveTextFile(test_clean,
test_case.get(EPhptSection.CLEAN));
} // else test_clean = null;
-
+ /*
if (StringUtil.isEmpty(ini.getExtensionDir()))
// this is done in PhpIni#createDefaultIniCopy if the
host is Windows
// but for Linux/non-Windows, this won't have been done
ini.setExtensionDir(build.getDefaultExtensionDir());
+ */
return true;
} // end boolean prepare
@@ -409,7 +410,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
}
if (expected_re_match||a(test_case)) {
- twriter.addResult(host, scenario_set, new
PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL_WORKS:EPhptTestStatus.PASS,
test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post,
getShellScript(), null, null, null));
+ twriter.addResult(host, scenario_set, new
PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, ini, env, splitCmdString(), stdin_post,
getShellScript(), null, null, null));
return;
}
@@ -431,7 +432,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
}
if (expected_re_match) {
- twriter.addResult(host, scenario_set,
new PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL_WORKS:EPhptTestStatus.PASS,
test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post,
getShellScript(), null, null, null));
+ twriter.addResult(host, scenario_set,
new PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, ini, env, splitCmdString(), stdin_post,
getShellScript(), null, null, null));
return;
}
@@ -443,7 +444,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
if (equalsNoWS(output,
expected)||a(test_case)||output.contains("<html>")) {
- twriter.addResult(host, scenario_set, new
PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL_WORKS:EPhptTestStatus.PASS,
test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post,
getShellScript(), null, null, null));
+ twriter.addResult(host, scenario_set, new
PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, ini, env, splitCmdString(), stdin_post,
getShellScript(), null, null, null));
return;
}
@@ -460,7 +461,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
// compare again
if (equalsNoWS(output, expected)) {
- twriter.addResult(host, scenario_set,
new PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL_WORKS:EPhptTestStatus.PASS,
test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post,
getShellScript(), null, null, null));
+ twriter.addResult(host, scenario_set,
new PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, ini, env, splitCmdString(), stdin_post,
getShellScript(), null, null, null));
return;
} // end if
@@ -470,7 +471,7 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
String output_trim = output.trim();
if
(StringUtil.isEmpty(output_trim)||a(test_case)||output.contains("<html>")) {
- twriter.addResult(host, scenario_set, new
PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL_WORKS:EPhptTestStatus.PASS,
test_case, output, null, null, charset, ini, env, splitCmdString(), stdin_post,
getShellScript(), null, null, null));
+ twriter.addResult(host, scenario_set, new
PhptTestResult(host,
test_case.isXFail()?EPhptTestStatus.XFAIL:EPhptTestStatus.PASS, test_case,
output, null, null, charset, ini, env, splitCmdString(), stdin_post,
getShellScript(), null, null, null));
return;
}
@@ -478,56 +479,48 @@ public abstract class AbstractPhptTestCaseRunner2 extends
AbstractPhptTestCaseRu
// if here, test failed!
- if (StringUtil.isNotEmpty(getCrashedSAPIOutput())) {
- // TODO
- twriter.addResult(host, scenario_set, new
PhptTestResult(host, EPhptTestStatus.CRASH, test_case, getCrashedSAPIOutput(),
null, null, charset, ini, env, splitCmdString(), stdin_post, getShellScript(),
null, null, preoverride_actual));
-
+ // generate a diff
+ String[] actual_lines = StringUtil.splitLines(output);
+ String[] expected_lines =
StringUtil.splitLines(test_case.getExpected());
+ Diff<String> diff = new Diff<String>(expected_lines,
actual_lines);
+
+ String expectf;
+ // generate the EXPECTF section to show the user the regular
expression that was actually used (generated from EXPECTF section) to evaluate
test output
+ if (test_case.containsSection(EPhptSection.EXPECTF)) {
+ expectf =
PhptTestCase.prepareExpectF(test_case.getTrim(EPhptSection.EXPECTF));
} else {
- // test is FAIL or XFAIL_WORKS
-
- // generate a diff
- String[] actual_lines = StringUtil.splitLines(output);
- String[] expected_lines =
StringUtil.splitLines(test_case.getExpected());
- Diff<String> diff = new Diff<String>(expected_lines,
actual_lines);
-
- String expectf;
- // generate the EXPECTF section to show the user the
regular expression that was actually used (generated from EXPECTF section) to
evaluate test output
- if (test_case.containsSection(EPhptSection.EXPECTF)) {
- expectf =
PhptTestCase.prepareExpectF(test_case.getTrim(EPhptSection.EXPECTF));
- } else {
- expectf = null;
- }
+ expectf = null;
+ }
- PhptTestResult result;
- if (test_case.isXFail()) {
- result = new PhptTestResult(host,
EPhptTestStatus.XFAIL, test_case, output, null, null, charset, ini, env,
splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual);
- } else {
- result = notifyFail(new PhptTestResult(host,
EPhptTestStatus.FAIL, test_case, output, actual_lines, expected_lines, charset,
ini, env, splitCmdString(), stdin_post, getShellScript(), diff, expectf,
preoverride_actual, getCrashedSAPIOutput()));
- }
-
+ PhptTestResult result;
+ if (test_case.isXFail()) {
+ result = new PhptTestResult(host,
EPhptTestStatus.XFAIL_WORKS, test_case, output, null, null, charset, ini, env,
splitCmdString(), stdin_post, getShellScript(), null, null, preoverride_actual);
+ } else {
+ result = notifyFail(new PhptTestResult(host,
EPhptTestStatus.FAIL, test_case, output, actual_lines, expected_lines, charset,
ini, env, splitCmdString(), stdin_post, getShellScript(), diff, expectf,
preoverride_actual, getCrashedSAPIOutput()));
+ }
+
+ //
+ // set result#regex_compiler_dump and result#regex_output dump
if test result is FAIL or XFAIL_WORKS and test has an EXPECTF or EXPECTREGEX
section
+ if (test_case.containsSection(EPhptSection.EXPECTF) ||
test_case.containsSection(EPhptSection.EXPECTREGEX)) {
+ // test may be failing due to a bad regular expression
in test or bug in regular expression engine
//
- // set result#regex_compiler_dump and
result#regex_output dump if test result is FAIL or XFAIL_WORKS and test has an
EXPECTF or EXPECTREGEX section
- if (test_case.containsSection(EPhptSection.EXPECTF) ||
test_case.containsSection(EPhptSection.EXPECTREGEX)) {
- // test may be failing due to a bad regular
expression in test or bug in regular expression engine
- //
- // get a debug dump from the regular expression
engine to save with the result
- //
- // (this is an expensive operation so it
shouldn't be done for every test. there shouldn't be
- // very many FAIL tests so this shouldn't be
done very much)
- LengthLimitStringWriter dump_sw = new
LengthLimitStringWriter();
- LengthLimitStringWriter output_sw = new
LengthLimitStringWriter();
- PrintWriter dump_pw = new PrintWriter(dump_sw);
- PrintWriter output_pw = new
PrintWriter(output_sw);
-
- test_case.debugExpectedRegularExpression(host,
scenario_set, twriter, result.actual, dump_pw, output_pw);
-
- result.regex_compiler_dump = dump_sw.toString();
- result.regex_output = output_sw.toString();
- }
+ // get a debug dump from the regular expression engine
to save with the result
//
+ // (this is an expensive operation so it shouldn't be
done for every test. there shouldn't be
+ // very many FAIL tests so this shouldn't be done very
much)
+ LengthLimitStringWriter dump_sw = new
LengthLimitStringWriter();
+ LengthLimitStringWriter output_sw = new
LengthLimitStringWriter();
+ PrintWriter dump_pw = new PrintWriter(dump_sw);
+ PrintWriter output_pw = new PrintWriter(output_sw);
- twriter.addResult(host, scenario_set, result);
+ test_case.debugExpectedRegularExpression(host,
scenario_set, twriter, result.actual, dump_pw, output_pw);
+
+ result.regex_compiler_dump = dump_sw.toString();
+ result.regex_output = output_sw.toString();
}
+ //
+
+ twriter.addResult(host, scenario_set, result);
} // end void evalTest
protected PhptTestResult notifyFail(PhptTestResult result) {
diff --git a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
index 794b4ad..0abd429 100644
--- a/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/CliPhptTestCaseRunner.java
@@ -19,6 +19,7 @@ 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;
@@ -111,7 +112,18 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
"ext/session/tests/023.phpt",
"ext/phar/tests/phar_get_supportedcomp3.phpt",
"ext/phar/tests/phar_create_in_cwd.phpt",
-
"ext/phar/tests/phar_get_supported_signatures_002.phpt"
+
"ext/phar/tests/phar_get_supported_signatures_002.phpt",
+ //
+
"ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt",
+
"ext/standard/tests/streams/stream_get_meta_data_socket_variation1.phpt",
+
"ext/standard/tests/network/gethostbyname_error002.phpt",
+ "ext/session/tests/003.phpt",
+
"ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt",
+ "ext/phar/tests/phar_commitwrite.phpt",
+
"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"
)) {
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));
@@ -151,6 +163,7 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
}
static boolean saved_ini = false;
+ static String ini_dir;
@Override
protected void prepareTest() throws Exception {
@@ -158,11 +171,15 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
//
if (!saved_ini) {
+ // @see CliScenario#createIniForTest
saved_ini = true;
- String ini_file = build.getDefaultPhpIniPath(host,
ESAPIType.CLI);
+ ini_dir = host.mktempname(getClass());
+ host.mkdirs(ini_dir);
+
+ String ini_file = ini_dir + "/php.ini";
- PhpIni def_ini = PhpIni.createDefaultIniCopy(host,
build);
+ PhpIni def_ini =
RequiredExtensionsSmokeTest.createDefaultIniCopy(host, build);
FileWriter fw = new FileWriter(ini_file);
fw.write(def_ini.toString());
@@ -176,8 +193,9 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
{
StringBuilder sb = new StringBuilder(64);
sb.append(selected_php_exe);
- // -n => critical: ignores any .ini file with the php
build
- // TODO sb.append(" -n ");
+ // -c => provide default PhpIni file
+ sb.append(" -c ");
+ sb.append(ini_dir);
sb.append(ini_settings);
sb.append(" -f
\"");sb.append(host.fixPath(test_file));sb.append("\" ");
if (test_case.containsSection(EPhptSection.ARGS)) {
@@ -297,6 +315,12 @@ public class CliPhptTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
// if test is taking longer than 40 seconds to run, spin
up an additional thread to compensate (so other non-slow tests can be executed)
output = host.exec(shell_file, Host.ONE_MINUTE, env,
stdin_post, test_case.isNon8BitCharset()?test_case.getCommonCharset():null,
active_test_pack.getDirectory(), thread, 40);
+ if (output.isCrashed() &&
StringUtil.isWhitespaceOrEmpty(output.output)) {
+ not_crashed = false; // @see #runTest
+
+ twriter.addResult(host, scenario_set, new
PhptTestResult(host, EPhptTestStatus.CRASH, test_case, "PFTT:
exit_code="+output.exit_code+"\n"+output.output, null, null, null, ini, env,
null, stdin_post, null, null, null, null, output.output));
+ }
+
return output.output;
} // end String executeTest
diff --git a/src/com/mostc/pftt/runner/HttpTestCaseRunner.java
b/src/com/mostc/pftt/runner/HttpTestCaseRunner.java
index 5a77980..d451504 100644
--- a/src/com/mostc/pftt/runner/HttpTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/HttpTestCaseRunner.java
@@ -47,11 +47,13 @@ import com.mostc.pftt.util.StringUtil;
*/
// TODO error msg should tell how many times web server was restarted
+// TODO restart a 2nd time before giving up
public class HttpTestCaseRunner extends AbstractPhptTestCaseRunner2 {
protected final WebServerManager smgr;
protected final ByteArrayOutputStream request_bytes, response_bytes;
protected WebServerInstance web = null;
protected String cookie_str;
+ protected DebuggingHttpClientConnection conn;
protected final HttpParams params;
protected final HttpProcessor httpproc;
protected final HttpRequestExecutor httpexecutor;
@@ -63,12 +65,12 @@ public class HttpTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
this.httpexecutor = httpexecutor;
this.smgr = smgr;
this.web = web;
- // CRITICAL: need this to get ENV from this TestCaseGroup
+ // IMPORTANT: need this to get ENV from this TestCaseGroup
if (env!=null &&
((env.containsKey("TEMP")&&env.get("TEMP").equals(".")) ||
(env.containsKey("TMP")&&env.get("TMP").equals(".")))) {
// checks for case like:
ext/phar/commit/tar/phar_commitwrite.phpt
this.env = new HashMap<String,String>(7);
this.env.putAll(env);
- // TODO
+
this.env.put("TEMP",
active_test_pack.getDirectory()+"/"+Host.dirname(test_case.getName()));
this.env.put("TMP",
active_test_pack.getDirectory()+"/"+Host.dirname(test_case.getName()));
} else {
@@ -166,8 +168,9 @@ public class HttpTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
"ext/standard/tests/general_functions/var_dump.phpt",
"ext/session/tests/003.phpt",
"ext/session/tests/023.phpt",
-
"ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt",
-
"ext/standard/tests/streams/stream_get_meta_data_socket_variation4.phpt",
+ "tests/basic/032.phpt",
+ "tests/basic/031.phpt",
+ "tests/basic/030.phpt",
/////////////////
// getopt returns false under web server (ok)
"ext/standard/tests/general_functions/bug43293_1.phpt",
@@ -206,6 +209,12 @@ public class HttpTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
cookie_str = test_case.get(EPhptSection.COOKIE);
}
+ protected void markTestAsCrash() {
+ not_crashed = false; // @see #runTest
+
+ twriter.addResult(host, scenario_set, new PhptTestResult(host,
EPhptTestStatus.CRASH, test_case, null, null, null, null, ini, env, null,
stdin_post, null, null, null, null, web==null?null:web.getSAPIOutput()));
+ }
+
/** executes SKIPIF, TEST or CLEAN over http.
*
* retries request if it times out and restarts web server if it crashes
@@ -266,7 +275,6 @@ public class HttpTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
return sb.toString();
}
} // end protected String http_execute
-
protected String do_http_execute(String path, EPhptSection section,
boolean is_replacement) throws Exception {
path = Host.toUnixPath(path);
@@ -334,13 +342,6 @@ public class HttpTestCaseRunner extends
AbstractPhptTestCaseRunner2 {
}
}
- protected void markTestAsCrash() {
- not_crashed = false; // @see #runTest
-
- twriter.addResult(host, scenario_set, new PhptTestResult(host,
EPhptTestStatus.CRASH, test_case, null, null, null, null, ini, env, null,
stdin_post, null, null, null, null, web==null?null:web.getSAPIOutput()));
- }
-
- protected DebuggingHttpClientConnection conn;
protected String do_http_get(String path) throws Exception {
return do_http_get(path, 0);
}
diff --git a/src/com/mostc/pftt/scenario/AbstractParallelScenario.java
b/src/com/mostc/pftt/scenario/AbstractParallelScenario.java
index 7e72338..3375664 100644
--- a/src/com/mostc/pftt/scenario/AbstractParallelScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractParallelScenario.java
@@ -8,4 +8,9 @@ package com.mostc.pftt.scenario;
public abstract class AbstractParallelScenario extends Scenario {
+ @Override
+ public boolean ignoreForShortName() {
+ return true;
+ }
+
}
diff --git a/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java
b/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java
index 2fbf93b..f6050d5 100644
--- a/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractSAPIScenario.java
@@ -84,5 +84,7 @@ public abstract class AbstractSAPIScenario extends
AbstractSerialScenario {
* @throws Exception
*/
public abstract TestCaseGroupKey createTestGroupKey(ConsoleManager cm,
Host host, PhpBuild build, ScenarioSet scenario_set, PhptActiveTestPack
active_test_pack, PhptTestCase test_case, TestCaseGroupKey group_key) throws
Exception;
+
+ public abstract PhpIni createIniForTest(ConsoleManager cm, Host host,
PhpBuild build, PhptActiveTestPack active_test_pack, ScenarioSet scenario_set);
} // end public abstract class AbstractSAPIScenario
diff --git a/src/com/mostc/pftt/scenario/AbstractSMBScenario.java
b/src/com/mostc/pftt/scenario/AbstractSMBScenario.java
index e84f723..fee0b1b 100644
--- a/src/com/mostc/pftt/scenario/AbstractSMBScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractSMBScenario.java
@@ -18,23 +18,25 @@ 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;
- protected String share_name, file_path, unc_path, smb_path, local_drive;
+ // 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))
- // @see SMBDeduplicationScenario
- base_file_path = "C:\\PFTT_Share";
+ // fallback to a default path, @see
SMBDeduplicationScenario
+ 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;
@@ -66,13 +68,35 @@ public abstract class AbstractSMBScenario extends
AbstractRemoteFileSystemScenar
return createShare(cm);
}
+ public boolean shareExists(ConsoleManager cm, String share_name) {
+ if (!remote_host.isWindows())
+ return false; // XXX samba support
+
+ try {
+ String output_str = remote_host.execElevated("NET
SHARE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).output;
+
+ return output_str.contains(share_name);
+ } catch ( Exception ex ) {
+ cm.addGlobalException(EPrintType.CANT_CONTINUE,
"shareExists", ex, "can't tell if share exists");
+ }
+ return false;
+ }
+
public boolean createShare(ConsoleManager cm) {
- for ( int i=1 ; ; ) {
- file_path = base_file_path + i;
+ // 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(file_path))
- break;
+ if (!remote_host.exists(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)) {
+ break;
+ }
+ }
}
+ //
+
+ cm.println(EPrintType.IN_PROGRESS, getName(), "Selected
share_name="+share_name+" remote_path="+remote_path+" (base: "+base_file_path+"
"+base_share_name+")");
try {
if (remote_host.isWindows()) {
@@ -82,22 +106,22 @@ public abstract class AbstractSMBScenario extends
AbstractRemoteFileSystemScenar
return false;
}
} catch (Exception ex ) {
-
cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(),
"createShare", ex, "", remote_host, file_path, share_name);
+
cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(),
"createShare", ex, "", remote_host, remote_path, share_name);
return false;
}
unc_path = "\\\\"+remote_host.getHostname()+"\\"+share_name; //
for Windows
- smb_path = "smb://"+remote_host.getHostname()+"/"+share_name;
// for linux
+ url_path = "smb://"+remote_host.getHostname()+"/"+share_name;
// for linux
- cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Share
created: "+unc_path+" "+smb_path);
+ cm.println(EPrintType.COMPLETED_OPERATION, getName(), "Share
created: unc="+unc_path+" remote_file="+remote_path+" url="+url_path);
return true;
} // end public boolean createShare
protected boolean createShareWindows(ConsoleManager cm) throws
Exception {
- remote_host.mkdirs(file_path);
+ remote_host.mkdirs(remote_path);
- return remote_host.exec("NET SHARE "+share_name+"="+file_path+"
/Grant:"+remote_host.getUsername()+",Full",
Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess();
+ return remote_host.execElevated("NET SHARE
"+share_name+"="+remote_path+" /Grant:"+remote_host.getUsername()+",Full",
Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess();
}
protected boolean createShareSamba() {
@@ -118,7 +142,7 @@ public abstract class AbstractSMBScenario extends
AbstractRemoteFileSystemScenar
}
} else {
// host is local, try using a local drive, normal file
system operations, not SMB, etc...
- local_drive = file_path;
+ local_path = remote_path;
return true;
}
@@ -126,17 +150,17 @@ public abstract class AbstractSMBScenario extends
AbstractRemoteFileSystemScenar
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_drive = null;
+ local_path = null;
for ( int i=0 ; i < DRIVES.length ; i++ ) {
- if (remote_host.exists(DRIVES[i] + ":\\")) {
- local_drive = DRIVES[i] + ":";
+ if (!local_host.exists(DRIVES[i] + ":\\")) {
+ local_path = DRIVES[i] + ":";
break;
}
}
- if (local_drive==null)
+ if (local_path==null)
return false;
- return local_host.exec("NET USE "+unc_path+" "+local_drive+"
/user:"+remote_host.getUsername()+" /password:"+remote_host.getPassword(),
Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess();
+ 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();
}
protected boolean connectFromSamba() {
@@ -146,27 +170,35 @@ public abstract class AbstractSMBScenario extends
AbstractRemoteFileSystemScenar
@Override
public String getTestPackStorageDir(Host host) {
- return local_drive; // H: I: J: ... Y:
+ return local_path; // H: I: J: ... Y:
}
public boolean deleteShare(ConsoleManager cm, Host host) {
try {
- if (host.execElevated("NET SHARE "+file_path+"
/DELETE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess()) {
- host.delete(file_path);
+ if (host.execElevated("NET SHARE "+remote_path+"
/DELETE", Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess()) {
+ try {
+ host.delete(remote_path);
+
+ cm.println(EPrintType.IN_PROGRESS,
getClass(), "Share deleted: remote_file="+remote_path+" unc="+unc_path+"
url="+url_path);
+ } catch ( Exception ex ) {
+ throw ex;
+ }
return true;
}
} catch ( Exception ex ) {
-
cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(),
"deleteShare", ex, "", host, file_path);
+
cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(),
"deleteShare", ex, "", host, remote_path);
}
return false;
}
public boolean disconnect(ConsoleManager cm, Host host) {
try {
- return host.exec("NET USE "+local_drive+" /DELETE",
Host.ONE_MINUTE).printOutputIfCrash(getClass(), cm).isSuccess();
+ 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);
+ }
} catch ( Exception ex ) {
-
cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(),
"disconnect", ex, "", host, local_drive);
+
cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(),
"disconnect", ex, "", host, local_path);
}
return false;
}
@@ -175,7 +207,7 @@ public abstract class AbstractSMBScenario extends
AbstractRemoteFileSystemScenar
public void notifyFinishedTestPack(ConsoleManager cm, Host host) {
if (deleteShare(cm, host) && disconnect(cm, host)) {
// reset
- share_name = file_path = unc_path = smb_path =
local_drive = null;
+ share_name = remote_path = unc_path = url_path =
local_path = null;
}
}
diff --git a/src/com/mostc/pftt/scenario/AbstractWebServerScenario.java
b/src/com/mostc/pftt/scenario/AbstractWebServerScenario.java
index 05e5602..dd53c91 100644
--- a/src/com/mostc/pftt/scenario/AbstractWebServerScenario.java
+++ b/src/com/mostc/pftt/scenario/AbstractWebServerScenario.java
@@ -28,6 +28,7 @@ import
com.mostc.pftt.model.sapi.SharedSAPIInstanceTestCaseGroupKey;
import com.mostc.pftt.model.sapi.TestCaseGroupKey;
import com.mostc.pftt.model.sapi.WebServerInstance;
import com.mostc.pftt.model.sapi.WebServerManager;
+import com.mostc.pftt.model.smoke.RequiredExtensionsSmokeTest;
import com.mostc.pftt.results.ConsoleManager;
import com.mostc.pftt.results.IPhptTestResultReceiver;
import com.mostc.pftt.runner.AbstractPhptTestCaseRunner;
@@ -110,8 +111,16 @@ public abstract class AbstractWebServerScenario extends
AbstractSAPIScenario {
return new HttpTestCaseRunner(group_key.getPhpIni(),
group_key.getEnv(), params, httpproc, httpexecutor, smgr, (WebServerInstance)
((SharedSAPIInstanceTestCaseGroupKey)group_key).getSAPIInstance(), thread,
test_case, cm, twriter, host, scenario_set, build, src_test_pack,
active_test_pack);
}
+ @Override
+ public PhpIni createIniForTest(ConsoleManager cm, Host host, PhpBuild
build, PhptActiveTestPack active_test_pack, ScenarioSet scenario_set) {
+ // entire PhpIni will be given to web server when its started
+ return RequiredExtensionsSmokeTest.createDefaultIniCopy(host,
build);
+ }
+
+ @Override
public TestCaseGroupKey createTestGroupKey(ConsoleManager cm, Host
host, PhpBuild build, ScenarioSet scenario_set, PhptActiveTestPack
active_test_pack, PhptTestCase test_case, TestCaseGroupKey group_key) throws
Exception {
Map<String,String> env = null;
+ // ENV vars will be passed to web server manager to wrap the
web server in when its executed
if (test_case.containsSection(EPhptSection.ENV)) {
env =
AbstractPhptTestCaseRunner.generateENVForTestCase(cm, host, build,
scenario_set, test_case);
@@ -119,7 +128,7 @@ public abstract class AbstractWebServerScenario extends
AbstractSAPIScenario {
}
if (test_case.containsSection(EPhptSection.INI)) {
- PhpIni ini =
AbstractPhptTestCaseRunner.createIniForTest(cm, host, build, active_test_pack,
scenario_set);
+ PhpIni ini = createIniForTest(cm, host, build,
active_test_pack, scenario_set);
ini.replaceAll(test_case.getINI(active_test_pack,
host));
// note: don't bother comparing test case's INI with
existing group_key's INI, PhptTestPackRunner
@@ -128,7 +137,7 @@ public abstract class AbstractWebServerScenario extends
AbstractSAPIScenario {
} else if (env==null && group_key!=null &&
group_key.getPhpIni().isDefault()) {
return group_key;
} else {
- return new
SharedSAPIInstanceTestCaseGroupKey(AbstractPhptTestCaseRunner.createIniForTest(cm,
host, build, active_test_pack, scenario_set), env);
+ return new
SharedSAPIInstanceTestCaseGroupKey(createIniForTest(cm, host, build,
active_test_pack, scenario_set), env);
}
} // end public TestCaseGroupKey createTestGroupKey
diff --git a/src/com/mostc/pftt/scenario/CLIScenario.java
b/src/com/mostc/pftt/scenario/CLIScenario.java
index d1cd5b8..fce286d 100644
--- a/src/com/mostc/pftt/scenario/CLIScenario.java
+++ b/src/com/mostc/pftt/scenario/CLIScenario.java
@@ -50,11 +50,19 @@ public class CliScenario extends AbstractSAPIScenario {
public ESAPIType getSAPIType() {
return ESAPIType.CLI;
}
+
+ @Override
+ public PhpIni createIniForTest(ConsoleManager cm, Host host, PhpBuild
build, PhptActiveTestPack active_test_pack, ScenarioSet scenario_set) {
+ // default PhpIni will be given to php.exe using a file... @see
CliPhptTestCaseRunner#prepare
+ //
+ // this is needed only to collect any custom directives that a
test case provides
+ return new PhpIni();
+ }
@Override
public TestCaseGroupKey createTestGroupKey(ConsoleManager cm, Host
host, PhpBuild build, ScenarioSet scenario_set, PhptActiveTestPack
active_test_pack, PhptTestCase test_case, TestCaseGroupKey group_key) {
if (test_case.containsSection(EPhptSection.INI)) {
- PhpIni ini =
AbstractPhptTestCaseRunner.createIniForTest(cm, host, build, active_test_pack,
scenario_set);
+ PhpIni ini = createIniForTest(cm, host, build,
active_test_pack, scenario_set);
ini.replaceAll(test_case.getINI(active_test_pack,
host));
// note: don't bother comparing test case's INI with
existing group_key's INI, PhptTestPackRunner
@@ -68,7 +76,7 @@ public class CliScenario extends AbstractSAPIScenario {
} else if (group_key!=null &&
group_key.getPhpIni().isDefault()) {
return group_key;
} else {
- return new
TestCaseGroupKey(AbstractPhptTestCaseRunner.createIniForTest(cm, host, build,
active_test_pack, scenario_set), null);
+ return new TestCaseGroupKey(createIniForTest(cm, host,
build, active_test_pack, scenario_set), null);
}
} // end public TestCaseGroupKey createTestGroupKey
diff --git a/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java
b/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java
index c32d645..c319874 100644
--- a/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java
+++ b/src/com/mostc/pftt/scenario/NoCodeCacheScenario.java
@@ -15,6 +15,11 @@ import com.mostc.pftt.results.ConsoleManager;
public class NoCodeCacheScenario extends AbstractCodeCacheScenario {
@Override
+ public boolean isPlaceholder() {
+ return true;
+ }
+
+ @Override
public String getName() {
return "No-Code-Cache";
}
diff --git a/src/com/mostc/pftt/scenario/NoDebugScenario.java
b/src/com/mostc/pftt/scenario/NoDebugScenario.java
index dd5a037..1ace267 100644
--- a/src/com/mostc/pftt/scenario/NoDebugScenario.java
+++ b/src/com/mostc/pftt/scenario/NoDebugScenario.java
@@ -14,6 +14,11 @@ import com.mostc.pftt.results.ConsoleManager;
public class NoDebugScenario extends AbstractDebugScenario {
@Override
+ public boolean isPlaceholder() {
+ return true;
+ }
+
+ @Override
public boolean setup(ConsoleManager cm, Host host, PhpBuild build,
PhpIni ini) {
return false;
}
diff --git a/src/com/mostc/pftt/scenario/PlainSocketScenario.java
b/src/com/mostc/pftt/scenario/PlainSocketScenario.java
index 570400e..6274f63 100644
--- a/src/com/mostc/pftt/scenario/PlainSocketScenario.java
+++ b/src/com/mostc/pftt/scenario/PlainSocketScenario.java
@@ -14,6 +14,11 @@ import com.mostc.pftt.results.ConsoleManager;
public class PlainSocketScenario extends AbstractSocketScenario {
@Override
+ public boolean isPlaceholder() {
+ return true;
+ }
+
+ @Override
public String getName() {
return "Plain-Socket";
}
diff --git a/src/com/mostc/pftt/scenario/SMBBasicScenario.java
b/src/com/mostc/pftt/scenario/SMBBasicScenario.java
index 02028d9..cdfafac 100644
--- a/src/com/mostc/pftt/scenario/SMBBasicScenario.java
+++ b/src/com/mostc/pftt/scenario/SMBBasicScenario.java
@@ -2,7 +2,7 @@ package com.mostc.pftt.scenario;
import com.mostc.pftt.host.RemoteHost;
-/** Tests running a PHP build and its test pack both stored remotely on a
basic SMB file share. (NOT IMPLEMENTED)
+/** Tests running a PHP build and its test pack both stored remotely on a
basic SMB file share.
*
* @author Matt Ficken
*
diff --git a/src/com/mostc/pftt/scenario/SMBCAScenario.java
b/src/com/mostc/pftt/scenario/SMBCAScenario.java
index 157f36c..22bf878 100644
--- a/src/com/mostc/pftt/scenario/SMBCAScenario.java
+++ b/src/com/mostc/pftt/scenario/SMBCAScenario.java
@@ -2,6 +2,7 @@ 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.results.ConsoleManager;
/** Tests PHP using SMB Continuous Availability (CA) (NOT IMPLEMENTED)
@@ -24,7 +25,9 @@ public class SMBCAScenario extends AbstractSMBScenario {
@Override
protected boolean createShareWindows(ConsoleManager cm) throws
Exception {
- return remote_host.exec("Powershell -Command{New-SmbShare -Name
"+share_name+" -Path "+file_path+" -Scope "+remote_host.getHostname()+"
-FullControl "+remote_host.getHostname()+"\\"+remote_host.getUsername()+"}",
Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess();
+ 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);
+ teo.printOutputIfCrash(getClass(), cm);
+ return teo.cleanupIfSuccess(remote_host);
}
@Override
@@ -34,7 +37,7 @@ public class SMBCAScenario extends AbstractSMBScenario {
@Override
public boolean isImplemented() {
- return true;
+ return false;
}
} // end public class SMBCAScenario
diff --git a/src/com/mostc/pftt/scenario/SMBDFSRScenario.java
b/src/com/mostc/pftt/scenario/SMBDFSRScenario.java
index 082c871..e0b8c5c 100644
--- a/src/com/mostc/pftt/scenario/SMBDFSRScenario.java
+++ b/src/com/mostc/pftt/scenario/SMBDFSRScenario.java
@@ -2,11 +2,12 @@ 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. (NOT IMPLEMENTED)
+/** 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.
*
@@ -17,13 +18,21 @@ import com.mostc.pftt.results.ConsoleManager.EPrintType;
* 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`
+ * @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);
}
@@ -34,31 +43,29 @@ public class SMBDFSRScenario extends AbstractSMBScenario {
}
@Override
- public boolean setup(ConsoleManager cm, Host host, PhpBuild build,
ScenarioSet scenario_set) {
+ 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");
- String tmp_file = host.mktempname(getName(), "ps1");
-
try {
- host.saveTextFile(tmp_file, ps_sb.toString());
-
- if (host.exec("Powershell -File "+tmp_file,
Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess()) {
- host.delete(tmp_file);
+ 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, host, build, scenario_set))
{
-
cm.println(EPrintType.COMPLETED_OPERATION, getName(), "DFSR setup successfully
on "+unc_path+" "+smb_path);
+ 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: "+tmp_file);
+
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, "", host, tmp_file, unc_path);
+
cm.addGlobalException(EPrintType.OPERATION_FAILED_CONTINUING, getClass(),
"setup", ex, "", remote_host, ps_sb, unc_path);
}
return false;
}
diff --git a/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
b/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
index ba8ee99..43b54a3 100644
--- a/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
+++ b/src/com/mostc/pftt/scenario/SMBDeduplicationScenario.java
@@ -2,11 +2,12 @@ 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 the new Remote Data Deduplication feature of Windows 2012 using SMB.
(NOT IMPLEMENTED)
+/** 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.
*
@@ -60,14 +61,18 @@ public class SMBDeduplicationScenario extends
AbstractSMBScenario {
@Override
public boolean notifyPrepareStorageDir(ConsoleManager cm, Host
local_host) {
// check that its win8
- if (!remote_host.isWin8OrLater()) {
+ System.out.println("64");
+ // TODO
+ if (false) { // TODO !remote_host.isWin8OrLater()) {
+ System.out.println("66");
cm.println(EPrintType.XSKIP_OPERATION, getName(),
"Scenario can only be run against a Windows 8/2012+ host");
return false;
} 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 false;
}
-
+ System.out.println("74");
StringBuilder ps_sb = new StringBuilder(128);
// install deduplication feature
ps_sb.append("Import-Module ServerManager\n");
@@ -79,25 +84,24 @@ public class SMBDeduplicationScenario extends
AbstractSMBScenario {
// 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");
- String tmp_file = remote_host.mktempname(getName(), "ps1");
-
// create PowerShell script to install and enable deduplication
try {
- remote_host.saveTextFile(tmp_file, ps_sb.toString());
-
//
- if (remote_host.execElevated("powershell -File
"+tmp_file, Host.ONE_MINUTE * 10).printOutputIfCrash(getClass(),
cm).isSuccess()) {
+ System.out.println("89");
+ cm.println(EPrintType.IN_PROGRESS, getName(), "Starting
to enable 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
- remote_host.delete(tmp_file);
+ 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_path+" "+smb_path);
+ 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, tmp_file);
+ cm.addGlobalException(EPrintType.CANT_CONTINUE,
getClass(), "notifyPrepareStorageDir", ex, "Unable to enable deduplication",
remote_host, ps_sb);
}
return false;
} // end public boolean notifyPrepareStorageDir
@@ -111,9 +115,9 @@ public class SMBDeduplicationScenario extends
AbstractSMBScenario {
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...");
- if (remote_host.exec("powershell -Command
{Start-Dedupjob -Volume "+volume+" -Type Optimization -Wait}",
Host.FOUR_HOURS).printOutputIfCrash(getClass(), cm).isSuccess()) {
- cm.println(EPrintType.COMPLETED_OPERATION,
getName(), "Deduplication completed successfully.");
+ 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");
@@ -122,12 +126,12 @@ public class SMBDeduplicationScenario extends
AbstractSMBScenario {
cm.addGlobalException(EPrintType.CANT_CONTINUE,
getClass(), "notifyTestPackInstalled", ex, "Deduplication failed", remote_host,
local_host, volume);
}
return false;
- }
+ } // end public boolean notifyTestPackInstalled
@Override
public String getName() {
return "SMB-Deduplication";
- }
+ }
@Override
public boolean isImplemented() {
diff --git a/src/com/mostc/pftt/scenario/Scenario.java
b/src/com/mostc/pftt/scenario/Scenario.java
index 562815e..2d6b558 100644
--- a/src/com/mostc/pftt/scenario/Scenario.java
+++ b/src/com/mostc/pftt/scenario/Scenario.java
@@ -57,6 +57,14 @@ public abstract class Scenario {
public void getENV(Map<String, String> env) {
}
+
+ public boolean isPlaceholder() {
+ return false;
+ }
+
+ public boolean ignoreForShortName() {
+ return false;
+ }
public boolean hasENV() {
return false;
diff --git a/src/com/mostc/pftt/scenario/ScenarioSet.java
b/src/com/mostc/pftt/scenario/ScenarioSet.java
index 156e95e..4060f84 100644
--- a/src/com/mostc/pftt/scenario/ScenarioSet.java
+++ b/src/com/mostc/pftt/scenario/ScenarioSet.java
@@ -66,15 +66,14 @@ public class ScenarioSet extends ArrayList<Scenario> {
StringBuilder sb = new StringBuilder(40);
String str;
for ( Scenario s : this ) {
- if (sb.length()>0)
+ if (s.isPlaceholder())
+ continue;
+ else if (sb.length()>0)
sb.append('_');
str = s.toString();
- if (str.startsWith("No-"))
- // ignore these scenarios, they're placeholders
- continue;
sb.append(str);
}
- str = sb.toString();
+ this.str = sb.toString();
}
protected void forceSort() {
@@ -91,10 +90,26 @@ public class ScenarioSet extends ArrayList<Scenario> {
@Override
public String toString() {
+ return getName();
+ }
+
+ public String getName() {
ensureSorted();
return str; // @see #sort
}
+ public String getShortName() {
+ StringBuilder sb = new StringBuilder();
+ for ( Scenario s : this ) {
+ if (s.ignoreForShortName())
+ continue;
+ else if (sb.length()>0)
+ sb.append('_');
+ sb.append(s.getName());
+ }
+ return sb.toString();
+ }
+
@Override
public boolean add(Scenario s) {
super.add(s);
diff --git a/src/com/mostc/pftt/ui/PhptHostTab.java
b/src/com/mostc/pftt/ui/PhptHostTab.java
index a31b73f..73d7db2 100644
--- a/src/com/mostc/pftt/ui/PhptHostTab.java
+++ b/src/com/mostc/pftt/ui/PhptHostTab.java
@@ -86,12 +86,12 @@ public class PhptHostTab extends JSplitPane {
stop_button.setEnabled(false);
}
});
- panel.add("left", new JLabel("Pass"));
- panel.add("left", pass_label = new JLabel("0"));
- panel.add("left", pass_bar = new JProgressBar(0, 12000)); //
#showResult updates pass_bar maximum
- pass_bar.setStringPainted(true);
panel.add("left", new JLabel("Total"));
panel.add("left", total_label = new JLabel("0"));
+ panel.add("left", pass_bar = new JProgressBar(0, 12000)); //
#showResult updates pass_bar maximum
+ pass_bar.setStringPainted(true);
+ panel.add("left", new JLabel("Pass"));
+ panel.add("left", pass_label = new JLabel("0"));
panel.add("left", new JLabel("Fail"));
panel.add("left", fail_label = new JLabel("0"));
panel.add(new JLabel("CRASH"));
@@ -305,9 +305,9 @@ public class PhptHostTab extends JSplitPane {
fail++;
fail_label.setText(Integer.toString(fail));
-
pass_bar.setString(Float.toString(PhptResultPack.round1( (float)( ((float)pass)
/ ((float)( pass + fail + crash )) )))+"%"); // 1 decimal places nn.y
+
pass_bar.setString(Float.toString(PhptResultPack.round1( (float)( ( 100.0f *
pass) / ((float)( pass + fail +crash )) )))+"%"); // 1 decimal place nn.y
pass_bar.setMaximum(fail+pass);
-
total_label.setText(""+(fail+pass));
+
total_label.setText(""+(fail+pass+crash));
// show in list
fail_list_model.addElement(result);
@@ -350,7 +350,7 @@ public class PhptHostTab extends JSplitPane {
break;
case PASS:
pass++;
-
pass_bar.setString(Float.toString(PhptResultPack.round1( (float)( (double)pass
/ ((double)( pass + fail )) )))+"%"); // 1 decimal places nn.y
+
pass_bar.setString(Float.toString(PhptResultPack.round1( (float)( ( 100.0f *
pass) / ((float)( pass + fail + crash )) )))+"%"); // 1 decimal place nn.y
pass_bar.setValue(pass);
diff --git a/src/com/mostc/pftt/util/StringUtil.java
b/src/com/mostc/pftt/util/StringUtil.java
index 92aa87c..6c83783 100644
--- a/src/com/mostc/pftt/util/StringUtil.java
+++ b/src/com/mostc/pftt/util/StringUtil.java
@@ -19,6 +19,15 @@ import com.mostc.pftt.util.apache.regexp.REProgram;
public final class StringUtil {
public static final String EMPTY = "";
+ public static String chomp(String in) {
+ if (in.endsWith("\r\n"))
+ return in.substring(0, in.length()-2);
+ else if (in.endsWith("\n"))
+ return in.substring(0, in.length()-1);
+ else
+ return in;
+ }
+
public static String unquote(String in) {
if (isEmpty(in))
return in;
@@ -277,7 +286,7 @@ public final class StringUtil {
StringBuilder sb = new StringBuilder(256);
sb.append(parts[off]);
off++;
- for ( int i=0 ; i < len ; i++, off++ ) {
+ for ( int i=0 ; i < len && off < parts.length ; i++, off++ ) {
sb.append(delim);
sb.append(parts[off]);
}
@@ -402,6 +411,19 @@ public final class StringUtil {
} // end public static class LengthLimitStringWriter
+ public static boolean isWhitespaceOrEmpty(String a) {
+ if (a==null)
+ return true;
+ final int a_len = a.length();
+ if (a_len==0)
+ return true;
+ for ( int i=0 ; i < a_len ; i++ ) {
+ if (!Character.isLetter(a.charAt(i)))
+ return false;
+ }
+ return true;
+ }
+
private StringUtil() {}
} // end public class StringUtil
diff --git a/src/org/apache/sshd/server/filesystem/NativeSshFile.java
b/src/org/apache/sshd/server/filesystem/NativeSshFile.java
index cac0bc0..cb893aa 100644
--- a/src/org/apache/sshd/server/filesystem/NativeSshFile.java
+++ b/src/org/apache/sshd/server/filesystem/NativeSshFile.java
@@ -71,7 +71,7 @@ public class NativeSshFile implements SshFile {
if (fileName.length() == 0) {
throw new IllegalArgumentException("fileName can not be empty");
- } else if (fileName.charAt(0) != '/') {
+ } else if (fileName.charAt(0) != '/' &&
(fileName.length()<2||!Character.isLetter(fileName.charAt(0))||fileName.charAt(1)!=':'))
{
throw new IllegalArgumentException("fileName must be an absolute
path");
}
@@ -552,7 +552,11 @@ public class NativeSshFile implements SshFile {
.length())) {
resArg = normalizedRootDir;
}
-
+ System.out.println("555 "+resArg);
+ int i = resArg.lastIndexOf(':');
+ if (i>0)
+ resArg = resArg.substring(i-1);
+ System.out.println("559 "+resArg);
return resArg;
}