Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .codex/agents/mechanical_worker.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
model = "gpt-6.1-sol"
model_reasoning_effort = "high"
model = "gpt-6-astra"
model_reasoning_effort = "medium"
sandbox_mode = "workspace-write"
developer_instructions = "Follow the Mechanical worker role and Delegation context in the repository root AGENTS.md. Apply its task-scoped reading policy; start with current guides and affected code/tests."
2 changes: 1 addition & 1 deletion .codex/agents/reviewer.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
model = "gpt-6.1-sol"
model = "gpt-6-astra"
model_reasoning_effort = "xhigh"
sandbox_mode = "read-only"
developer_instructions = "Follow the Reviewer role and Delegation context in the repository root AGENTS.md. Apply its task-scoped reading policy; start with current guides and affected code/tests."
4 changes: 2 additions & 2 deletions .codex/agents/scout.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
model = "gpt-6.1-sol"
model_reasoning_effort = "high"
model = "gpt-6-astra"
model_reasoning_effort = "medium"
sandbox_mode = "read-only"
developer_instructions = "Follow the Scout role and Delegation context in the repository root AGENTS.md. Apply its task-scoped reading policy; start with current guides and affected code/tests."
4 changes: 2 additions & 2 deletions .codex/agents/test_author.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
model = "gpt-6.1-sol"
model_reasoning_effort = "high"
model = "gpt-6-astra"
model_reasoning_effort = "low"
sandbox_mode = "workspace-write"
developer_instructions = "Follow the Test author role and Delegation context in the repository root AGENTS.md. Apply its task-scoped reading policy; start with current guides and affected code/tests."
2 changes: 1 addition & 1 deletion .codex/agents/verifier.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
model = "gpt-6.1-sol"
model = "gpt-6-astra"
model_reasoning_effort = "xhigh"
sandbox_mode = "workspace-write"
developer_instructions = "Follow the Verifier role and Delegation context in the repository root AGENTS.md. Apply its task-scoped reading policy; start with current guides and affected code/tests."
34 changes: 0 additions & 34 deletions scripts/check_architecture_docs.sh

This file was deleted.

7 changes: 7 additions & 0 deletions scripts/render_architecture_diagrams.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,18 @@ CLASS_SOURCE="${DOC_ROOT}/architecture_classes.puml"
FLOW_SOURCE="${DOC_ROOT}/architecture_flow.puml"
CLASS_ASSET="${DOC_ROOT}/assets/architecture_class_diagram.svg"
FLOW_ASSET="${DOC_ROOT}/assets/architecture_flow.svg"
OVERVIEW_ASSET="${DOC_ROOT}/assets/framework_overview.svg"

echo "================================================================"
echo " [Architecture Diagram Renderer & Gate] Mode: ${MODE}"
echo "================================================================"

# The overview is maintained separately from the generated PlantUML diagrams.
if [[ ! -s "${OVERVIEW_ASSET}" ]]; then
echo "❌ Missing or empty framework overview: ${OVERVIEW_ASSET}"
exit 1
fi

