func TestTCP(t *testing.T) { // Lower maxAssertAttempts to keep this test from running too long maxAssertAttempts = 2 l0, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatal(err) } defer func() { if err := l0.Close(); err != nil { t.Fatalf("Unable to close listener: %v", err) } }() start, fdc, err := Matching("TCP") if err != nil { t.Fatal(err) } assert.Equal(t, 1, start, "Starting count should have been 1") err = fdc.AssertDelta(0) if err != nil { t.Fatal(err) } assert.NoError(t, err, "Initial TCP count should be 0") l, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatal(err) } _, middle, err := Matching("TCP") if err != nil { t.Fatal(err) } err = fdc.AssertDelta(0) if assert.Error(t, err, "Asserting wrong count should fail") { assert.Contains(t, err.Error(), "Expected 0, have 1") assert.True(t, len(err.Error()) > 100) } err = fdc.AssertDelta(1) assert.NoError(t, err, "Ending TCP count should be 1") err = fdc.AssertDelta(0) if assert.Error(t, err, "Asserting wrong count should fail") { assert.Contains(t, err.Error(), "Expected 0, have 1") assert.Contains(t, err.Error(), "New") assert.True(t, len(err.Error()) > 100) } if err := l.Close(); err != nil { t.Fatalf("Unable to close listener: %v", err) } err = middle.AssertDelta(0) if assert.Error(t, err, "Asserting wrong count should fail") { assert.Contains(t, err.Error(), "Expected 0, have -1") assert.Contains(t, err.Error(), "Removed") assert.True(t, len(err.Error()) > 100) } }
func TestTranslate(t *testing.T) { assertTranslation(t, "", "HELLO") UseOSLocale() assertTranslation(t, "I speak America English!", "ONLY_IN_EN_US") assertTranslation(t, "I speak Generic English!", "ONLY_IN_EN") assertTranslation(t, "", "NOT_EXISTED") SetMessagesDir("not-existed-dir") err := SetLocale("en_US") assert.Error(t, err, "should error if dir is not existed") SetMessagesDir("locale") assert.Error(t, SetLocale("e0"), "should error on malformed locale") assert.Error(t, SetLocale("e0-DO"), "should error on malformed locale") assert.Error(t, SetLocale("e0-DO.C"), "should error on malformed locale") assert.NoError(t, SetLocale("en"), "should change locale") if assert.NoError(t, SetLocale("en_US"), "should change locale") { // formatting assertTranslation(t, "Hello An Argument!", "HELLO", "An Argument") assertTranslation(t, "", "NOT_EXISTED", "extra args") } if assert.NoError(t, SetLocale("zh_CN"), "should change locale") { assertTranslation(t, "An Argumentä½ å¥½!", "HELLO", "An Argument") // fallbacks assertTranslation(t, "I speak Mandarin!", "ONLY_IN_ZH_CN") assertTranslation(t, "I speak Chinese!", "ONLY_IN_ZH") assertTranslation(t, "I speak America English!", "ONLY_IN_EN_US") assertTranslation(t, "I speak Generic English!", "ONLY_IN_EN") } }
func TestWaitUntilNoneMatchTimeout(t *testing.T) { conn, err := net.Dial("tcp", "www.google.com:80") if err != nil { t.Fatalf("Unable to dial google: %v", err) } defer func() { if err := conn.Close(); err != nil { fmt.Println("Unable to close connection: %v", err) } }() wait := 500 * time.Millisecond start := time.Now() go func() { time.Sleep(wait) if err := conn.Close(); err != nil { t.Fatalf("Unable to close connection: %v", err) } }() err = WaitUntilNoneMatch("TCP", wait/2) elapsed := time.Now().Sub(start) assert.Error(t, err, "Waiting should have failed") assert.True(t, elapsed < wait, "Should have waited less than time to close conn") }
func TestBadConnectStatus(t *testing.T) { l, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatalf("Unable to listen: %s", err) } hs := &http.Server{ Handler: http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { resp.WriteHeader(403) // forbidden }), } go func() { if err := hs.Serve(l); err != nil { t.Fatalf("Unable to serve: %v", err) } }() dialer := NewDialer(Config{ DialServer: func() (net.Conn, error) { return net.Dial("tcp", l.Addr().String()) }, }) _, err = dialer.Dial("tcp", "www.google.com") assert.Error(t, err, "Dialing a server that sends a non-successful HTTP status to our CONNECT request should have failed") }
func doTestNonGlobalAddress(t *testing.T, overrideAddr string) { l := startServer(t, false, nil) d := dialerFor(t, l, 0) defer d.Close() gotConn := false var gotConnMutex sync.Mutex tl, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatalf("Unable to listen: %s", err) } go func() { tl.Accept() gotConnMutex.Lock() gotConn = true gotConnMutex.Unlock() }() addr := tl.Addr().String() if overrideAddr != "" { addr = overrideAddr } conn, err := d.Dial("tcp", addr) if err != nil { t.Fatalf("Unable to dial %v: %v", addr, err) } data := []byte("Some Meaningless Data") conn.Write(data) // Give enproxy time to flush time.Sleep(500 * time.Millisecond) _, err = conn.Write(data) assert.Error(t, err, "Sending data after previous attempt to write to local address should have failed") assert.False(t, gotConn, "Sending data to local address should never have resulted in connection") }
func TestIdleClientConnections(t *testing.T) { limitedServer, err := setupNewHTTPServer(0, 100*time.Millisecond) if err != nil { assert.Fail(t, "Error starting proxy server") } okFn := func(conn net.Conn, proxy *server.Server, originURL *url.URL) { time.Sleep(time.Millisecond * 90) conn.Write([]byte("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n")) var buf [400]byte _, err := conn.Read(buf[:]) assert.NoError(t, err) } idleFn := func(conn net.Conn, proxy *server.Server, originURL *url.URL) { time.Sleep(time.Millisecond * 110) conn.Write([]byte("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n")) var buf [400]byte _, err := conn.Read(buf[:]) assert.Error(t, err) } go testRoundTrip(t, limitedServer, httpOriginServer, okFn) testRoundTrip(t, limitedServer, httpOriginServer, idleFn) }
func TestTimeout(t *testing.T) { offer := Offer(1 * time.Millisecond) _, err := offer.FiveTuple() assert.Error(t, err, "There should be an error") if err != nil { assert.Contains(t, err.Error(), "Timed out", "Error should mention timing out") } }
func TestReadFailure(t *testing.T) { id1 := Random() b := make([]byte, EncodedLength) err := id1.Write(b) assert.NoError(t, err, "Unable to write") _, err = Read(b[:EncodedLength-1]) assert.Error(t, err, "Read should have failed") }
func TestBadEnproxyConn(t *testing.T) { d := NewDialer(Config{ Host: "localhost", Port: 3253, }) _, err := d.Dial("tcp", "www.google.com") assert.Error(t, err, "Dialing using a non-existent host should have failed") }
func TestDialFailure(t *testing.T) { fail := int32(1) dialAttempts := int32(0) addr, err := startTestServer() if err != nil { t.Fatalf("Unable to start test server: %s", err) } _, fdc, err := fdcount.Matching("TCP") if err != nil { t.Fatal(err) } poolSize := 10 p := New(Config{ Size: poolSize, Dial: func() (net.Conn, error) { atomic.AddInt32(&dialAttempts, 1) if fail == int32(1) { return nil, fmt.Errorf("I'm failing intentionally!") } return net.DialTimeout("tcp", addr, 15*time.Millisecond) }, }) // Try to get connection, make sure it fails conn, err := p.Get() if !assert.Error(t, err, "Dialing should have failed") { if err := conn.Close(); err != nil { t.Fatalf("Unable to close connection: %v", err) } } // Wait for fill to run for a while with a failing connection time.Sleep(1 * time.Second) assert.Equal(t, 1, atomic.LoadInt32(&dialAttempts), fmt.Sprintf("There should have been only 1 dial attempt")) assert.NoError(t, fdc.AssertDelta(0), "There should be no additional file descriptors open") // Now make connection succeed and verify that it works atomic.StoreInt32(&fail, 0) time.Sleep(100 * time.Millisecond) connectAndRead(t, p, 1) time.Sleep(fillTime) log.Debug("Testing") assert.NoError(t, fdc.AssertDelta(10), "Pool should have filled") // Now make the connection fail again so that when we stop, we're stopping // while failing (tests a different code path for stopping) atomic.StoreInt32(&fail, 1) time.Sleep(100 * time.Millisecond) p.Close() assert.NoError(t, fdc.AssertDelta(0), "All connections should be closed") }
func TestBadProtocol(t *testing.T) { dialer := NewDialer(Config{ DialServer: func() (net.Conn, error) { return net.Dial("tcp", "www.google.com") }, }) _, err := dialer.Dial("udp", "www.google.com") assert.Error(t, err, "Dialing with a non-tcp protocol should have failed") }
func TestHttpClientWithBadEnproxyConn(t *testing.T) { d := NewDialer(Config{ Host: "localhost", Port: 3253, }) hc := d.HttpClientUsing(nil) _, err := hc.Get("http://www.google.com/humans.txt") assert.Error(t, err, "HttpClient using a non-existent host should have failed") }
func doTestTimeout(t *testing.T, timeout time.Duration) { _, err := DialWithDialer(&net.Dialer{ Timeout: timeout, }, "tcp", ADDR, false, nil) assert.Error(t, err, "There should have been a problem dialing", timeout) if err != nil { assert.True(t, err.(net.Error).Timeout(), "Dial error should be timeout", timeout) } }
func TestBadDialServer(t *testing.T) { dialer := NewDialer(Config{ DialServer: func() (net.Conn, error) { return nil, fmt.Errorf("I refuse to dial") }, }) _, err := dialer.Dial("tcp", "www.google.com") assert.Error(t, err, "Dialing with a bad DialServer function should have failed") }
func TestNotOKWithServerName(t *testing.T) { fdStart := countTCPFiles() conn, err := Dial("tcp", ADDR, true, nil) assert.Error(t, err, "There should have been a problem dialing") if err != nil { assert.Contains(t, err.Error(), CERTIFICATE_ERROR, "Wrong error on dial") } <-receivedServerNames closeAndCountFDs(t, conn, err, fdStart) }
func TestWriteTooLong(t *testing.T) { w := NewWriter(ioutil.Discard) b := make([]byte, MaxFrameLength+1) n, err := w.Write(b) assert.Error(t, err, "Writing too long message should result in error") assert.Equal(t, 0, n, "Writing too long message should result in 0 bytes written") n, err = w.Write(b[:len(b)-1]) assert.NoError(t, err, "Writing message of MaxFrameLength should be allowed") assert.Equal(t, MaxFrameLength, n, "Writing message of MaxFrameLength should have written MaxFrameLength bytes") }
func TestReplaceBadOnDial(t *testing.T) { d := NewDialer(Config{ Host: "fallbacks.getiantem.org", Port: 443, OnDial: func(conn net.Conn, err error) (net.Conn, error) { return nil, fmt.Errorf("Gotcha!") }, }) _, err := d.Dial("tcp", "www.google.com") assert.Error(t, err, "Dialing using a bad OnDial should fail") }
func TestBadCertificateFile(t *testing.T) { server := &Server{ Addr: "localhost:0", CertContext: &CertContext{ PKFile: "testpk.pem", ServerCertFile: "", }, } _, err := server.Listen() assert.Error(t, err, "Listen should have failed") }
func TestDeadlineBeforeTimeout(t *testing.T) { fdStart := countTCPFiles() conn, err := DialWithDialer(&net.Dialer{ Timeout: 500 * time.Second, Deadline: time.Now().Add(5 * time.Microsecond), }, "tcp", ADDR, false, nil) assert.Error(t, err, "There should have been a problem dialing") if err != nil { assert.True(t, err.(net.Error).Timeout(), "Dial error should be timeout") } closeAndCountFDs(t, conn, err, fdStart) }
func TestAllowed(t *testing.T) { gotConn := false var gotConnMutex sync.Mutex tl, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatalf("Unable to listen: %s", err) } go func() { if _, err := tl.Accept(); err != nil { t.Fatalf("Unable to accept connections: %v", err) } gotConnMutex.Lock() gotConn = true gotConnMutex.Unlock() }() _, portString, err := net.SplitHostPort(tl.Addr().String()) if err != nil { t.Fatalf("Unable to get port for test server: %v", err) } port, err := strconv.Atoi(portString) if err != nil { t.Fatalf("Unable to convert port %v to integer: %v", portString, err) } // Only allow some port other than the actual port l := startServer(t, true, []int{port + 1}) d := dialerFor(t, l, 0) defer func() { if err := d.Close(); err != nil { t.Fatalf("Unable to close dialer: %v", err) } }() addr := tl.Addr().String() conn, err := d.Dial("tcp", addr) defer func() { if err := conn.Close(); err != nil { t.Fatalf("Unable to close connection: %v", err) } }() data := []byte("Some Meaningless Data") if _, err := conn.Write(data); err != nil { t.Fatalf("Unable to write connection: %v", err) } // Give enproxy time to flush time.Sleep(500 * time.Millisecond) _, err = conn.Write(data) assert.Error(t, err, "Sending data after previous attempt to write to disallowed port should have failed") assert.False(t, gotConn, "Sending data to disallowed port should never have resulted in connection") }
func TestNonIdempotentOp(t *testing.T) { defer stopMockServers() proxiedURL, _ := newMockServer(detourMsg) mockURL, mock := newMockServer("") u, _ := url.Parse(mockURL) mock.Timeout(200*time.Millisecond, directMsg) client := newClient(proxiedURL, 100*time.Millisecond) _, err := client.PostForm(mockURL, url.Values{"key": []string{"value"}}) if assert.Error(t, err, "Non-idempotent method should not be detoured in same connection") { time.Sleep(50 * time.Millisecond) assert.True(t, wlTemporarily(u.Host), "but should be added to whitelist so will detour next time") } }
func TestNotOKWithoutServerName(t *testing.T) { fdStart := countTCPFiles() conn, err := Dial("tcp", ADDR, true, &tls.Config{ ServerName: "localhost", }) assert.Error(t, err, "There should have been a problem dialing") if err != nil { assert.Contains(t, err.Error(), CERTIFICATE_ERROR, "Wrong error on dial") } serverName := <-receivedServerNames assert.Empty(t, serverName, "Unexpected ServerName on server") closeAndCountFDs(t, conn, err, fdStart) }
func TestNonDefaultClient(t *testing.T) { // Set up a client that will fail client := &http.Client{ Transport: &http.Transport{ Dial: func(network, addr string) (net.Conn, error) { return nil, fmt.Errorf("Failing intentionally") }, }, } _, err := LookupIPWithClient("", client) assert.Error(t, err, "Using bad client should have resulted in error") }
func TestBlockedImmediately(t *testing.T) { defer stopMockServers() proxiedURL, _ := newMockServer(detourMsg) TimeoutToDetour = 50 * time.Millisecond mockURL, mock := newMockServer(directMsg) client := &http.Client{Timeout: 50 * time.Millisecond} mock.Timeout(200*time.Millisecond, directMsg) resp, err := client.Get(mockURL) assert.Error(t, err, "direct access to a timeout url should fail") client = newClient(proxiedURL, 100*time.Millisecond) resp, err = client.Get("http://255.0.0.1") // it's reserved for future use so will always time out if assert.NoError(t, err, "should have no error if dialing times out") { assert.True(t, wlTemporarily("255.0.0.1:80"), "should be added to whitelist if dialing times out") assertContent(t, resp, detourMsg, "should detour if dialing times out") } client = newClient(proxiedURL, 100*time.Millisecond) resp, err = client.Get("http://127.0.0.1:4325") // hopefully this port didn't open, so connection will be refused if assert.NoError(t, err, "should have no error if connection is refused") { assert.True(t, wlTemporarily("127.0.0.1:4325"), "should be added to whitelist if connection is refused") assertContent(t, resp, detourMsg, "should detour if connection is refused") } u, _ := url.Parse(mockURL) resp, err = client.Get(mockURL) if assert.NoError(t, err, "should have no error if reading times out") { assert.True(t, wlTemporarily(u.Host), "should be added to whitelist if reading times out") assertContent(t, resp, detourMsg, "should detour if reading times out") } client = newClient(proxiedURL, 100*time.Millisecond) RemoveFromWl(u.Host) resp, err = client.PostForm(mockURL, url.Values{"key": []string{"value"}}) if assert.Error(t, err, "Non-idempotent method should not be detoured in same connection") { assert.True(t, wlTemporarily(u.Host), "but should be added to whitelist so will detour next time") } }
func TestMaxConnections(t *testing.T) { connectReq := "CONNECT %s HTTP/1.1\r\nHost: %s\r\n\r\n" limitedServer, err := setupNewHTTPServer(5, 30*time.Second) if err != nil { assert.Fail(t, "Error starting proxy server") } //limitedServer.httpServer.SetKeepAlivesEnabled(false) okFn := func(conn net.Conn, proxy *server.Server, originURL *url.URL) { req := fmt.Sprintf(connectReq, originURL.Host, originURL.Host) conn.Write([]byte(req)) var buf [400]byte _, err = conn.Read(buf[:]) assert.NoError(t, err) time.Sleep(time.Millisecond * 100) } waitFn := func(conn net.Conn, proxy *server.Server, originURL *url.URL) { conn.SetReadDeadline(time.Now().Add(50 * time.Millisecond)) req := fmt.Sprintf(connectReq, originURL.Host, originURL.Host) conn.Write([]byte(req)) var buf [400]byte _, err = conn.Read(buf[:]) if assert.Error(t, err) { e, ok := err.(*net.OpError) assert.True(t, ok && e.Timeout(), "should be a time out error") } } for i := 0; i < 5; i++ { go testRoundTrip(t, limitedServer, httpOriginServer, okFn) } time.Sleep(time.Millisecond * 10) for i := 0; i < 5; i++ { go testRoundTrip(t, limitedServer, httpOriginServer, waitFn) } time.Sleep(time.Millisecond * 100) for i := 0; i < 5; i++ { go testRoundTrip(t, limitedServer, httpOriginServer, okFn) } }
func TestRemoveFromWhitelist(t *testing.T) { defer stopMockServers() proxiedURL, proxy := newMockServer(detourMsg) proxy.Timeout(200*time.Millisecond, detourMsg) mockURL, _ := newMockServer(directMsg) client := newClient(proxiedURL, 100*time.Millisecond) u, _ := url.Parse(mockURL) AddToWl(u.Host, false) _, err := client.Get(mockURL) if assert.Error(t, err, "should have error if reading times out through detour") { assert.False(t, whitelisted(u.Host), "should be removed from whitelist if reading times out through detour") } }
func TestNotOKWithServerName(t *testing.T) { _, fdc, err := fdcount.Matching("TCP") if err != nil { t.Fatal(err) } conn, err := Dial("tcp", ADDR, true, nil) assert.Error(t, err, "There should have been a problem dialing") if err != nil { assert.Contains(t, err.Error(), CERTIFICATE_ERROR, "Wrong error on dial") } <-receivedServerNames closeAndCountFDs(t, conn, err, fdc) }
func TestBadAddressToServer(t *testing.T) { l := startServer(t) req, err := buildCONNECTRequest("somebadaddressasdfdasfds.asdfasdf.dfads:532400", nil) if err != nil { t.Fatalf("Unable to build request: %s", err) } conn, err := net.Dial("tcp", l.Addr().String()) if err != nil { t.Fatalf("Unable to dial server: %s", err) } err = req.Write(conn) if err != nil { t.Fatalf("Unable to make request: %s", err) } r := bufio.NewReader(conn) err = checkCONNECTResponse(r, req) assert.Error(t, err, "Connect response should be bad") }
func TestReadTimeout(t *testing.T) { defer stopMockServers() proxiedURL, _ := newMockServer(detourMsg) mockURL, mock := newMockServer("") mock.Timeout(200*time.Millisecond, directMsg) client := &http.Client{Timeout: 100 * time.Millisecond} resp, err := client.Get(mockURL) assert.Error(t, err, "direct access to a timeout url should fail") u, _ := url.Parse(mockURL) client = newClient(proxiedURL, 100*time.Millisecond) resp, err = client.Get(mockURL) if assert.NoError(t, err, "should have no error if reading times out") { time.Sleep(50 * time.Millisecond) assert.True(t, wlTemporarily(u.Host), "should be added to whitelist if reading times out") assertContent(t, resp, detourMsg, "should detour if reading times out") } }
func TestBadServer(t *testing.T) { l, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatalf("Unable to listen: %s", err) } go func() { conn, err := l.Accept() if err == nil { conn.Close() } }() dialer := NewDialer(Config{ DialServer: func() (net.Conn, error) { return net.Dial("tcp", l.Addr().String()) }, }) _, err = dialer.Dial("tcp", "www.google.com") assert.Error(t, err, "Dialing a server that disconnects too soon should have failed") }