internal/app/physical_bluez_test.go
raw ยท 2099 bytes
package app
import (
"context"
"errors"
"testing"
"time"
"homekey.local/provisioner/drivers/sesame"
"homekey.local/provisioner/internal/physical"
)
// A failed preparation owns no Link. Retiring it must not short-circuit the
// actual BlueZ disconnect, which was the reason repeated clicks were needed.
func TestDisconnectFailedPreparationReleasesBlueZLink(t *testing.T) {
m, err := physical.Open(context.Background(), t.TempDir(), func(context.Context, sesame.Target) (sesame.Link, sesame.Target, error) {
return nil, sesame.Target{}, errors.New("Sesame is already connected through this adapter")
})
if err != nil {
t.Fatal(err)
}
defer m.Close()
target := sesame.Target{UUID: "00112233-4455-6677-8899-aabbccddeeff", Model: "sesame_6_pro", Adapter: "hci0", Address: "AA:BB:CC:DD:EE:FF"}
m.Prepare([]sesame.Target{target})
deadline := time.Now().Add(time.Second)
for time.Now().Before(deadline) {
states := m.RegistrationConnections()
if len(states) == 1 && states[0].Phase == "failed" {
break
}
time.Sleep(time.Millisecond)
}
if states := m.RegistrationConnections(); len(states) != 1 || states[0].Phase != "failed" {
t.Fatal("preparation did not fail", states)
}
connected := true
calls := 0
release := func(ctx context.Context, adapter, address string) error {
if adapter != target.Adapter || address != target.Address {
t.Fatal("released wrong lock", adapter, address)
}
if len(m.RegistrationConnections()) != 0 {
t.Fatal("released before retiring preparation")
}
calls++
connected = false
return nil
}
if err = disconnectSesame(context.Background(), m, target.Adapter, target.Address, release); err != nil {
t.Fatal(err)
}
if connected || calls != 1 {
t.Fatal("failed preparation hid the live BlueZ link", connected, calls)
}
transportError := errors.New("disconnect failed")
if err = disconnectSesame(context.Background(), m, target.Adapter, target.Address, func(context.Context, string, string) error { return transportError }); !errors.Is(err, transportError) {
t.Fatal("hid transport disconnect failure", err)
}
}