resolve_java() {
local candidate
for candidate in \
Expand Down
6 changes: 3 additions & 3 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ cmake --build build --target edgeflow_test_nodes_runner -j4
```

四个 runner 的源码目录在 `RuntimeTests.cmake` 中定义。GoogleTest 从编译出的用例生成 CTest
入口,包括脚手架生成的测试。新测试套件无需手动注册名称。`contract/architecture/test_test_labels_contract.py`
把实际用例与 CTest 过滤器对照,拒绝空匹配、漏执行、重复执行及不明确的 tier,
同时拒绝禁用的 CTest 条目和仅列举 GoogleTest 用例的命令。
入口,包括脚手架生成的测试。新测试套件无需手动注册名称,每个用例恰好一个入口。
`contract/architecture/test_test_labels_contract.py` 检查 CTest 元数据,拒绝不明确的 tier、
禁用的条目、仅列举 GoogleTest 用例的命令,以及不以返回码 77 表示跳过的 GoogleTest 入口。
常规 `test_*.cpp` 和 `dev_support/` 所属目录中的 `.cpp` 递归收集,增删后在下次构建自动更新。
独立 registry/SDK 目标保持进程和公开依赖隔离;生成源码和可选 E2E 仍显式声明。

Expand Down
11 changes: 1 addition & 10 deletions tests/RuntimeTests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/SafeGtestDiscovery.cmake")
set(_edgeflow_tier2 "tier2;dev-fast;sanitizer-compatible;sanitizer-runtime")
set(_edgeflow_tier3 "tier3;integration;dev-fast;sanitizer-compatible;sanitizer-runtime")
set(_edgeflow_tier4 "tier4;tooling;dev-fast;sanitizer-compatible")
function(edgeflow_discover target)
gtest_discover_tests(${target}
DISCOVERY_MODE PRE_TEST
Expand Down Expand Up @@ -269,16 +268,14 @@ add_test(NAME LayerGuardTest
COMMAND ${CMAKE_COMMAND} -E env
"LLM_EDGEFLOW_LAYER_COMPILE_MANIFEST=${PROJECT_BINARY_DIR}/layer_includes/compile_checks_$<CONFIG>.cmake"
${PROJECT_SOURCE_DIR}/scripts/check_layer_isolation.sh)
add_test(NAME ArchitectureDocsDriftTest
COMMAND ${PROJECT_SOURCE_DIR}/scripts/check_architecture_docs.sh)
add_test(NAME GovernanceConsistencyTest
COMMAND ${PROJECT_SOURCE_DIR}/scripts/check_governance.sh)
add_test(NAME DocLinksTest
COMMAND ${Python3_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/check_doc_links.py)
add_test(NAME DiagramAssetsCheckTest
COMMAND ${PROJECT_SOURCE_DIR}/scripts/render_architecture_diagrams.sh --check)
set_tests_properties(
LayerGuardTest ArchitectureDocsDriftTest GovernanceConsistencyTest DocLinksTest
LayerGuardTest GovernanceConsistencyTest DocLinksTest
PROPERTIES WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
LABELS "tier1;static-gate;dev-fast;sanitizer-compatible")
set_tests_properties(DiagramAssetsCheckTest PROPERTIES
Expand Down Expand Up @@ -321,12 +318,6 @@ if(LLM_EDGEFLOW_HAS_ONNXRUNTIME)
PROPERTIES WILL_FAIL TRUE)
endif()

add_test(NAME PipelineToolCatalogTest COMMAND $<TARGET_FILE:alg_pipeline_tool>
catalog)
set_tests_properties(PipelineToolCatalogTest
PROPERTIES WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
LABELS "${_edgeflow_tier4}")

add_custom_target(edgeflow_dev_tests DEPENDS
alg_demo alg_pipeline_tool alg_pipeline_tool_test alg_show
test_cpp_operator_sdk
Expand Down
1 change: 0 additions & 1 deletion tests/ScriptTests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ set_property(SOURCE contract/authoring/test_spec_signature_diagnostics.cmake
"-DLAYER_COMPILE_MANIFEST=${PROJECT_BINARY_DIR}/layer_includes/compile_checks_$<CONFIG>.cmake")
set_property(SOURCE tooling/test_pipeline_cli.py PROPERTY EDGEFLOW_TEST_ARGS
--tool $<TARGET_FILE:alg_pipeline_tool>
--test-tool $<TARGET_FILE:alg_pipeline_tool_test>
--repo "${PROJECT_SOURCE_DIR}")

edgeflow_collect_test_files(scripts
Expand Down
31 changes: 0 additions & 31 deletions tests/contract/architecture/test_architecture_docs_drift_gate.sh

This file was deleted.

6 changes: 6 additions & 0 deletions tests/contract/architecture/test_diagram_render_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ cp "$root/doc/architecture_classes.puml" "$workspace/doc/"
cp "$root/doc/architecture_flow.puml" "$workspace/doc/"
cp "$root/doc/assets/architecture_class_diagram.svg" "$workspace/doc/assets/"
cp "$root/doc/assets/architecture_flow.svg" "$workspace/doc/assets/"
cp "$root/doc/assets/framework_overview.svg" "$workspace/doc/assets/"
renderer="$root/scripts/render_architecture_diagrams.sh"
cache="${LLM_EDGEFLOW_TOOL_CACHE_DIR:-$root/build/tool-cache}"
run() {
Expand All @@ -23,6 +24,11 @@ expect_failure() {
grep -Fq "$message" "$workspace/output" || { cat "$workspace/output" >&2; exit 1; }
}
expect_failure 'Usage:' run --unsupported
rm "$workspace/doc/assets/framework_overview.svg"
expect_failure 'Missing or empty framework overview' run --check
touch "$workspace/doc/assets/framework_overview.svg"
expect_failure 'Missing or empty framework overview' run --check
cp "$root/doc/assets/framework_overview.svg" "$workspace/doc/assets/"
# A narrow Java transport stub proves rejected cache bytes never reach rendering.
cat > "$workspace/java-version-only" <<'JAVA'
#!/usr/bin/env bash
Expand Down
46 changes: 5 additions & 41 deletions tests/contract/architecture/test_test_labels_contract.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#!/usr/bin/env python3
"""Inspect current CTest metadata and discover actual selected GoogleTest cases."""
"""Inspect current CTest metadata for tier, enablement and skip policy."""

import argparse
import fnmatch
import json
from pathlib import Path
import subprocess
Expand All @@ -12,15 +11,13 @@


class TestRegistrationConsumerTest(unittest.TestCase):
def test_current_registrations_have_one_tier_and_nonempty_actual_gtest_filters(self):
def test_current_registrations_have_one_tier_and_executable_skip_policy(self):
process = subprocess.run(['ctest', '--show-only=json-v1'], cwd=BUILD,
capture_output=True, text=True, check=True)
tests = json.loads(process.stdout)['tests']
self.assertTrue(tests, 'CTest discovery must not be empty')
names = [test['name'] for test in tests]
self.assertEqual(len(names), len(set(names)))
discovery = {}
scheduled = {}
for test in tests:
with self.subTest(test=test['name']):
properties = {item['name']: item['value'] for item in test.get('properties', [])}
Expand All @@ -34,42 +31,9 @@ def test_current_registrations_have_one_tier_and_nonempty_actual_gtest_filters(s
self.assertFalse(any(not separator or value[:1] not in ('0', 'f', 'F')
for _, separator, value in listing_flags),
'CTest execution command must not list GoogleTest cases')
filters = [argument.split('=', 1)[1] for argument in command if argument.startswith('--gtest_filter=')]
if not filters:
continue
self.assertEqual(properties.get('SKIP_RETURN_CODE'), 77)
self.assertNotIn('SKIP_REGULAR_EXPRESSION', properties)
executable = command[0]
if executable not in discovery:
listed = subprocess.run([executable, '--gtest_list_tests', '--gtest_filter=*'], cwd=properties.get('WORKING_DIRECTORY', BUILD),
capture_output=True, text=True, timeout=30)
self.assertEqual(listed.returncode, 0, listed.stdout + listed.stderr)
cases, suite = [], ''
for line in listed.stdout.splitlines():
text = line.split('#', 1)[0].strip()
if not text:
continue
if not line.startswith(' ') and text.endswith('.'):
suite = text
elif line.startswith(' ') and suite:
cases.append(suite + text)
discovery[executable] = cases
scheduled[executable] = set()
for expression in filters:
positive, _, negative = expression.partition('-')
include = positive.split(':') if positive else ['*']
exclude = negative.split(':') if negative else []
selected = [case for case in discovery[executable]
if any(fnmatch.fnmatchcase(case, pattern) for pattern in include)
and not any(fnmatch.fnmatchcase(case, pattern) for pattern in exclude)]
self.assertTrue(selected, f'Current filter selects no cases: {expression}')
duplicate = scheduled[executable].intersection(selected)
self.assertFalse(duplicate, f'Cases scheduled twice: {sorted(duplicate)}')
scheduled[executable].update(selected)
for executable, cases in discovery.items():
with self.subTest(executable=executable):
self.assertEqual(set(cases), scheduled[executable],
f'Compiled cases without a CTest owner: {sorted(set(cases) - scheduled[executable])}')
if any(argument.startswith('--gtest_filter=') for argument in command):
self.assertEqual(properties.get('SKIP_RETURN_CODE'), 77)
self.assertNotIn('SKIP_REGULAR_EXPRESSION', properties)


if __name__ == '__main__':
Expand Down
10 changes: 0 additions & 10 deletions tests/contract/catalog/test_catalog_contract_ssot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,5 @@ TEST(CatalogPublicationTest,
}
}
}

TEST(CatalogPublicationTest, SnapshotIsIndependentOfPublishedCopyMutation) {
const auto snapshot = PipelineCatalog::Snapshot();
ASSERT_FALSE(snapshot.nodes.empty());
auto copied = snapshot;
copied.nodes.front().node_type = "caller mutation";
const auto current = PipelineCatalog::Snapshot();
EXPECT_EQ(current.nodes.front().node_type, snapshot.nodes.front().node_type);
EXPECT_FALSE(current.node_registry_has_conflict);
}
} // namespace
} // namespace llm_edgeflow
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@
namespace llm_edgeflow {
namespace {

// 只读解析返回 mock 宿主结构名和业务服务码;转换器身份由通用套件覆盖。
// 只读解析返回 mock 宿主结构名和业务服务码;转换器身份和槽位由通用套件覆盖。
TEST(MockHostIoContractTest, ResolutionReturnsNativeHostTypesAndServices) {
operator_api::OperatorIoContract contract;
ASSERT_EQ(operator_api::ResolveOperatorConfigIo(
".", "configs/pipeline_keyword_match_rules.conf", &contract),
0);
ASSERT_EQ(contract.inputs.size(), 1u);
ASSERT_EQ(contract.outputs.size(), 1u);
EXPECT_EQ(contract.inputs[0].type, "keyword_in");
EXPECT_EQ(contract.inputs[0].name, "keyword_match");
EXPECT_EQ(contract.inputs[0].type_name, "MockInput");
// 文本 envelope 不带 service_type。
EXPECT_FALSE(contract.inputs[0].service_type);
EXPECT_EQ(contract.outputs[0].type, "json_out");
EXPECT_EQ(contract.outputs[0].type_name, "MockOutput");
EXPECT_EQ(contract.outputs[0].service_type, kMockServiceKeywordMatch);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class KeywordResponseTest : public ::testing::Test {
api::NamedIoBatch outputs_;
};

TEST_F(KeywordResponseTest, CompleteRowsAndUpdatedRulesUseTheRealPipeline) {
TEST_F(KeywordResponseTest, CompleteRowsUseTheConfiguredRulePipeline) {
api::CreateParam create;
create.model_path = ".";
create.cfg_file_name = "configs/pipeline_keyword_match_rules.conf";
Expand Down Expand Up @@ -63,46 +63,19 @@ TEST_F(KeywordResponseTest, CompleteRowsAndUpdatedRulesUseTheRealPipeline) {
{{{"category", "SYSTEM_INIT"}, {"matched_word", "初始化"}},
{{"category", "SYSTEM_INIT"}, {"matched_word", "自检"}}})}}};

// Refill every slot twice. Clearing all output views returns the three
// leases.
for (int round = 0; round < 2; ++round) {
SCOPED_TRACE(round);
outputs_.resize(3);
for (auto& row : outputs_) row["keyword.json_out"] = nullptr;
ASSERT_EQ(ops_.Process(handle_, inputs, outputs_), 0)
<< api::GetOperatorLastError();
ASSERT_EQ(outputs_.size(), expected.size());
for (size_t i = 0; i < expected.size(); ++i) {
SCOPED_TRACE(i);
const auto* value = static_cast<const MockOutput*>(
outputs_[i].at("keyword.json_out").get());
ASSERT_NE(value, nullptr);
EXPECT_EQ(value->service_type, kMockServiceKeywordMatch);
EXPECT_EQ(Json::parse(test_support::MockOutputText(value)), expected[i]);
}
outputs_.clear();
}

api::ControlUpdateRulesParam update{R"({"categories":{"UPDATED":["自检"]}})"};
ASSERT_EQ(
ops_.Control(handle_, static_cast<int>(api::ControlCommand::kUpdateRules),
&update),
0);
outputs_.resize(3);
for (auto& row : outputs_) row["keyword.json_out"] = nullptr;
ASSERT_EQ(ops_.Process(handle_, inputs, outputs_), 0)
<< api::GetOperatorLastError();
const auto changed =
test_support::MockOutputText(outputs_[2].at("keyword.json_out").get());
ASSERT_FALSE(changed.empty());
EXPECT_EQ(Json::parse(changed),
(Json{{"is_hit", 1},
{"intent", "UPDATED"},
{"confidence", 1.0},
{"matched_word", "自检"},
{"slots", Json::object()},
{"matches", Json::array({{{"category", "UPDATED"},
{"matched_word", "自检"}}})}}));
ASSERT_EQ(outputs_.size(), expected.size());
for (size_t i = 0; i < expected.size(); ++i) {
SCOPED_TRACE(i);
const auto* value = static_cast<const MockOutput*>(
outputs_[i].at("keyword.json_out").get());
ASSERT_NE(value, nullptr);
EXPECT_EQ(value->service_type, kMockServiceKeywordMatch);
EXPECT_EQ(Json::parse(test_support::MockOutputText(value)), expected[i]);
}
}
} // namespace
} // namespace llm_edgeflow
1 change: 0 additions & 1 deletion tests/tooling/test_pipeline_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ def test_resolve_reports_the_effective_decode_batch_size(self):
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--tool", type=Path, default=TOOL)
parser.add_argument("--test-tool", type=Path)
parser.add_argument("--repo", type=Path, default=ROOT)
arguments, remaining = parser.parse_known_args()
TOOL = arguments.tool.resolve()
Expand Down
Loading