This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const testJSON = `{
|
||||
"networks": {
|
||||
"smarthost-loadbalancer": {
|
||||
"network_name": "smarthost-loadbalancer",
|
||||
"subnet": "172.18.103.0/24",
|
||||
"gateway": "172.18.103.1"
|
||||
},
|
||||
"smarthost_backend-1": {
|
||||
"network_name": "smarthost_backend-1",
|
||||
"subnet": "172.18.104.0/24",
|
||||
"gateway": "172.18.104.1"
|
||||
}
|
||||
},
|
||||
"ips": {
|
||||
"172.18.103.2": {
|
||||
"ip": "172.18.103.2",
|
||||
"container_name": "smarthostloadbalancer",
|
||||
"selector": "smarthostloadbalancer",
|
||||
"service_name": "smarthost-proxy"
|
||||
},
|
||||
"172.18.104.2": {
|
||||
"ip": "172.18.104.2",
|
||||
"container_name": "smarthostbackend-1",
|
||||
"selector": "smarthostbackend-1",
|
||||
"service_name": "smarthost-proxy"
|
||||
}
|
||||
},
|
||||
"policies": [
|
||||
{
|
||||
"service_name": "smarthost-proxy",
|
||||
"container_name": "smarthost_loadbalancer",
|
||||
"selector": "smarthostloadbalancer",
|
||||
"from": "publicbackend",
|
||||
"port": 80,
|
||||
"proto": "tcp"
|
||||
},
|
||||
{
|
||||
"service_name": "smarthost-proxy",
|
||||
"container_name": "smarthost_loadbalancer",
|
||||
"selector": "smarthostloadbalancer",
|
||||
"name": "wireguardproxy",
|
||||
"iface": "wg0",
|
||||
"nat": "dnat",
|
||||
"to": "smarthostloadbalancer",
|
||||
"port": 80,
|
||||
"proto": "tcp"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "networks.json")
|
||||
if err := os.WriteFile(path, []byte(testJSON), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
cfg, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Load() returned error: %v", err)
|
||||
}
|
||||
|
||||
if len(cfg.Networks) != 2 {
|
||||
t.Errorf("expected 2 networks, got %d", len(cfg.Networks))
|
||||
}
|
||||
|
||||
if cfg.Networks["smarthost-loadbalancer"].Subnet != "172.18.103.0/24" {
|
||||
t.Errorf("unexpected subnet: %s", cfg.Networks["smarthost-loadbalancer"].Subnet)
|
||||
}
|
||||
|
||||
if len(cfg.IPs) != 2 {
|
||||
t.Errorf("expected 2 IPs, got %d", len(cfg.IPs))
|
||||
}
|
||||
|
||||
if cfg.IPs["172.18.103.2"].ContainerName != "smarthostloadbalancer" {
|
||||
t.Errorf("unexpected container name: %s", cfg.IPs["172.18.103.2"].ContainerName)
|
||||
}
|
||||
|
||||
if len(cfg.Policies) != 2 {
|
||||
t.Errorf("expected 2 policies, got %d", len(cfg.Policies))
|
||||
}
|
||||
|
||||
if cfg.Policies[0].From != "publicbackend" {
|
||||
t.Errorf("unexpected from: %s", cfg.Policies[0].From)
|
||||
}
|
||||
|
||||
if cfg.Policies[1].Nat != "dnat" {
|
||||
t.Errorf("unexpected nat: %s", cfg.Policies[1].Nat)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFileNotFound(t *testing.T) {
|
||||
_, err := Load("/nonexistent/path/networks.json")
|
||||
if err == nil {
|
||||
t.Error("expected error for nonexistent file, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadInvalidJSON(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "bad.json")
|
||||
if err := os.WriteFile(path, []byte("{invalid json"), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
_, err := Load(path)
|
||||
if err == nil {
|
||||
t.Error("expected error for invalid JSON, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestToCIDR(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
want string
|
||||
}{
|
||||
{"172.18.103.0", "172.18.103.0/24"},
|
||||
{"172.18.103.2", "172.18.103.2"},
|
||||
{"172.18.103.0/24", "172.18.103.0/24"},
|
||||
{"10.0.0.0", "10.0.0.0/24"},
|
||||
{"invalid", "invalid"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := ToCIDR(tt.input)
|
||||
if got != tt.want {
|
||||
t.Errorf("ToCIDR(%q) = %q, want %q", tt.input, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetworkPrefix(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
want string
|
||||
}{
|
||||
{"172.18.103.2", "172.18.103.0/24"},
|
||||
{"10.0.0.1", "10.0.0.0/24"},
|
||||
{"invalid", "invalid"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := NetworkPrefix(tt.input)
|
||||
if got != tt.want {
|
||||
t.Errorf("NetworkPrefix(%q) = %q, want %q", tt.input, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsIP(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
want bool
|
||||
}{
|
||||
{"172.18.103.2", true},
|
||||
{"10.0.0.0", true},
|
||||
{"255.255.255.255", true},
|
||||
{"publicbackend", false},
|
||||
{"172.18.103.0/24", false},
|
||||
{"", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := IsIP(tt.input)
|
||||
if got != tt.want {
|
||||
t.Errorf("IsIP(%q) = %v, want %v", tt.input, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNetworkConfigParseCIDR(t *testing.T) {
|
||||
nc := NetworkConfig{Subnet: "172.18.103.0/24"}
|
||||
ipNet, err := nc.ParseCIDR()
|
||||
if err != nil {
|
||||
t.Fatalf("ParseCIDR() returned error: %v", err)
|
||||
}
|
||||
if ipNet.String() != "172.18.103.0/24" {
|
||||
t.Errorf("ParseCIDR() = %s, want 172.18.103.0/24", ipNet.String())
|
||||
}
|
||||
|
||||
nc2 := NetworkConfig{Subnet: "invalid"}
|
||||
_, err = nc2.ParseCIDR()
|
||||
if err == nil {
|
||||
t.Error("expected error for invalid subnet, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadReproducible(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "networks.json")
|
||||
if err := os.WriteFile(path, []byte(testJSON), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
// Load twice and compare
|
||||
cfg1, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("first Load() error: %v", err)
|
||||
}
|
||||
|
||||
cfg2, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("second Load() error: %v", err)
|
||||
}
|
||||
|
||||
// Verify reproducibility
|
||||
if len(cfg1.Networks) != len(cfg2.Networks) {
|
||||
t.Errorf("reproducibility: network count mismatch %d vs %d", len(cfg1.Networks), len(cfg2.Networks))
|
||||
}
|
||||
if len(cfg1.IPs) != len(cfg2.IPs) {
|
||||
t.Errorf("reproducibility: IP count mismatch %d vs %d", len(cfg1.IPs), len(cfg2.IPs))
|
||||
}
|
||||
if len(cfg1.Policies) != len(cfg2.Policies) {
|
||||
t.Errorf("reproducibility: policy count mismatch %d vs %d", len(cfg1.Policies), len(cfg2.Policies))
|
||||
}
|
||||
|
||||
for name, net1 := range cfg1.Networks {
|
||||
net2 := cfg2.Networks[name]
|
||||
if net1.Subnet != net2.Subnet || net1.Gateway != net2.Gateway {
|
||||
t.Errorf("reproducibility: network %s mismatch", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user