M dist/build.xml

- do Alpha 8 release

- Copy artifacts to local www for dist via CVS.

A dist/webclient-pom.xml

- Create Maven POM for error free artifact resolution

M dist/mcp-test/src/test/java/cardemo/CarDemoTest.java

- Update clientIds

- Use new package for WebclientTestCase

M dist/mcp-test/src/test/java/jsf_jmaki/JsfjMakiTest.java

- Use new timeout mechanism.

- Use new package for WebclientTestCase

M dist/netbeans/build.xml
M dist/netbeans/nbproject/project.properties

- alpha 8

M webclient/build-tests.xml

- remove cardemo from automated test run

M webclient/classes_spec/org/mozilla/mcp/MCP.java
A webclient/classes_spec/org/mozilla/mcp/TimeoutHandler.java

- Generalized timeout mechanism

A webclient/classes_spec/org/mozilla/mcp/CompareFiles.java
A webclient/classes_spec/org/mozilla/mcp/THTTPD.java
A webclient/classes_spec/org/mozilla/mcp/junit/TestLogStrings.properties
A webclient/classes_spec/org/mozilla/mcp/junit/WebclientTestCase.java
A webclient/classes_spec/org/mozilla/mcp/junit/package.html
R webclient/test/automated/src/classes/org/mozilla/util/THTTPD.java
R webclient/test/automated/src/classes/org/mozilla/webclient/CompareFiles.java
R webclient/test/automated/src/classes/org/mozilla/webclient/TestLogStrings.properties
R webclient/test/automated/src/classes/org/mozilla/webclient/WebclientTestCase.java
M webclient/test/automated/src/classes/org/mozilla/webclient/BookmarksTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/BrowserControlFactoryTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/CurrentPageTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/DOMTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/DocumentLoadListenerTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/HistoryTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/KeyListenerTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/MouseListenerTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/NavigationTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/PreferencesTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/ProfileManagerTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/WindowCreatorTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/impl/WebclientFactoryImplTest.java
M webclient/test/automated/src/classes/org/mozilla/webclient/impl/wrapper_native/TestGtkBrowserControlCanvas.java
M webclient/test/automated/src/classes/org/mozilla/webclient/impl/wrapper_native/WrapperFactoryImplTest.java

- New package for mcp JUnit support


git-svn-id: svn://10.0.0.236/trunk@225589 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
edburns%acm.org
2007-05-04 17:10:35 +00:00
parent d0415ed6dc
commit 4b3f15474f
29 changed files with 541 additions and 82 deletions

View File

