1 // Copyright 2016 The Chromium Authors. All rights reserved.
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 org.junit.Assert.assertEquals;
8 import static org.junit.Assert.assertTrue;
9 
10 import static org.chromium.net.CronetTestRule.getContext;
11 import static org.chromium.net.CronetTestRule.getTestStorage;
12 
13 import android.support.test.runner.AndroidJUnit4;
14 
15 import androidx.test.filters.SmallTest;
16 
17 import org.junit.After;
18 import org.junit.Before;
19 import org.junit.Rule;
20 import org.junit.Test;
21 import org.junit.runner.RunWith;
22 
23 import org.chromium.base.FileUtils;
24 import org.chromium.base.PathUtils;
25 import org.chromium.base.test.util.Feature;
26 import org.chromium.net.CronetTestRule.OnlyRunNativeCronet;
27 
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.FileOutputStream;
32 import java.io.FileReader;
33 import java.util.Arrays;
34 
35 /**
36  * Test CronetEngine disk storage.
37  */
38 @RunWith(AndroidJUnit4.class)
39 public class DiskStorageTest {
40     @Rule
41     public final CronetTestRule mTestRule = new CronetTestRule();
42 
43     private String mReadOnlyStoragePath;
44 
45     @Before
setUp()46     public void setUp() throws Exception {
47         System.loadLibrary("cronet_tests");
48         assertTrue(NativeTestServer.startNativeTestServer(getContext()));
49     }
50 
51     @After
tearDown()52     public void tearDown() throws Exception {
53         if (mReadOnlyStoragePath != null) {
54             FileUtils.recursivelyDeleteFile(new File(mReadOnlyStoragePath), FileUtils.DELETE_ALL);
55         }
56         NativeTestServer.shutdownNativeTestServer();
57     }
58 
59     @Test
60     @SmallTest
61     @Feature({"Cronet"})
62     @OnlyRunNativeCronet
63     // Crashing on Android Cronet Builder, see crbug.com/601409.
testReadOnlyStorageDirectory()64     public void testReadOnlyStorageDirectory() throws Exception {
65         mReadOnlyStoragePath = PathUtils.getDataDirectory() + "/read_only";
66         File readOnlyStorage = new File(mReadOnlyStoragePath);
67         assertTrue(readOnlyStorage.mkdir());
68         // Setting the storage directory as readonly has no effect.
69         assertTrue(readOnlyStorage.setReadOnly());
70         ExperimentalCronetEngine.Builder builder =
71                 new ExperimentalCronetEngine.Builder(getContext());
72         builder.setStoragePath(mReadOnlyStoragePath);
73         builder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK, 1024 * 1024);
74 
75         CronetEngine cronetEngine = builder.build();
76         TestUrlRequestCallback callback = new TestUrlRequestCallback();
77         String url = NativeTestServer.getFileURL("/cacheable.txt");
78         UrlRequest.Builder requestBuilder =
79                 cronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor());
80         UrlRequest urlRequest = requestBuilder.build();
81         urlRequest.start();
82         callback.blockForDone();
83         assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
84         cronetEngine.shutdown();
85         FileInputStream newVersionFile = null;
86         // Make sure that version file is in readOnlyStoragePath.
87         File versionFile = new File(mReadOnlyStoragePath + "/version");
88         try {
89             newVersionFile = new FileInputStream(versionFile);
90             byte[] buffer = new byte[] {0, 0, 0, 0};
91             int bytesRead = newVersionFile.read(buffer, 0, 4);
92             assertEquals(4, bytesRead);
93             assertTrue(Arrays.equals(new byte[] {1, 0, 0, 0}, buffer));
94         } finally {
95             if (newVersionFile != null) {
96                 newVersionFile.close();
97             }
98         }
99         File diskCacheDir = new File(mReadOnlyStoragePath + "/disk_cache");
100         assertTrue(diskCacheDir.exists());
101         File prefsDir = new File(mReadOnlyStoragePath + "/prefs");
102         assertTrue(prefsDir.exists());
103     }
104 
105     @Test
106     @SmallTest
107     @Feature({"Cronet"})
108     @OnlyRunNativeCronet
109     // Crashing on Android Cronet Builder, see crbug.com/601409.
testPurgeOldVersion()110     public void testPurgeOldVersion() throws Exception {
111         String testStorage = getTestStorage(getContext());
112         File versionFile = new File(testStorage + "/version");
113         FileOutputStream versionOut = null;
114         try {
115             versionOut = new FileOutputStream(versionFile);
116             versionOut.write(new byte[] {0, 0, 0, 0}, 0, 4);
117         } finally {
118             if (versionOut != null) {
119                 versionOut.close();
120             }
121         }
122         File oldPrefsFile = new File(testStorage + "/local_prefs.json");
123         FileOutputStream oldPrefsOut = null;
124         try {
125             oldPrefsOut = new FileOutputStream(oldPrefsFile);
126             String dummy = "dummy content";
127             oldPrefsOut.write(dummy.getBytes(), 0, dummy.length());
128         } finally {
129             if (oldPrefsOut != null) {
130                 oldPrefsOut.close();
131             }
132         }
133 
134         ExperimentalCronetEngine.Builder builder =
135                 new ExperimentalCronetEngine.Builder(getContext());
136         builder.setStoragePath(getTestStorage(getContext()));
137         builder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK, 1024 * 1024);
138 
139         CronetEngine cronetEngine = builder.build();
140         TestUrlRequestCallback callback = new TestUrlRequestCallback();
141         String url = NativeTestServer.getFileURL("/cacheable.txt");
142         UrlRequest.Builder requestBuilder =
143                 cronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor());
144         UrlRequest urlRequest = requestBuilder.build();
145         urlRequest.start();
146         callback.blockForDone();
147         assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
148         cronetEngine.shutdown();
149         FileInputStream newVersionFile = null;
150         try {
151             newVersionFile = new FileInputStream(versionFile);
152             byte[] buffer = new byte[] {0, 0, 0, 0};
153             int bytesRead = newVersionFile.read(buffer, 0, 4);
154             assertEquals(4, bytesRead);
155             assertTrue(Arrays.equals(new byte[] {1, 0, 0, 0}, buffer));
156         } finally {
157             if (newVersionFile != null) {
158                 newVersionFile.close();
159             }
160         }
161         oldPrefsFile = new File(testStorage + "/local_prefs.json");
162         assertTrue(!oldPrefsFile.exists());
163         File diskCacheDir = new File(testStorage + "/disk_cache");
164         assertTrue(diskCacheDir.exists());
165         File prefsDir = new File(testStorage + "/prefs");
166         assertTrue(prefsDir.exists());
167     }
168 
169     @Test
170     @SmallTest
171     @Feature({"Cronet"})
172     @OnlyRunNativeCronet
173     // Tests that if cache version is current, Cronet does not purge the directory.
testCacheVersionCurrent()174     public void testCacheVersionCurrent() throws Exception {
175         // Initialize a CronetEngine and shut it down.
176         ExperimentalCronetEngine.Builder builder =
177                 new ExperimentalCronetEngine.Builder(getContext());
178         builder.setStoragePath(getTestStorage(getContext()));
179         builder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK, 1024 * 1024);
180 
181         CronetEngine cronetEngine = builder.build();
182         TestUrlRequestCallback callback = new TestUrlRequestCallback();
183         String url = NativeTestServer.getFileURL("/cacheable.txt");
184         UrlRequest.Builder requestBuilder =
185                 cronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor());
186         UrlRequest urlRequest = requestBuilder.build();
187         urlRequest.start();
188         callback.blockForDone();
189         assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
190         cronetEngine.shutdown();
191 
192         // Create a dummy file in storage directory.
193         String testStorage = getTestStorage(getContext());
194         File dummyFile = new File(testStorage + "/dummy.json");
195         FileOutputStream dummyFileOut = null;
196         String dummyContent = "dummy content";
197         try {
198             dummyFileOut = new FileOutputStream(dummyFile);
199             dummyFileOut.write(dummyContent.getBytes(), 0, dummyContent.length());
200         } finally {
201             if (dummyFileOut != null) {
202                 dummyFileOut.close();
203             }
204         }
205 
206         // Creates a new CronetEngine and make a request.
207         CronetEngine engine = builder.build();
208         TestUrlRequestCallback callback2 = new TestUrlRequestCallback();
209         String url2 = NativeTestServer.getFileURL("/cacheable.txt");
210         UrlRequest.Builder requestBuilder2 =
211                 engine.newUrlRequestBuilder(url2, callback2, callback2.getExecutor());
212         UrlRequest urlRequest2 = requestBuilder2.build();
213         urlRequest2.start();
214         callback2.blockForDone();
215         assertEquals(200, callback2.mResponseInfo.getHttpStatusCode());
216         engine.shutdown();
217         // Dummy file still exists.
218         BufferedReader reader = new BufferedReader(new FileReader(dummyFile));
219         StringBuilder stringBuilder = new StringBuilder();
220         String line;
221         while ((line = reader.readLine()) != null) {
222             stringBuilder.append(line);
223         }
224         reader.close();
225         assertEquals(dummyContent, stringBuilder.toString());
226         File diskCacheDir = new File(testStorage + "/disk_cache");
227         assertTrue(diskCacheDir.exists());
228         File prefsDir = new File(testStorage + "/prefs");
229         assertTrue(prefsDir.exists());
230     }
231 }
232