157 lines
5.1 KiB
Go
157 lines
5.1 KiB
Go
package config
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
const sampleLogPath = `C:\ProgramData\gpu-turnstile\gpu-turnstile.log`
|
|
|
|
var allSettingNames = []string{
|
|
"LISTEN_OLLAMA", "LISTEN_COMFY", "OLLAMA_URL", "COMFY_URL",
|
|
"WARM_MODEL", "UNLOAD_TIMEOUT", "JOB_TIMEOUT", "LLM_WAIT_TIMEOUT",
|
|
"LLM_BUSY_MODE", "LLM_BUSY_STATUS", "BUSY_RETRY_AFTER",
|
|
"LOGLEVEL", "LOG_FORMAT", "LOG_FILE",
|
|
"UNLOAD_POLL_INTERVAL", "HISTORY_POLL_INTERVAL", "PROBE_TIMEOUT",
|
|
"FREE_TIMEOUT", "WARM_TIMEOUT", "SHUTDOWN_TIMEOUT",
|
|
"BACKOFF_INITIAL", "BACKOFF_MAX", "PROMPT_CAPTURE_LIMIT",
|
|
"AUTO_UPDATE", "UPDATE_INTERVAL", "UPDATE_REPO", "UPDATE_ASSET",
|
|
}
|
|
|
|
func TestSampleEnv(t *testing.T) {
|
|
sample := SampleEnv("v0.1.7", sampleLogPath)
|
|
|
|
if !strings.HasPrefix(sample, "CFG_VER=v0.1.7\n") {
|
|
t.Errorf("first line does not carry CFG_VER: %q", strings.SplitN(sample, "\n", 2)[0])
|
|
}
|
|
|
|
// Every setting known to Load must appear.
|
|
for _, name := range allSettingNames {
|
|
if !strings.Contains(sample, name+"=") {
|
|
t.Errorf("sample is missing %s", name)
|
|
}
|
|
}
|
|
|
|
// The sample must parse cleanly; active values are CFG_VER, APP_VER
|
|
// and LOG_FILE.
|
|
values, err := ParseEnvFile(strings.NewReader(sample))
|
|
if err != nil {
|
|
t.Fatalf("sample does not parse: %v", err)
|
|
}
|
|
want := map[string]string{"CFG_VER": "v0.1.7", "APP_VER": "stable", "LOG_FILE": sampleLogPath}
|
|
if len(values) != len(want) {
|
|
t.Fatalf("active values = %v, want %v", values, want)
|
|
}
|
|
for k, v := range want {
|
|
if values[k] != v {
|
|
t.Errorf("%s = %q, want %q", k, values[k], v)
|
|
}
|
|
}
|
|
|
|
// Without a log path LOG_FILE stays commented out.
|
|
values, err = ParseEnvFile(strings.NewReader(SampleEnv("v0.1.7", "")))
|
|
if err != nil {
|
|
t.Fatalf("sample without log path does not parse: %v", err)
|
|
}
|
|
if len(values) != 2 || values["LOG_FILE"] != "" {
|
|
t.Fatalf("active values = %v, want only CFG_VER and APP_VER", values)
|
|
}
|
|
}
|
|
|
|
func TestSyncSample(t *testing.T) {
|
|
old := SampleEnv("v0.1.6", sampleLogPath)
|
|
// Simulate a setting that did not exist yet when the file was written.
|
|
old = strings.Replace(old, "#UPDATE_ASSET=gpu-turnstile.exe\n", "", 1)
|
|
|
|
out, changed := SyncSample(old, "v0.1.7", sampleLogPath)
|
|
if !changed {
|
|
t.Fatal("older installer file was not upgraded")
|
|
}
|
|
if !strings.Contains(out, "\nCFG_VER=v0.1.7\n") && !strings.HasPrefix(out, "CFG_VER=v0.1.7\n") {
|
|
t.Error("CFG_VER was not updated to the new version")
|
|
}
|
|
if !strings.Contains(out, "#UPDATE_ASSET=gpu-turnstile.exe") {
|
|
t.Error("missing setting was not appended")
|
|
}
|
|
if !strings.Contains(out, "LOG_FILE="+sampleLogPath) {
|
|
t.Error("existing active LOG_FILE was lost")
|
|
}
|
|
if !strings.Contains(out, "Added by gpu-turnstile v0.1.7") {
|
|
t.Error("appended section is not attributed")
|
|
}
|
|
if _, err := ParseEnvFile(strings.NewReader(out)); err != nil {
|
|
t.Fatalf("upgraded file does not parse: %v", err)
|
|
}
|
|
|
|
// A file written by the same or a newer version is left alone.
|
|
if _, changed := SyncSample(SampleEnv("v0.1.7", sampleLogPath), "v0.1.7", sampleLogPath); changed {
|
|
t.Error("same-version file was modified")
|
|
}
|
|
if _, changed := SyncSample(SampleEnv("v0.2.0", sampleLogPath), "v0.1.7", sampleLogPath); changed {
|
|
t.Error("newer-version file was modified")
|
|
}
|
|
|
|
// Files without CFG_VER are not installer-written; the installer
|
|
// replaces them, SyncSample leaves them alone.
|
|
user := "OLLAMA_URL=http://host:11434\n"
|
|
if out, changed := SyncSample(user, "v0.1.7", sampleLogPath); changed || out != user {
|
|
t.Error("file without CFG_VER was modified")
|
|
}
|
|
|
|
// A dev build never upgrades.
|
|
if _, changed := SyncSample(old, "dev", sampleLogPath); changed {
|
|
t.Error("dev build modified the file")
|
|
}
|
|
}
|
|
|
|
func TestSyncSampleAppendsMissingAppVer(t *testing.T) {
|
|
old := SampleEnv("v0.1.6", sampleLogPath)
|
|
old = strings.Replace(old, "# "+appVerComment+"\n", "", 1)
|
|
old = strings.Replace(old, "APP_VER=stable\n", "", 1)
|
|
|
|
out, changed := SyncSample(old, "v0.1.7", sampleLogPath)
|
|
if !changed {
|
|
t.Fatal("file without APP_VER was not upgraded")
|
|
}
|
|
values, err := ParseEnvFile(strings.NewReader(out))
|
|
if err != nil {
|
|
t.Fatalf("upgraded file does not parse: %v", err)
|
|
}
|
|
if values["APP_VER"] != "stable" {
|
|
t.Fatalf("APP_VER = %q, want appended default \"stable\"", values["APP_VER"])
|
|
}
|
|
}
|
|
|
|
func TestSampleEnvDevStampsConcreteVersion(t *testing.T) {
|
|
// A dev build must never write CFG_VER=dev: it stamps v0.0.0, and the
|
|
// next release install upgrades the file to a proper version.
|
|
dev := SampleEnv("dev", sampleLogPath)
|
|
if !strings.HasPrefix(dev, "CFG_VER=v0.0.0\n") {
|
|
t.Errorf("dev sample first line: %q", strings.SplitN(dev, "\n", 2)[0])
|
|
}
|
|
out, changed := SyncSample(dev, "v0.1.7", sampleLogPath)
|
|
if !changed || !strings.HasPrefix(out, "CFG_VER=v0.1.7\n") {
|
|
t.Errorf("dev-stamped file was not upgraded to v0.1.7 (changed=%v)", changed)
|
|
}
|
|
}
|
|
|
|
func TestCompareVersions(t *testing.T) {
|
|
cases := []struct {
|
|
a, b string
|
|
want int
|
|
}{
|
|
{"v0.1.6", "v0.1.7", -1},
|
|
{"v0.1.7", "v0.1.7", 0},
|
|
{"v1.0.0", "v0.9.9", 1},
|
|
{"0.1.7", "v0.1.6", 1},
|
|
{"dev", "v0.1.7", -1},
|
|
{"v0.1.7", "dev", 1},
|
|
{"dev", "dev", 0},
|
|
}
|
|
for _, c := range cases {
|
|
if got := compareVersions(c.a, c.b); got != c.want {
|
|
t.Errorf("compareVersions(%q, %q) = %d, want %d", c.a, c.b, got, c.want)
|
|
}
|
|
}
|
|
}
|