@@ -0,0 +1,193 @@
/*
* $Id: CompareFiles.java,v 1.1 2007-05-04 17:10:17 edburns%acm.org Exp $
*/
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Sun
* Microsystems, Inc. Portions created by Sun are
* Copyright (C) 1999 Sun Microsystems, Inc. All
* Rights Reserved.
*
* Contributor(s): Ed Burns <edburns@acm.org>
*/
package org.mozilla.mcp;
import java.io.*;
import java.util.List;
import java.util.Iterator;
public class CompareFiles {
public CompareFiles() {
}
/**
* This method compares the input files character by character.
* Skips whitespaces and comparison is not case sensitive.
*/
public static boolean filesIdentical (String actualFileName,
String expectedFileName,
List expectedLinesToIgnore,
boolean ignorePrefix,
boolean ignoreWarnings,
List ignoreKeywords)
throws IOException {
boolean same = true;
File actualFile = new File(actualFileName);
File expectedFile = new File(expectedFileName);
FileReader actualFileReader = new FileReader(actualFile);
FileReader expectedFileReader = new FileReader(expectedFile);
LineNumberReader actualReader = new LineNumberReader(actualFileReader);
LineNumberReader expectedReader = new LineNumberReader(expectedFileReader);
String actualLine, expectedLine;
boolean swallowedLine = false;
actualLine = actualReader.readLine().trim();
expectedLine = expectedReader.readLine().trim();
// if one of the lines is null, but not the other
if (((null == actualLine) && (null != expectedLine)) ||
((null != actualLine) && (null == expectedLine))) {
same = false;
}
while (null != actualLine && null != expectedLine) {
if (ignorePrefix) {
int bracketColon = 0;
if (-1 != (bracketColon = actualLine.indexOf("]: "))) {
actualLine = actualLine.substring(bracketColon + 3);
}
if (-1 != (bracketColon = expectedLine.indexOf("]: "))) {
expectedLine = expectedLine.substring(bracketColon + 3);
}
}
swallowedLine = false;
// while the actual lines start with a warning condition
// keep reading them until we get a non-warning line or end
// of stream.
while (null != actualLine && ignoreWarnings &&
(-1 != actualLine.indexOf("WARNING:") ||
-1 != actualLine.indexOf("###!!! ASSERTION:") ||
-1 != actualLine.indexOf("###!!! Break:"))) {
// we're ignoring warnings, no-op
actualLine = actualReader.readLine(); // swallow WARNING
// line
swallowedLine = true;
}
if (null != actualLine && swallowedLine) {
continue;
}
swallowedLine = false;
// while the expected lines start with a warning condition,
// keep reading them until we get a non-warning line or end
// of stream.
while (null != expectedLine && ignoreWarnings &&
(-1 != expectedLine.indexOf("WARNING:") ||
-1 != expectedLine.indexOf("###!!! ASSERTION:") ||
-1 != expectedLine.indexOf("###!!! Break:"))) {
// we're ignoring warnings, no-op
expectedLine = expectedReader.readLine(); // swallow
// WARNING
// line
swallowedLine = true;
}
if (null != actualLine && swallowedLine) {
continue;
}
if (null == actualLine && null == expectedLine) {
same = true;
continue;
}
// if one of the lines is null, but not the other
if (((null == actualLine) && (null != expectedLine)) ||
((null != actualLine) && (null == expectedLine))) {
same = false;
break;
}
if (!actualLine.equals(expectedLine)) {
if (null != expectedLinesToIgnore) {
// go thru the list of expectedLinesToIgnore and see if
// the current expectedLine matches any of them.
Iterator ignoreLines = expectedLinesToIgnore.iterator();
boolean foundMatch = false;
while (ignoreLines.hasNext()) {
String newTrim = ((String) ignoreLines.next()).trim();
if (expectedLine.equals(newTrim)) {
foundMatch = true;
break;
}
}
// If we haven't found a match, then this mismatch is
// important
if (!foundMatch) {
same = false;
System.out.println("actualLine: " + actualLine);
System.out.println("expectedLine: " + expectedLine);
break;
}
}
else {
same = false;
if (null != ignoreKeywords && 0 < ignoreKeywords.size()) {
Iterator iter = ignoreKeywords.iterator();
while (iter.hasNext()) {
if (-1 != actualLine.indexOf((String) iter.next())) {
// we're ignoring lines that contain this
// keyword, no-op
same = true;
break;
}
}
}
if (!same) {
System.out.println("actualLine: " + actualLine);
System.out.println("expectedLine: " + expectedLine);
break;
}
}
}
actualLine = actualReader.readLine();
expectedLine = expectedReader.readLine();
if (null != actualLine) {
actualLine = actualLine.trim();
}
if (null != expectedLine) {
expectedLine = expectedLine.trim();
}
}
actualReader.close();
expectedReader.close();
// if same is true and both files have reached eof, then
// files are identical
if (same == true) {
return true;
}
return false;
}
}

View File

