tsnet: add data transfer test
Signed-off-by: David Crawshaw <crawshaw@tailscale.com>pull/7368/head
parent
46467e39c2
commit
44e027abca
|
@ -204,11 +204,15 @@ func (s *Server) Close() error {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
// Perform a best-effort final flush.
|
// Perform a best-effort final flush.
|
||||||
s.logtail.Shutdown(ctx)
|
if s.logtail != nil {
|
||||||
s.logbuffer.Close()
|
s.logtail.Shutdown(ctx)
|
||||||
|
}
|
||||||
|
if s.logbuffer != nil {
|
||||||
|
s.logbuffer.Close()
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if _, isMemStore := s.Store.(*mem.Store); isMemStore && s.Ephemeral {
|
if _, isMemStore := s.Store.(*mem.Store); isMemStore && s.Ephemeral && s.lb != nil {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
@ -221,11 +225,21 @@ func (s *Server) Close() error {
|
||||||
s.netstack.Close()
|
s.netstack.Close()
|
||||||
s.netstack = nil
|
s.netstack = nil
|
||||||
}
|
}
|
||||||
s.shutdownCancel()
|
if s.shutdownCancel != nil {
|
||||||
s.lb.Shutdown()
|
s.shutdownCancel()
|
||||||
s.linkMon.Close()
|
}
|
||||||
s.dialer.Close()
|
if s.lb != nil {
|
||||||
s.localAPIListener.Close()
|
s.lb.Shutdown()
|
||||||
|
}
|
||||||
|
if s.linkMon != nil {
|
||||||
|
s.linkMon.Close()
|
||||||
|
}
|
||||||
|
if s.dialer != nil {
|
||||||
|
s.dialer.Close()
|
||||||
|
}
|
||||||
|
if s.localAPIListener != nil {
|
||||||
|
s.localAPIListener.Close()
|
||||||
|
}
|
||||||
|
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
|
|
@ -4,8 +4,23 @@
|
||||||
package tsnet
|
package tsnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path/filepath"
|
||||||
|
"os"
|
||||||
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tailscale.com/ipn/store/mem"
|
||||||
|
"tailscale.com/tailcfg"
|
||||||
|
"tailscale.com/tstest/integration"
|
||||||
|
"tailscale.com/net/netns"
|
||||||
|
"tailscale.com/tstest/integration/testcontrol"
|
||||||
|
"tailscale.com/types/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestListener_Server ensures that the listener type always keeps the Server
|
// TestListener_Server ensures that the listener type always keeps the Server
|
||||||
|
@ -44,3 +59,111 @@ func TestListenerPort(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var verboseDERP = flag.Bool("verbose-derp", false, "if set, print DERP and STUN logs")
|
||||||
|
var verboseNodes = flag.Bool("verbose-nodes", false, "if set, print tsnet.Server logs")
|
||||||
|
|
||||||
|
func TestConn(t *testing.T) {
|
||||||
|
// Corp#4520: don't use netns for tests.
|
||||||
|
netns.SetEnabled(false)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
netns.SetEnabled(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
derpLogf := logger.Discard
|
||||||
|
if *verboseDERP {
|
||||||
|
derpLogf = t.Logf
|
||||||
|
}
|
||||||
|
derpMap := integration.RunDERPAndSTUN(t, derpLogf, "127.0.0.1")
|
||||||
|
control := &testcontrol.Server{
|
||||||
|
DERPMap: derpMap,
|
||||||
|
}
|
||||||
|
control.HTTPTestServer = httptest.NewUnstartedServer(control)
|
||||||
|
control.HTTPTestServer.Start()
|
||||||
|
t.Cleanup(control.HTTPTestServer.Close)
|
||||||
|
controlURL := control.HTTPTestServer.URL
|
||||||
|
t.Logf("testcontrol listening on %s", controlURL)
|
||||||
|
|
||||||
|
tmp := t.TempDir()
|
||||||
|
tmps1 := filepath.Join(tmp, "s1")
|
||||||
|
os.MkdirAll(tmps1, 0755)
|
||||||
|
s1 := &Server{
|
||||||
|
Dir: tmps1,
|
||||||
|
ControlURL: controlURL,
|
||||||
|
Hostname: "s1",
|
||||||
|
Store: new(mem.Store),
|
||||||
|
Ephemeral: true,
|
||||||
|
}
|
||||||
|
defer s1.Close()
|
||||||
|
|
||||||
|
tmps2 := filepath.Join(tmp, "s1")
|
||||||
|
os.MkdirAll(tmps2, 0755)
|
||||||
|
s2 := &Server{
|
||||||
|
Dir: tmps2,
|
||||||
|
ControlURL: controlURL,
|
||||||
|
Hostname: "s2",
|
||||||
|
Store: new(mem.Store),
|
||||||
|
Ephemeral: true,
|
||||||
|
}
|
||||||
|
defer s2.Close()
|
||||||
|
|
||||||
|
if !*verboseNodes {
|
||||||
|
s1.Logf = logger.Discard
|
||||||
|
s2.Logf = logger.Discard
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
s1status, err := s1.Up(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
s1ip := s1status.TailscaleIPs[0]
|
||||||
|
if _, err := s2.Up(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lc2, err := s2.LocalClient()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ping to make sure the connection is up.
|
||||||
|
res, err := lc2.Ping(ctx, s1ip, tailcfg.PingICMP)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Logf("ping success: %#+v", res)
|
||||||
|
|
||||||
|
// pass some data through TCP.
|
||||||
|
ln, err := s1.Listen("tcp", ":8081")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
w, err := s2.Dial(ctx, "tcp", fmt.Sprintf("%s:8081", s1ip))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := ln.Accept()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := "hello"
|
||||||
|
if _, err := io.WriteString(w, want); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := make([]byte, len(want))
|
||||||
|
if _, err := io.ReadAtLeast(r, got, len(got)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Logf("got: %q", got)
|
||||||
|
if string(got) != want {
|
||||||
|
t.Errorf("got %q, want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue