Files
wild-central/internal/config/extraports_test.go
2026-07-10 20:46:22 +00:00

115 lines
3.9 KiB
Go

package config
import (
"encoding/json"
"testing"
"gopkg.in/yaml.v3"
)
func TestExtraPortsJSONDecode_Legacy(t *testing.T) {
// Legacy format: plain integer array
input := `{"cloud":{"nftables":{"extraPorts":[22]}}}`
var cfg State
if err := json.Unmarshal([]byte(input), &cfg); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if len(cfg.Cloud.Nftables.ExtraPorts) != 1 || cfg.Cloud.Nftables.ExtraPorts[0].Port != 22 {
t.Errorf("after JSON decode: expected [{Port:22}], got %v", cfg.Cloud.Nftables.ExtraPorts)
}
}
func TestExtraPortsJSONDecode_Structured(t *testing.T) {
// New structured format
input := `{"cloud":{"nftables":{"extraPorts":[{"port":22,"protocol":"tcp","label":"SSH"},{"port":5353,"protocol":"udp"}]}}}`
var cfg State
if err := json.Unmarshal([]byte(input), &cfg); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if len(cfg.Cloud.Nftables.ExtraPorts) != 2 {
t.Fatalf("expected 2 ports, got %d", len(cfg.Cloud.Nftables.ExtraPorts))
}
if cfg.Cloud.Nftables.ExtraPorts[0].Port != 22 || cfg.Cloud.Nftables.ExtraPorts[0].Protocol != "tcp" || cfg.Cloud.Nftables.ExtraPorts[0].Label != "SSH" {
t.Errorf("port 0: expected {22,tcp,SSH}, got %+v", cfg.Cloud.Nftables.ExtraPorts[0])
}
if cfg.Cloud.Nftables.ExtraPorts[1].Port != 5353 || cfg.Cloud.Nftables.ExtraPorts[1].Protocol != "udp" {
t.Errorf("port 1: expected {5353,udp}, got %+v", cfg.Cloud.Nftables.ExtraPorts[1])
}
}
func TestExtraPortsJSONEncode(t *testing.T) {
var cfg State
cfg.Cloud.Nftables.ExtraPorts = []ExtraPort{{Port: 22, Protocol: "tcp", Label: "SSH"}}
out, err := json.Marshal(cfg)
if err != nil {
t.Fatalf("marshal: %v", err)
}
var decoded map[string]any
json.Unmarshal(out, &decoded)
cloud := decoded["cloud"].(map[string]any)
nft := cloud["nftables"].(map[string]any)
ports, ok := nft["extraPorts"]
if !ok {
t.Errorf("extraPorts missing from JSON output: %s", out)
}
arr := ports.([]any)
if len(arr) != 1 {
t.Fatalf("expected 1 port, got %d", len(arr))
}
entry := arr[0].(map[string]any)
if entry["port"].(float64) != 22 {
t.Errorf("expected port 22, got %v", entry["port"])
}
if entry["label"].(string) != "SSH" {
t.Errorf("expected label SSH, got %v", entry["label"])
}
}
func TestExtraPortsYAML_LegacyRoundTrip(t *testing.T) {
// Legacy YAML format with plain integers
input := "cloud:\n nftables:\n extraPorts:\n - 22\n - 8080\n"
var cfg State
if err := yaml.Unmarshal([]byte(input), &cfg); err != nil {
t.Fatalf("yaml unmarshal: %v", err)
}
if len(cfg.Cloud.Nftables.ExtraPorts) != 2 {
t.Fatalf("expected 2 ports, got %d", len(cfg.Cloud.Nftables.ExtraPorts))
}
if cfg.Cloud.Nftables.ExtraPorts[0].Port != 22 || cfg.Cloud.Nftables.ExtraPorts[1].Port != 8080 {
t.Errorf("expected [22, 8080], got %v", cfg.Cloud.Nftables.ExtraPorts)
}
}
func TestExtraPortsYAML_StructuredRoundTrip(t *testing.T) {
input := "cloud:\n nftables:\n extraPorts:\n - port: 22\n protocol: tcp\n label: SSH\n - port: 5353\n protocol: udp\n"
var cfg State
if err := yaml.Unmarshal([]byte(input), &cfg); err != nil {
t.Fatalf("yaml unmarshal: %v", err)
}
if len(cfg.Cloud.Nftables.ExtraPorts) != 2 {
t.Fatalf("expected 2 ports, got %d", len(cfg.Cloud.Nftables.ExtraPorts))
}
if cfg.Cloud.Nftables.ExtraPorts[0].Label != "SSH" {
t.Errorf("expected label SSH, got %q", cfg.Cloud.Nftables.ExtraPorts[0].Label)
}
if cfg.Cloud.Nftables.ExtraPorts[1].Protocol != "udp" {
t.Errorf("expected protocol udp, got %q", cfg.Cloud.Nftables.ExtraPorts[1].Protocol)
}
}
func TestSplitExtraPorts(t *testing.T) {
ports := []ExtraPort{
{Port: 22, Protocol: "tcp"},
{Port: 80}, // default = tcp
{Port: 5353, Protocol: "udp"},
{Port: 123, Protocol: "UDP"}, // case-insensitive
}
tcp, udp := SplitExtraPorts(ports)
if len(tcp) != 2 || tcp[0] != 22 || tcp[1] != 80 {
t.Errorf("expected tcp=[22,80], got %v", tcp)
}
if len(udp) != 2 || udp[0] != 5353 || udp[1] != 123 {
t.Errorf("expected udp=[5353,123], got %v", udp)
}
}