featurebase/holder_internal_test.go
Seebs 964e7d86c8 kill everything that tries to pass nil tx to field/view things
The "field/view will just synthesize a tx" behavior is awful and
also hides a number of fundamental flaws. We distinguish between
"we really do mean to work on a single shard here" and "we intend
to work on the whole field or view", and the latter now take
Qcx instead of Tx.

This eliminates a lot of very weird cases where we checked for
nil Tx and synthesized them, and also gets us away from
field and view taking Tx parameters when no possible Tx
can be constructed which is valid, because Tx are inherently
shard-specific at this time.
2022-09-30 11:10:47 -07:00

118 lines
2.8 KiB
Go

// Copyright 2022 Molecula Corp. (DBA FeatureBase).
// SPDX-License-Identifier: Apache-2.0
package pilosa
import (
"testing"
"github.com/featurebasedb/featurebase/v3/disco"
"github.com/featurebasedb/featurebase/v3/testhook"
)
// mustHolderConfig sets up a default holder config for tests.
func mustHolderConfig() *HolderConfig {
cfg := DefaultHolderConfig()
cfg.StorageConfig.FsyncEnabled = false
cfg.RBFConfig.FsyncEnabled = false
cfg.Schemator = disco.NewInMemSchemator()
cfg.Sharder = disco.InMemSharder
return cfg
}
func setupTest(t *testing.T, h *Holder, rowCol []rowCols, indexName string) (*Index, *Field) {
idx, err := h.CreateIndexIfNotExists(indexName, IndexOptions{TrackExistence: true})
if err != nil {
t.Fatalf("failed to create index %v: %v", indexName, err)
}
f, err := idx.CreateFieldIfNotExists("f", OptFieldTypeDefault())
if err != nil {
t.Fatalf("failed to create field in index %v: %v", indexName, err)
}
existencefield := idx.existenceFld
qcx := idx.Txf().NewWritableQcx()
defer qcx.Abort()
for _, r := range rowCol {
_, err = f.SetBit(qcx, r.row, r.col, nil)
if err != nil {
t.Fatalf("failed to set bit in index %v: %v", indexName, err)
}
_, err = existencefield.SetBit(qcx, r.row, r.col, nil)
if err != nil {
t.Fatalf("failed to set bit in index %v: %v", indexName, err)
}
}
if err = qcx.Finish(); err != nil {
t.Fatalf("failed to commit tx for index %v: %v", indexName, err)
}
shardsFound := idx.AvailableShards(includeRemote).Slice()
if len(shardsFound) != 3 {
t.Fatalf("expected 3 shards for index %v, got %v", indexName, len(shardsFound))
}
return idx, f
}
type rowCols struct {
row uint64
col uint64
}
func TestHolder_ProcessDeleteInflight(t *testing.T) {
path, _ := testhook.TempDir(t, "delete-inflight")
h := NewHolder(path, mustHolderConfig())
defer h.Close()
err := h.Open()
if err != nil {
t.Fatalf("failed to open holder: %v", err)
}
rowCol := []rowCols{
{1, 1},
{1, 2},
{10, ShardWidth + 1},
{1, ShardWidth * 2},
}
idx1, f1 := setupTest(t, h, rowCol, "idxdelete1")
idx2, f2 := setupTest(t, h, rowCol, "idxdelete2")
err = h.processDeleteInflight()
if err != nil {
t.Fatalf("failed to delete: %v", err)
}
tests := []struct {
idx *Index
f *Field
}{
{idx1, f1},
{idx2, f2},
}
for _, test := range tests {
func() {
idx, f := test.idx, test.f
qcx := idx.Txf().NewQcx()
defer qcx.Abort()
for _, r := range rowCol {
row, err := f.Row(qcx, r.row)
if err != nil {
t.Fatalf("failed to get row: %v", err)
}
existenceRow, err := idx.existenceFld.Row(qcx, r.row)
if err != nil {
t.Fatalf("failed to get row: %v", err)
}
if len(row.Columns()) != 0 || len(existenceRow.Columns()) != 0 {
t.Fatalf("expected columns for fields to be empty after delete")
}
}
}()
}
}