finish index feature
This commit is contained in:
218
tests/nonpartitioned/collection_test.go
Normal file
218
tests/nonpartitioned/collection_test.go
Normal file
@@ -0,0 +1,218 @@
|
||||
package nonpartitioned
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"linedb/pkg/linedb"
|
||||
)
|
||||
|
||||
const dbDir = "./data/nonpartitioned"
|
||||
|
||||
func setupDB(t *testing.T) *linedb.LineDb {
|
||||
t.Helper()
|
||||
dir := filepath.Join(dbDir, t.Name())
|
||||
_ = os.RemoveAll(dir)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
t.Fatalf("mkdir: %v", err)
|
||||
}
|
||||
|
||||
initOptions := &linedb.LineDbInitOptions{
|
||||
DBFolder: dir,
|
||||
Collections: []linedb.JSONLFileOptions{
|
||||
{
|
||||
CollectionName: "users",
|
||||
AllocSize: 512,
|
||||
IndexedFields: []string{"id", "email", "name"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
db := linedb.NewLineDb(&linedb.LineDbOptions{
|
||||
IndexStore: linedb.NewInMemoryIndexStore(),
|
||||
})
|
||||
if err := db.Init(true, initOptions); err != nil {
|
||||
t.Fatalf("Init: %v", err)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func TestNonPartitioned_InsertRead(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer db.Close()
|
||||
opts := linedb.LineDbAdapterOptions{}
|
||||
|
||||
// Insert
|
||||
users := []any{
|
||||
map[string]any{"id": 1, "email": "a@test.com", "name": "Alice"},
|
||||
map[string]any{"id": 2, "email": "b@test.com", "name": "Bob"},
|
||||
map[string]any{"id": 3, "email": "c@test.com", "name": "Charlie"},
|
||||
}
|
||||
if err := db.Insert(users, "users", opts); err != nil {
|
||||
t.Fatalf("Insert: %v", err)
|
||||
}
|
||||
|
||||
// Read
|
||||
all, err := db.Read("users", opts)
|
||||
if err != nil {
|
||||
t.Fatalf("Read: %v", err)
|
||||
}
|
||||
if len(all) != 3 {
|
||||
t.Errorf("Read: expected 3, got %d", len(all))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonPartitioned_ReadByFilter_Indexed(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer db.Close()
|
||||
opts := linedb.LineDbAdapterOptions{}
|
||||
|
||||
if err := db.Insert([]any{
|
||||
map[string]any{"id": 1, "email": "x@test.com", "name": "X"},
|
||||
map[string]any{"id": 2, "email": "y@test.com", "name": "Y"},
|
||||
}, "users", opts); err != nil {
|
||||
t.Fatalf("Insert: %v", err)
|
||||
}
|
||||
|
||||
// Поиск по индексированному полю
|
||||
found, err := db.ReadByFilter(map[string]any{"email": "y@test.com"}, "users", opts)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadByFilter: %v", err)
|
||||
}
|
||||
if len(found) != 1 {
|
||||
t.Fatalf("ReadByFilter email: expected 1, got %d", len(found))
|
||||
}
|
||||
if m, ok := found[0].(map[string]any); !ok || m["name"] != "Y" {
|
||||
t.Errorf("ReadByFilter: wrong record %v", found[0])
|
||||
}
|
||||
|
||||
foundByID, _ := db.ReadByFilter(map[string]any{"id": 1}, "users", opts)
|
||||
if len(foundByID) != 1 {
|
||||
t.Fatalf("ReadByFilter id: expected 1, got %d", len(foundByID))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonPartitioned_Update(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer db.Close()
|
||||
opts := linedb.LineDbAdapterOptions{}
|
||||
|
||||
if err := db.Insert(map[string]any{"id": 1, "email": "old@test.com", "name": "Old"}, "users", opts); err != nil {
|
||||
t.Fatalf("Insert: %v", err)
|
||||
}
|
||||
|
||||
updated, err := db.Update(
|
||||
map[string]any{"email": "new@test.com", "name": "New"},
|
||||
"users",
|
||||
map[string]any{"id": 1},
|
||||
opts,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Update: %v", err)
|
||||
}
|
||||
if len(updated) != 1 {
|
||||
t.Fatalf("Update: expected 1, got %d", len(updated))
|
||||
}
|
||||
|
||||
found, _ := db.ReadByFilter(map[string]any{"email": "new@test.com"}, "users", opts)
|
||||
if len(found) != 1 {
|
||||
t.Fatalf("After update ReadByFilter: expected 1, got %d", len(found))
|
||||
}
|
||||
oldFound, _ := db.ReadByFilter(map[string]any{"email": "old@test.com"}, "users", opts)
|
||||
if len(oldFound) != 0 {
|
||||
t.Errorf("Old email should not exist after update, got %d", len(oldFound))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonPartitioned_Delete(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer db.Close()
|
||||
opts := linedb.LineDbAdapterOptions{}
|
||||
|
||||
if err := db.Insert([]any{
|
||||
map[string]any{"id": 1, "email": "del@test.com", "name": "Del"},
|
||||
map[string]any{"id": 2, "email": "keep@test.com", "name": "Keep"},
|
||||
}, "users", opts); err != nil {
|
||||
t.Fatalf("Insert: %v", err)
|
||||
}
|
||||
|
||||
deleted, err := db.Delete(map[string]any{"email": "del@test.com"}, "users", opts)
|
||||
if err != nil {
|
||||
t.Fatalf("Delete: %v", err)
|
||||
}
|
||||
if len(deleted) != 1 {
|
||||
t.Fatalf("Delete: expected 1, got %d", len(deleted))
|
||||
}
|
||||
|
||||
all, _ := db.Read("users", opts)
|
||||
if len(all) != 1 {
|
||||
t.Fatalf("After delete expected 1, got %d", len(all))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonPartitioned_WriteWithDoIndexing(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer db.Close()
|
||||
opts := linedb.LineDbAdapterOptions{}
|
||||
|
||||
// Write с DoIndexing
|
||||
if err := db.Write(
|
||||
[]any{map[string]any{"id": 10, "email": "write@test.com", "name": "Written"}},
|
||||
"users",
|
||||
linedb.LineDbAdapterOptions{DoIndexing: true},
|
||||
); err != nil {
|
||||
t.Fatalf("Write: %v", err)
|
||||
}
|
||||
|
||||
found, _ := db.ReadByFilter(map[string]any{"email": "write@test.com"}, "users", opts)
|
||||
if len(found) != 1 {
|
||||
t.Fatalf("Write+DoIndexing: expected 1, got %d", len(found))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNonPartitioned_FullCycle(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer db.Close()
|
||||
opts := linedb.LineDbAdapterOptions{}
|
||||
|
||||
// 1. Insert
|
||||
if err := db.Insert([]any{
|
||||
map[string]any{"id": 1, "email": "one@test.com", "name": "One"},
|
||||
map[string]any{"id": 2, "email": "two@test.com", "name": "Two"},
|
||||
map[string]any{"id": 3, "email": "three@test.com", "name": "Three"},
|
||||
}, "users", opts); err != nil {
|
||||
t.Fatalf("Insert: %v", err)
|
||||
}
|
||||
|
||||
// 2. Read all
|
||||
all, _ := db.Read("users", opts)
|
||||
if len(all) != 3 {
|
||||
t.Fatalf("Read: expected 3, got %d", len(all))
|
||||
}
|
||||
|
||||
// 3. Update
|
||||
_, err := db.Update(map[string]any{"name": "TwoUpdated"}, "users", map[string]any{"id": 2}, opts)
|
||||
if err != nil {
|
||||
t.Fatalf("Update: %v", err)
|
||||
}
|
||||
|
||||
// 4. Delete
|
||||
_, err = db.Delete(map[string]any{"id": 3}, "users", opts)
|
||||
if err != nil {
|
||||
t.Fatalf("Delete: %v", err)
|
||||
}
|
||||
|
||||
// 5. Verify
|
||||
all2, _ := db.Read("users", opts)
|
||||
if len(all2) != 2 {
|
||||
t.Fatalf("After cycle expected 2, got %d", len(all2))
|
||||
}
|
||||
found, _ := db.ReadByFilter(map[string]any{"email": "two@test.com"}, "users", opts)
|
||||
if len(found) != 1 {
|
||||
t.Fatalf("ReadByFilter two: expected 1, got %d", len(found))
|
||||
}
|
||||
if m, ok := found[0].(map[string]any); ok && m["name"] != "TwoUpdated" {
|
||||
t.Errorf("Update did not apply: name=%v", m["name"])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user