@@ -1,5 +1,5 @@
/*
* $Id: MCP.java,v 1.9 2007-04-21 03:25:37 edburns%acm.org Exp $
* $Id: MCP.java,v 1.10 2007-05-04 17:10:17 edburns%acm.org Exp $
*/
/*
@@ -91,6 +91,8 @@ public class MCP {
private Robot robot;
private DOMTreeDumper treeDumper = null;
private CountDownLatch latch = null;
private TimeoutHandler timeoutHandler = null;
private long Timeout = 30000L;
private void createLatch() {
if (null != latch) {
@@ -528,6 +530,7 @@ public class MCP {
robot.mouseMove(x, y);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
startTimeoutCheckIfNecessary();
} catch (NumberFormatException ex) {
LOGGER.throwing(this.getClass().getName(), "clickElementGivenId",
@@ -612,6 +615,7 @@ public class MCP {
Navigation2 nav = getNavigation();
synchronized (this) {
nav.loadURL(url);
startTimeoutCheckIfNecessary();
createLatch();
try {
lockLatch();
@@ -652,6 +656,10 @@ public class MCP {
case ((int) DocumentLoadEvent.END_AJAX_EVENT_MASK):
case ((int) DocumentLoadEvent.END_DOCUMENT_LOAD_EVENT_MASK):
openLatch();
if (null != MCP.this.timeoutThread) {
MCP.this.abortTimeoutCheck();
}
break;
case ((int) DocumentLoadEvent.START_URL_LOAD_EVENT_MASK):
String method = (String) eventData.get("method");
@@ -683,4 +691,165 @@ public class MCP {
}
private void startTimeoutCheckIfNecessary() {
// If we are already tracking a timeout...
if (null != timeoutThread) {
abortTimeoutCheck();
}
if (null != getTimeoutHandler()) {
timeoutRunnable = new TimeoutRunnable();
timeoutThread = new Thread(timeoutRunnable,
"TimeoutThread-" + getTimeoutHandler().toString());
timeoutThread.start();
}
}
private void abortTimeoutCheck() {
assert(null != timeoutThread);
assert(null != timeoutRunnable);
timeoutRunnable.setRunning(false);
timeoutThread.interrupt();
timeoutRunnable = null;
timeoutThread = null;
}
private Thread timeoutThread = null;
private TimeoutRunnable timeoutRunnable = null;
/**
* <p>Return the currently installed {@link TimeoutHandler}, if
* any.</p>
*/
public TimeoutHandler getTimeoutHandler() {
return timeoutHandler;
}
/**
* <p>Install an instance of {@link TimeoutHandler} that will be
* used for all subsequent browser interactions (clicks, loads, Ajax
* transactions, etc). To remove the <code>TimeoutHandler</code>,
* pass <code>null</code> to this method. If a handler is
* installed, the timer is automatically started when a browser
* interaction commences. If the browser interaction does not
* complete within {@link #getTimeout} milliseconds, the {@link
* TimeoutHandler#timeout} method is called on the argument
* <code>TimeoutHandler</code> instance.</p>
*/
public void setTimeoutHandler(TimeoutHandler timeoutHandler) {
if (null != timeoutThread) {
abortTimeoutCheck();
}
this.timeoutHandler = timeoutHandler;
}
/**
* <p>Return the number of milliseconds that must elapse before the
* {@link TimeoutHandler} is called. Note that a
* <code>TimeoutHandler</code> is only called if the user has
* installed one by calling {@link #setTimeoutHandler}.</p>
*/
public long getTimeout() {
return Timeout;
}
/**
* <p>Set the number of milliseconds that must elapse before the
* {@link TimeoutHandler} is called, if such an instance has been
* installed via a previous call to {@link @setTimeoutHandler}.</p>
*/
public void setTimeout(long Timeout) {
this.Timeout = Timeout;
}
private long waitInterval = 5000L;
/**
* <p>Return the number of milliseconds to wait between timeout
* checks.</p>
*/
public long getTimeoutWaitInterval() {
return waitInterval;
}
/**
* <p>Set the number of milliseconds to wait between timeout
* checks.</p>
*/
public void setTimeoutWaitInterval(long waitInterval) {
this.waitInterval = waitInterval;
}
private class TimeoutRunnable implements Runnable {
public void run() {
setRunning(true);
while (isRunning()) {
try {
Thread.currentThread().sleep(MCP.this.getTimeoutWaitInterval());
} catch (InterruptedException ex) {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, "Thread " +
Thread.currentThread().getName() +
" interrupted while sleeping.", ex);
}
setRunning(false);
return;
}
if (isTimedout()) {
setRunning(false);
if (null != MCP.this.getTimeoutHandler()) {
MCP.this.getTimeoutHandler().timeout();
}
}
}
}
private long startTime = -1L;
private boolean running = false;
public boolean isRunning() {
return running;
}
public void setRunning(boolean newValue) {
if (newValue) {
startTime = System.currentTimeMillis();
}
else {
startTime = -1L;
}
this.running = newValue;
}
/**
* <p>Returns <code>true</code> if {@link isTiming} returns <code>true</code>
* and the elapsed time between when timing commenced and
* the current time is greater than the value returned by {@link getTimeout}.
* Otherwise, returns <code>false</code>. This method need not be called
* by the user.
*/
public boolean isTimedout() {
boolean result = false;
if (isRunning()) {
result = (MCP.this.getTimeout() < (System.currentTimeMillis() - startTime));
}
return result;
}
}
}

