cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 馃崈
charm leaflet readability golang
29
fork

Configure Feed

Select the types of activity you want to include in your feed.

at d2c4ecc217c2c1655026bba3b364c124b3a95a8a 302 lines 7.6 kB view raw
1package store 2 3import ( 4 "os" 5 "path/filepath" 6 "runtime" 7 "testing" 8) 9 10func TestNewDatabase(t *testing.T) { 11 tempDir, err := os.MkdirTemp("", "noteleaf-db-test-*") 12 if err != nil { 13 t.Fatalf("Failed to create temp directory: %v", err) 14 } 15 defer os.RemoveAll(tempDir) 16 17 originalGetConfigDir := GetConfigDir 18 GetConfigDir = func() (string, error) { 19 return tempDir, nil 20 } 21 defer func() { GetConfigDir = originalGetConfigDir }() 22 23 t.Run("creates database successfully", func(t *testing.T) { 24 db, err := NewDatabase() 25 if err != nil { 26 t.Fatalf("NewDatabase failed: %v", err) 27 } 28 defer db.Close() 29 30 if db == nil { 31 t.Fatal("Database should not be nil") 32 } 33 34 dbPath := filepath.Join(tempDir, "noteleaf.db") 35 if _, err := os.Stat(dbPath); os.IsNotExist(err) { 36 t.Error("Database file should exist") 37 } 38 39 if db.GetPath() != dbPath { 40 t.Errorf("Expected database path %s, got %s", dbPath, db.GetPath()) 41 } 42 }) 43 44 t.Run("enables foreign keys", func(t *testing.T) { 45 db, err := NewDatabase() 46 if err != nil { 47 t.Fatalf("NewDatabase failed: %v", err) 48 } 49 defer db.Close() 50 51 var foreignKeys int 52 err = db.QueryRow("PRAGMA foreign_keys").Scan(&foreignKeys) 53 if err != nil { 54 t.Fatalf("Failed to check foreign keys: %v", err) 55 } 56 57 if foreignKeys != 1 { 58 t.Error("Foreign keys should be enabled") 59 } 60 }) 61 62 t.Run("enables WAL mode", func(t *testing.T) { 63 db, err := NewDatabase() 64 if err != nil { 65 t.Fatalf("NewDatabase failed: %v", err) 66 } 67 defer db.Close() 68 69 var journalMode string 70 err = db.QueryRow("PRAGMA journal_mode").Scan(&journalMode) 71 if err != nil { 72 t.Fatalf("Failed to check journal mode: %v", err) 73 } 74 75 if journalMode != "wal" { 76 t.Errorf("Expected WAL journal mode, got %s", journalMode) 77 } 78 }) 79 80 t.Run("runs migrations", func(t *testing.T) { 81 db, err := NewDatabase() 82 if err != nil { 83 t.Fatalf("NewDatabase failed: %v", err) 84 } 85 defer db.Close() 86 87 var count int 88 err = db.QueryRow("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='migrations'").Scan(&count) 89 if err != nil { 90 t.Fatalf("Failed to check migrations table: %v", err) 91 } 92 93 if count != 1 { 94 t.Error("Migrations table should exist") 95 } 96 97 var migrationCount int 98 err = db.QueryRow("SELECT COUNT(*) FROM migrations").Scan(&migrationCount) 99 if err != nil { 100 t.Fatalf("Failed to count migrations: %v", err) 101 } 102 103 if migrationCount == 0 { 104 t.Error("At least one migration should be applied") 105 } 106 }) 107 108 t.Run("creates migration runner", func(t *testing.T) { 109 db, err := NewDatabase() 110 if err != nil { 111 t.Fatalf("NewDatabase failed: %v", err) 112 } 113 defer db.Close() 114 115 runner := db.NewMigrationRunner() 116 if runner == nil { 117 t.Error("Migration runner should not be nil") 118 } 119 }) 120 121 t.Run("closes database connection", func(t *testing.T) { 122 db, err := NewDatabase() 123 if err != nil { 124 t.Fatalf("NewDatabase failed: %v", err) 125 } 126 127 err = db.Close() 128 if err != nil { 129 t.Errorf("Close should not return error: %v", err) 130 } 131 132 err = db.Ping() 133 if err == nil { 134 t.Error("Database should be closed and ping should fail") 135 } 136 }) 137} 138 139func TestDatabaseErrorHandling(t *testing.T) { 140 t.Run("handles GetConfigDir error", func(t *testing.T) { 141 originalGetConfigDir := GetConfigDir 142 GetConfigDir = func() (string, error) { 143 return "", os.ErrPermission 144 } 145 defer func() { GetConfigDir = originalGetConfigDir }() 146 147 _, err := NewDatabase() 148 if err == nil { 149 t.Error("NewDatabase should fail when GetConfigDir fails") 150 } 151 }) 152 153 t.Run("handles invalid database path", func(t *testing.T) { 154 originalGetConfigDir := GetConfigDir 155 GetConfigDir = func() (string, error) { 156 return "/invalid/path/that/does/not/exist", nil 157 } 158 defer func() { GetConfigDir = originalGetConfigDir }() 159 160 _, err := NewDatabase() 161 if err == nil { 162 t.Error("NewDatabase should fail with invalid database path") 163 } 164 }) 165 166 t.Run("handles invalid database connection", func(t *testing.T) { 167 originalGetConfigDir := GetConfigDir 168 GetConfigDir = func() (string, error) { 169 return "/dev/null", nil 170 } 171 defer func() { GetConfigDir = originalGetConfigDir }() 172 173 _, err := NewDatabase() 174 if err == nil { 175 t.Error("NewDatabase should fail when database path is invalid") 176 } 177 }) 178 179 t.Run("handles migration failure during database creation", func(t *testing.T) { 180 tempDir, err := os.MkdirTemp("", "noteleaf-db-migration-fail-test-*") 181 if err != nil { 182 t.Fatalf("Failed to create temp directory: %v", err) 183 } 184 defer os.RemoveAll(tempDir) 185 186 originalGetConfigDir := GetConfigDir 187 GetConfigDir = func() (string, error) { 188 return tempDir, nil 189 } 190 defer func() { GetConfigDir = originalGetConfigDir }() 191 192 dbPath := filepath.Join(tempDir, "noteleaf.db") 193 194 // Create a corrupted database file that will cause issues 195 corruptedSQL := "this is not valid SQL and will cause failures" 196 err = os.WriteFile(dbPath, []byte(corruptedSQL), 0644) 197 if err != nil { 198 t.Fatalf("Failed to create corrupted database file: %v", err) 199 } 200 201 _, err = NewDatabase() 202 if err == nil { 203 t.Error("NewDatabase should fail when database file is corrupted") 204 } 205 }) 206 207 t.Run("handles database file permission error", func(t *testing.T) { 208 if runtime.GOOS == "windows" { 209 t.Skip("Permission test not reliable on Windows") 210 } 211 212 tempDir, err := os.MkdirTemp("", "noteleaf-db-perm-test-*") 213 if err != nil { 214 t.Fatalf("Failed to create temp directory: %v", err) 215 } 216 defer os.RemoveAll(tempDir) 217 218 originalGetConfigDir := GetConfigDir 219 GetConfigDir = func() (string, error) { 220 return tempDir, nil 221 } 222 defer func() { GetConfigDir = originalGetConfigDir }() 223 224 err = os.Chmod(tempDir, 0555) 225 if err != nil { 226 t.Fatalf("Failed to change directory permissions: %v", err) 227 } 228 defer os.Chmod(tempDir, 0755) 229 230 _, err = NewDatabase() 231 if err == nil { 232 t.Error("NewDatabase should fail when database directory is not writable") 233 } 234 }) 235} 236 237func TestDatabaseIntegration(t *testing.T) { 238 tempDir, err := os.MkdirTemp("", "noteleaf-db-integration-test-*") 239 if err != nil { 240 t.Fatalf("Failed to create temp directory: %v", err) 241 } 242 defer os.RemoveAll(tempDir) 243 244 originalGetConfigDir := GetConfigDir 245 GetConfigDir = func() (string, error) { 246 return tempDir, nil 247 } 248 defer func() { GetConfigDir = originalGetConfigDir }() 249 250 t.Run("multiple database instances use same file", func(t *testing.T) { 251 db1, err := NewDatabase() 252 if err != nil { 253 t.Fatalf("First NewDatabase failed: %v", err) 254 } 255 defer db1.Close() 256 257 db2, err := NewDatabase() 258 if err != nil { 259 t.Fatalf("Second NewDatabase failed: %v", err) 260 } 261 defer db2.Close() 262 263 if db1.GetPath() != db2.GetPath() { 264 t.Error("Both database instances should use the same file path") 265 } 266 }) 267 268 t.Run("database survives connection close and reopen", func(t *testing.T) { 269 db1, err := NewDatabase() 270 if err != nil { 271 t.Fatalf("NewDatabase failed: %v", err) 272 } 273 274 _, err = db1.Exec("CREATE TABLE IF NOT EXISTS test_table (id INTEGER PRIMARY KEY, name TEXT)") 275 if err != nil { 276 t.Fatalf("Failed to create test table: %v", err) 277 } 278 279 _, err = db1.Exec("INSERT INTO test_table (name) VALUES (?)", "test_value") 280 if err != nil { 281 t.Fatalf("Failed to insert test data: %v", err) 282 } 283 284 db1.Close() 285 286 db2, err := NewDatabase() 287 if err != nil { 288 t.Fatalf("Second NewDatabase failed: %v", err) 289 } 290 defer db2.Close() 291 292 var name string 293 err = db2.QueryRow("SELECT name FROM test_table WHERE id = 1").Scan(&name) 294 if err != nil { 295 t.Fatalf("Failed to query test data: %v", err) 296 } 297 298 if name != "test_value" { 299 t.Errorf("Expected 'test_value', got '%s'", name) 300 } 301 }) 302}