// Copyright (c) 2026 Storm Dragon // SPDX-License-Identifier: GPL-3.0-or-later package config import ( "bytes" "os" "path/filepath" "testing" ) func TestStartupSaveDestinationAndLegacySettingsIgnored(t *testing.T) { for _, scenario := range []string{"defaults", "system fallback", "personal", "explicit", "root"} { t.Run(scenario, func(t *testing.T) { root := t.TempDir() paths := Paths(root, 1000) userPath := paths[0] // Substitute an isolated system directory without touching /etc. systemPath := filepath.Join(root, "etc", "settings.toml") paths[1] = systemPath legacyPath := filepath.Join(filepath.Dir(userPath), "settings.conf") legacy := []byte("[speech]\nrate = 19\n") if err := os.MkdirAll(filepath.Dir(userPath), 0700); err != nil { t.Fatal(err) } if err := os.WriteFile(legacyPath, legacy, 0600); err != nil { t.Fatal(err) } requested, destination, rate := "", userPath, 0 if scenario != "defaults" { system := Defaults() system.Presentation.Speech.Rate = 30 if err := Save(systemPath, system); err != nil { t.Fatal(err) } rate = 30 } switch scenario { case "personal": personal := Defaults() personal.Presentation.Speech.Rate = 40 if err := Save(userPath, personal); err != nil { t.Fatal(err) } rate = 40 case "explicit": requested, destination = systemPath, systemPath case "root": paths, destination = []string{systemPath}, systemPath } systemBefore, _ := os.ReadFile(systemPath) settings, path, err := Load_startup(requested, paths) if err != nil || path != destination || settings.Presentation.Speech.Rate != rate { t.Fatalf("startup: destination=%q rate=%d err=%v", path, settings.Presentation.Speech.Rate, err) } // Follow the settings menu's document save workflow, then restart. doc, err := Open_document(path, settings) if err != nil || doc.Settings.Presentation.Speech.Rate != rate { t.Fatalf("open settings: %+v %v", doc, err) } settings.Presentation.Speech.Rate = 55 if err := doc.Save(settings); err != nil { t.Fatal(err) } restarted, path, err := Load_startup(requested, paths) if err != nil || path != destination || restarted.Presentation.Speech.Rate != 55 { t.Fatalf("restart: destination=%q rate=%d err=%v", path, restarted.Presentation.Speech.Rate, err) } if destination != systemPath { systemAfter, _ := os.ReadFile(systemPath) if !bytes.Equal(systemBefore, systemAfter) { t.Fatal("personal save modified the system file") } } if data, err := os.ReadFile(legacyPath); err != nil || !bytes.Equal(data, legacy) { t.Fatal("legacy settings changed", err) } }) } } func TestStartupErrorsIdentifySource(t *testing.T) { root := t.TempDir() userPath, systemPath := filepath.Join(root, "user.toml"), filepath.Join(root, "system.toml") if err := os.WriteFile(systemPath, []byte("invalid=true"), 0600); err != nil { t.Fatal(err) } if _, path, err := Load_startup("", []string{userPath, systemPath}); err == nil || path != systemPath { t.Fatal("invalid fallback did not identify source", path, err) } if _, path, err := Load_startup(userPath, []string{systemPath}); err == nil || path != userPath { t.Fatal("explicit missing file did not identify source", path, err) } }