View File

@@ -0,0 +1,267 @@
/*
* $Id: THTTPD.java,v 1.1 2007-05-04 17:10:17 edburns%acm.org Exp $
*/
/*
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Sun
* Microsystems, Inc. Portions created by Sun are
* Copyright (C) 1999 Sun Microsystems, Inc. All
* Rights Reserved.
*
* Contributor(s): Ed Burns &lt;edburns@acm.org&gt;
*/
package org.mozilla.mcp;
import java.io.File;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
// THTTPD.java
public class THTTPD extends Object {
public final static int PORT = 5243;
public static class ServerThread extends Thread {
protected File root = null;
protected boolean keepRunning = true;
protected int maxRequests = -1;
protected int numRequests = 0;
protected int count = 0;
public final static int REQUEST_GET = 2;
public final static int REQUEST_POST = 3;
protected StringBuffer requestData = null;
public ServerThread(String name, File root,
int maxRequests) {
super(name);
this.root = root;
this.maxRequests = maxRequests;
keepRunning = true;
requestData = new StringBuffer();
}
public String getRequestData() {
String result = null;
if (null != requestData) {
synchronized (requestData) {
result = requestData.toString();
}
}
return result;
}
protected int soTimeout = -1;
public int getSoTimeout() {
return soTimeout;
}
public void setSoTimeout(int newSoTimeout) {
soTimeout = newSoTimeout;
}
public void stopRunning() {
keepRunning = false;
this.interrupt();
}
public void run() {
ServerSocket serverSocket = null;
Socket socket = null;
BufferedReader
responseReader = null,
requestReader = null;
InputStream socketInputStream = null;
BufferedWriter
responseWriter = null;
String
requestLine = null,
curLine = null;
File responseFile = null;
StringBuffer
responseString = null;
V();
while (keepRunning) {
if (numRequests >= maxRequests) {
if (-1 != maxRequests) {
break;
}
}
numRequests++;
try {
serverSocket = new ServerSocket(PORT);
if (-1 != getSoTimeout()) {
serverSocket.setSoTimeout(getSoTimeout());
}
socket = serverSocket.accept();
requestReader = new BufferedReader(new InputStreamReader(socketInputStream = socket.getInputStream()));
requestLine = requestReader.readLine();
synchronized (requestData) {
requestData.delete(0, requestData.length());
requestData.append(requestLine);
while (null != (curLine = requestReader.readLine())) {
requestData.append(curLine);
if (curLine.trim().length() == 0) {
break;
}
}
}
switch (getRequestMethod(requestLine)) {
case REQUEST_POST:
System.out.println("THTTPD: POST");
// intentional fall through!
case REQUEST_GET:
responseWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
if (null !=
(responseFile = getFileForRequestURI(getRequestURI(requestLine)))) {
curLine = "HTTP/1.0 200 OK\r\n";
responseWriter.write(curLine, 0,
curLine.length());
responseReader = new BufferedReader(new InputStreamReader(new FileInputStream(responseFile)));
responseString = new StringBuffer();
while (null != (curLine = responseReader.readLine())) {
responseString.append(curLine);
}
curLine = "Server: THTTPD\r\n" +
"Content-type: " +
getContentTypeForFile(responseFile) +
"\r\nContent-Length: " +
responseString.length() + "\r\n\r\n";
responseWriter.write(curLine, 0,
curLine.length());
responseWriter.write(responseString.toString(),
0, responseString.length());
responseWriter.flush();
responseWriter.close();
}
break;
}
socket.close();
serverSocket.close();
}
catch (Exception e) {
System.out.println("Exception: " + e + " " +
e.getMessage());
stopRunning();
}
}
V();
}
protected int getRequestMethod(String requestLine) {
int result = REQUEST_GET;
if (0 == requestLine.indexOf("GET")) {
result = REQUEST_GET;
}
else if (0 == requestLine.indexOf("POST")) {
result = REQUEST_POST;
}
return result;
}
protected String getRequestURI(String requestLine) {
String result = null;
int space2, space1 = requestLine.indexOf(" ");
if (-1 == space1) {
return result;
}
space2 = requestLine.indexOf(" ", ++space1);
if (-1 == space2) {
return result;
}
result = requestLine.substring(space1, space2);
return result;
}
protected File getFileForRequestURI(String requestURI) {
File result = new File(root, requestURI);
if (!result.exists() || result.isDirectory()) {
result = null;
}
return result;
}
protected String getContentTypeForFile(File file) {
String
fileName = file.getName(),
result = "text/plain";
int lastDot = fileName.lastIndexOf(".");
if (-1 != lastDot) {
result = fileName.substring(lastDot+1);
if (result.equalsIgnoreCase("html")) {
result = "text/html";
}
}
return result;
}
public synchronized void P() {
while (count <= 0) {
try { wait(); } catch (InterruptedException ex) {}
}
--count;
}
public synchronized void V() {
++count;
notifyAll();
}
}
public static void printUsage() {
}
public static void main(String args[]) {
// validate args
if ((args.length < 2) ||
(null == args[0] || 0 == args[0].length()) ||
(null == args[1] || 0 == args[1].length()) ||
(!args[0].equals("-root"))) {
printUsage();
return;
}
File root = new File(args[1]);
if (!root.exists() || !root.isDirectory()) {
printUsage();
}
Object toNotify = new Object();
ServerThread server = new ServerThread("THTTPD-MainThread", root, -1);
server.start();
server.P();
server.P();
}
}

