// Copyright (c) Tailscale Inc & contributors // SPDX-License-Identifier: BSD-3-Clause //go:build go1.19 package local import ( "context" "net" "net/http" "testing" "tailscale.com/tstest/deptest" "tailscale.com/tstest/nettest" "tailscale.com/types/key" ) func TestGetServeConfigFromJSON(t *testing.T) { sc, err := getServeConfigFromJSON([]byte("null")) if sc != nil { t.Errorf("want nil for null") } if err != nil { t.Errorf("reading null: %v", err) } sc, err = getServeConfigFromJSON([]byte(`{"TCP":{}}`)) if err != nil { t.Errorf("reading object: %v", err) } else if sc == nil { t.Errorf("want non-nil for object") } else if sc.TCP == nil { t.Errorf("want non-nil TCP for object") } } func TestWhoIsPeerNotFound(t *testing.T) { nw := nettest.GetNetwork(t) ts := nettest.NewHTTPServer(nw, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(404) })) defer ts.Close() lc := &Client{ Dial: func(ctx context.Context, network, addr string) (net.Conn, error) { return nw.Dial(ctx, network, ts.Listener.Addr().String()) }, } var k key.NodePublic if err := k.UnmarshalText([]byte("nodekey:5c8f86d5fc70d924e55f02446165a5dae8f822994ad26bcf4b08fd841f9bf261")); err != nil { t.Fatal(err) } res, err := lc.WhoIsNodeKey(context.Background(), k) if err != ErrPeerNotFound { t.Errorf("got (%v, %v), want ErrPeerNotFound", res, err) } res, err = lc.WhoIs(context.Background(), "1.2.3.4:5678") if err != ErrPeerNotFound { t.Errorf("got (%v, %v), want ErrPeerNotFound", res, err) } } func TestUserDialSelf(t *testing.T) { // Start a real TCP listener that the client should dial directly // when the server tells it to dial-self. ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } defer ln.Close() go func() { for { c, err := ln.Accept() if err != nil { return } c.Write([]byte("hello")) c.Close() } }() targetAddr := ln.Addr().(*net.TCPAddr) // Mock LocalAPI server that returns Dial-Self response. nw := nettest.GetNetwork(t) ts := nettest.NewHTTPServer(nw, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Dial-Self", "true") w.Header().Set("Dial-Addr", targetAddr.String()) w.WriteHeader(http.StatusOK) })) defer ts.Close() lc := &Client{ Dial: func(ctx context.Context, network, addr string) (net.Conn, error) { return nw.Dial(ctx, network, ts.Listener.Addr().String()) }, } conn, err := lc.UserDial(context.Background(), "tcp", targetAddr.IP.String(), uint16(targetAddr.Port)) if err != nil { t.Fatalf("UserDial: %v", err) } defer conn.Close() buf := make([]byte, 5) n, err := conn.Read(buf) if err != nil { t.Fatalf("Read: %v", err) } if got := string(buf[:n]); got != "hello" { t.Errorf("got %q, want %q", got, "hello") } } func TestDeps(t *testing.T) { deptest.DepChecker{ BadDeps: map[string]string{ // Make sure we don't again accidentally bring in a dependency on // drive or its transitive dependencies "testing": "do not use testing package in production code", "tailscale.com/drive/driveimpl": "https://github.com/tailscale/tailscale/pull/10631", "github.com/studio-b12/gowebdav": "https://github.com/tailscale/tailscale/pull/10631", }, }.Check(t) }