package main import ( "os" "path/filepath" "strings" "testing" ) func TestGenerateBindConf(t *testing.T) { entries := []ZoneEntry{ {Zone: "bitcard.org.", ZoneFile: "data/misc/bitcard.org", DNSSEC: true, ZonesFile: "test", Line: 1}, {Zone: "askask.com.", ZoneFile: "data/ask/askask.com", ZonesFile: "test", Line: 2}, } got := generateBindConf(entries) // Header assertContains(t, got, "# THIS FILE IS GENERATED BY catalog-zone-gen") assertContains(t, got, "#=============================================") // Zones should be sorted alphabetically (askask.com before bitcard.org) askIdx := strings.Index(got, "askask.com") bitIdx := strings.Index(got, "bitcard.org") if askIdx == -1 || bitIdx == -1 { t.Fatal("expected both zones in output") } if askIdx >= bitIdx { t.Error("expected askask.com before bitcard.org (alphabetical sort)") } // Non-DNSSEC zone assertContains(t, got, `zone "askask.com" {`) assertContains(t, got, ` type master;`) assertContains(t, got, ` file "data/ask/askask.com";`) // DNSSEC zone has directives on file line assertContains(t, got, ` file "data/misc/bitcard.org"; dnssec-policy standard; inline-signing yes;`) // No trailing dot in zone name if strings.Contains(got, `zone "askask.com."`) { t.Error("zone name should not have trailing dot in BIND config") } } func TestGenerateBindConfEmpty(t *testing.T) { got := generateBindConf(nil) // Should just have the header lines := splitLines(got) if len(lines) != 3 { t.Errorf("expected 3 header lines for empty input, got %d", len(lines)) } } func TestGenerateBindConfNoDNSSEC(t *testing.T) { entries := []ZoneEntry{ {Zone: "example.com.", ZoneFile: "data/example.com", ZonesFile: "test", Line: 1}, } got := generateBindConf(entries) if strings.Contains(got, "dnssec-policy") { t.Error("non-DNSSEC zone should not have dnssec-policy") } if strings.Contains(got, "inline-signing") { t.Error("non-DNSSEC zone should not have inline-signing") } } func TestValidateBindConf(t *testing.T) { t.Run("all zones have file", func(t *testing.T) { entries := []ZoneEntry{ {Zone: "a.example.com.", ZoneFile: "data/a", ZonesFile: "zones.txt", Line: 1}, {Zone: "b.example.com.", ZoneFile: "data/b", ZonesFile: "zones.txt", Line: 2}, } if err := writeBindConf(filepath.Join(t.TempDir(), "domains.conf"), entries); err != nil { t.Fatalf("unexpected error: %v", err) } }) t.Run("zones without file are skipped", func(t *testing.T) { entries := []ZoneEntry{ {Zone: "a.example.com.", ZoneFile: "data/a", ZonesFile: "zones.txt", Line: 1}, {Zone: "dyn.example.com.", ZoneFile: "", ZonesFile: "zones.txt", Line: 3}, } dir := t.TempDir() path := filepath.Join(dir, "domains.conf") if err := writeBindConf(path, entries); err != nil { t.Fatalf("unexpected error: %v", err) } data, err := os.ReadFile(path) if err != nil { t.Fatal(err) } got := string(data) assertContains(t, got, `zone "a.example.com"`) if strings.Contains(got, "dyn.example.com") { t.Error("catalog-only zone without file= should not appear in BIND config") } }) } func TestWriteBindConf(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "domains.conf") entries := []ZoneEntry{ {Zone: "example.com.", ZoneFile: "data/example.com", ZonesFile: "test", Line: 1}, {Zone: "example.org.", ZoneFile: "data/example.org", DNSSEC: true, ZonesFile: "test", Line: 2}, } if err := writeBindConf(path, entries); err != nil { t.Fatalf("unexpected error: %v", err) } data, err := os.ReadFile(path) if err != nil { t.Fatal(err) } got := string(data) assertContains(t, got, `zone "example.com"`) assertContains(t, got, `zone "example.org"`) assertContains(t, got, "dnssec-policy standard") } func TestWriteBindConfSkipsCatalogOnlyZones(t *testing.T) { dir := t.TempDir() path := filepath.Join(dir, "domains.conf") entries := []ZoneEntry{ {Zone: "example.com.", ZoneFile: "", ZonesFile: "zones.txt", Line: 5}, } if err := writeBindConf(path, entries); err != nil { t.Fatalf("unexpected error: %v", err) } data, err := os.ReadFile(path) if err != nil { t.Fatal(err) } got := string(data) // Should have header but no zone blocks assertContains(t, got, "# THIS FILE IS GENERATED BY catalog-zone-gen") if strings.Contains(got, "example.com") { t.Error("zone without file= should not appear in BIND config") } }