13713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick/* 23713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * Copyright (C) 2011 The Android Open Source Project 33713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * 43713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * Licensed under the Apache License, Version 2.0 (the "License"); 53713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * you may not use this file except in compliance with the License. 63713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * You may obtain a copy of the License at 73713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * 83713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * http://www.apache.org/licenses/LICENSE-2.0 93713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * 103713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * Unless required by applicable law or agreed to in writing, software 113713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * distributed under the License is distributed on an "AS IS" BASIS, 123713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * See the License for the specific language governing permissions and 143713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick * limitations under the License. 153713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick */ 163713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 173713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickpackage com.android.volley.toolbox; 183713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 19cebf98c8edef6b3506258ddb68266febadd0db1aJeff Sharkeyimport android.test.suitebuilder.annotation.SmallTest; 20cebf98c8edef6b3506258ddb68266febadd0db1aJeff Sharkey 213713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport com.android.volley.Cache; 223713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport com.android.volley.NetworkResponse; 233713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 243713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.text.DateFormat; 253713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.text.SimpleDateFormat; 263713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.util.Date; 273713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.util.HashMap; 283713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport java.util.Map; 293713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 303713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickimport junit.framework.TestCase; 313713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 32cebf98c8edef6b3506258ddb68266febadd0db1aJeff Sharkey@SmallTest 333713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrickpublic class HttpHeaderParserTest extends TestCase { 343713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 353713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick private static long ONE_MINUTE_MILLIS = 1000L * 60; 363713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick private static long ONE_HOUR_MILLIS = 1000L * 60 * 60; 373713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 383713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick private NetworkResponse response; 393713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick private Map<String, String> headers; 403713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 413713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick @Override 423713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick protected void setUp() throws Exception { 433713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick super.setUp(); 443713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers = new HashMap<String, String>(); 453713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick response = new NetworkResponse(0, null, headers, false); 463713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick } 473713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 483713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick public void testParseCacheHeaders_noHeaders() { 493713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response); 503713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 513713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertNotNull(entry); 523713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertNull(entry.etag); 533713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals(0, entry.serverDate); 543713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals(0, entry.ttl); 553713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals(0, entry.softTtl); 563713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick } 573713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 583713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick public void testParseCacheHeaders_etag() { 593713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("ETag", "Yow!"); 603713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 613713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response); 623713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 633713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertNotNull(entry); 643713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals("Yow!", entry.etag); 653713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick } 663713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 673713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick public void testParseCacheHeaders_normalExpire() { 683713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick long now = System.currentTimeMillis(); 693713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Date", rfc1123Date(now)); 703713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS)); 713713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 723713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response); 733713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 743713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertNotNull(entry); 753713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertNull(entry.etag); 763713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEqualsWithin(entry.serverDate, now, ONE_MINUTE_MILLIS); 773713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertTrue(entry.softTtl >= (now + ONE_HOUR_MILLIS)); 783713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertTrue(entry.ttl == entry.softTtl); 793713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick } 803713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 813713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick public void testParseCacheHeaders_expiresInPast() { 823713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick long now = System.currentTimeMillis(); 833713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Date", rfc1123Date(now)); 843713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Expires", rfc1123Date(now - ONE_HOUR_MILLIS)); 853713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 863713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response); 873713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 883713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertNotNull(entry); 893713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertNull(entry.etag); 903713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEqualsWithin(entry.serverDate, now, ONE_MINUTE_MILLIS); 913713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals(0, entry.ttl); 923713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals(0, entry.softTtl); 933713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick } 943713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 953713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick public void testParseCacheHeaders_serverRelative() { 963713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 973713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick long now = System.currentTimeMillis(); 983713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick // Set "current" date as one hour in the future 993713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Date", rfc1123Date(now + ONE_HOUR_MILLIS)); 1003713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick // TTL four hours in the future, so should be three hours from now 1013713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Expires", rfc1123Date(now + 4 * ONE_HOUR_MILLIS)); 1023713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1033713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response); 1043713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1053713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEqualsWithin(now + 3 * ONE_HOUR_MILLIS, entry.ttl, ONE_MINUTE_MILLIS); 1063713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals(entry.softTtl, entry.ttl); 1073713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick } 1083713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 109ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta public void testParseCacheHeaders_cacheControlOverridesExpires() { 110ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta long now = System.currentTimeMillis(); 111ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta headers.put("Date", rfc1123Date(now)); 112ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS)); 113ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta headers.put("Cache-Control", "public, max-age=86400"); 114ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta 115ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response); 116ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta 117ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta assertNotNull(entry); 118ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta assertNull(entry.etag); 119ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta assertEqualsWithin(now + 24 * ONE_HOUR_MILLIS, entry.ttl, ONE_MINUTE_MILLIS); 120ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta assertEquals(entry.softTtl, entry.ttl); 121ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta } 122ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta 123ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta public void testParseCacheHeaders_cacheControlNoCache() { 124ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta long now = System.currentTimeMillis(); 125ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta headers.put("Date", rfc1123Date(now)); 126ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS)); 127ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta headers.put("Cache-Control", "no-cache"); 128ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta 129ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response); 130ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta 131ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta assertNull(entry); 132ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta } 133ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta 134ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta public void testParseCacheHeaders_cacheControlMustRevalidate() { 135ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta long now = System.currentTimeMillis(); 136ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta headers.put("Date", rfc1123Date(now)); 137ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS)); 138ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta headers.put("Cache-Control", "must-revalidate"); 139ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta 140ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response); 141ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta 142ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta assertNotNull(entry); 143ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta assertNull(entry.etag); 144ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta assertEqualsWithin(now, entry.ttl, ONE_MINUTE_MILLIS); 145ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta assertEquals(entry.softTtl, entry.ttl); 146ccde61ed8922020f05bd43a80dfcc130c99c00f0Scott Barta } 1473713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1483713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick private void assertEqualsWithin(long expected, long value, long fudgeFactor) { 1493713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick long diff = Math.abs(expected - value); 1503713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertTrue(diff < fudgeFactor); 1513713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick } 1523713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1533713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick private static String rfc1123Date(long millis) { 1543713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz"); 1553713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick return df.format(new Date(millis)); 1563713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick } 1573713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1583713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick // -------------------------- 1593713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1603713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick public void testParseCharset() { 1613713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick // Like the ones we usually see 1623713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Content-Type", "text/plain; charset=utf-8"); 1633713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals("utf-8", HttpHeaderParser.parseCharset(headers)); 1643713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1653713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick // Extra whitespace 1663713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Content-Type", "text/plain; charset=utf-8 "); 1673713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals("utf-8", HttpHeaderParser.parseCharset(headers)); 1683713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1693713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick // Extra parameters 1703713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Content-Type", "text/plain; charset=utf-8; frozzle=bar"); 1713713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals("utf-8", HttpHeaderParser.parseCharset(headers)); 1723713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1733713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick // No Content-Type header 1743713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.clear(); 1753713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers)); 1763713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1773713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick // Empty value 1783713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Content-Type", "text/plain; charset="); 1793713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers)); 1803713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1813713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick // None specified 1823713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Content-Type", "text/plain"); 1833713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers)); 1843713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick 1853713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick // None specified, extra semicolon 1863713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick headers.put("Content-Type", "text/plain;"); 1873713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers)); 1883713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick } 1893713094c56d25e25df2a508dbee4aea869ffdea1Ficus Kirkpatrick} 190