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