package hostnat import ( "slices" "testing" ) func TestParseDefaultUplink(t *testing.T) { t.Parallel() output := "default via 192.168.1.1 dev enp5s0 proto dhcp src 192.168.1.40 metric 100\n" uplink, err := ParseDefaultUplink(output) if err != nil { t.Fatalf("ParseDefaultUplink returned error: %v", err) } if uplink != "enp5s0" { t.Fatalf("uplink = %q, want enp5s0", uplink) } } func TestParseDefaultUplinkFailsWithoutRoute(t *testing.T) { t.Parallel() if _, err := ParseDefaultUplink("10.0.0.0/24 dev br-fc proto kernel scope link src 10.0.0.1\n"); err == nil { t.Fatal("expected ParseDefaultUplink to fail without a default route") } } func TestRulesRequireRuntimeData(t *testing.T) { t.Parallel() tests := []struct { name string guestIP string tapDevice string uplink string }{ {name: "guest ip", tapDevice: "tap-fc-abcd1234", uplink: "eth0"}, {name: "tap", guestIP: "172.16.0.8", uplink: "eth0"}, {name: "uplink", guestIP: "172.16.0.8", tapDevice: "tap-fc-abcd1234"}, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() if _, err := Rules(tt.guestIP, tt.tapDevice, tt.uplink); err == nil { t.Fatalf("expected Rules to fail for missing %s", tt.name) } }) } } func TestRulePlans(t *testing.T) { t.Parallel() rules, err := Rules("172.16.0.8", "tap-fc-abcd1234", "eth0") if err != nil { t.Fatalf("Rules returned error: %v", err) } if len(rules) != 3 { t.Fatalf("rule count = %d, want 3", len(rules)) } if got, want := RuleArgs("-A", rules[0]), []string{"-t", "nat", "-A", "POSTROUTING", "-s", "172.16.0.8/32", "-o", "eth0", "-j", "MASQUERADE"}; !slices.Equal(got, want) { t.Fatalf("postrouting args = %v, want %v", got, want) } if got, want := RuleArgs("-A", rules[1]), []string{"-A", "FORWARD", "-i", "tap-fc-abcd1234", "-o", "eth0", "-j", "ACCEPT"}; !slices.Equal(got, want) { t.Fatalf("forward-out args = %v, want %v", got, want) } if got, want := RuleArgs("-A", rules[2]), []string{"-A", "FORWARD", "-i", "eth0", "-o", "tap-fc-abcd1234", "-m", "state", "--state", "RELATED,ESTABLISHED", "-j", "ACCEPT"}; !slices.Equal(got, want) { t.Fatalf("forward-in args = %v, want %v", got, want) } addPlan := AddPlan(rules) if got, want := addPlan[0], []string{"sysctl", "-w", "net.ipv4.ip_forward=1"}; !slices.Equal(got, want) { t.Fatalf("sysctl command = %v, want %v", got, want) } removePlan := RemovePlan(rules) if got, want := removePlan[0], []string{"-t", "nat", "-D", "POSTROUTING", "-s", "172.16.0.8/32", "-o", "eth0", "-j", "MASQUERADE"}; !slices.Equal(got, want) { t.Fatalf("remove NAT command = %v, want %v", got, want) } }