278 lines
7.4 KiB
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")
|
|
}
|
|
}
|