Skip to content

Commit 3d09b94

Browse files
authored
test(x) add psiphon integration tests (#430)
* adding a possible psiphon integration test * split config out into its own file * add fetch example * reviewer comments
1 parent 26d33d5 commit 3d09b94

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright 2023 The Outline Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build psiphon && nettest
16+
// +build psiphon,nettest
17+
18+
package psiphon
19+
20+
import (
21+
"context"
22+
"encoding/json"
23+
"io"
24+
"net"
25+
"net/http"
26+
"os"
27+
"path/filepath"
28+
"strings"
29+
"testing"
30+
"time"
31+
32+
"github.com/stretchr/testify/require"
33+
)
34+
35+
func readPsiphonConfigFromFile(tb testing.TB) string {
36+
// It's useful to test actually starting psiphon connections,
37+
// but doing so requires supplying a valid psiphon config with private information.
38+
// To run these tests please supply your own config in integration_test_config.yaml
39+
configPath := filepath.Join("testdata", "integration_test_config.yaml")
40+
configBytes, err := os.ReadFile(configPath)
41+
if err != nil {
42+
require.NoError(tb, err)
43+
}
44+
return string(configBytes)
45+
}
46+
47+
func newValidTestConfig(tb testing.TB) (*DialerConfig, func()) {
48+
privatePsiphonConfig := readPsiphonConfigFromFile(tb)
49+
if strings.Contains(privatePsiphonConfig, "{<YOUR_CONFIG_HERE>}") {
50+
tb.Skip("Integration testing for Psiphon requires adding a user-supplied config in integration_test_config.yaml")
51+
}
52+
tempDir, err := os.MkdirTemp("", "psiphon")
53+
require.NoError(tb, err)
54+
return &DialerConfig{
55+
DataRootDirectory: tempDir,
56+
ProviderConfig: json.RawMessage(privatePsiphonConfig),
57+
}, func() { os.RemoveAll(tempDir) }
58+
}
59+
60+
func TestDialer_CancelinledAfterStart_DoesntCloseTunnel(t *testing.T) {
61+
cfg, delete := newValidTestConfig(t)
62+
defer delete()
63+
startCtx, startCancel := context.WithCancel(context.Background())
64+
dialer := GetSingletonDialer()
65+
66+
startDone := make(chan error)
67+
go func() { startDone <- dialer.Start(startCtx, cfg) }()
68+
<-startDone
69+
startCancel() // Cancel only after start is done.
70+
71+
// Cancelling the start does not nix the tunnel.
72+
require.NotNil(t, dialer.tunnel)
73+
74+
dialer.Stop()
75+
}
76+
77+
func TestDialer_FetchExample(t *testing.T) {
78+
cfg, delete := newValidTestConfig(t)
79+
defer delete()
80+
startCtx, startCancel := context.WithCancel(context.Background())
81+
defer startCancel()
82+
dialer := GetSingletonDialer()
83+
84+
startDone := make(chan error)
85+
go func() { startDone <- dialer.Start(startCtx, cfg) }()
86+
require.NoError(t, <-startDone)
87+
88+
dialContext := func(ctx context.Context, network, addr string) (net.Conn, error) {
89+
return dialer.DialStream(ctx, addr)
90+
}
91+
httpClient := &http.Client{Transport: &http.Transport{DialContext: dialContext}, Timeout: 5 * time.Second}
92+
93+
req, err := http.NewRequest("GET", "http://www.gstatic.com/generate_204", nil)
94+
require.NoError(t, err)
95+
resp, err := httpClient.Do(req)
96+
require.NoError(t, err)
97+
defer resp.Body.Close()
98+
_, err = io.Copy(io.Discard, resp.Body)
99+
require.NoError(t, err)
100+
101+
dialer.Stop()
102+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{<YOUR_CONFIG_HERE>}

0 commit comments

Comments
 (0)