1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package proxy
6
7import (
8	"bytes"
9	"fmt"
10	"net/url"
11	"os"
12	"strings"
13	"testing"
14
15	"golang.org/x/net/internal/sockstest"
16)
17
18type proxyFromEnvTest struct {
19	allProxyEnv string
20	noProxyEnv  string
21	wantTypeOf  Dialer
22}
23
24func (t proxyFromEnvTest) String() string {
25	var buf bytes.Buffer
26	space := func() {
27		if buf.Len() > 0 {
28			buf.WriteByte(' ')
29		}
30	}
31	if t.allProxyEnv != "" {
32		fmt.Fprintf(&buf, "all_proxy=%q", t.allProxyEnv)
33	}
34	if t.noProxyEnv != "" {
35		space()
36		fmt.Fprintf(&buf, "no_proxy=%q", t.noProxyEnv)
37	}
38	return strings.TrimSpace(buf.String())
39}
40
41func TestFromEnvironment(t *testing.T) {
42	ResetProxyEnv()
43
44	type dummyDialer struct {
45		direct
46	}
47
48	RegisterDialerType("irc", func(_ *url.URL, _ Dialer) (Dialer, error) {
49		return dummyDialer{}, nil
50	})
51
52	proxyFromEnvTests := []proxyFromEnvTest{
53		{allProxyEnv: "127.0.0.1:8080", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
54		{allProxyEnv: "ftp://example.com:8000", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
55		{allProxyEnv: "socks5://example.com:8080", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: &PerHost{}},
56		{allProxyEnv: "irc://example.com:8000", wantTypeOf: dummyDialer{}},
57		{noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
58		{wantTypeOf: direct{}},
59	}
60
61	for _, tt := range proxyFromEnvTests {
62		os.Setenv("ALL_PROXY", tt.allProxyEnv)
63		os.Setenv("NO_PROXY", tt.noProxyEnv)
64		ResetCachedEnvironment()
65
66		d := FromEnvironment()
67		if got, want := fmt.Sprintf("%T", d), fmt.Sprintf("%T", tt.wantTypeOf); got != want {
68			t.Errorf("%v: got type = %T, want %T", tt, d, tt.wantTypeOf)
69		}
70	}
71}
72
73func TestFromURL(t *testing.T) {
74	ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
75	if err != nil {
76		t.Fatal(err)
77	}
78	defer ss.Close()
79	url, err := url.Parse("socks5://user:password@" + ss.Addr().String())
80	if err != nil {
81		t.Fatal(err)
82	}
83	proxy, err := FromURL(url, nil)
84	if err != nil {
85		t.Fatal(err)
86	}
87	c, err := proxy.Dial("tcp", "fqdn.doesnotexist:5963")
88	if err != nil {
89		t.Fatal(err)
90	}
91	c.Close()
92}
93
94func TestSOCKS5(t *testing.T) {
95	ss, err := sockstest.NewServer(sockstest.NoAuthRequired, sockstest.NoProxyRequired)
96	if err != nil {
97		t.Fatal(err)
98	}
99	defer ss.Close()
100	proxy, err := SOCKS5("tcp", ss.Addr().String(), nil, nil)
101	if err != nil {
102		t.Fatal(err)
103	}
104	c, err := proxy.Dial("tcp", ss.TargetAddr().String())
105	if err != nil {
106		t.Fatal(err)
107	}
108	c.Close()
109}
110
111func ResetProxyEnv() {
112	for _, env := range []*envOnce{allProxyEnv, noProxyEnv} {
113		for _, v := range env.names {
114			os.Setenv(v, "")
115		}
116	}
117	ResetCachedEnvironment()
118}
119
120func ResetCachedEnvironment() {
121	allProxyEnv.reset()
122	noProxyEnv.reset()
123}
124