tstest/natlab/vmtest, cmd/tta: add TestTaildrop
Add a vmtest that brings up two Ubuntu nodes, each behind its own EasyNAT, joined to the tailnet. The sender pushes a small file via "tailscale file cp" and the receiver fetches it via "tailscale file get --wait", asserting that the filename and contents round-trip unchanged. To make Taildrop work in vmtest, three small pieces were needed: The Linux/FreeBSD cloud-init now starts tailscaled with --statedir as well as --state=mem:, so the daemon has a VarRoot to host Taildrop's incoming-files directory. State itself remains in-memory (so nothing persists across reboots); only the var-root scratch space is on disk. vmtest.New grows a variadic EnvOption parameter and a SameTailnetUser helper. When the option is passed, Start sets AllNodesSameUser=true on the embedded testcontrol.Server. Cross-node Taildrop requires the sender and receiver to share a Tailnet user (or have an explicit PeerCapabilityFileSharingTarget granted between them, which we don't plumb here), so TestTaildrop opts in. Existing tests don't. cmd/tta gains /taildrop-send and /taildrop-recv handlers that wrap "tailscale file cp" and "tailscale file get --wait", plus Env.SendTaildropFile and Env.RecvTaildropFile helpers in vmtest that drive them. Updates #13038 Change-Id: I8f5f70f88106e6e2ee07780dd46fe00f8efcfdf1 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
4b8e0ede6d
commit
ec7b11d986
@@ -4,6 +4,7 @@
|
||||
package vmtest_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"strings"
|
||||
@@ -363,6 +364,58 @@ func TestSubnetRouterAndExitNode(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaildrop verifies that one Ubuntu node can send a file to another
|
||||
// Ubuntu node via Taildrop, and the receiver gets the same content.
|
||||
//
|
||||
// Topology: two Ubuntu nodes, each behind its own EasyNAT, both joined to the
|
||||
// tailnet. The sender runs `tailscale file cp` to push to the receiver's
|
||||
// Tailscale IP; the receiver then runs `tailscale file get --wait` to fetch
|
||||
// it.
|
||||
func TestTaildrop(t *testing.T) {
|
||||
env := vmtest.New(t, vmtest.SameTailnetUser())
|
||||
|
||||
senderNet := env.AddNetwork("1.0.0.1", "192.168.1.1/24", vnet.EasyNAT)
|
||||
receiverNet := env.AddNetwork("2.0.0.1", "192.168.2.1/24", vnet.EasyNAT)
|
||||
|
||||
sender := env.AddNode("sender", senderNet,
|
||||
vmtest.OS(vmtest.Ubuntu2404))
|
||||
receiver := env.AddNode("receiver", receiverNet,
|
||||
vmtest.OS(vmtest.Ubuntu2404))
|
||||
|
||||
// Declare test-specific steps for the web UI.
|
||||
sendStep := env.AddStep("Taildrop send (sender -> receiver)")
|
||||
recvStep := env.AddStep("Taildrop receive (on receiver)")
|
||||
verifyStep := env.AddStep("Verify received name and contents")
|
||||
|
||||
env.Start()
|
||||
|
||||
const filename = "hello.txt"
|
||||
want := []byte("hello world this is a Taildrop test\n")
|
||||
|
||||
sendStep.Begin()
|
||||
env.SendTaildropFile(sender, receiver, filename, want)
|
||||
sendStep.End(nil)
|
||||
|
||||
recvStep.Begin()
|
||||
gotName, gotContent := env.RecvTaildropFile(t.Context(), receiver)
|
||||
recvStep.End(nil)
|
||||
|
||||
verifyStep.Begin()
|
||||
if gotName != filename {
|
||||
err := fmt.Errorf("received name = %q; want %q", gotName, filename)
|
||||
verifyStep.End(err)
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(gotContent, want) {
|
||||
err := fmt.Errorf("received content = %q; want %q", gotContent, want)
|
||||
verifyStep.End(err)
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
verifyStep.End(nil)
|
||||
}
|
||||
|
||||
// TestExitNode verifies that switching the client's exit node setting between
|
||||
// off, exit1, and exit2 correctly routes the client's internet traffic.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user