View File

@@ -0,0 +1,125 @@
/*
* $Id: TimeoutHandler.java,v 1.1 2007-05-04 17:10:17 edburns%acm.org Exp $
*/
/*
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Sun
* Microsystems, Inc. Portions created by Sun are
* Copyright (C) 1999 Sun Microsystems, Inc. All
* Rights Reserved.
*
* Contributor(s): Ed Burns &lt;edburns@acm.org&gt;
*/
package org.mozilla.mcp;
/**
* <p>This class provides a simple facility for placing a time bound on
* browser interactions (clicks, Ajax transactions, etc).</p>
*
* <p>Usage</p>
*
* <p>A useful pattern is to use this as an inner class within a JUnit
* testscase:</p>
<pre><code>
final Thread testThread = Thread.currentThread();
timeoutHandler = new TimeoutHandler() {
public void timeout() {
super.timeout();
testThread.interrupt();
fail("Action timed out");
}
};
mcp.setTimeoutHandler(timeoutHandler);
</code></pre>
*
* <p><code>TimeoutHandler</code> has a boolean JavaBeans property
* called <code>didTimeout</code> that can be used after blocking
* operations to test if a timeout happened.</p>
<pre><code>
if (timeoutHandler.isDidTimeout()) {
fail("timed out waiting for load");
}
</code></pre>
*
* <p>Another useful pattern is to combine the previous inner class
* approach with having the browser perform a non-blocking operation,
* and then causing the main thread to enter a loop until either a
* condition is met, or the timeout occurs:</p>
*
<pre><code>
bitSet.clear();
mcp.clickElement(inplaceFields.get(1));
makeAjaxAssertions(bitSet);
//...
private void makeAjaxAssertions(BitSet bitSet) throws Exception {
// Artifically wait for the ajax transaction to complete, or the timeout to be reached.
int i = 0;
while (true) {
if (bitSet.get(TestFeature.STOP_WAITING.ordinal())) {
break;
}
i++;
Thread.currentThread().sleep(mcp.getTimeoutWaitInterval());
}
// assert that the ajax transaction succeeded
assertTrue(bitSet.get(TestFeature.RECEIVED_END_AJAX_EVENT.ordinal()));
}
</code></pre>
*
* <p>The above code will either exit normally, by virtuo of the
* AjaxListener being called and it setting the STOP_WAITING bit in the
* bitset, or it will terminate due to timeout, in which case the inner
* class timeout method will be called.</p>
*
* @author edburns
*/
public class TimeoutHandler {
/**
* <p>The default implementation sets the value of the
* <code>didTimeout</code> JavaBeans property to
* <code>true</code>.</p>
*/
public void timeout() {
setDidTimeout(true);
}
private boolean didTimeout = false;
/**
* <p>Getter for boolean JavaBeans property
* <code>didTimeout</code>.</p>
*/
public boolean isDidTimeout() {
return didTimeout;
}
/**
* <p>Setter for boolean JavaBeans property
* <code>didTimeout</code>.</p>
*/
public void setDidTimeout(boolean didTimeout) {
this.didTimeout = didTimeout;
}
}

