blob: c16d3e810df7219636c2236d0d88411a6d958370 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.net;
import android.support.test.filters.MediumTest;
import org.json.JSONObject;
import org.chromium.base.Log;
import org.chromium.base.PathUtils;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.test.util.Feature;
import org.chromium.net.impl.CronetUrlRequestContext;
import org.chromium.net.test.EmbeddedTestServer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
/**
* Tests for experimental options.
*/
@JNINamespace("cronet")
public class ExperimentalOptionsTest extends CronetTestBase {
private static final String TAG = ExperimentalOptionsTest.class.getSimpleName();
private ExperimentalCronetEngine.Builder mBuilder;
@Override
protected void setUp() throws Exception {
super.setUp();
mBuilder = new ExperimentalCronetEngine.Builder(getContext());
CronetTestUtil.setMockCertVerifierForTesting(
mBuilder, QuicTestServer.createMockCertVerifier());
assertTrue(Http2TestServer.startHttp2TestServer(
getContext(), SERVER_CERT_PEM, SERVER_KEY_PKCS8_PEM));
}
@Override
protected void tearDown() throws Exception {
assertTrue(Http2TestServer.shutdownHttp2TestServer());
super.tearDown();
}
@MediumTest
@Feature({"Cronet"})
@OnlyRunNativeCronet
// Tests that NetLog writes effective experimental options to NetLog.
public void testNetLog() throws Exception {
File directory = new File(PathUtils.getDataDirectory());
File logfile = File.createTempFile("cronet", "json", directory);
JSONObject hostResolverParams = CronetTestUtil.generateHostResolverRules();
JSONObject experimentalOptions =
new JSONObject().put("HostResolverRules", hostResolverParams);
mBuilder.setExperimentalOptions(experimentalOptions.toString());
CronetEngine cronetEngine = mBuilder.build();
cronetEngine.startNetLogToFile(logfile.getPath(), false);
String url = Http2TestServer.getEchoMethodUrl();
TestUrlRequestCallback callback = new TestUrlRequestCallback();
UrlRequest.Builder builder =
cronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor());
UrlRequest urlRequest = builder.build();
urlRequest.start();
callback.blockForDone();
assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
assertEquals("GET", callback.mResponseAsString);
cronetEngine.stopNetLog();
assertFileContainsString(logfile, "HostResolverRules");
assertTrue(logfile.delete());
assertFalse(logfile.exists());
cronetEngine.shutdown();
}
@MediumTest
@Feature({"Cronet"})
@OnlyRunNativeCronet
public void testSetSSLKeyLogFile() throws Exception {
String url = Http2TestServer.getEchoMethodUrl();
File dir = new File(PathUtils.getDataDirectory());
File file = File.createTempFile("ssl_key_log_file", "", dir);
JSONObject experimentalOptions = new JSONObject().put("ssl_key_log_file", file.getPath());
mBuilder.setExperimentalOptions(experimentalOptions.toString());
CronetEngine cronetEngine = mBuilder.build();
TestUrlRequestCallback callback = new TestUrlRequestCallback();
UrlRequest.Builder builder =
cronetEngine.newUrlRequestBuilder(url, callback, callback.getExecutor());
UrlRequest urlRequest = builder.build();
urlRequest.start();
callback.blockForDone();
assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
assertEquals("GET", callback.mResponseAsString);
assertFileContainsString(file, "CLIENT_RANDOM");
assertTrue(file.delete());
assertFalse(file.exists());
cronetEngine.shutdown();
}
// Helper method to assert that file contains content. It retries 5 times
// with a 100ms interval.
private void assertFileContainsString(File file, String content) throws Exception {
boolean contains = false;
for (int i = 0; i < 5; i++) {
contains = fileContainsString(file, content);
if (contains) break;
Log.i(TAG, "Retrying...");
Thread.sleep(100);
}
assertTrue("file content doesn't match", contains);
}
// Returns whether a file contains a particular string.
private boolean fileContainsString(File file, String content) throws IOException {
FileInputStream fileInputStream = null;
Log.i(TAG, "looking for [%s] in %s", content, file.getName());
try {
fileInputStream = new FileInputStream(file);
byte[] data = new byte[(int) file.length()];
fileInputStream.read(data);
String actual = new String(data, "UTF-8");
boolean contains = actual.contains(content);
if (!contains) {
Log.i(TAG, "file content [%s]", actual);
}
return contains;
} catch (FileNotFoundException e) {
// Ignored this exception since the file will only be created when updates are
// flushed to the disk.
Log.i(TAG, "file not found");
} finally {
if (fileInputStream != null) {
fileInputStream.close();
}
}
return false;
}
@MediumTest
@Feature({"Cronet"})
@OnlyRunNativeCronet
// Tests that basic Cronet functionality works when host cache persistence is enabled, and that
// persistence works.
public void testHostCachePersistence() throws Exception {
EmbeddedTestServer testServer = EmbeddedTestServer.createAndStartServer(getContext());
String realUrl = testServer.getURL("/echo?status=200");
URL javaUrl = new URL(realUrl);
String realHost = javaUrl.getHost();
int realPort = javaUrl.getPort();
String testHost = "host-cache-test-host";
String testUrl = new URL("http", testHost, realPort, javaUrl.getPath()).toString();
mBuilder.setStoragePath(getTestStorage(getContext()))
.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK, 0);
// Set a short delay so the pref gets written quickly.
JSONObject staleDns = new JSONObject()
.put("enable", true)
.put("delay_ms", 0)
.put("allow_other_network", true)
.put("persist_to_disk", true)
.put("persist_delay_ms", 0);
JSONObject experimentalOptions = new JSONObject().put("StaleDNS", staleDns);
mBuilder.setExperimentalOptions(experimentalOptions.toString());
CronetUrlRequestContext context = (CronetUrlRequestContext) mBuilder.build();
// Create a HostCache entry for "host-cache-test-host".
nativeWriteToHostCache(context.getUrlRequestContextAdapter(), realHost);
// Do a request for the test URL to make sure it's cached.
TestUrlRequestCallback callback = new TestUrlRequestCallback();
UrlRequest.Builder builder =
context.newUrlRequestBuilder(testUrl, callback, callback.getExecutor());
UrlRequest urlRequest = builder.build();
urlRequest.start();
callback.blockForDone();
assertNull(callback.mError);
assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
// Shut down the context, persisting contents to disk, and build a new one.
context.shutdown();
context = (CronetUrlRequestContext) mBuilder.build();
// Use the test URL without creating a new cache entry first. It should use the persisted
// one.
callback = new TestUrlRequestCallback();
builder = context.newUrlRequestBuilder(testUrl, callback, callback.getExecutor());
urlRequest = builder.build();
urlRequest.start();
callback.blockForDone();
assertNull(callback.mError);
assertEquals(200, callback.mResponseInfo.getHttpStatusCode());
}
// Sets a host cache entry with hostname "host-cache-test-host" and an AddressList containing
// the provided address.
private static native void nativeWriteToHostCache(long adapter, String address);
}