mirror of
https://github.com/coredns/coredns.git
synced 2026-07-22 07:30:13 -04:00
ci: run plugin tests on Windows (#8314)
Plugin package tests previously ran only on Linux, so Windows- specific failures were never caught. Run them in CI and make the affected tests portable across platforms. Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
This commit is contained in:
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# DNSSEC key material must keep LF; CRLF breaks miekg/dns private-key parsing.
|
||||||
|
*.private text eol=lf
|
||||||
|
*.key text eol=lf
|
||||||
6
.github/workflows/go.test.yml
vendored
6
.github/workflows/go.test.yml
vendored
@@ -59,7 +59,10 @@ jobs:
|
|||||||
|
|
||||||
test-plugins:
|
test-plugins:
|
||||||
name: Test Plugins
|
name: Test Plugins
|
||||||
runs-on: ubuntu-latest
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
@@ -76,6 +79,7 @@ jobs:
|
|||||||
run: go build -v ./...
|
run: go build -v ./...
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
|
shell: bash
|
||||||
run: ( cd plugin; go test -race ./... )
|
run: ( cd plugin; go test -race ./... )
|
||||||
|
|
||||||
test-e2e:
|
test-e2e:
|
||||||
|
|||||||
@@ -151,6 +151,11 @@ func TestWalkWarnsForDuplicateOrigin(t *testing.T) {
|
|||||||
|
|
||||||
func TestWalkKeepsFirstMatchingFileForOrigin(t *testing.T) {
|
func TestWalkKeepsFirstMatchingFileForOrigin(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
|
// Match Walk: it stores paths after EvalSymlinks.
|
||||||
|
dir, err := filepath.EvalSymlinks(dir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
zone := filepath.Join(dir, "example.org.zone")
|
zone := filepath.Join(dir, "example.org.zone")
|
||||||
backup := filepath.Join(dir, "example.org.zone.bak-20260528")
|
backup := filepath.Join(dir, "example.org.zone.bak-20260528")
|
||||||
|
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ func TestSetupAutoPath(t *testing.T) {
|
|||||||
{`autopath example.org @kubernetes`, false, "example.org.", "kubernetes", nil, ""},
|
{`autopath example.org @kubernetes`, false, "example.org.", "kubernetes", nil, ""},
|
||||||
{`autopath 10.0.0.0/8 @kubernetes`, false, "10.in-addr.arpa.", "kubernetes", nil, ""},
|
{`autopath 10.0.0.0/8 @kubernetes`, false, "10.in-addr.arpa.", "kubernetes", nil, ""},
|
||||||
{`autopath ` + resolv, false, "", "", []string{"bar.com.", "baz.com.", ""}, ""},
|
{`autopath ` + resolv, false, "", "", []string{"bar.com.", "baz.com.", ""}, ""},
|
||||||
// negative
|
// negative (OS error text differs; match the portable prefix)
|
||||||
{`autopath kubernetes`, true, "", "", nil, "open kubernetes: no such file or directory"},
|
{`autopath kubernetes`, true, "", "", nil, "open kubernetes:"},
|
||||||
{`autopath`, true, "", "", nil, "no resolv-conf"},
|
{`autopath`, true, "", "", nil, "no resolv-conf"},
|
||||||
{`autopath ""`, true, "", "", nil, "no such file"},
|
{`autopath ""`, true, "", "", nil, "failed to parse"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
|||||||
@@ -83,26 +83,8 @@ func TestZoneReloadSOAChange(t *testing.T) {
|
|||||||
func TestZoneReloadByMtime(t *testing.T) {
|
func TestZoneReloadByMtime(t *testing.T) {
|
||||||
// Test 1: Basic mtime trigger - file modification should trigger reload
|
// Test 1: Basic mtime trigger - file modification should trigger reload
|
||||||
t.Run("BasicMtimeTrigger", func(t *testing.T) {
|
t.Run("BasicMtimeTrigger", func(t *testing.T) {
|
||||||
fileName, rm, err := test.TempFile(".", reloadZoneTest)
|
z, fileName, cleanup := prepareMtimeZone(t, reloadZoneTest)
|
||||||
if err != nil {
|
defer cleanup()
|
||||||
t.Fatalf("Failed to create zone: %s", err)
|
|
||||||
}
|
|
||||||
defer rm()
|
|
||||||
|
|
||||||
reader, err := os.Open(fileName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to open zone: %s", err)
|
|
||||||
}
|
|
||||||
z, err := Parse(reader, "miek.nl", fileName, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to parse zone: %s", err)
|
|
||||||
}
|
|
||||||
reader.Close()
|
|
||||||
|
|
||||||
// Enable mtime-based reload
|
|
||||||
z.ReloadInterval = 10 * time.Millisecond
|
|
||||||
z.ReloadByMtime = true
|
|
||||||
z.Reload(&transfer.Transfer{})
|
|
||||||
|
|
||||||
// Wait for initial load to complete
|
// Wait for initial load to complete
|
||||||
time.Sleep(20 * time.Millisecond)
|
time.Sleep(20 * time.Millisecond)
|
||||||
@@ -136,26 +118,8 @@ func TestZoneReloadByMtime(t *testing.T) {
|
|||||||
|
|
||||||
// Test 2: No reload when mtime unchanged
|
// Test 2: No reload when mtime unchanged
|
||||||
t.Run("NoReloadWhenMtimeUnchanged", func(t *testing.T) {
|
t.Run("NoReloadWhenMtimeUnchanged", func(t *testing.T) {
|
||||||
fileName, rm, err := test.TempFile(".", reloadZoneTest)
|
z, _, cleanup := prepareMtimeZone(t, reloadZoneTest)
|
||||||
if err != nil {
|
defer cleanup()
|
||||||
t.Fatalf("Failed to create zone: %s", err)
|
|
||||||
}
|
|
||||||
defer rm()
|
|
||||||
|
|
||||||
reader, err := os.Open(fileName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to open zone: %s", err)
|
|
||||||
}
|
|
||||||
z, err := Parse(reader, "miek.nl", fileName, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to parse zone: %s", err)
|
|
||||||
}
|
|
||||||
reader.Close()
|
|
||||||
|
|
||||||
// Enable mtime-based reload
|
|
||||||
z.ReloadInterval = 10 * time.Millisecond
|
|
||||||
z.ReloadByMtime = true
|
|
||||||
z.Reload(&transfer.Transfer{})
|
|
||||||
|
|
||||||
// Wait for initial load
|
// Wait for initial load
|
||||||
time.Sleep(20 * time.Millisecond)
|
time.Sleep(20 * time.Millisecond)
|
||||||
@@ -193,26 +157,8 @@ func TestZoneReloadByMtime(t *testing.T) {
|
|||||||
|
|
||||||
// Test 3: Content verification after reload
|
// Test 3: Content verification after reload
|
||||||
t.Run("ContentVerificationAfterReload", func(t *testing.T) {
|
t.Run("ContentVerificationAfterReload", func(t *testing.T) {
|
||||||
fileName, rm, err := test.TempFile(".", reloadZoneTest)
|
z, fileName, cleanup := prepareMtimeZone(t, reloadZoneTest)
|
||||||
if err != nil {
|
defer cleanup()
|
||||||
t.Fatalf("Failed to create zone: %s", err)
|
|
||||||
}
|
|
||||||
defer rm()
|
|
||||||
|
|
||||||
reader, err := os.Open(fileName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to open zone: %s", err)
|
|
||||||
}
|
|
||||||
z, err := Parse(reader, "miek.nl", fileName, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to parse zone: %s", err)
|
|
||||||
}
|
|
||||||
reader.Close()
|
|
||||||
|
|
||||||
// Enable mtime-based reload
|
|
||||||
z.ReloadInterval = 10 * time.Millisecond
|
|
||||||
z.ReloadByMtime = true
|
|
||||||
z.Reload(&transfer.Transfer{})
|
|
||||||
|
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
@@ -266,26 +212,8 @@ func TestZoneReloadByMtime(t *testing.T) {
|
|||||||
|
|
||||||
// Test 4: File deleted/missing during reload
|
// Test 4: File deleted/missing during reload
|
||||||
t.Run("FileMissingDuringReload", func(t *testing.T) {
|
t.Run("FileMissingDuringReload", func(t *testing.T) {
|
||||||
fileName, rm, err := test.TempFile(".", reloadZoneTest)
|
z, fileName, cleanup := prepareMtimeZone(t, reloadZoneTest)
|
||||||
if err != nil {
|
defer cleanup()
|
||||||
t.Fatalf("Failed to create zone: %s", err)
|
|
||||||
}
|
|
||||||
defer rm()
|
|
||||||
|
|
||||||
reader, err := os.Open(fileName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to open zone: %s", err)
|
|
||||||
}
|
|
||||||
z, err := Parse(reader, "miek.nl", fileName, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to parse zone: %s", err)
|
|
||||||
}
|
|
||||||
reader.Close()
|
|
||||||
|
|
||||||
// Enable mtime-based reload
|
|
||||||
z.ReloadInterval = 10 * time.Millisecond
|
|
||||||
z.ReloadByMtime = true
|
|
||||||
z.Reload(&transfer.Transfer{})
|
|
||||||
|
|
||||||
// Wait for initial load
|
// Wait for initial load
|
||||||
time.Sleep(20 * time.Millisecond)
|
time.Sleep(20 * time.Millisecond)
|
||||||
@@ -327,6 +255,45 @@ func TestZoneReloadByMtime(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepareMtimeZone creates a zone with mtime-based reload enabled.
|
||||||
|
func prepareMtimeZone(t *testing.T, content string) (*Zone, string, func()) {
|
||||||
|
t.Helper()
|
||||||
|
fileName, rm, err := test.TempFile(".", content)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create zone: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
reader, err := os.Open(fileName)
|
||||||
|
if err != nil {
|
||||||
|
rm()
|
||||||
|
t.Fatalf("Failed to open zone: %s", err)
|
||||||
|
}
|
||||||
|
z, err := Parse(reader, "miek.nl", fileName, 0)
|
||||||
|
reader.Close()
|
||||||
|
if err != nil {
|
||||||
|
rm()
|
||||||
|
t.Fatalf("Failed to parse zone: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fi, err := os.Stat(fileName)
|
||||||
|
if err != nil {
|
||||||
|
rm()
|
||||||
|
t.Fatalf("Failed to stat zone: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
z.ReloadInterval = 10 * time.Millisecond
|
||||||
|
z.ReloadByMtime = true
|
||||||
|
// Parse does not set file_mtime unless ReloadByMtime is already enabled.
|
||||||
|
// Seed it so the reload loop only opens the file when mtime changes.
|
||||||
|
z.file_mtime = fi.ModTime()
|
||||||
|
z.Reload(&transfer.Transfer{})
|
||||||
|
|
||||||
|
return z, fileName, func() {
|
||||||
|
z.OnShutdown()
|
||||||
|
rm()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const reloadZoneTest = `miek.nl. 1627 IN SOA linode.atoom.net. miek.miek.nl. 1460175181 14400 3600 604800 14400
|
const reloadZoneTest = `miek.nl. 1627 IN SOA linode.atoom.net. miek.miek.nl. 1460175181 14400 3600 604800 14400
|
||||||
miek.nl. 1627 IN NS ext.ns.whyscream.net.
|
miek.nl. 1627 IN NS ext.ns.whyscream.net.
|
||||||
miek.nl. 1627 IN NS omval.tednet.nl.
|
miek.nl. 1627 IN NS omval.tednet.nl.
|
||||||
|
|||||||
@@ -72,11 +72,16 @@ func TestPrint(t *testing.T) {
|
|||||||
|
|
||||||
f, err := os.CreateTemp(t.TempDir(), "print_test_tmp")
|
f, err := os.CreateTemp(t.TempDir(), "print_test_tmp")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer os.Remove(f.Name())
|
// Redirect Print output to a temp file, then restore stdout and close
|
||||||
//Redirect the printed results to a tmp file for later comparison
|
// the handle so TempDir cleanup can remove it on Windows.
|
||||||
|
stdout := os.Stdout
|
||||||
os.Stdout = f
|
os.Stdout = f
|
||||||
|
t.Cleanup(func() {
|
||||||
|
os.Stdout = stdout
|
||||||
|
f.Close()
|
||||||
|
})
|
||||||
|
|
||||||
tree.Print()
|
tree.Print()
|
||||||
/**
|
/**
|
||||||
@@ -85,12 +90,12 @@ func TestPrint(t *testing.T) {
|
|||||||
server3.example.com.
|
server3.example.com.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if _, err := f.Seek(0, 0); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
buf := make([]byte, 256)
|
buf := make([]byte, 256)
|
||||||
f.Seek(0, 0)
|
if _, err := f.Read(buf); err != nil {
|
||||||
_, err = f.Read(buf)
|
t.Fatal(err)
|
||||||
if err != nil {
|
|
||||||
f.Close()
|
|
||||||
t.Error(err)
|
|
||||||
}
|
}
|
||||||
height := strings.Count(string(buf), ". \n")
|
height := strings.Count(string(buf), ". \n")
|
||||||
//Compare the height of the print with the actual height of the tree
|
//Compare the height of the print with the actual height of the tree
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -290,6 +291,12 @@ nameserver 10.10.255.253`), 0666); err != nil {
|
|||||||
}
|
}
|
||||||
defer os.Remove(emptyResolv)
|
defer os.Remove(emptyResolv)
|
||||||
|
|
||||||
|
// Portable stand-in for /dev/null: a resolv.conf with no nameserver lines.
|
||||||
|
nullResolv := filepath.Join(t.TempDir(), "null.conf")
|
||||||
|
if err := os.WriteFile(nullResolv, nil, 0666); err != nil {
|
||||||
|
t.Fatalf("Failed to write null.conf file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
input string
|
input string
|
||||||
shouldErr bool
|
shouldErr bool
|
||||||
@@ -299,7 +306,7 @@ nameserver 10.10.255.253`), 0666); err != nil {
|
|||||||
// pass
|
// pass
|
||||||
{`forward . ` + resolv, false, "", []string{"10.10.255.252:53", "10.10.255.253:53"}},
|
{`forward . ` + resolv, false, "", []string{"10.10.255.252:53", "10.10.255.253:53"}},
|
||||||
// fail
|
// fail
|
||||||
{`forward . /dev/null`, true, "no valid upstream addresses found", nil},
|
{`forward . ` + nullResolv, true, "no valid upstream addresses found", nil},
|
||||||
// IPV6 with local zone
|
// IPV6 with local zone
|
||||||
{`forward . ` + resolvIPV6, false, "", []string{"[0388:d254:7aec:6892:9f7f:e93b:5806:1b0f]:53"}},
|
{`forward . ` + resolvIPV6, false, "", []string{"[0388:d254:7aec:6892:9f7f:e93b:5806:1b0f]:53"}},
|
||||||
// pass when empty forward file is found
|
// pass when empty forward file is found
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func TestGeoIPParse(t *testing.T) {
|
|||||||
{true, fmt.Sprintf("%s 1 2 3", pluginName), "Wrong argument count", 0},
|
{true, fmt.Sprintf("%s 1 2 3", pluginName), "Wrong argument count", 0},
|
||||||
{true, fmt.Sprintf("%s { }", pluginName), "Error during parsing", 0},
|
{true, fmt.Sprintf("%s { }", pluginName), "Error during parsing", 0},
|
||||||
{true, fmt.Sprintf("%s /dbpath { city }", pluginName), "unknown property \"city\"", 0},
|
{true, fmt.Sprintf("%s /dbpath { city }", pluginName), "unknown property \"city\"", 0},
|
||||||
{true, fmt.Sprintf("%s /invalidPath\n", pluginName), "failed to open database file: open /invalidPath: no such file or directory", 0},
|
{true, fmt.Sprintf("%s /invalidPath\n", pluginName), "failed to open database file: open /invalidPath:", 0},
|
||||||
{true, fmt.Sprintf("%s %s\n", pluginName, unknownDBPath), "reader does not support the \"UnknownDbType\" database type", 0},
|
{true, fmt.Sprintf("%s %s\n", pluginName, unknownDBPath), "reader does not support the \"UnknownDbType\" database type", 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"path"
|
"path"
|
||||||
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -99,6 +100,10 @@ func (m testServiceClient) Query(_ctx context.Context, _in *pb.DnsPacket, _opts
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestProxyUnix(t *testing.T) {
|
func TestProxyUnix(t *testing.T) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
t.Skip("unix domain sockets are not supported on windows")
|
||||||
|
}
|
||||||
|
|
||||||
tdir := t.TempDir()
|
tdir := t.TempDir()
|
||||||
|
|
||||||
fd := path.Join(tdir, "test.grpc")
|
fd := path.Join(tdir, "test.grpc")
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -221,6 +222,7 @@ func TestCoreDNSOverflow(t *testing.T) {
|
|||||||
response, _, _, err := p.Connect(context.Background(), request, options)
|
response, _, _, err := p.Connect(context.Background(), request, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to connect to testdnsserver: %s", err)
|
t.Errorf("Failed to connect to testdnsserver: %s", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if response.Truncated != expectTruncated {
|
if response.Truncated != expectTruncated {
|
||||||
@@ -228,15 +230,18 @@ func TestCoreDNSOverflow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test PreferUDP, expect truncated response
|
// Oversized UDP replies are truncated on Unix; Windows surfaces WSAEMSGSIZE instead.
|
||||||
testConnection("PreferUDP", Options{PreferUDP: true}, true)
|
if runtime.GOOS != "windows" {
|
||||||
|
// Test PreferUDP, expect truncated response
|
||||||
|
testConnection("PreferUDP", Options{PreferUDP: true}, true)
|
||||||
|
|
||||||
|
// Test No options specified, expect truncated response
|
||||||
|
testConnection("NoOptionsSpecified", Options{}, true)
|
||||||
|
}
|
||||||
|
|
||||||
// Test ForceTCP, expect no truncated response
|
// Test ForceTCP, expect no truncated response
|
||||||
testConnection("ForceTCP", Options{ForceTCP: true}, false)
|
testConnection("ForceTCP", Options{ForceTCP: true}, false)
|
||||||
|
|
||||||
// Test No options specified, expect truncated response
|
|
||||||
testConnection("NoOptionsSpecified", Options{}, true)
|
|
||||||
|
|
||||||
// Test both TCP and UDP provided, expect no truncated response
|
// Test both TCP and UDP provided, expect no truncated response
|
||||||
testConnection("BothTCPAndUDP", Options{PreferUDP: true, ForceTCP: true}, false)
|
testConnection("BothTCPAndUDP", Options{PreferUDP: true, ForceTCP: true}, false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package tls
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -52,6 +53,12 @@ func TestTLS(t *testing.T) {
|
|||||||
t.Errorf("Test %d: Expected error to contain: %v, found error: %v, input: %s", i, test.expectedErrContent, err, test.input)
|
t.Errorf("Test %d: Expected error to contain: %v, found error: %v, input: %s", i, test.expectedErrContent, err, test.input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup registers OnShutdown to close KeyLogWriter, but tests never shut down.
|
||||||
|
// Close explicitly so t.TempDir cleanup can remove the file on Windows.
|
||||||
|
if err == nil {
|
||||||
|
closeKeyLogWriter(t, dnsserver.GetConfig(c))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,5 +128,22 @@ func TestTLSKeyLog(t *testing.T) {
|
|||||||
if cfg.TLSConfig.KeyLogWriter == nil {
|
if cfg.TLSConfig.KeyLogWriter == nil {
|
||||||
t.Fatal("KeyLogWriter is not set")
|
t.Fatal("KeyLogWriter is not set")
|
||||||
}
|
}
|
||||||
|
// setup registers OnShutdown to close KeyLogWriter, but tests never shut down.
|
||||||
|
// Close explicitly so t.TempDir cleanup can remove the file on Windows.
|
||||||
|
closeKeyLogWriter(t, cfg)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func closeKeyLogWriter(t *testing.T, cfg *dnsserver.Config) {
|
||||||
|
t.Helper()
|
||||||
|
if cfg.TLSConfig == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
closer, ok := cfg.TLSConfig.KeyLogWriter.(io.Closer)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Cleanup(func() {
|
||||||
|
closer.Close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user