After commit c018f5fd29 Fenrir is being switched over to go. If you do not want to be part of the testing process, please switch to master.

This commit is contained in:
Storm Dragon committed 2026-10-27 20:30:55 -04:00
1 parent c018f5fd29
commit 0e50de4c76
1047 files changed
+58364 -63747

No files matched your search

+176
View File
@@ -0,0 +1,176 @@
// Copyright (c) 2026 Storm Dragon
// SPDX-License-Identifier: GPL-3.0-or-later
package app
import (
"os"
"reflect"
"slices"
"testing"
"git.stormux.org/storm/fenrir/internal/config"
"git.stormux.org/storm/fenrir/internal/control"
"git.stormux.org/storm/fenrir/internal/presentation"
)
func runtime_request(a *application, text string) string {
reply := make(chan string, 1)
a.remote_request(control.Request{UID: os.Geteuid(), Text: text, Reply: reply})
return <-reply
}
func TestRemoteTrackingSelectionAndAtomicFlags(t *testing.T) {
for _, baseMode := range []string{"cursor", "table", "highlight"} {
base := config.Defaults()
base.Reading.Mode = baseMode
for _, trial := range []struct{ text, mode string }{
{"reading#mode=cursor", "cursor"},
{"reading#mode=table", "table"},
{"reading#mode=highlight", "highlight"},
{"focus#cursor=False;focus#highlight=True", "highlight"},
{"focus#highlight=True;focus#cursor=False", "highlight"},
{"focus#highlight=False,focus#cursor=True", "cursor"},
{"focus#cursor=False;focus#highlight=False", "table"},
} {
updated, err := remote_settings(base, "SET "+trial.text)
if err != nil || updated.Reading.Mode != trial.mode {
t.Fatal(baseMode, trial, updated.Reading.Mode, err)
}
}
for _, invalid := range []string{
"reading#mode=", "reading#mode=invalid", "reading#mode=CURSOR",
"focus#cursor=invalid", "focus#cursor=True;focus#highlight=True",
"reading#mode=cursor;focus#highlight=False",
} {
updated, err := remote_settings(base, "SET speech#enabled=False;"+invalid)
if err == nil || !reflect.DeepEqual(updated, base) {
t.Fatal("invalid selection partially applied", baseMode, invalid, updated, err)
}
}
}
}
func TestRemoteTrackingLiveSaveResetAndGates(t *testing.T) {
for _, terminalMode := range []bool{false, true} {
a, _ := persistence_application(t, terminalMode)
// A Python flag update must use the current mode for both live and
// saved state, even when a menu draft chose a different startup mode.
a.settings.saveDraft.Reading.Mode = "highlight"
for _, text := range []string{"SETTING SET focus#cursor=False;focus#highlight=True", "SETTING SET reading#mode=highlight"} {
a.settings.live.Remote.EnableSettingsRemote = false
if runtime_request(a, text) == "" || a.engine.Tracking_mode() != "cursor" {
t.Fatal("disabled remote changed mode")
}
a.settings.live.Remote.EnableSettingsRemote = true
reply := make(chan string, 1)
a.remote_request(control.Request{UID: os.Geteuid() + 1, Text: text, Reply: reply})
if <-reply == "" || a.engine.Tracking_mode() != "cursor" {
t.Fatal("unauthorized caller changed mode")
}
if response := runtime_request(a, text); response != "" || a.engine.Tracking_mode() != "highlight" || a.settings.saveDraft.Reading.Mode != "highlight" {
t.Fatal("tracking not applied to live/draft", response)
}
if response := runtime_request(a, "SETTING RESET"); response != "" || a.engine.Tracking_mode() != "cursor" || a.settings.saveDraft.Reading.Mode != "cursor" {
t.Fatal("reset did not restore tracking", response)
}
}
a.settings.saveDraft.Reading.Mode = "highlight"
if response := runtime_request(a, "SETTING SET focus#cursor=False"); response != "" || a.engine.Tracking_mode() != "table" || a.settings.saveDraft.Reading.Mode != "table" {
t.Fatal("partial flag update used a stale saved mode", response)
}
reply := persistence_request(a, "SAVE")
finish_persistence(t, a, false)
persistence_reply(t, reply, false)
saved, _, err := config.Load(a.options.ConfigPath, nil)
if err != nil || saved.Reading.Mode != "table" {
t.Fatal("remote tracking not saved", saved.Reading.Mode, err)
}
if response := runtime_request(a, "SETTING SET reading#mode=highlight"); response != "" {
t.Fatal(response)
}
if response := runtime_request(a, "SETTING RESET"); response != "" || a.engine.Tracking_mode() != "table" {
t.Fatal("reset lost saved tracking baseline", response)
}
}
}
func TestRemoteSpeechRestorationFeedbackAndAdmission(t *testing.T) {
for _, terminalMode := range []bool{false, true} {
for _, soundMode := range []string{"enabled", "disabled", "missing", "unavailable"} {
a, voice := persistence_application(t, terminalMode)
sounds := a.cues.(*fakeSounds)
a.settings.live.Presentation.Sound.Enabled = soundMode != "disabled"
if soundMode == "missing" {
sounds.missing = map[presentation.Cue]bool{presentation.SpeechOn: true, presentation.SpeechOff: true}
} else if soundMode == "unavailable" {
a.cues = nil
}
voice.messages, sounds.cues = nil, nil
for _, text := range []string{"SETTING SET speech#enabled=False", "COMMAND SAY discarded", "SETTING SET speech#enabled=True"} {
if response := runtime_request(a, text); response != "" {
t.Fatal(response)
}
}
if a.muted || voice.muted || slices.Contains(voice.messages, "discarded") {
t.Fatal("remote mute/restoration or discard failed", voice.messages)
}
if soundMode == "enabled" {
if !reflect.DeepEqual(sounds.cues, []presentation.Cue{presentation.SpeechOff, presentation.SpeechOn}) || len(voice.messages) != 0 {
t.Fatal("missing or duplicated mute feedback", sounds.cues, voice.messages)
}
} else if !reflect.DeepEqual(voice.messages, []string{"speech enabled"}) {
t.Fatal("missing restoration speech fallback", soundMode, voice.messages)
}
voice.messages, sounds.cues = nil, nil
if response := runtime_request(a, "SETTING SET speech#enabled=True"); response != "" || len(voice.messages)+len(sounds.cues) != 0 {
t.Fatal("identical enable repeated feedback", response)
}
if response := runtime_request(a, "COMMAND TEMPDISABLESPEECH"); response != "" || !a.temporarySilence {
t.Fatal("remote keypad action did not silence", response)
}
voice.messages, sounds.cues = nil, nil
before := a.settings.saveDraft
reply := make(chan string, 1)
a.remote_request(control.Request{UID: os.Geteuid() + 1, Text: "SETTING SET speech#enabled=True", Reply: reply})
if <-reply == "" || !a.temporarySilence {
t.Fatal("unauthorized enable restored temporary silence")
}
a.settings.live.Remote.EnableSettingsRemote = false
if response := runtime_request(a, "SETTING SET speech#enabled=True"); response == "" || !a.temporarySilence {
t.Fatal("disabled remote enable restored temporary silence", response)
}
a.settings.live.Remote.EnableSettingsRemote = true
for _, text := range []string{"SETTING SET speech#enabled=True;reading#mode=bad", "COMMAND TEMPDISABLESPEECH extra"} {
if response := runtime_request(a, text); response == "" || !a.temporarySilence || !reflect.DeepEqual(a.settings.saveDraft, before) || len(voice.messages)+len(sounds.cues) != 0 {
t.Fatal("invalid request restored speech or changed state", text, response)
}
}
for _, text := range []string{"COMMAND SAY discarded", "SETTING SET reading#mode=highlight"} {
if response := runtime_request(a, text); response != "" || !a.temporarySilence || len(voice.messages) != 0 {
t.Fatal("unrelated request cleared temporary silence", text, response)
}
}
if response := runtime_request(a, "SETTING SET speech#enabled=True"); response != "" || a.temporarySilence || a.muted {
t.Fatal("explicit enable failed to restore temporary silence", response)
}
if soundMode == "enabled" {
if !reflect.DeepEqual(sounds.cues, []presentation.Cue{presentation.SpeechOn}) || len(voice.messages) != 0 {
t.Fatal("temporary restoration feedback", sounds.cues, voice.messages)
}
} else if !reflect.DeepEqual(voice.messages, []string{"speech enabled"}) {
t.Fatal("temporary restoration fallback", soundMode, voice.messages)
}
}
}
}
func TestRemoteNoArgumentCommandsRejectExtraParameters(t *testing.T) {
a, voice := persistence_application(t, true)
for _, verb := range []string{"INTERRUPT", "TEMPDISABLESPEECH", "QUITAPPLICATION", "EXPORTCLIPBOARD"} {
before := voice.interrupts
if response := runtime_request(a, "COMMAND "+verb+" extra"); response == "" || a.quitting || a.temporarySilence || voice.interrupts != before {
t.Fatal("malformed command had side effects", verb, response)
}
}
}