1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.net; 6 7 import static com.google.common.truth.Truth.assertThat; 8 9 import static org.junit.Assert.assertThrows; 10 11 import static org.chromium.net.CronetTestRule.getTestStorage; 12 import static org.chromium.net.truth.UrlResponseInfoSubject.assertThat; 13 14 import androidx.test.ext.junit.runners.AndroidJUnit4; 15 import androidx.test.filters.SmallTest; 16 import com.android.testutils.SkipPresubmit; 17 18 import org.junit.After; 19 import org.junit.Before; 20 import org.junit.Rule; 21 import org.junit.Test; 22 import org.junit.runner.RunWith; 23 24 import org.chromium.base.PathUtils; 25 import org.chromium.base.test.util.DoNotBatch; 26 import org.chromium.net.CronetTestRule.CronetImplementation; 27 import org.chromium.net.CronetTestRule.IgnoreFor; 28 29 import java.io.BufferedReader; 30 import java.io.File; 31 import java.io.FileInputStream; 32 import java.io.FileOutputStream; 33 import java.io.FileReader; 34 35 /** Test CronetEngine disk storage. */ 36 @DoNotBatch(reason = "crbug/1459563") 37 @RunWith(AndroidJUnit4.class) 38 @IgnoreFor( 39 implementations = {CronetImplementation.FALLBACK}, 40 reason = "The fallback implementation doesn't support on-disk caches") 41 public class DiskStorageTest { 42 @Rule public final CronetTestRule mTestRule = CronetTestRule.withManualEngineStartup(); 43 44 private String mReadOnlyStoragePath; 45 46 @Before setUp()47 public void setUp() throws Exception { 48 System.loadLibrary("cronet_tests"); 49 assertThat( 50 NativeTestServer.startNativeTestServer( 51 mTestRule.getTestFramework().getContext())) 52 .isTrue(); 53 } 54 55 @After tearDown()56 public void tearDown() throws Exception { 57 if (mReadOnlyStoragePath != null) { 58 FileUtils.recursivelyDeleteFile(new File(mReadOnlyStoragePath)); 59 } 60 NativeTestServer.shutdownNativeTestServer(); 61 } 62 63 @Test 64 @SmallTest 65 // Crashing on Android Cronet Builder, see crbug.com/601409. testReadOnlyStorageDirectory()66 public void testReadOnlyStorageDirectory() throws Exception { 67 mReadOnlyStoragePath = PathUtils.getDataDirectory() + "/read_only"; 68 File readOnlyStorage = new File(mReadOnlyStoragePath); 69 assertThat(readOnlyStorage.mkdir()).isTrue(); 70 // Setting the storage directory as readonly has no effect. 71 assertThat(readOnlyStorage.setReadOnly()).isTrue(); 72 mTestRule 73 .getTestFramework() 74 .applyEngineBuilderPatch( 75 (builder) -> { 76 builder.setStoragePath(mReadOnlyStoragePath); 77 builder.enableHttpCache( 78 CronetEngine.Builder.HTTP_CACHE_DISK, 1024 * 1024); 79 }); 80 81 CronetEngine cronetEngine = mTestRule.getTestFramework().startEngine(); 82 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 83 String url = NativeTestServer.getFileURL("/cacheable.txt"); 84 UrlRequest.Builder requestBuilder = 85 cronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor()); 86 UrlRequest urlRequest = requestBuilder.build(); 87 urlRequest.start(); 88 callback.blockForDone(); 89 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 90 cronetEngine.shutdown(); 91 FileInputStream newVersionFile = null; 92 // Make sure that version file is in readOnlyStoragePath. 93 File versionFile = new File(mReadOnlyStoragePath + "/version"); 94 try { 95 newVersionFile = new FileInputStream(versionFile); 96 byte[] buffer = new byte[] {0, 0, 0, 0}; 97 int bytesRead = newVersionFile.read(buffer, 0, 4); 98 assertThat(bytesRead).isEqualTo(4); 99 assertThat(buffer).isEqualTo(new byte[] {1, 0, 0, 0}); 100 } finally { 101 if (newVersionFile != null) { 102 newVersionFile.close(); 103 } 104 } 105 File diskCacheDir = new File(mReadOnlyStoragePath + "/disk_cache"); 106 assertThat(diskCacheDir.exists()).isTrue(); 107 File prefsDir = new File(mReadOnlyStoragePath + "/prefs"); 108 assertThat(prefsDir.exists()).isTrue(); 109 } 110 111 @Test 112 @SmallTest 113 @SkipPresubmit(reason = "b/293141085 Tests that enable disk cache are flaky") 114 // Crashing on Android Cronet Builder, see crbug.com/601409. testPurgeOldVersion()115 public void testPurgeOldVersion() throws Exception { 116 String testStorage = getTestStorage(mTestRule.getTestFramework().getContext()); 117 File versionFile = new File(testStorage + "/version"); 118 FileOutputStream versionOut = null; 119 try { 120 versionOut = new FileOutputStream(versionFile); 121 versionOut.write(new byte[] {0, 0, 0, 0}, 0, 4); 122 } finally { 123 if (versionOut != null) { 124 versionOut.close(); 125 } 126 } 127 File oldPrefsFile = new File(testStorage + "/local_prefs.json"); 128 FileOutputStream oldPrefsOut = null; 129 try { 130 oldPrefsOut = new FileOutputStream(oldPrefsFile); 131 String sample = "sample content"; 132 oldPrefsOut.write(sample.getBytes(), 0, sample.length()); 133 } finally { 134 if (oldPrefsOut != null) { 135 oldPrefsOut.close(); 136 } 137 } 138 139 mTestRule 140 .getTestFramework() 141 .applyEngineBuilderPatch( 142 (builder) -> { 143 builder.setStoragePath( 144 getTestStorage(mTestRule.getTestFramework().getContext())); 145 builder.enableHttpCache( 146 CronetEngine.Builder.HTTP_CACHE_DISK, 1024 * 1024); 147 }); 148 149 CronetEngine cronetEngine = mTestRule.getTestFramework().startEngine(); 150 151 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 152 String url = NativeTestServer.getFileURL("/cacheable.txt"); 153 UrlRequest.Builder requestBuilder = 154 cronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor()); 155 UrlRequest urlRequest = requestBuilder.build(); 156 urlRequest.start(); 157 callback.blockForDone(); 158 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 159 cronetEngine.shutdown(); 160 FileInputStream newVersionFile = null; 161 try { 162 newVersionFile = new FileInputStream(versionFile); 163 byte[] buffer = new byte[] {0, 0, 0, 0}; 164 int bytesRead = newVersionFile.read(buffer, 0, 4); 165 assertThat(bytesRead).isEqualTo(4); 166 assertThat(buffer).isEqualTo(new byte[] {1, 0, 0, 0}); 167 } finally { 168 if (newVersionFile != null) { 169 newVersionFile.close(); 170 } 171 } 172 oldPrefsFile = new File(testStorage + "/local_prefs.json"); 173 assertThat(!oldPrefsFile.exists()).isTrue(); 174 File diskCacheDir = new File(testStorage + "/disk_cache"); 175 assertThat(diskCacheDir.exists()).isTrue(); 176 File prefsDir = new File(testStorage + "/prefs"); 177 assertThat(prefsDir.exists()).isTrue(); 178 } 179 180 @Test 181 @SmallTest 182 @SkipPresubmit(reason = "b/293141085 Tests that enable disk cache are flaky") 183 // Tests that if cache version is current, Cronet does not purge the directory. testCacheVersionCurrent()184 public void testCacheVersionCurrent() throws Exception { 185 // Initialize a CronetEngine and shut it down. 186 ExperimentalCronetEngine.Builder builder = 187 mTestRule 188 .getTestFramework() 189 .createNewSecondaryBuilder(mTestRule.getTestFramework().getContext()); 190 builder.setStoragePath(getTestStorage(mTestRule.getTestFramework().getContext())); 191 builder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK, 1024 * 1024); 192 193 CronetEngine cronetEngine = builder.build(); 194 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 195 String url = NativeTestServer.getFileURL("/cacheable.txt"); 196 UrlRequest.Builder requestBuilder = 197 cronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor()); 198 UrlRequest urlRequest = requestBuilder.build(); 199 urlRequest.start(); 200 callback.blockForDone(); 201 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 202 cronetEngine.shutdown(); 203 204 // Create a sample file in storage directory. 205 String testStorage = getTestStorage(mTestRule.getTestFramework().getContext()); 206 File sampleFile = new File(testStorage + "/sample.json"); 207 FileOutputStream sampleFileOut = null; 208 String sampleContent = "sample content"; 209 try { 210 sampleFileOut = new FileOutputStream(sampleFile); 211 sampleFileOut.write(sampleContent.getBytes(), 0, sampleContent.length()); 212 } finally { 213 if (sampleFileOut != null) { 214 sampleFileOut.close(); 215 } 216 } 217 218 // Creates a new CronetEngine and make a request. 219 CronetEngine engine = builder.build(); 220 TestUrlRequestCallback callback2 = new TestUrlRequestCallback(); 221 String url2 = NativeTestServer.getFileURL("/cacheable.txt"); 222 UrlRequest.Builder requestBuilder2 = 223 engine.newUrlRequestBuilder(url2, callback2, callback2.getExecutor()); 224 UrlRequest urlRequest2 = requestBuilder2.build(); 225 urlRequest2.start(); 226 callback2.blockForDone(); 227 assertThat(callback2.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 228 engine.shutdown(); 229 // Sample file still exists. 230 BufferedReader reader = new BufferedReader(new FileReader(sampleFile)); 231 StringBuilder stringBuilder = new StringBuilder(); 232 String line; 233 while ((line = reader.readLine()) != null) { 234 stringBuilder.append(line); 235 } 236 reader.close(); 237 assertThat(stringBuilder.toString()).isEqualTo(sampleContent); 238 File diskCacheDir = new File(testStorage + "/disk_cache"); 239 assertThat(diskCacheDir.exists()).isTrue(); 240 File prefsDir = new File(testStorage + "/prefs"); 241 assertThat(prefsDir.exists()).isTrue(); 242 } 243 244 @Test 245 @SmallTest 246 // Tests that enableHttpCache throws if storage path not set testEnableHttpCacheThrowsIfStoragePathNotSet()247 public void testEnableHttpCacheThrowsIfStoragePathNotSet() throws Exception { 248 // Initialize a CronetEngine and shut it down. 249 mTestRule 250 .getTestFramework() 251 .applyEngineBuilderPatch( 252 (builder) -> { 253 assertThrows( 254 IllegalArgumentException.class, 255 () -> 256 builder.enableHttpCache( 257 CronetEngine.Builder.HTTP_CACHE_DISK, 258 1024 * 1024)); 259 }); 260 261 CronetEngine cronetEngine = mTestRule.getTestFramework().startEngine(); 262 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 263 String url = NativeTestServer.getFileURL("/cacheable.txt"); 264 UrlRequest.Builder requestBuilder = 265 cronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor()); 266 UrlRequest urlRequest = requestBuilder.build(); 267 urlRequest.start(); 268 callback.blockForDone(); 269 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 270 cronetEngine.shutdown(); 271 272 String testStorage = getTestStorage(mTestRule.getTestFramework().getContext()); 273 File diskCacheDir = new File(testStorage + "/disk_cache"); 274 assertThat(diskCacheDir.exists()).isFalse(); 275 File prefsDir = new File(testStorage + "/prefs"); 276 assertThat(prefsDir.exists()).isFalse(); 277 } 278 279 @Test 280 @SmallTest 281 // Tests that prefs file is created even if httpcache isn't enabled testPrefsFileCreatedWithoutHttpCache()282 public void testPrefsFileCreatedWithoutHttpCache() throws Exception { 283 // Initialize a CronetEngine and shut it down. 284 String testStorage = getTestStorage(mTestRule.getTestFramework().getContext()); 285 mTestRule 286 .getTestFramework() 287 .applyEngineBuilderPatch((builder) -> builder.setStoragePath(testStorage)); 288 289 CronetEngine cronetEngine = mTestRule.getTestFramework().startEngine(); 290 TestUrlRequestCallback callback = new TestUrlRequestCallback(); 291 String url = NativeTestServer.getFileURL("/cacheable.txt"); 292 UrlRequest.Builder requestBuilder = 293 cronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor()); 294 UrlRequest urlRequest = requestBuilder.build(); 295 urlRequest.start(); 296 callback.blockForDone(); 297 assertThat(callback.getResponseInfoWithChecks()).hasHttpStatusCodeThat().isEqualTo(200); 298 cronetEngine.shutdown(); 299 300 File diskCacheDir = new File(testStorage + "/disk_cache"); 301 assertThat(diskCacheDir.exists()).isFalse(); 302 File prefsDir = new File(testStorage + "/prefs"); 303 assertThat(prefsDir.exists()).isTrue(); 304 } 305 } 306