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
58e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru    public void testParseCacheHeaders_headersSet() {
59e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru        headers.put("MyCustomHeader", "42");
60e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru
61e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru        Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
62e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru
63e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru        assertNotNull(entry);
64e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru        assertNotNull(entry.responseHeaders);
65e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru        assertEquals(1, entry.responseHeaders.size());
66e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru        assertEquals("42", entry.responseHeaders.get("MyCustomHeader"));
67e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru    }
68e48f4430bfd3030350aa5ba827b449c37e2fadc9Jean-Baptiste Queru
69d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public void testParseCacheHeaders_etag() {
70d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("ETag", "Yow!");
71d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
72d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
73d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
74d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertNotNull(entry);
75d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals("Yow!", entry.etag);
76d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
77d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
78d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public void testParseCacheHeaders_normalExpire() {
79d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        long now = System.currentTimeMillis();
80d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Date", rfc1123Date(now));
81d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS));
82d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
83d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
84d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
85d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertNotNull(entry);
86d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertNull(entry.etag);
87d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEqualsWithin(entry.serverDate, now, ONE_MINUTE_MILLIS);
88d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertTrue(entry.softTtl >= (now + ONE_HOUR_MILLIS));
89d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertTrue(entry.ttl == entry.softTtl);
90d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
91d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
92d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public void testParseCacheHeaders_expiresInPast() {
93d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        long now = System.currentTimeMillis();
94d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Date", rfc1123Date(now));
95d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Expires", rfc1123Date(now - ONE_HOUR_MILLIS));
96d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
97d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
98d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
99d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertNotNull(entry);
100d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertNull(entry.etag);
101d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEqualsWithin(entry.serverDate, now, ONE_MINUTE_MILLIS);
102d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals(0, entry.ttl);
103d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals(0, entry.softTtl);
104d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
105d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
106d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public void testParseCacheHeaders_serverRelative() {
107d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
108d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        long now = System.currentTimeMillis();
109d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        // Set "current" date as one hour in the future
110d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Date", rfc1123Date(now + ONE_HOUR_MILLIS));
111d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        // TTL four hours in the future, so should be three hours from now
112d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Expires", rfc1123Date(now + 4 * ONE_HOUR_MILLIS));
113d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
114d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
115d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
116d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEqualsWithin(now + 3 * ONE_HOUR_MILLIS, entry.ttl, ONE_MINUTE_MILLIS);
117d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals(entry.softTtl, entry.ttl);
118d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
119d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
120d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public void testParseCacheHeaders_cacheControlOverridesExpires() {
121d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        long now = System.currentTimeMillis();
122d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Date", rfc1123Date(now));
123d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS));
124d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Cache-Control", "public, max-age=86400");
125d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
126d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
127d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
128d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertNotNull(entry);
129d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertNull(entry.etag);
130d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEqualsWithin(now + 24 * ONE_HOUR_MILLIS, entry.ttl, ONE_MINUTE_MILLIS);
131d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals(entry.softTtl, entry.ttl);
132d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
133d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
134d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public void testParseCacheHeaders_cacheControlNoCache() {
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", "no-cache");
139d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
140d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
141d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
142d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertNull(entry);
143d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
144d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
145d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public void testParseCacheHeaders_cacheControlMustRevalidate() {
146d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        long now = System.currentTimeMillis();
147d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Date", rfc1123Date(now));
148d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Expires", rfc1123Date(now + ONE_HOUR_MILLIS));
149d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Cache-Control", "must-revalidate");
150d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
151d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
152d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
153d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertNotNull(entry);
154d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertNull(entry.etag);
155d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEqualsWithin(now, entry.ttl, ONE_MINUTE_MILLIS);
156d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals(entry.softTtl, entry.ttl);
157d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
158d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
159d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    private void assertEqualsWithin(long expected, long value, long fudgeFactor) {
160d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        long diff = Math.abs(expected - value);
161d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertTrue(diff < fudgeFactor);
162d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
163d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
164d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    private static String rfc1123Date(long millis) {
165d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
166d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        return df.format(new Date(millis));
167d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
168d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
169d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    // --------------------------
170d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
171d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    public void testParseCharset() {
172d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        // Like the ones we usually see
173d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Content-Type", "text/plain; charset=utf-8");
174d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals("utf-8", HttpHeaderParser.parseCharset(headers));
175d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
176d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        // Extra whitespace
177d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Content-Type", "text/plain;    charset=utf-8 ");
178d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals("utf-8", HttpHeaderParser.parseCharset(headers));
179d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
180d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        // Extra parameters
181d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Content-Type", "text/plain; charset=utf-8; frozzle=bar");
182d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals("utf-8", HttpHeaderParser.parseCharset(headers));
183d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
184d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        // No Content-Type header
185d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.clear();
186d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers));
187d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
188d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        // Empty value
189d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Content-Type", "text/plain; charset=");
190d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers));
191d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
192d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        // None specified
193d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Content-Type", "text/plain");
194d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers));
195d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru
196d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        // None specified, extra semicolon
197d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        headers.put("Content-Type", "text/plain;");
198d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru        assertEquals("ISO-8859-1", HttpHeaderParser.parseCharset(headers));
199d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru    }
200d56b88ae161057e848e7410d1b9ce5b0b8c427fcJean-Baptiste Queru}
201