mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-14 04:36:52 +08:00
Fix compilation template config validation for JSONMap; merge template groups into agents list ordered by category/name; install nav service in ingestor; write readable nav cluster/doc names and emit nav_doc leaves; port tree-to-graph projection and full document structure graph endpoint parity.
108 lines
3.9 KiB
Go
108 lines
3.9 KiB
Go
package service
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
// TestProjectEntity_FromPayload verifies projectEntity maps the tree-node
|
|
// payload shape to the graph-node shape (mirroring _struct_graph_entity).
|
|
func TestProjectEntity_FromPayload(t *testing.T) {
|
|
row := map[string]interface{}{
|
|
"content_with_weight": `{"name":"NVIDIA","type":"tree_node","description":"chip maker","source_chunk_ids":["c1","c2"]}`,
|
|
"source_chunk_ids": []string{"c1"},
|
|
"mention_count_int": 3,
|
|
}
|
|
n := projectEntity(row)
|
|
if n == nil {
|
|
t.Fatal("projectEntity returned nil")
|
|
}
|
|
if n["name"] != "NVIDIA" || n["type"] != "tree_node" {
|
|
t.Errorf("name/type = %v/%v, want NVIDIA/tree_node", n["name"], n["type"])
|
|
}
|
|
if n["mention_count"] != 3 {
|
|
t.Errorf("mention_count = %v, want 3", n["mention_count"])
|
|
}
|
|
chunks, _ := n["source_chunk_ids"].([]string)
|
|
if !reflect.DeepEqual(chunks, []string{"c1", "c2"}) {
|
|
t.Errorf("source_chunk_ids = %v, want [c1 c2]", chunks)
|
|
}
|
|
}
|
|
|
|
// TestProjectEntity_RejectsInvalidName verifies sentinel/empty names are dropped.
|
|
func TestProjectEntity_RejectsInvalidName(t *testing.T) {
|
|
for _, payload := range []string{`{"name":""}`, `{"name":"unknown"}`} {
|
|
if n := projectEntity(map[string]interface{}{"content_with_weight": payload}); n != nil {
|
|
t.Errorf("expected nil for payload %s, got %v", payload, n)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestProjectRelation_FromPayload verifies the relation projection.
|
|
func TestProjectRelation_FromPayload(t *testing.T) {
|
|
row := map[string]interface{}{"content_with_weight": `{"from":"NVIDIA","to":"GPU","type":"child"}`}
|
|
r := projectRelation(row)
|
|
if r == nil {
|
|
t.Fatal("projectRelation returned nil")
|
|
}
|
|
if r["from"] != "NVIDIA" || r["to"] != "GPU" || r["type"] != "child" {
|
|
t.Errorf("relation = %v, want {NVIDIA GPU child}", r)
|
|
}
|
|
}
|
|
|
|
// TestProjectRelation_FallsBackToKwdColumns verifies the authoritative *_entity_kwd
|
|
// columns are used when the payload has no from/to.
|
|
func TestProjectRelation_FallsBackToKwdColumns(t *testing.T) {
|
|
row := map[string]interface{}{
|
|
"content_with_weight": `{"type":"related"}`,
|
|
"from_entity_kwd": "NVIDIA",
|
|
"to_entity_kwd": "GPU",
|
|
}
|
|
r := projectRelation(row)
|
|
if r == nil || r["from"] != "NVIDIA" || r["to"] != "GPU" || r["type"] != "related" {
|
|
t.Errorf("relation = %v, want {NVIDIA GPU related}", r)
|
|
}
|
|
}
|
|
|
|
// TestDedupEntities_OrderPreserving verifies dedup by (lowercased name, type).
|
|
func TestDedupEntities_OrderPreserving(t *testing.T) {
|
|
in := []StructureGraphNode{
|
|
{"name": "A", "type": "x"},
|
|
{"name": "a", "type": "x"}, // dup (case-insensitive)
|
|
{"name": "B", "type": "y"},
|
|
{"name": ""}, // dropped (empty name)
|
|
}
|
|
out := dedupEntities(in)
|
|
if len(out) != 2 || out[0]["name"] != "A" || out[1]["name"] != "B" {
|
|
t.Errorf("dedupEntities = %v, want [A B]", out)
|
|
}
|
|
}
|
|
|
|
// TestNormalizeRelationEndpoints aligns relation endpoints to entity ids/names.
|
|
func TestNormalizeRelationEndpoints(t *testing.T) {
|
|
entities := []StructureGraphNode{{"name": "NVIDIA", "type": "x"}}
|
|
relations := []StructureGraphRelation{{"from": "nvidia", "to": "GPU", "type": "child"}}
|
|
out := normalizeRelationEndpoints(entities, relations)
|
|
if out[0]["from"] != "NVIDIA" {
|
|
t.Errorf("normalized from = %v, want NVIDIA (matched to entity name)", out[0]["from"])
|
|
}
|
|
}
|
|
|
|
// TestCompilationTemplateKind_Normalization covers kind normalization.
|
|
func TestCompilationTemplateKind_Normalization(t *testing.T) {
|
|
if compilationTemplateKind("Page_Index") != "page_index" {
|
|
t.Errorf("Page_Index => %q, want page_index", compilationTemplateKind("Page_Index"))
|
|
}
|
|
if compilationTemplateKind("tree") != "tree" {
|
|
t.Errorf("tree => %q, want tree", compilationTemplateKind("tree"))
|
|
}
|
|
}
|
|
|
|
// TestRowTemplateID_FromList covers compilation_template_ids extraction.
|
|
func TestRowTemplateID_FromList(t *testing.T) {
|
|
row := map[string]interface{}{"compilation_template_ids": []interface{}{"", "tid1", "tid2"}}
|
|
if got := rowTemplateID(row); got != "tid1" {
|
|
t.Errorf("rowTemplateID = %q, want tid1", got)
|
|
}
|
|
}
|