1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.impl.client.cache;
28
29 import static org.junit.Assert.assertEquals;
30 import static org.junit.Assert.assertNotSame;
31 import static org.junit.Assert.fail;
32
33 import java.io.IOException;
34 import java.util.Date;
35
36 import org.apache.http.Header;
37 import org.apache.http.HttpResponse;
38 import org.apache.http.HttpStatus;
39 import org.apache.http.HttpVersion;
40 import org.apache.http.client.cache.HttpCacheEntry;
41 import org.apache.http.client.utils.DateUtils;
42 import org.apache.http.message.BasicHeader;
43 import org.apache.http.message.BasicHttpResponse;
44 import org.junit.Before;
45 import org.junit.Test;
46
47 public class TestCacheEntryUpdater {
48
49 private Date requestDate;
50 private Date responseDate;
51
52 private CacheEntryUpdater impl;
53 private HttpCacheEntry entry;
54 private Date now;
55 private Date oneSecondAgo;
56 private Date twoSecondsAgo;
57 private Date eightSecondsAgo;
58 private Date tenSecondsAgo;
59 private HttpResponse response;
60
61 @Before
62 public void setUp() throws Exception {
63 requestDate = new Date(System.currentTimeMillis() - 1000);
64 responseDate = new Date();
65
66 now = new Date();
67 oneSecondAgo = new Date(now.getTime() - 1000L);
68 twoSecondsAgo = new Date(now.getTime() - 2000L);
69 eightSecondsAgo = new Date(now.getTime() - 8000L);
70 tenSecondsAgo = new Date(now.getTime() - 10000L);
71
72 response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
73 HttpStatus.SC_NOT_MODIFIED, "Not Modified");
74
75 impl = new CacheEntryUpdater();
76 }
77
78 @Test
79 public void testUpdateCacheEntryReturnsDifferentEntryInstance()
80 throws IOException {
81 entry = HttpTestUtils.makeCacheEntry();
82 final HttpCacheEntry newEntry = impl.updateCacheEntry(null, entry,
83 requestDate, responseDate, response);
84 assertNotSame(newEntry, entry);
85 }
86
87 @Test
88 public void testHeadersAreMergedCorrectly() throws IOException {
89 final Header[] headers = {
90 new BasicHeader("Date", DateUtils.formatDate(responseDate)),
91 new BasicHeader("ETag", "\"etag\"")};
92 entry = HttpTestUtils.makeCacheEntry(headers);
93 response.setHeaders(new Header[]{});
94
95 final HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, entry,
96 new Date(), new Date(), response);
97
98
99 final Header[] updatedHeaders = updatedEntry.getAllHeaders();
100 assertEquals(2, updatedHeaders.length);
101 headersContain(updatedHeaders, "Date", DateUtils.formatDate(responseDate));
102 headersContain(updatedHeaders, "ETag", "\"etag\"");
103 }
104
105 @Test
106 public void testNewerHeadersReplaceExistingHeaders() throws IOException {
107 final Header[] headers = {
108 new BasicHeader("Date", DateUtils.formatDate(requestDate)),
109 new BasicHeader("Cache-Control", "private"),
110 new BasicHeader("ETag", "\"etag\""),
111 new BasicHeader("Last-Modified", DateUtils.formatDate(requestDate)),
112 new BasicHeader("Cache-Control", "max-age=0"),};
113 entry = HttpTestUtils.makeCacheEntry(headers);
114
115 response.setHeaders(new Header[] {
116 new BasicHeader("Last-Modified", DateUtils.formatDate(responseDate)),
117 new BasicHeader("Cache-Control", "public")});
118
119 final HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, entry,
120 new Date(), new Date(), response);
121
122 final Header[] updatedHeaders = updatedEntry.getAllHeaders();
123
124 assertEquals(4, updatedHeaders.length);
125 headersContain(updatedHeaders, "Date", DateUtils.formatDate(requestDate));
126 headersContain(updatedHeaders, "ETag", "\"etag\"");
127 headersContain(updatedHeaders, "Last-Modified", DateUtils.formatDate(responseDate));
128 headersContain(updatedHeaders, "Cache-Control", "public");
129 }
130
131 @Test
132 public void testNewHeadersAreAddedByMerge() throws IOException {
133
134 final Header[] headers = {
135 new BasicHeader("Date", DateUtils.formatDate(requestDate)),
136 new BasicHeader("ETag", "\"etag\"")};
137
138 entry = HttpTestUtils.makeCacheEntry(headers);
139 response.setHeaders(new Header[]{
140 new BasicHeader("Last-Modified", DateUtils.formatDate(responseDate)),
141 new BasicHeader("Cache-Control", "public"),});
142
143 final HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, entry,
144 new Date(), new Date(), response);
145
146 final Header[] updatedHeaders = updatedEntry.getAllHeaders();
147 assertEquals(4, updatedHeaders.length);
148
149 headersContain(updatedHeaders, "Date", DateUtils.formatDate(requestDate));
150 headersContain(updatedHeaders, "ETag", "\"etag\"");
151 headersContain(updatedHeaders, "Last-Modified", DateUtils.formatDate(responseDate));
152 headersContain(updatedHeaders, "Cache-Control", "public");
153 }
154
155 @Test
156 public void oldHeadersRetainedIfResponseOlderThanEntry()
157 throws Exception {
158 final Header[] headers = {
159 new BasicHeader("Date", DateUtils.formatDate(oneSecondAgo)),
160 new BasicHeader("ETag", "\"new-etag\"")
161 };
162 entry = HttpTestUtils.makeCacheEntry(twoSecondsAgo, now, headers);
163 response.setHeader("Date", DateUtils.formatDate(tenSecondsAgo));
164 response.setHeader("ETag", "\"old-etag\"");
165 final HttpCacheEntry result = impl.updateCacheEntry("A", entry, new Date(),
166 new Date(), response);
167 assertEquals(2, result.getAllHeaders().length);
168 headersContain(result.getAllHeaders(), "Date", DateUtils.formatDate(oneSecondAgo));
169 headersContain(result.getAllHeaders(), "ETag", "\"new-etag\"");
170 }
171
172 @Test
173 public void testUpdatedEntryHasLatestRequestAndResponseDates()
174 throws IOException {
175 entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, eightSecondsAgo);
176 final HttpCacheEntry updated = impl.updateCacheEntry(null, entry,
177 twoSecondsAgo, oneSecondAgo, response);
178
179 assertEquals(twoSecondsAgo, updated.getRequestDate());
180 assertEquals(oneSecondAgo, updated.getResponseDate());
181 }
182
183 @Test
184 public void entry1xxWarningsAreRemovedOnUpdate() throws Exception {
185 final Header[] headers = {
186 new BasicHeader("Warning", "110 fred \"Response is stale\""),
187 new BasicHeader("ETag", "\"old\""),
188 new BasicHeader("Date", DateUtils.formatDate(eightSecondsAgo))
189 };
190 entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, eightSecondsAgo, headers);
191 response.setHeader("ETag", "\"new\"");
192 response.setHeader("Date", DateUtils.formatDate(twoSecondsAgo));
193 final HttpCacheEntry updated = impl.updateCacheEntry(null, entry,
194 twoSecondsAgo, oneSecondAgo, response);
195
196 assertEquals(0, updated.getHeaders("Warning").length);
197 }
198
199 @Test
200 public void entryWithMalformedDateIsStillUpdated() throws Exception {
201 final Header[] headers = {
202 new BasicHeader("ETag", "\"old\""),
203 new BasicHeader("Date", "bad-date")
204 };
205 entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, eightSecondsAgo, headers);
206 response.setHeader("ETag", "\"new\"");
207 response.setHeader("Date", DateUtils.formatDate(twoSecondsAgo));
208 final HttpCacheEntry updated = impl.updateCacheEntry(null, entry,
209 twoSecondsAgo, oneSecondAgo, response);
210
211 assertEquals("\"new\"", updated.getFirstHeader("ETag").getValue());
212 }
213
214 @Test
215 public void entryIsStillUpdatedByResponseWithMalformedDate() throws Exception {
216 final Header[] headers = {
217 new BasicHeader("ETag", "\"old\""),
218 new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo))
219 };
220 entry = HttpTestUtils.makeCacheEntry(tenSecondsAgo, eightSecondsAgo, headers);
221 response.setHeader("ETag", "\"new\"");
222 response.setHeader("Date", "bad-date");
223 final HttpCacheEntry updated = impl.updateCacheEntry(null, entry,
224 twoSecondsAgo, oneSecondAgo, response);
225
226 assertEquals("\"new\"", updated.getFirstHeader("ETag").getValue());
227 }
228
229 @Test
230 public void cannotUpdateFromANon304OriginResponse() throws Exception {
231 entry = HttpTestUtils.makeCacheEntry();
232 response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
233 HttpStatus.SC_OK, "OK");
234 try {
235 impl.updateCacheEntry("A", entry, new Date(), new Date(),
236 response);
237 fail("should have thrown exception");
238 } catch (final IllegalArgumentException expected) {
239 }
240 }
241
242 @Test
243 public void testContentEncodingHeaderIsNotUpdatedByMerge() throws IOException {
244 final Header[] headers = {
245 new BasicHeader("Date", DateUtils.formatDate(requestDate)),
246 new BasicHeader("ETag", "\"etag\""),
247 new BasicHeader("Content-Encoding", "identity")};
248
249 entry = HttpTestUtils.makeCacheEntry(headers);
250 response.setHeaders(new Header[]{
251 new BasicHeader("Last-Modified", DateUtils.formatDate(responseDate)),
252 new BasicHeader("Cache-Control", "public"),
253 new BasicHeader("Content-Encoding", "gzip")});
254
255 final HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, entry,
256 new Date(), new Date(), response);
257
258 final Header[] updatedHeaders = updatedEntry.getAllHeaders();
259 headersContain(updatedHeaders, "Content-Encoding", "identity");
260 headersNotContain(updatedHeaders, "Content-Encoding", "gzip");
261 }
262
263 @Test
264 public void testContentLengthIsNotAddedWhenTransferEncodingIsPresent() throws IOException {
265 final Header[] headers = {
266 new BasicHeader("Date", DateUtils.formatDate(requestDate)),
267 new BasicHeader("ETag", "\"etag\""),
268 new BasicHeader("Transfer-Encoding", "chunked")};
269
270 entry = HttpTestUtils.makeCacheEntry(headers);
271 response.setHeaders(new Header[]{
272 new BasicHeader("Last-Modified", DateUtils.formatDate(responseDate)),
273 new BasicHeader("Cache-Control", "public"),
274 new BasicHeader("Content-Length", "0")});
275
276 final HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, entry,
277 new Date(), new Date(), response);
278
279 final Header[] updatedHeaders = updatedEntry.getAllHeaders();
280 headersContain(updatedHeaders, "Transfer-Encoding", "chunked");
281 headersNotContain(updatedHeaders, "Content-Length", "0");
282 }
283
284 private void headersContain(final Header[] headers, final String name, final String value) {
285 for (final Header header : headers) {
286 if (header.getName().equals(name)) {
287 if (header.getValue().equals(value)) {
288 return;
289 }
290 }
291 }
292 fail("Header [" + name + ": " + value + "] not found in headers.");
293 }
294
295 private void headersNotContain(final Header[] headers, final String name, final String value) {
296 for (final Header header : headers) {
297 if (header.getName().equals(name)) {
298 if (header.getValue().equals(value)) {
299 fail("Header [" + name + ": " + value + "] found in headers where it should not be");
300 }
301 }
302 }
303 }
304 }