Files
elowdb-go/tests/nonpartitioned/collection_test.go
2026-04-07 11:49:42 +06:00

219 lines
5.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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"])
}
}