blob: ce5aa03438cc5b1abc4c215710a0e09b2f47eca1 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.cts.deviceowner.proxy;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.ProxySelector;
import java.net.Socket;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import android.net.ProxyInfo;
import android.net.Uri;
public class PacProxyTest extends BaseProxyTest {
private PacFileServer mPacServer;
/**
* PAC file that always returns DIRECT.
*/
private static final String DIRECT_PAC = "function FindProxyForURL(url, host)" +
"{" +
" return \"DIRECT\";" +
"}";
/**
* PAC file that returns three proxies, the third is DIRECT.
*/
private static final String LOCAL_PLUS_DIRECT_PAC = "function FindProxyForURL(url, host)" +
"{" +
" return \"PROXY localhost:8080; PROXY localhost:8081; DIRECT \";" +
"}";
/**
* PAC file that returns either proxy or DIRECT depending on the host.
*
* The return result is a bogus proxy that demonstrates that the input variables
* are passed through correctly.
*/
private static final String HOST_PAC = "function FindProxyForURL(url, host)" +
"{" +
" if (host == \"testhost\") {" +
" return \"PROXY localhost:8080\";" +
" }" +
" return \"DIRECT\";" +
"}";
/**
* PAC file that returns either proxy or DIRECT depending on the URL.
*
* The return result is a bogus proxy that demonstrates that the input variables
* are passed through correctly.
*/
private static final String URL_PAC = "function FindProxyForURL(url, host)\n" +
"{" +
" if (url == \"http://localhost/my/url/\") {" +
" return \"PROXY localhost:8080\";" +
" } " +
" return \"DIRECT\";" +
"}";
/**
* Wait for the PacFileServer to tell us it has had a successful
* HTTP request and responded with the PAC file we set.
*/
private void waitForPacDownload() throws InterruptedException {
boolean success = mPacServer.awaitPacSent(30, TimeUnit.SECONDS);
assertTrue("Took too long to set PAC", success);
}
@Override
protected void setUp() throws Exception {
super.setUp();
mPacServer = new PacFileServer(null);
mPacServer.startServer();
mProxy = null;
}
@Override
protected void tearDown() throws Exception {
try {
mPacServer.stopServer();
} finally {
super.tearDown();
}
}
private void setPacURLAndWaitForDownload() throws Exception {
Uri pacProxyUri = Uri.parse(mPacServer.getPacURL());
ProxyInfo proxy = ProxyInfo.buildPacProxy(pacProxyUri);
assertTrue("No broadcast after setting proxy", setProxyAndWaitForBroadcast(proxy));
assertTrue("Current Proxy " + mProxy, isCorrectPacProxy(pacProxyUri));
waitForPacDownload();
}
/**
* Make sure that the PAC file can be set and it downloads it
* from the local HTTP server we are hosting.
*/
public void testFileLoaded() throws Exception {
mPacServer.setPacFile(DIRECT_PAC);
setPacURLAndWaitForDownload();
}
/**
* Make sure when we set the PAC file URL we get a broadcast
* containing the proxy info.
*/
public void testBroadcast() throws Exception {
mPacServer.setPacFile(DIRECT_PAC);
setPacURLAndWaitForDownload();
assertNotNull("Broadcast must contain proxy", mProxy);
assertEquals("Proxy must contain PAC URL", mPacServer.getPacURL(),
mProxy.getPacFileUrl().toString());
}
/**
* Make sure that we also get a broadcast after we clear the
* PAC proxy settings.
*/
public void testClearBroadcast() throws Exception {
testBroadcast();
assertTrue("No broadcast after clearing proxy.", clearProxyAndWaitForBroadcast());
assertTrue(isProxyEmpty());
}
/**
* Verify that the locally-hosted android backup proxy is up and
* running.
* Android hosts a proxy server that provides legacy support for apps that
* don't use the apache HTTP stack, but still read the static proxy
* settings. The static settings point to a server that will handle
* the PAC parsing for them.
*/
public void testProxyIsUp() throws Exception {
testBroadcast();
assertNotNull("Broadcast must contain proxy", mProxy);
try {
Socket s = new Socket(mProxy.getHost(), mProxy.getPort());
assertTrue("Must connect to proxy", s.isConnected());
s.close();
} catch (UnknownHostException e) {
fail("Proxy contained invalid host - " + mProxy.getHost() + ":" + mProxy.getPort());
} catch (IOException e) {
fail("Unable to connect to proxy - " + mProxy.getHost() + ":" + mProxy.getPort());
}
}
/**
* The local legacy proxy described above needs to support HTTP CONNECT
* requests where data should be passed through without interference.
* This test hosts a socket and uses this functionality to connect through
* the proxy and pass data back and forth. See PassthroughTestHelper for
* more details.
*/
public void testProxyPassthrough() throws Exception {
mPacServer.setPacFile(DIRECT_PAC);
setPacURLAndWaitForDownload();
waitForSetProxySysProp();
PassthroughTestHelper ptt = new PassthroughTestHelper(mProxy);
ptt.runTest();
}
/**
* Verify that for a simple PAC that returns direct the
* result is direct.
*/
public void testDirect() throws Exception {
testBroadcast();
waitForSetProxySysProp();
URI uri = new URI("http://localhost/test/my/url");
ProxySelector selector = ProxySelector.getDefault();
List<Proxy> list = selector.select(uri);
assertEquals("Proxy must be direct", newArrayList(Proxy.NO_PROXY), list);
}
/**
* Test a PAC file that returns a list of proxies, including one direct.
*/
public void testLocalPlusDirect() throws Exception {
mPacServer.setPacFile(LOCAL_PLUS_DIRECT_PAC);
setPacURLAndWaitForDownload();
waitForSetProxySysProp();
URI uri = new URI("http://localhost/test/my/url");
ProxySelector selector = ProxySelector.getDefault();
List<Proxy> list = selector.select(uri);
assertEquals("Must return multiple proxies", newArrayList(
new Proxy(Type.HTTP, InetSocketAddress.createUnresolved("localhost", 8080)),
new Proxy(Type.HTTP, InetSocketAddress.createUnresolved("localhost", 8081)),
Proxy.NO_PROXY), list);
}
/**
* Tests a PAC file that returns different proxies depending on
* the host that is being accessed.
*/
public void testHostPassthrough() throws Exception {
mPacServer.setPacFile(HOST_PAC);
setPacURLAndWaitForDownload();
waitForSetProxySysProp();
String host = "testhost";
URI uri = new URI("http://" + host + "/test/my/url");
ProxySelector selector = ProxySelector.getDefault();
List<Proxy> list = selector.select(uri);
assertEquals("Proxy must have correct port", newArrayList(
new Proxy(Type.HTTP, InetSocketAddress.createUnresolved("localhost", 8080))),
list);
}
/**
* Tests a PAC file that returns different proxies depending on
* the url that is being accessed.
*/
public void testUrlPassthrough() throws Exception {
mPacServer.setPacFile(URL_PAC);
setPacURLAndWaitForDownload();
waitForSetProxySysProp();
URI uri = new URI("http://localhost/my/url/");
ProxySelector selector = ProxySelector.getDefault();
List<Proxy> list = selector.select(uri);
assertEquals("Correct URL returns proxy", newArrayList(
new Proxy(Type.HTTP, InetSocketAddress.createUnresolved("localhost", 8080))),
list);
uri = new URI("http://localhost/not/my/url/");
list = selector.select(uri);
assertEquals("Incorrect URL should return DIRECT",
newArrayList(Proxy.NO_PROXY), list);
}
}