coredns/core/dnsserver/register_test.go
Ville Vesilehto a070d22bc3
test(dnsserver): improve core/dnsserver test coverage (#7317)
Add comprehensive tests for multiple components including server blocks
inspection, configuration handling, DoH/DoQ writers, and server startup
functions. Increases overall test coverage from 27% to 38.4% with
particular focus on register.go, https.go, quic.go, and config.go.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-05-22 06:40:13 -07:00

335 lines
11 KiB
Go

package dnsserver
import (
"testing"
"github.com/coredns/caddy/caddyfile"
)
func TestHandler(t *testing.T) {
tp := testPlugin{}
c := testConfig("dns", tp)
if _, err := NewServer("127.0.0.1:53", []*Config{c}); err != nil {
t.Errorf("Expected no error for NewServer, got %s", err)
}
if h := c.Handler("local"); h != tp {
t.Errorf("Expected testPlugin from Handler, got %T", h)
}
if h := c.Handler("nothing"); h != nil {
t.Errorf("Expected nil from Handler, got %T", h)
}
}
func TestHandlers(t *testing.T) {
tp := testPlugin{}
c := testConfig("dns", tp)
if _, err := NewServer("127.0.0.1:53", []*Config{c}); err != nil {
t.Errorf("Expected no error for NewServer, got %s", err)
}
hs := c.Handlers()
if len(hs) != 1 || hs[0] != tp {
t.Errorf("Expected [testPlugin] from Handlers, got %v", hs)
}
}
func TestGroupingServers(t *testing.T) {
for i, test := range []struct {
configs []*Config
expectedGroups []string
failing bool
}{
// single config -> one group
{configs: []*Config{
{Transport: "dns", Zone: ".", Port: "53", ListenHosts: []string{""}},
},
expectedGroups: []string{"dns://:53"},
failing: false},
// 2 configs on different port -> 2 groups
{configs: []*Config{
{Transport: "dns", Zone: ".", Port: "53", ListenHosts: []string{""}},
{Transport: "dns", Zone: ".", Port: "54", ListenHosts: []string{""}},
},
expectedGroups: []string{"dns://:53", "dns://:54"},
failing: false},
// 2 configs on same port, both not using bind, diff zones -> 1 group
{configs: []*Config{
{Transport: "dns", Zone: ".", Port: "53", ListenHosts: []string{""}},
{Transport: "dns", Zone: "com.", Port: "53", ListenHosts: []string{""}},
},
expectedGroups: []string{"dns://:53"},
failing: false},
// 2 configs on same port, one addressed - one not using bind, diff zones -> 1 group
{configs: []*Config{
{Transport: "dns", Zone: ".", Port: "53", ListenHosts: []string{"127.0.0.1"}},
{Transport: "dns", Zone: ".", Port: "54", ListenHosts: []string{""}},
},
expectedGroups: []string{"dns://127.0.0.1:53", "dns://:54"},
failing: false},
// 2 configs on diff ports, 3 different address, diff zones -> 3 group
{configs: []*Config{
{Transport: "dns", Zone: ".", Port: "53", ListenHosts: []string{"127.0.0.1", "::1"}},
{Transport: "dns", Zone: ".", Port: "54", ListenHosts: []string{""}}},
expectedGroups: []string{"dns://127.0.0.1:53", "dns://[::1]:53", "dns://:54"},
failing: false},
// 2 configs on same port, same address, diff zones -> 1 group
{configs: []*Config{
{Transport: "dns", Zone: ".", Port: "53", ListenHosts: []string{"127.0.0.1", "::1"}},
{Transport: "dns", Zone: "com.", Port: "53", ListenHosts: []string{"127.0.0.1", "::1"}},
},
expectedGroups: []string{"dns://127.0.0.1:53", "dns://[::1]:53"},
failing: false},
// 2 configs on same port, total 2 diff addresses, diff zones -> 2 groups
{configs: []*Config{
{Transport: "dns", Zone: ".", Port: "53", ListenHosts: []string{"127.0.0.1"}},
{Transport: "dns", Zone: "com.", Port: "53", ListenHosts: []string{"::1"}},
},
expectedGroups: []string{"dns://127.0.0.1:53", "dns://[::1]:53"},
failing: false},
// 2 configs on same port, total 3 diff addresses, diff zones -> 3 groups
{configs: []*Config{
{Transport: "dns", Zone: ".", Port: "53", ListenHosts: []string{"127.0.0.1", "::1"}},
{Transport: "dns", Zone: "com.", Port: "53", ListenHosts: []string{""}}},
expectedGroups: []string{"dns://127.0.0.1:53", "dns://[::1]:53", "dns://:53"},
failing: false},
} {
groups, err := groupConfigsByListenAddr(test.configs)
if err != nil {
if !test.failing {
t.Fatalf("Test %d, expected no errors, but got: %v", i, err)
}
continue
}
if test.failing {
t.Fatalf("Test %d, expected to failed but did not, returned values", i)
}
if len(groups) != len(test.expectedGroups) {
t.Errorf("Test %d : expected the group's size to be %d, was %d", i, len(test.expectedGroups), len(groups))
continue
}
for _, v := range test.expectedGroups {
if _, ok := groups[v]; !ok {
t.Errorf("Test %d : expected value %v to be in the group, was not", i, v)
}
}
}
}
func TestInspectServerBlocks(t *testing.T) {
tests := []struct {
name string
serverBlocks []caddyfile.ServerBlock
expectedServerBlocks []caddyfile.ServerBlock
expectedConfigsLen int
expectedZoneAddrs map[string]zoneAddr
wantErr bool
}{
{
name: "simple dns",
serverBlocks: []caddyfile.ServerBlock{
{Keys: []string{"example.org"}},
},
expectedServerBlocks: []caddyfile.ServerBlock{
{Keys: []string{"dns://example.org.:53"}},
},
expectedConfigsLen: 1,
expectedZoneAddrs: map[string]zoneAddr{
"dns://example.org.:53": {Zone: "example.org.", Port: "53", Transport: "dns"},
},
},
{
name: "dns with port",
serverBlocks: []caddyfile.ServerBlock{
{Keys: []string{"example.org:1053"}},
},
expectedServerBlocks: []caddyfile.ServerBlock{
{Keys: []string{"dns://example.org.:1053"}},
},
expectedConfigsLen: 1,
expectedZoneAddrs: map[string]zoneAddr{
"dns://example.org.:1053": {Zone: "example.org.", Port: "1053", Transport: "dns"},
},
},
{
name: "tls",
serverBlocks: []caddyfile.ServerBlock{
{Keys: []string{"tls://example.org"}},
},
expectedServerBlocks: []caddyfile.ServerBlock{
{Keys: []string{"tls://example.org.:853"}},
},
expectedConfigsLen: 1,
expectedZoneAddrs: map[string]zoneAddr{
"tls://example.org.:853": {Zone: "example.org.", Port: "853", Transport: "tls"},
},
},
{
name: "quic",
serverBlocks: []caddyfile.ServerBlock{
{Keys: []string{"quic://example.org"}},
},
expectedServerBlocks: []caddyfile.ServerBlock{
{Keys: []string{"quic://example.org.:853"}},
},
expectedConfigsLen: 1,
expectedZoneAddrs: map[string]zoneAddr{
"quic://example.org.:853": {Zone: "example.org.", Port: "853", Transport: "quic"},
},
},
{
name: "grpc",
serverBlocks: []caddyfile.ServerBlock{
{Keys: []string{"grpc://example.org"}},
},
expectedServerBlocks: []caddyfile.ServerBlock{
{Keys: []string{"grpc://example.org.:443"}},
},
expectedConfigsLen: 1,
expectedZoneAddrs: map[string]zoneAddr{
"grpc://example.org.:443": {Zone: "example.org.", Port: "443", Transport: "grpc"},
},
},
{
name: "https",
serverBlocks: []caddyfile.ServerBlock{
{Keys: []string{"https://example.org."}},
},
expectedServerBlocks: []caddyfile.ServerBlock{
{Keys: []string{"https://example.org.:443"}},
},
expectedConfigsLen: 1,
expectedZoneAddrs: map[string]zoneAddr{
"https://example.org.:443": {Zone: "example.org.", Port: "443", Transport: "https"},
},
},
{
name: "multiple hosts same key",
serverBlocks: []caddyfile.ServerBlock{
{Keys: []string{"example.org,example.com:1053"}},
},
expectedServerBlocks: []caddyfile.ServerBlock{
{Keys: []string{"dns://example.org,example.com.:1053"}},
},
expectedConfigsLen: 1,
expectedZoneAddrs: map[string]zoneAddr{
"dns://example.org,example.com.:1053": {Zone: "example.org,example.com.", Port: "1053", Transport: "dns"},
},
},
{
name: "multiple keys",
serverBlocks: []caddyfile.ServerBlock{
{Keys: []string{"example.org", "example.com:1053"}},
},
expectedServerBlocks: []caddyfile.ServerBlock{
{Keys: []string{"dns://example.org.:53", "dns://example.com.:1053"}},
},
expectedConfigsLen: 2,
expectedZoneAddrs: map[string]zoneAddr{
"dns://example.org.:53": {Zone: "example.org.", Port: "53", Transport: "dns"},
"dns://example.com.:1053": {Zone: "example.com.", Port: "1053", Transport: "dns"},
},
},
{
name: "fqdn input",
serverBlocks: []caddyfile.ServerBlock{
{Keys: []string{"example.org."}},
},
expectedServerBlocks: []caddyfile.ServerBlock{
{Keys: []string{"dns://example.org.:53"}},
},
expectedConfigsLen: 1,
expectedZoneAddrs: map[string]zoneAddr{
"dns://example.org.:53": {Zone: "example.org.", Port: "53", Transport: "dns"},
},
},
{
name: "multiple server blocks",
serverBlocks: []caddyfile.ServerBlock{
{Keys: []string{"example.org"}},
{Keys: []string{"sub.example.org:1054"}},
},
expectedServerBlocks: []caddyfile.ServerBlock{
{Keys: []string{"dns://example.org.:53"}},
{Keys: []string{"dns://sub.example.org.:1054"}},
},
expectedConfigsLen: 2,
expectedZoneAddrs: map[string]zoneAddr{
"dns://example.org.:53": {Zone: "example.org.", Port: "53", Transport: "dns"},
"dns://sub.example.org.:1054": {Zone: "sub.example.org.", Port: "1054", Transport: "dns"},
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
ctx := newContext(nil).(*dnsContext)
processedBlocks, err := ctx.InspectServerBlocks("TestInspectServerBlocks", tc.serverBlocks)
if (err != nil) != tc.wantErr {
t.Fatalf("InspectServerBlocks() error = %v, wantErr %v", err, tc.wantErr)
}
if tc.wantErr {
return
}
if len(processedBlocks) != len(tc.expectedServerBlocks) {
t.Fatalf("Expected %d processed blocks, got %d", len(tc.expectedServerBlocks), len(processedBlocks))
}
for i, block := range processedBlocks {
expectedBlock := tc.expectedServerBlocks[i]
if len(block.Keys) != len(expectedBlock.Keys) {
t.Errorf("Block %d: expected %d keys, got %d. Expected: %v, Got: %v", i, len(expectedBlock.Keys), len(block.Keys), expectedBlock.Keys, block.Keys)
continue
}
for j, key := range block.Keys {
if key != expectedBlock.Keys[j] {
t.Errorf("Block %d, Key %d: expected key '%s', got '%s'", i, j, expectedBlock.Keys[j], key)
}
}
}
if len(ctx.configs) != tc.expectedConfigsLen {
t.Errorf("Expected %d configs to be created, got %d", tc.expectedConfigsLen, len(ctx.configs))
}
if tc.expectedZoneAddrs != nil {
configIndex := 0
for ib := range processedBlocks {
for ik, key := range processedBlocks[ib].Keys {
if configIndex >= len(ctx.configs) {
t.Fatalf("Not enough configs stored, expected at least %d, processed block %d key %d", configIndex+1, ib, ik)
}
cfg := ctx.configs[configIndex]
expectedZa, ok := tc.expectedZoneAddrs[key]
if !ok {
t.Errorf("No expected zoneAddr for processed key '%s'", key)
continue
}
if cfg.Zone != expectedZa.Zone {
t.Errorf("Config for key '%s': expected Zone '%s', got '%s'", key, expectedZa.Zone, cfg.Zone)
}
if cfg.Port != expectedZa.Port {
t.Errorf("Config for key '%s': expected Port '%s', got '%s'", key, expectedZa.Port, cfg.Port)
}
if cfg.Transport != expectedZa.Transport {
t.Errorf("Config for key '%s': expected Transport '%s', got '%s'", key, expectedZa.Transport, cfg.Transport)
}
if len(cfg.ListenHosts) != 1 || cfg.ListenHosts[0] != "" {
t.Errorf("Config for key '%s': expected ListenHosts [''], got %v", key, cfg.ListenHosts)
}
configIndex++
}
}
}
})
}
}