package index
import (
"path/filepath"
"strings"
"testing"
)
// A bulk rebuild recreates its dropped indexes, and the writer that
// does it keeps temp b-trees on disk while readers keep theirs in
// memory: on netbsd-src the in-memory sort ran SQLite out of memory and
// took the forge down (#357).
func TestResumeRebuildsIndexesWithTheSortOnDisk(t *testing.T) {
ix := openIndex(t)
if err := ix.SuspendDerivedMaintenance(); err != nil {
t.Fatal(err)
}
if err := ix.ResumeDerivedMaintenance(); err != nil {
t.Fatal(err)
}
for _, name := range bulkDroppable {
var n int
if err := ix.w.QueryRow(`SELECT count(*) FROM sqlite_master WHERE type = 'index' AND name = ?`, name).Scan(&n); err != nil {
t.Fatal(err)
}
if n != 1 {
t.Errorf("FAIL: index %s not rebuilt", name)
}
}
var w, r int
if err := ix.w.QueryRow(`PRAGMA temp_store`).Scan(&w); err != nil {
t.Fatal(err)
}
if err := ix.db.QueryRow(`PRAGMA temp_store`).Scan(&r); err != nil {
t.Fatal(err)
}
if w != 1 || r != 2 {
t.Errorf("FAIL: temp_store writer %d reader %d, want 1 (file) and 2 (memory)", w, r)
}
}
// Every index connection may use connMaxMemory, not the driver's 256MB.
func TestIndexConnectionsCarryTheMemoryCeiling(t *testing.T) {
ix := openIndex(t)
for _, q := range []struct {
name string
lim func() (int64, error)
}{
{"writer", func() (n int64, err error) { err = ix.w.QueryRow(`PRAGMA soft_heap_limit`).Scan(&n); return }},
{"reader", func() (n int64, err error) { err = ix.db.QueryRow(`PRAGMA soft_heap_limit`).Scan(&n); return }},
} {
n, err := q.lim()
if err != nil {
t.Fatal(err)
}
if n < 512<<20 {
t.Errorf("FAIL: %s soft heap limit %d, want near %d", q.name, n, connMaxMemory)
}
}
}
// An index that runs SQLite out of memory while opening is an error for
// that store, not a panic: at startup every store opens at once, and a
// panic there ended the forge on every restart (#357).
func TestAnIndexThatRunsOutOfMemoryFailsToOpen(t *testing.T) {
old := connMaxMemory
connMaxMemory = 1 << 16 // one wasm page: far too little to apply the schema
defer func() { connMaxMemory = old }()
ix, err := Open(filepath.Join(t.TempDir(), "index.db"))
if err == nil {
ix.Close()
t.Fatal("FAIL: an index with no memory to work in opened")
}
if !strings.Contains(err.Error(), "out of memory") {
t.Errorf("FAIL: want the out-of-memory error, got %v", err)
}
}