diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 70e2870e0..4370fef73 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -11,7 +11,6 @@ import ( "crypto/tls" "encoding/binary" "encoding/json" - "errors" "fmt" "io/ioutil" "net" @@ -535,93 +534,6 @@ func TestDeviceStartStop(t *testing.T) { dev.Close() } -// A context used in TestConnClosing() which seeks to test that code which calls -// Err() to see if a connection is already being closed does not then proceed to -// try to acquire the mutex, as this would lead to deadlock. When Err() is called -// this context acquires the lock itself, in order to force a deadlock (and test -// failure on timeout). -type testConnClosingContext struct { - parent context.Context - mu *sync.Mutex -} - -func (c *testConnClosingContext) Deadline() (deadline time.Time, ok bool) { - d, o := c.parent.Deadline() - return d, o -} -func (c *testConnClosingContext) Done() <-chan struct{} { - return c.parent.Done() -} -func (c *testConnClosingContext) Err() error { - // Deliberately deadlock if anything grabs the lock after checking Err() - c.mu.Lock() - return errors.New("testConnClosingContext error") -} -func (c *testConnClosingContext) Value(key interface{}) interface{} { - return c.parent.Value(key) -} -func (*testConnClosingContext) String() string { - return "testConnClosingContext" -} - -func TestConnClosing(t *testing.T) { - privateKey, err := wgkey.NewPrivate() - if err != nil { - t.Fatalf("generating private key: %v", err) - } - - logf, closeLogf := logger.LogfCloser(t.Logf) - defer closeLogf() - - epCh := make(chan []string, 100) - conn, err := NewConn(Options{ - Logf: logf, - PacketListener: nettype.Std{}, - EndpointsFunc: func(eps []string) { - epCh <- eps - }, - SimulatedNetwork: false, - DisableLegacyNetworking: true, - }) - if err != nil { - t.Fatalf("constructing magicsock: %v", err) - } - - derpMap, cleanup := runDERPAndStun(t, logf, nettype.Std{}, netaddr.IPv4(127, 0, 3, 1)) - defer cleanup() - - // The point of this test case is to exercise handling in derpWriteChanOfAddr() which - // returns early if connCtx.Err() returns non-nil, to avoid a deadlock on conn.mu. - // We swap in a context which always returns an error, and deliberately grabs the lock - // to cause a deadlock if magicsock.go tries to acquire the lock after calling Err(). - closingCtx := testConnClosingContext{parent: conn.connCtx, mu: &conn.mu} - conn.connCtx = &closingCtx - conn.Start() - - conn.SetDERPMap(derpMap) - if err := conn.SetPrivateKey(privateKey); err != nil { - t.Fatalf("setting private key in magicsock: %v", err) - } - - tun := tuntest.NewChannelTUN() - tsTun := tstun.WrapTUN(logf, tun.TUN()) - tsTun.SetFilter(filter.NewAllowAllForTest(logf)) - - dev := device.NewDevice(tsTun, &device.DeviceOptions{ - Logger: wireguardGoLogger(logf), - CreateEndpoint: conn.CreateEndpoint, - CreateBind: conn.CreateBind, - SkipBindUpdate: true, - }) - - dev.Up() - conn.WaitReady(t) - - // We don't assert any failures within the test itself. If derpWriteChanOfAddr tries to - // grab the lock it will deadlock, and conn.WaitReady(t) will call t.Fatal() after timeout. - // (verified by deliberately breaking derpWriteChanOfAddr) -} - // Exercise a code path in sendDiscoMessage if the connection has been closed. func TestConnClosed(t *testing.T) { mstun := &natlab.Machine{Name: "stun"}