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),
|
ctx context.Context, events []EventCode, predicate func(Event) (bool, error),
|
||||||
) (Event, error) {
|
) (Event, error) {
|
||||||
eventCh := make(chan Event, 10)
|
eventCh := make(chan Event, 10)
|
||||||
defer close(eventCh)
|
|
||||||
if err := c.AddEventListener(eventCh, events...); err != nil {
|
if err := c.AddEventListener(eventCh, events...); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -131,6 +130,8 @@ func (c *Conn) EventWait(
|
||||||
go func() { errCh <- c.HandleEvents(eventCtx) }()
|
go func() { errCh <- c.HandleEvents(eventCtx) }()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
case <-eventCtx.Done():
|
||||||
|
return nil, eventCtx.Err()
|
||||||
case err := <-errCh:
|
case err := <-errCh:
|
||||||
return nil, err
|
return nil, err
|
||||||
case event := <-eventCh:
|
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 (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -1,4 +1,4 @@
|
||||||
package controltest
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
|
@ -0,0 +1,3 @@
|
||||||
|
package tests
|
||||||
|
|
||||||
|
// TODO: test several event parsers
|
|
@ -1,4 +1,4 @@
|
||||||
package controltest
|
package tests
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package controltest
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"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 if true does not set --hush. By default --hush is set.
|
||||||
NoHush bool
|
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()
|
// 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 {
|
if !conf.NoHush {
|
||||||
args = append(args, "--hush")
|
args = append(args, "--hush")
|
||||||
}
|
}
|
||||||
|
if !conf.NoAutoSocksPort {
|
||||||
|
args = append(args, "--SocksPort", "auto")
|
||||||
|
}
|
||||||
// If there is no Torrc file, create a blank temp one
|
// If there is no Torrc file, create a blank temp one
|
||||||
torrcFileName := conf.TorrcFile
|
torrcFileName := conf.TorrcFile
|
||||||
if torrcFileName == "" {
|
if torrcFileName == "" {
|
||||||
|
|
Loading…
Reference in New Issue