diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2024-08-22 21:12:12 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2024-08-22 21:12:12 -0400 |
| commit | d8743bbc53c8db43151ef89d21264b531bea3d4c (patch) | |
| tree | ba941b7aa904bbde985d3a76ca90028f4bf8a475 /kill_test.go | |
| parent | 59cf78dbab8549761207b706f9856898cb5cd9c2 (diff) | |
| download | gui-d8743bbc53c8db43151ef89d21264b531bea3d4c.zip | |
test attachHandler
Diffstat (limited to 'kill_test.go')
| -rw-r--r-- | kill_test.go | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/kill_test.go b/kill_test.go new file mode 100644 index 0000000..d11e54c --- /dev/null +++ b/kill_test.go @@ -0,0 +1,112 @@ +package gui + +import ( + "fmt" + "testing" +) + +// Kill the attachHandler with no victim attached. +func TestAttachHandlerKill(t *testing.T) { + handler := newAttachHandler() + if !trySend(handler.kill, true, timeout) { + t.Errorf("kill attachHandler timed out after %v", timeout) + } + if _, ok := tryRecv(handler.dead, timeout); !ok { + t.Errorf("no dead signal from attachHandler after %v", timeout) + } +} + +// Kill the attachHandler with a victim attached. +func TestAttachHandlerAttachKill(t *testing.T) { + handler := newAttachHandler() + victim, err := newDummyAttachable(handler) + if err != nil { + t.Error(err) + } + + // Kill attachHandler. + if !trySend(handler.kill, true, timeout) { + t.Errorf("failed to kill attachHandler after %v", timeout) + } + if _, ok := tryRecv(handler.dead, timeout); !ok { + t.Errorf("attachHandler not dead after %v", timeout) + } + + // victim.Dead() should now be closed. + if _, notClosed := <-victim.Dead(); notClosed { + t.Errorf("victim not dead after killing attachHandler") + } +} + +// Detach the victim and attach another in its place. +func TestAttachHandlerReattach(t *testing.T) { + handler := newAttachHandler() + + // Attach first victim. + victim1, err := newDummyAttachable(handler) + if err != nil { + t.Error(err) + } + + // Try to attach second victim while first still attached—should fail. + if _, err := newDummyAttachable(handler); err == nil { + t.Errorf("attachHandler accepted another victim while the first was still attached.") + } + + // Detach first victim. + if !trySend(victim1.Kill(), true, timeout) { + t.Errorf("failed to kill first victim after %v", timeout) + } + if _, ok := tryRecv(victim1.Dead(), timeout); !ok { + t.Errorf("first victim failed to die after %v", timeout) + } + + // Attach second victim. + if _, err := newDummyAttachable(handler); err != nil { + t.Error(err) + } + + handler.kill <- true + <-handler.dead +} + +type dummyAttachable struct { + kill chan<- bool + dead <-chan bool + detachChan <-chan bool +} + +// newDummyAttachable returns a dummyAttachable that is attached to parent, +// or error if the parent does not accept the attach. +func newDummyAttachable(parent killer) (attachable, error) { + kill := make(chan bool) + dead := make(chan bool) + detachChan := make(chan bool) + + go func() { + <-kill + close(kill) + detachChan <- true + close(detachChan) + dead <- true + close(dead) + }() + + da := dummyAttachable{kill, dead, detachChan} + if !trySend(parent.attach(), attachable(da), timeout) { + return da, fmt.Errorf("failed to attach after %v", timeout) + } + return da, nil +} + +func (da dummyAttachable) Kill() chan<- bool { + return da.kill +} + +func (da dummyAttachable) Dead() <-chan bool { + return da.dead +} + +func (da dummyAttachable) detach() <-chan bool { + return da.detachChan +} |