mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-30 05:25:35 +00:00
7330aa593e
On some platforms (notably macOS and iOS) we look up the default interface to bind outgoing connections to. This is both duplicated work and results in logspam when the default interface is not available (i.e. when a phone has no connectivity, we log an error and thus cause more things that we will try to upload and fail). Fixed by passing around a netmon.Monitor to more places, so that we can use its cached interface state. Fixes #7850 Updates #7621 Signed-off-by: Mihai Parparita <mihai@tailscale.com>
125 lines
2.9 KiB
Go
125 lines
2.9 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package portmapper
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"reflect"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestCreateOrGetMapping(t *testing.T) {
|
|
if v, _ := strconv.ParseBool(os.Getenv("HIT_NETWORK")); !v {
|
|
t.Skip("skipping test without HIT_NETWORK=1")
|
|
}
|
|
c := NewClient(t.Logf, nil, nil, nil)
|
|
defer c.Close()
|
|
c.SetLocalPort(1234)
|
|
for i := 0; i < 2; i++ {
|
|
if i > 0 {
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
ext, err := c.createOrGetMapping(context.Background())
|
|
t.Logf("Got: %v, %v", ext, err)
|
|
}
|
|
}
|
|
|
|
func TestClientProbe(t *testing.T) {
|
|
if v, _ := strconv.ParseBool(os.Getenv("HIT_NETWORK")); !v {
|
|
t.Skip("skipping test without HIT_NETWORK=1")
|
|
}
|
|
c := NewClient(t.Logf, nil, nil, nil)
|
|
defer c.Close()
|
|
for i := 0; i < 3; i++ {
|
|
if i > 0 {
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
res, err := c.Probe(context.Background())
|
|
t.Logf("Got(t=%dms): %+v, %v", i*100, res, err)
|
|
}
|
|
}
|
|
|
|
func TestClientProbeThenMap(t *testing.T) {
|
|
if v, _ := strconv.ParseBool(os.Getenv("HIT_NETWORK")); !v {
|
|
t.Skip("skipping test without HIT_NETWORK=1")
|
|
}
|
|
c := NewClient(t.Logf, nil, nil, nil)
|
|
defer c.Close()
|
|
c.SetLocalPort(1234)
|
|
res, err := c.Probe(context.Background())
|
|
t.Logf("Probe: %+v, %v", res, err)
|
|
ext, err := c.createOrGetMapping(context.Background())
|
|
t.Logf("createOrGetMapping: %v, %v", ext, err)
|
|
}
|
|
|
|
func TestProbeIntegration(t *testing.T) {
|
|
igd, err := NewTestIGD(t.Logf, TestIGDOptions{PMP: true, PCP: true, UPnP: true})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer igd.Close()
|
|
|
|
c := newTestClient(t, igd)
|
|
t.Logf("Listening on pxp=%v, upnp=%v", c.testPxPPort, c.testUPnPPort)
|
|
defer c.Close()
|
|
|
|
res, err := c.Probe(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("Probe: %v", err)
|
|
}
|
|
if !res.UPnP {
|
|
t.Errorf("didn't detect UPnP")
|
|
}
|
|
st := igd.stats()
|
|
want := igdCounters{
|
|
numUPnPDiscoRecv: 1,
|
|
numPMPRecv: 1,
|
|
numPCPRecv: 1,
|
|
numPCPDiscoRecv: 1,
|
|
numPMPPublicAddrRecv: 1,
|
|
}
|
|
if !reflect.DeepEqual(st, want) {
|
|
t.Errorf("unexpected stats:\n got: %+v\nwant: %+v", st, want)
|
|
}
|
|
|
|
t.Logf("Probe: %+v", res)
|
|
t.Logf("IGD stats: %+v", st)
|
|
// TODO(bradfitz): finish
|
|
}
|
|
|
|
func TestPCPIntegration(t *testing.T) {
|
|
igd, err := NewTestIGD(t.Logf, TestIGDOptions{PMP: false, PCP: true, UPnP: false})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer igd.Close()
|
|
|
|
c := newTestClient(t, igd)
|
|
defer c.Close()
|
|
res, err := c.Probe(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("probe failed: %v", err)
|
|
}
|
|
if res.UPnP || res.PMP {
|
|
t.Errorf("probe unexpectedly saw upnp or pmp: %+v", res)
|
|
}
|
|
if !res.PCP {
|
|
t.Fatalf("probe did not see pcp: %+v", res)
|
|
}
|
|
|
|
external, err := c.createOrGetMapping(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("failed to get mapping: %v", err)
|
|
}
|
|
if !external.IsValid() {
|
|
t.Errorf("got zero IP, expected non-zero")
|
|
}
|
|
if c.mapping == nil {
|
|
t.Errorf("got nil mapping after successful createOrGetMapping")
|
|
}
|
|
}
|