package firewall import ( "strings" "testing" ) func TestBuildNATRuleLines_InterfaceList(t *testing.T) { rule := NATRule{ ID: "nat-test-1", Order: 1, Chain: "srcnat", Action: "masquerade", OutInterface: "wan0", Disabled: false, } resolved := resolveRoles([]byte(`{"interfaces":{"wan0":{"role":"WAN"},"lan0":{"role":"LAN"}}}`), "WAN") if len(resolved) != 1 || resolved[0] != "wan0" { t.Fatal(resolved) } lines := buildNATRuleLines(rule) if len(lines) == 0 { t.Fatalf("expected non-empty lines for WAN interface list, got 0") } for _, l := range lines { if !strings.Contains(l, "-j MASQUERADE") { t.Errorf("line missing -j MASQUERADE: %s", l) } if !strings.Contains(l, "-o ") { t.Errorf("expected -o flag in expanded NAT rule, got: %s", l) } } } func TestBuildRuleLines_SDWANGroup(t *testing.T) { oldResolver := SDWANResolver defer func() { SDWANResolver = oldResolver }() SDWANResolver = func(groupName string) []string { if groupName == "sdwan0" { return []string{"eth0", "eth1"} } return nil } rule := FilterRule{ ID: "filter-sdwan-1", Order: 1, Chain: "forward", Action: "drop", OutInterface: "sdwan0", Protocol: "tcp", DstPort: "25", Disabled: false, } lines := buildFilterRuleLines(rule) if len(lines) != 2 { t.Fatalf("expected 2 lines for 2 SD-WAN member interfaces, got %d", len(lines)) } if !strings.Contains(lines[0], "-o eth0") && !strings.Contains(lines[1], "-o eth0") { t.Errorf("expected eth0 in lines: %v", lines) } if !strings.Contains(lines[0], "-o eth1") && !strings.Contains(lines[1], "-o eth1") { t.Errorf("expected eth1 in lines: %v", lines) } }