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
28
29
30 package com.jcabi.http.wire;
31
32 import com.jcabi.http.Request;
33 import com.jcabi.http.mock.MkAnswer;
34 import com.jcabi.http.mock.MkContainer;
35 import com.jcabi.http.mock.MkGrizzlyContainer;
36 import com.jcabi.http.mock.MkQuery;
37 import com.jcabi.http.request.JdkRequest;
38 import com.jcabi.http.response.RestResponse;
39 import jakarta.ws.rs.core.HttpHeaders;
40 import java.net.HttpURLConnection;
41 import java.util.Collections;
42 import java.util.Map;
43 import org.hamcrest.Description;
44 import org.hamcrest.Matcher;
45 import org.hamcrest.MatcherAssert;
46 import org.hamcrest.Matchers;
47 import org.hamcrest.TypeSafeMatcher;
48 import org.hamcrest.core.IsAnything;
49 import org.junit.jupiter.api.Test;
50
51
52
53
54
55 final class LastModifiedCachingWireTest {
56
57
58
59
60
61
62
63
64
65
66
67
68 private static final String BODY = "Test body";
69
70
71
72
73 private static final String BODY_UPDATED = "Test body updated";
74
75
76
77
78
79 @Test
80 void requestWithoutHeaderPassed() throws Exception {
81 final MkContainer container = new MkGrizzlyContainer()
82 .next(
83 new MkAnswer.Simple(
84 HttpURLConnection.HTTP_OK, LastModifiedCachingWireTest.BODY
85 )
86 ).start();
87 try {
88 final Request req = new JdkRequest(container.home())
89 .through(LastModifiedCachingWire.class);
90 req.fetch().as(RestResponse.class)
91 .assertStatus(HttpURLConnection.HTTP_OK)
92 .assertBody(Matchers.equalTo(LastModifiedCachingWireTest.BODY));
93 MatcherAssert.assertThat(container.queries(), Matchers.equalTo(1));
94 } finally {
95 container.stop();
96 }
97 }
98
99
100
101
102
103 @Test
104 void cachesGetRequest() throws Exception {
105 final Map<String, String> headers = Collections.singletonMap(
106 HttpHeaders.LAST_MODIFIED,
107 "Wed, 15 Nov 1995 04:58:08 GMT"
108 );
109 final int count = 10;
110 final MkContainer container = new MkGrizzlyContainer()
111 .next(
112 new MkAnswer.Simple(
113 HttpURLConnection.HTTP_OK,
114 headers.entrySet(),
115 LastModifiedCachingWireTest.BODY.getBytes()
116 )
117 )
118 .next(
119 new MkAnswer.Simple(HttpURLConnection.HTTP_NOT_MODIFIED),
120 new IsAnything<MkQuery>(),
121 count
122 ).start();
123 try {
124 final Request req = new JdkRequest(container.home())
125 .through(LastModifiedCachingWire.class);
126 for (int idx = 0; idx < count; ++idx) {
127 req
128 .fetch()
129 .as(RestResponse.class)
130 .assertStatus(HttpURLConnection.HTTP_OK)
131 .assertBody(
132 Matchers.equalTo(LastModifiedCachingWireTest.BODY)
133 );
134 }
135 MatcherAssert.assertThat(
136 container.queries(), Matchers.equalTo(count)
137 );
138 } finally {
139 container.stop();
140 }
141 }
142
143
144
145
146
147
148
149
150 @Test
151 void doesNotCacheGetRequestIfTheLastModifiedHeaderIsMissing()
152 throws Exception {
153 final String first = "Body 1";
154 final String second = "Body 2";
155 final String third = "Body 3";
156 final MkContainer container = new MkGrizzlyContainer()
157 .next(
158 new MkAnswer.Simple(
159 HttpURLConnection.HTTP_OK,
160 Collections.singletonMap(
161 HttpHeaders.LAST_MODIFIED,
162 "Wed, 15 Nov 1995 05:58:08 GMT"
163 ).entrySet(),
164 first.getBytes()
165 ),
166 Matchers.not(queryContainsIfModifiedSinceHeader())
167 )
168 .next(
169 new MkAnswer.Simple(
170 HttpURLConnection.HTTP_OK,
171 Collections.<Map.Entry<String, String>>emptySet(),
172 second.getBytes()
173 ),
174 queryContainsIfModifiedSinceHeader()
175 )
176 .next(
177 new MkAnswer.Simple(
178 HttpURLConnection.HTTP_OK,
179 Collections.<Map.Entry<String, String>>emptySet(),
180 third.getBytes()
181 ),
182 Matchers.not(queryContainsIfModifiedSinceHeader())
183 ).start();
184 try {
185 final Request req = new JdkRequest(container.home())
186 .through(LastModifiedCachingWire.class);
187 req.fetch().as(RestResponse.class)
188 .assertStatus(HttpURLConnection.HTTP_OK)
189 .assertBody(Matchers.equalTo(first));
190 req.fetch().as(RestResponse.class)
191 .assertStatus(HttpURLConnection.HTTP_OK)
192 .assertBody(Matchers.equalTo(second));
193 req.fetch().as(RestResponse.class)
194 .assertStatus(HttpURLConnection.HTTP_OK)
195 .assertBody(Matchers.equalTo(third));
196 } finally {
197 container.stop();
198 }
199 }
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215 @Test
216 void doesNotEvictCacheOnNonOk()
217 throws Exception {
218 final String body = "Body";
219 final MkContainer container = new MkGrizzlyContainer()
220 .next(
221 new MkAnswer.Simple(
222 HttpURLConnection.HTTP_OK,
223 Collections.singletonMap(
224 HttpHeaders.LAST_MODIFIED,
225 "Wed, 15 Nov 1995 06:58:08 GMT"
226 ).entrySet(),
227 body.getBytes()
228 ),
229 Matchers.not(queryContainsIfModifiedSinceHeader())
230 )
231 .next(
232 new MkAnswer.Simple(HttpURLConnection.HTTP_NOT_FOUND),
233 queryContainsIfModifiedSinceHeader()
234 )
235 .next(
236 new MkAnswer.Simple(HttpURLConnection.HTTP_NOT_MODIFIED),
237 queryContainsIfModifiedSinceHeader()
238 ).start();
239 try {
240 final Request req = new JdkRequest(container.home())
241 .through(LastModifiedCachingWire.class);
242 req
243 .fetch()
244 .as(RestResponse.class)
245 .assertStatus(HttpURLConnection.HTTP_OK)
246 .assertBody(
247 Matchers.equalTo(body)
248 );
249 req
250 .fetch()
251 .as(RestResponse.class)
252 .assertStatus(HttpURLConnection.HTTP_NOT_FOUND);
253 req
254 .fetch()
255 .as(RestResponse.class)
256 .assertStatus(HttpURLConnection.HTTP_OK)
257 .assertBody(
258 Matchers.equalTo(body)
259 );
260 } finally {
261 container.stop();
262 }
263 }
264
265
266
267
268
269 @Test
270 void cacheUpdateNewerResponse() throws Exception {
271 final Map<String, String> headers = Collections.singletonMap(
272 HttpHeaders.LAST_MODIFIED,
273 "Wed, 16 Nov 1995 04:58:08 GMT"
274 );
275 final MkContainer container = new MkGrizzlyContainer()
276 .next(
277 new MkAnswer.Simple(
278 HttpURLConnection.HTTP_OK,
279 headers.entrySet(),
280 LastModifiedCachingWireTest.BODY.getBytes()
281 )
282 )
283 .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NOT_MODIFIED))
284 .next(
285 new MkAnswer.Simple(
286 HttpURLConnection.HTTP_OK,
287 headers.entrySet(),
288 LastModifiedCachingWireTest.BODY_UPDATED.getBytes()
289 )
290 )
291 .next(new MkAnswer.Simple(HttpURLConnection.HTTP_NOT_MODIFIED))
292 .start();
293 try {
294 final Request req = new JdkRequest(container.home())
295 .through(LastModifiedCachingWire.class);
296 for (int idx = 0; idx < 2; ++idx) {
297 req
298 .fetch()
299 .as(RestResponse.class)
300 .assertStatus(HttpURLConnection.HTTP_OK)
301 .assertBody(
302 Matchers.equalTo(LastModifiedCachingWireTest.BODY)
303 );
304 }
305 for (int idx = 0; idx < 2; ++idx) {
306 req
307 .fetch()
308 .as(RestResponse.class)
309 .assertStatus(HttpURLConnection.HTTP_OK)
310 .assertBody(
311 Matchers.equalTo(
312 LastModifiedCachingWireTest.BODY_UPDATED
313 )
314 );
315 }
316 MatcherAssert.assertThat(
317 container.queries(), Matchers.equalTo(2 + 2)
318 );
319 } finally {
320 container.stop();
321 }
322 }
323
324
325
326
327
328
329 @Test
330 void sendsRequestDirectly() throws Exception {
331 final MkContainer container = new MkGrizzlyContainer()
332 .next(
333 new MkAnswer.Simple(
334 HttpURLConnection.HTTP_OK, LastModifiedCachingWireTest.BODY
335 )
336 )
337 .next(
338 new MkAnswer.Simple(
339 HttpURLConnection.HTTP_OK, LastModifiedCachingWireTest.BODY
340 )
341 )
342 .start();
343 try {
344 final Request req = new JdkRequest(container.home())
345 .through(LastModifiedCachingWire.class).header(
346 HttpHeaders.IF_MODIFIED_SINCE,
347 "Fri, 01 Jan 2016 00:00:00 GMT"
348 );
349 for (int idx = 0; idx < 2; ++idx) {
350 req
351 .fetch()
352 .as(RestResponse.class)
353 .assertStatus(HttpURLConnection.HTTP_OK)
354 .assertBody(
355 Matchers.equalTo(LastModifiedCachingWireTest.BODY)
356 );
357 }
358 MatcherAssert.assertThat(container.queries(), Matchers.equalTo(2));
359 } finally {
360 container.stop();
361 }
362 }
363
364
365
366
367
368 private static Matcher<MkQuery> queryContainsIfModifiedSinceHeader() {
369 return LastModifiedCachingWireTest.queryContainingHeader(
370 "If-Modified-Since"
371 );
372 }
373
374
375
376
377
378
379
380 private static Matcher<MkQuery> queryContainingHeader(final String header) {
381 return new TypeSafeMatcher<MkQuery>() {
382 @Override
383 protected boolean matchesSafely(final MkQuery query) {
384 return query.headers().containsKey(header);
385 }
386
387 @Override
388 public void describeTo(final Description description) {
389 description.appendText("contains ");
390 description.appendText(header);
391 }
392 };
393 }
394 }