You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2008/06/14 17:44:35 UTC
svn commit: r667821 [1/2] -
/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/
Author: costin
Date: Sat Jun 14 08:44:34 2008
New Revision: 667821
URL: http://svn.apache.org/viewvc?rev=667821&view=rev
Log:
Helper to start all test servers and init testing.
A small refactoring of the ancient watchdog, for lazy people - it runs now as JUnit test suite, pretty easy to integrate
in an eclipse workflow.
Added:
tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/
tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java (with props)
tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java (with props)
tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java (with props)
tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java (with props)
tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java (with props)
tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java (with props)
tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java (with props)
tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/SimpleHttpClient.java (with props)
tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/WatchdogClient.java (with props)
Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,639 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.test;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * Represents a collection of Cookie instances.
+ * <p>
+ * Fires events when the cookies have been changed internally. Deals
+ * with management of cookies in terms of saving and loading them,
+ * and disabling them.
+ *
+ * @author Ramesh.Mandava
+ */
+public class CookieController {
+
+// private VetoableChangeSupport vceListeners;
+
+ private static Hashtable cookieJar = new Hashtable();
+
+ /* public no arg constructor for bean */
+ public CookieController() {
+ }
+
+/////////////////////////////////////////////////////////////
+ /**
+ * Records any cookies which have been sent as part of an HTTP response.
+ * The connection parameter must be already have been opened, so that
+ * the response headers are available. It's ok to pass a non-HTTP
+ * URL connection, or one which does not have any set-cookie headers.
+ */
+ public void recordAnyCookies(Vector rcvVectorOfCookies , URL url ) {
+
+ if ((rcvVectorOfCookies == null) || ( rcvVectorOfCookies.size()== 0) ) {
+ // no headers here
+ return;
+ }
+ try {
+ /*
+ Properties properties = new Properties();
+ FileInputStream fin = new FileInputStream("ServerAutoRun.properties");
+ properties.load(fin);
+
+ String cookiepolicy = properties.getProperty("cookie.acceptpolicy");
+ if (cookiepolicy == null || cookiepolicy.equals("none")) {
+ return;
+ }
+ */
+
+
+
+
+ for (int hi = 0; hi<rcvVectorOfCookies.size(); hi++) {
+
+ String cookieValue = (String)rcvVectorOfCookies.elementAt(hi) ;
+ recordCookie(url, cookieValue); // What to do here
+ }
+
+ }
+ catch( Exception e )
+ {
+ System.out.println("exception : " + e );
+ }
+ }
+
+
+ /**
+ * Create a cookie from the cookie, and use the HttpURLConnection to
+ * fill in unspecified values in the cookie with defaults.
+ */
+ public void recordCookie(URL url,
+ String cookieValue) {
+ HttpCookie cookie = new HttpCookie(url, cookieValue);
+
+ // First, check to make sure the cookie's domain matches the
+ // server's, and has the required number of '.'s
+ String twodot[]=
+ {"com", "edu", "net", "org", "gov", "mil", "int"};
+ String domain = cookie.getDomain();
+ if( domain == null )
+ return;
+ int index = domain.indexOf(':');
+ if (index != -1) {
+ int portCookie;
+ try {
+ portCookie = (Integer.valueOf(domain.substring(index+1,domain.length()))).intValue();
+ } catch (Exception e) {
+ return;
+ }
+ portCookie = ( portCookie == -1 ) ? 80 : portCookie;
+ domain=domain.substring(0,index);
+ }
+ domain.toLowerCase();
+
+ String host = url.getHost();
+ host.toLowerCase();
+
+ boolean domainOK = host.equals(domain);
+ if( !domainOK && host.endsWith( domain ) ) {
+ int dotsNeeded = 2;
+ for( int i = 0; i < twodot.length; i++ ) {
+ if( domain.endsWith( twodot[i] ) ) {
+ dotsNeeded = 1;
+ }
+ }
+
+ int lastChar = domain.length();
+ for( ; lastChar > 0 && dotsNeeded > 0; dotsNeeded-- ) {
+ lastChar = domain.lastIndexOf( '.', lastChar-1 );
+ }
+
+ if( lastChar > 0 )
+ domainOK = true;
+ }
+
+ if( domainOK ) {
+ recordCookie(cookie);
+
+ }
+ }
+
+
+ /**
+ * Record the cookie in the in-memory container of cookies. If there
+ * is already a cookie which is in the exact same domain with the
+ * exact same
+ */
+ public void recordCookie(HttpCookie cookie) {
+ if (!checkIfCookieOK(cookie)) {
+ return;
+ }
+ synchronized (cookieJar) {
+
+ String domain = cookie.getDomain().toLowerCase();
+
+ Vector cookieList = (Vector)cookieJar.get(domain);
+ if (cookieList == null) {
+ cookieList = new Vector();
+ }
+
+ addOrReplaceCookie(cookieList, cookie);
+ cookieJar.put(domain, cookieList);
+
+ }
+
+ }
+
+ public boolean checkIfCookieOK(HttpCookie cookie) {
+ return true;
+ }
+
+ /**
+ * Scans the vector of cookies looking for an exact match with the
+ * given cookie. Replaces it if there is one, otherwise adds
+ * one at the end. The vector is presumed to have cookies which all
+ * have the same domain, so the domain of the cookie is not checked.
+ * <p>
+ * <p>
+ * If this is called, it is assumed that the cookie jar is exclusively
+ * held by the current thread.
+ *
+ */
+ private void addOrReplaceCookie(Vector cookies,
+ HttpCookie cookie) {
+ int numCookies = cookies.size();
+
+ String path = cookie.getPath();
+ String name = cookie.getName();
+ HttpCookie replaced = null;
+ int replacedIndex = -1;
+
+ for (int i = 0; i < numCookies; i++) {
+ HttpCookie existingCookie = (HttpCookie)cookies.elementAt(i);
+
+ String existingPath = existingCookie.getPath();
+ if (path.equals(existingPath)) {
+ String existingName = existingCookie.getName();
+ if (name.equals(existingName)) {
+ // need to replace this one!
+ replaced = existingCookie;
+ replacedIndex = i;
+ break;
+ }
+ }
+ }
+
+
+ // Do the replace - if cookie has already expired, remove
+ // the replaced cookie.
+ if (replaced != null) {
+ if (cookie.isSaveableInMemory()) {
+ cookies.setElementAt(cookie, replacedIndex);
+ //System.out.println("REPLACED existing cookie with " + cookie);
+ } else {
+ cookies.removeElementAt(replacedIndex);
+ //System.out.println("Removed cookie b/c or expr " + cookie);
+ }
+
+ } else { // only save the cookie in memory if it is non persistent
+ // or not expired.
+ if (cookie.isSaveableInMemory()) {
+ cookies.addElement(cookie);
+ //System.out.println("RECORDED new cookie " + cookie);
+ }
+
+ }
+
+ }
+
+ public String applyRelevantCookies(URL url ) {
+
+ try {
+ /*
+ Properties properties = new Properties();
+ FileInputStream fin = new FileInputStream("ServerAutoRun.properties");
+ properties.load(fin);
+ // check current accept policy instead enableCookies
+ String cookiepolicy = properties.getProperty("cookie.acceptpolicy");
+ if (cookiepolicy == null || cookiepolicy.equals("none")) {
+ return null;
+ }
+
+ */
+
+ return applyCookiesForHost(url);
+
+ }
+ catch ( Exception e )
+ {
+ System.out.println("Exception : " +e );
+ return null;
+ }
+
+
+
+
+ }
+
+
+ /**
+ * Host may be a FQDN, or a partial domain name starting with a dot.
+ * Adds any cookies which match the host and path to the
+ * cookie set on the URL connection.
+ */
+ private String applyCookiesForHost(URL url ){
+ String cookieString = null;
+ Vector cookieVector = getAllRelevantCookies(url);
+
+ if (cookieVector != null) {
+
+ for (Enumeration e = cookieVector.elements(); e.hasMoreElements();) {
+ HttpCookie cookie = (HttpCookie)e.nextElement();
+ if( cookieString == null ) {
+ cookieString = cookie.getNameValue();
+ } else {
+ cookieString = cookieString + "; " + cookie.getNameValue();
+ }
+ }
+
+ /*
+
+ if( cookieString != null ) {
+ httpConn.setRequestProperty("Cookie", cookieString);
+
+// System.out.println("Returned cookie string: " + cookieString + " for HOST = " + host);
+ }
+
+ */
+
+
+ }
+// System.out.println("Returned cookie string: " + cookieString + " for HOST = " + host);
+ return cookieString;
+
+ }
+
+ private Vector getAllRelevantCookies(URL url) {
+ String host = url.getHost();
+ Vector cookieVector = getSubsetRelevantCookies(host, url);
+
+ Vector tempVector;
+ int index;
+
+ while ((index = host.indexOf('.', 1)) >= 0) {
+ // trim off everything up to, and including the dot.
+ host = host.substring(index+1);
+
+ // add onto cookieVector
+ tempVector = getSubsetRelevantCookies(host,url);
+ if (tempVector != null ) {
+ for (Enumeration e = tempVector.elements(); e.hasMoreElements(); ) {
+ if (cookieVector == null) {
+ cookieVector = new Vector(2);
+ }
+
+ cookieVector.addElement(e.nextElement());
+
+ }
+ }
+ }
+ return cookieVector;
+ }
+
+ private Vector getSubsetRelevantCookies(String host, URL url) {
+
+ Vector cookieList = (Vector)cookieJar.get(host);
+
+// System.out.println("getRelevantCookies() .. for host, url " + host +", "+url);
+ Vector cookiePortList = (Vector)cookieJar.get(host+":"+((url.getPort() == -1) ? 80 : url.getPort()));
+ if (cookiePortList != null) {
+ if (cookieList == null) {
+ cookieList = new Vector(10);
+ }
+ Enumeration cookies = cookiePortList.elements();
+ while (cookies.hasMoreElements()) {
+ cookieList.addElement(cookies.nextElement());
+ }
+ }
+
+
+ if (cookieList == null) {
+ return null;
+ }
+
+ String path = url.getFile();
+// System.out.println(" path is " + path + "; protocol = " + url.getProtocol());
+
+
+ int queryInd = path.indexOf('?');
+ if (queryInd > 0) {
+ // strip off the part following the ?
+ path = path.substring(0, queryInd);
+ }
+
+ Enumeration cookies = cookieList.elements();
+ Vector cookiesToSend = new Vector(10);
+
+ while (cookies.hasMoreElements()) {
+ HttpCookie cookie = (HttpCookie)cookies.nextElement();
+
+ String cookiePath = cookie.getPath();
+
+ if (path.startsWith(cookiePath)) {
+ // larrylf: Actually, my documentation (from Netscape)
+ // says that /foo should
+ // match /foobar and /foo/bar. Yuck!!!
+
+ if (!cookie.hasExpired()) {
+ cookiesToSend.addElement(cookie);
+ }
+
+/*
+ We're keeping this piece of commented out code around just in
+ case we decide to put it back. the spec does specify the above,
+ but it is so disgusting!
+
+ int cookiePathLen = cookiePath.length();
+
+ // verify that /foo does not match /foobar by mistake
+ if ((path.length() == cookiePathLen)
+ || (path.length() > cookiePathLen &&
+ path.charAt(cookiePathLen) == '/')) {
+
+ // We have a matching cookie!
+
+ if (!cookie.hasExpired()) {
+ cookiesToSend.addElement(cookie);
+ }
+ }
+*/
+ }
+ }
+
+ // Now, sort the cookies in most to least specific order
+ // Yes, its the deaded bubblesort!! Wah Ha-ha-ha-ha....
+ // (it should be a small vector, so perf is not an issue...)
+ if( cookiesToSend.size() > 1 ) {
+ for( int i = 0; i < cookiesToSend.size()-1; i++ ) {
+ HttpCookie headC = (HttpCookie)cookiesToSend.elementAt(i);
+ String head = headC.getPath();
+ // This little excercise is a cheap way to get
+ // '/foo' to read more specfic then '/'
+ if( !head.endsWith("/") ) {
+ head = head + "/";
+ }
+ for( int j = i+1; j < cookiesToSend.size(); j++ ) {
+ HttpCookie scanC = (HttpCookie)cookiesToSend.elementAt(j);
+ String scan = scanC.getPath();
+ if( !scan.endsWith("/") ) {
+ scan = scan + "/";
+ }
+
+ int headCount = 0;
+ int index = -1;
+ while( (index=head.indexOf('/', index+1)) != -1 ) {
+ headCount++;
+ }
+ index = -1;
+
+ int scanCount = 0;
+ while( (index=scan.indexOf('/', index+1)) != -1 ) {
+ scanCount++;
+ }
+
+ if( scanCount > headCount ) {
+ cookiesToSend.setElementAt(headC, j);
+ cookiesToSend.setElementAt(scanC, i);
+ headC = scanC;
+ head = scan;
+ }
+ }
+ }
+ }
+
+
+ return cookiesToSend;
+
+ }
+
+ /*
+ * Writes cookies out to PrintWriter if they are persistent
+ * (i.e. have a expr date)
+ * and haven't expired. Will remove cookies that have expired as well
+ */
+ private void saveCookiesToStream(PrintWriter pw) {
+
+ Enumeration cookieLists = cookieJar.elements();
+
+ while (cookieLists.hasMoreElements()) {
+ Vector cookieList = (Vector)cookieLists.nextElement();
+
+ Enumeration cookies = cookieList.elements();
+
+ while (cookies.hasMoreElements()) {
+ HttpCookie cookie = (HttpCookie)cookies.nextElement();
+
+ if (cookie.getExpirationDate() != null) {
+ if (cookie.isSaveable()) {
+ pw.println(cookie);
+ } else { // the cookie must have expired,
+ //remove from Vector cookieList
+ cookieList.removeElement(cookie);
+ }
+
+ }
+ }
+ }
+ // Must print something to the printwriter in the case that
+ // the cookieJar has been cleared - otherwise the old cookie
+ // file will continue to exist.
+ pw.print("");
+ }
+/////////////////////////////////////////////////////////////
+ /* adds cookieList to the existing cookie jar*/
+ public void addToCookieJar(HttpCookie[] cookieList) {
+
+ if (cookieList != null) {
+ for (int i = 0; i < cookieList.length; i++) {
+
+ recordCookie(cookieList[i]);
+ }
+ }
+
+ }
+
+ /*adds one cookie to the Cookie Jar */
+ public void addToCookieJar(String cookieString, URL docURL) {
+ recordCookie(new HttpCookie(docURL, cookieString));
+ }
+
+ /* loads the cookies from the given filename */
+ public void loadCookieJarFromFile(String cookieFileName) {
+ try {
+ FileReader fr = new FileReader(cookieFileName);
+
+ BufferedReader in = new BufferedReader(fr);
+
+ try {
+ String cookieString;
+ while ((cookieString = in.readLine()) != null) {
+ HttpCookie cookie = new HttpCookie(cookieString);
+ // Record the cookie, without notification. We don't
+ // do a notification for cookies that are read at
+ // program start-up.
+ recordCookie(cookie);
+ }
+ } finally {
+ in.close();
+ }
+
+
+ } catch (IOException e) {
+ // do nothing; it's not an error not to have persistent cookies
+ }
+
+ }
+
+ /* saves the cookies to the given file specified by fname */
+ public void saveCookieJarToFile(String cookieFileName) {
+ try {
+ FileWriter fw = new FileWriter(cookieFileName);
+ PrintWriter pw = new PrintWriter(fw, false);
+
+ try {
+ saveCookiesToStream(pw);
+ } finally {
+ pw.close();
+ }
+
+ } catch (IOException e) {
+ // REMIND: I18N
+ System.err.println("Saving cookies failed " + e.getMessage());
+ }
+ }
+
+ /**
+ * Return an array with all of the cookies represented by this
+ * jar. This is useful when the bean is shutting down, and the client
+ * wants to make the cookie jar persist.
+ */
+ public HttpCookie[] getAllCookies() {
+
+ Vector result = new Vector();
+ Hashtable jar;
+ jar = (Hashtable) cookieJar.clone();
+
+ synchronized (jar) {
+
+ for (Enumeration e = jar.elements(); e.hasMoreElements() ;) {
+ Vector v = (Vector) e.nextElement();
+ for (int i = 0; i < v.size(); i++) {
+ HttpCookie hc = (HttpCookie) v.elementAt(i);
+ result.addElement(hc);
+
+ }
+
+ }
+ }
+
+ HttpCookie[] resultA = new HttpCookie[result.size()];
+ for (int i = 0; i < result.size(); i++) {
+ resultA[i] = (HttpCookie) result.elementAt(i);
+ }
+ return resultA;
+ }
+
+ /* Gets all cookies that applies for the URL */
+ public HttpCookie[] getCookiesForURL(URL url) {
+
+ Vector cookieVector = getAllRelevantCookies(url);
+
+ if (cookieVector == null) {
+ return null;
+ }
+
+ int i = 0;
+ HttpCookie[] cookieArr = new HttpCookie[cookieVector.size()];
+
+ for (Enumeration e = cookieVector.elements(); e.hasMoreElements(); ) {
+
+ cookieArr[i++] = (HttpCookie)e.nextElement();
+// System.out.println("cookieArr["+(i-1)+"] = " +cookieArr[i-1].toString());
+ }
+
+ return cookieArr;
+ }
+
+ /* this will set the property of enableCookies to isDisabled */
+ public void setCookieDisable(boolean isDisabled) {
+
+ // Pending visit back this again
+ try {
+ Properties properties = new Properties();
+ properties.load(new FileInputStream("ServerAutoRun.properties") );
+
+
+ properties.put("enableCookies", isDisabled ? "false" : "true");
+ properties.store(new FileOutputStream("ServerAutoRun.properties"),"comments");
+ }
+ catch ( Exception e )
+ {
+ System.out.println("Exception : " + e );
+ }
+ }
+
+ public void discardAllCookies() {
+ cookieJar.clear();
+
+ }
+
+ /*
+ * purges any expired cookies in the Cookie hashtable.
+ */
+ public void purgeExpiredCookies() {
+ Enumeration cookieLists = cookieJar.elements();
+
+ while (cookieLists.hasMoreElements()) {
+ Vector cookieList = (Vector)cookieLists.nextElement();
+
+ Enumeration cookies = cookieList.elements();
+
+ while (cookies.hasMoreElements()) {
+ HttpCookie cookie = (HttpCookie)cookies.nextElement();
+
+ if (cookie.hasExpired()) {
+ cookieList.removeElement(cookie);
+ }
+ }
+ }
+
+ }
+
+}
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CookieController.java
------------------------------------------------------------------------------
svn:executable = *
Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.test;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import org.apache.coyote.adapters.CoyoteServer;
+import org.apache.coyote.adapters.EchoAdapter;
+import org.apache.coyote.adapters.MapperAdapter;
+import org.apache.coyote.adapters.ProxyAdapter;
+import org.apache.coyote.adapters.SleepAdapter;
+import org.apache.coyote.adapters.StaticAdapter;
+import org.apache.coyote.client.AsyncHttp;
+import org.apache.coyote.client.AsyncHttpPool;
+import org.apache.coyote.client.BlockingHttp;
+import org.apache.coyote.http11.async.AsyncProtocolHandler;
+import org.apache.juli.JdkLoggerConfig;
+import org.apache.tomcat.lite.TomcatLite;
+import org.apache.tomcat.lite.TomcatLiteTest;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+public class CoyoteTestHelper {
+
+ public static boolean testWithNewConnector = true;
+ public static boolean testWithAsyncClient = true;
+
+ /**
+ * Get url using URLConnection.
+ */
+ public static ByteChunk getUrl(String path) throws IOException {
+
+ ByteChunk out = new ByteChunk();
+
+ if (!testWithAsyncClient) {
+ URL url = new URL(path);
+ URLConnection connection = url.openConnection();
+ connection.setReadTimeout(5000);
+ connection.connect();
+ InputStream is = connection.getInputStream();
+ BufferedInputStream bis = new BufferedInputStream(is);
+ byte[] buf = new byte[2048];
+ int rd = 0;
+ while((rd = bis.read(buf)) > 0) {
+ out.append(buf, 0, rd);
+ }
+ } else {
+ AsyncHttp aclient = AsyncHttpPool.getDefault().get();
+ BlockingHttp client = aclient.getBlockingHttp();
+ aclient.open(path);
+ client.readAll(out, 20000);
+ aclient.release(); // return connection to pool
+ }
+ return out;
+ }
+
+ private void dumpHead(AsyncHttp client) throws IOException {
+ ByteChunk buf = new ByteChunk();
+ AsyncHttp.serializeResponse(client.getResponse(), buf);
+ System.err.println("-------RESPONSE HEAD:" + buf);
+ }
+
+ static Map<Integer, CoyoteServer> servers = new HashMap();
+
+ /**
+ * Return a test suite which will run with a started coyote server with all
+ * the test servlets.
+k */
+ public static TestSuite coyoteSuite() {
+ return new TestSuite("Coyote") {
+ public void run(TestResult r) {
+
+ super.run(r);
+ }
+ };
+ }
+
+ /**
+ * Return a (singleton) test server. Use to avoid starting
+ * coyote on each test.
+ *
+ * @param port
+ * @return
+ * @throws ServletException
+ */
+ public static CoyoteServer getTestServer(int port) {
+ CoyoteServer server = getCachedServer(port);
+ if (!server.getStarted()) {
+ server.start();
+ }
+ return server;
+ }
+
+ private static CoyoteServer getCachedServer(int port) {
+ CoyoteServer server = servers.get(port);
+ if (server == null) {
+ try {
+ server = startServer(port, true);
+ } catch (ServletException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ servers.put(port, server);
+ }
+ return server;
+}
+
+ public static CoyoteServer getProxyServer(int port) {
+ CoyoteServer server = servers.get(port);
+ if (server == null) {
+ server = new CoyoteServer(port, new ProxyAdapter());
+ AsyncProtocolHandler proto = new AsyncProtocolHandler();
+ server.setConnector(proto);
+ server.start();
+ servers.put(port, server);
+
+ }
+ return server;
+ }
+
+ public static CoyoteServer startServer(int port, boolean daemon)
+ throws ServletException, IOException {
+ JdkLoggerConfig.loadCustom();
+ CoyoteServer server = initServerAdapters(port, daemon);
+
+ addConnector(port, daemon, server);
+
+ server.start();
+
+ return server;
+ }
+
+ private static void addConnector(int port, boolean daemon,
+ CoyoteServer server) {
+ server.setPort(port);
+ server.setDaemon(daemon);
+ if (testWithNewConnector) {
+ server.setAsyncConnector();
+ } else {
+ server.setNioConnector();
+ }
+ }
+
+ private static CoyoteServer initServerAdapters(int port, boolean daemon) throws ServletException, IOException {
+ CoyoteServer server = new CoyoteServer();
+ server.setPort(port);
+ server.setDaemon(daemon);
+
+ server.addAdapter("/hello",
+ new StaticAdapter().setData("Hello world"));
+
+ server.addAdapter("/2nd",
+ new StaticAdapter().setData("Hello world2"));
+
+ server.addAdapter("/sleep/1",
+ new SleepAdapter().sleep(1000).setData("sleep 1"));
+ server.addAdapter("/sleep/1c",
+ new SleepAdapter().sleep(1000).setData("sleep 1c").chunked());
+ server.addAdapter("/sleep/2",
+ new SleepAdapter().sleep(2000).setData("sleep 2"));
+ server.addAdapter("/sleep/10",
+ new SleepAdapter().sleep(10000).setData("sleep 10"));
+
+ server.addAdapter("/echo/*", new EchoAdapter());
+ server.addAdapter("/chunked/*",
+ new StaticAdapter().chunked());
+
+ server.addAdapter("/aaa/*",
+ new StaticAdapter());
+
+ // Add servlets
+ TomcatLite servlets = new TomcatLite(server);
+ TomcatLiteTest.initServlets(servlets);
+
+ server.addAdapter("/", servlets);
+ server.init();
+ return server;
+ }
+
+ public static CoyoteServer getWatchdog(String path) throws ServletException,
+ IOException {
+ if (path == null) {
+ path = System.getProperty("watchdog.home");
+ }
+ if (path == null) {
+ path = "../../watchdog";
+ }
+
+ File f = new File(path + "/build/webapps");
+ CoyoteServer server = new CoyoteServer();
+ server.setPort(8080);
+ server.setDaemon(true);
+ TomcatLite servlets = new TomcatLite(server);
+
+ servlets.init("webapps/ROOT", "/");
+
+ for (String s : new String[] {
+ "servlet-compat",
+ "servlet-tests",
+ "jsp-tests"} ) {
+ servlets.init(f.getCanonicalPath() + "/" + s,
+ "/" + s);
+ }
+ server.addAdapter("/", new MapperAdapter());
+ server.addAdapter("/", servlets);
+ server.init();
+ addConnector(8080, true, server);
+ servlets.init();
+ servlets.start();
+ server.start();
+ return server;
+ }
+
+
+ public static void main(String[] args) throws ServletException, IOException {
+ startServer(8902, false);
+ startServer(0, false);
+ getWatchdog(null);
+ //CoyoteServer proxyServer = getProxyServer(8901);
+ }
+}
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/CoyoteTestHelper.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,1196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+* @Author Costin, Ramesh.Mandava
+*/
+
+package org.apache.tomcat.test;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import com.sun.xml.internal.rngom.ast.builder.BuildException;
+
+
+// derived from Jsp
+
+public class GTest {
+
+ private static final String ZEROS = "00000000";
+ private static final int SHORTPADSIZE = 4;
+ private static final int BYTEPADSIZE = 2;
+
+ int failureCount = 0;
+ int passCount = 0;
+ Throwable lastError;
+ boolean hasFailed = false;
+
+ String prefix = "http";
+ String host = "localhost";
+ String localHost = null;
+ String localIP = null;
+ int port = 8080;
+ int debug = 0;
+
+ String description = "No description";
+
+ String request;
+ HashMap requestHeaders = new HashMap();
+ String content;
+
+ // true if task is nested
+ private boolean nested = false;
+
+ // Expected response
+ boolean magnitude = true;
+ boolean exactMatch = false;
+
+ // expect a response body
+ boolean expectResponseBody = true;
+
+ // Match the body against a golden file
+ String goldenFile;
+ // Match the body against a string
+ String responseMatch;
+ // the response should include the following headers
+ HashMap expectHeaders = new HashMap();
+
+ // Headers that should not be found in response
+ HashMap unexpectedHeaders = new HashMap();
+
+ // Match request line
+ String returnCode = "";
+ String returnCodeMsg = "";
+
+ // Actual response
+ String responseLine;
+ byte[] responseBody;
+ HashMap headers;
+
+
+ // For Report generation
+ StringBuffer resultOut = new StringBuffer();
+
+ boolean firstTask = false;
+ boolean lastTask = false;
+ String expectedString;
+ String actualString;
+
+ String testName;
+ String assertion;
+ String testStrategy;
+
+ // For Session Tracking
+ static Hashtable sessionHash;
+ static Hashtable cookieHash;
+
+ String testSession;
+ Vector cookieVector;
+ URL requestURL;
+ CookieController cookieController ;
+
+ /**
+ * Creates a new <code>GTest</code> instance.
+ *
+ */
+ public GTest() {
+ }
+
+ /**
+ * <code>setTestSession</code> adds a
+ * CookieController for the value of sessionName
+ *
+ * @param sessionName a <code>String</code> value
+ */
+ public void setTestSession( String sessionName ) {
+ testSession = sessionName;
+
+ if ( sessionHash == null ) {
+ sessionHash = new Hashtable();
+ } else if ( sessionHash.get( sessionName ) == null ) {
+ sessionHash.put ( sessionName, new CookieController() );
+ }
+ }
+
+ /**
+ * <code>setTestName</code> sets the current test name.
+ *
+ * @param tn current testname.
+ */
+ public void setTestName ( String tn ) {
+ testName = tn;
+ }
+
+ /**
+ * <code>setAssertion</code> sets the assertion text
+ * for the current test.
+ *
+ * @param assertion assertion text
+ */
+ public void setAssertion ( String assertion ) {
+ this.assertion = assertion;
+ }
+
+ /**
+ * <code>setTestStrategy</code> sets the test strategy
+ * for the current test.
+ *
+ * @param strategy test strategy text
+ */
+ public void setTestStrategy ( String strategy ) {
+ testStrategy = strategy;
+ }
+
+ /**
+ * <code>getTestName</code> returns the current
+ * test name.
+ *
+ * @return a <code>String</code> value
+ */
+ public String getTestName( ) {
+ return testName;
+ }
+
+ /**
+ * <code>getAssertion</code> returns the current
+ * assertion text.
+ *
+ * @return a <code>String</code> value
+ */
+ public String getAssertion( ) {
+ return assertion;
+ }
+
+ /**
+ * <code>getTestStrategy</code> returns the current
+ * test strategy test.
+ *
+ * @return a <code>String</code> value
+ */
+ public String getTestStrategy( ) {
+ return testStrategy;
+ }
+
+ /**
+ * <code>setFirstTask</code> denotes that current task
+ * being executed is the first task within the list.
+ *
+ * @param a <code>boolean</code> value
+ */
+ public void setFirstTask( boolean val ) {
+ firstTask = val;
+ }
+
+
+ /**
+ * <code>setLastTask</code> denotes that the current task
+ * being executed is the last task within the list.
+ *
+ * @param a <code>boolean</code> value
+ */
+ public void setLastTask ( boolean val ) {
+ lastTask = val;
+ }
+
+ /**
+ * <code>setPrefix</code> sets the protocol
+ * prefix. Defaults to "http"
+ *
+ * @param prefix Either http or https
+ */
+ public void setPrefix( String prefix ) {
+ this.prefix = prefix;
+ }
+
+ /**
+ * <code>setHost</code> sets hostname where
+ * the target server is running. Defaults to
+ * "localhost"
+ *
+ * @param h a <code>String</code> value
+ */
+ public void setHost( String h ) {
+ this.host = h;
+ }
+
+ /**
+ * <code>setPort</code> sets the port
+ * that the target server is listening on.
+ * Defaults to "8080"
+ *
+ * @param portS a <code>String</code> value
+ */
+ public void setPort( String portS ) {
+ this.port = Integer.valueOf( portS ).intValue();
+ }
+
+ /**
+ * <code>setExactMatch</code> determines if a
+ * byte-by-byte comparsion is made of the server's
+ * response and the test's goldenFile, or if
+ * a token comparison is made. By default, only
+ * a token comparison is made ("false").
+ *
+ * @param exact a <code>String</code> value
+ */
+ public void setExactMatch( String exact ) {
+ exactMatch = Boolean.valueOf( exact ).booleanValue();
+ }
+
+ /**
+ * <code>setContent</code> String value upon which
+ * the request header Content-Length is based upon.
+ *
+ * @param s a <code>String</code> value
+ */
+ public void setContent( String s ) {
+ this.content = s;
+ }
+
+ /**
+ * <code>setDebug</code> enables debug output.
+ * By default, this is disabled ( value of "0" ).
+ *
+ * @param debugS a <code>String</code> value
+ */
+ public void setDebug( String debugS ) {
+ debug = Integer.valueOf( debugS ).intValue();
+ }
+
+ /**
+ * <code>setMagnitude</code> Expected return
+ * value of the test execution.
+ * Defaults to "true"
+ *
+ * @param magnitudeS a <code>String</code> value
+ */
+ public void setMagnitude( String magnitudeS ) {
+ magnitude = Boolean.valueOf( magnitudeS ).booleanValue();
+ }
+
+ /**
+ * <code>setGoldenFile</code> Sets the goldenfile
+ * that will be used to validate the server's response.
+ *
+ * @param s fully qualified path and filename
+ */
+ public void setGoldenFile( String s ) {
+ this.goldenFile = s;
+ }
+
+ /**
+ * <code>setExpectResponseBody</code> sets a flag
+ * to indicate if a response body is expected from the
+ * server or not
+ *
+ * @param b a <code>boolean</code> value
+ */
+ public void setExpectResponseBody( boolean b ) {
+ this.expectResponseBody = b;
+ }
+
+ /**
+ * <code>setExpectHeaders</code> Configures GTest
+ * to look for the header passed in the server's
+ * response.
+ *
+ * @param s a <code>String</code> value in the
+ * format of <header-field>:<header-value>
+ */
+ public void setExpectHeaders( String s ) {
+ this.expectHeaders = new HashMap();
+ StringTokenizer tok = new StringTokenizer( s, "|" );
+ while ( tok.hasMoreElements() ) {
+ String header = (String) tok.nextElement();
+ setHeaderDetails( header, expectHeaders, false );
+ }
+ }
+
+ /**
+ * <code>setUnexpectedHeaders</code> Configures GTest
+ * to look for the header passed to validate that it
+ * doesn't exist in the server's response.
+ *
+ * @param s a <code>String</code> value in the
+ * format of <header-field>:<header-value>
+ */
+ public void setUnexpectedHeaders( String s ) {
+ this.unexpectedHeaders = new HashMap();
+ setHeaderDetails( s, unexpectedHeaders, false );
+ }
+
+ public void setNested( String s ) {
+ nested = Boolean.valueOf( s ).booleanValue();
+ }
+
+ /**
+ * <code>setResponseMatch</code> Match the
+ * passed value in the server's response.
+ *
+ * @param s a <code>String</code> value
+ */
+ public void setResponseMatch( String s ) {
+ this.responseMatch = s;
+ }
+
+ /**
+ * <code>setRequest</code> Sets the HTTP/HTTPS
+ * request to be sent to the target server
+ * Ex.
+ * GET /servlet_path/val HTTP/1.0
+ *
+ * @param s a <code>String</code> value in the form
+ * of METHOD PATH HTTP_VERSION
+ */
+ public void setRequest ( String s ) {
+ this.request = s;
+ }
+
+ /**
+ * <code>setReturnCode</code> Sets the expected
+ * return code from the server's response.
+ *
+ * @param code a valid HTTP response status code
+ */
+ public void setReturnCode( String code ) {
+ this.returnCode = code;
+ }
+
+ /**
+ * Describe <code>setReturnCodeMsg</code> Sets the expected
+ * return message to be found in the server's
+ * response.
+ *
+ * @param code a valid HTTP resonse status code
+ * @param message a <code>String</code> value
+ */
+ public void setReturnCodeMsg( String message ) {
+ this.returnCodeMsg = message;
+ }
+
+ /**
+ * <code>setRequestHeaders</code> Configures the request
+ * headers GTest should send to the target server.
+ *
+ * @param s a <code>String</code> value in for format
+ * of <field-name>:<field-value>
+ */
+ public void setRequestHeaders( String s ) {
+ requestHeaders = new HashMap();
+ StringTokenizer tok = new StringTokenizer( s, "|" );
+ while ( tok.hasMoreElements() ) {
+ String header = (String) tok.nextElement();
+ setHeaderDetails( header, requestHeaders, true );
+ }
+ }
+
+ // Inner tests are not used currently, can be reworked
+
+// /**
+// * Add a Task to this container
+// *
+// * @param Task to add
+// */
+// public void addTask(Task task) {
+// children.add(task);
+// }
+
+ /**
+ * <code>execute</code> Executes the test.
+ *
+ * @exception BuildException if an error occurs
+ */
+ public void execute() {
+
+ try {
+
+ if ( resultOut != null && !nested ) {
+ resultOut.append("\ntestName: " + testName);
+ resultOut.append("\nreq: " + request);
+ resultOut.append("\nassertion: " + assertion);
+ resultOut.append("\ntestStrategy: " + testStrategy);
+ }
+
+ SimpleHttpClient.dispatch(this);
+
+ hasFailed = !checkResponse( magnitude );
+
+
+// if ( !children.isEmpty() ) {
+// Iterator iter = children.iterator();
+// while (iter.hasNext()) {
+// Task task = (Task) iter.next();
+// task.perform();
+// }
+// }
+
+ if ( !hasFailed && !nested ) {
+ passCount++;
+ if ( resultOut != null ) {
+ resultOut.append( "<result>PASS</result>\n" );
+ }
+ System.out.println( " PASSED " + testName + "\n (" + request + ")" );
+ } else if ( hasFailed && !nested ){
+ failureCount++;
+ if ( resultOut != null ) {
+ resultOut.append( "<result>FAIL</result>\n" );
+ }
+ System.out.println( " FAILED " + testName + "\n (" + request + ")\n" +
+ resultOut.toString());
+ }
+
+ } catch ( Exception ex ) {
+ failureCount++;
+ System.out.println( " FAIL " + description + " (" + request + ")" );
+ lastError = ex;
+ ex.printStackTrace();
+ } finally {
+ if ( !nested ) {
+ hasFailed = false;
+ }
+ }
+ }
+
+ /**
+ * <code>checkResponse</code> Executes various response
+ * checking mechanisms against the server's response.
+ * Checks include:
+ * <ul>
+ * <li>expected headers
+ * <li>unexpected headers
+ * <li>return codes and messages in the Status-Line
+ * <li>response body comparison againt a goldenfile
+ * </ul>
+ *
+ * @param testCondition a <code>boolean</code> value
+ * @return a <code>boolean</code> value
+ * @exception Exception if an error occurs
+ */
+ private boolean checkResponse( boolean testCondition )
+ throws Exception {
+ boolean match = false;
+
+ if ( responseLine != null ) {
+ // If returnCode doesn't match
+ if ( responseLine.indexOf( "HTTP/1." ) > -1 ) {
+
+ if ( !returnCode.equals( "" ) ) {
+ boolean resCode = ( responseLine.indexOf( returnCode ) > -1 );
+ boolean resMsg = ( responseLine.indexOf( returnCodeMsg ) > -1 );
+
+ if ( returnCodeMsg.equals( "" ) ) {
+ match = resCode;
+ } else {
+ match = ( resCode && resMsg );
+ }
+
+ if ( match != testCondition ) {
+
+ if ( resultOut != null ) {
+ String expectedStatusCode = "<expectedStatusCode>" + returnCode + "</expectedReturnCode>\n";
+ String expectedReasonPhrase = "<expectedReasonPhrase>" + returnCodeMsg + "</expectedReasonPhrase>";
+ actualString = "<actualStatusLine>" + responseLine + "</actualStatusLine>\n";
+ resultOut.append( expectedStatusCode );
+ resultOut.append( expectedReasonPhrase );
+ resultOut.append( actualString );
+ }
+
+ return false;
+ }
+ }
+ } else {
+ resultOut.append("\n<failure>Wrong Http version: " + responseLine +
+ "</failure>");
+ return false;
+ }
+ } else {
+ resultOut.append("\n<failure>No response from server</failure>" );
+ return false;
+ }
+
+ /*
+ * Check for headers the test expects to be in the server's response
+ */
+
+ // Duplicate set of response headers
+ HashMap copiedHeaders = cloneHeaders( headers );
+
+ // used for error reporting
+ String currentHeaderField = null;
+ String currentHeaderValue = null;
+
+ if ( !expectHeaders.isEmpty() ) {
+ boolean found = false;
+ String expHeader = null;
+
+ if ( !headers.isEmpty() ) {
+ Iterator expectIterator = expectHeaders.keySet().iterator();
+ while ( expectIterator.hasNext() ) {
+ found = false;
+ String expFieldName = (String) expectIterator.next();
+ currentHeaderField = expFieldName;
+ ArrayList expectValues = (ArrayList) expectHeaders.get( expFieldName );
+ Iterator headersIterator = copiedHeaders.keySet().iterator();
+
+ while( headersIterator.hasNext() ) {
+ String headerFieldName = (String) headersIterator.next();
+ ArrayList headerValues = (ArrayList) copiedHeaders.get( headerFieldName );
+
+ // compare field names and values in an HTTP 1.x compliant fashion
+ if ( ( headerFieldName.equalsIgnoreCase( expFieldName ) ) ) {
+ int hSize = headerValues.size();
+ int eSize = expectValues.size();
+
+ // number of expected headers found in server response
+ int numberFound = 0;
+
+ for ( int i = 0; i < eSize; i++ ) {
+ currentHeaderValue = (String) expectValues.get( i );
+
+ /*
+ * Handle the Content-Type header appropriately
+ * based on the the test is configured to look for.
+ */
+ if ( currentHeaderField.equalsIgnoreCase( "content-type" ) ) {
+ String resVal = (String) headerValues.get( 0 );
+ if ( currentHeaderValue.indexOf( ';' ) > -1 ) {
+ if ( currentHeaderValue.equals( resVal ) ) {
+ numberFound++;
+ headerValues.remove( 0 );
+ }
+ } else if ( resVal.indexOf( currentHeaderValue ) > -1 ) {
+ numberFound++;
+ headerValues.remove( 0 );
+ }
+ } else if ( currentHeaderField.equalsIgnoreCase( "location" ) ) {
+ String resVal = (String) headerValues.get( 0 );
+ int idx = currentHeaderValue.indexOf( ":80/" );
+ if ( idx > -1 ) {
+ String tempValue = currentHeaderValue.substring( 0, idx ) +
+ currentHeaderValue.substring( idx + 3 );
+ if ( currentHeaderValue.equals( resVal ) ||
+ tempValue.equals( resVal ) ) {
+ numberFound++;
+ headerValues.remove( 0 );
+ }
+ } else {
+ if ( currentHeaderValue.equals( resVal ) ) {
+ numberFound++;
+ headerValues.remove( 0 );
+ }
+ }
+ } else if ( headerValues.contains( currentHeaderValue ) ) {
+ numberFound++;
+ headerValues.remove( headerValues.indexOf( currentHeaderValue ) );
+ }
+ }
+ if ( numberFound == eSize ) {
+ found = true;
+ }
+ }
+ }
+ if ( !found ) {
+ /*
+ * Expected headers not found in server response.
+ * Break the processing loop.
+ */
+ break;
+ }
+ }
+ }
+
+ if ( !found ) {
+ StringBuffer actualBuffer = new StringBuffer( 128 );
+ if ( resultOut != null ) {
+ expectedString = "<expectedHeaderNotFound>" + currentHeaderField + ": " + currentHeaderValue + "</expectedHeader>\n";
+ }
+ if ( !headers.isEmpty() ) {
+ Iterator iter = headers.keySet().iterator();
+ while ( iter.hasNext() ) {
+ String headerName = (String) iter.next();
+ ArrayList vals = (ArrayList) headers.get( headerName );
+ String[] val = (String[]) vals.toArray( new String[ vals.size() ] );
+ for ( int i = 0; i < val.length; i++ ) {
+ if ( resultOut != null ) {
+ actualBuffer.append( "<actualHeader>" + headerName + ": " + val[ i ] + "</actualHeader>\n" );
+ }
+ }
+ }
+ if ( resultOut != null ) {
+ resultOut.append( expectedString );
+ resultOut.append( actualBuffer.toString() );
+ }
+ }
+ return false;
+ }
+ }
+
+ /*
+ * Check to see if we're looking for unexpected headers.
+ * If we are, compare the values in the unexectedHeaders
+ * ArrayList against the headers from the server response.
+ * if the unexpected header is found, then return false.
+ */
+
+ if ( !unexpectedHeaders.isEmpty() ) {
+ boolean found = false;
+ String unExpHeader = null;
+ // Check if we got any unexpected headers
+
+ if ( !copiedHeaders.isEmpty() ) {
+ Iterator unexpectedIterator = unexpectedHeaders.keySet().iterator();
+ while ( unexpectedIterator.hasNext() ) {
+ found = false;
+ String unexpectedFieldName = (String) unexpectedIterator.next();
+ ArrayList unexpectedValues = (ArrayList) unexpectedHeaders.get( unexpectedFieldName );
+ Iterator headersIterator = copiedHeaders.keySet().iterator();
+
+ while ( headersIterator.hasNext() ) {
+ String headerFieldName = (String) headersIterator.next();
+ ArrayList headerValues = (ArrayList) copiedHeaders.get( headerFieldName );
+
+ // compare field names and values in an HTTP 1.x compliant fashion
+ if ( ( headerFieldName.equalsIgnoreCase( unexpectedFieldName ) ) ) {
+ int hSize = headerValues.size();
+ int eSize = unexpectedValues.size();
+ int numberFound = 0;
+ for ( int i = 0; i < eSize; i++ ) {
+ if ( headerValues.contains( unexpectedValues.get( i ) ) ) {
+ numberFound++;
+ headerValues.remove( headerValues.indexOf( headerFieldName ) );
+ }
+ }
+ if ( numberFound == eSize ) {
+ found = true;
+ }
+ }
+ }
+ if ( !found ) {
+ /*
+ * Expected headers not found in server response.
+ * Break the processing loop.
+ */
+ break;
+ }
+ }
+ }
+
+ if ( found ) {
+ resultOut.append( "\n Unexpected header received from server: " + unExpHeader );
+ return false;
+ }
+ }
+
+
+
+ if ( responseMatch != null ) {
+ // check if we got the string we wanted
+ if ( expectResponseBody && responseBody == null ) {
+ resultOut.append( "\n ERROR: got no response, expecting " + responseMatch );
+ return false;
+ }
+ String responseBodyString = new String( responseBody );
+ if ( responseBodyString.indexOf( responseMatch ) < 0 ) {
+ resultOut.append( "\n ERROR: expecting match on " + responseMatch );
+ resultOut.append( "\n Received: \n" + responseBodyString );
+ }
+ }
+
+ if ( !expectResponseBody && responseBody != null ) {
+ resultOut.append("Received a response body from the server where none was expected" );
+ return false;
+ }
+
+ // compare the body
+ if ( goldenFile == null )
+ return true;
+
+ // Get the expected result from the "golden" file.
+ byte[] expResult = getExpectedResult();
+ String expResultS = (expResult == null) ? "" : new String(expResult);
+ // Compare the results and set the status
+ boolean cmp = true;
+
+ if ( exactMatch ) {
+ cmp = compare( responseBody, expResult );
+ } else {
+ cmp = compareWeak( responseBody, expResult );
+ }
+
+ if ( cmp != testCondition ) {
+
+ if ( resultOut != null ) {
+ expectedString = "<expectedBody>" + new String(expResult) + "</expectedBody>\n";
+ actualString = "<actualBody>" +
+ (responseBody != null ? new String(responseBody) : "null" ) +
+ "</actualBody>\n";
+ resultOut.append( expectedString );
+ resultOut.append( actualString );
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Replaces any |client.ip| and |client.host| parameter marks
+ * with the host and IP values of the host upon which Watchdog
+ * is running.
+ *
+ * @param request An HTTP request.
+ */
+ String replaceMarkers( String req, Socket socket ) {
+
+ final String CLIENT_IP = "client.ip";
+ final String CLIENT_HOME = "client.host";
+
+ if (localIP == null || localHost == null) {
+ InetAddress addr = socket.getLocalAddress();
+ localHost = addr.getHostName();
+ localIP = addr.getHostAddress();
+ }
+
+ if (req.indexOf('|') > -1) {
+ StringTokenizer tok = new StringTokenizer( request, "|" );
+ StringBuffer sb = new StringBuffer( 50 );
+
+ while ( tok.hasMoreElements() ) {
+ String token = tok.nextToken();
+ if ( token.equals( CLIENT_IP ) ) {
+ sb.append( localIP );
+ } else if ( token.equals( CLIENT_HOME ) ) {
+ sb.append( localHost );
+ } else {
+ sb.append( token );
+ }
+ }
+ return sb.toString();
+ } else {
+ return req;
+ }
+ }
+
+
+
+ /**
+ * <code>getExpectedResult</code> returns a byte array
+ * containing the content of the configured goldenfile
+ *
+ * @return goldenfile as a byte[]
+ * @exception IOException if an error occurs
+ */
+ private byte[] getExpectedResult()
+ throws IOException {
+ byte[] expResult = { 'N','O',' ',
+ 'G','O','L','D','E','N','F','I','L','E',' ',
+ 'F','O','U','N','D' };
+
+ try {
+ InputStream in = new BufferedInputStream(
+ new FileInputStream( goldenFile ) );
+ return readBody ( in );
+ } catch ( Exception ex ) {
+ System.out.println( "Golden file not found: " + goldenFile );
+ return expResult;
+ }
+ }
+
+ /**
+ * <code>compare</code> compares the two byte arrays passed
+ * in to verify that the lengths of the arrays are equal, and
+ * that the content of the two arrays, byte for byte are equal.
+ *
+ * @param fromServer a <code>byte[]</code> value
+ * @param fromGoldenFile a <code>byte[]</code> value
+ * @return <code>boolean</code> true if equal, otherwise false
+ */
+ private boolean compare( byte[] fromServer, byte[] fromGoldenFile ) {
+ if ( fromServer == null || fromGoldenFile == null ) {
+ return false;
+ }
+
+ /*
+ * Check to see that the respose and golden file lengths
+ * are equal. If they are not, dump the hex and don't
+ * bother comparing the bytes. If they are equal,
+ * iterate through the byte arrays and compare each byte.
+ * If the bytes don't match, dump the hex representation
+ * of the server response and the goldenfile and return
+ * false.
+ */
+ if ( fromServer.length != fromGoldenFile.length ) {
+ StringBuffer sb = new StringBuffer( 50 );
+ sb.append( " Response and golden files lengths do not match!\n" );
+ sb.append( " Server response length: " );
+ sb.append( fromServer.length );
+ sb.append( "\n Goldenfile length: " );
+ sb.append( fromGoldenFile.length );
+ resultOut.append( sb.toString() );
+ sb = null;
+ // dump the hex representation of the byte arrays
+ dumpHex( fromServer, fromGoldenFile );
+
+ return false;
+ } else {
+
+ int i = 0;
+ int j = 0;
+
+ while ( ( i < fromServer.length ) && ( j < fromGoldenFile.length ) ) {
+ if ( fromServer[ i ] != fromGoldenFile[ j ] ) {
+ resultOut.append( "\n Error at position " + ( i + 1 ) );
+ // dump the hex representation of the byte arrays
+ dumpHex( fromServer, fromGoldenFile );
+
+ return false;
+ }
+
+ i++;
+ j++;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * <code>compareWeak</code> creates new Strings from the passed arrays
+ * and then uses a StringTokenizer to compare non-whitespace tokens.
+ *
+ * @param fromServer a <code>byte[]</code> value
+ * @param fromGoldenFile a <code>byte[]</code> value
+ * @return a <code>boolean</code> value
+ */
+ private boolean compareWeak( byte[] fromServer, byte[] fromGoldenFile ) {
+ if ( fromServer == null || fromGoldenFile == null ) {
+ return false;
+ }
+
+ boolean status = true;
+
+ String server = new String( fromServer );
+ String golden = new String( fromGoldenFile );
+
+ StringTokenizer st1 = new StringTokenizer( server );
+
+ StringTokenizer st2 = new StringTokenizer( golden );
+
+ while ( st1.hasMoreTokens() && st2.hasMoreTokens() ) {
+ String tok1 = st1.nextToken();
+ String tok2 = st2.nextToken();
+
+ if ( !tok1.equals( tok2 ) ) {
+ resultOut.append( "\t FAIL*** : Rtok1 = " + tok1
+ + ", Etok2 = " + tok2 );
+ status = false;
+ }
+ }
+
+ if ( st1.hasMoreTokens() || st2.hasMoreTokens() ) {
+ status = false;
+ }
+
+ if ( !status ) {
+ StringBuffer sb = new StringBuffer( 255 );
+ sb.append( "ERROR: Server's response and configured goldenfile do not match!\n" );
+ sb.append( "Response received from server:\n" );
+ sb.append( "---------------------------------------------------------\n" );
+ sb.append( server );
+ sb.append( "\nContent of Goldenfile:\n" );
+ sb.append( "---------------------------------------------------------\n" );
+ sb.append( golden );
+ sb.append( "\n" );
+ resultOut.append( sb.toString() );
+ }
+ return status;
+ }
+
+ /**
+ * <code>readBody</code> reads the body of the response
+ * from the InputStream.
+ *
+ * @param input an <code>InputStream</code>
+ * @return a <code>byte[]</code> representation of the response
+ */
+ private byte[] readBody( InputStream input ) {
+ StringBuffer sb = new StringBuffer( 255 );
+ while ( true ) {
+ try {
+ int ch = input.read();
+
+ if ( ch < 0 ) {
+ if ( sb.length() == 0 ) {
+ return ( null );
+ } else {
+ break;
+ }
+ }
+ sb.append( ( char ) ch );
+
+ } catch ( IOException ex ) {
+ return null;
+ }
+ }
+ return sb.toString().getBytes();
+ }
+
+ /**
+ * <code>setHeaderDetails</code> Wrapper method for parseHeader.
+ * Allows easy addition of headers to the specified
+ * HashMap
+ *
+ * @param line a <code>String</code> value
+ * @param headerMap a <code>HashMap</code> value
+ * @param isRequest a <code>boolean</code> indicating if the passed Header
+ * HashMap is for request headers
+ */
+ void setHeaderDetails( String line, HashMap headerHash, boolean isRequest ) {
+ StringTokenizer stk = new StringTokenizer( line, "##" );
+
+ while ( stk.hasMoreElements( ) ) {
+ String presentHeader = stk.nextToken();
+ parseHeader( presentHeader, headerHash, isRequest );
+ }
+ }
+
+ /**
+ * <code>parseHeader</code> parses input headers in format of "key:value"
+ * The parsed header field-name will be used as a key in the passed
+ * HashMap object, and the values found will be stored in an ArrayList
+ * associated with the field-name key.
+ *
+ * @param line String representation of an HTTP header line.
+ * @param headers a<code>HashMap</code> to store key/value header objects.
+ * @param isRequest set to true if the headers being processed are
+ * requestHeaders.
+ */
+ void parseHeader( String line, HashMap headerMap, boolean isRequest ) {
+ // Parse the header name and value
+ int colon = line.indexOf( ":" );
+
+ if ( colon < 0 ) {
+ resultOut.append( "\n ERROR: Header is in incorrect format: " + line );
+ return ;
+ }
+
+ String name = line.substring( 0, colon ).trim();
+ String value = line.substring( colon + 1 ).trim();
+
+ if ( ( cookieVector != null ) && ( name.equalsIgnoreCase( "Set-Cookie" ) ) ) {
+ cookieVector.addElement( value );
+ /*
+ if ( ( value.indexOf("JSESSIONID") > -1 ) || (value.indexOf("jsessionid") > -1 ) )
+ {
+ String sessionId= value.substring( value.indexOf("=")+1);
+ if ( testSession != null )
+ {
+ sessionHash.put( testSession, sessionId );
+ }
+ System.out.println("Got Session-ID : " + sessionId );
+ }
+ */
+ }
+
+ // System.out.println("HEADER: " +name + " " + value);
+
+ ArrayList values = (ArrayList) headerMap.get( name );
+ if ( values == null ) {
+ values = new ArrayList();
+ }
+ // HACK
+ if ( value.indexOf( ',' ) > -1 && !isRequest && !name.equalsIgnoreCase( "Date" ) ) {
+ StringTokenizer st = new StringTokenizer( value, "," );
+ while ( st.hasMoreElements() ) {
+ values.add( st.nextToken() );
+ }
+ } else {
+ values.add( value );
+ }
+
+ headerMap.put( name, values );
+ }
+
+ /**
+ * <code>dumpHex</code> helper method to dump formatted
+ * hex output of the server response and the goldenfile.
+ *
+ * @param serverResponse a <code>byte[]</code> value
+ * @param goldenFile a <code>byte[]</code> value
+ */
+ private void dumpHex( byte[] serverResponse, byte[] goldenFile ) {
+ StringBuffer outBuf = new StringBuffer( ( serverResponse.length + goldenFile.length ) * 2 );
+
+ String fromServerString = getHexValue( serverResponse, 0, serverResponse.length );
+ String fromGoldenFileString = getHexValue( goldenFile, 0, goldenFile.length );
+
+ outBuf.append( " Hex dump of server response and goldenfile below.\n\n### RESPONSE FROM SERVER ###\n" );
+ outBuf.append( "----------------------------\n" );
+ outBuf.append( fromServerString );
+ outBuf.append( "\n\n### GOLDEN FILE ###\n" );
+ outBuf.append( "-------------------\n" );
+ outBuf.append( fromGoldenFileString );
+ outBuf.append( "\n\n### END OF DUMP ###\n" );
+
+ resultOut.append( outBuf.toString() );
+
+ }
+
+ /**
+ * <code>getHexValue</code> displays a formatted hex
+ * representation of the passed byte array. It also
+ * allows for only a specified offset and length of
+ * a particular array to be returned.
+ *
+ * @param bytes <code>byte[]</code> array to process.
+ * @param pos <code>int</code> specifies offset to begin processing.
+ * @param len <code>int</code> specifies the number of bytes to process.
+ * @return <code>String</code> formatted hex representation of processed
+ * array.
+ */
+ private String getHexValue( byte[] bytes, int pos, int len ) {
+ StringBuffer outBuf = new StringBuffer( bytes.length * 2 );
+ int bytesPerLine = 36;
+ int cnt = 1;
+ int groups = 4;
+ int curPos = pos;
+ int linePos = 1;
+ boolean displayOffset = true;
+
+ while ( len-- > 0 ) {
+ if ( displayOffset ) {
+
+ outBuf.append( "\n" + paddedHexString( pos, SHORTPADSIZE,
+ true ) + ": " );
+ displayOffset = false;
+ }
+
+ outBuf.append(
+ paddedHexString( ( int ) bytes[ pos ], BYTEPADSIZE, false ) );
+ linePos += 2; // Byte is padded to 2 characters
+
+ if ( ( cnt % 4 ) == 0 ) {
+ outBuf.append( " " );
+ linePos++;
+ }
+
+ // Now display the characters that are printable
+ if ( ( cnt % ( groups * 4 ) ) == 0 ) {
+ outBuf.append( " " );
+
+ while ( curPos <= pos ) {
+ if ( !Character.isWhitespace( ( char ) bytes[ curPos ] ) ) {
+ outBuf.append( ( char ) bytes[ curPos ] );
+ } else {
+ outBuf.append( "." );
+ }
+
+ curPos++;
+ }
+
+ curPos = pos + 1;
+ linePos = 1;
+ displayOffset = true;
+ }
+
+ cnt++;
+ pos++;
+ }
+
+ // pad out the line with spaces
+ while ( linePos++ <= bytesPerLine ) {
+ outBuf.append( " " );
+ }
+
+ outBuf.append( " " );
+ // Now display the printable characters for the trailing bytes
+ while ( curPos < pos ) {
+ if ( !Character.isWhitespace( ( char ) bytes[ curPos ] ) ) {
+ outBuf.append( ( char ) bytes[ curPos ] );
+ } else {
+ outBuf.append( "." );
+ }
+
+ curPos++;
+ }
+
+ return outBuf.toString();
+ }
+
+ /**
+ * <code>paddedHexString</code> pads the passed value
+ * based on the specified wordsize and the value of the
+ * prefixFlag.
+ *
+ * @param val an <code>int</code> value
+ * @param wordsize an <code>int</code> value
+ * @param prefixFlag a <code>boolean</code> value
+ * @return a <code>String</code> value
+ */
+ private String paddedHexString( int val, int wordsize,
+ boolean prefixFlag ) {
+
+ String prefix = prefixFlag ? "0x" : "" ;
+ String hexVal = Integer.toHexString( val );
+
+ if ( hexVal.length() > wordsize )
+ hexVal = hexVal.substring( hexVal.length() - wordsize );
+
+ return ( prefix + ( wordsize > hexVal.length() ?
+ ZEROS.substring( 0, wordsize - hexVal.length() ) : "" ) + hexVal );
+ }
+
+ /**
+ * <code>cloneHeaders</code> returns a "cloned"
+ * HashMap of the map passed in.
+ *
+ * @param map a <code>HashMap</code> value
+ * @return a <code>HashMap</code> value
+ */
+ private HashMap cloneHeaders( HashMap map ) {
+ HashMap dupMap = new HashMap();
+ Iterator iter = map.keySet().iterator();
+
+ while ( iter.hasNext() ) {
+ String key = new String( (String) iter.next() );
+ ArrayList origValues = (ArrayList) map.get( key );
+ ArrayList dupValues = new ArrayList();
+
+ String[] dupVal = (String[]) origValues.toArray( new String[ origValues.size() ] );
+ for ( int i = 0; i < dupVal.length; i++ ) {
+ dupValues.add( new String( dupVal[ i ] ) );
+ }
+
+ dupMap.put( key, dupValues );
+ }
+ return dupMap;
+ }
+
+}
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/GTest.java
------------------------------------------------------------------------------
svn:executable = *
Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tomcat.test;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Date;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/**
+ * An object which represents an HTTP cookie. Can be constructed by
+ * parsing a string from the set-cookie: header.
+ *
+ * Syntax: Set-Cookie: NAME=VALUE; expires=DATE;
+ * path=PATH; domain=DOMAIN_NAME; secure
+ *
+ * All but the first field are optional.
+ *
+ * @author Ramesh.Mandava
+ */
+
+public class HttpCookie {
+ private Date expirationDate = null;
+ private String nameAndValue;
+ private String path;
+ private String domain;
+ private boolean isSecure = false;
+ private static boolean defaultSet = true;
+ private static long defExprTime = 100;
+
+ public HttpCookie(String cookieString) {
+ /*
+ System.out.println("Calling default expiration :");
+ getDefaultExpiration();
+ */
+ parseCookieString(cookieString);
+ }
+
+ //
+ // Constructor for use by the bean
+ //
+ public HttpCookie(Date expirationDate,
+ String nameAndValue,
+ String path,
+ String domain,
+ boolean isSecure) {
+ this.expirationDate = expirationDate;
+ this.nameAndValue = nameAndValue;
+ this.path = path;
+ this.domain = domain;
+ this.isSecure = isSecure;
+ }
+
+ public HttpCookie(URL url, String cookieString) {
+ parseCookieString(cookieString);
+ applyDefaults(url);
+ }
+
+ /**
+ * Fills in default values for domain, path, etc. from the URL
+ * after creation of the cookie.
+ */
+ private void applyDefaults(URL url) {
+ if (domain == null) {
+ domain = url.getHost()+":"+((url.getPort() == -1) ? 80 : url.getPort());
+ }
+
+ if (path == null) {
+ path = url.getFile();
+
+ // larrylf: The documentation for cookies say that the path is
+ // by default, the path of the document, not the filename of the
+ // document. This could be read as not including that document
+ // name itself, just its path (this is how NetScape intrprets it)
+ // so amputate the document name!
+ int last = path.lastIndexOf("/");
+ if( last > -1 ) {
+ path = path.substring(0, last);
+ }
+ }
+ }
+
+
+ /**
+ * Parse the given string into its individual components, recording them
+ * in the member variables of this object.
+ */
+ private void parseCookieString(String cookieString) {
+ StringTokenizer tokens = new StringTokenizer(cookieString, ";");
+
+ if (!tokens.hasMoreTokens()) {
+ // REMIND: make this robust against parse errors
+ nameAndValue="=";
+ return;
+ }
+
+ nameAndValue = tokens.nextToken().trim();
+
+ while (tokens.hasMoreTokens()) {
+ String token = tokens.nextToken().trim();
+
+ if (token.equalsIgnoreCase("secure")) {
+ isSecure = true;
+ } else {
+ int equIndex = token.indexOf("=");
+
+ if (equIndex < 0) {
+ continue;
+ // REMIND: malformed cookie
+ }
+
+ String attr = token.substring(0, equIndex);
+ String val = token.substring(equIndex+1);
+
+ if (attr.equalsIgnoreCase("path")) {
+ path = val;
+ } else if (attr.equalsIgnoreCase("domain")) {
+ if( val.indexOf(".") == 0 ) {
+ // spec seems to allow for setting the domain in
+ // the form 'domain=.eng.sun.com'. We want to
+ // trim off the leading '.' so we can allow for
+ // both leading dot and non leading dot forms
+ // without duplicate storage.
+ domain = val.substring(1);
+ } else {
+ domain = val;
+ }
+ } else if (attr.equalsIgnoreCase("expires")) {
+ expirationDate = parseExpireDate(val);
+ } else {
+ // unknown attribute -- do nothing
+ }
+ }
+ }
+
+ // commented the following out, b/c ok to have no expirationDate
+ // that means that the cookie should last only for that particular
+ // session.
+ // if (expirationDate == null) {
+ // expirationDate = getDefaultExpiration();
+ // }
+ }
+
+ /* Returns the default expiration, which is the current time + default
+ expiration as specified in the properties file.
+ This uses reflection to get at the properties file, since Globals is
+ not in the utils/ directory
+ */
+ private Date getDefaultExpiration() {
+ if (defaultSet == false) {
+ Properties props = new Properties();
+
+ try {
+ FileInputStream fin = new FileInputStream("ServerAutoRun.properties");
+ props.load( fin );
+
+ System.out.println("Got properties from ServerAutoRun.properties");
+ props.list(System.out);
+
+ } catch (IOException ex) {
+ System.out.println("HttpCookie getDefaultExpiration : ServerAutoRun.properties not found!" + ex);
+ }
+
+ // defExprTime = props.getProperty("cookies.default.expiration");
+ defExprTime = Long.parseLong( props.getProperty("cookies.default.expiration") );
+
+ }
+ defaultSet = true;
+
+ return (new Date(System.currentTimeMillis() + defExprTime));
+
+ }
+
+ //======================================================================
+ //
+ // Accessor functions
+ //
+
+
+
+ public String getNameValue() {
+ return nameAndValue;
+ }
+
+ /**
+ * Returns just the name part of the cookie
+ */
+ public String getName() {
+
+ // it probably can't have null value, but doesn't hurt much
+ // to check.
+ if (nameAndValue == null) {
+ return "=";
+ }
+ int index = nameAndValue.indexOf("=");
+ return (index < 0) ? "=" : nameAndValue.substring(0, index);
+ }
+
+
+ /**
+ * Returns the domain of the cookie as it was presented
+ */
+ public String getDomain() {
+ // REMIND: add port here if appropriate
+ return domain;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public Date getExpirationDate() {
+ return expirationDate;
+ }
+
+ public boolean hasExpired() {
+ if(expirationDate == null) {
+ return false;
+ }
+ return (expirationDate.getTime() <= System.currentTimeMillis());
+ }
+
+ /**
+ * Returns true if the cookie has an expiration date (meaning it's
+ * persistent), and if the date nas not expired;
+ */
+ public boolean isSaveable() {
+ return (expirationDate != null)
+ && (expirationDate.getTime() > System.currentTimeMillis());
+ }
+
+ public boolean isSaveableInMemory() {
+ return ((expirationDate == null) ||
+ (expirationDate != null && expirationDate.getTime() > System.currentTimeMillis()));
+ }
+
+ public boolean isSecure() {
+ return isSecure;
+ }
+
+ private Date parseExpireDate(String dateString) {
+ // format is wdy, DD-Mon-yyyy HH:mm:ss GMT
+ RfcDateParser parser = new RfcDateParser(dateString);
+ Date theDate = parser.getDate();
+ if (theDate == null) {
+ // Expire in some intelligent default time
+ theDate = getDefaultExpiration();
+ }
+ return theDate;
+ }
+
+ public String toString() {
+
+ String result = (nameAndValue == null) ? "=" : nameAndValue;
+ if (expirationDate != null) {
+ result += "; expires=" + expirationDate;
+ }
+
+ if (path != null) {
+ result += "; path=" + path;
+ }
+
+ if (domain != null) {
+ result += "; domain=" + domain;
+ }
+
+ if (isSecure) {
+ result += "; secure";
+ }
+
+ return result;
+ }
+}
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/HttpCookie.java
------------------------------------------------------------------------------
svn:executable = *
Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.test;
+
+import junit.framework.Test;
+
+public class LiteJspTests extends LiteServletTests {
+
+ public static Test suite() {
+ // The individual targets are dups - and bad ones,
+ // RequestWrapper are missing part of the URL
+ String base = "../../watchdog";
+ String goldenDir =
+ base + "/src/clients/org/apache/jcheck/jsp/client/";
+ String file = base + "/src/conf/jsp-gtest.xml";
+
+ return new LiteServletTests().getSuite(base,
+ file, goldenDir, testMatch,
+ "jsp-test", exclude);
+ }
+
+}
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteJspTests.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.test;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+
+public class LiteServletTests extends WatchdogClient {
+
+ static String testMatch =
+ null;
+ //"ServletToJSP";
+
+ static String[] exclude = null;
+ static String[] slow =
+ {
+ "SingleModelTest" // slow
+
+ };
+
+ protected void beforeSuite() {
+ // Start the server
+ try {
+ CoyoteTestHelper.getWatchdog(null);
+ } catch (ServletException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ protected void afterSuite(TestResult res) {
+ // no need to stop it - using daemon threads.
+ System.out.println("DONE");
+ }
+
+
+ public static Test suite() {
+ // The individual targets are dups - and bad ones,
+ // RequestWrapper are missing part of the URL
+ String base = "../../watchdog";
+ String goldenDir =
+ base + "/src/clients/org/apache/jcheck/servlet/client/";
+ String file = base + "/src/conf/servlet-gtest.xml";
+
+ return new LiteServletTests().getSuite(base,
+ file, goldenDir, testMatch,
+ "gtestservlet-test", exclude);
+ }
+
+}
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/LiteServletTests.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java?rev=667821&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java (added)
+++ tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java Sat Jun 14 08:44:34 2008
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.test;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * A parser for date strings commonly found in http and email headers that
+ * follow various RFC conventions. Given a date-string, the parser will
+ * attempt to parse it by trying matches with a set of patterns, returning
+ * null on failure, a Date object on success.
+ *
+ * @author Ramesh.Mandava
+ */
+public class RfcDateParser {
+
+ private boolean isGMT = false;
+
+ static final String[] standardFormats = {
+ "EEEE', 'dd-MMM-yy HH:mm:ss z", // RFC 850 (obsoleted by 1036)
+ "EEEE', 'dd-MMM-yy HH:mm:ss", // ditto but no tz. Happens too often
+ "EEE', 'dd-MMM-yyyy HH:mm:ss z", // RFC 822/1123
+ "EEE', 'dd MMM yyyy HH:mm:ss z", // REMIND what rfc? Apache/1.1
+ "EEEE', 'dd MMM yyyy HH:mm:ss z", // REMIND what rfc? Apache/1.1
+ "EEE', 'dd MMM yyyy hh:mm:ss z", // REMIND what rfc? Apache/1.1
+ "EEEE', 'dd MMM yyyy hh:mm:ss z", // REMIND what rfc? Apache/1.1
+ "EEE MMM dd HH:mm:ss z yyyy", // Date's string output format
+ "EEE MMM dd HH:mm:ss yyyy", // ANSI C asctime format()
+ "EEE', 'dd-MMM-yy HH:mm:ss", // No time zone 2 digit year RFC 1123
+ "EEE', 'dd-MMM-yyyy HH:mm:ss" // No time zone RFC 822/1123
+ };
+
+ /* because there are problems with JDK1.1.6/SimpleDateFormat with
+ * recognizing GMT, we have to create this workaround with the following
+ * hardcoded strings */
+ static final String[] gmtStandardFormats = {
+ "EEEE',' dd-MMM-yy HH:mm:ss 'GMT'", // RFC 850 (obsoleted by 1036)
+ "EEE',' dd-MMM-yyyy HH:mm:ss 'GMT'", // RFC 822/1123
+ "EEE',' dd MMM yyyy HH:mm:ss 'GMT'", // REMIND what rfc? Apache/1.1
+ "EEEE',' dd MMM yyyy HH:mm:ss 'GMT'", // REMIND what rfc? Apache/1.1
+ "EEE',' dd MMM yyyy hh:mm:ss 'GMT'", // REMIND what rfc? Apache/1.1
+ "EEEE',' dd MMM yyyy hh:mm:ss 'GMT'", // REMIND what rfc? Apache/1.1
+ "EEE MMM dd HH:mm:ss 'GMT' yyyy" // Date's string output format
+ };
+
+ String dateString;
+
+ public RfcDateParser(String dateString) {
+ this.dateString = dateString.trim();
+ if (this.dateString.indexOf("GMT") != -1) {
+ isGMT = true;
+ }
+ }
+
+ public Date getDate() {
+
+ int arrayLen = isGMT ? gmtStandardFormats.length : standardFormats.length;
+ for (int i = 0; i < arrayLen; i++) {
+ Date d = null;
+
+ if (isGMT) {
+ d = tryParsing(gmtStandardFormats[i]);
+ } else {
+ d = tryParsing(standardFormats[i]);
+ }
+ if (d != null) {
+ return d;
+ }
+
+ }
+
+ return null;
+ }
+
+ private Date tryParsing(String format) {
+
+ java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(format, Locale.US);
+ if (isGMT) {
+ df.setTimeZone(TimeZone.getTimeZone("GMT"));
+ }
+ try {
+ return df.parse(dateString);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+} /* class RfcDateParser */
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: tomcat/sandbox/tomcat-lite/test/org/apache/tomcat/test/RfcDateParser.java
------------------------------------------------------------------------------
svn:executable = *
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org