1/*
2 * Copyright (C) 2014 Square, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.squareup.okhttp;
17
18import com.squareup.okhttp.mockwebserver.MockResponse;
19import com.squareup.okhttp.mockwebserver.MockWebServer;
20import java.io.IOException;
21import java.net.Proxy;
22import java.net.ProxySelector;
23import java.net.SocketAddress;
24import java.net.URI;
25import java.util.Collections;
26import java.util.List;
27import org.junit.After;
28import org.junit.Before;
29import org.junit.Test;
30
31import static org.junit.Assert.assertEquals;
32
33public final class SocksProxyTest {
34  private final SocksProxy socksProxy = new SocksProxy();
35  private final MockWebServer server = new MockWebServer();
36
37  @Before public void setUp() throws Exception {
38    server.start();
39    socksProxy.play();
40  }
41
42  @After public void tearDown() throws Exception {
43    server.shutdown();
44    socksProxy.shutdown();
45  }
46
47  @Test public void proxy() throws Exception {
48    server.enqueue(new MockResponse().setBody("abc"));
49    server.enqueue(new MockResponse().setBody("def"));
50
51    OkHttpClient client = new OkHttpClient()
52        .setProxy(socksProxy.proxy());
53
54    Request request1 = new Request.Builder().url(server.url("/")).build();
55    Response response1 = client.newCall(request1).execute();
56    assertEquals("abc", response1.body().string());
57
58    Request request2 = new Request.Builder().url(server.url("/")).build();
59    Response response2 = client.newCall(request2).execute();
60    assertEquals("def", response2.body().string());
61
62    // The HTTP calls should share a single connection.
63    assertEquals(1, socksProxy.connectionCount());
64  }
65
66  @Test public void proxySelector() throws Exception {
67    server.enqueue(new MockResponse().setBody("abc"));
68
69    ProxySelector proxySelector = new ProxySelector() {
70      @Override public List<Proxy> select(URI uri) {
71        return Collections.singletonList(socksProxy.proxy());
72      }
73
74      @Override public void connectFailed(URI uri, SocketAddress socketAddress, IOException e) {
75        throw new AssertionError();
76      }
77    };
78
79    OkHttpClient client = new OkHttpClient()
80        .setProxySelector(proxySelector);
81
82    Request request = new Request.Builder().url(server.url("/")).build();
83    Response response = client.newCall(request).execute();
84    assertEquals("abc", response.body().string());
85
86    assertEquals(1, socksProxy.connectionCount());
87  }
88
89  @Test public void checkRemoteDNSResolve() throws Exception {
90    // This testcase will fail if the target is resolved locally instead of through the proxy.
91    server.enqueue(new MockResponse().setBody("abc"));
92
93    OkHttpClient client = new OkHttpClient()
94        .setProxy(socksProxy.proxy());
95
96    HttpUrl url = server.url("/")
97        .newBuilder()
98        .host(socksProxy.HOSTNAME_THAT_ONLY_THE_PROXY_KNOWS)
99        .build();
100
101    Request request = new Request.Builder().url(url).build();
102    Response response1 = client.newCall(request).execute();
103    assertEquals("abc", response1.body().string());
104
105    assertEquals(1, socksProxy.connectionCount());
106  }
107}
108