View File

@@ -0,0 +1 @@
# Sample ResourceBundle properties file

View File

@@ -0,0 +1,325 @@
/*
* $Id: WebclientTestCase.java,v 1.1 2007-05-04 17:10:17 edburns%acm.org Exp $
*/
/*
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Sun
* Microsystems, Inc. Portions created by Sun are
* Copyright (C) 1999 Sun Microsystems, Inc. All
* Rights Reserved.
*
* Contributor(s): Ed Burns &lt;edburns@acm.org&gt;
*/
package org.mozilla.mcp.junit;
// WebclientTestCase.java
import java.util.ArrayList;
import java.util.List;
import java.io.IOException;
import java.io.File;
import java.util.logging.Logger;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.framework.TestResult;
import org.mozilla.mcp.CompareFiles;
import org.mozilla.mcp.THTTPD;
import org.mozilla.webclient.BrowserControlFactory;
/**
*
* <p>WebclientTestCase extends <code>junit.framework.TestCase</code>
* and allows using MCP from a JUnit test. It makes assertions that
* verify preconditions for running MCP.</p>
*
* <p>This class currently has a number of undocumented and unsupported
* features that can be useful if you take the time to look at the
* source. Specifically, it has the ability to capture output from
* running the testcase, compare that output with a golden file, and it
* has a trivial HTTP server built in so webclient automated tests can
* run without any extra server baggage.</p>
*
* @version $Id: WebclientTestCase.java,v 1.1 2007-05-04 17:10:17 edburns%acm.org Exp $
*
*
*/
public abstract class WebclientTestCase extends TestCase
{
//
// Protected Constants
//
public static final String WEBCLIENTSTUB_LOG_MODULE = "webclientstub";
public static final String WEBCLIENT_LOG_MODULE = "webclient";
public static String OUTPUT_FILE_ROOT = null;
public static final String TEST_LOG = "org.mozilla.mcp.junit";
public static final String TEST_LOG_STRINGS = "org.mozilla.mcp.junit.TestLogStrings";
public static final Logger LOGGER = getLogger(TEST_LOG);
//
// Class Variables
//
static THTTPD.ServerThread serverThread;
//
// Instance Variables
//
// Attribute Instance Variables
// Relationship Instance Variables
//
// Constructors and Initializers
//
public WebclientTestCase()
{
super("WebclientTestCase");
}
public WebclientTestCase(String name)
{
super(name);
}
//
// Class methods
//
public static Logger getLogger( String loggerName ) {
return Logger.getLogger(loggerName, TEST_LOG_STRINGS );
}
//
// Methods From TestCase
//
public void setUp()
{
verifyPreconditions();
verifyOutputFileRootIsSet();
LOGGER.info(this.getClass().getName() + " setUp()");
}
public void tearDown()
{
LOGGER.info(this.getClass().getName() + " tearDown()");
}
//
// General Methods
//
public static TestSuite createServerTestSuite() {
verifyOutputFileRootIsSet();
TestSuite result = new TestSuite() {
public void run(TestResult result) {
serverThread =
new THTTPD.ServerThread("LocalHTTPD",
new File (OUTPUT_FILE_ROOT), -1);
serverThread.start();
serverThread.P();
super.run(result);
try {
BrowserControlFactory.appTerminate();
}
catch (Exception e) {
fail();
}
serverThread.stopRunning();
}
};
return result;
}
/**
* assertTrue that the string logModuleName is a correct log module
* string as specified in pr_log.h, and that its value is at least n.
*/
protected void verifyLogModuleValueIsAtLeastN(String logModuleName, int n)
{
int i = 0;
String logModuleValue = null;
assertTrue(null != (logModuleValue =
System.getProperty("NSPR_LOG_MODULES")));
assertTrue(-1 !=
(i = logModuleValue.indexOf(logModuleName + ":")));
try {
i = Integer.
valueOf(logModuleValue.substring(i + logModuleName.length() + 1,
i + logModuleName.length() + 2)).
intValue();
assertTrue(i >= n);
}
catch (Throwable e) {
e.printStackTrace();
assertTrue(false);
}
}
protected static void verifyBinDirSet()
{
assertTrue("BROWSER_BIN_DIR is not set",
null != System.getProperty("BROWSER_BIN_DIR"));
}
protected static String getBrowserBinDir() {
return System.getProperty("BROWSER_BIN_DIR");
}
protected static String getOutputFileRoot() {
return OUTPUT_FILE_ROOT;
}
/**
* assertTrue that NSPR_LOG_FILE is set.
*/
protected String verifyOutputFileIsSet()
{
String logFileValue = null;
assertTrue(null != (logFileValue =
System.getProperty("NSPR_LOG_FILE")));
return logFileValue;
}
private static void verifyOutputFileRootIsSet() {
if (null != OUTPUT_FILE_ROOT) {
return;
}
OUTPUT_FILE_ROOT = System.getProperty("build.test.results.dir");
assertNotNull(OUTPUT_FILE_ROOT);
File outputRoot = new File(OUTPUT_FILE_ROOT);
assertTrue(outputRoot.exists());
}
/**
* This implementation checks that the proper environment vars are set.
*/
protected void verifyPreconditions()
{
String nsprLogModules = null;
// make sure we have at least PR_LOG_DEBUG set
verifyLogModuleValueIsAtLeastN(WEBCLIENTSTUB_LOG_MODULE, 4);
verifyLogModuleValueIsAtLeastN(WEBCLIENT_LOG_MODULE, 4);
verifyBinDirSet();
if (sendOutputToFile()) {
verifyOutputFileIsSet();
}
}
public boolean verifyExpectedOutput()
{
boolean result = false;
CompareFiles cf = new CompareFiles();
String errorMessage = null;
String outputFileName = null;
String correctFileName = null;
// If this testcase doesn't participate in file comparison
if (!this.sendOutputToFile() &&
(null == this.getExpectedOutputFilename())) {
return true;
}
if (this.sendOutputToFile() ) {
outputFileName = verifyOutputFileIsSet();
}
correctFileName = OUTPUT_FILE_ROOT + this.getExpectedOutputFilename();
errorMessage = "File Comparison failed: diff -u " + outputFileName + " " +
correctFileName;
ArrayList ignoreList = null;
String [] ignore = null;
if (null != (ignore = this.getLinesToIgnore())) {
ignoreList = new ArrayList();
for (int i = 0; i < ignore.length; i++) {
ignoreList.add(ignore[i]);
}
}
try {
result = cf.filesIdentical(outputFileName, correctFileName,ignoreList,
getIgnorePrefix(), getIgnoreWarnings(),
getIgnoreKeywords());
}
catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
if (!result) {
System.out.println(errorMessage);
}
System.out.println("VERIFY:"+result);
return result;
}
/**
* @return the name of the expected output filename for this testcase.
*/
public String getExpectedOutputFilename() { return null; }
public String [] getLinesToIgnore() { return null; }
public List getIgnoreKeywords() {
ArrayList result = new ArrayList();
result.add("nativeBinDir");
return result;
}
public boolean getIgnorePrefix() { return true; }
public boolean getIgnoreWarnings() { return true; }
public boolean sendOutputToFile() { return false; }
} // end of class WebclientTestCase

View File

@@ -0,0 +1,43 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!--
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Ed Burns &gt;edburns@acm.org&lt;
-->
<html>
<head>
<title>org.mozilla.mcp.junit</title>
</head>
<body>
<p>JUnit Support for Mozilla Control Program</p>
<img width="120" height="86" src="../mcp.jpg" style="float:left; padding:1%;" alt="Master Control Program, from TRON" />
<p>This class extends JUnit TestCase for use with MCP.</p>
</body>
</html>