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
17package com.squareup.okhttp.android;
18
19import com.squareup.okhttp.AndroidInternal;
20import com.squareup.okhttp.HttpUrl;
21import com.squareup.okhttp.OkHttpClient;
22import com.squareup.okhttp.OkUrlFactory;
23import com.squareup.okhttp.mockwebserver.MockResponse;
24import com.squareup.okhttp.mockwebserver.MockWebServer;
25import java.io.File;
26import java.io.InputStream;
27import java.net.CacheRequest;
28import java.net.CacheResponse;
29import java.net.ResponseCache;
30import java.net.URI;
31import java.net.URLConnection;
32import java.util.List;
33import java.util.Map;
34import org.junit.After;
35import org.junit.Before;
36import org.junit.Rule;
37import org.junit.Test;
38import org.junit.rules.TemporaryFolder;
39
40import static org.junit.Assert.assertEquals;
41import static org.junit.Assert.assertNotNull;
42import static org.junit.Assert.assertNotSame;
43import static org.junit.Assert.assertNull;
44import static org.junit.Assert.assertSame;
45import static org.junit.Assert.fail;
46
47/**
48 * A port of Android's android.net.http.HttpResponseCacheTest to JUnit4.
49 */
50public final class HttpResponseCacheTest {
51
52  @Rule public TemporaryFolder cacheRule = new TemporaryFolder();
53  @Rule public MockWebServer server = new MockWebServer();
54
55  private File cacheDir;
56  private OkUrlFactory client;
57
58  @Before public void setUp() throws Exception {
59    cacheDir = cacheRule.getRoot();
60    client = new OkUrlFactory(new OkHttpClient());
61  }
62
63  @After public void tearDown() throws Exception {
64    ResponseCache.setDefault(null);
65  }
66
67  @Test public void install() throws Exception {
68    HttpResponseCache installed = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
69    assertNotNull(installed);
70    assertSame(installed, ResponseCache.getDefault());
71    assertSame(installed, HttpResponseCache.getDefault());
72  }
73
74  @Test public void secondEquivalentInstallDoesNothing() throws Exception {
75    HttpResponseCache first = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
76    HttpResponseCache another = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
77    assertSame(first, another);
78  }
79
80  @Test public void installClosesPreviouslyInstalled() throws Exception {
81    HttpResponseCache first = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
82    initializeCache(first);
83
84    HttpResponseCache another = HttpResponseCache.install(cacheDir, 8 * 1024 * 1024);
85    initializeCache(another);
86
87    assertNotSame(first, another);
88    try {
89      first.flush();
90      fail();
91    } catch (IllegalStateException expected) {
92    }
93  }
94
95  @Test public void getInstalledWithWrongTypeInstalled() {
96    ResponseCache.setDefault(new ResponseCache() {
97      @Override
98      public CacheResponse get(URI uri, String requestMethod,
99          Map<String, List<String>> requestHeaders) {
100        return null;
101      }
102
103      @Override
104      public CacheRequest put(URI uri, URLConnection connection) {
105        return null;
106      }
107    });
108    assertNull(HttpResponseCache.getInstalled());
109  }
110
111  @Test public void closeCloses() throws Exception {
112    HttpResponseCache cache = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
113    initializeCache(cache);
114
115    cache.close();
116    try {
117      cache.flush();
118      fail();
119    } catch (IllegalStateException expected) {
120    }
121  }
122
123  @Test public void closeUninstalls() throws Exception {
124    HttpResponseCache cache = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
125    cache.close();
126    assertNull(ResponseCache.getDefault());
127  }
128
129  @Test public void deleteUninstalls() throws Exception {
130    HttpResponseCache cache = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
131    cache.delete();
132    assertNull(ResponseCache.getDefault());
133  }
134
135  /**
136   * Make sure that statistics tracking are wired all the way through the
137   * wrapper class. http://code.google.com/p/android/issues/detail?id=25418
138   */
139  @Test public void statisticsTracking() throws Exception {
140    HttpResponseCache cache = HttpResponseCache.install(cacheDir, 10 * 1024 * 1024);
141
142    server.enqueue(new MockResponse()
143        .addHeader("Cache-Control: max-age=60")
144        .setBody("A"));
145
146    URLConnection c1 = openUrl(server.url("/"));
147
148    InputStream inputStream = c1.getInputStream();
149    assertEquals('A', inputStream.read());
150    inputStream.close();
151    assertEquals(1, cache.getRequestCount());
152    assertEquals(1, cache.getNetworkCount());
153    assertEquals(0, cache.getHitCount());
154
155    URLConnection c2 = openUrl(server.url("/"));
156    assertEquals('A', c2.getInputStream().read());
157
158    URLConnection c3 = openUrl(server.url("/"));
159    assertEquals('A', c3.getInputStream().read());
160    assertEquals(3, cache.getRequestCount());
161    assertEquals(1, cache.getNetworkCount());
162    assertEquals(2, cache.getHitCount());
163  }
164
165  // This mimics the Android HttpHandler, which is found in the com.squareup.okhttp package.
166  private URLConnection openUrl(HttpUrl url) {
167    ResponseCache responseCache = ResponseCache.getDefault();
168    AndroidInternal.setResponseCache(client, responseCache);
169    return client.open(url.url());
170  }
171
172  private void initializeCache(HttpResponseCache cache) {
173    // Ensure the cache is initialized, otherwise various methods are no-ops.
174    cache.size();
175  }
176}
177