155 lines
4.1 KiB
Go
155 lines
4.1 KiB
Go
|
package kv_test
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/influxdata/influxdb/kv"
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
"github.com/stretchr/testify/require"
|
||
|
)
|
||
|
|
||
|
func TestIndexStore(t *testing.T) {
|
||
|
newStoreBase := func(resource string, bktName []byte, encKeyFn, encBodyFn kv.EncodeEntFn, decFn kv.DecodeBucketEntFn, decToEntFn kv.DecodedValToEntFn) *kv.StoreBase {
|
||
|
return kv.NewStoreBase(resource, bktName, encKeyFn, encBodyFn, decFn, decToEntFn)
|
||
|
}
|
||
|
|
||
|
newFooIndexStore := func(t *testing.T, bktSuffix string) (*kv.IndexStore, kv.Store) {
|
||
|
inmemStore, _, _ := NewTestInmemStore(t)
|
||
|
|
||
|
const resource = "foo"
|
||
|
|
||
|
indexStore := &kv.IndexStore{
|
||
|
Resource: resource,
|
||
|
EntStore: newStoreBase(resource, []byte("foo_ent_"+bktSuffix), kv.EncIDKey, kv.EncBodyJSON, decJSONFooFn, decFooEntFn),
|
||
|
IndexStore: kv.NewOrgNameKeyStore(resource, []byte("foo_idx_"+bktSuffix), false),
|
||
|
}
|
||
|
|
||
|
return indexStore, inmemStore
|
||
|
}
|
||
|
|
||
|
t.Run("Put", func(t *testing.T) {
|
||
|
indexStore, inmem := newFooIndexStore(t, "put")
|
||
|
|
||
|
expected := testPutBase(t, inmem, indexStore, indexStore.EntStore.BktName)
|
||
|
|
||
|
key, _, err := indexStore.IndexStore.EncodeEntKeyFn(kv.Entity{
|
||
|
OrgID: expected.OrgID,
|
||
|
Name: expected.Name,
|
||
|
})
|
||
|
require.NoError(t, err)
|
||
|
|
||
|
rawIndex := getEntRaw(t, inmem, indexStore.IndexStore.BktName, key)
|
||
|
assert.Equal(t, encodeID(t, expected.ID), rawIndex)
|
||
|
})
|
||
|
|
||
|
t.Run("DeleteEnt", func(t *testing.T) {
|
||
|
indexStore, inmem := newFooIndexStore(t, "delete_ent")
|
||
|
|
||
|
expected := testDeleteEntBase(t, inmem, indexStore)
|
||
|
|
||
|
err := inmem.View(context.TODO(), func(tx kv.Tx) error {
|
||
|
_, err := indexStore.IndexStore.FindEnt(context.TODO(), tx, kv.Entity{
|
||
|
OrgID: expected.OrgID,
|
||
|
Name: expected.Name,
|
||
|
})
|
||
|
return err
|
||
|
})
|
||
|
isNotFoundErr(t, err)
|
||
|
})
|
||
|
|
||
|
t.Run("Delete", func(t *testing.T) {
|
||
|
fn := func(t *testing.T, suffix string) (storeBase, kv.Store) {
|
||
|
return newFooIndexStore(t, suffix)
|
||
|
}
|
||
|
|
||
|
testDeleteBase(t, fn, func(t *testing.T, kvStore kv.Store, base storeBase, foosLeft []foo) {
|
||
|
var expectedIndexIDs []interface{}
|
||
|
for _, ent := range foosLeft {
|
||
|
expectedIndexIDs = append(expectedIndexIDs, ent.ID)
|
||
|
}
|
||
|
|
||
|
indexStore, ok := base.(*kv.IndexStore)
|
||
|
require.True(t, ok)
|
||
|
|
||
|
// next to verify they are not within the index store
|
||
|
var actualIDs []interface{}
|
||
|
view(t, kvStore, func(tx kv.Tx) error {
|
||
|
return indexStore.IndexStore.Find(context.TODO(), tx, kv.FindOpts{
|
||
|
CaptureFn: func(key []byte, decodedVal interface{}) error {
|
||
|
actualIDs = append(actualIDs, decodedVal)
|
||
|
return nil
|
||
|
},
|
||
|
})
|
||
|
})
|
||
|
|
||
|
assert.Equal(t, expectedIndexIDs, actualIDs)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
t.Run("FindEnt", func(t *testing.T) {
|
||
|
t.Run("by ID", func(t *testing.T) {
|
||
|
base, inmemStore := newFooIndexStore(t, "find_ent")
|
||
|
testFindEnt(t, inmemStore, base)
|
||
|
})
|
||
|
|
||
|
t.Run("find by name", func(t *testing.T) {
|
||
|
base, kvStore := newFooIndexStore(t, "find_ent")
|
||
|
expected := newFooEnt(1, 9000, "foo_1")
|
||
|
seedEnts(t, kvStore, base, expected)
|
||
|
|
||
|
var actual interface{}
|
||
|
view(t, kvStore, func(tx kv.Tx) error {
|
||
|
f, err := base.FindEnt(context.TODO(), tx, kv.Entity{
|
||
|
OrgID: expected.OrgID,
|
||
|
Name: expected.Name,
|
||
|
})
|
||
|
actual = f
|
||
|
return err
|
||
|
})
|
||
|
|
||
|
assert.Equal(t, expected.Body, actual)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
t.Run("Find", func(t *testing.T) {
|
||
|
t.Run("base", func(t *testing.T) {
|
||
|
fn := func(t *testing.T, suffix string) (storeBase, kv.Store) {
|
||
|
return newFooIndexStore(t, suffix)
|
||
|
}
|
||
|
|
||
|
testFind(t, fn)
|
||
|
})
|
||
|
|
||
|
t.Run("lookup via orgID", func(t *testing.T) {
|
||
|
base, kvStore := newFooIndexStore(t, "find_index_search")
|
||
|
|
||
|
expectedEnts := []kv.Entity{
|
||
|
newFooEnt(1, 9000, "foo_0"),
|
||
|
newFooEnt(2, 9001, "foo_1"),
|
||
|
newFooEnt(3, 9003, "foo_2"),
|
||
|
newFooEnt(4, 9003, "foo_3"),
|
||
|
}
|
||
|
|
||
|
seedEnts(t, kvStore, base, expectedEnts...)
|
||
|
|
||
|
var actuals []interface{}
|
||
|
view(t, kvStore, func(tx kv.Tx) error {
|
||
|
return base.Find(context.TODO(), tx, kv.FindOpts{
|
||
|
Prefix: encodeID(t, 9003),
|
||
|
CaptureFn: func(key []byte, decodedVal interface{}) error {
|
||
|
actuals = append(actuals, decodedVal)
|
||
|
return nil
|
||
|
},
|
||
|
})
|
||
|
})
|
||
|
|
||
|
expected := []interface{}{
|
||
|
expectedEnts[2].Body,
|
||
|
expectedEnts[3].Body,
|
||
|
}
|
||
|
assert.Equal(t, expected, actuals)
|
||
|
})
|
||
|
})
|
||
|
}
|