During the 2026-10-09 outage the control node's resolver stayed active while it no longer listened on its private address, and nothing on the mesh could ask that address a question or show which sockets were bound. netcheck_dns takes server (and tcp) to ask one resolver alone and say its response code; netcheck_listening reads the kernel's socket tables, as ss -lunt does, with the owning program where the tool's account may see it and a sentence where it may not.
69 lines
2.1 KiB
Go
69 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestATCPPortThatListensIsReachableAndOneThatDoesNotIsNot(t *testing.T) {
|
|
l, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
port := l.Addr().(*net.TCPAddr).Port
|
|
got, err := CheckTCP("127.0.0.1", port, time.Second)
|
|
if err != nil || !got.Reachable || got.Error != "" {
|
|
t.Fatalf("a listening port: %+v, %v", got, err)
|
|
}
|
|
l.Close()
|
|
got, err = CheckTCP("127.0.0.1", port, time.Second)
|
|
if err != nil || got.Reachable || got.Error == "" {
|
|
t.Fatalf("a closed port is reported as a result with its error, not a failure: %+v, %v", got, err)
|
|
}
|
|
}
|
|
|
|
func TestAPortOutsideTheRangeIsRefused(t *testing.T) {
|
|
for _, p := range []int{0, -1, 65536} {
|
|
if _, err := CheckTCP("127.0.0.1", p, time.Second); err == nil {
|
|
t.Errorf("port %d was accepted", p)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDNSAnswersFromTheMachinesResolverAndRefusesAnUnknownType(t *testing.T) {
|
|
got, err := CheckDNS("localhost", "a", time.Second)
|
|
if err != nil || got.Type != "A" || len(got.Answers) == 0 {
|
|
t.Fatalf("localhost A: %+v, %v", got, err)
|
|
}
|
|
if _, err := CheckDNS("localhost", "SRV", time.Second); err == nil {
|
|
t.Fatal("an unknown record type was accepted")
|
|
}
|
|
got, err = CheckDNS("no-such-name.invalid", "A", time.Second)
|
|
if err != nil || got.Error == "" || len(got.Answers) != 0 {
|
|
t.Fatalf("a name that does not resolve is a result with its error: %+v, %v", got, err)
|
|
}
|
|
}
|
|
|
|
func TestTimeoutIsDefaultedAndBounded(t *testing.T) {
|
|
if d, _ := timeoutOf(map[string]any{}); d != DefaultTimeout {
|
|
t.Errorf("default: %v", d)
|
|
}
|
|
if d, _ := timeoutOf(map[string]any{"timeout_ms": float64(10 * 60 * 1000)}); d != MostTimeout {
|
|
t.Errorf("bounded: %v", d)
|
|
}
|
|
if _, err := timeoutOf(map[string]any{"timeout_ms": float64(0)}); err == nil {
|
|
t.Error("a zero timeout was accepted")
|
|
}
|
|
}
|
|
|
|
func TestTheToolsAreListedUnprefixed(t *testing.T) {
|
|
names := map[string]bool{}
|
|
for _, tool := range tools() {
|
|
names[tool.Name] = true
|
|
}
|
|
if !names["netcheck_tcp"] || !names["netcheck_dns"] || !names["netcheck_listening"] || len(names) != 3 {
|
|
t.Fatalf("tools: %v", names)
|
|
}
|
|
}
|