1// Copyright (c) 2012 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/**
6 * Test suite for Android's default ProxySelector implementation. The purpose of these tests
7 * is to check that the behaviour of the ProxySelector implementation matches what we have
8 * implemented in net/proxy/proxy_config_service_android.cc.
9 *
10 * IMPORTANT: These test cases are generated from net/android/tools/proxy_test_cases.py, so if any
11 * of these tests fail, please be sure to edit that file and regenerate the test cases here and also
12 * in net/proxy/proxy_config_service_android_unittests.cc if required.
13 */
14
15package org.chromium.net;
16
17import android.test.InstrumentationTestCase;
18import android.test.suitebuilder.annotation.SmallTest;
19
20import java.net.Proxy;
21import java.net.ProxySelector;
22import java.net.URI;
23import java.net.URISyntaxException;
24import java.util.List;
25import java.util.Properties;
26
27import org.chromium.base.test.util.Feature;
28
29public class AndroidProxySelectorTest extends InstrumentationTestCase {
30    Properties mProperties;
31
32    public AndroidProxySelectorTest() {
33        // Start with a clean slate in case there is a system proxy configured.
34        mProperties = new Properties();
35    }
36
37    @Override
38    public void setUp() {
39        System.setProperties(mProperties);
40    }
41
42    static String toString(Proxy proxy) {
43        if (proxy == Proxy.NO_PROXY)
44            return "DIRECT";
45        // java.net.Proxy only knows about http and socks proxies.
46        Proxy.Type type = proxy.type();
47        switch (type) {
48        case HTTP: return "PROXY " + proxy.address().toString();
49        case SOCKS: return "SOCKS5 " + proxy.address().toString();
50        case DIRECT: return "DIRECT";
51        default:
52            // If a new proxy type is supported in future, add a case to match it.
53            fail("Unknown proxy type" + type);
54            return "unknown://";
55        }
56    }
57
58    static String toString(List<Proxy> proxies) {
59        StringBuilder builder = new StringBuilder();
60        for (Proxy proxy : proxies) {
61            if (builder.length() > 0)
62                builder.append(';');
63            builder.append(toString(proxy));
64        }
65        return builder.toString();
66   }
67
68    static void checkMapping(String url, String expected) throws URISyntaxException {
69        URI uri = new URI(url);
70        List<Proxy> proxies = ProxySelector.getDefault().select(uri);
71        assertEquals("Mapping", expected, toString(proxies));
72    }
73
74    /**
75     * Test direct mapping when no proxy defined.
76     *
77     * @throws Exception
78     */
79    @SmallTest
80    @Feature({"AndroidWebView"})
81    public void testNoProxy() throws Exception {
82        checkMapping("ftp://example.com/", "DIRECT");
83        checkMapping("http://example.com/", "DIRECT");
84        checkMapping("https://example.com/", "DIRECT");
85    }
86
87    /**
88     * Test http.proxyHost and http.proxyPort works.
89     *
90     * @throws Exception
91     */
92    @SmallTest
93    @Feature({"AndroidWebView"})
94    public void testHttpProxyHostAndPort() throws Exception {
95        System.setProperty("http.proxyHost", "httpproxy.com");
96        System.setProperty("http.proxyPort", "8080");
97        checkMapping("ftp://example.com/", "DIRECT");
98        checkMapping("http://example.com/", "PROXY httpproxy.com:8080");
99        checkMapping("https://example.com/", "DIRECT");
100    }
101
102    /**
103     * We should get the default port (80) for proxied hosts.
104     *
105     * @throws Exception
106     */
107    @SmallTest
108    @Feature({"AndroidWebView"})
109    public void testHttpProxyHostOnly() throws Exception {
110        System.setProperty("http.proxyHost", "httpproxy.com");
111        checkMapping("ftp://example.com/", "DIRECT");
112        checkMapping("http://example.com/", "PROXY httpproxy.com:80");
113        checkMapping("https://example.com/", "DIRECT");
114    }
115
116    /**
117     * http.proxyPort only should not result in any hosts being proxied.
118     *
119     * @throws Exception
120     */
121    @SmallTest
122    @Feature({"AndroidWebView"})
123    public void testHttpProxyPortOnly() throws Exception {
124        System.setProperty("http.proxyPort", "8080");
125        checkMapping("ftp://example.com/", "DIRECT");
126        checkMapping("http://example.com/", "DIRECT");
127        checkMapping("https://example.com/", "DIRECT");
128    }
129
130    /**
131     * Test that HTTP non proxy hosts are mapped correctly
132     *
133     * @throws Exception
134     */
135    @SmallTest
136    @Feature({"AndroidWebView"})
137    public void testHttpNonProxyHosts1() throws Exception {
138        System.setProperty("http.nonProxyHosts", "slashdot.org");
139        System.setProperty("http.proxyHost", "httpproxy.com");
140        System.setProperty("http.proxyPort", "8080");
141        checkMapping("http://example.com/", "PROXY httpproxy.com:8080");
142        checkMapping("http://slashdot.org/", "DIRECT");
143    }
144
145    /**
146     * Test that | pattern works.
147     *
148     * @throws Exception
149     */
150    @SmallTest
151    @Feature({"AndroidWebView"})
152    public void testHttpNonProxyHosts2() throws Exception {
153        System.setProperty("http.nonProxyHosts", "slashdot.org|freecode.net");
154        System.setProperty("http.proxyHost", "httpproxy.com");
155        System.setProperty("http.proxyPort", "8080");
156        checkMapping("http://example.com/", "PROXY httpproxy.com:8080");
157        checkMapping("http://freecode.net/", "DIRECT");
158        checkMapping("http://slashdot.org/", "DIRECT");
159    }
160
161    /**
162     * Test that * pattern works.
163     *
164     * @throws Exception
165     */
166    @SmallTest
167    @Feature({"AndroidWebView"})
168    public void testHttpNonProxyHosts3() throws Exception {
169        System.setProperty("http.nonProxyHosts", "*example.com");
170        System.setProperty("http.proxyHost", "httpproxy.com");
171        System.setProperty("http.proxyPort", "8080");
172        checkMapping("http://example.com/", "DIRECT");
173        checkMapping("http://slashdot.org/", "PROXY httpproxy.com:8080");
174        checkMapping("http://www.example.com/", "DIRECT");
175    }
176
177    /**
178     * Test that FTP non proxy hosts are mapped correctly
179     *
180     * @throws Exception
181     */
182    @SmallTest
183    @Feature({"AndroidWebView"})
184    public void testFtpNonProxyHosts() throws Exception {
185        System.setProperty("ftp.nonProxyHosts", "slashdot.org");
186        System.setProperty("ftp.proxyHost", "httpproxy.com");
187        System.setProperty("ftp.proxyPort", "8080");
188        checkMapping("ftp://example.com/", "PROXY httpproxy.com:8080");
189        checkMapping("http://example.com/", "DIRECT");
190    }
191
192    /**
193     * Test ftp.proxyHost and ftp.proxyPort works.
194     *
195     * @throws Exception
196     */
197    @SmallTest
198    @Feature({"AndroidWebView"})
199    public void testFtpProxyHostAndPort() throws Exception {
200        System.setProperty("ftp.proxyHost", "httpproxy.com");
201        System.setProperty("ftp.proxyPort", "8080");
202        checkMapping("ftp://example.com/", "PROXY httpproxy.com:8080");
203        checkMapping("http://example.com/", "DIRECT");
204        checkMapping("https://example.com/", "DIRECT");
205    }
206
207    /**
208     * Test ftp.proxyHost and default port.
209     *
210     * @throws Exception
211     */
212    @SmallTest
213    @Feature({"AndroidWebView"})
214    public void testFtpProxyHostOnly() throws Exception {
215        System.setProperty("ftp.proxyHost", "httpproxy.com");
216        checkMapping("ftp://example.com/", "PROXY httpproxy.com:80");
217        checkMapping("http://example.com/", "DIRECT");
218        checkMapping("https://example.com/", "DIRECT");
219    }
220
221    /**
222     * Test https.proxyHost and https.proxyPort works.
223     *
224     * @throws Exception
225     */
226    @SmallTest
227    @Feature({"AndroidWebView"})
228    public void testHttpsProxyHostAndPort() throws Exception {
229        System.setProperty("https.proxyHost", "httpproxy.com");
230        System.setProperty("https.proxyPort", "8080");
231        checkMapping("ftp://example.com/", "DIRECT");
232        checkMapping("http://example.com/", "DIRECT");
233        checkMapping("https://example.com/", "PROXY httpproxy.com:8080");
234    }
235
236    /**
237     * Default http proxy is used if a scheme-specific one is not found.
238     *
239     * @throws Exception
240     */
241    @SmallTest
242    @Feature({"AndroidWebView"})
243    public void testDefaultProxyExplictPort() throws Exception {
244        System.setProperty("ftp.proxyHost", "httpproxy.com");
245        System.setProperty("ftp.proxyPort", "8080");
246        System.setProperty("proxyHost", "defaultproxy.com");
247        System.setProperty("proxyPort", "8080");
248        checkMapping("ftp://example.com/", "PROXY httpproxy.com:8080");
249        checkMapping("http://example.com/", "PROXY defaultproxy.com:8080");
250        checkMapping("https://example.com/", "PROXY defaultproxy.com:8080");
251    }
252
253    /**
254     * SOCKS proxy is used if scheme-specific one is not found.
255     *
256     * @throws Exception
257     */
258    @SmallTest
259    @Feature({"AndroidWebView"})
260    public void testFallbackToSocks() throws Exception {
261        System.setProperty("http.proxyHost", "defaultproxy.com");
262        System.setProperty("socksProxyHost", "socksproxy.com");
263        checkMapping("ftp://example.com", "SOCKS5 socksproxy.com:1080");
264        checkMapping("http://example.com/", "PROXY defaultproxy.com:80");
265        checkMapping("https://example.com/", "SOCKS5 socksproxy.com:1080");
266    }
267
268    /**
269     * SOCKS proxy port is used if specified
270     *
271     * @throws Exception
272     */
273    @SmallTest
274    @Feature({"AndroidWebView"})
275    public void testSocksExplicitPort() throws Exception {
276        System.setProperty("socksProxyHost", "socksproxy.com");
277        System.setProperty("socksProxyPort", "9000");
278        checkMapping("http://example.com/", "SOCKS5 socksproxy.com:9000");
279    }
280
281    /**
282     * SOCKS proxy is ignored if default HTTP proxy defined.
283     *
284     * @throws Exception
285     */
286    @SmallTest
287    @Feature({"AndroidWebView"})
288    public void testHttpProxySupercedesSocks() throws Exception {
289        System.setProperty("proxyHost", "defaultproxy.com");
290        System.setProperty("socksProxyHost", "socksproxy.com");
291        System.setProperty("socksProxyPort", "9000");
292        checkMapping("http://example.com/", "PROXY defaultproxy.com:80");
293    }
294}
295
296