增加代码知识库;修复文档处理内容;增加API设置
This commit is contained in:
145
rag-web-ui/backend/tests/test_consistency_services.py
Normal file
145
rag-web-ui/backend/tests/test_consistency_services.py
Normal file
@@ -0,0 +1,145 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from app.services.code_kb.adapter import CodeKnowledgeBaseAdapter
|
||||
from app.services.code_kb.graph import CodeCallGraph
|
||||
from app.services.code_kb.schema import CodeFunctionEvidence, CodeSearchHit
|
||||
from app.services.consistency.comparator import ConsistencyComparator
|
||||
from app.services.consistency.schema import RequirementSnapshot
|
||||
from app.services.consistency.scorer import coverage_score
|
||||
|
||||
|
||||
def test_metadata_normalization_uses_aliases_and_graph_fields():
|
||||
adapter = CodeKnowledgeBaseAdapter()
|
||||
graph_nodes = {
|
||||
"Function:Init": {
|
||||
"id": "Function:Init",
|
||||
"name": "Init",
|
||||
"file_path": "src/init.c",
|
||||
"start_line": 10,
|
||||
"end_line": 20,
|
||||
"signature": "void Init(void)",
|
||||
"logic_flow": "init flow",
|
||||
"raw_attributes": {"code_snippet": "void Init(void) {}", "includes": ["a.h"]},
|
||||
}
|
||||
}
|
||||
evidence = adapter._normalize_metadata(
|
||||
{"node_id": "Function:Init", "function_name": "Init", "file_path": "src/init.c", "summary": "summary"},
|
||||
graph_nodes,
|
||||
index_dimension=1024,
|
||||
)
|
||||
|
||||
assert evidence.name == "Init"
|
||||
assert evidence.file == "src/init.c"
|
||||
assert evidence.start_line == 10
|
||||
assert evidence.code_snippet == "void Init(void) {}"
|
||||
assert evidence.embedding_dim == 1024
|
||||
|
||||
|
||||
def test_call_graph_expands_metadata_edges():
|
||||
center = CodeFunctionEvidence(node_id="Function:Center", name="Center", qualified_name="Center", file="a.c")
|
||||
caller = CodeFunctionEvidence(
|
||||
node_id="Function:Caller",
|
||||
name="Caller",
|
||||
qualified_name="Caller",
|
||||
file="a.c",
|
||||
calls=["Center"],
|
||||
)
|
||||
callee = CodeFunctionEvidence(node_id="Function:Callee", name="Callee", qualified_name="Callee", file="a.c")
|
||||
center.calls = ["Callee"]
|
||||
graph = CodeCallGraph({}, [center, caller, callee])
|
||||
|
||||
context = graph.expand("Function:Center", max_hops=1)
|
||||
|
||||
assert [item.name for item in context.callers] == ["Caller"]
|
||||
assert [item.name for item in context.callees] == ["Callee"]
|
||||
assert "Caller -> Center -> Callee" in context.call_chains
|
||||
|
||||
|
||||
def test_simple_vector_index_json_can_be_loaded():
|
||||
vector_path = Path("uploads") / "test-simple-vector-index.faiss"
|
||||
vector_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
try:
|
||||
vector_path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"format": "simple_l2_vector_index",
|
||||
"dimension": 3,
|
||||
"vectors": [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0]],
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
adapter = CodeKnowledgeBaseAdapter()
|
||||
index = adapter._read_faiss_index(str(vector_path))
|
||||
|
||||
assert index.ntotal == 2
|
||||
assert index.d == 3
|
||||
finally:
|
||||
if vector_path.exists():
|
||||
vector_path.unlink()
|
||||
|
||||
|
||||
def test_lexical_search_falls_back_to_function_metadata():
|
||||
adapter = CodeKnowledgeBaseAdapter()
|
||||
adapter.functions = [
|
||||
CodeFunctionEvidence(
|
||||
node_id="Function:InitAttEnv",
|
||||
name="InitAttEnv",
|
||||
qualified_name="InitAttEnv",
|
||||
file="AttEnvMod.c",
|
||||
summary="initializes attitude environment parameters",
|
||||
code_snippet="void InitAttEnv(void) {}",
|
||||
),
|
||||
CodeFunctionEvidence(
|
||||
node_id="Function:MatrixProduct",
|
||||
name="MatrixProduct",
|
||||
qualified_name="MatrixProduct",
|
||||
file="AttMath.c",
|
||||
summary="matrix multiplication",
|
||||
),
|
||||
]
|
||||
|
||||
hits = adapter._lexical_search_functions("InitAttEnv attitude environment", top_k=1, min_similarity=0.2)
|
||||
|
||||
assert hits[0].evidence.name == "InitAttEnv"
|
||||
|
||||
|
||||
def test_parse_json_judgment_from_markdown_block():
|
||||
raw = """```json
|
||||
{"verdict":"partial","confidence":0.6,"covered_points":["A"],"missing_points":["B"]}
|
||||
```"""
|
||||
|
||||
parsed = ConsistencyComparator.parse_json_judgment(raw)
|
||||
|
||||
assert parsed["verdict"] == "partial"
|
||||
assert parsed["confidence"] == 0.6
|
||||
|
||||
|
||||
def test_coverage_score_caps_missing_verdict():
|
||||
requirement = RequirementSnapshot(
|
||||
requirement_uid="REQ-1",
|
||||
title="",
|
||||
description="init system",
|
||||
acceptance_criteria=["A", "B"],
|
||||
)
|
||||
evidence = CodeFunctionEvidence(
|
||||
node_id="Function:Init",
|
||||
name="Init",
|
||||
qualified_name="Init",
|
||||
file="init.c",
|
||||
start_line=1,
|
||||
end_line=10,
|
||||
summary="init system",
|
||||
logic_flow="flow",
|
||||
code_snippet="code",
|
||||
)
|
||||
score = coverage_score(
|
||||
requirement,
|
||||
[CodeSearchHit(evidence=evidence, similarity=0.95, distance=0.1, rank=1)],
|
||||
[],
|
||||
{"verdict": "missing", "missing_points": ["B"]},
|
||||
)
|
||||
|
||||
assert score <= 0.25
|
||||
Reference in New Issue
Block a user