219 lines
5.6 KiB
Go
219 lines
5.6 KiB
Go
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"])
|
||
}
|
||
}
|