gomog/internal/engine/memory_store_batch2_test.go

278 lines
7.4 KiB
Go

package engine
import (
"testing"
"time"
"git.kingecg.top/kingecg/gomog/pkg/types"
)
// createTestCollection 创建测试集合的辅助函数
func createTestCollection(store *MemoryStore, name string, documents map[string]types.Document) {
store.collections[name] = &Collection{
name: name,
documents: documents,
}
}
// TestMemoryStoreUpdateWithUpsert 测试 MemoryStore 的 upsert 功能
func TestMemoryStoreUpdateWithUpsert(t *testing.T) {
store := NewMemoryStore(nil)
// 创建测试集合
collection := "test.upsert_collection"
createTestCollection(store, collection, map[string]types.Document{})
tests := []struct {
name string
filter types.Filter
update types.Update
upsert bool
expectedMatch int
expectedMod int
expectUpsert bool
checkField string
expectedValue interface{}
}{
{
name: "upsert creates new document",
filter: types.Filter{"_id": "new_doc"},
update: types.Update{
Set: map[string]interface{}{
"status": "active",
},
SetOnInsert: map[string]interface{}{
"createdAt": "2024-01-01T00:00:00Z",
},
},
upsert: true,
expectedMatch: 1,
expectedMod: 1,
expectUpsert: true,
checkField: "createdAt",
expectedValue: "2024-01-01T00:00:00Z",
},
{
name: "update existing document without setOnInsert",
filter: types.Filter{"name": "Alice"},
update: types.Update{
Set: map[string]interface{}{
"status": "updated",
},
SetOnInsert: map[string]interface{}{
"shouldNotAppear": true,
},
},
upsert: false,
expectedMatch: 0, // No matching document initially
expectedMod: 0,
expectUpsert: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Clear collection before each test
createTestCollection(store, collection, map[string]types.Document{})
matched, modified, upsertedIDs, err := store.Update(collection, tt.filter, tt.update, tt.upsert, nil)
if err != nil {
t.Fatalf("Update() error = %v", err)
}
if matched != tt.expectedMatch {
t.Errorf("matched = %d, want %d", matched, tt.expectedMatch)
}
if modified != tt.expectedMod {
t.Errorf("modified = %d, want %d", modified, tt.expectedMod)
}
if tt.expectUpsert && len(upsertedIDs) == 0 {
t.Error("Expected upsert ID but got none")
}
if tt.checkField != "" {
// Find the created/updated document
found := false
for _, d := range store.collections[collection].documents {
if val, ok := d.Data[tt.checkField]; ok {
if compareEq(val, tt.expectedValue) {
found = true
break
}
}
}
if tt.expectUpsert && !found {
t.Errorf("Document with %s = %v not found", tt.checkField, tt.expectedValue)
}
}
})
}
}
// TestMemoryStoreUpdateWithArrayFilters 测试 MemoryStore 的 arrayFilters 功能
func TestMemoryStoreUpdateWithArrayFilters(t *testing.T) {
store := NewMemoryStore(nil)
collection := "test.array_filters_collection"
createTestCollection(store, collection, map[string]types.Document{
"doc1": {
ID: "doc1",
Data: map[string]interface{}{
"name": "Product A",
"scores": []interface{}{
map[string]interface{}{"subject": "math", "score": float64(85)},
map[string]interface{}{"subject": "english", "score": float64(92)},
map[string]interface{}{"subject": "science", "score": float64(78)},
},
},
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
})
arrayFilters := []types.Filter{
{
"identifier": "elem",
"score": map[string]interface{}{"$gte": float64(90)},
},
}
update := types.Update{
Set: map[string]interface{}{
"scores.$[elem].grade": "A",
},
}
matched, modified, _, err := store.Update(collection, types.Filter{"name": "Product A"}, update, false, arrayFilters)
if err != nil {
t.Fatalf("Update() error = %v", err)
}
if matched != 1 {
t.Errorf("matched = %d, want 1", matched)
}
if modified != 1 {
t.Errorf("modified = %d, want 1", modified)
}
// Verify the update was applied correctly
doc := store.collections[collection].documents["doc1"]
scores, ok := doc.Data["scores"].([]interface{})
if !ok {
t.Fatal("scores is not an array")
}
// Check that english score has grade "A"
foundGradeA := false
for _, score := range scores {
scoreMap, ok := score.(map[string]interface{})
if !ok {
continue
}
if subject, ok := scoreMap["subject"].(string); ok && subject == "english" {
if grade, ok := scoreMap["grade"].(string); ok && grade == "A" {
foundGradeA = true
break
}
}
}
if !foundGradeA {
t.Error("Expected to find grade A for english score >= 90")
}
}
// TestMemoryStoreFindAll 测试获取所有文档
func TestMemoryStoreGetAllDocuments(t *testing.T) {
store := NewMemoryStore(nil)
collection := "test.get_all_collection"
createTestCollection(store, collection, map[string]types.Document{
"doc1": {ID: "doc1", Data: map[string]interface{}{"name": "Alice"}, CreatedAt: time.Now(), UpdatedAt: time.Now()},
"doc2": {ID: "doc2", Data: map[string]interface{}{"name": "Bob"}, CreatedAt: time.Now(), UpdatedAt: time.Now()},
"doc3": {ID: "doc3", Data: map[string]interface{}{"name": "Charlie"}, CreatedAt: time.Now(), UpdatedAt: time.Now()},
})
docs, err := store.GetAllDocuments(collection)
if err != nil {
t.Fatalf("GetAllDocuments() error = %v", err)
}
if len(docs) != 3 {
t.Errorf("GetAllDocuments() returned %d documents, want 3", len(docs))
}
}
// TestMemoryStoreCollectionNotFound 测试集合不存在的情况
func TestMemoryStoreCollectionNotFound(t *testing.T) {
store := NewMemoryStore(nil)
_, err := store.GetCollection("nonexistent.collection")
if err == nil {
t.Error("Expected error for non-existent collection")
}
}
// TestMemoryStoreInsert 测试插入功能
func TestMemoryStoreInsert(t *testing.T) {
store := NewMemoryStore(nil)
collection := "test.insert_collection"
createTestCollection(store, collection, make(map[string]types.Document))
doc := types.Document{
ID: "test_id",
Data: map[string]interface{}{"name": "Test Document"},
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
err := store.Insert(collection, doc)
if err != nil {
t.Fatalf("Insert() error = %v", err)
}
// Verify insertion
storedDoc, exists := store.collections[collection].documents["test_id"]
if !exists {
t.Error("Document was not inserted")
}
if storedDoc.Data["name"] != "Test Document" {
t.Errorf("Document data mismatch: got %v", storedDoc.Data)
}
}
// TestMemoryStoreDelete 测试删除功能
func TestMemoryStoreDelete(t *testing.T) {
store := NewMemoryStore(nil)
collection := "test.delete_collection"
createTestCollection(store, collection, map[string]types.Document{
"doc1": {ID: "doc1", Data: map[string]interface{}{"status": "active"}, CreatedAt: time.Now(), UpdatedAt: time.Now()},
"doc2": {ID: "doc2", Data: map[string]interface{}{"status": "inactive"}, CreatedAt: time.Now(), UpdatedAt: time.Now()},
})
deleted, err := store.Delete(collection, types.Filter{"status": "inactive"})
if err != nil {
t.Fatalf("Delete() error = %v", err)
}
if deleted != 1 {
t.Errorf("Delete() deleted %d documents, want 1", deleted)
}
// Verify only doc1 remains
if _, exists := store.collections[collection].documents["doc2"]; exists {
t.Error("Document should have been deleted")
}
if _, exists := store.collections[collection].documents["doc1"]; !exists {
t.Error("Document should still exist")
}
}