diff options
| author | julianknodt <julianknodt@gmail.com> | 2021-07-23 15:43:35 -0700 |
|---|---|---|
| committer | julianknodt <julianknodt@gmail.com> | 2021-07-23 15:45:28 -0700 |
| commit | 4f0d35a47fc4230cba3f983371a00e2b0d97ac76 (patch) | |
| tree | 6ef922e4021e4d2dd49e16eea717bfb3a9d2913d | |
| parent | d145c594ad6b2bd2ce9d04b96ab89d8f30203a7a (diff) | |
| download | tailscale-jknodt/vms_ref.tar.xz tailscale-jknodt/vms_ref.zip | |
tstest/integration/vms: mv into own fnsjknodt/vms_ref
While reading through these tests, I found it really difficult to grok the dependencies of each
one, and if any of them modify the environment in some way. This makes it clear that each test
is running in its own scope, and what is exactly necessary for each test, as well as making the
entry point cleaner and easier to add into for more tests.
Signed-off-by: julianknodt <julianknodt@gmail.com>
| -rw-r--r-- | tstest/integration/vms/vms_test.go | 386 |
1 files changed, 196 insertions, 190 deletions
diff --git a/tstest/integration/vms/vms_test.go b/tstest/integration/vms/vms_test.go index 689cd5f8e..1f45d0295 100644 --- a/tstest/integration/vms/vms_test.go +++ b/tstest/integration/vms/vms_test.go @@ -362,61 +362,6 @@ func (h *Harness) testDistro(t *testing.T, d Distro, ipm ipMapping) { }) }) - t.Run("tailscale status", func(t *testing.T) { - dur := 100 * time.Millisecond - var outp []byte - var err error - - // NOTE(Xe): retry `tailscale status` a few times until it works. When tailscaled - // starts with testcontrol sometimes there can be up to a few seconds where - // tailscaled is in an unknown state on these virtual machines. This exponential - // delay loop should delay long enough for tailscaled to be ready. - for count := 0; count < 10; count++ { - sess := getSession(t, cli) - - outp, err = sess.CombinedOutput("tailscale status") - if err == nil { - if !strings.Contains(string(outp), "100.64.0.1") { - t.Log(string(outp)) - t.Fatal("can't find tester IP") - } - - return - } - time.Sleep(dur) - dur = dur * 2 - } - - t.Log(string(outp)) - t.Fatalf("error: %v", err) - }) - - t.Run("dump routes", func(t *testing.T) { - sess, err := cli.NewSession() - if err != nil { - t.Fatal(err) - } - defer sess.Close() - sess.Stdout = logger.FuncWriter(t.Logf) - sess.Stderr = logger.FuncWriter(t.Logf) - err = sess.Run("ip route show table 52") - if err != nil { - t.Fatal(err) - } - - sess, err = cli.NewSession() - if err != nil { - t.Fatal(err) - } - defer sess.Close() - sess.Stdout = logger.FuncWriter(t.Logf) - sess.Stderr = logger.FuncWriter(t.Logf) - err = sess.Run("ip -6 route show table 52") - if err != nil { - t.Fatal(err) - } - }) - for _, tt := range []struct { ipProto string addr netaddr.IP @@ -443,178 +388,239 @@ func (h *Harness) testDistro(t *testing.T, d Distro, ipm ipMapping) { }) } - t.Run("incoming-ssh-ipv4", func(t *testing.T) { - sess, err := cli.NewSession() - if err != nil { - t.Fatalf("can't make incoming session: %v", err) - } - defer sess.Close() - ipBytes, err := sess.Output("tailscale ip -4") - if err != nil { - t.Fatalf("can't run `tailscale ip -4`: %v", err) - } - ip := string(bytes.TrimSpace(ipBytes)) + t.Run("tailscale status", func(t *testing.T) { testTailscaleStatus(t, cli) }) + t.Run("dump routes", func(t *testing.T) { testDumpRoutes(t, cli) }) + t.Run("incoming-ssh-ipv4", func(t *testing.T) { testIncomingSSHIPv4(t, h, cli, ccfg) }) + t.Run("outgoing-udp-ipv4", func(t *testing.T) { testOutgoingUDPIPv4(t, h, cli) }) + t.Run("incoming-udp-ipv4", func(t *testing.T) { testIncomingUDPIPv4(t, h, cli) }) +} - conn, err := h.testerDialer.Dial("tcp", net.JoinHostPort(ip, "22")) - if err != nil { - t.Fatalf("can't dial connection to vm: %v", err) - } - defer conn.Close() - conn.SetDeadline(time.Now().Add(30 * time.Second)) +func testTailscaleStatus(t *testing.T, cli *ssh.Client) { + dur := 100 * time.Millisecond + var outp []byte + var err error - sshConn, chanchan, reqchan, err := ssh.NewClientConn(conn, net.JoinHostPort(ip, "22"), ccfg) - if err != nil { - t.Fatalf("can't negotiate connection over tailscale: %v", err) - } - defer sshConn.Close() + // NOTE(Xe): retry `tailscale status` a few times until it works. When tailscaled + // starts with testcontrol sometimes there can be up to a few seconds where + // tailscaled is in an unknown state on these virtual machines. This exponential + // delay loop should delay long enough for tailscaled to be ready. + for count := 0; count < 10; count++ { + sess := getSession(t, cli) - cli := ssh.NewClient(sshConn, chanchan, reqchan) - defer cli.Close() + outp, err = sess.CombinedOutput("tailscale status") + if err == nil { + if !strings.Contains(string(outp), "100.64.0.1") { + t.Log(string(outp)) + t.Fatal("can't find tester IP") + } - sess, err = cli.NewSession() - if err != nil { - t.Fatalf("can't make SSH session with VM: %v", err) + return } - defer sess.Close() + time.Sleep(dur) + dur = dur * 2 + } - testIPBytes, err := sess.Output("tailscale ip -4") - if err != nil { - t.Fatalf("can't run command on remote VM: %v", err) - } + t.Log(string(outp)) + t.Fatalf("error: %v", err) +} - if !bytes.Equal(testIPBytes, ipBytes) { - t.Fatalf("wanted reported ip to be %q, got: %q", string(ipBytes), string(testIPBytes)) - } - }) +func testDumpRoutes(t *testing.T, cli *ssh.Client) { + sess, err := cli.NewSession() + if err != nil { + t.Fatal(err) + } + defer sess.Close() + sess.Stdout = logger.FuncWriter(t.Logf) + sess.Stderr = logger.FuncWriter(t.Logf) + err = sess.Run("ip route show table 52") + if err != nil { + t.Fatal(err) + } - t.Run("outgoing-udp-ipv4", func(t *testing.T) { - cwd, err := os.Getwd() - if err != nil { - t.Fatalf("can't get working directory: %v", err) - } - dir := t.TempDir() - run(t, cwd, "go", "build", "-o", filepath.Join(dir, "udp_tester"), "./udp_tester.go") + sess, err = cli.NewSession() + if err != nil { + t.Fatal(err) + } + defer sess.Close() + sess.Stdout = logger.FuncWriter(t.Logf) + sess.Stderr = logger.FuncWriter(t.Logf) + err = sess.Run("ip -6 route show table 52") + if err != nil { + t.Fatal(err) + } +} - sftpCli, err := sftp.NewClient(cli) - if err != nil { - t.Fatalf("can't connect over sftp to copy binaries: %v", err) - } - defer sftpCli.Close() +func testIncomingSSHIPv4(t *testing.T, h *Harness, cli *ssh.Client, ccfg *ssh.ClientConfig) { + sess, err := cli.NewSession() + if err != nil { + t.Fatalf("can't make incoming session: %v", err) + } + defer sess.Close() + ipBytes, err := sess.Output("tailscale ip -4") + if err != nil { + t.Fatalf("can't run `tailscale ip -4`: %v", err) + } + ip := string(bytes.TrimSpace(ipBytes)) - copyFile(t, sftpCli, filepath.Join(dir, "udp_tester"), "/udp_tester") + conn, err := h.testerDialer.Dial("tcp", net.JoinHostPort(ip, "22")) + if err != nil { + t.Fatalf("can't dial connection to vm: %v", err) + } + defer conn.Close() + conn.SetDeadline(time.Now().Add(30 * time.Second)) - uaddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort("::", "0")) - if err != nil { - t.Fatalf("can't resolve udp listener addr: %v", err) - } + sshConn, chanchan, reqchan, err := ssh.NewClientConn(conn, net.JoinHostPort(ip, "22"), ccfg) + if err != nil { + t.Fatalf("can't negotiate connection over tailscale: %v", err) + } + defer sshConn.Close() - buf := make([]byte, 2048) + cli = ssh.NewClient(sshConn, chanchan, reqchan) + defer cli.Close() - ln, err := net.ListenUDP("udp", uaddr) - if err != nil { - t.Fatalf("can't listen for UDP traffic: %v", err) - } - defer ln.Close() + sess, err = cli.NewSession() + if err != nil { + t.Fatalf("can't make SSH session with VM: %v", err) + } + defer sess.Close() + + testIPBytes, err := sess.Output("tailscale ip -4") + if err != nil { + t.Fatalf("can't run command on remote VM: %v", err) + } - ctx, cancel := context.WithCancel(context.Background()) - t.Cleanup(cancel) + if !bytes.Equal(testIPBytes, ipBytes) { + t.Fatalf("wanted reported ip to be %q, got: %q", string(ipBytes), string(testIPBytes)) + } +} + +func testOutgoingUDPIPv4(t *testing.T, h *Harness, cli *ssh.Client) { + cwd, err := os.Getwd() + if err != nil { + t.Fatalf("can't get working directory: %v", err) + } + dir := t.TempDir() + run(t, cwd, "go", "build", "-o", filepath.Join(dir, "udp_tester"), "./udp_tester.go") + + sftpCli, err := sftp.NewClient(cli) + if err != nil { + t.Fatalf("can't connect over sftp to copy binaries: %v", err) + } + defer sftpCli.Close() - go func() { - for { - select { - case <-ctx.Done(): - return - default: - } + copyFile(t, sftpCli, filepath.Join(dir, "udp_tester"), "/udp_tester") - sess, err := cli.NewSession() - if err != nil { - t.Errorf("can't open session: %v", err) - return - } - defer sess.Close() + uaddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort("::", "0")) + if err != nil { + t.Fatalf("can't resolve udp listener addr: %v", err) + } - sess.Stdin = strings.NewReader("hi") - sess.Stdout = logger.FuncWriter(t.Logf) - sess.Stderr = logger.FuncWriter(t.Logf) + buf := make([]byte, 2048) - _, port, _ := net.SplitHostPort(ln.LocalAddr().String()) + ln, err := net.ListenUDP("udp", uaddr) + if err != nil { + t.Fatalf("can't listen for UDP traffic: %v", err) + } + defer ln.Close() - cmd := fmt.Sprintf("/udp_tester -client %s\n", net.JoinHostPort("100.64.0.1", port)) - t.Logf("sending packet: %s", cmd) - err = sess.Run(cmd) - if err != nil { - t.Logf("can't send UDP packet: %v", err) - } + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) - time.Sleep(10 * time.Millisecond) + go func() { + for { + select { + case <-ctx.Done(): + return + default: } - }() - t.Log("listening for packet") - n, _, err := ln.ReadFromUDP(buf) - if err != nil { - t.Fatal(err) - } + sess, err := cli.NewSession() + if err != nil { + t.Errorf("can't open session: %v", err) + return + } + defer sess.Close() - if n == 0 { - t.Fatal("got nothing") - } + sess.Stdin = strings.NewReader("hi") + sess.Stdout = logger.FuncWriter(t.Logf) + sess.Stderr = logger.FuncWriter(t.Logf) - if !bytes.Contains(buf, []byte("hi")) { - t.Fatal("did not get UDP message") - } - }) + _, port, _ := net.SplitHostPort(ln.LocalAddr().String()) - t.Run("incoming-udp-ipv4", func(t *testing.T) { - // vms_test.go:947: can't dial: socks connect udp 127.0.0.1:36497->100.64.0.2:33409: network not implemented - t.Skip("can't make outgoing sockets over UDP with our socks server") + cmd := fmt.Sprintf("/udp_tester -client %s\n", net.JoinHostPort("100.64.0.1", port)) + t.Logf("sending packet: %s", cmd) + err = sess.Run(cmd) + if err != nil { + t.Logf("can't send UDP packet: %v", err) + } - sess, err := cli.NewSession() - if err != nil { - t.Fatalf("can't open session: %v", err) + time.Sleep(10 * time.Millisecond) } - defer sess.Close() + }() - ip, err := sess.Output("tailscale ip -4") - if err != nil { - t.Fatalf("can't nab ipv4 address: %v", err) - } + t.Log("listening for packet") + n, _, err := ln.ReadFromUDP(buf) + if err != nil { + t.Fatal(err) + } - port, err := getProbablyFreePortNumber() - if err != nil { - t.Fatalf("unable to fetch port number: %v", err) - } + if n == 0 { + t.Fatal("got nothing") + } - go func() { - time.Sleep(10 * time.Millisecond) + if !bytes.Contains(buf, []byte("hi")) { + t.Fatal("did not get UDP message") + } +} - conn, err := h.testerDialer.Dial("udp", net.JoinHostPort(string(bytes.TrimSpace(ip)), strconv.Itoa(port))) - if err != nil { - t.Errorf("can't dial: %v", err) - } +func testIncomingUDPIPv4(t *testing.T, h *Harness, cli *ssh.Client) { + // vms_test.go:947: can't dial: socks connect udp 127.0.0.1:36497->100.64.0.2:33409: network not implemented + t.Skip("can't make outgoing sockets over UDP with our socks server") - fmt.Fprint(conn, securePassword) - }() + sess, err := cli.NewSession() + if err != nil { + t.Fatalf("can't open session: %v", err) + } + defer sess.Close() - sess, err = cli.NewSession() + ip, err := sess.Output("tailscale ip -4") + if err != nil { + t.Fatalf("can't nab ipv4 address: %v", err) + } + + port, err := getProbablyFreePortNumber() + if err != nil { + t.Fatalf("unable to fetch port number: %v", err) + } + + go func() { + time.Sleep(10 * time.Millisecond) + + conn, err := h.testerDialer.Dial("udp", net.JoinHostPort(string(bytes.TrimSpace(ip)), strconv.Itoa(port))) if err != nil { - t.Fatalf("can't open session: %v", err) + t.Errorf("can't dial: %v", err) } - defer sess.Close() - sess.Stderr = logger.FuncWriter(t.Logf) - msg, err := sess.Output( - fmt.Sprintf( - "/udp_tester -server %s", - net.JoinHostPort(string(bytes.TrimSpace(ip)), strconv.Itoa(port)), - ), - ) + fmt.Fprint(conn, securePassword) + }() - if msg := string(bytes.TrimSpace(msg)); msg != securePassword { - t.Fatalf("wanted %q from vm, got: %q", securePassword, msg) - } - }) + sess, err = cli.NewSession() + if err != nil { + t.Fatalf("can't open session: %v", err) + } + defer sess.Close() + sess.Stderr = logger.FuncWriter(t.Logf) + + msg, err := sess.Output( + fmt.Sprintf( + "/udp_tester -server %s", + net.JoinHostPort(string(bytes.TrimSpace(ip)), strconv.Itoa(port)), + ), + ) + + if msg := string(bytes.TrimSpace(msg)); msg != securePassword { + t.Fatalf("wanted %q from vm, got: %q", securePassword, msg) + } } func runTestCommands(t *testing.T, timeout time.Duration, cli *ssh.Client, batch []expect.Batcher) { |
