Skip to content
quarry Artifact [326ff86d04]
Login

Artifact [326ff86d04]

Artifact 326ff86d04e2c9c9ef4e360b2b98e7415dd5521614cd72ce8d9b6ab5986f6c80:


package index

import (
	"path/filepath"
	"slices"
	"testing"
)

func eventIndexes(t *testing.T, ix *Index) []string {
	t.Helper()
	rows, err := ix.db.Query(`SELECT name FROM sqlite_master
		WHERE type = 'index' AND tbl_name = 'event' AND sql IS NOT NULL ORDER BY name`)
	if err != nil {
		t.Fatal(err)
	}
	defer rows.Close()
	var out []string
	for rows.Next() {
		var n string
		if err := rows.Scan(&n); err != nil {
			t.Fatal(err)
		}
		out = append(out, n)
	}
	return out
}

// Every store in the fleet already has an index file with the old
// user index. Opening it must bring the new one in and take the old one
// out, without a reindex: an index changes no row, so it needs no
// schema bump.
func TestOpeningAnOldIndexGainsTheUserDateIndex(t *testing.T) {
	path := filepath.Join(t.TempDir(), "index.db")
	ix, err := Open(path)
	if err != nil {
		t.Fatal(err)
	}
	// The file as the fleet has it today.
	for _, stmt := range []string{
		`DROP INDEX IF EXISTS event_by_user_date`,
		`CREATE INDEX IF NOT EXISTS event_by_user ON event (user)`,
	} {
		if _, err := ix.w.Exec(stmt); err != nil {
			t.Fatal(err)
		}
	}
	ix.Close()

	ix, err = Open(path)
	if err != nil {
		t.Fatal(err)
	}
	defer ix.Close()
	if ix.stale {
		t.Error("the new index made the file stale: every store would reindex on deploy")
	}
	got := eventIndexes(t, ix)
	if !slices.Contains(got, "event_by_user_date") {
		t.Errorf("reopened index has no event_by_user_date: %v", got)
	}
	if slices.Contains(got, "event_by_user") {
		t.Errorf("the superseded event_by_user is still maintained on every write: %v", got)
	}
}

// A bulk rebuild keeps the event indexes the fleet pages read: with
// them dropped, every home page scanned a large mirror's whole event
// table while it ingested (the Linux kernel, 7 s a page).
func TestBulkRebuildKeepsTheEventIndexes(t *testing.T) {
	ix := openIndex(t)
	if err := ix.SuspendDerivedMaintenance(); err != nil {
		t.Fatal(err)
	}
	got := eventIndexes(t, ix)
	for _, want := range []string{"event_by_date", "event_by_user_date", "event_by_kind", "event_by_branch"} {
		if !slices.Contains(got, want) {
			t.Errorf("FAIL: %s dropped during a bulk rebuild: %v", want, got)
		}
	}
	if !ix.Bulk() {
		t.Error("FAIL: Bulk() false during a bulk rebuild")
	}
	if err := ix.ResumeDerivedMaintenance(); err != nil {
		t.Fatal(err)
	}
	if ix.Bulk() {
		t.Error("FAIL: Bulk() still true after the rebuild")
	}
}