mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-19 00:56:16 +00:00
Mirrors the .md/.txt sweep across all tracked _test.go, testdata XML,
and .http integration files. Test files are self-contained (producer
+ assertion in the same file), so the matched-pair swap stays green
under `go test ./...`.
Mapping applied:
192.168.178.[0-9]+ → 192.0.2.[same]
192.168.1.[0-9]+ → 192.0.2.[same]
Sound Machinechen → Living Room SoundTouch
A Sound Machine → Kitchen SoundTouch
A81B6A536A98 + case/separator variants → AABBCCDDEEFF (etc.)
A81B6A849D99 → AABBCCDDEE01
A81B6A849D88 → AABBCCDDEE03
A81B6A536A09 → AABBCCDDEE04
884AEAEEBD27 → AABBCCDDEE02
3230304 → 1000001
9569497 → 1000002
Two semantic fixes alongside the bulk swap:
- pkg/service/zeroconf/zeroconf_test.go: the "private 192" and
"strips query" cases pin acceptance of RFC-1918 192.168/16. They
must use a real 192.168 value; doc-range IPs would (correctly) be
rejected by validateZcBaseURL. Switched to 192.168.10.10 — generic
enough not to match any home LAN default, real enough for the
validator. Added a comment explaining why this single test still
carries a 192.168 literal.
- pkg/service/setup/setup_test.go: TestTestDNSRedirection mocks the
device's `od -An -tu1` byte output, which is space-separated
octets ("192 168 1 100"). My sed only matched the dot-separated
form, so the mock was returning the old IP while the test
assertions had moved to the doc range. Updated to " 192 0 2 100".
go build ./... clean. go test ./... clean (only TestDocsConsistency
remains failing, which is a pre-existing/untracked-file issue).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
163 lines
3.7 KiB
Go
163 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"net"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestResolveBindAddr_PassThrough(t *testing.T) {
|
|
// Inputs that don't match any local interface name must be returned
|
|
// unchanged: empty string, hostnames, IPv4/IPv6 literals, and bogus
|
|
// strings the user might have typed.
|
|
tests := []string{
|
|
"",
|
|
"localhost",
|
|
"127.0.0.1",
|
|
"192.0.2.5",
|
|
"::1",
|
|
"definitely-not-an-iface-xyz",
|
|
}
|
|
|
|
for _, input := range tests {
|
|
t.Run(quoted(input), func(t *testing.T) {
|
|
got, err := resolveBindAddr(input)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if got != input {
|
|
t.Errorf("got %q, want %q (input should pass through unchanged)", got, input)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestResolveBindAddr_LoopbackInterface(t *testing.T) {
|
|
loopback, expected, ok := findLoopbackWithSingleIPv4(t)
|
|
if !ok {
|
|
t.Skipf("no loopback interface with exactly one IPv4 address found")
|
|
}
|
|
|
|
got, err := resolveBindAddr(loopback)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error resolving %q: %v", loopback, err)
|
|
}
|
|
|
|
if got != expected {
|
|
t.Errorf("got %q, want %q for loopback interface %q", got, expected, loopback)
|
|
}
|
|
}
|
|
|
|
// findLoopbackWithSingleIPv4 returns the name of a loopback interface and the
|
|
// single IPv4 address attached to it. If the host has multiple loopback
|
|
// interfaces or the loopback has zero or several IPv4 addresses, it returns
|
|
// ok=false so the caller can skip the test rather than fail on an environment
|
|
// quirk.
|
|
func findLoopbackWithSingleIPv4(t *testing.T) (name, addr string, ok bool) {
|
|
t.Helper()
|
|
|
|
ifaces, err := net.Interfaces()
|
|
if err != nil {
|
|
t.Fatalf("net.Interfaces: %v", err)
|
|
}
|
|
|
|
for _, iface := range ifaces {
|
|
if iface.Flags&net.FlagLoopback == 0 {
|
|
continue
|
|
}
|
|
|
|
addrs, addrErr := iface.Addrs()
|
|
if addrErr != nil {
|
|
continue
|
|
}
|
|
|
|
var ipv4s []string
|
|
|
|
for _, a := range addrs {
|
|
if ipnet, isIPNet := a.(*net.IPNet); isIPNet {
|
|
if v4 := ipnet.IP.To4(); v4 != nil {
|
|
ipv4s = append(ipv4s, v4.String())
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(ipv4s) == 1 {
|
|
return iface.Name, ipv4s[0], true
|
|
}
|
|
}
|
|
|
|
return "", "", false
|
|
}
|
|
|
|
func TestDefaultDiscoveryInterface(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
rawInterface string
|
|
rawBind string
|
|
resolvedBind string
|
|
want string
|
|
}{
|
|
{
|
|
name: "explicit interface wins over bind-derived default",
|
|
rawInterface: "eth1",
|
|
rawBind: "eth0",
|
|
resolvedBind: "192.0.2.5",
|
|
want: "eth1",
|
|
},
|
|
{
|
|
name: "derive from --bind when --bind was an interface name",
|
|
rawInterface: "",
|
|
rawBind: "eth0",
|
|
resolvedBind: "192.0.2.5",
|
|
want: "eth0",
|
|
},
|
|
{
|
|
name: "no derivation when --bind was an IP literal",
|
|
rawInterface: "",
|
|
rawBind: "192.0.2.5",
|
|
resolvedBind: "192.0.2.5",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "no derivation when --bind was a hostname (pass-through)",
|
|
rawInterface: "",
|
|
rawBind: "localhost",
|
|
resolvedBind: "localhost",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "both empty stays empty (auto-pick)",
|
|
rawInterface: "",
|
|
rawBind: "",
|
|
resolvedBind: "",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "explicit interface alone, --bind empty",
|
|
rawInterface: "eth1",
|
|
rawBind: "",
|
|
resolvedBind: "",
|
|
want: "eth1",
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := defaultDiscoveryInterface(tc.rawInterface, tc.rawBind, tc.resolvedBind)
|
|
if got != tc.want {
|
|
t.Errorf("got %q, want %q (rawInterface=%q rawBind=%q resolvedBind=%q)",
|
|
got, tc.want, tc.rawInterface, tc.rawBind, tc.resolvedBind)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func quoted(s string) string {
|
|
if s == "" {
|
|
return "(empty)"
|
|
}
|
|
|
|
return strings.ReplaceAll(s, "/", "_")
|
|
}
|