package store import ( "path/filepath" "testing" ) func testKey() []byte { k := make([]byte, 32) for i := range k { k[i] = byte(i) } return k } // openTemp opens a fresh store in a temp dir. func openTemp(t *testing.T) *Store { t.Helper() p := filepath.Join(t.TempDir(), "emcli.db") s, err := Open(p, testKey()) if err != nil { t.Fatalf("Open: %v", err) } t.Cleanup(func() { s.Close() }) return s } func TestOpenCreatesSchemaAndIsIdempotent(t *testing.T) { p := filepath.Join(t.TempDir(), "emcli.db") s, err := Open(p, testKey()) if err != nil { t.Fatalf("first Open: %v", err) } v, err := s.GetSetting("schema_version") if err != nil || v != "1" { t.Fatalf("schema_version: %q err=%v", v, err) } s.Close() // Re-open: must not error or duplicate. s2, err := Open(p, testKey()) if err != nil { t.Fatalf("second Open: %v", err) } defer s2.Close() if v, _ := s2.GetSetting("schema_version"); v != "1" { t.Fatalf("schema_version after reopen: %q", v) } } func TestSettingsRoundTrip(t *testing.T) { s := openTemp(t) if err := s.SetSetting("audit_retention_days", "30"); err != nil { t.Fatalf("SetSetting: %v", err) } got, err := s.GetSetting("audit_retention_days") if err != nil || got != "30" { t.Fatalf("got %q err=%v", got, err) } // Upsert overwrites. _ = s.SetSetting("audit_retention_days", "7") if got, _ := s.GetSetting("audit_retention_days"); got != "7" { t.Fatalf("upsert failed: %q", got) } } func TestForeignKeyCascade(t *testing.T) { s := openTemp(t) // Insert an account directly via raw SQL. _, err := s.db.Exec(` INSERT INTO accounts(name, mode, imap_host, imap_port, imap_security, auth_type, username) VALUES('test_account', 'RO', 'imap.example.com', 993, 'tls', 'password', 'user@example.com') `) if err != nil { t.Fatalf("insert account: %v", err) } // Get the inserted account ID. var accountID int64 err = s.db.QueryRow("SELECT id FROM accounts WHERE name = 'test_account'").Scan(&accountID) if err != nil { t.Fatalf("query account id: %v", err) } // Insert a whitelist_in row referencing the account. _, err = s.db.Exec("INSERT INTO whitelist_in(account_id, address) VALUES(?, 'test@example.com')", accountID) if err != nil { t.Fatalf("insert whitelist_in: %v", err) } // Verify the whitelist_in row exists. var count int err = s.db.QueryRow("SELECT COUNT(*) FROM whitelist_in WHERE account_id = ?", accountID).Scan(&count) if err != nil || count != 1 { t.Fatalf("whitelist_in row not found: count=%d err=%v", count, err) } // Delete the account (should cascade and delete whitelist_in row). _, err = s.db.Exec("DELETE FROM accounts WHERE name = 'test_account'") if err != nil { t.Fatalf("delete account: %v", err) } // Verify the whitelist_in row was cascade-deleted. err = s.db.QueryRow("SELECT COUNT(*) FROM whitelist_in WHERE account_id = ?", accountID).Scan(&count) if err != nil || count != 0 { t.Fatalf("whitelist_in row not cascade-deleted: count=%d err=%v", count, err) } }