Home | History | Annotate | Download | only in toolbox
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.volley.toolbox;
     18 
     19 import android.test.suitebuilder.annotation.SmallTest;
     20 
     21 import com.android.volley.Cache;
     22 import com.android.volley.NetworkResponse;
     23 
     24 import java.text.DateFormat;
     25 import java.text.SimpleDateFormat;
     26 import java.util.Date;
     27 import java.util.HashMap;
     28 import java.util.Map;
     29 
     30 import junit.framework.TestCase;
     31 
     32 @SmallTest
     33 public class HttpHeaderParserTest extends TestCase {
     34 
     35     private static long ONE_MINUTE_MILLIS = 1000L * 60;
     36     private static long ONE_HOUR_MILLIS = 1000L * 60 * 60;
     37 
     38     private NetworkResponse response;
     39     private Map<String, String> headers;
     40 
     41     @Override
     42     protected void setUp() throws Exception {
     43         super.setUp();
     44         headers = new HashMap<String, String>();
     45         response = new NetworkResponse(0, null, headers, false);
     46     }
     47 
     48     public void testParseCacheHeaders_noHeaders() {
     49         Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
     50 
     51         assertNotNull(entry);
     52         assertNull(entry.etag);
     53         assertEquals(0, entry.serverDate);
     54         assertEquals(0, entry.ttl);
     55         assertEquals(0, entry.softTtl);
     56     }
     57 
     58     public void testParseCacheHeaders_headersSet() {
     59         headers.put("MyCustomHeader", "42");
     60 
     61         Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
     62 
     63         assertNotNull(entry);
     64         assertNotNull(entry.responseHeaders);
     65         assertEquals(1, entry.responseHeaders.size());
     66         assertEquals("42", entry.responseHeaders.get("MyCustomHeader"));
     67     }
     68 
     69     public void testParseCacheHeaders_etag() {
     70         headers.put("ETag", "Yow!");
     71 
     72         Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
     73 
     74         assertNotNull(entry);
     75         assertEquals("Yow!", entry.etag);
     76     }
     77 
     78     public void testParseCacheHeaders_normalExpire() {
     79         long now = System.currentTimeMillis();
     80         headers.put("Date", rfc1123Date(now));
     81         headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS));
     82 
     83         Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
     84 
     85         assertNotNull(entry);
     86         assertNull(entry.etag);
     87         assertEqualsWithin(entry.serverDate, now, ONE_MINUTE_MILLIS);
     88         assertTrue(entry.softTtl >= (now + ONE_HOUR_MILLIS));
     89         assertTrue(entry.ttl == entry.softTtl);
     90     }
     91 
     92     public void testParseCacheHeaders_expiresInPast() {
     93         long now = System.currentTimeMillis();
     94         headers.put("Date", rfc1123Date(now));
     95         headers.put("Expires", rfc1123Date(now - ONE_HOUR_MILLIS));
     96 
     97         Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
     98 
     99         assertNotNull(entry);
    100         assertNull(entry.etag);
    101         assertEqualsWithin(entry.serverDate, now, ONE_MINUTE_MILLIS);
    102         assertEquals(0, entry.ttl);
    103         assertEquals(0, entry.softTtl);
    104     }
    105 
    106     public void testParseCacheHeaders_serverRelative() {
    107 
    108         long now = System.currentTimeMillis();
    109         // Set "current" date as one hour in the future
    110         headers.put("Date", rfc1123Date(now + ONE_HOUR_MILLIS));
    111         // TTL four hours in the future, so should be three hours from now
    112         headers.put("Expires", rfc1123Date(now + 4 * ONE_HOUR_MILLIS));
    113 
    114         Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
    115 
    116         assertEqualsWithin(now + 3 * ONE_HOUR_MILLIS, entry.ttl, ONE_MINUTE_MILLIS);
    117         assertEquals(entry.softTtl, entry.ttl);
    118     }
    119 
    120     public void testParseCacheHeaders_cacheControlOverridesExpires() {
    121         long now = System.currentTimeMillis();
    122         headers.put("Date", rfc1123Date(now));
    123         headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS));
    124         headers.put("Cache-Control", "public, max-age=86400");
    125 
    126         Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
    127 
    128         assertNotNull(entry);
    129         assertNull(entry.etag);
    130         assertEqualsWithin(now + 24 * ONE_HOUR_MILLIS, entry.ttl, ONE_MINUTE_MILLIS);
    131         assertEquals(entry.softTtl, entry.ttl);
    132     }
    133 
    134     public void testParseCacheHeaders_cacheControlNoCache() {
    135         long now = System.currentTimeMillis();
    136         headers.put("Date", rfc1123Date(now));
    137         headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS));
    138         headers.put("Cache-Control", "no-cache");
    139 
    140         Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
    141 
    142         assertNull(entry);
    143     }
    144 
    145     public void testParseCacheHeaders_cacheControlMustRevalidate() {
    146         long now = System.currentTimeMillis();
    147         headers.put("Date", rfc1123Date(now));
    148         headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS));
    149         headers.put("Cache-Control", "must-revalidate");
    150 
    151         Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
    152 
    153         assertNotNull(entry);
    154         assertNull(entry.etag);
    155         assertEqualsWithin(now, entry.ttl, ONE_MINUTE_MILLIS);
    156         assertEquals(entry.softTtl, entry.ttl);
    157     }
    158 
    159     private void assertEqualsWithin(long expected, long value, long fudgeFactor) {
    160         long diff = Math.abs(expected - value);
    161         assertTrue(diff < fudgeFactor);
    162     }
    163 
    164     private static String rfc1123Date(long millis) {
    165         DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
    166         return df.format(new Date(millis));
    167     }
    168 
    169     // --------------------------
    170 
    171     public void testParseCharset() {
    172         // Like the ones we usually see
    173         headers.put("Content-Type", "text/plain; charset=utf-8");
    174         assertEquals("utf-8", HttpHeaderParser.parseCharset(headers));
    175 
    176         // Extra whitespace
    177         headers.put("Content-Type", "text/plain;    charset=utf-8 ");
    178         assertEquals("utf-8", HttpHeaderParser.parseCharset(headers));
    179 
    180         // Extra parameters
    181         headers.put("Content-Type", "text/plain; charset=utf-8; frozzle=bar");
    182         assertEquals("utf-8", HttpHeaderParser.parseCharset(headers));
    183 
    184         // No Content-Type header
    185         headers.clear();
    186         assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers));
    187 
    188         // Empty value
    189         headers.put("Content-Type", "text/plain; charset=");
    190         assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers));
    191 
    192         // None specified
    193         headers.put("Content-Type", "text/plain");
    194         assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers));
    195 
    196         // None specified, extra semicolon
    197         headers.put("Content-Type", "text/plain;");
    198         assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers));
    199     }
    200 }
    201