mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-24 14:47:23 +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>
131 lines
3.3 KiB
Go
131 lines
3.3 KiB
Go
package handlers
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/gesellix/bose-soundtouch/pkg/models"
|
|
"github.com/gesellix/bose-soundtouch/pkg/service/datastore"
|
|
)
|
|
|
|
func TestMergeOverlappingDevices(t *testing.T) {
|
|
tempDir, err := os.MkdirTemp("", "merge-test-*")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
ds := datastore.NewDataStore(tempDir)
|
|
s := NewServer(ds, nil, "http://localhost", false, false, false)
|
|
|
|
// Case 1: IP-only entry and Serial-based entry for the same IP
|
|
ip := "192.0.2.100"
|
|
serial := "SERIAL123"
|
|
|
|
// 1. Save IP-based entry
|
|
infoIP := &models.ServiceDeviceInfo{
|
|
DeviceID: ip,
|
|
Name: "Speaker IP",
|
|
IPAddress: ip,
|
|
AccountID: "default",
|
|
ProductCode: "ST10",
|
|
}
|
|
err = ds.SaveDeviceInfo("default", ip, infoIP)
|
|
if err != nil {
|
|
t.Fatalf("Failed to save IP info: %v", err)
|
|
}
|
|
|
|
// 2. Save Serial-based entry
|
|
infoSerial := &models.ServiceDeviceInfo{
|
|
DeviceID: serial,
|
|
DeviceSerialNumber: serial,
|
|
Name: "Speaker Serial",
|
|
IPAddress: ip,
|
|
AccountID: "default",
|
|
ProductCode: "ST10",
|
|
}
|
|
err = ds.SaveDeviceInfo("default", serial, infoSerial)
|
|
if err != nil {
|
|
t.Fatalf("Failed to save Serial info: %v", err)
|
|
}
|
|
|
|
// Verify both exist
|
|
devices, _ := ds.ListAllDevices()
|
|
if len(devices) != 2 {
|
|
t.Fatalf("Expected 2 devices before merge, got %d", len(devices))
|
|
}
|
|
|
|
// Run merge
|
|
s.mergeOverlappingDevices()
|
|
|
|
// Verify merge
|
|
devices, _ = ds.ListAllDevices()
|
|
if len(devices) != 1 {
|
|
t.Fatalf("Expected 1 device after merge, got %d", len(devices))
|
|
}
|
|
|
|
if devices[0].DeviceID != serial {
|
|
t.Errorf("Expected remaining device to be Serial-based (%s), got %s", serial, devices[0].DeviceID)
|
|
}
|
|
}
|
|
|
|
func TestFindExistingDeviceID(t *testing.T) {
|
|
tempDir, _ := os.MkdirTemp("", "find-test-*")
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
ds := datastore.NewDataStore(tempDir)
|
|
s := NewServer(ds, nil, "http://localhost", false, false, false)
|
|
|
|
ip := "192.0.2.101"
|
|
serial := "SERIAL456"
|
|
|
|
// Save IP-based
|
|
ds.SaveDeviceInfo("default", ip, &models.ServiceDeviceInfo{
|
|
DeviceID: ip,
|
|
IPAddress: ip,
|
|
Name: "IP Speaker",
|
|
AccountID: "default",
|
|
ProductCode: "ST10",
|
|
})
|
|
|
|
// Test finding by IP
|
|
foundID := s.findExistingDeviceID(models.DiscoveredDevice{
|
|
Host: ip,
|
|
})
|
|
if foundID != ip {
|
|
t.Errorf("Expected to find by IP, got %s", foundID)
|
|
}
|
|
|
|
// Save Serial-based for SAME IP
|
|
ds.SaveDeviceInfo("default", serial, &models.ServiceDeviceInfo{
|
|
DeviceID: serial,
|
|
DeviceSerialNumber: serial,
|
|
IPAddress: ip,
|
|
Name: "Serial Speaker",
|
|
AccountID: "default",
|
|
ProductCode: "ST10",
|
|
})
|
|
|
|
// Test finding by IP should now return Serial (if Serial is known)
|
|
// Actually findExistingDeviceID returns the first match it finds in allDevices.
|
|
// Since we haven't merged yet, it could be either.
|
|
|
|
// Test finding by Serial
|
|
foundID = s.findExistingDeviceID(models.DiscoveredDevice{
|
|
Host: ip,
|
|
SerialNo: serial,
|
|
})
|
|
if foundID != serial && foundID != ip {
|
|
t.Errorf("Expected to find by Serial or IP, got %s", foundID)
|
|
}
|
|
|
|
// Merge and check again
|
|
s.mergeOverlappingDevices()
|
|
foundID = s.findExistingDeviceID(models.DiscoveredDevice{
|
|
Host: ip,
|
|
})
|
|
if foundID != serial {
|
|
t.Errorf("After merge, expected to find Serial ID for IP, got %s", foundID)
|
|
}
|
|
}
|