test(drm): expect the owner to retry a protected modeset refused for master
The master-loss resume test sent a second seat activation after 20 ms, racing the owner's own retry at 20 ms and hanging on a duplicate render. The owner now retries without a seat event; the test checks the proof follows a successful retry commit.
- commit
- 72285c7b48fa22786601cf6adb284ffd6f07e077
- author
- brice · · 2026-10-10 15:11 UTC
- committer
- brice · · 2026-10-10 15:39 UTC
- parent
- 591baeb
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +11 -13
M internal/adapters/drm/security_resume_test.go +11 -13
| @@ -58,19 +58,9 @@ func TestSecurityUnlockedResumeUsesOwnerRetry(t *testing.T) { | |||
| 58 | 58 | waitFor(t, func() bool { mu.Lock(); defer mu.Unlock(); return len(*commits) == 1 }) | |
| 59 | 59 | state.Store(3) | |
| 60 | 60 | wake <- ports.SecurityState{} | |
| 61 | - | select { | |
| 62 | - | case ev := <-events: | |
| 63 | - | if _, ok := ev.(ports.SecurityOutputProof); ok { | |
| 64 | - | t.Fatal("master loss forged proof") | |
| 65 | - | } | |
| 66 | - | case <-time.After(20 * time.Millisecond): | |
| 67 | - | } | |
| 68 | - | select { | |
| 69 | - | case err := <-done: | |
| 70 | - | t.Fatalf("resume stopped owner: %v", err) | |
| 71 | - | default: | |
| 72 | - | } | |
| 73 | - | active <- true // only real seat reacquisition permits preparation | |
| 61 | + | // The seat reported active before master came back: the owner | |
| 62 | + | // retries the protected modeset itself, with no second seat | |
| 63 | + | // event. The proof below must follow that successful retry. | |
| 74 | 64 | } | |
| 75 | 65 | for { | |
| 76 | 66 | select { | |
| @@ -79,6 +69,14 @@ func TestSecurityUnlockedResumeUsesOwnerRetry(t *testing.T) { | |||
| 79 | 69 | if p.Proof.Generation != 1 || p.Proof.Instance != 77 { | |
| 80 | 70 | t.Fatalf("proof %+v", p) | |
| 81 | 71 | } | |
| 72 | + | if stage == "master-loss" { | |
| 73 | + | mu.Lock() | |
| 74 | + | n := len(*commits) | |
| 75 | + | mu.Unlock() | |
| 76 | + | if n < 2 { | |
| 77 | + | t.Fatal("master loss forged proof: no successful retry") | |
| 78 | + | } | |
| 79 | + | } | |
| 82 | 80 | cancel() | |
| 83 | 81 | if err := <-done; err != nil { | |
| 84 | 82 | t.Fatal(err) | |
| @@ -58,19 +58,9 @@ func TestSecurityUnlockedResumeUsesOwnerRetry(t *testing.T) { | |||||
| 58 | waitFor(t, func() bool { mu.Lock(); defer mu.Unlock(); return len(*commits) == 1 }) | 58 | waitFor(t, func() bool { mu.Lock(); defer mu.Unlock(); return len(*commits) == 1 }) | ||
| 59 | state.Store(3) | 59 | state.Store(3) | ||
| 60 | wake <- ports.SecurityState{} | 60 | wake <- ports.SecurityState{} | ||
| 61 | - | select { | 61 | + | // The seat reported active before master came back: the owner |
| 62 | - | case ev := <-events: | 62 | + | // retries the protected modeset itself, with no second seat |
| 63 | - | if _, ok := ev.(ports.SecurityOutputProof); ok { | 63 | + | // event. The proof below must follow that successful retry. |
| 64 | - | t.Fatal("master loss forged proof") | |||
| 65 | - | } | |||
| 66 | - | case <-time.After(20 * time.Millisecond): | |||
| 67 | - | } | |||
| 68 | - | select { | |||
| 69 | - | case err := <-done: | |||
| 70 | - | t.Fatalf("resume stopped owner: %v", err) | |||
| 71 | - | default: | |||
| 72 | - | } | |||
| 73 | - | active <- true // only real seat reacquisition permits preparation | |||
| 74 | } | 64 | } | ||
| 75 | for { | 65 | for { | ||
| 76 | select { | 66 | select { | ||
| @@ -79,6 +69,14 @@ func TestSecurityUnlockedResumeUsesOwnerRetry(t *testing.T) { | |||||
| 79 | if p.Proof.Generation != 1 || p.Proof.Instance != 77 { | 69 | if p.Proof.Generation != 1 || p.Proof.Instance != 77 { | ||
| 80 | t.Fatalf("proof %+v", p) | 70 | t.Fatalf("proof %+v", p) | ||
| 81 | } | 71 | } | ||
| 72 | + | if stage == "master-loss" { | |||
| 73 | + | mu.Lock() | |||
| 74 | + | n := len(*commits) | |||
| 75 | + | mu.Unlock() | |||
| 76 | + | if n < 2 { | |||
| 77 | + | t.Fatal("master loss forged proof: no successful retry") | |||
| 78 | + | } | |||
| 79 | + | } | |||
| 82 | cancel() | 80 | cancel() | ||
| 83 | if err := <-done; err != nil { | 81 | if err := <-done; err != nil { | ||
| 84 | t.Fatal(err) | 82 | t.Fatal(err) | ||