Something went wrong. Try again.
cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 🍃
charm leaflet readability golang
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311package store
import ( "database/sql" "fmt" "os" "path/filepath" "runtime" "strings" "testing"
"github.com/stormlightlabs/noteleaf/internal/shared")
func withTempDirs(t *testing.T) string { t.Helper() tempDir, cleanup := shared.CreateTempDir("noteleaf-db-test-*", t) t.Cleanup(func() { cleanup() })
origConfig, origData := GetConfigDir, GetDataDir GetConfigDir = func() (string, error) { return tempDir, nil } GetDataDir = func() (string, error) { return tempDir, nil } t.Cleanup(func() { GetConfigDir, GetDataDir = origConfig, origData })
return tempDir}
func TestNewDatabase(t *testing.T) { tempDir := withTempDirs(t)
t.Run("creates database file", func(t *testing.T) { db, err := NewDatabase() if err != nil { t.Fatalf("NewDatabase failed: %v", err) } defer db.Close()
dbPath := filepath.Join(tempDir, "noteleaf.db") if _, err := os.Stat(dbPath); os.IsNotExist(err) { t.Errorf("expected database file at %s", dbPath) } })
t.Run("foreign keys enabled", func(t *testing.T) { db, _ := NewDatabase() defer db.Close()
var fk int if err := db.QueryRow("PRAGMA foreign_keys").Scan(&fk); err != nil { t.Fatalf("query failed: %v", err) } if fk != 1 { t.Errorf("expected foreign_keys=1, got %d", fk) } })
t.Run("WAL enabled", func(t *testing.T) { db, _ := NewDatabase() defer db.Close()
var mode string if err := db.QueryRow("PRAGMA journal_mode").Scan(&mode); err != nil { t.Fatalf("query failed: %v", err) } if strings.ToLower(mode) != "wal" { t.Errorf("expected wal, got %s", mode) } })}
func TestNewDatabase_ErrorPaths(t *testing.T) { t.Run("sql.Open fails", func(t *testing.T) { orig := sqlOpen sqlOpen = func(driver, dsn string) (*sql.DB, error) { return nil, fmt.Errorf("boom") } t.Cleanup(func() { sqlOpen = orig })
_, err := NewDatabase() if err == nil || !strings.Contains(err.Error(), "failed to open database") { t.Errorf("expected open error, got %v", err) } })
t.Run("foreign_keys pragma fails", func(t *testing.T) { orig := pragmaExec pragmaExec = func(db *sql.DB, stmt string) (sql.Result, error) { if strings.Contains(stmt, "foreign_keys") { return nil, fmt.Errorf("fk fail") } return orig(db, stmt) } t.Cleanup(func() { pragmaExec = orig })
_, err := NewDatabase() if err == nil || !strings.Contains(err.Error(), "failed to enable foreign keys") { t.Errorf("expected foreign key error, got %v", err) } })
t.Run("WAL pragma fails", func(t *testing.T) { orig := pragmaExec pragmaExec = func(db *sql.DB, stmt string) (sql.Result, error) { if strings.Contains(stmt, "journal_mode") { return nil, fmt.Errorf("wal fail") } return orig(db, stmt) } t.Cleanup(func() { pragmaExec = orig })
_, err := NewDatabase() if err == nil || !strings.Contains(err.Error(), "failed to enable WAL mode") { t.Errorf("expected WAL error, got %v", err) } })
t.Run("migration runner fails", func(t *testing.T) { orig := createMigrationRunner createMigrationRunner = func(db *sql.DB, fs FileSystem) *MigrationRunner { return &MigrationRunner{runFn: func() error { return fmt.Errorf("migration fail") }} } t.Cleanup(func() { createMigrationRunner = orig })
_, err := NewDatabase() if err == nil || !strings.Contains(err.Error(), "failed to run migrations") { t.Errorf("expected migration error, got %v", err) } })
t.Run("permission denied on config dir", func(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("not reliable on Windows") } dir := withTempDirs(t) os.Chmod(dir, 0555) // make read-only defer os.Chmod(dir, 0755)
GetConfigDir = func() (string, error) { return dir, nil }
_, err := NewDatabase() if err == nil { t.Error("expected mkdir fail due to permission denied") } })}
func TestGetConfigDir_AllBranches(t *testing.T) { tmp := t.TempDir()
t.Run("windows success", func(t *testing.T) { origGOOS := getRuntime getRuntime = func() string { return "windows" } defer func() { getRuntime = origGOOS }()
os.Setenv("APPDATA", tmp) defer os.Unsetenv("APPDATA")
dir, err := GetConfigDir() if err != nil { t.Fatalf("unexpected error: %v", err) } expected := filepath.Join(tmp, "noteleaf") if dir != expected { t.Errorf("expected %s, got %s", expected, dir) } })
t.Run("windows missing APPDATA", func(t *testing.T) { origGOOS := getRuntime getRuntime = func() string { return "windows" } defer func() { getRuntime = origGOOS }()
os.Unsetenv("APPDATA")
_, err := GetConfigDir() if err == nil || !strings.Contains(err.Error(), "APPDATA") { t.Errorf("expected APPDATA error, got %v", err) } })
t.Run("darwin success", func(t *testing.T) { origGOOS, origHome := getRuntime, getHomeDir getRuntime = func() string { return "darwin" } getHomeDir = func() (string, error) { return tmp, nil } defer func() { getRuntime = origGOOS getHomeDir = origHome }()
dir, err := GetConfigDir() if err != nil { t.Fatalf("unexpected error: %v", err) } expected := filepath.Join(tmp, "Library", "Application Support", "noteleaf") if dir != expected { t.Errorf("expected %s, got %s", expected, dir) } })
t.Run("linux default with XDG_CONFIG_HOME unset", func(t *testing.T) { origGOOS, origHome := getRuntime, getHomeDir getRuntime = func() string { return "linux" } getHomeDir = func() (string, error) { return tmp, nil } defer func() { getRuntime = origGOOS getHomeDir = origHome }()
os.Unsetenv("XDG_CONFIG_HOME")
dir, err := GetConfigDir() if err != nil { t.Fatalf("unexpected error: %v", err) } expected := filepath.Join(tmp, ".config", "noteleaf") if dir != expected { t.Errorf("expected %s, got %s", expected, dir) } })}
func TestGetDataDir_AllBranches(t *testing.T) { tmp := t.TempDir()
t.Run("NOTELEAF_DATA_DIR overrides", func(t *testing.T) { os.Setenv("NOTELEAF_DATA_DIR", tmp) defer os.Unsetenv("NOTELEAF_DATA_DIR")
dir, err := GetDataDir() if err != nil { t.Fatalf("unexpected error: %v", err) } if dir != tmp { t.Errorf("expected %s, got %s", tmp, dir) } })
t.Run("windows success", func(t *testing.T) { origGOOS := getRuntime getRuntime = func() string { return "windows" } defer func() { getRuntime = origGOOS }()
os.Setenv("LOCALAPPDATA", tmp) defer os.Unsetenv("LOCALAPPDATA")
dir, err := GetDataDir() if err != nil { t.Fatalf("unexpected error: %v", err) } expected := filepath.Join(tmp, "noteleaf") if dir != expected { t.Errorf("expected %s, got %s", expected, dir) } })
t.Run("windows missing LOCALAPPDATA", func(t *testing.T) { origGOOS := getRuntime getRuntime = func() string { return "windows" } defer func() { getRuntime = origGOOS }()
os.Unsetenv("LOCALAPPDATA")
_, err := GetDataDir() if err == nil || !strings.Contains(err.Error(), "LOCALAPPDATA") { t.Errorf("expected LOCALAPPDATA error, got %v", err) } })
t.Run("darwin success", func(t *testing.T) { origGOOS, origHome := getRuntime, getHomeDir getRuntime = func() string { return "darwin" } getHomeDir = func() (string, error) { return tmp, nil } defer func() { getRuntime = origGOOS getHomeDir = origHome }()
dir, err := GetDataDir() if err != nil { t.Fatalf("unexpected error: %v", err) } expected := filepath.Join(tmp, "Library", "Application Support", "noteleaf") if dir != expected { t.Errorf("expected %s, got %s", expected, dir) } })
t.Run("linux default with XDG_DATA_HOME unset", func(t *testing.T) { origGOOS, origHome := getRuntime, getHomeDir getRuntime = func() string { return "linux" } getHomeDir = func() (string, error) { return tmp, nil } defer func() { getRuntime = origGOOS getHomeDir = origHome }()
os.Unsetenv("XDG_DATA_HOME")
dir, err := GetDataDir() if err != nil { t.Fatalf("unexpected error: %v", err) } expected := filepath.Join(tmp, ".local", "share", "noteleaf") if dir != expected { t.Errorf("expected %s, got %s", expected, dir) } })}