mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-22 01:48:11 +00:00
refactor: remove IO route mapping, add HTTP API tests, system prompt update
This commit is contained in:
227
internal/memory/graph_test.go
Normal file
227
internal/memory/graph_test.go
Normal file
@ -0,0 +1,227 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func newTestGraph(t *testing.T) *GraphDB {
|
||||
t.Helper()
|
||||
f, err := os.CreateTemp("", "graph_test_*.db")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
os.Remove(f.Name())
|
||||
|
||||
g, err := NewGraphDB(f.Name())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
func TestNewGraphDB(t *testing.T) {
|
||||
g := newTestGraph(t)
|
||||
defer os.Remove(g.dbPath)
|
||||
defer g.Close()
|
||||
|
||||
stats, err := g.Introspect()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if stats["entity_count"].(int) != 0 {
|
||||
t.Errorf("expected 0 entities, got %d", stats["entity_count"])
|
||||
}
|
||||
if stats["relation_count"].(int) != 0 {
|
||||
t.Errorf("expected 0 relations, got %d", stats["relation_count"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitTriples(t *testing.T) {
|
||||
g := newTestGraph(t)
|
||||
defer os.Remove(g.dbPath)
|
||||
defer g.Close()
|
||||
|
||||
triples := []Triple{
|
||||
{Subject: "张三", Relation: "喜欢", Object: "编程"},
|
||||
{Subject: "张三", Relation: "居住", Object: "北京"},
|
||||
}
|
||||
|
||||
ec, rc, err := g.Commit(triples, "test_session", 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if ec != 4 {
|
||||
t.Errorf("expected 4 entity ops (张三×2, 编程, 北京), got %d", ec)
|
||||
}
|
||||
if rc != 2 {
|
||||
t.Errorf("expected 2 relations, got %d", rc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitEmptyTriples(t *testing.T) {
|
||||
g := newTestGraph(t)
|
||||
defer os.Remove(g.dbPath)
|
||||
defer g.Close()
|
||||
|
||||
ec, rc, err := g.Commit(nil, "test", 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if ec != 0 || rc != 0 {
|
||||
t.Errorf("expected 0,0 for nil triples, got %d,%d", ec, rc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecallByKeywords(t *testing.T) {
|
||||
g := newTestGraph(t)
|
||||
defer os.Remove(g.dbPath)
|
||||
defer g.Close()
|
||||
|
||||
g.Commit([]Triple{
|
||||
{Subject: "咖啡", Relation: "属于", Object: "饮品"},
|
||||
{Subject: "咖啡", Relation: "含有", Object: "咖啡因"},
|
||||
}, "session1", 0)
|
||||
|
||||
result, err := g.Recall([]string{"咖啡"}, nil, 1, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result.Entities) == 0 {
|
||||
t.Error("expected entities for keyword '咖啡'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecallBySeedEntity(t *testing.T) {
|
||||
g := newTestGraph(t)
|
||||
defer os.Remove(g.dbPath)
|
||||
defer g.Close()
|
||||
|
||||
g.Commit([]Triple{
|
||||
{Subject: "Go", Relation: "是", Object: "编程语言"},
|
||||
{Subject: "Go", Relation: "用于", Object: "后端开发"},
|
||||
}, "session2", 0)
|
||||
|
||||
result, err := g.Recall(nil, []string{"Go"}, 1, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result.Entities) == 0 {
|
||||
t.Error("expected entities for seed 'Go'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecallWithDepth(t *testing.T) {
|
||||
g := newTestGraph(t)
|
||||
defer os.Remove(g.dbPath)
|
||||
defer g.Close()
|
||||
|
||||
g.Commit([]Triple{
|
||||
{Subject: "甲", Relation: "认识", Object: "乙"},
|
||||
{Subject: "乙", Relation: "认识", Object: "丙"},
|
||||
}, "session3", 0)
|
||||
|
||||
result, err := g.Recall(nil, []string{"甲"}, 2, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(result.Relations) == 0 {
|
||||
t.Error("expected relations with depth search")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPurgeHard(t *testing.T) {
|
||||
g := newTestGraph(t)
|
||||
defer os.Remove(g.dbPath)
|
||||
defer g.Close()
|
||||
|
||||
g.Commit([]Triple{
|
||||
{Subject: "临时", Relation: "用于", Object: "测试"},
|
||||
}, "session4", 0)
|
||||
|
||||
n, err := g.Purge(map[string]string{"subject_contains": "临时"}, "hard")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != 1 {
|
||||
t.Errorf("expected 1 purged relation, got %d", n)
|
||||
}
|
||||
|
||||
stats, _ := g.Introspect()
|
||||
if stats["relation_count"].(int) != 0 {
|
||||
t.Errorf("expected 0 relations after purge, got %d", stats["relation_count"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestPurgeSoft(t *testing.T) {
|
||||
g := newTestGraph(t)
|
||||
defer os.Remove(g.dbPath)
|
||||
defer g.Close()
|
||||
|
||||
g.Commit([]Triple{
|
||||
{Subject: "可删除", Relation: "属于", Object: "测试"},
|
||||
}, "session5", 0)
|
||||
|
||||
n, err := g.Purge(map[string]string{"subject_contains": "可删除"}, "soft")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != 1 {
|
||||
t.Errorf("expected 1 soft-deleted relation, got %d", n)
|
||||
}
|
||||
|
||||
stats, _ := g.Introspect()
|
||||
if stats["relation_count"].(int) != 0 {
|
||||
t.Errorf("expected 0 active relations after soft-delete, got %d", stats["relation_count"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestArchive(t *testing.T) {
|
||||
g := newTestGraph(t)
|
||||
defer os.Remove(g.dbPath)
|
||||
defer g.Close()
|
||||
|
||||
// 直接插入一条旧记录
|
||||
g.db.Exec(`INSERT INTO entities (id, name, type) VALUES (1, '旧数据', 'Concept')`)
|
||||
g.db.Exec(`INSERT INTO relations (source_id, target_id, relation_type, created_at)
|
||||
VALUES (1, 1, '包含', datetime('now', '-1 day'))`)
|
||||
|
||||
n, err := g.Archive(0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != 1 {
|
||||
t.Errorf("expected 1 archived relation, got %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntrospectHotspots(t *testing.T) {
|
||||
g := newTestGraph(t)
|
||||
defer os.Remove(g.dbPath)
|
||||
defer g.Close()
|
||||
|
||||
g.Commit([]Triple{
|
||||
{Subject: "热门话题", Relation: "关于", Object: "AI"},
|
||||
{Subject: "热门话题", Relation: "关于", Object: "机器学习"},
|
||||
{Subject: "冷门话题", Relation: "关于", Object: "旧技术"},
|
||||
}, "session7", 0)
|
||||
|
||||
stats, _ := g.Introspect()
|
||||
hotspots := stats["memory_hotspots"].([]map[string]interface{})
|
||||
if len(hotspots) == 0 {
|
||||
t.Error("expected hotspots")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaceholders(t *testing.T) {
|
||||
if placeholders(0) != "NULL" {
|
||||
t.Errorf("expected NULL for n=0, got %s", placeholders(0))
|
||||
}
|
||||
if placeholders(1) != "?" {
|
||||
t.Errorf("expected '?' for n=1, got %s", placeholders(1))
|
||||
}
|
||||
if placeholders(3) != "?,?,?" {
|
||||
t.Errorf("expected '?,?,?' for n=3, got %s", placeholders(3))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user