Reset master to testing content
This commit is contained in:
1 parent
0f2587b719
commit
42afa2a56c
1483 files changed
+145308
-938069
No files matched your search
@@ -0,0 +1,109 @@
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// Authors: Storm Dragon, Angus Kola
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.stormux.org/storm/cthulhu/internal/atspi"
|
||||
"git.stormux.org/storm/cthulhu/internal/config"
|
||||
"git.stormux.org/storm/cthulhu/internal/input"
|
||||
)
|
||||
|
||||
func TestRunPresentsLockStatesWithKeyEchoDisabled(t *testing.T) {
|
||||
settings := config.DefaultSettings()
|
||||
settings.EnableSound = false
|
||||
settings.EnableBraille = false
|
||||
settings.EnableKeyEcho = false
|
||||
speaker := &fakeSpeaker{spoken: make(chan string, 4)}
|
||||
commands := &fakeCommands{commands: make(chan input.CommandEvent), lockStates: make(chan input.LockState)}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
completed := make(chan error, 1)
|
||||
go func() {
|
||||
completed <- Run(ctx, Options{
|
||||
Logger: slog.New(slog.DiscardHandler), Settings: &settings,
|
||||
newCommands: func() commandListener { return commands },
|
||||
newSpeaker: func() Speaker { return speaker },
|
||||
newAdapter: func() Adapter { return &fakeAdapter{events: make(chan atspi.Event)} },
|
||||
newInput: func() InputListener { return &fakeInputListener{events: make(chan input.Event)} },
|
||||
})
|
||||
}()
|
||||
defer func() {
|
||||
cancel()
|
||||
select {
|
||||
case err := <-completed:
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Error("reader did not stop")
|
||||
}
|
||||
}()
|
||||
select {
|
||||
case <-speaker.spoken:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("missing startup speech")
|
||||
}
|
||||
for _, name := range []string{"Caps Lock", "Num Lock", "Scroll Lock"} {
|
||||
for _, locked := range []bool{true, false} {
|
||||
state := input.LockState{Name: name, Locked: locked, Timestamp: 100}
|
||||
select {
|
||||
case commands.lockStates <- state:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("lock event was not received")
|
||||
}
|
||||
select {
|
||||
case text := <-speaker.spoken:
|
||||
if text != state.Text() {
|
||||
t.Fatalf("speech = %q, want %q", text, state.Text())
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("lock state did not reach speech")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandSpeechSurvivesDelayedInitiatingInput(t *testing.T) {
|
||||
for _, cause := range []string{"current-time", "current-date", "version"} {
|
||||
t.Run(cause, func(t *testing.T) {
|
||||
worker := newSpeechWorker(slog.New(slog.DiscardHandler), nil)
|
||||
worker.running = true
|
||||
worker.ProtectCommand(100)
|
||||
worker.Enqueue(speechRequest{Text: "Command result", Role: "system", Cause: cause})
|
||||
for _, timestamp := range []uint32{80, 99, 100} {
|
||||
if worker.InterruptForInput(input.Event{Pressed: true, Timestamp: timestamp}) {
|
||||
t.Fatalf("command interrupted by initiating input at %d", timestamp)
|
||||
}
|
||||
}
|
||||
if len(worker.pending) != 1 || worker.generation != 1 {
|
||||
t.Fatal("command speech was discarded")
|
||||
}
|
||||
if !worker.InterruptForInput(input.Event{Pressed: true, Timestamp: 101}) || len(worker.pending) != 0 {
|
||||
t.Fatal("later input did not interrupt command speech")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandInputProtectionOrdersTimestampsAcrossWrap(t *testing.T) {
|
||||
worker := newSpeechWorker(slog.New(slog.DiscardHandler), nil)
|
||||
worker.ProtectCommand(^uint32(0) - 1)
|
||||
worker.ProtectCommand(3)
|
||||
worker.ProtectCommand(^uint32(0)) // An older queued notification cannot move the cutoff back.
|
||||
for _, timestamp := range []uint32{^uint32(0), 2, 3} {
|
||||
if worker.InterruptForInput(input.Event{Pressed: true, Timestamp: timestamp}) {
|
||||
t.Fatalf("old input at %d interrupted", timestamp)
|
||||
}
|
||||
}
|
||||
for _, timestamp := range []uint32{4, 0} {
|
||||
if !worker.InterruptForInput(input.Event{Pressed: true, Timestamp: timestamp}) {
|
||||
t.Fatalf("new or untimed input at %d ignored", timestamp)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user