156 lines
6.1 KiB
Go
156 lines
6.1 KiB
Go
// Fenrir console screen reader.
|
|
// Copyright (c) 2026 Storm Dragon
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify it
|
|
// under the terms of the GNU General Public License as published by the Free
|
|
// Software Foundation, either version 3 of the License, or (at your option)
|
|
// any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
// more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along with
|
|
// this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
|
|
|
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestVersionOneMigrationPreservesValuesAndOnlyWritesOnSave(t *testing.T) {
|
|
original := []byte(`version = 1
|
|
[clipboard]
|
|
sync = true
|
|
sync_display = ":42"
|
|
number_of_clipboards = 7
|
|
export_path = "/tmp/fixture-clipboard"
|
|
[sound]
|
|
enabled = false
|
|
volume = 0.3
|
|
[speech]
|
|
enabled = false
|
|
rate = 45
|
|
module = "fixture"
|
|
socket = "/tmp/fixture.sock"
|
|
[keyboard]
|
|
layout = "laptop"
|
|
devices = ["/dev/input/event-fixture"]
|
|
character_echo = false
|
|
word_echo = true
|
|
echo_on_capslock = true
|
|
[reading]
|
|
automatic = false
|
|
cursor_echo = false
|
|
`)
|
|
path := filepath.Join(t.TempDir(), "settings.toml")
|
|
if err := os.WriteFile(path, original, 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
doc, err := Open_document(path, Defaults())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
wanted := Defaults()
|
|
wanted.Presentation.Sound = Sound{Enabled: false, Volume: 0.3, Driver: "pulse", Theme: "default", Device: "default"}
|
|
wanted.Presentation.Speech = Speech{Enabled: false, Rate: 45, Volume: 100, Driver: "speech-dispatcher", Module: "fixture"}
|
|
wanted.Keyboard = Keyboard{MultiPressTimeoutMS: 200, Layout: "laptop", Devices: []string{"/dev/input/event-fixture"}, WordEcho: true, EchoOnCapsLock: true}
|
|
wanted.Reading = Reading{Emoticons: true, RepeatedSymbolsMin: 4, Spellcheck: true, SpellcheckSound: true, Attributes: Defaults().Reading.Attributes, AttributeFormat: Defaults().Reading.AttributeFormat, Indentation: "none", RaisePitchForCapitals: true, Mode: "cursor", PunctuationProfile: "default", PunctuationLevel: "some"}
|
|
wanted.Clipboard = Clipboard{Sync: true, SyncDisplay: ":42", NumberOfClipboards: 7, ExportPath: "/tmp/fixture-clipboard"}
|
|
if !reflect.DeepEqual(doc.Settings, wanted) {
|
|
t.Fatal(doc.Settings, wanted)
|
|
}
|
|
data, err := os.ReadFile(path)
|
|
if err != nil || string(data) != string(original) {
|
|
t.Fatal("opening rewrote settings", err)
|
|
}
|
|
if err := doc.Save(doc.Settings); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data, err = os.ReadFile(path)
|
|
if err != nil || !strings.Contains(string(data), "version = 3") || strings.Contains(string(data), "\n[sound]") || strings.Contains(string(data), "socket =") {
|
|
t.Fatal(string(data), err)
|
|
}
|
|
got, err := Open_document(path, Defaults())
|
|
wantedOrder := []string{"clipboard", "presentation", "presentation.sound", "presentation.speech", "presentation.progress", "presentation.time_and_date", "keyboard", "reading", "internal_ui", "review", "screen", "general", "scripts", "remote", "prompt"}
|
|
if err != nil || !reflect.DeepEqual(got.Settings, wanted) || !reflect.DeepEqual(got.Order, wantedOrder) {
|
|
t.Fatal(got, err)
|
|
}
|
|
}
|
|
|
|
func TestRejectMixedSchemasAndUnknownDriverEvenWhenSpeechDisabled(t *testing.T) {
|
|
for _, input := range []string{
|
|
"version=1\n[presentation.speech]\nrate=40\n",
|
|
"version=2\n[speech]\nrate=40\n",
|
|
"version=2\n[presentation.speech]\ndriver='invented'\nenabled=false\n",
|
|
"version=1\n[speech]\ndriver='invented'\n",
|
|
"version=2\n[presentation.speech]\ndrivers=['speech-dispatcher']\n",
|
|
"version=0\n", "version=4\n",
|
|
"version=2\n[presentation.sound]\nvolume=nan\n",
|
|
"version=2\n[presentation.progress]\nenabled=true\n",
|
|
} {
|
|
if _, err := Decode([]byte(input)); err == nil {
|
|
t.Fatal("invalid schema accepted", input)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNestedDottedAndInlineSectionsShareOrder(t *testing.T) {
|
|
for _, input := range []string{
|
|
"version=2\n[reading]\nautomatic=false\n[presentation.sound]\nvolume=0.2\n[presentation.speech]\nrate=40\n",
|
|
"version=2\nreading.automatic=false\npresentation.sound.volume=0.2\npresentation.speech.rate=40\n",
|
|
"version=2\nreading={automatic=false}\npresentation.sound={volume=0.2}\npresentation.speech={rate=40}\n",
|
|
"version=2\nreading={automatic=false}\npresentation={sound={volume=0.2}, speech={rate=40}}\n",
|
|
"version=2\n[reading]\nautomatic=false\n[presentation]\nsound={volume=0.2}\nspeech={rate=40}\n",
|
|
} {
|
|
path := filepath.Join(t.TempDir(), "settings.toml")
|
|
if err := os.WriteFile(path, []byte(input), 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
doc, err := Open_document(path, Defaults())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := []string{"reading", "presentation", "presentation.sound", "presentation.speech"}
|
|
if !reflect.DeepEqual(doc.Order, want) {
|
|
t.Fatal(doc.Order)
|
|
}
|
|
if err := doc.Save(doc.Settings); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
saved, err := Open_document(path, Defaults())
|
|
if err == nil {
|
|
saved.Settings.Keyboard.Devices = doc.Settings.Keyboard.Devices
|
|
}
|
|
if err != nil || !reflect.DeepEqual(saved.Settings, doc.Settings) {
|
|
t.Fatal(saved, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestVersionTwoMigrationDiscardsSocketAndCurrentSchemaRejectsIt(t *testing.T) {
|
|
old := []byte("version=2\n[presentation.speech]\nsocket='/tmp/obsolete.sock'\nrate=45\nmodule='fixture'\n[presentation.sound]\nvolume=0.3\n")
|
|
settings, err := Decode(old)
|
|
if err != nil || settings.Version != 3 || settings.Presentation.Speech.Rate != 45 || settings.Presentation.Speech.Module != "fixture" || settings.Presentation.Sound.Volume != 0.3 {
|
|
t.Fatal(settings, err)
|
|
}
|
|
path := filepath.Join(t.TempDir(), "settings.toml")
|
|
if err := Save(path, settings); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data, err := os.ReadFile(path)
|
|
if err != nil || strings.Contains(string(data), "socket =") {
|
|
t.Fatal(string(data), err)
|
|
}
|
|
if _, err := Decode([]byte("version=3\n[presentation.speech]\nsocket='/tmp/unused.sock'\n")); err == nil {
|
|
t.Fatal("removed setting accepted in current schema")
|
|
}
|
|
}
|