This repository has been archived on 2026-03-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
oubliette/internal/config/config_test.go
Torjus Håkestad d655968216 feat: add SQLite storage for login attempts and sessions
Adds persistent storage using modernc.org/sqlite (pure Go). Login
attempts are deduplicated by (username, password, ip) with counts.
Sessions and session logs are tracked with UUID IDs. Includes embedded
SQL migrations, configurable retention with background pruning, and
an in-memory store for tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 17:33:45 +01:00

195 lines
4.8 KiB
Go

package config
import (
"os"
"path/filepath"
"testing"
"time"
)
func TestLoadValidConfig(t *testing.T) {
content := `
log_level = "debug"
[ssh]
listen_addr = ":3333"
host_key_path = "/tmp/test_key"
[auth]
accept_after = 5
credential_ttl = "1h"
[[auth.static_credentials]]
username = "root"
password = "toor"
`
path := writeTemp(t, content)
cfg, err := Load(path)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if cfg.LogLevel != "debug" {
t.Errorf("log_level = %q, want %q", cfg.LogLevel, "debug")
}
if cfg.SSH.ListenAddr != ":3333" {
t.Errorf("listen_addr = %q, want %q", cfg.SSH.ListenAddr, ":3333")
}
if cfg.SSH.HostKeyPath != "/tmp/test_key" {
t.Errorf("host_key_path = %q, want %q", cfg.SSH.HostKeyPath, "/tmp/test_key")
}
if cfg.Auth.AcceptAfter != 5 {
t.Errorf("accept_after = %d, want %d", cfg.Auth.AcceptAfter, 5)
}
if cfg.Auth.CredentialTTLDuration != time.Hour {
t.Errorf("credential_ttl_duration = %v, want %v", cfg.Auth.CredentialTTLDuration, time.Hour)
}
if len(cfg.Auth.StaticCredentials) != 1 {
t.Fatalf("static_credentials len = %d, want 1", len(cfg.Auth.StaticCredentials))
}
if cfg.Auth.StaticCredentials[0].Username != "root" {
t.Errorf("username = %q, want %q", cfg.Auth.StaticCredentials[0].Username, "root")
}
}
func TestLoadDefaults(t *testing.T) {
path := writeTemp(t, "")
cfg, err := Load(path)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if cfg.SSH.ListenAddr != ":2222" {
t.Errorf("default listen_addr = %q, want %q", cfg.SSH.ListenAddr, ":2222")
}
if cfg.SSH.HostKeyPath != "oubliette_host_key" {
t.Errorf("default host_key_path = %q, want %q", cfg.SSH.HostKeyPath, "oubliette_host_key")
}
if cfg.Auth.AcceptAfter != 10 {
t.Errorf("default accept_after = %d, want %d", cfg.Auth.AcceptAfter, 10)
}
if cfg.Auth.CredentialTTLDuration != 24*time.Hour {
t.Errorf("default credential_ttl = %v, want %v", cfg.Auth.CredentialTTLDuration, 24*time.Hour)
}
if cfg.LogLevel != "info" {
t.Errorf("default log_level = %q, want %q", cfg.LogLevel, "info")
}
if cfg.Storage.DBPath != "oubliette.db" {
t.Errorf("default db_path = %q, want %q", cfg.Storage.DBPath, "oubliette.db")
}
if cfg.Storage.RetentionDays != 90 {
t.Errorf("default retention_days = %d, want %d", cfg.Storage.RetentionDays, 90)
}
if cfg.Storage.RetentionIntervalDuration != time.Hour {
t.Errorf("default retention_interval = %v, want %v", cfg.Storage.RetentionIntervalDuration, time.Hour)
}
}
func TestLoadInvalidTTL(t *testing.T) {
content := `
[auth]
credential_ttl = "notaduration"
`
path := writeTemp(t, content)
_, err := Load(path)
if err == nil {
t.Fatal("expected error for invalid credential_ttl")
}
}
func TestLoadNegativeTTL(t *testing.T) {
content := `
[auth]
credential_ttl = "-1h"
`
path := writeTemp(t, content)
_, err := Load(path)
if err == nil {
t.Fatal("expected error for negative credential_ttl")
}
}
func TestLoadInvalidStaticCredential(t *testing.T) {
content := `
[[auth.static_credentials]]
username = ""
password = "test"
`
path := writeTemp(t, content)
_, err := Load(path)
if err == nil {
t.Fatal("expected error for empty username")
}
}
func TestLoadInvalidRetentionInterval(t *testing.T) {
content := `
[storage]
retention_interval = "notaduration"
`
path := writeTemp(t, content)
_, err := Load(path)
if err == nil {
t.Fatal("expected error for invalid retention_interval")
}
}
func TestLoadInvalidRetentionDays(t *testing.T) {
content := `
[storage]
retention_days = -1
`
path := writeTemp(t, content)
_, err := Load(path)
if err == nil {
t.Fatal("expected error for negative retention_days")
}
}
func TestLoadStorageConfig(t *testing.T) {
content := `
[storage]
db_path = "/tmp/test.db"
retention_days = 30
retention_interval = "2h"
`
path := writeTemp(t, content)
cfg, err := Load(path)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if cfg.Storage.DBPath != "/tmp/test.db" {
t.Errorf("db_path = %q, want %q", cfg.Storage.DBPath, "/tmp/test.db")
}
if cfg.Storage.RetentionDays != 30 {
t.Errorf("retention_days = %d, want 30", cfg.Storage.RetentionDays)
}
if cfg.Storage.RetentionIntervalDuration != 2*time.Hour {
t.Errorf("retention_interval = %v, want 2h", cfg.Storage.RetentionIntervalDuration)
}
}
func TestLoadMissingFile(t *testing.T) {
_, err := Load("/nonexistent/path/config.toml")
if err == nil {
t.Fatal("expected error for missing file")
}
}
func TestLoadInvalidTOML(t *testing.T) {
path := writeTemp(t, "{{{{invalid toml")
_, err := Load(path)
if err == nil {
t.Fatal("expected error for invalid TOML")
}
}
func writeTemp(t *testing.T, content string) string {
t.Helper()
path := filepath.Join(t.TempDir(), "config.toml")
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
t.Fatalf("writing temp config: %v", err)
}
return path
}