Cthulhu is no longer a fork. Now it is a screen reader written in Golang.
This commit is contained in:
1 parent
a998fe67de
commit
069fc674dc
708 files changed
+112482
-532
No files matched your search
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// Authors: Storm Dragon, Angus Kola
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package speech
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestContinuousSpeechWaitsForEndAndSurvivesCancellation(t *testing.T) {
|
||||
for _, interrupted := range []bool{false, true} {
|
||||
t.Run(fmt.Sprint(interrupted), func(t *testing.T) {
|
||||
conn, server := net.Pipe()
|
||||
control, controlServer := net.Pipe()
|
||||
client := connectedClient(conn)
|
||||
client.cancelConn, client.cancelReader, client.clientID = control, bufio.NewReader(control), 42
|
||||
t.Cleanup(func() { server.Close(); controlServer.Close(); client.Close(context.Background()) })
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
began := make(chan struct{}, 1)
|
||||
finished := make(chan error, 1)
|
||||
go func() { finished <- client.SpeakAndWait(ctx, "First line", func() { began <- struct{}{} }) }()
|
||||
server.SetDeadline(time.Now().Add(2 * time.Second))
|
||||
reader := bufio.NewReader(server)
|
||||
if err := exchangeSSIP(reader, server, "SET SELF NOTIFICATION ALL on\r\n", "200 OK\r\n"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, want := range []string{"SPEAK\r\n", "First line\r\n", ".\r\n"} {
|
||||
got, err := reader.ReadString('\n')
|
||||
if err != nil || got != want {
|
||||
t.Fatalf("speech block %q, %v; want %q", got, err, want)
|
||||
}
|
||||
}
|
||||
fmt.Fprint(server, "230 OK\r\n225-1\r\n225 QUEUED\r\n")
|
||||
select {
|
||||
case <-began:
|
||||
t.Fatal("queue acknowledgement advanced reading position")
|
||||
case <-finished:
|
||||
t.Fatal("queue acknowledgement completed speech")
|
||||
default:
|
||||
}
|
||||
fmt.Fprint(server, "701-1\r\n701-42\r\n701 BEGIN\r\n")
|
||||
select {
|
||||
case <-began:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("BEGIN did not update reading position")
|
||||
}
|
||||
if interrupted {
|
||||
cancel()
|
||||
controlServer.SetDeadline(time.Now().Add(time.Second))
|
||||
if err := exchangeSSIP(bufio.NewReader(controlServer), controlServer, "CANCEL 42\r\n", "200 OK\r\n"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fmt.Fprint(server, "703-1\r\n703-42\r\n703 CANCELED\r\n")
|
||||
} else {
|
||||
fmt.Fprint(server, "702-1\r\n702-42\r\n702 END\r\n")
|
||||
}
|
||||
if err := exchangeSSIP(reader, server, "SET SELF NOTIFICATION ALL off\r\n", "200 OK\r\n"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := <-finished; interrupted && !errors.Is(err, context.Canceled) || !interrupted && err != nil {
|
||||
t.Fatalf("completion = %v", err)
|
||||
}
|
||||
// The cancellation notification must not become the next SPEAK reply.
|
||||
go func() { finished <- client.Speak(context.Background(), "After") }()
|
||||
for range 3 {
|
||||
if _, err := reader.ReadString('\n'); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
fmt.Fprint(server, "230 OK\r\n225-2\r\n225 QUEUED\r\n")
|
||||
if err := <-finished; err != nil {
|
||||
t.Fatalf("speech after read all: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user