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