View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.hc.client5.http.impl.cache;
28  
29  import static org.junit.jupiter.api.Assertions.assertAll;
30  import static org.junit.jupiter.api.Assertions.assertEquals;
31  import static org.junit.jupiter.api.Assertions.assertThrows;
32  import static org.junit.jupiter.api.Assertions.assertTrue;
33  
34  import java.util.Arrays;
35  import java.util.Collections;
36  
37  import org.apache.hc.core5.http.Header;
38  import org.apache.hc.core5.http.message.BasicHeader;
39  import org.junit.jupiter.api.Test;
40  
41  public class CacheControlParserTest {
42  
43      private final CacheControlHeaderParser parser = CacheControlHeaderParser.INSTANCE;
44  
45      @Test
46      public void testParseMaxAgeZero() {
47          final Header header = new BasicHeader("Cache-Control", "max-age=0 , this = stuff;");
48          final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
49          assertEquals(0L, cacheControl.getMaxAge());
50      }
51  
52      @Test
53      public void testParseSMaxAge() {
54          final Header header = new BasicHeader("Cache-Control", "s-maxage=3600");
55          final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
56          assertEquals(3600L, cacheControl.getSharedMaxAge());
57      }
58  
59      @Test
60      public void testParseInvalidCacheValue() {
61          final Header header = new BasicHeader("Cache-Control", "max-age=invalid");
62          final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
63          assertEquals(0L, cacheControl.getMaxAge());
64      }
65  
66      @Test
67      public void testParseInvalidHeader() {
68          final Header header = new BasicHeader("Cache-Control", "max-age");
69          final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
70          assertEquals(-1L, cacheControl.getMaxAge());
71      }
72  
73      @Test
74      public void testParseNullHeader() {
75          final Header header = null;
76          assertThrows(NullPointerException.class, () -> parser.parseResponse(Collections.singletonList(header).iterator()));
77      }
78  
79      @Test
80      public void testParseEmptyHeader() {
81          final Header header = new BasicHeader("Cache-Control", "");
82          final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
83          assertEquals(-1L, cacheControl.getMaxAge());
84      }
85  
86      @Test
87      public void testParseCookieEmptyValue() {
88          final Header header = new BasicHeader("Cache-Control", "max-age=,");
89          final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
90          assertEquals(-1L, cacheControl.getMaxAge());
91      }
92  
93      @Test
94      public void testParseNoCache() {
95          final Header header = new BasicHeader(" Cache-Control", "no-cache");
96          final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
97          assertEquals(-1L, cacheControl.getMaxAge());
98      }
99  
100     @Test
101     public void testParseNoDirective() {
102         final Header header = new BasicHeader(" Cache-Control", "");
103         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
104         assertEquals(-1L, cacheControl.getMaxAge());
105     }
106 
107     @Test
108     public void testGarbage() {
109         final Header header = new BasicHeader("Cache-Control", ",,= blah,");
110         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
111         assertEquals(-1L, cacheControl.getMaxAge());
112     }
113 
114 
115     @Test
116     public void testParseMultipleDirectives() {
117         final Header header = new BasicHeader("Cache-Control", "max-age=604800, stale-while-revalidate=86400, s-maxage=3600, must-revalidate, private");
118         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
119 
120         assertAll("Must all pass",
121                 () -> assertEquals(604800L, cacheControl.getMaxAge()),
122                 () -> assertEquals(3600L, cacheControl.getSharedMaxAge()),
123                 () -> assertTrue(cacheControl.isMustRevalidate()),
124                 () -> assertTrue(cacheControl.isCachePrivate())
125         );
126     }
127 
128     @Test
129     public void testParseMultipleDirectives2() {
130         final Header header = new BasicHeader("Cache-Control", "max-age=604800, stale-while-revalidate=86400, must-revalidate, private, s-maxage=3600");
131         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
132 
133         assertAll("Must all pass",
134                 () -> assertEquals(604800L, cacheControl.getMaxAge()),
135                 () -> assertEquals(3600L, cacheControl.getSharedMaxAge()),
136                 () -> assertTrue(cacheControl.isMustRevalidate()),
137                 () -> assertTrue(cacheControl.isCachePrivate())
138         );
139     }
140 
141     @Test
142     public void testParsePublic() {
143         final Header header = new BasicHeader("Cache-Control", "public");
144         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
145 
146         assertTrue(cacheControl.isPublic());
147     }
148 
149     @Test
150     public void testParsePrivate() {
151         final Header header = new BasicHeader("Cache-Control", "private");
152         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
153 
154         assertTrue(cacheControl.isCachePrivate());
155     }
156 
157     @Test
158     public void testParseNoStore() {
159         final Header header = new BasicHeader("Cache-Control", "no-store");
160         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
161 
162         assertTrue(cacheControl.isNoStore());
163     }
164 
165     @Test
166     public void testParseStaleWhileRevalidate() {
167         final Header header = new BasicHeader("Cache-Control", "max-age=3600, stale-while-revalidate=120");
168         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
169 
170         assertEquals(120, cacheControl.getStaleWhileRevalidate());
171     }
172 
173     @Test
174     public void testParseNoCacheFields() {
175         final Header header = new BasicHeader("Cache-Control", "no-cache=\"Set-Cookie, Content-Language\", stale-while-revalidate=120");
176         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
177 
178         assertTrue(cacheControl.isNoCache());
179         assertEquals(2, cacheControl.getNoCacheFields().size());
180         assertTrue(cacheControl.getNoCacheFields().contains("Set-Cookie"));
181         assertTrue(cacheControl.getNoCacheFields().contains("Content-Language"));
182         assertEquals(120, cacheControl.getStaleWhileRevalidate());
183     }
184 
185     @Test
186     public void testParseNoCacheFieldsNoQuote() {
187         final Header header = new BasicHeader("Cache-Control", "no-cache=Set-Cookie, Content-Language, stale-while-revalidate=120");
188         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
189 
190         assertTrue(cacheControl.isNoCache());
191         assertEquals(1, cacheControl.getNoCacheFields().size());
192         assertTrue(cacheControl.getNoCacheFields().contains("Set-Cookie"));
193         assertEquals(120, cacheControl.getStaleWhileRevalidate());
194     }
195 
196     @Test
197     public void testParseNoCacheFieldsMessy() {
198         final Header header = new BasicHeader("Cache-Control", "no-cache=\"  , , ,,, Set-Cookie  , , Content-Language ,   \", stale-while-revalidate=120");
199         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
200 
201         assertTrue(cacheControl.isNoCache());
202         assertEquals(2, cacheControl.getNoCacheFields().size());
203         assertTrue(cacheControl.getNoCacheFields().contains("Set-Cookie"));
204         assertTrue(cacheControl.getNoCacheFields().contains("Content-Language"));
205         assertEquals(120, cacheControl.getStaleWhileRevalidate());
206     }
207 
208 
209     @Test
210     public void testParseMultipleHeaders() {
211         // Create headers
212         final Header header1 = new BasicHeader("Cache-Control", "max-age=3600, no-store");
213         final Header header2 = new BasicHeader("Cache-Control", "private, must-revalidate");
214         final Header header3 = new BasicHeader("Cache-Control", "max-age=3600");
215         final Header header4 = new BasicHeader("Cache-Control", "no-store");
216         final Header header5 = new BasicHeader("Cache-Control", "private");
217         final Header header6 = new BasicHeader("Cache-Control", "must-revalidate");
218 
219         // Parse headers
220         final ResponseCacheControl cacheControl1 = parser.parseResponse(Arrays.asList(header1, header2).iterator());
221         final ResponseCacheControl cacheControl2 = parser.parseResponse(Arrays.asList(header3, header4, header5, header6).iterator());
222 
223         // Validate Cache-Control directives
224         assertEquals(cacheControl1.getMaxAge(), cacheControl2.getMaxAge());
225         assertEquals(cacheControl1.isNoStore(), cacheControl2.isNoStore());
226         assertEquals(cacheControl1.isCachePrivate(), cacheControl2.isCachePrivate());
227         assertEquals(cacheControl1.isMustRevalidate(), cacheControl2.isMustRevalidate());
228     }
229 
230     @Test
231     public void testParseRequestMultipleDirectives() {
232         final Header header = new BasicHeader("Cache-Control", "blah, max-age=1111, max-stale=2222, " +
233                 "min-fresh=3333, no-cache, no-store, no-cache, no-stuff, only-if-cached, only-if-cached-or-maybe-not");
234         final RequestCacheControl cacheControl = parser.parseRequest(Collections.singletonList(header).iterator());
235 
236         assertAll("Must all pass",
237                 () -> assertEquals(1111L, cacheControl.getMaxAge()),
238                 () -> assertEquals(2222L, cacheControl.getMaxStale()),
239                 () -> assertEquals(3333L, cacheControl.getMinFresh()),
240                 () -> assertTrue(cacheControl.isNoCache()),
241                 () -> assertTrue(cacheControl.isNoCache()),
242                 () -> assertTrue(cacheControl.isOnlyIfCached())
243         );
244     }
245 
246     @Test
247     public void testParseIsImmutable() {
248         final Header header = new BasicHeader("Cache-Control", "max-age=0 , immutable");
249         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
250         assertTrue(cacheControl.isImmutable());
251     }
252 
253     @Test
254     public void testParseMultipleIsImmutable() {
255         final Header header = new BasicHeader("Cache-Control", "immutable, nmax-age=0 , immutable");
256         final ResponseCacheControl cacheControl = parser.parseResponse(Collections.singletonList(header).iterator());
257         assertTrue(cacheControl.isImmutable());
258     }
259 
260 }