Switch config from YAML to TOML

This commit is contained in:
prosolis
2026-05-24 22:11:36 -07:00
parent e88483526d
commit 9d5db63c56
11 changed files with 280 additions and 253 deletions

View File

@@ -8,28 +8,29 @@ import (
// validMatrix is a reusable matrix config block for tests.
const validMatrix = `
matrix:
homeserver: "https://matrix.example.org"
user_id: "@pete:example.org"
password: "testpass"
channels:
tech: "!tech:example.org"
politics: "!politics:example.org"
[matrix]
homeserver = "https://matrix.example.org"
user_id = "@pete:example.org"
password = "testpass"
[matrix.channels]
tech = "!tech:example.org"
politics = "!politics:example.org"
`
func TestLoadValid(t *testing.T) {
yaml := validMatrix + `
storage:
db_path: "/tmp/test.db"
sources:
- name: "Test Source"
feed_url: "https://example.com/rss"
tier: 1
poll_interval_minutes: 20
direct_route: "tech"
enabled: true
toml := validMatrix + `
[storage]
db_path = "/tmp/test.db"
[[sources]]
name = "Test Source"
feed_url = "https://example.com/rss"
tier = 1
poll_interval_minutes = 20
direct_route = "tech"
enabled = true
`
cfg := loadFromString(t, yaml)
cfg := loadFromString(t, toml)
if cfg.Matrix.Homeserver != "https://matrix.example.org" {
t.Errorf("homeserver = %q", cfg.Matrix.Homeserver)
@@ -51,18 +52,18 @@ sources:
func TestEnvVarExpansion(t *testing.T) {
t.Setenv("TEST_PETE_PASS", "secret_pass_123")
yaml := `
matrix:
homeserver: "https://matrix.example.org"
user_id: "@pete:example.org"
password: "${TEST_PETE_PASS}"
channels:
tech: "!tech:example.org"
storage:
db_path: "/tmp/test.db"
sources: []
toml := `
[matrix]
homeserver = "https://matrix.example.org"
user_id = "@pete:example.org"
password = "${TEST_PETE_PASS}"
[matrix.channels]
tech = "!tech:example.org"
[storage]
db_path = "/tmp/test.db"
`
cfg := loadFromString(t, yaml)
cfg := loadFromString(t, toml)
if cfg.Matrix.Password != "secret_pass_123" {
t.Errorf("password = %q, want secret_pass_123", cfg.Matrix.Password)
@@ -70,18 +71,19 @@ sources: []
}
func TestDefaults(t *testing.T) {
yaml := validMatrix + `
storage:
db_path: "/tmp/test.db"
sources:
- name: "S"
feed_url: "https://example.com/rss"
tier: 1
poll_interval_minutes: 20
direct_route: "tech"
enabled: true
toml := validMatrix + `
[storage]
db_path = "/tmp/test.db"
[[sources]]
name = "S"
feed_url = "https://example.com/rss"
tier = 1
poll_interval_minutes = 20
direct_route = "tech"
enabled = true
`
cfg := loadFromString(t, yaml)
cfg := loadFromString(t, toml)
if cfg.Matrix.DataDir != "./data" {
t.Errorf("data_dir default = %q, want ./data", cfg.Matrix.DataDir)
@@ -106,109 +108,125 @@ sources:
func TestValidationErrors(t *testing.T) {
tests := []struct {
name string
yaml string
toml string
}{
{"missing homeserver", `
matrix:
user_id: "@p:h"
password: "pw"
channels: {tech: "!t:e"}
storage: {db_path: "/tmp/t.db"}
[matrix]
user_id = "@p:h"
password = "pw"
[matrix.channels]
tech = "!t:e"
[storage]
db_path = "/tmp/t.db"
`},
{"missing user_id", `
matrix:
homeserver: "https://h"
password: "pw"
channels: {tech: "!t:e"}
storage: {db_path: "/tmp/t.db"}
[matrix]
homeserver = "https://h"
password = "pw"
[matrix.channels]
tech = "!t:e"
[storage]
db_path = "/tmp/t.db"
`},
{"missing password", `
matrix:
homeserver: "https://h"
user_id: "@p:h"
channels: {tech: "!t:e"}
storage: {db_path: "/tmp/t.db"}
[matrix]
homeserver = "https://h"
user_id = "@p:h"
[matrix.channels]
tech = "!t:e"
[storage]
db_path = "/tmp/t.db"
`},
{"no channels", `
matrix:
homeserver: "https://h"
user_id: "@p:h"
password: "pw"
storage: {db_path: "/tmp/t.db"}
[matrix]
homeserver = "https://h"
user_id = "@p:h"
password = "pw"
[storage]
db_path = "/tmp/t.db"
`},
{"missing db_path", `
matrix:
homeserver: "https://h"
user_id: "@p:h"
password: "pw"
channels: {tech: "!t:e"}
storage: {}
[matrix]
homeserver = "https://h"
user_id = "@p:h"
password = "pw"
[matrix.channels]
tech = "!t:e"
[storage]
`},
{"invalid tier", `
matrix:
homeserver: "https://h"
user_id: "@p:h"
password: "pw"
channels: {tech: "!t:e"}
storage: {db_path: "/tmp/t.db"}
sources:
- name: "S"
feed_url: "https://e.com/rss"
tier: 5
poll_interval_minutes: 20
direct_route: "tech"
enabled: true
[matrix]
homeserver = "https://h"
user_id = "@p:h"
password = "pw"
[matrix.channels]
tech = "!t:e"
[storage]
db_path = "/tmp/t.db"
[[sources]]
name = "S"
feed_url = "https://e.com/rss"
tier = 5
poll_interval_minutes = 20
direct_route = "tech"
enabled = true
`},
{"missing source name", `
matrix:
homeserver: "https://h"
user_id: "@p:h"
password: "pw"
channels: {tech: "!t:e"}
storage: {db_path: "/tmp/t.db"}
sources:
- feed_url: "https://e.com/rss"
tier: 1
poll_interval_minutes: 20
direct_route: "tech"
enabled: true
[matrix]
homeserver = "https://h"
user_id = "@p:h"
password = "pw"
[matrix.channels]
tech = "!t:e"
[storage]
db_path = "/tmp/t.db"
[[sources]]
feed_url = "https://e.com/rss"
tier = 1
poll_interval_minutes = 20
direct_route = "tech"
enabled = true
`},
{"enabled source missing direct_route", `
matrix:
homeserver: "https://h"
user_id: "@p:h"
password: "pw"
channels: {tech: "!t:e"}
storage: {db_path: "/tmp/t.db"}
sources:
- name: "S"
feed_url: "https://e.com/rss"
tier: 1
poll_interval_minutes: 20
enabled: true
[matrix]
homeserver = "https://h"
user_id = "@p:h"
password = "pw"
[matrix.channels]
tech = "!t:e"
[storage]
db_path = "/tmp/t.db"
[[sources]]
name = "S"
feed_url = "https://e.com/rss"
tier = 1
poll_interval_minutes = 20
enabled = true
`},
{"direct_route not in channels", `
matrix:
homeserver: "https://h"
user_id: "@p:h"
password: "pw"
channels: {tech: "!t:e"}
storage: {db_path: "/tmp/t.db"}
sources:
- name: "S"
feed_url: "https://e.com/rss"
tier: 1
poll_interval_minutes: 20
direct_route: "gaming"
enabled: true
[matrix]
homeserver = "https://h"
user_id = "@p:h"
password = "pw"
[matrix.channels]
tech = "!t:e"
[storage]
db_path = "/tmp/t.db"
[[sources]]
name = "S"
feed_url = "https://e.com/rss"
tier = 1
poll_interval_minutes = 20
direct_route = "gaming"
enabled = true
`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "config.yaml")
os.WriteFile(path, []byte(tt.yaml), 0o644)
path := filepath.Join(dir, "config.toml")
os.WriteFile(path, []byte(tt.toml), 0o644)
_, err := Load(path)
if err == nil {
t.Error("expected validation error, got nil")
@@ -219,31 +237,33 @@ sources:
func TestDisabledSourceSkipsDirectRouteCheck(t *testing.T) {
// A disabled source without direct_route must not fail validation.
yaml := `
matrix:
homeserver: "https://h"
user_id: "@p:h"
password: "pw"
channels: {tech: "!t:e"}
storage: {db_path: "/tmp/t.db"}
sources:
- name: "Off"
feed_url: "https://e.com/rss"
tier: 1
poll_interval_minutes: 20
enabled: false
toml := `
[matrix]
homeserver = "https://h"
user_id = "@p:h"
password = "pw"
[matrix.channels]
tech = "!t:e"
[storage]
db_path = "/tmp/t.db"
[[sources]]
name = "Off"
feed_url = "https://e.com/rss"
tier = 1
poll_interval_minutes = 20
enabled = false
`
cfg := loadFromString(t, yaml)
cfg := loadFromString(t, toml)
if cfg.Sources[0].DirectRoute != "" {
t.Errorf("expected empty direct_route, got %q", cfg.Sources[0].DirectRoute)
}
}
func loadFromString(t *testing.T, yamlContent string) *Config {
func loadFromString(t *testing.T, tomlContent string) *Config {
t.Helper()
dir := t.TempDir()
path := filepath.Join(dir, "config.yaml")
if err := os.WriteFile(path, []byte(yamlContent), 0o644); err != nil {
path := filepath.Join(dir, "config.toml")
if err := os.WriteFile(path, []byte(tomlContent), 0o644); err != nil {
t.Fatal(err)
}
cfg, err := Load(path)