package registry import ( "context" "path/filepath" "testing" ) // 6b-N1: a claim transaction whose ROLLBACK (or NORMAL restore) fails // discards its pooled connection. database/sql then opens a replacement, and // that replacement must carry Open's pragmas: busy_timeout 5000, WAL and // synchronous NORMAL, not SQLite's defaults (busy_timeout 0, synchronous // FULL). func TestClaimTransactionReplacementConnectionKeepsOpenPragmas(t *testing.T) { r, err := Open(filepath.Join(t.TempDir(), "registry.db")) if err != nil { t.Fatal(err) } defer r.Close() ctx := context.Background() // A connection-local marker: it survives only while the pool keeps the // same connection, so its loss proves the replacement happened. if _, err := r.sql.Exec("PRAGMA cache_size=-1234"); err != nil { t.Fatal(err) } tx, err := r.beginClaimTransaction(ctx, true) if err != nil { t.Fatal(err) } // End the transaction behind the wrapper so its ROLLBACK fails and the // connection is discarded with driver.ErrBadConn. if _, err := tx.ExecContext(ctx, "COMMIT"); err != nil { t.Fatal(err) } if err := tx.Rollback(); err == nil { t.Fatal("ROLLBACK after COMMIT succeeded; the discard path was not exercised") } var cache, busy, sync int var mode string if err := r.sql.QueryRow("PRAGMA cache_size").Scan(&cache); err != nil { t.Fatal(err) } if cache == -1234 { t.Fatal("the failed claim transaction's connection was kept; expected a replacement") } if err := r.sql.QueryRow("PRAGMA busy_timeout").Scan(&busy); err != nil { t.Fatal(err) } if err := r.sql.QueryRow("PRAGMA synchronous").Scan(&sync); err != nil { t.Fatal(err) } if err := r.sql.QueryRow("PRAGMA journal_mode").Scan(&mode); err != nil { t.Fatal(err) } if busy != 5000 || sync != 1 || mode != "wal" { t.Fatalf("replacement connection pragmas: busy_timeout=%d synchronous=%d journal_mode=%s, want 5000, 1 (NORMAL), wal", busy, sync, mode) } } // The first connection keeps exactly main's pragmas. func TestOpenPragmasUnchangedOnFirstConnection(t *testing.T) { r, err := Open(filepath.Join(t.TempDir(), "registry.db")) if err != nil { t.Fatal(err) } defer r.Close() var busy, sync int var mode string if err := r.sql.QueryRow("PRAGMA busy_timeout").Scan(&busy); err != nil { t.Fatal(err) } if err := r.sql.QueryRow("PRAGMA synchronous").Scan(&sync); err != nil { t.Fatal(err) } if err := r.sql.QueryRow("PRAGMA journal_mode").Scan(&mode); err != nil { t.Fatal(err) } if busy != 5000 || sync != 1 || mode != "wal" { t.Fatalf("first connection pragmas: busy_timeout=%d synchronous=%d journal_mode=%s", busy, sync, mode) } }