Moved integration tests and other minor fixes
This commit is contained in:
parent
0e8472626c
commit
db2d028c4a
|
@ -120,7 +120,6 @@ func (c *Conn) EventWait(
|
|||
ctx context.Context, events []EventCode, predicate func(Event) (bool, error),
|
||||
) (Event, error) {
|
||||
eventCh := make(chan Event, 10)
|
||||
defer close(eventCh)
|
||||
if err := c.AddEventListener(eventCh, events...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -131,6 +130,8 @@ func (c *Conn) EventWait(
|
|||
go func() { errCh <- c.HandleEvents(eventCtx) }()
|
||||
for {
|
||||
select {
|
||||
case <-eventCtx.Done():
|
||||
return nil, eventCtx.Err()
|
||||
case err := <-errCh:
|
||||
return nil, err
|
||||
case event := <-eventCh:
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
package controltest
|
||||
|
||||
/*
|
||||
func TestEvents(t *testing.T) {
|
||||
SkipIfNotRunningSpecifically(t)
|
||||
ctx, conn := NewTestContextAuthenticated(t)
|
||||
defer ctx.CloseConnected(conn)
|
||||
// Turn on event handler
|
||||
eventCtx, cancelFn := context.WithCancel(ctx)
|
||||
defer cancelFn()
|
||||
go func() { ctx.Require.Equal(context.Canceled, conn.HandleEvents(eventCtx)) }()
|
||||
// Enable all events and hold on to which ones were seen
|
||||
allEvents := control.EventCodes()
|
||||
seenEvents := map[control.EventCode]struct{}{}
|
||||
ch := make(chan control.Event, 1000)
|
||||
ctx.Require.NoError(conn.AddEventListener(ch, allEvents...))
|
||||
// Turn on the network
|
||||
ctx.Require.NoError(conn.SetConf(control.NewKeyVal("DisableNetwork", "0")))
|
||||
MainLoop:
|
||||
for {
|
||||
select {
|
||||
case e := <-ch:
|
||||
// Remove the event listener if it was seen
|
||||
if _, ok := seenEvents[e.Code()]; !ok {
|
||||
ctx.Debugf("Got event: %v", e.Code())
|
||||
seenEvents[e.Code()] = struct{}{}
|
||||
ctx.Require.NoError(conn.RemoveEventListener(ch, e.Code()))
|
||||
}
|
||||
case <-time.After(3 * time.Second):
|
||||
ctx.Debugf("3 seconds passed")
|
||||
break MainLoop
|
||||
}
|
||||
}
|
||||
// Check that each event was sent at least once
|
||||
for _, event := range allEvents {
|
||||
_, ok := seenEvents[event]
|
||||
ctx.Debugf("Event %v seen? %v", event, ok)
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -1,10 +0,0 @@
|
|||
package controltest
|
||||
|
||||
/*
|
||||
func TestGetHiddenServiceDescriptorAsync(t *testing.T) {
|
||||
ctx, conn := NewTestContextAuthenticated(t)
|
||||
defer ctx.CloseConnected(conn)
|
||||
t.Skip("TODO")
|
||||
}
|
||||
|
||||
*/
|
|
@ -1,62 +0,0 @@
|
|||
package controltest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/cretz/bine/tor"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func SkipIfNotRunningSpecifically(t *testing.T) {
|
||||
if f := flag.Lookup("test.run"); f == nil || f.Value == nil || f.Value.String() != t.Name() {
|
||||
t.Skip("Only runs if -run specifies this test exactly")
|
||||
}
|
||||
}
|
||||
|
||||
type TestContext struct {
|
||||
context.Context
|
||||
*testing.T
|
||||
*tor.Tor
|
||||
Require *require.Assertions
|
||||
}
|
||||
|
||||
var torExePath string
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&torExePath, "tor.path", "tor", "The TOR exe path")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func NewTestContext(t *testing.T, conf *tor.StartConf) *TestContext {
|
||||
// Build start conf
|
||||
if conf == nil {
|
||||
conf = &tor.StartConf{}
|
||||
}
|
||||
conf.ExePath = torExePath
|
||||
if f := flag.Lookup("test.v"); f != nil && f.Value != nil && f.Value.String() == "true" {
|
||||
conf.DebugWriter = os.Stdout
|
||||
} else {
|
||||
conf.ExtraArgs = append(conf.ExtraArgs, "--quiet")
|
||||
}
|
||||
ret := &TestContext{Context: context.Background(), T: t, Require: require.New(t)}
|
||||
// Start tor
|
||||
var err error
|
||||
if ret.Tor, err = tor.Start(ret.Context, conf); err != nil {
|
||||
defer ret.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (t *TestContext) Close() {
|
||||
if err := t.Tor.Close(); err != nil {
|
||||
if t.Failed() {
|
||||
t.Logf("Failure on close: %v", err)
|
||||
} else {
|
||||
t.Errorf("Failure on close: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
// Package controltest contains the integration tests for package control.
|
||||
package controltest
|
|
@ -0,0 +1,95 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cretz/bine/tor"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var torExePath string
|
||||
var torVerbose bool
|
||||
var torIncludeNetworkTests bool
|
||||
var globalEnabledNetworkContext *TestContext
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.StringVar(&torExePath, "tor.path", "tor", "The Tor exe path")
|
||||
flag.BoolVar(&torVerbose, "tor.verbose", false, "Show verbose test info")
|
||||
flag.BoolVar(&torIncludeNetworkTests, "tor.network", false, "Include network tests")
|
||||
flag.Parse()
|
||||
exitCode := m.Run()
|
||||
if globalEnabledNetworkContext != nil {
|
||||
globalEnabledNetworkContext.CloseTorOnClose = true
|
||||
globalEnabledNetworkContext.Close()
|
||||
}
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
func SkipIfExcludingNetworkTests(t *testing.T) {
|
||||
if !torIncludeNetworkTests {
|
||||
t.Skip("Only runs if -tor.network is set")
|
||||
}
|
||||
}
|
||||
|
||||
func GlobalEnabledNetworkContext(t *testing.T) *TestContext {
|
||||
SkipIfExcludingNetworkTests(t)
|
||||
if globalEnabledNetworkContext == nil {
|
||||
ctx := NewTestContext(t, nil)
|
||||
ctx.CloseTorOnClose = false
|
||||
// 45 second wait for enable network
|
||||
enableCtx, enableCancel := context.WithTimeout(ctx, 45*time.Second)
|
||||
defer enableCancel()
|
||||
ctx.Require.NoError(ctx.EnableNetwork(enableCtx, true))
|
||||
globalEnabledNetworkContext = ctx
|
||||
} else {
|
||||
globalEnabledNetworkContext.T = t
|
||||
globalEnabledNetworkContext.Require = require.New(t)
|
||||
}
|
||||
return globalEnabledNetworkContext
|
||||
}
|
||||
|
||||
type TestContext struct {
|
||||
context.Context
|
||||
*testing.T
|
||||
*tor.Tor
|
||||
Require *require.Assertions
|
||||
CloseTorOnClose bool
|
||||
}
|
||||
|
||||
func NewTestContext(t *testing.T, conf *tor.StartConf) *TestContext {
|
||||
// Build start conf
|
||||
if conf == nil {
|
||||
conf = &tor.StartConf{}
|
||||
}
|
||||
conf.ExePath = torExePath
|
||||
if torVerbose {
|
||||
conf.DebugWriter = os.Stdout
|
||||
conf.NoHush = true
|
||||
} else {
|
||||
conf.ExtraArgs = append(conf.ExtraArgs, "--quiet")
|
||||
}
|
||||
ret := &TestContext{Context: context.Background(), T: t, Require: require.New(t), CloseTorOnClose: true}
|
||||
// Start tor
|
||||
var err error
|
||||
if ret.Tor, err = tor.Start(ret.Context, conf); err != nil {
|
||||
defer ret.Close()
|
||||
t.Fatal(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (t *TestContext) Close() {
|
||||
if t.CloseTorOnClose {
|
||||
if err := t.Tor.Close(); err != nil {
|
||||
if t.Failed() {
|
||||
t.Logf("Failure on close: %v", err)
|
||||
} else {
|
||||
t.Errorf("Failure on close: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package controltest
|
||||
package tests
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -1,4 +1,4 @@
|
|||
package controltest
|
||||
package tests
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
|
@ -0,0 +1,3 @@
|
|||
package tests
|
||||
|
||||
// TODO: test several event parsers
|
|
@ -1,4 +1,4 @@
|
|||
package controltest
|
||||
package tests
|
||||
|
||||
import "testing"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package controltest
|
||||
package tests
|
||||
|
||||
import (
|
||||
"strings"
|
|
@ -0,0 +1,2 @@
|
|||
// Package tests contains integration tests.
|
||||
package tests
|
|
@ -0,0 +1,44 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
)
|
||||
|
||||
func TestDialerSimpleHTTP(t *testing.T) {
|
||||
ctx := GlobalEnabledNetworkContext(t)
|
||||
httpClient := httpClient(ctx)
|
||||
// IsTor check
|
||||
byts := httpGet(ctx, httpClient, "https://check.torproject.org/api/ip")
|
||||
jsn := map[string]interface{}{}
|
||||
ctx.Require.NoError(json.Unmarshal(byts, &jsn))
|
||||
ctx.Require.True(jsn["IsTor"].(bool))
|
||||
}
|
||||
|
||||
func httpClient(ctx *TestContext) *http.Client {
|
||||
// 15 seconds max to dial
|
||||
dialCtx, dialCancel := context.WithTimeout(ctx, 15*time.Second)
|
||||
defer dialCancel()
|
||||
// Make connection
|
||||
dialer, err := ctx.Dialer(dialCtx, nil)
|
||||
ctx.Require.NoError(err)
|
||||
return &http.Client{Transport: &http.Transport{DialContext: dialer.DialContext}}
|
||||
}
|
||||
|
||||
func httpGet(ctx *TestContext, client *http.Client, url string) []byte {
|
||||
// We'll give it 30 seconds to respond
|
||||
callCtx, callCancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
defer callCancel()
|
||||
resp, err := ctxhttp.Get(callCtx, client, url)
|
||||
ctx.Require.NoError(err)
|
||||
defer resp.Body.Close()
|
||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||
ctx.Require.NoError(err)
|
||||
return respBytes
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cretz/bine/tor"
|
||||
)
|
||||
|
||||
func TestListenSimpleHTTPV2(t *testing.T) {
|
||||
ctx := GlobalEnabledNetworkContext(t)
|
||||
// Create an onion service to listen on random port but show as 80
|
||||
conf := &tor.ListenConf{RemotePorts: []int{80}}
|
||||
client, server, onion := startHTTPServer(ctx, conf, "/test", func(w http.ResponseWriter, r *http.Request) {
|
||||
_, err := w.Write([]byte("Test Content"))
|
||||
ctx.Require.NoError(err)
|
||||
})
|
||||
defer server.Shutdown(ctx)
|
||||
// Call /test
|
||||
byts := httpGet(ctx, client, "http://"+onion.ID+".onion/test")
|
||||
ctx.Require.Equal("Test Content", string(byts))
|
||||
}
|
||||
|
||||
// Only have to shutdown the HTTP server
|
||||
func startHTTPServer(
|
||||
ctx *TestContext,
|
||||
listenConf *tor.ListenConf,
|
||||
handlePattern string,
|
||||
handler func(http.ResponseWriter, *http.Request),
|
||||
) (*http.Client, *http.Server, *tor.OnionService) {
|
||||
httpClient := httpClient(ctx)
|
||||
// Wait at most a few minutes for the entire test
|
||||
listenCtx, listenCancel := context.WithTimeout(context.Background(), 4*time.Minute)
|
||||
defer listenCancel()
|
||||
// Create an onion service to listen on random port but show as 80
|
||||
onion, err := ctx.Listen(listenCtx, listenConf)
|
||||
ctx.Require.NoError(err)
|
||||
// Make HTTP server
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc(handlePattern, handler)
|
||||
httpServer := &http.Server{Handler: mux}
|
||||
go func() { ctx.Require.Equal(http.ErrServerClosed, httpServer.Serve(onion)) }()
|
||||
return httpClient, httpServer, onion
|
||||
}
|
|
@ -102,6 +102,11 @@ type StartConf struct {
|
|||
|
||||
// NoHush if true does not set --hush. By default --hush is set.
|
||||
NoHush bool
|
||||
|
||||
// NoAutoSocksPort if true does not set "--SocksPort auto" as is done by
|
||||
// default. This means the caller could set their own or just let it
|
||||
// default to 9050.
|
||||
NoAutoSocksPort bool
|
||||
}
|
||||
|
||||
// Start a Tor instance and connect to it. If ctx is nil, context.Background()
|
||||
|
@ -175,6 +180,9 @@ func (t *Tor) startProcess(ctx context.Context, conf *StartConf) error {
|
|||
if !conf.NoHush {
|
||||
args = append(args, "--hush")
|
||||
}
|
||||
if !conf.NoAutoSocksPort {
|
||||
args = append(args, "--SocksPort", "auto")
|
||||
}
|
||||
// If there is no Torrc file, create a blank temp one
|
||||
torrcFileName := conf.TorrcFile
|
||||
if torrcFileName == "" {
|
||||
|
|
Loading…
Reference in New Issue