001: /*
002: * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: * 2. Redistributions in binary form must reproduce the above copyright notice,
010: * this list of conditions and the following disclaimer in the documentation
011: * and/or other materials provided with the distribution.
012: * 3. The end-user documentation included with the redistribution, if any, must
013: * include the following acknowledgment:
014: *
015: * "This product includes software developed by Gargoyle Software Inc.
016: * (http://www.GargoyleSoftware.com/)."
017: *
018: * Alternately, this acknowledgment may appear in the software itself, if
019: * and wherever such third-party acknowledgments normally appear.
020: * 4. The name "Gargoyle Software" must not be used to endorse or promote
021: * products derived from this software without prior written permission.
022: * For written permission, please contact info@GargoyleSoftware.com.
023: * 5. Products derived from this software may not be called "HtmlUnit", nor may
024: * "HtmlUnit" appear in their name, without prior written permission of
025: * Gargoyle Software Inc.
026: *
027: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
028: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
029: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
030: * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
031: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
032: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
033: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
036: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: */
038: package com.gargoylesoftware.htmlunit;
039:
040: import java.io.IOException;
041: import java.io.InputStream;
042: import java.net.URL;
043: import java.util.ArrayList;
044: import java.util.Collections;
045: import java.util.Date;
046: import java.util.HashMap;
047: import java.util.List;
048: import java.util.Map;
049:
050: import org.apache.commons.httpclient.Header;
051: import org.apache.commons.httpclient.util.DateUtil;
052: import org.apache.commons.lang.time.DateUtils;
053:
054: import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
055: import com.gargoylesoftware.htmlunit.html.HtmlPage;
056:
057: /**
058: * Tests for {@link Cache}.
059: *
060: * @version $Revision: 2132 $
061: * @author Marc Guillemot
062: */
063: public class CacheTest extends WebTestCase {
064:
065: /**
066: * Create an instance
067: * @param name The name of the test
068: */
069: public CacheTest(final String name) {
070: super (name);
071: }
072:
073: /**
074: * @throws Exception if the test fails
075: */
076: public void testIsDynamicContent() throws Exception {
077: final Cache cache = new Cache();
078: final Map headers = new HashMap();
079: final WebResponse response = new DummyWebResponse() {
080: public String getResponseHeaderValue(final String headerName) {
081: return (String) headers.get(headerName);
082: }
083: };
084:
085: assertTrue(cache.isDynamicContent(response));
086:
087: headers.put("Last-Modified", "Sun, 15 Jul 2007 20:46:27 GMT");
088: assertFalse(cache.isDynamicContent(response));
089:
090: headers.put("Last-Modified", DateUtil.formatDate(DateUtils
091: .addMinutes(new Date(), -5)));
092: assertTrue(cache.isDynamicContent(response));
093:
094: headers.put("Expires", DateUtil.formatDate(DateUtils
095: .addMinutes(new Date(), 5)));
096: assertTrue(cache.isDynamicContent(response));
097:
098: headers.put("Expires", DateUtil.formatDate(DateUtils.addHours(
099: new Date(), 1)));
100: assertFalse(cache.isDynamicContent(response));
101:
102: headers.remove("Last-Modified");
103: assertFalse(cache.isDynamicContent(response));
104: }
105:
106: /**
107: * @throws Exception if the test fails
108: */
109: public void testIsJavascript() throws Exception {
110: final Cache cache = new Cache();
111:
112: final String[] contentType = { "" };
113: final URL[] url = { URL_FIRST };
114: final WebResponse response = new DummyWebResponse() {
115: public String getContentType() {
116: return contentType[0];
117: }
118:
119: public URL getUrl() {
120: return url[0];
121: }
122: };
123:
124: assertFalse(cache.isJavaScript(response));
125:
126: contentType[0] = "text/javascript";
127: assertTrue(cache.isJavaScript(response));
128:
129: contentType[0] = "application/x-javascript";
130: assertTrue(cache.isJavaScript(response));
131:
132: contentType[0] = "text/plain";
133: assertFalse(cache.isJavaScript(response));
134:
135: url[0] = new URL(URL_FIRST, "foo.js");
136: assertTrue(cache.isJavaScript(response));
137:
138: url[0] = new URL(URL_FIRST, "foo.js?1_1_40C");
139: assertTrue(cache.isJavaScript(response));
140: }
141:
142: /**
143: *@throws Exception if the test fails
144: */
145: public void testUsage() throws Exception {
146: final String content = "<html><head><title>page 1</title>"
147: + "<script src='foo1.js' type='text/javascript'/>"
148: + "<script src='foo2.js' type='text/javascript'/>"
149: + "</head><body>"
150: + "<a href='page2.html'>to page 2</a>"
151: + "</body></html>";
152:
153: final String content2 = "<html><head><title>page 2</title>"
154: + "<script src='foo2.js' type='text/javascript'/>"
155: + "</head><body>"
156: + "<a href='page1.html'>to page 1</a>"
157: + "</body></html>";
158:
159: final String script1 = "alert('in foo1');";
160: final String script2 = "alert('in foo2');";
161:
162: final WebClient webClient = new WebClient();
163: final MockWebConnection connection = new MockWebConnection(
164: webClient);
165: webClient.setWebConnection(connection);
166:
167: final URL urlPage1 = new URL(URL_FIRST, "page1.html");
168: connection.setResponse(urlPage1, content);
169: final URL urlPage2 = new URL(URL_FIRST, "page2.html");
170: connection.setResponse(urlPage2, content2);
171:
172: final List headers = Collections.singletonList(new Header(
173: "Last-Modified", "Sun, 15 Jul 2007 20:46:27 GMT"));
174: connection.setResponse(new URL(URL_FIRST, "foo1.js"), script1,
175: 200, "ok", "text/javascript", headers);
176: connection.setResponse(new URL(URL_FIRST, "foo2.js"), script2,
177: 200, "ok", "text/javascript", headers);
178:
179: final List collectedAlerts = new ArrayList();
180: webClient.setAlertHandler(new CollectingAlertHandler(
181: collectedAlerts));
182:
183: final HtmlPage page1 = (HtmlPage) webClient.getPage(urlPage1);
184: final String[] expectedAlerts = { "in foo1", "in foo2" };
185: assertEquals(expectedAlerts, collectedAlerts);
186:
187: collectedAlerts.clear();
188: ((HtmlAnchor) page1.getAnchors().get(0)).click();
189:
190: assertEquals(new String[] { "in foo2" }, collectedAlerts);
191: assertEquals(
192: "no request for scripts should have been performed",
193: urlPage2, connection.getLastWebRequestSettings()
194: .getURL());
195: }
196:
197: /**
198: *@throws Exception if the test fails
199: */
200: public void testMaxSizeMaintained() throws Exception {
201:
202: final String html = "<html><head><title>page 1</title>"
203: + "<script src='foo1.js' type='text/javascript'/>"
204: + "<script src='foo2.js' type='text/javascript'/>"
205: + "</head><body>abc</body></html>";
206:
207: final WebClient client = new WebClient();
208: client.getCache().setMaxSize(1);
209:
210: final MockWebConnection connection = new MockWebConnection(
211: client);
212: client.setWebConnection(connection);
213:
214: final URL pageUrl = new URL(URL_FIRST, "page1.html");
215: connection.setResponse(pageUrl, html);
216:
217: final List headers = Collections.singletonList(new Header(
218: "Last-Modified", "Sun, 15 Jul 2007 20:46:27 GMT"));
219: connection.setResponse(new URL(URL_FIRST, "foo1.js"), ";", 200,
220: "ok", "text/javascript", headers);
221: connection.setResponse(new URL(URL_FIRST, "foo2.js"), ";", 200,
222: "ok", "text/javascript", headers);
223:
224: client.getPage(pageUrl);
225: assertEquals(1, client.getCache().getSize());
226: }
227:
228: }
229:
230: class DummyWebResponse implements WebResponse {
231:
232: public InputStream getContentAsStream() throws IOException {
233: throw new RuntimeException("not implemented");
234: }
235:
236: public String getContentAsString() {
237: throw new RuntimeException("not implemented");
238: }
239:
240: public String getContentCharSet() {
241: throw new RuntimeException("not implemented");
242: }
243:
244: public String getContentType() {
245: throw new RuntimeException("not implemented");
246: }
247:
248: public long getLoadTimeInMilliSeconds() {
249: throw new RuntimeException("not implemented");
250: }
251:
252: public SubmitMethod getRequestMethod() {
253: throw new RuntimeException("not implemented");
254: }
255:
256: public byte[] getResponseBody() {
257: throw new RuntimeException("not implemented");
258: }
259:
260: public List getResponseHeaders() {
261: throw new RuntimeException("not implemented");
262: }
263:
264: public String getResponseHeaderValue(final String headerName) {
265: throw new RuntimeException("not implemented");
266: }
267:
268: public int getStatusCode() {
269: throw new RuntimeException("not implemented");
270: }
271:
272: public String getStatusMessage() {
273: throw new RuntimeException("not implemented");
274: }
275:
276: public URL getUrl() {
277: throw new RuntimeException("not implemented");
278: }
279: }
|