From 36b85ebb0e1df70a31eb256f54efaea4202bb8dd Mon Sep 17 00:00:00 2001 From: Melody Ma Date: Wed, 1 Jul 2026 16:33:39 +0800 Subject: [PATCH 1/5] fix(cpp-parser): preserve enum source locations --- .../cases/complex_class/expected.json | 8 ++++---- .../cases/include_3rdparty/expected.json | 2 +- .../cases/nest_namespace_class/expected.json | 2 +- .../relationship_implementation/expected.json | 2 +- .../cases/relationship_inheritance/expected.json | 2 +- .../cases/simple_enums/expected.json | 16 ++++++++-------- .../cases/type_alias/expected.json | 2 +- .../src/visitor/src/class_parser_helper.rs | 8 ++++++-- cpp/libclang/src/visitor/src/class_visitor.rs | 15 +++++++++------ cpp/libclang/src/visitor/src/enum_visitor.rs | 5 +++++ 10 files changed, 37 insertions(+), 25 deletions(-) diff --git a/cpp/libclang/integration_test/cases/complex_class/expected.json b/cpp/libclang/integration_test/cases/complex_class/expected.json index 9a486f30..0ec48c89 100644 --- a/cpp/libclang/integration_test/cases/complex_class/expected.json +++ b/cpp/libclang/integration_test/cases/complex_class/expected.json @@ -9,7 +9,7 @@ "methods": [ { "name": "Car", - "return_type": "void", + "return_type": null, "parameters": [ { "is_variadic": false, @@ -101,7 +101,7 @@ "methods": [ { "name": "~ITransport", - "return_type": "void", + "return_type": null, "parameters": [], "modifiers": [ "Virtual", @@ -149,7 +149,7 @@ "methods": [ { "name": "VehicleBase", - "return_type": "void", + "return_type": null, "parameters": [ { "is_variadic": false, @@ -165,7 +165,7 @@ }, { "name": "~VehicleBase", - "return_type": "void", + "return_type": null, "parameters": [], "modifiers": [ "Virtual", diff --git a/cpp/libclang/integration_test/cases/include_3rdparty/expected.json b/cpp/libclang/integration_test/cases/include_3rdparty/expected.json index 4229fd1f..19a0097f 100644 --- a/cpp/libclang/integration_test/cases/include_3rdparty/expected.json +++ b/cpp/libclang/integration_test/cases/include_3rdparty/expected.json @@ -59,7 +59,7 @@ "visibility": "private" } ], - "source_file": "./cpp/libclang/integration_test/cases/include_3rdparty/transport.h", + "source_file": "cpp/libclang/integration_test/cases/include_3rdparty/transport.h", "source_line": 19 } }, diff --git a/cpp/libclang/integration_test/cases/nest_namespace_class/expected.json b/cpp/libclang/integration_test/cases/nest_namespace_class/expected.json index 6abb6362..97c38968 100644 --- a/cpp/libclang/integration_test/cases/nest_namespace_class/expected.json +++ b/cpp/libclang/integration_test/cases/nest_namespace_class/expected.json @@ -9,7 +9,7 @@ "methods": [ { "name": "~ITransport", - "return_type": "void", + "return_type": null, "parameters": [], "modifiers": [ "Virtual", diff --git a/cpp/libclang/integration_test/cases/relationship_implementation/expected.json b/cpp/libclang/integration_test/cases/relationship_implementation/expected.json index 39457a27..181844eb 100644 --- a/cpp/libclang/integration_test/cases/relationship_implementation/expected.json +++ b/cpp/libclang/integration_test/cases/relationship_implementation/expected.json @@ -43,7 +43,7 @@ "methods": [ { "name": "~IService", - "return_type": "void", + "return_type": null, "parameters": [], "modifiers": [ "Virtual", diff --git a/cpp/libclang/integration_test/cases/relationship_inheritance/expected.json b/cpp/libclang/integration_test/cases/relationship_inheritance/expected.json index 57ce0395..fe846d37 100644 --- a/cpp/libclang/integration_test/cases/relationship_inheritance/expected.json +++ b/cpp/libclang/integration_test/cases/relationship_inheritance/expected.json @@ -9,7 +9,7 @@ "methods": [ { "name": "~Base", - "return_type": "void", + "return_type": null, "parameters": [], "modifiers": [ "Virtual", diff --git a/cpp/libclang/integration_test/cases/simple_enums/expected.json b/cpp/libclang/integration_test/cases/simple_enums/expected.json index de107734..97d8ef54 100644 --- a/cpp/libclang/integration_test/cases/simple_enums/expected.json +++ b/cpp/libclang/integration_test/cases/simple_enums/expected.json @@ -28,8 +28,8 @@ "template_parameters": null, "type_aliases": [], "variables": [], - "source_file": null, - "source_line": null + "source_file": "cpp/libclang/integration_test/cases/simple_enums/transport.h", + "source_line": 25 }, "MyNamespace::Direction": { "id": "MyNamespace::Direction", @@ -59,8 +59,8 @@ "template_parameters": null, "type_aliases": [], "variables": [], - "source_file": null, - "source_line": null + "source_file": "cpp/libclang/integration_test/cases/simple_enums/transport.h", + "source_line": 35 }, "RGBColor": { "id": "RGBColor", @@ -86,8 +86,8 @@ "template_parameters": null, "type_aliases": [], "variables": [], - "source_file": null, - "source_line": null + "source_file": "cpp/libclang/integration_test/cases/simple_enums/transport.h", + "source_line": 17 }, "MyNamespace::Direction3D": { "id": "MyNamespace::Direction3D", @@ -125,8 +125,8 @@ "template_parameters": null, "type_aliases": [], "variables": [], - "source_file": null, - "source_line": null + "source_file": "cpp/libclang/integration_test/cases/simple_enums/transport.h", + "source_line": 43 } }, "functions": [] diff --git a/cpp/libclang/integration_test/cases/type_alias/expected.json b/cpp/libclang/integration_test/cases/type_alias/expected.json index 36deba03..ba2ee5c5 100644 --- a/cpp/libclang/integration_test/cases/type_alias/expected.json +++ b/cpp/libclang/integration_test/cases/type_alias/expected.json @@ -9,7 +9,7 @@ "methods": [ { "name": "Car", - "return_type": "void", + "return_type": null, "parameters": [ { "name": "name", diff --git a/cpp/libclang/src/visitor/src/class_parser_helper.rs b/cpp/libclang/src/visitor/src/class_parser_helper.rs index 9684af72..322e4942 100644 --- a/cpp/libclang/src/visitor/src/class_parser_helper.rs +++ b/cpp/libclang/src/visitor/src/class_parser_helper.rs @@ -661,9 +661,13 @@ pub fn to_workspace_relative_or_abs_path(abs_path: std::path::PathBuf) -> String // so golden files stay portable across machines. if let Ok(cwd) = std::env::current_dir() { if let Ok(rel) = abs_path.strip_prefix(&cwd) { - return rel.to_string_lossy().into_owned(); + return normalize_source_path(rel.to_string_lossy().as_ref()); } } - abs_path.to_string_lossy().into_owned() + normalize_source_path(abs_path.to_string_lossy().as_ref()) +} + +fn normalize_source_path(path: &str) -> String { + path.strip_prefix("./").unwrap_or(path).to_string() } diff --git a/cpp/libclang/src/visitor/src/class_visitor.rs b/cpp/libclang/src/visitor/src/class_visitor.rs index c09f22d9..3ea81286 100644 --- a/cpp/libclang/src/visitor/src/class_visitor.rs +++ b/cpp/libclang/src/visitor/src/class_visitor.rs @@ -138,7 +138,7 @@ impl ClassVisitor { } } -fn parse_source_location(entity: &Entity) -> (Option, Option) { +pub(crate) fn parse_source_location(entity: &Entity) -> (Option, Option) { let Some(location) = entity.get_location() else { return (None, None); }; @@ -207,10 +207,13 @@ fn parse_method(entity: &Entity, parsed_method_type: &ParsedMethodType) -> Optio .map(|methods| !methods.is_empty()) .unwrap_or(false); - let return_type = entity - .get_result_type() - .map(|ret| render_type_for_display(&ret, &parsed_method_type.return_type)) - .unwrap_or_else(|| "void".to_string()); + let return_type = if matches!(kind, EntityKind::Constructor | EntityKind::Destructor) { + None + } else { + entity + .get_result_type() + .map(|ret| render_type_for_display(&ret, &parsed_method_type.return_type)) + }; let mut parameters = Vec::new(); let method_is_variadic = entity.get_type().map(|t| t.is_variadic()).unwrap_or(false); @@ -233,7 +236,7 @@ fn parse_method(entity: &Entity, parsed_method_type: &ParsedMethodType) -> Optio Some(Method { name, - return_type: Some(return_type), + return_type, visibility: parse_visibility(entity), parameters, template_parameters: None, diff --git a/cpp/libclang/src/visitor/src/enum_visitor.rs b/cpp/libclang/src/visitor/src/enum_visitor.rs index acbc092b..e88b385a 100644 --- a/cpp/libclang/src/visitor/src/enum_visitor.rs +++ b/cpp/libclang/src/visitor/src/enum_visitor.rs @@ -10,6 +10,7 @@ // // SPDX-License-Identifier: Apache-2.0 //////////////////////////////////////////////////////////////////////////////////// +use crate::class_visitor::parse_source_location; use crate::context::VisitContext; use crate::visitor::AstVisitor; use clang::Entity; @@ -34,12 +35,16 @@ impl EnumVisitor { } else { name.clone() }; + let (source_file, source_line) = parse_source_location(&entity); + Some(SimpleEntity { id: full_qualified_id, name, enclosing_namespace_id: namespace_id, entity_type: EntityType::Enum, enum_literals: get_literals(entity), + source_file, + source_line, ..Default::default() }) } From d9352bc18213e34817e83abdf0b974a9f1797c2c Mon Sep 17 00:00:00 2001 From: Melody Ma Date: Wed, 1 Jul 2026 16:34:02 +0800 Subject: [PATCH 2/5] fix(puml-parser): preserve class diagram source locations --- .../class_diagram_cpp_members/output.json | 4 +- .../output.json | 8 ++-- .../output.json | 12 +++--- .../class_diagram_modifiers/output.json | 8 ++-- .../class_diagram_object_syntax/output.json | 4 +- .../class_diagram_positive/output.json | 26 ++++++------ .../output.json | 14 +++---- .../class_diagram_syntax_coverage/output.json | 41 +++++++++---------- .../src/class_diagram/src/class_ast.rs | 2 + .../src/class_diagram/src/class_parser.rs | 9 +++- .../src/include/include_expander.rs | 22 +++++++++- .../src/procedure/procedure_expander.rs | 10 +++++ .../class_diagram/alias_class/output.json | 3 +- .../class_diagram/alias_package/output.json | 3 +- .../class_diagram/attr_method/output.json | 3 +- .../class_diagram/class_merge/output.json | 3 +- .../tests/class_diagram/color/output.json | 3 +- .../tests/class_diagram/cpp_style/output.json | 3 +- .../class_diagram/ctrl_instruct/output.json | 3 +- .../tests/class_diagram/empty/output.json | 3 +- .../tests/class_diagram/enum/output.json | 3 +- .../class_diagram/full_features/output.json | 3 +- .../tests/class_diagram/interface/output.json | 3 +- .../class_diagram/namespace_1/output.json | 3 +- .../class_diagram/namespace_2/output.json | 3 +- .../class_diagram/namespace_3/output.json | 3 +- .../tests/class_diagram/one_class/output.json | 3 +- .../class_diagram/only_attribute/output.json | 3 +- .../class_diagram/only_method/output.json | 3 +- .../tests/class_diagram/package/output.json | 3 +- .../tests/class_diagram/param/output.json | 3 +- .../class_diagram/param_templete/output.json | 3 +- .../relationship_arrows/output.json | 3 +- .../relationship_inheritance/output.json | 3 +- .../relationship_mix_inher/output.json | 3 +- .../relationship_normal/output.json | 3 +- .../relationship_qualified_id/output.json | 3 +- .../stereotype_definition/output.json | 3 +- .../stereotype_relationship/output.json | 3 +- .../tests/class_diagram/struct/output.json | 3 +- .../src/class_diagram/src/class_resolver.rs | 15 +++---- 41 files changed, 163 insertions(+), 96 deletions(-) diff --git a/plantuml/parser/integration_test/class_diagram/class_diagram_cpp_members/output.json b/plantuml/parser/integration_test/class_diagram/class_diagram_cpp_members/output.json index 91352107..31a6ee80 100644 --- a/plantuml/parser/integration_test/class_diagram/class_diagram_cpp_members/output.json +++ b/plantuml/parser/integration_test/class_diagram/class_diagram_cpp_members/output.json @@ -115,7 +115,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_cpp_members", + "source_file": "class_diagram_cpp_members.puml", "source_line": 16, "variables": [], "relationships": [] @@ -123,7 +123,7 @@ ], "relationships": [], "source_files": [ - "class_diagram_cpp_members" + "class_diagram_cpp_members.puml" ], "version": null } diff --git a/plantuml/parser/integration_test/class_diagram/class_diagram_enum_value_sequence/output.json b/plantuml/parser/integration_test/class_diagram/class_diagram_enum_value_sequence/output.json index 6c734e7b..79930938 100644 --- a/plantuml/parser/integration_test/class_diagram/class_diagram_enum_value_sequence/output.json +++ b/plantuml/parser/integration_test/class_diagram/class_diagram_enum_value_sequence/output.json @@ -36,7 +36,7 @@ "value": 11 } ], - "source_file": "class_diagram_enum_value_sequence", + "source_file": "class_diagram_enum_value_sequence.puml", "source_line": 17, "variables": [], "relationships": [] @@ -67,7 +67,7 @@ "value": 11 } ], - "source_file": "class_diagram_enum_value_sequence", + "source_file": "class_diagram_enum_value_sequence.puml", "source_line": 29, "variables": [], "relationships": [] @@ -102,7 +102,7 @@ "value": 2 } ], - "source_file": "class_diagram_enum_value_sequence", + "source_file": "class_diagram_enum_value_sequence.puml", "source_line": 39, "variables": [], "relationships": [] @@ -110,7 +110,7 @@ ], "relationships": [], "source_files": [ - "class_diagram_enum_value_sequence" + "class_diagram_enum_value_sequence.puml" ], "version": null } diff --git a/plantuml/parser/integration_test/class_diagram/class_diagram_file_level_constructs/output.json b/plantuml/parser/integration_test/class_diagram/class_diagram_file_level_constructs/output.json index 403beac7..fa0b3735 100644 --- a/plantuml/parser/integration_test/class_diagram/class_diagram_file_level_constructs/output.json +++ b/plantuml/parser/integration_test/class_diagram/class_diagram_file_level_constructs/output.json @@ -11,7 +11,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_file_level_constructs", + "source_file": "class_diagram_file_level_constructs.puml", "source_line": 20, "variables": [], "relationships": [] @@ -25,7 +25,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_file_level_constructs", + "source_file": "class_diagram_file_level_constructs.puml", "source_line": 21, "variables": [], "relationships": [] @@ -54,7 +54,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_file_level_constructs", + "source_file": "class_diagram_file_level_constructs.puml", "source_line": 33, "variables": [], "relationships": [] @@ -79,7 +79,7 @@ "T" ], "enum_literals": [], - "source_file": "class_diagram_file_level_constructs", + "source_file": "class_diagram_file_level_constructs.puml", "source_line": 37, "variables": [], "relationships": [] @@ -137,7 +137,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_file_level_constructs", + "source_file": "class_diagram_file_level_constructs.puml", "source_line": 41, "variables": [], "relationships": [] @@ -145,7 +145,7 @@ ], "relationships": [], "source_files": [ - "class_diagram_file_level_constructs" + "class_diagram_file_level_constructs.puml" ], "version": null } diff --git a/plantuml/parser/integration_test/class_diagram/class_diagram_modifiers/output.json b/plantuml/parser/integration_test/class_diagram/class_diagram_modifiers/output.json index c2e269df..3651fa40 100644 --- a/plantuml/parser/integration_test/class_diagram/class_diagram_modifiers/output.json +++ b/plantuml/parser/integration_test/class_diagram/class_diagram_modifiers/output.json @@ -22,7 +22,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_modifiers", + "source_file": "class_diagram_modifiers.puml", "source_line": 16, "variables": [], "relationships": [] @@ -57,7 +57,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_modifiers", + "source_file": "class_diagram_modifiers.puml", "source_line": 20, "variables": [], "relationships": [] @@ -98,7 +98,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_modifiers", + "source_file": "class_diagram_modifiers.puml", "source_line": 25, "variables": [], "relationships": [] @@ -106,7 +106,7 @@ ], "relationships": [], "source_files": [ - "class_diagram_modifiers" + "class_diagram_modifiers.puml" ], "version": null } diff --git a/plantuml/parser/integration_test/class_diagram/class_diagram_object_syntax/output.json b/plantuml/parser/integration_test/class_diagram/class_diagram_object_syntax/output.json index 9c2e8e32..d87d85db 100644 --- a/plantuml/parser/integration_test/class_diagram/class_diagram_object_syntax/output.json +++ b/plantuml/parser/integration_test/class_diagram/class_diagram_object_syntax/output.json @@ -20,7 +20,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_object_syntax", + "source_file": "class_diagram_object_syntax.puml", "source_line": 20, "variables": [], "relationships": [] @@ -28,7 +28,7 @@ ], "relationships": [], "source_files": [ - "class_diagram_object_syntax" + "class_diagram_object_syntax.puml" ], "version": null } diff --git a/plantuml/parser/integration_test/class_diagram/class_diagram_positive/output.json b/plantuml/parser/integration_test/class_diagram/class_diagram_positive/output.json index e7e9bce8..e7bfa9c7 100644 --- a/plantuml/parser/integration_test/class_diagram/class_diagram_positive/output.json +++ b/plantuml/parser/integration_test/class_diagram/class_diagram_positive/output.json @@ -11,7 +11,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 25, "variables": [ { @@ -38,7 +38,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 30, "variables": [ { @@ -78,7 +78,7 @@ "value": 2 } ], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 35, "variables": [], "relationships": [ @@ -117,7 +117,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 41, "variables": [], "relationships": [ @@ -155,7 +155,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 46, "variables": [], "relationships": [] @@ -192,7 +192,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 50, "variables": [ { @@ -230,7 +230,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 59, "variables": [ { @@ -281,7 +281,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 65, "variables": [ { @@ -323,7 +323,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 75, "variables": [ { @@ -369,7 +369,7 @@ "value": 3 } ], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 83, "variables": [], "relationships": [] @@ -403,7 +403,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 90, "variables": [], "relationships": [] @@ -426,7 +426,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_positive_test", + "source_file": "class_diagram_positive.puml", "source_line": 98, "variables": [], "relationships": [ @@ -513,7 +513,7 @@ } ], "source_files": [ - "class_positive_test" + "class_diagram_positive.puml" ], "version": null } diff --git a/plantuml/parser/integration_test/class_diagram/class_diagram_relationship_variants/output.json b/plantuml/parser/integration_test/class_diagram/class_diagram_relationship_variants/output.json index b1d131e8..eacb1cd4 100644 --- a/plantuml/parser/integration_test/class_diagram/class_diagram_relationship_variants/output.json +++ b/plantuml/parser/integration_test/class_diagram/class_diagram_relationship_variants/output.json @@ -11,7 +11,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_relationship_variants", + "source_file": "class_diagram_relationship_variants.puml", "source_line": 18, "variables": [], "relationships": [] @@ -25,7 +25,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_relationship_variants", + "source_file": "class_diagram_relationship_variants.puml", "source_line": 19, "variables": [], "relationships": [ @@ -47,7 +47,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_relationship_variants", + "source_file": "class_diagram_relationship_variants.puml", "source_line": 21, "variables": [], "relationships": [ @@ -69,7 +69,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_relationship_variants", + "source_file": "class_diagram_relationship_variants.puml", "source_line": 23, "variables": [ { @@ -107,7 +107,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_relationship_variants", + "source_file": "class_diagram_relationship_variants.puml", "source_line": 27, "variables": [], "relationships": [] @@ -121,7 +121,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_relationship_variants", + "source_file": "class_diagram_relationship_variants.puml", "source_line": 31, "variables": [], "relationships": [ @@ -180,7 +180,7 @@ } ], "source_files": [ - "class_diagram_relationship_variants" + "class_diagram_relationship_variants.puml" ], "version": null } diff --git a/plantuml/parser/integration_test/class_diagram/class_diagram_syntax_coverage/output.json b/plantuml/parser/integration_test/class_diagram/class_diagram_syntax_coverage/output.json index 4b890b98..9263f888 100644 --- a/plantuml/parser/integration_test/class_diagram/class_diagram_syntax_coverage/output.json +++ b/plantuml/parser/integration_test/class_diagram/class_diagram_syntax_coverage/output.json @@ -11,7 +11,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 21, "variables": [], "relationships": [] @@ -25,7 +25,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 22, "variables": [], "relationships": [] @@ -54,7 +54,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 39, "variables": [], "relationships": [] @@ -68,7 +68,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 43, "variables": [], "relationships": [] @@ -82,7 +82,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 45, "variables": [], "relationships": [ @@ -111,7 +111,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 48, "variables": [], "relationships": [] @@ -136,7 +136,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 50, "variables": [], "relationships": [] @@ -159,10 +159,9 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 54, - "variables": [ - ], + "variables": [], "relationships": [ { "source": "sample.newline.CheckProgrammingDependenciesFlag", @@ -182,7 +181,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 58, "variables": [], "relationships": [] @@ -201,7 +200,7 @@ "value": 0 } ], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 60, "variables": [], "relationships": [ @@ -230,7 +229,7 @@ "methods": [], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 64, "variables": [ { @@ -261,7 +260,7 @@ "T" ], "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 68, "variables": [], "relationships": [] @@ -297,7 +296,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 71, "variables": [], "relationships": [] @@ -346,7 +345,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 75, "variables": [], "relationships": [] @@ -579,7 +578,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 79, "variables": [ { @@ -632,7 +631,7 @@ "T" ], "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 111, "variables": [], "relationships": [] @@ -686,7 +685,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 116, "variables": [ { @@ -734,7 +733,7 @@ ], "template_parameters": null, "enum_literals": [], - "source_file": "class_diagram_syntax_coverage", + "source_file": "class_diagram_syntax_coverage.puml", "source_line": 128, "variables": [], "relationships": [] @@ -799,7 +798,7 @@ } ], "source_files": [ - "class_diagram_syntax_coverage" + "class_diagram_syntax_coverage.puml" ], "version": null } diff --git a/plantuml/parser/puml_parser/src/class_diagram/src/class_ast.rs b/plantuml/parser/puml_parser/src/class_diagram/src/class_ast.rs index 8c4b22a2..fc082d7f 100644 --- a/plantuml/parser/puml_parser/src/class_diagram/src/class_ast.rs +++ b/plantuml/parser/puml_parser/src/class_diagram/src/class_ast.rs @@ -276,6 +276,7 @@ pub struct Package { #[derive(Debug, Default, Serialize, Deserialize, PartialEq)] pub struct ClassUmlFile { pub name: String, + pub source_file: String, pub elements: Vec, pub relationships: Vec, } @@ -659,6 +660,7 @@ mod tests { fn test_class_uml_file_is_empty_for_empty_named_file() { let file = ClassUmlFile { name: "x".into(), + source_file: "x.puml".into(), elements: vec![], relationships: vec![], }; diff --git a/plantuml/parser/puml_parser/src/class_diagram/src/class_parser.rs b/plantuml/parser/puml_parser/src/class_diagram/src/class_parser.rs index 96ac26c6..8273b5ec 100644 --- a/plantuml/parser/puml_parser/src/class_diagram/src/class_parser.rs +++ b/plantuml/parser/puml_parser/src/class_diagram/src/class_parser.rs @@ -1055,7 +1055,14 @@ impl DiagramParser for PumlClassParser { ); } - let mut uml_file = ClassUmlFile::default(); + let mut uml_file = ClassUmlFile { + source_file: path + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or_default() + .to_string(), + ..Default::default() + }; let mut ignored_objects = IgnoredObjectRegistry::default(); let mut relationships = Vec::new(); diff --git a/plantuml/parser/puml_parser/src/preprocessor/src/include/include_expander.rs b/plantuml/parser/puml_parser/src/preprocessor/src/include/include_expander.rs index 4445da57..9634cb60 100644 --- a/plantuml/parser/puml_parser/src/preprocessor/src/include/include_expander.rs +++ b/plantuml/parser/puml_parser/src/preprocessor/src/include/include_expander.rs @@ -31,6 +31,7 @@ use log::debug; use std::collections::{HashMap, HashSet}; +use std::fs; use std::path::PathBuf; use std::rc::Rc; use thiserror::Error; @@ -228,10 +229,19 @@ impl IncludeExpander { ctx.push_stack(file)?; + let original_content = + fs::read_to_string(file.as_ref()).map_err(|_| IncludeExpandError::FileNotFound { + file: Rc::clone(file), + })?; + + if file_list.len() == 1 && !has_include_or_subblock_directive(&original_content) { + ctx.pop_stack(); + return Ok(original_content); + } + let stmts_ast = self.load_ast(file)?; let expanded_ast = self.expand_stmts(&stmts_ast, file, ctx, file_list)?; let rendered = render_stmts(expanded_ast); - ctx.pop_stack(); Ok(rendered) } @@ -366,6 +376,16 @@ impl IncludeExpander { } } +fn has_include_or_subblock_directive(content: &str) -> bool { + content.lines().any(|line| { + let trimmed = line.trim_start(); + trimmed.starts_with("!include") + || trimmed.starts_with("!includesub") + || trimmed.starts_with("!startsub") + || trimmed.starts_with("!endsub") + }) +} + /// Renders AST statements into PlantUML text. /// /// # Arguments diff --git a/plantuml/parser/puml_parser/src/preprocessor/src/procedure/procedure_expander.rs b/plantuml/parser/puml_parser/src/preprocessor/src/procedure/procedure_expander.rs index b70a8d8f..9fd74e59 100644 --- a/plantuml/parser/puml_parser/src/preprocessor/src/procedure/procedure_expander.rs +++ b/plantuml/parser/puml_parser/src/preprocessor/src/procedure/procedure_expander.rs @@ -74,6 +74,10 @@ impl ProcedureExpander { content: &str, log_level: LogLevel, ) -> Result { + if !has_procedure_definition(content) { + return Ok(content.to_string()); + } + let mut out = String::new(); let mut stack = Vec::new(); @@ -276,3 +280,9 @@ impl ProcedureExpander { Ok(out) } } + +fn has_procedure_definition(content: &str) -> bool { + content + .lines() + .any(|line| line.trim_start().starts_with("!procedure")) +} diff --git a/plantuml/parser/puml_parser/tests/class_diagram/alias_class/output.json b/plantuml/parser/puml_parser/tests/class_diagram/alias_class/output.json index ff65805a..3152e629 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/alias_class/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/alias_class/output.json @@ -84,6 +84,7 @@ }, "label": null } - ] + ], + "source_file": "alias_class.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/alias_package/output.json b/plantuml/parser/puml_parser/tests/class_diagram/alias_package/output.json index cbc3ff21..0eaa0869 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/alias_package/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/alias_package/output.json @@ -108,6 +108,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "alias_package.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/attr_method/output.json b/plantuml/parser/puml_parser/tests/class_diagram/attr_method/output.json index 3a007389..1fa66d90 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/attr_method/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/attr_method/output.json @@ -45,6 +45,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "attr_method.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/class_merge/output.json b/plantuml/parser/puml_parser/tests/class_diagram/class_merge/output.json index b97a6c8b..7d872cde 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/class_merge/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/class_merge/output.json @@ -57,6 +57,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "class_merge.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/color/output.json b/plantuml/parser/puml_parser/tests/class_diagram/color/output.json index f722ffbc..d1db9a7f 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/color/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/color/output.json @@ -41,6 +41,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "color.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/cpp_style/output.json b/plantuml/parser/puml_parser/tests/class_diagram/cpp_style/output.json index a882cbb8..04934e9a 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/cpp_style/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/cpp_style/output.json @@ -58,6 +58,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "cpp_style.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/ctrl_instruct/output.json b/plantuml/parser/puml_parser/tests/class_diagram/ctrl_instruct/output.json index 1db95f98..b3c98694 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/ctrl_instruct/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/ctrl_instruct/output.json @@ -59,6 +59,7 @@ }, "label": null } - ] + ], + "source_file": "ctrl_instruct.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/empty/output.json b/plantuml/parser/puml_parser/tests/class_diagram/empty/output.json index 1cb8a88f..2a04e4c1 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/empty/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/empty/output.json @@ -2,6 +2,7 @@ "empty.puml": { "name": "", "elements": [], - "relationships": [] + "relationships": [], + "source_file": "empty.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/enum/output.json b/plantuml/parser/puml_parser/tests/class_diagram/enum/output.json index 3bcf2b36..4308aa78 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/enum/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/enum/output.json @@ -100,6 +100,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "enum.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/full_features/output.json b/plantuml/parser/puml_parser/tests/class_diagram/full_features/output.json index 307b15ad..170bad08 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/full_features/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/full_features/output.json @@ -189,6 +189,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "full_features.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/interface/output.json b/plantuml/parser/puml_parser/tests/class_diagram/interface/output.json index 4c6b899b..8f869497 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/interface/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/interface/output.json @@ -28,6 +28,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "interface.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/namespace_1/output.json b/plantuml/parser/puml_parser/tests/class_diagram/namespace_1/output.json index 154d3893..f883e56d 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/namespace_1/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/namespace_1/output.json @@ -72,6 +72,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "namespace_1.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/namespace_2/output.json b/plantuml/parser/puml_parser/tests/class_diagram/namespace_2/output.json index 26e12d17..1f247336 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/namespace_2/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/namespace_2/output.json @@ -41,6 +41,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "namespace_2.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/namespace_3/output.json b/plantuml/parser/puml_parser/tests/class_diagram/namespace_3/output.json index 04121b21..cd77ce3c 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/namespace_3/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/namespace_3/output.json @@ -52,6 +52,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "namespace_3.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/one_class/output.json b/plantuml/parser/puml_parser/tests/class_diagram/one_class/output.json index 93986436..aa35f56f 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/one_class/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/one_class/output.json @@ -23,6 +23,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "one_class.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/only_attribute/output.json b/plantuml/parser/puml_parser/tests/class_diagram/only_attribute/output.json index 306034e9..9e658835 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/only_attribute/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/only_attribute/output.json @@ -30,6 +30,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "only_attribute.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/only_method/output.json b/plantuml/parser/puml_parser/tests/class_diagram/only_method/output.json index 0ea856cd..efd2cccf 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/only_method/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/only_method/output.json @@ -32,6 +32,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "only_method.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/package/output.json b/plantuml/parser/puml_parser/tests/class_diagram/package/output.json index c0d7f051..de86e43f 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/package/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/package/output.json @@ -91,6 +91,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "package.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/param/output.json b/plantuml/parser/puml_parser/tests/class_diagram/param/output.json index b936cfbb..bb3ed1d5 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/param/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/param/output.json @@ -43,6 +43,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "param.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/param_templete/output.json b/plantuml/parser/puml_parser/tests/class_diagram/param_templete/output.json index 7d730961..d3718d1f 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/param_templete/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/param_templete/output.json @@ -40,6 +40,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "param_templete.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/relationship_arrows/output.json b/plantuml/parser/puml_parser/tests/class_diagram/relationship_arrows/output.json index 9ba94360..32ec44a1 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/relationship_arrows/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/relationship_arrows/output.json @@ -63,6 +63,7 @@ }, "label": null } - ] + ], + "source_file": "relationship_arrows.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/relationship_inheritance/output.json b/plantuml/parser/puml_parser/tests/class_diagram/relationship_inheritance/output.json index 5195b582..409e716c 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/relationship_inheritance/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/relationship_inheritance/output.json @@ -33,6 +33,7 @@ }, "label": null } - ] + ], + "source_file": "relationship_inheritance.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/relationship_mix_inher/output.json b/plantuml/parser/puml_parser/tests/class_diagram/relationship_mix_inher/output.json index f56131ea..a43657f5 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/relationship_mix_inher/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/relationship_mix_inher/output.json @@ -33,6 +33,7 @@ }, "label": null } - ] + ], + "source_file": "relationship_mix_inher.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/relationship_normal/output.json b/plantuml/parser/puml_parser/tests/class_diagram/relationship_normal/output.json index c2bff09c..30bd2c6f 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/relationship_normal/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/relationship_normal/output.json @@ -16,6 +16,7 @@ }, "label": null } - ] + ], + "source_file": "relationship_normal.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/relationship_qualified_id/output.json b/plantuml/parser/puml_parser/tests/class_diagram/relationship_qualified_id/output.json index 3c7a1eb1..440d9b97 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/relationship_qualified_id/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/relationship_qualified_id/output.json @@ -18,6 +18,7 @@ }, "label": null } - ] + ], + "source_file": "relationship_qualified_id.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/stereotype_definition/output.json b/plantuml/parser/puml_parser/tests/class_diagram/stereotype_definition/output.json index f1294214..2bd877a3 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/stereotype_definition/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/stereotype_definition/output.json @@ -112,6 +112,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "stereotype_definition.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/stereotype_relationship/output.json b/plantuml/parser/puml_parser/tests/class_diagram/stereotype_relationship/output.json index c5ca50f8..033821e4 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/stereotype_relationship/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/stereotype_relationship/output.json @@ -59,6 +59,7 @@ }, "label": "<>" } - ] + ], + "source_file": "stereotype_relationship.puml" } } diff --git a/plantuml/parser/puml_parser/tests/class_diagram/struct/output.json b/plantuml/parser/puml_parser/tests/class_diagram/struct/output.json index b140d43d..a5f23eff 100644 --- a/plantuml/parser/puml_parser/tests/class_diagram/struct/output.json +++ b/plantuml/parser/puml_parser/tests/class_diagram/struct/output.json @@ -89,6 +89,7 @@ } } ], - "relationships": [] + "relationships": [], + "source_file": "struct.puml" } } diff --git a/plantuml/parser/puml_resolver/src/class_diagram/src/class_resolver.rs b/plantuml/parser/puml_resolver/src/class_diagram/src/class_resolver.rs index eb7063e2..7ca7a720 100644 --- a/plantuml/parser/puml_resolver/src/class_diagram/src/class_resolver.rs +++ b/plantuml/parser/puml_resolver/src/class_diagram/src/class_resolver.rs @@ -158,11 +158,11 @@ impl ClassResolver { } fn current_source_file(&self) -> Option { - if self.logic.name.is_empty() { - None - } else { - Some(self.logic.name.clone()) - } + self.logic + .source_files + .first() + .filter(|source_file| !source_file.is_empty()) + .cloned() } fn register_entity_names(&mut self, name: &Name, id: &str) { @@ -717,7 +717,7 @@ impl DiagramResolver for ClassResolver { self.name_map.clear(); self.logic.name = document.name.clone(); - self.logic.source_files.push(document.name.clone()); + self.logic.source_files.push(document.source_file.clone()); self.analyze(document)?; @@ -1053,6 +1053,7 @@ mod tests { let file = ClassUmlFile { name: "test".to_string(), + source_file: "test.puml".to_string(), elements: vec![ClassUmlTopLevel::Types(make_class("User"))], relationships: vec![], }; @@ -1062,7 +1063,7 @@ mod tests { assert_eq!(logic.entities.len(), 1); assert_eq!(logic.entities[0].id, "User"); assert!(logic.entities[0].relationships.is_empty()); - assert_eq!(logic.entities[0].source_file.as_deref(), Some("test")); + assert_eq!(logic.entities[0].source_file.as_deref(), Some("test.puml")); } // ---------------------------- From 41f6c2f7ce2d9ce8bc783829eee683e111367a3a Mon Sep 17 00:00:00 2001 From: Melody Ma Date: Wed, 1 Jul 2026 16:34:32 +0800 Subject: [PATCH 3/5] feat(bazel): add unit validation support --- .../rules_score/examples/seooc/unit_2/bar.h | 2 +- .../unit_2/docs/unit_2_class_diagram.puml | 6 ++-- bazel/rules/rules_score/private/unit.bzl | 34 ++++++++++++++++++- .../rules/rules_score/private/validation.bzl | 1 + bazel/rules/rules_score/providers.bzl | 2 ++ 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/bazel/rules/rules_score/examples/seooc/unit_2/bar.h b/bazel/rules/rules_score/examples/seooc/unit_2/bar.h index ce4ac2a5..c5e63243 100644 --- a/bazel/rules/rules_score/examples/seooc/unit_2/bar.h +++ b/bazel/rules/rules_score/examples/seooc/unit_2/bar.h @@ -25,7 +25,7 @@ namespace unit_2 { // SampleComponent.REQ_COMP_005 class Bar final { public: - explicit Bar(std::unique_ptr); + explicit Bar(std::unique_ptr foo); bool AssertNumber() const; private: diff --git a/bazel/rules/rules_score/examples/seooc/unit_2/docs/unit_2_class_diagram.puml b/bazel/rules/rules_score/examples/seooc/unit_2/docs/unit_2_class_diagram.puml index 9a625d1a..a8d71a1e 100644 --- a/bazel/rules/rules_score/examples/seooc/unit_2/docs/unit_2_class_diagram.puml +++ b/bazel/rules/rules_score/examples/seooc/unit_2/docs/unit_2_class_diagram.puml @@ -14,8 +14,7 @@ @startuml unit_2_class_diagram namespace unit_1 { - class Foo { - {final} + class Foo <>{ -- + GetNumber() : uint8_t + SetNumber(value : uint8_t) : void @@ -23,8 +22,7 @@ namespace unit_1 { } namespace unit_2 { - class Bar { - {final} + class Bar <>{ -- - foo_ : unique_ptr -- diff --git a/bazel/rules/rules_score/private/unit.bzl b/bazel/rules/rules_score/private/unit.bzl index 954e15dd..4cc1f7fb 100644 --- a/bazel/rules/rules_score/private/unit.bzl +++ b/bazel/rules/rules_score/private/unit.bzl @@ -27,6 +27,8 @@ load("@rules_rust//rust:defs.bzl", "rust_common") load("//bazel/rules/rules_score:providers.bzl", "CcDependencyInfo", "CertifiedScope", "SphinxSourcesInfo", "UnitDesignInfo", "UnitInfo") load("//cpp/libclang:cpp_parser.bzl", "cpp_parser_action_internal_attrs", "cpp_parser_action_toolchains", "cpp_parser_target_aspects", "has_cpp_parser_inputs", "run_cpp_parser_action") load(":cc_dependency_aspect.bzl", "cc_dependencies_aspect") +load(":validation.bzl", "PROFILES", "VALIDATION_ATTRS", "run_validation") +load(":verbosity.bzl", "VERBOSITY_ATTR", "get_log_level") def _run_implementation_cpp_parser(ctx, impl, output_prefix): return run_cpp_parser_action( @@ -42,6 +44,21 @@ def _target_output_prefix(ctx, target): target_name = target.label.name.replace("/", "_") return "{}_{}_{}".format(ctx.label.name, package_name, target_name) +def _run_validation(ctx, design_class_fbs, implementation_class_fbs): + return run_validation( + ctx = ctx, + validation_cli = ctx.executable._validation_cli, + profile = PROFILES.UNIT, + input_bundle = { + "design_classes": [f.path for f in design_class_fbs], + "implementation_classes": [f.path for f in implementation_class_fbs], + }, + inputs = design_class_fbs + implementation_class_fbs, + mnemonic = "UnitValidate", + maturity = ctx.attr.maturity, + log_level = get_log_level(ctx), + ) + # ============================================================================ # Private Rule Implementation # ============================================================================ @@ -105,9 +122,15 @@ def _unit_impl(ctx): tests_depset = depset(xml_files) + validation_log = _run_validation( + ctx, + design_static_fbs_depset.to_list(), + implementation_class_fbs, + ) + # Combine all files for DefaultInfo all_files = depset( - xml_files + implementation_class_fbs, + xml_files + implementation_class_fbs + [validation_log.file], transitive = [design_depset], ) @@ -119,6 +142,8 @@ def _unit_impl(ctx): unit_design = design_depset, unit_design_static_fbs = design_static_fbs_depset, unit_design_dynamic_fbs = design_dynamic_fbs_depset, + implementation_class_fbs = depset(implementation_class_fbs), + implementation_sequence_fbs = depset(), implementation = depset(ctx.attr.implementation), tests = tests_depset, dependent_labels = depset(transitive = collected_dependent_labels), @@ -155,9 +180,16 @@ _unit_attrs = { cfg = "exec", doc = "Test targets that verify the unit (cc_test, py_test, rust_test, etc.)", ), + "maturity": attr.string( + default = "release", + values = ["release", "development"], + doc = "Maturity level of the unit. 'release' treats validation findings as errors; 'development' emits warnings and continues.", + ), } _unit_attrs.update(cpp_parser_action_internal_attrs()) +_unit_attrs.update(VALIDATION_ATTRS) +_unit_attrs.update(VERBOSITY_ATTR) _unit = rule( implementation = _unit_impl, diff --git a/bazel/rules/rules_score/private/validation.bzl b/bazel/rules/rules_score/private/validation.bzl index 2a008d9e..c960073d 100644 --- a/bazel/rules/rules_score/private/validation.bzl +++ b/bazel/rules/rules_score/private/validation.bzl @@ -16,6 +16,7 @@ PROFILES = struct( ARCHITECTURAL_DESIGN = "architectural-design", DEPENDABLE_ELEMENT = "dependable-element", + UNIT = "unit", ) VALIDATION_ATTRS = { diff --git a/bazel/rules/rules_score/providers.bzl b/bazel/rules/rules_score/providers.bzl index 72128959..0bf78451 100644 --- a/bazel/rules/rules_score/providers.bzl +++ b/bazel/rules/rules_score/providers.bzl @@ -79,6 +79,8 @@ UnitInfo = provider( "unit_design": "Depset of design artifact files (PlantUML diagrams, RST documents, etc.).", "unit_design_static_fbs": "Depset of FlatBuffers binaries generated from static unit_design diagrams.", "unit_design_dynamic_fbs": "Depset of FlatBuffers binaries generated from dynamic unit_design diagrams.", + "implementation_class_fbs": "Depset of FlatBuffers binaries generated from implementation class diagrams.", + "implementation_sequence_fbs": "Depset of FlatBuffers binaries generated from implementation sequence diagrams.", "implementation": "Depset of implementation targets (cc_library, rust_library, etc.).", "tests": "Depset of test targets (cc_test, rust_test, etc.).", "dependent_labels": "Depset of Labels that this unit's implementation depends on transitively (used for certification scope validation).", From c47e40866eaf1a674d20419368375b3bf5f07014 Mon Sep 17 00:00:00 2001 From: Melody Ma Date: Wed, 1 Jul 2026 16:36:04 +0800 Subject: [PATCH 4/5] feat(validation): add class design implementation validator --- validation/core/BUILD | 2 + validation/core/README.md | 4 +- .../core/src/models/class_diagram_models.rs | 116 +- validation/core/src/models/mod.rs | 4 +- validation/core/src/profiles/mod.rs | 5 + validation/core/src/profiles/profile.rs | 9 +- validation/core/src/profiles/unit.rs | 57 + .../class_design_implementation_validator.rs | 1119 +++++++++++++++++ validation/core/src/validators/mod.rs | 2 + 9 files changed, 1312 insertions(+), 6 deletions(-) create mode 100644 validation/core/src/profiles/unit.rs create mode 100644 validation/core/src/validators/class_design_implementation_validator.rs diff --git a/validation/core/BUILD b/validation/core/BUILD index 395bf590..e5b74a03 100644 --- a/validation/core/BUILD +++ b/validation/core/BUILD @@ -42,6 +42,7 @@ rust_library( "src/profiles/dependable_element.rs", "src/profiles/mod.rs", "src/profiles/profile.rs", + "src/profiles/unit.rs", "src/readers/bazel_reader.rs", "src/readers/class_diagram_reader.rs", "src/readers/component_diagram_reader.rs", @@ -50,6 +51,7 @@ rust_library( "src/results/diagnostics.rs", "src/results/mod.rs", "src/validators/bazel_component_validator.rs", + "src/validators/class_design_implementation_validator.rs", "src/validators/component_sequence_validator.rs", "src/validators/mod.rs", "src/validators/test/component_sequence_validator_test.rs", diff --git a/validation/core/README.md b/validation/core/README.md index 36088d77..18787285 100644 --- a/validation/core/README.md +++ b/validation/core/README.md @@ -74,7 +74,7 @@ Supported profiles: |---------|--------|--------------|------------------| | `architectural-design` | Supported | `ArchitecturalDesignInputs` | Design consistency | | `dependable-element` | Supported | `DependableElementInputs` | Bazel architecture consistency | -| `unit` | Placeholder | not read | none; writes `SKIPPED` | +| `unit` | Supported | `UnitInputs` | Unit design/implementation consistency | Profile validators: @@ -86,7 +86,7 @@ Profile validators: - `validate_component_class` (pending) `unit`: -- placeholder +- `validate_class_implementation` Each profile owns its own input schema. diff --git a/validation/core/src/models/class_diagram_models.rs b/validation/core/src/models/class_diagram_models.rs index c0ba27df..0ff926c1 100644 --- a/validation/core/src/models/class_diagram_models.rs +++ b/validation/core/src/models/class_diagram_models.rs @@ -13,15 +13,67 @@ //! Models for class-diagram and internal-API FlatBuffer inputs -use std::collections::BTreeSet; +use std::collections::{BTreeMap, BTreeSet}; -use class_diagram::{ClassDiagram as ClassDiagramInput, EntityType}; +use class_diagram::{ClassDiagram as ClassDiagramInput, EntityType, SimpleEntity}; use crate::ValidationResult; /// Collection of class diagrams loaded from one or more FlatBuffer files. pub type ClassDiagramInputs = Vec; +/// Class-like entities from one or more class diagrams, keyed by lower-case id. +pub struct ClassEntityIndex { + entities: BTreeMap, +} + +impl ClassEntityIndex { + /// Build an index from class diagrams for class implementation validation. + pub fn build_index(diagrams: &[ClassDiagramInput], result: &mut ValidationResult) -> Self { + let mut entities = BTreeMap::new(); + + for diagram in diagrams { + for entity in &diagram.entities { + let indexed_entity = entity.clone(); + + let key = indexed_entity.id.to_lowercase(); + if let Some(prev) = entities.get(&key) { + result.add_failure(format!( + "Duplicate class entity in validation input:\n\ + Key : {key}\n\ + First location : {}\n\ + Second location : {}", + entity_location(prev), + entity_location(&indexed_entity) + )); + } else { + entities.insert(key, indexed_entity); + } + } + } + + Self { entities } + } + + pub fn entities(&self) -> impl Iterator + '_ { + self.entities.values() + } + + pub fn find_by_id(&self, id: &str) -> Option<&SimpleEntity> { + self.entities.get(&id.to_lowercase()) + } +} + +fn entity_location(entity: &SimpleEntity) -> String { + let source_file = entity.source_file.as_deref().unwrap_or("unknown-file"); + let source_line = entity + .source_line + .map(|line| line.to_string()) + .unwrap_or_else(|| "unknown-line".to_string()); + + format!("{source_file}:{source_line}") +} + /// Indexed internal-API data prepared for interface and method validators. pub struct InternalApiInterface { pub id: String, @@ -82,6 +134,66 @@ mod tests { } } + fn entity(id: &str, source_file: Option<&str>, source_line: Option) -> SimpleEntity { + SimpleEntity { + id: id.to_string(), + name: id.rsplit('.').next().unwrap_or(id).to_string(), + enclosing_namespace_id: None, + entity_type: EntityType::Class, + type_aliases: Vec::new(), + variables: Vec::new(), + methods: Vec::new(), + template_parameters: None, + enum_literals: Vec::new(), + relationships: Vec::new(), + source_file: source_file.map(str::to_string), + source_line, + } + } + + #[test] + fn class_entity_index_reports_duplicate_source_locations() { + let diagrams = vec![ClassDiagram { + name: "classes".to_string(), + entities: vec![ + entity("Unit.Sample", Some("design_a.puml"), Some(12)), + entity("unit.sample", Some("design_b.puml"), Some(34)), + ], + relationships: Vec::new(), + source_files: Vec::new(), + version: None, + }]; + + let mut result = ValidationResult::default(); + let _index = ClassEntityIndex::build_index(&diagrams, &mut result); + + assert_eq!(result.failures.len(), 1); + assert!(result.failures[0].contains("Key : unit.sample")); + assert!(result.failures[0].contains("First location : design_a.puml:12")); + assert!(result.failures[0].contains("Second location : design_b.puml:34")); + } + + #[test] + fn class_entity_index_reports_unknown_duplicate_source_locations() { + let diagrams = vec![ClassDiagram { + name: "classes".to_string(), + entities: vec![ + entity("Unit.Sample", None, Some(12)), + entity("unit.sample", Some("design_b.puml"), None), + ], + relationships: Vec::new(), + source_files: Vec::new(), + version: None, + }]; + + let mut result = ValidationResult::default(); + let _index = ClassEntityIndex::build_index(&diagrams, &mut result); + + assert_eq!(result.failures.len(), 1); + assert!(result.failures[0].contains("First location : unknown-file:12")); + assert!(result.failures[0].contains("Second location : design_b.puml:unknown-line")); + } + #[test] fn internal_api_index_collects_interfaces_and_methods() { let diagrams = vec![ClassDiagram { diff --git a/validation/core/src/models/mod.rs b/validation/core/src/models/mod.rs index 583d824d..8996f603 100644 --- a/validation/core/src/models/mod.rs +++ b/validation/core/src/models/mod.rs @@ -24,7 +24,9 @@ use shared::EntityKey; #[cfg(test)] pub use bazel_models::BazelInputEntry; pub use bazel_models::{BazelArchitecture, BazelInput}; -pub use class_diagram_models::{ClassDiagramInputs, InternalApiIndex, InternalApiInterface}; +pub use class_diagram_models::{ + ClassDiagramInputs, ClassEntityIndex, InternalApiIndex, InternalApiInterface, +}; pub use component_diagram_models::{ ComponentDiagramArchitecture, ComponentDiagramElementType, ComponentDiagramInput, ComponentDiagramInputs, ComponentDiagramRelation, diff --git a/validation/core/src/profiles/mod.rs b/validation/core/src/profiles/mod.rs index 895e7f32..8b5517d8 100644 --- a/validation/core/src/profiles/mod.rs +++ b/validation/core/src/profiles/mod.rs @@ -16,14 +16,17 @@ mod architectural_design; mod dependable_element; mod profile; +mod unit; pub use architectural_design::ArchitecturalDesignInputs; pub use dependable_element::DependableElementInputs; pub use profile::{Profile, ProfileRun}; +pub use unit::UnitInputs; pub enum ProfileInputs { ArchitecturalDesign(ArchitecturalDesignInputs), DependableElement(DependableElementInputs), + Unit(UnitInputs), } pub fn read_profile_inputs(profile: Profile, path: &str) -> Result { @@ -34,6 +37,7 @@ pub fn read_profile_inputs(profile: Profile, path: &str) -> Result { profile::read_input_bundle(path).map(ProfileInputs::DependableElement) } + Profile::Unit => profile::read_input_bundle(path).map(ProfileInputs::Unit), } } @@ -45,6 +49,7 @@ pub fn run_profile(profile: Profile, inputs: &ProfileInputs) -> Result { dependable_element::run(inputs) } + (Profile::Unit, ProfileInputs::Unit(inputs)) => unit::run(inputs), _ => Err(format!( "Input bundle does not match validation profile {}", profile.as_str() diff --git a/validation/core/src/profiles/profile.rs b/validation/core/src/profiles/profile.rs index 12620434..3ae38ea5 100644 --- a/validation/core/src/profiles/profile.rs +++ b/validation/core/src/profiles/profile.rs @@ -24,6 +24,8 @@ pub enum Profile { ArchitecturalDesign, #[value(name = "dependable-element")] DependableElement, + #[value(name = "unit")] + Unit, } impl Profile { @@ -31,11 +33,16 @@ impl Profile { match self { Self::ArchitecturalDesign => "architectural-design", Self::DependableElement => "dependable-element", + Self::Unit => "unit", } } pub fn all() -> &'static [Self] { - &[Self::ArchitecturalDesign, Self::DependableElement] + &[ + Self::ArchitecturalDesign, + Self::DependableElement, + Self::Unit, + ] } } diff --git a/validation/core/src/profiles/unit.rs b/validation/core/src/profiles/unit.rs new file mode 100644 index 00000000..aa095f65 --- /dev/null +++ b/validation/core/src/profiles/unit.rs @@ -0,0 +1,57 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +use crate::models::{ClassDiagramInputs, ClassEntityIndex}; +use crate::readers::ClassDiagramReader; +use crate::validators::validate_class_design_implementation; +use crate::ValidationResult; +use serde::Deserialize; + +use super::profile::{merge_results, read_and_convert, ProfileRun}; + +#[derive(Default, Deserialize)] +#[serde(default, deny_unknown_fields)] +pub struct UnitInputs { + design_classes: Vec, + implementation_classes: Vec, +} + +pub fn run(inputs: &UnitInputs) -> Result { + let mut result = ValidationResult::default(); + let design_classes = read_and_convert::( + inputs.design_classes.as_slice(), + &mut result, + |raw: ClassDiagramInputs, errs| ClassEntityIndex::build_index(&raw, errs), + )?; + let implementation_classes = read_and_convert::( + inputs.implementation_classes.as_slice(), + &mut result, + |raw: ClassDiagramInputs, errs| ClassEntityIndex::build_index(&raw, errs), + )?; + + let mut ran_validator = false; + if let (Some(design_classes), Some(implementation_classes)) = + (design_classes.as_ref(), implementation_classes.as_ref()) + { + merge_results( + &mut result, + validate_class_design_implementation(design_classes, implementation_classes), + ); + ran_validator = true; + } + + Ok(ProfileRun { + ran_validator, + result, + }) +} diff --git a/validation/core/src/validators/class_design_implementation_validator.rs b/validation/core/src/validators/class_design_implementation_validator.rs new file mode 100644 index 00000000..c5f9f734 --- /dev/null +++ b/validation/core/src/validators/class_design_implementation_validator.rs @@ -0,0 +1,1119 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +//! Class implementation validation: compare unit design class diagrams with +//! implementation class diagrams produced by the C++ parser. + +use crate::models::ClassEntityIndex; +use crate::ValidationResult; +use class_diagram::{EnumLiteral, MemberVariable, Method, Relationship, SimpleEntity, TypeAlias}; +use std::collections::BTreeMap; + +/// Run design-class-vs-implementation-class validation using indexed inputs. +pub fn validate_class_design_implementation( + design_classes: &ClassEntityIndex, + implementation_classes: &ClassEntityIndex, +) -> ValidationResult { + ClassDesignImplementationValidator::new().run(design_classes, implementation_classes) +} + +struct ClassDesignImplementationValidator { + result: ValidationResult, +} + +impl ClassDesignImplementationValidator { + fn new() -> Self { + Self { + result: ValidationResult::default(), + } + } + + fn run( + mut self, + design_classes: &ClassEntityIndex, + implementation_classes: &ClassEntityIndex, + ) -> ValidationResult { + self.check_design_classes_have_implementation(design_classes, implementation_classes); + self.result + } + + fn check_design_classes_have_implementation( + &mut self, + design_classes: &ClassEntityIndex, + implementation_classes: &ClassEntityIndex, + ) { + for design_entity in design_classes.entities() { + let normalized_design_id = normalize_reference_name(&design_entity.id); + let Some(implementation_entity) = implementation_classes + .find_by_id(&design_entity.id) + .or_else(|| implementation_classes.find_by_id(&normalized_design_id)) + else { + self.result + .add_failure(Self::format_missing_class(design_entity)); + continue; + }; + + self.append_class_comparison_diagnostics(design_entity, implementation_entity); + self.check_entity(design_entity, implementation_entity); + } + } + + fn append_class_comparison_diagnostics( + &mut self, + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, + ) { + self.result + .diagnostics + .debug(|| format_class_comparison_debug(design_entity, implementation_entity)); + self.result + .diagnostics + .trace(|| format_entity_trace("Design entity", design_entity)); + self.result + .diagnostics + .trace(|| format_entity_trace("Implementation entity", implementation_entity)); + } + + fn check_entity(&mut self, design_entity: &SimpleEntity, implementation_entity: &SimpleEntity) { + if design_entity.entity_type != implementation_entity.entity_type { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + "entity_type", + &format!("{:?}", design_entity.entity_type), + &format!("{:?}", implementation_entity.entity_type), + )); + } + + if design_entity.template_parameters != implementation_entity.template_parameters { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + "template_parameters", + &format!("{:?}", design_entity.template_parameters), + &format!("{:?}", implementation_entity.template_parameters), + )); + } + + self.check_type_aliases(design_entity, implementation_entity); + self.check_variables(design_entity, implementation_entity); + self.check_methods(design_entity, implementation_entity); + self.check_enum_literals(design_entity, implementation_entity); + self.check_relationships(design_entity, implementation_entity); + } + + fn check_type_aliases( + &mut self, + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, + ) { + let implementation_aliases = type_alias_map(implementation_entity); + for design_alias in &design_entity.type_aliases { + match implementation_aliases.get(design_alias.alias.as_str()) { + Some(implementation_alias) + if type_aliases_match(design_alias, implementation_alias) => {} + Some(implementation_alias) => self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("type_alias {:?} original_type", design_alias.alias.as_str()), + &design_alias.original_type, + &implementation_alias.original_type, + )), + None => self.result.add_failure(Self::format_missing_member( + design_entity, + "type_alias", + &design_alias.alias, + )), + } + } + } + + fn check_variables( + &mut self, + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, + ) { + let implementation_variables = variable_map(implementation_entity); + for design_variable in &design_entity.variables { + match implementation_variables.get(design_variable.name.as_str()) { + Some(implementation_variable) + if member_variables_match(design_variable, implementation_variable) => {} + Some(implementation_variable) => self.check_variable_fields( + design_entity, + implementation_entity, + design_variable, + implementation_variable, + ), + None => self.result.add_failure(Self::format_missing_member( + design_entity, + "variable", + &design_variable.name, + )), + } + } + } + + fn check_variable_fields( + &mut self, + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, + design_variable: &MemberVariable, + implementation_variable: &MemberVariable, + ) { + let variable_name = &design_variable.name; + + if normalized_optional_type(&design_variable.data_type) + != normalized_optional_type(&implementation_variable.data_type) + { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("variable {variable_name:?} data_type"), + &format!("{:?}", design_variable.data_type), + &format!("{:?}", implementation_variable.data_type), + )); + } + + if design_variable.visibility != implementation_variable.visibility { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("variable {variable_name:?} visibility"), + &format!("{:?}", design_variable.visibility), + &format!("{:?}", implementation_variable.visibility), + )); + } + + if design_variable.is_static != implementation_variable.is_static { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("variable {variable_name:?} is_static"), + &format!("{:?}", design_variable.is_static), + &format!("{:?}", implementation_variable.is_static), + )); + } + } + + fn check_methods( + &mut self, + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, + ) { + let implementation_methods = method_map(implementation_entity); + for design_method in &design_entity.methods { + let key = method_key(design_method); + match implementation_methods.get(key.as_str()) { + Some(implementation_method) + if methods_match(design_method, implementation_method) => {} + Some(implementation_method) => self.check_method_fields( + design_entity, + implementation_entity, + design_method, + implementation_method, + ), + // NOTE: Parameter mismatch diagnostics are emitted only when a same-named + // implementation method is unique. Overloaded methods are left as missing full + // signatures because the validator cannot safely choose a candidate yet. + None => { + match unique_method_index_by_name(implementation_entity, &design_method.name) + .and_then(|index| implementation_entity.methods.get(index)) + { + Some(implementation_method) => self.check_method_fields( + design_entity, + implementation_entity, + design_method, + implementation_method, + ), + None => self.result.add_failure(Self::format_missing_member( + design_entity, + "method", + &key, + )), + } + } + } + } + } + + fn check_method_fields( + &mut self, + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, + design_method: &Method, + implementation_method: &Method, + ) { + let method_name = &design_method.name; + + if normalized_optional_type(&design_method.return_type) + != normalized_optional_type(&implementation_method.return_type) + { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("method {method_name:?} return_type"), + &format!("{:?}", design_method.return_type), + &format!("{:?}", implementation_method.return_type), + )); + } + + if design_method.visibility != implementation_method.visibility { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("method {method_name:?} visibility"), + &format!("{:?}", design_method.visibility), + &format!("{:?}", implementation_method.visibility), + )); + } + + self.check_method_parameter_fields( + design_entity, + implementation_entity, + design_method, + implementation_method, + ); + + if design_method.template_parameters != implementation_method.template_parameters { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("method {method_name:?} template_parameters"), + &format!("{:?}", design_method.template_parameters), + &format!("{:?}", implementation_method.template_parameters), + )); + } + + if design_method.modifiers != implementation_method.modifiers { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("method {method_name:?} modifiers"), + &format!("{:?}", design_method.modifiers), + &format!("{:?}", implementation_method.modifiers), + )); + } + } + + fn check_method_parameter_fields( + &mut self, + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, + design_method: &Method, + implementation_method: &Method, + ) { + let method_name = &design_method.name; + + if design_method.parameters.len() != implementation_method.parameters.len() { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("method {method_name:?} parameter_count"), + &format_parameter_count(&design_method.parameters), + &format_parameter_count(&implementation_method.parameters), + )); + return; + } + + for (design_parameter, implementation_parameter) in design_method + .parameters + .iter() + .zip(&implementation_method.parameters) + { + if design_parameter.name != implementation_parameter.name { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("method {method_name:?} parameter name"), + &format_parameter(design_parameter), + &format_parameter(implementation_parameter), + )); + } + + if normalized_optional_type(&design_parameter.param_type) + != normalized_optional_type(&implementation_parameter.param_type) + { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("method {method_name:?} parameter type"), + &format_parameter(design_parameter), + &format_parameter(implementation_parameter), + )); + } + + if design_parameter.is_variadic != implementation_parameter.is_variadic { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("method {method_name:?} parameter list"), + &format_method_parameters(&design_method.parameters), + &format_method_parameters(&implementation_method.parameters), + )); + } + } + } + + fn check_enum_literals( + &mut self, + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, + ) { + let implementation_literals = enum_literal_map(implementation_entity); + for design_literal in &design_entity.enum_literals { + match implementation_literals.get(design_literal.name.as_str()) { + Some(implementation_literal) if *implementation_literal == design_literal => {} + Some(implementation_literal) => self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + &format!("{:?}", design_literal.name.as_str()), + &format!("{:?}", design_literal), + &format!("{:?}", implementation_literal), + )), + None => self.result.add_failure(Self::format_missing_member( + design_entity, + "enum_literal", + &design_literal.name, + )), + } + } + } + + fn check_relationships( + &mut self, + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, + ) { + let implementation_relationships = relationship_map(implementation_entity); + for design_relationship in &design_entity.relationships { + let key = relationship_key(design_relationship); + let display_name = relationship_display_name(design_relationship); + match implementation_relationships.get(key.as_str()) { + Some(implementation_relationship) + if design_relationship.relation_type + == implementation_relationship.relation_type => {} + Some(implementation_relationship) => { + self.result.add_failure(Self::format_mismatch( + design_entity, + implementation_entity, + "relationship type", + &display_name, + &relationship_display_name(implementation_relationship), + )) + } + None => self.result.add_failure(Self::format_missing_member( + design_entity, + "relationship", + &display_name, + )), + } + } + } + + fn format_missing_class(entity: &SimpleEntity) -> String { + format!( + "Missing implementation class for unit design entity:\n\ + Entity ID : {}\n\ + Design source file : {}\n\ + Design source line : {}\n\ + Required Action : Add a matching implementation class or update the unit design", + entity.id, + design_source_file(entity), + design_source_line(entity), + ) + } + + fn format_missing_member( + design_entity: &SimpleEntity, + member_type: &str, + member_name: &str, + ) -> String { + format!( + "Missing implementation {member_type} for unit design entity:\n\ + Entity ID : {}\n\ + Member : {}\n\ + Design source file : {}\n\ + Design source line : {}\n\ + Required Action : Implement the member or update the unit design", + design_entity.id, + member_name, + design_source_file(design_entity), + design_source_line(design_entity), + ) + } + + fn format_mismatch( + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, + field: &str, + design_value: &str, + implementation_value: &str, + ) -> String { + format!( + "Implementation class data differs from unit design entity:\n\ + Entity ID : {}\n\ + Field : {}\n\ + Design value : {}\n\ + Design source file : {}\n\ + Design source line : {}\n\ + Implement value : {}\n\ + Implement source file : {}\n\ + Implement source line : {}\n\ + Required Action : Align the implementation with the unit design or update the unit design", + design_entity.id, + field, + design_value, + design_source_file(design_entity), + design_source_line(design_entity), + implementation_value, + source_file(implementation_entity), + source_line(implementation_entity) + ) + } +} + +fn design_source_file(entity: &SimpleEntity) -> &str { + source_file(entity) +} + +fn source_file(entity: &SimpleEntity) -> &str { + entity + .source_file + .as_deref() + .filter(|source_file| !source_file.is_empty()) + .unwrap_or("") +} + +fn design_source_line(entity: &SimpleEntity) -> String { + source_line(entity) +} + +fn source_line(entity: &SimpleEntity) -> String { + entity + .source_line + .map(|line| line.to_string()) + .unwrap_or_else(|| "".to_string()) +} + +fn format_class_comparison_debug( + design_entity: &SimpleEntity, + implementation_entity: &SimpleEntity, +) -> String { + format!( + "Comparing design entity {:?} with implementation entity {:?}", + design_entity.id, implementation_entity.id + ) +} + +fn format_entity_trace(label: &str, entity: &SimpleEntity) -> String { + format!( + "{label} {:?} details:\n\ + name={:?}\n\ + namespace={:?}\n\ + type={:?}\n\ + type_aliases={:?}\n\ + variables={:?}\n\ + methods={:?}\n\ + template_parameters={:?}\n\ + enum_literals={:?}\n\ + relationships={:?}", + entity.id, + entity.name, + entity.enclosing_namespace_id, + entity.entity_type, + entity.type_aliases, + entity.variables, + entity.methods, + entity.template_parameters, + entity.enum_literals, + entity.relationships + ) +} + +fn type_alias_map(entity: &SimpleEntity) -> BTreeMap<&str, &TypeAlias> { + entity + .type_aliases + .iter() + .map(|type_alias| (type_alias.alias.as_str(), type_alias)) + .collect() +} + +fn type_aliases_match(design_alias: &TypeAlias, implementation_alias: &TypeAlias) -> bool { + design_alias.alias == implementation_alias.alias + && normalize_type_name(&design_alias.original_type) + == normalize_type_name(&implementation_alias.original_type) +} + +fn variable_map(entity: &SimpleEntity) -> BTreeMap<&str, &MemberVariable> { + entity + .variables + .iter() + .map(|variable| (variable.name.as_str(), variable)) + .collect() +} + +fn member_variables_match( + design_variable: &MemberVariable, + implementation_variable: &MemberVariable, +) -> bool { + design_variable.name == implementation_variable.name + && normalized_optional_type(&design_variable.data_type) + == normalized_optional_type(&implementation_variable.data_type) + && design_variable.visibility == implementation_variable.visibility + && design_variable.is_static == implementation_variable.is_static +} + +fn method_map(entity: &SimpleEntity) -> BTreeMap { + entity + .methods + .iter() + .map(|method| (method_key(method), method)) + .collect() +} + +fn unique_method_index_by_name(entity: &SimpleEntity, method_name: &str) -> Option { + let mut matching_methods = entity + .methods + .iter() + .enumerate() + .filter(|(_, method)| method.name == method_name); + let (index, _) = matching_methods.next()?; + matching_methods.next().is_none().then_some(index) +} + +fn methods_match(design_method: &Method, implementation_method: &Method) -> bool { + design_method.name == implementation_method.name + && normalized_optional_type(&design_method.return_type) + == normalized_optional_type(&implementation_method.return_type) + && design_method.visibility == implementation_method.visibility + && parameters_match(&design_method.parameters, &implementation_method.parameters) + && design_method.template_parameters == implementation_method.template_parameters + && design_method.modifiers == implementation_method.modifiers +} + +fn parameters_match( + design_parameters: &[class_diagram::FunctionArgument], + implementation_parameters: &[class_diagram::FunctionArgument], +) -> bool { + design_parameters.len() == implementation_parameters.len() + && design_parameters.iter().zip(implementation_parameters).all( + |(design_parameter, implementation_parameter)| { + design_parameter.name == implementation_parameter.name + && normalized_optional_type(&design_parameter.param_type) + == normalized_optional_type(&implementation_parameter.param_type) + && design_parameter.is_variadic == implementation_parameter.is_variadic + }, + ) +} + +fn method_key(method: &Method) -> String { + let parameter_types = method + .parameters + .iter() + .map(|parameter| { + let variadic = if parameter.is_variadic { "..." } else { "" }; + format!( + "{}{}", + parameter + .param_type + .as_deref() + .map(normalize_type_name) + .unwrap_or_default(), + variadic + ) + }) + .collect::>() + .join(", "); + format!("{}({})", method.name, parameter_types) +} + +fn format_parameter_type(type_name: &Option) -> String { + type_name + .as_deref() + .map(normalize_type_name) + .unwrap_or_else(|| "".to_string()) +} + +fn format_parameter(parameter: &class_diagram::FunctionArgument) -> String { + if parameter.name.is_empty() { + format_parameter_type(¶meter.param_type) + } else { + format!( + "{}: {}", + parameter.name, + format_parameter_type(¶meter.param_type), + ) + } +} + +fn format_parameter_list(parameters: &[class_diagram::FunctionArgument]) -> String { + let mut parts = Vec::new(); + for parameter in parameters { + parts.push(format_parameter(parameter)); + if parameter.is_variadic { + parts.push("...".to_string()); + } + } + parts.join(", ") +} + +fn format_method_parameters(parameters: &[class_diagram::FunctionArgument]) -> String { + format!("({})", format_parameter_list(parameters)) +} + +fn format_parameter_count(parameters: &[class_diagram::FunctionArgument]) -> String { + let count = parameters.len(); + let label = if count == 1 { + "parameter" + } else { + "parameters" + }; + format!( + "{} {} {}", + count, + label, + format_method_parameters(parameters) + ) +} + +fn normalized_optional_type(type_name: &Option) -> Option { + type_name.as_deref().map(normalize_type_name) +} + +fn normalize_type_name(type_name: &str) -> String { + normalize_reference_name( + &type_name + .trim() + .replace("std::", "") + .replace(" *", "*") + .replace(" &", "&"), + ) +} + +fn normalize_reference_name(reference: &str) -> String { + // TODO: Remove this workaround once class diagram and implementation parser UIDs use the same namespace separator. + reference.trim().replace('.', "::") +} + +fn enum_literal_map(entity: &SimpleEntity) -> BTreeMap<&str, &EnumLiteral> { + entity + .enum_literals + .iter() + .map(|literal| (literal.name.as_str(), literal)) + .collect() +} + +fn relationship_map(entity: &SimpleEntity) -> BTreeMap { + entity + .relationships + .iter() + .map(|relationship| (relationship_key(relationship), relationship)) + .collect() +} + +fn relationship_key(relationship: &Relationship) -> String { + format!( + "{} -> {}", + normalize_reference_name(&relationship.source), + normalize_reference_name(&relationship.target) + ) +} + +fn relationship_display_name(relationship: &Relationship) -> String { + format!( + "{} -> {:?} -> {}", + normalize_reference_name(&relationship.source), + relationship.relation_type, + normalize_reference_name(&relationship.target) + ) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::models::ClassDiagramInputs; + use class_diagram::{ + ClassDiagram, EntityType, FunctionArgument, MemberVariable, Method, RelationType, + Relationship, SimpleEntity, Visibility, + }; + use std::sync::Once; + + struct TestLogger; + + impl log::Log for TestLogger { + fn enabled(&self, _metadata: &log::Metadata<'_>) -> bool { + true + } + + fn log(&self, _record: &log::Record<'_>) {} + + fn flush(&self) {} + } + + static LOGGER: TestLogger = TestLogger; + static INIT_LOGGER: Once = Once::new(); + + fn enable_trace_diagnostics() { + INIT_LOGGER.call_once(|| { + let _ = log::set_logger(&LOGGER); + }); + log::set_max_level(log::LevelFilter::Trace); + } + + fn method(name: &str) -> Method { + Method { + name: name.to_string(), + return_type: None, + visibility: Visibility::Public, + parameters: Vec::new(), + template_parameters: None, + modifiers: Vec::new(), + } + } + + fn method_with_return_type(name: &str, return_type: &str) -> Method { + Method { + return_type: Some(return_type.to_string()), + ..method(name) + } + } + + fn method_with_parameter_types(name: &str, parameter_types: &[&str]) -> Method { + Method { + parameters: parameter_types + .iter() + .map(|parameter_type| FunctionArgument { + name: String::new(), + param_type: Some((*parameter_type).to_string()), + is_variadic: false, + }) + .collect(), + ..method(name) + } + } + + fn parameter(name: &str, param_type: &str, is_variadic: bool) -> FunctionArgument { + FunctionArgument { + name: name.to_string(), + param_type: Some(param_type.to_string()), + is_variadic, + } + } + + fn entity(id: &str, methods: Vec<&str>) -> SimpleEntity { + entity_in_namespace(id, None, methods) + } + + fn variable(name: &str, data_type: &str) -> MemberVariable { + MemberVariable { + name: name.to_string(), + data_type: Some(data_type.to_string()), + visibility: Visibility::Private, + is_static: false, + } + } + + fn relationship(source: &str, target: &str, relation_type: RelationType) -> Relationship { + Relationship { + source: source.to_string(), + target: target.to_string(), + relation_type, + source_multiplicity: None, + target_multiplicity: None, + } + } + + fn entity_in_namespace( + id: &str, + enclosing_namespace_id: Option<&str>, + methods: Vec<&str>, + ) -> SimpleEntity { + SimpleEntity { + id: id.to_string(), + name: id.rsplit('.').next().unwrap_or(id).to_string(), + enclosing_namespace_id: enclosing_namespace_id.map(str::to_string), + entity_type: EntityType::Class, + type_aliases: Vec::new(), + variables: Vec::new(), + methods: methods.into_iter().map(method).collect(), + template_parameters: None, + enum_literals: Vec::new(), + relationships: Vec::new(), + source_file: None, + source_line: None, + } + } + + fn index(entities: Vec) -> ClassEntityIndex { + let diagrams: ClassDiagramInputs = vec![ClassDiagram { + name: "unit".to_string(), + entities, + relationships: Vec::new(), + source_files: Vec::new(), + version: None, + }]; + ClassEntityIndex::build_index(&diagrams, &mut ValidationResult::default()) + } + + #[test] + fn method_key_normalizes_parameter_types_and_marks_variadic_parameters() { + let mut method = method("dispatch"); + method.parameters = vec![ + parameter("mode", "std::uint8_t", false), + parameter("args", "vehicle.Payload", true), + ]; + + assert_eq!( + method_key(&method), + "dispatch(uint8_t, vehicle::Payload...)" + ); + } + + #[test] + fn method_parameter_formatting_includes_count_names_types_and_variadic_marker() { + let parameters = vec![ + parameter("mode", "int", false), + parameter("args", "std::uint8_t", true), + ]; + + assert_eq!( + format_parameter_count(¶meters), + "2 parameters (mode: int, args: uint8_t, ...)" + ); + } + + #[test] + fn relationship_helpers_normalize_namespace_separators() { + let relationship = relationship( + "vehicle.Engine", + "vehicle.Manufacturer", + RelationType::Composition, + ); + + assert_eq!( + relationship_key(&relationship), + "vehicle::Engine -> vehicle::Manufacturer" + ); + assert_eq!( + relationship_display_name(&relationship), + "vehicle::Engine -> Composition -> vehicle::Manufacturer" + ); + } + + #[test] + fn type_name_normalization_ignores_pointer_and_reference_spacing() { + assert_eq!(normalize_type_name("std::uint8_t *"), "uint8_t*"); + assert_eq!( + normalize_type_name("vehicle.Payload &"), + "vehicle::Payload&" + ); + } + + #[test] + fn class_implementation_validation_passes_when_design_class_and_methods_exist() { + let design = index(vec![entity("Sample", vec!["run"])]); + let implementation = index(vec![entity("sample", vec!["run", "helper"])]); + + let result = validate_class_design_implementation(&design, &implementation); + + assert!( + result.is_empty(), + "Expected pass, got: {:?}", + result.failures + ); + } + + #[test] + fn class_implementation_validation_reports_missing_class() { + let design = index(vec![entity("Sample", vec!["run"])]); + let implementation = index(vec![]); + + let result = validate_class_design_implementation(&design, &implementation); + + assert!(result + .failures + .iter() + .any(|message| message.contains("Missing implementation class"))); + } + + #[test] + fn class_implementation_validation_reports_missing_method() { + let design = index(vec![entity("Sample", vec!["run"])]); + let implementation = index(vec![entity("Sample", vec!["init"])]); + + let result = validate_class_design_implementation(&design, &implementation); + + assert!(result + .failures + .iter() + .any(|message| message.contains("Missing implementation method"))); + } + + #[test] + fn class_implementation_validation_ignores_std_prefix_for_method_return_type() { + let mut design_entity = entity("Sample", vec![]); + design_entity.methods = vec![method_with_return_type("GetNumber", "uint8_t")]; + let mut implementation_entity = entity("Sample", vec![]); + implementation_entity.methods = vec![method_with_return_type("GetNumber", "std::uint8_t")]; + + let design = index(vec![design_entity]); + let implementation = index(vec![implementation_entity]); + + let result = validate_class_design_implementation(&design, &implementation); + + assert!( + result.is_empty(), + "Expected pass, got: {:?}", + result.failures + ); + } + + #[test] + fn class_implementation_validation_reports_variable_mismatch() { + let mut design_entity = entity("Sample", vec![]); + design_entity.variables = vec![variable("value_", "uint8_t")]; + let mut implementation_entity = entity("Sample", vec![]); + implementation_entity.variables = vec![variable("value_", "uint16_t")]; + + let design = index(vec![design_entity]); + let implementation = index(vec![implementation_entity]); + + let result = validate_class_design_implementation(&design, &implementation); + + assert!(result.failures.iter().any(|message| { + message.contains("Implementation class data differs") + && message.contains("variable \"value_\" data_type") + })); + } + + #[test] + fn class_implementation_validation_reports_parameter_mismatch_for_unique_same_name_method() { + let mut design_entity = entity("Sample", vec![]); + design_entity.methods = vec![method_with_parameter_types("stop", &["int", "int"])]; + let mut implementation_entity = entity("Sample", vec![]); + implementation_entity.methods = + vec![method_with_parameter_types("stop", &["int", "double"])]; + + let design = index(vec![design_entity]); + let implementation = index(vec![implementation_entity]); + + let result = validate_class_design_implementation(&design, &implementation); + + assert!(result.failures.iter().any(|message| { + message.contains("method \"stop\" parameter type") + && message.contains("int") + && message.contains("double") + })); + assert!(result + .failures + .iter() + .all(|message| !message.contains("Missing implementation method"))); + } + + #[test] + fn class_implementation_validation_normalizes_namespace_separator_for_relationships() { + let mut design_entity = entity("vehicle.Engine", vec![]); + design_entity.relationships = vec![relationship( + "vehicle.Engine", + "vehicle.Manufacturer", + RelationType::Composition, + )]; + let mut implementation_entity = entity("vehicle::Engine", vec![]); + implementation_entity.relationships = vec![relationship( + "vehicle::Engine", + "vehicle::Manufacturer", + RelationType::Composition, + )]; + + let design = index(vec![design_entity]); + let implementation = index(vec![implementation_entity]); + + let result = validate_class_design_implementation(&design, &implementation); + + assert!( + result.is_empty(), + "Expected pass, got: {:?}", + result.failures + ); + } + + #[test] + fn class_implementation_validation_matches_exact_overloaded_method_signature() { + let mut design_entity = entity("Sample", vec![]); + design_entity.methods = vec![method_with_parameter_types("stop", &["int", "int"])]; + let mut implementation_entity = entity("Sample", vec![]); + implementation_entity.methods = vec![ + method_with_parameter_types("stop", &["int", "double"]), + method_with_parameter_types("stop", &["int", "int"]), + ]; + + let design = index(vec![design_entity]); + let implementation = index(vec![implementation_entity]); + + let result = validate_class_design_implementation(&design, &implementation); + + assert!( + result.is_empty(), + "Expected pass, got: {:?}", + result.failures + ); + } + + #[test] + fn class_implementation_validation_does_not_guess_between_overloaded_methods() { + let mut design_entity = entity("Sample", vec![]); + design_entity.methods = vec![method_with_parameter_types("stop", &["int", "int"])]; + let mut implementation_entity = entity("Sample", vec![]); + implementation_entity.methods = vec![ + method_with_parameter_types("stop", &["int", "double"]), + method_with_parameter_types("stop", &["int", "int", "bool"]), + ]; + + let design = index(vec![design_entity]); + let implementation = index(vec![implementation_entity]); + + let result = validate_class_design_implementation(&design, &implementation); + + assert!(result.failures.iter().any(|message| { + message.contains("Missing implementation method") && message.contains("stop(int, int)") + })); + assert!(result + .failures + .iter() + .all(|message| !message.contains("parameter type") + && !message.contains("parameter_count"))); + } + + #[test] + fn class_implementation_validation_keeps_failures_and_diagnostics_separate() { + enable_trace_diagnostics(); + + let mut design_entity = entity("Sample", vec![]); + design_entity.variables = vec![variable("value_", "uint8_t")]; + let mut implementation_entity = entity("Sample", vec![]); + implementation_entity.variables = vec![variable("value_", "uint16_t")]; + + let design = index(vec![design_entity]); + let implementation = index(vec![implementation_entity]); + + let result = validate_class_design_implementation(&design, &implementation); + let diagnostics = result.diagnostics.render(); + + assert!(result + .failures + .iter() + .any(|message| message.contains("Implementation class data differs"))); + assert!(diagnostics.contains("Comparing design entity")); + assert!(!diagnostics.contains("Implementation class data differs")); + } +} diff --git a/validation/core/src/validators/mod.rs b/validation/core/src/validators/mod.rs index 94cf983d..1b068efa 100644 --- a/validation/core/src/validators/mod.rs +++ b/validation/core/src/validators/mod.rs @@ -14,7 +14,9 @@ //! Validator entrypoints for architecture checks. mod bazel_component_validator; +mod class_design_implementation_validator; mod component_sequence_validator; pub use bazel_component_validator::validate_bazel_component; +pub use class_design_implementation_validator::validate_class_design_implementation; pub use component_sequence_validator::validate_component_sequence; From a7f99530eab315d4c98d67af20d6d7e1e619371d Mon Sep 17 00:00:00 2001 From: Melody Ma Date: Wed, 1 Jul 2026 16:51:53 +0800 Subject: [PATCH 5/5] test(validation): cover class design implementation validation --- validation/core/integration_test/BUILD | 97 +-------- validation/core/integration_test/README.md | 121 +++++++----- .../integration_test/bazel_component/BUILD | 43 ++++ .../bazel_component_suite.rs | 0 .../class_design_implementation/BUILD | 62 ++++++ .../class_design_implementation_suite.rs | 186 ++++++++++++++++++ .../negative_class_member_missing/BUILD | 54 +++++ .../class_diagram.puml | 26 +++ .../expected.yaml | 20 ++ .../transport.cpp | 21 ++ .../negative_class_missing/BUILD | 54 +++++ .../negative_class_missing/class_diagram.puml | 28 +++ .../negative_class_missing/expected.yaml | 19 ++ .../negative_class_missing/transport.cpp | 26 +++ .../negative_entity_type_mismatch/BUILD | 54 +++++ .../class_diagram.puml | 16 ++ .../expected.yaml | 24 +++ .../transport.cpp | 16 ++ .../negative_enum_literal_mismatch/BUILD | 46 +++++ .../class_diagram.puml | 11 ++ .../expected.yaml | 24 +++ .../transport.cpp | 10 + .../negative_enum_literal_missing/BUILD | 46 +++++ .../class_diagram.puml | 11 ++ .../expected.yaml | 20 ++ .../transport.cpp | 9 + .../negative_method_mismatch/BUILD | 46 +++++ .../class_diagram.puml | 10 + .../negative_method_mismatch/expected.yaml | 24 +++ .../negative_method_mismatch/transport.cpp | 9 + .../negative_method_missing/BUILD | 46 +++++ .../class_diagram.puml | 10 + .../negative_method_missing/expected.yaml | 20 ++ .../negative_method_missing/transport.cpp | 8 + .../negative_method_modifier_mismatch/BUILD | 46 +++++ .../class_diagram.puml | 10 + .../expected.yaml | 15 ++ .../transport.cpp | 9 + .../BUILD | 46 +++++ .../class_diagram.puml | 10 + .../expected.yaml | 15 ++ .../transport.cpp | 9 + .../BUILD | 46 +++++ .../class_diagram.puml | 10 + .../expected.yaml | 24 +++ .../transport.cpp | 9 + .../BUILD | 46 +++++ .../class_diagram.puml | 10 + .../expected.yaml | 24 +++ .../transport.cpp | 9 + .../BUILD | 46 +++++ .../class_diagram.puml | 10 + .../expected.yaml | 24 +++ .../transport.cpp | 9 + .../negative_method_visibility_mismatch/BUILD | 46 +++++ .../class_diagram.puml | 10 + .../expected.yaml | 24 +++ .../transport.cpp | 10 + .../negative_relationship_missing/BUILD | 46 +++++ .../class_diagram.puml | 11 ++ .../expected.yaml | 20 ++ .../transport.cpp | 12 ++ .../negative_relationship_type_mismatch/BUILD | 54 +++++ .../class_diagram.puml | 22 +++ .../expected.yaml | 24 +++ .../transport.cpp | 21 ++ .../BUILD | 46 +++++ .../class_diagram.puml | 8 + .../expected.yaml | 24 +++ .../transport.cpp | 9 + .../negative_type_alias_mismatch/BUILD | 46 +++++ .../class_diagram.puml | 10 + .../expected.yaml | 24 +++ .../transport.cpp | 12 ++ .../negative_type_alias_missing/BUILD | 46 +++++ .../class_diagram.puml | 10 + .../negative_type_alias_missing/expected.yaml | 20 ++ .../negative_type_alias_missing/transport.cpp | 8 + .../negative_variable_mismatch/BUILD | 54 +++++ .../class_diagram.puml | 10 + .../negative_variable_mismatch/expected.yaml | 24 +++ .../negative_variable_mismatch/transport.cpp | 9 + .../negative_variable_static_mismatch/BUILD | 46 +++++ .../class_diagram.puml | 10 + .../expected.yaml | 24 +++ .../transport.cpp | 9 + .../BUILD | 46 +++++ .../class_diagram.puml | 10 + .../expected.yaml | 24 +++ .../transport.cpp | 10 + .../positive_class_features/BUILD | 46 +++++ .../class_diagram.puml | 34 ++++ .../positive_class_features/expected.yaml | 13 ++ .../positive_class_features/transport.cpp | 46 +++++ .../positive_method_features/BUILD | 46 +++++ .../class_diagram.puml | 17 ++ .../positive_method_features/expected.yaml | 13 ++ .../positive_method_features/transport.cpp | 23 +++ .../BUILD | 46 +++++ .../class_diagram.puml | 10 + .../expected.yaml | 13 ++ .../transport.cpp | 21 ++ .../positive_relationship_features/BUILD | 46 +++++ .../class_diagram.puml | 21 ++ .../expected.yaml | 13 ++ .../transport.cpp | 32 +++ .../positive_variable_features/BUILD | 46 +++++ .../class_diagram.puml | 18 ++ .../positive_variable_features/expected.yaml | 13 ++ .../positive_variable_features/transport.cpp | 20 ++ .../integration_test/component_class/BUILD | 44 +++++ .../component_class_suite.rs | 0 .../integration_test/component_sequence/BUILD | 49 +++++ .../component_sequence_suite.rs | 0 .../core/integration_test/puml_fixture.bzl | 23 ++- validation/core/integration_test/src/lib.rs | 3 +- .../integration_test/src/test_framework.rs | 32 ++- 117 files changed, 3024 insertions(+), 147 deletions(-) create mode 100644 validation/core/integration_test/bazel_component/BUILD rename validation/core/integration_test/{src => bazel_component}/bazel_component_suite.rs (100%) create mode 100644 validation/core/integration_test/class_design_implementation/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/class_design_implementation_suite.rs create mode 100644 validation/core/integration_test/class_design_implementation/negative_class_member_missing/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_class_member_missing/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_class_member_missing/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_class_member_missing/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_class_missing/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_class_missing/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_class_missing/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_class_missing/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_missing/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_missing/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_missing/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_missing/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_relationship_missing/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_relationship_missing/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_relationship_missing/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_relationship_missing/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_type_alias_missing/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_type_alias_missing/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_type_alias_missing/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_type_alias_missing/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/positive_class_features/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/positive_class_features/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/positive_class_features/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/positive_class_features/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/positive_method_features/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/positive_method_features/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/positive_method_features/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/positive_method_features/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/positive_relationship_features/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/positive_relationship_features/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/positive_relationship_features/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/positive_relationship_features/transport.cpp create mode 100644 validation/core/integration_test/class_design_implementation/positive_variable_features/BUILD create mode 100644 validation/core/integration_test/class_design_implementation/positive_variable_features/class_diagram.puml create mode 100644 validation/core/integration_test/class_design_implementation/positive_variable_features/expected.yaml create mode 100644 validation/core/integration_test/class_design_implementation/positive_variable_features/transport.cpp create mode 100644 validation/core/integration_test/component_class/BUILD rename validation/core/integration_test/{src => component_class}/component_class_suite.rs (100%) create mode 100644 validation/core/integration_test/component_sequence/BUILD rename validation/core/integration_test/{src => component_sequence}/component_sequence_suite.rs (100%) diff --git a/validation/core/integration_test/BUILD b/validation/core/integration_test/BUILD index 672347e9..8155f31c 100644 --- a/validation/core/integration_test/BUILD +++ b/validation/core/integration_test/BUILD @@ -11,52 +11,7 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") - -filegroup( - name = "bazel_component_test_data", - srcs = [ - "//validation/core/integration_test/bazel_component/negative_extra_component:case_data", - "//validation/core/integration_test/bazel_component/negative_extra_unit:case_data", - "//validation/core/integration_test/bazel_component/negative_missing_component:case_data", - "//validation/core/integration_test/bazel_component/negative_missing_unit:case_data", - "//validation/core/integration_test/bazel_component/negative_wrong_stereotype:case_data", - "//validation/core/integration_test/bazel_component/positive_case_insensitive:case_data", - "//validation/core/integration_test/bazel_component/positive_component:case_data", - ], -) - -filegroup( - name = "component_class_test_data", - srcs = [ - "//validation/core/integration_test/component_class/negative_boundary_mismatch:case_data", - "//validation/core/integration_test/component_class/negative_case_sensitive_mismatch:case_data", - "//validation/core/integration_test/component_class/negative_missing_namespace_coverage:case_data", - "//validation/core/integration_test/component_class/negative_multi_class_files_with_mismatch:case_data", - "//validation/core/integration_test/component_class/positive_exact_match:case_data", - "//validation/core/integration_test/component_class/positive_multi_class_files:case_data", - "//validation/core/integration_test/component_class/positive_suffix_match:case_data", - ], -) - -filegroup( - name = "component_sequence_test_data", - srcs = [ - "//validation/core/integration_test/component_sequence/negative_interface_function_not_exercised:case_data", - "//validation/core/integration_test/component_sequence/negative_invalid_consumer_provider_direction:case_data", - "//validation/core/integration_test/component_sequence/negative_method_missing_from_internal_api:case_data", - "//validation/core/integration_test/component_sequence/negative_missing_interface_connection_for_sequence_connected_units:case_data", - "//validation/core/integration_test/component_sequence/negative_missing_method_in_related_interface:case_data", - "//validation/core/integration_test/component_sequence/negative_missing_participant:case_data", - "//validation/core/integration_test/component_sequence/negative_missing_sequence_interaction_for_interface_connected_units:case_data", - "//validation/core/integration_test/component_sequence/negative_missing_unit_interface_relation:case_data", - "//validation/core/integration_test/component_sequence/negative_mixed_mismatch:case_data", - "//validation/core/integration_test/component_sequence/negative_orphan_participant:case_data", - "//validation/core/integration_test/component_sequence/positive_exact_match:case_data", - "//validation/core/integration_test/component_sequence/positive_internal_api_method_match:case_data", - "//validation/core/integration_test/component_sequence/positive_self_call_method_match:case_data", - ], -) +load("@rules_rust//rust:defs.bzl", "rust_library") rust_library( name = "test_framework", @@ -70,54 +25,6 @@ rust_library( "//validation/core:validation", "@crates//:serde", "@crates//:serde_json", - ], -) - -rust_test( - name = "bazel_component_integration_test", - srcs = ["src/bazel_component_suite.rs"], - crate_root = "src/bazel_component_suite.rs", - data = [ - ":bazel_component_test_data", - "//validation/core:validation_cli", - ], - deps = [ - ":test_framework", - "//validation/core:validation", - "@crates//:serde", - "@crates//:serde_json", - ], -) - -rust_test( - name = "component_class_integration_test", - srcs = ["src/component_class_suite.rs"], - crate_root = "src/component_class_suite.rs", - data = [ - ":component_class_test_data", - "//validation/core:validation_cli", - ], - deps = [ - ":test_framework", - "//tools/metamodel/class:class_diagram", - "//validation/core:validation", - "@crates//:serde", - "@crates//:serde_json", - ], -) - -rust_test( - name = "component_sequence_integration_test", - srcs = ["src/component_sequence_suite.rs"], - crate_root = "src/component_sequence_suite.rs", - data = [ - ":component_sequence_test_data", - "//validation/core:validation_cli", - ], - deps = [ - ":test_framework", - "//validation/core:validation", - "@crates//:serde", - "@crates//:serde_json", + "@crates//:serde_yaml", ], ) diff --git a/validation/core/integration_test/README.md b/validation/core/integration_test/README.md index a4f6aa7c..a37593cd 100644 --- a/validation/core/integration_test/README.md +++ b/validation/core/integration_test/README.md @@ -15,20 +15,21 @@ End-to-end tests for the `validation_cli` binary. Each test case feeds real PlantUML diagrams through the full pipeline — PlantUML parser → FlatBuffers -binary → validation CLI — and asserts the outcome against a JSON fixture. +binary → validation CLI — and asserts the outcome against a JSON/YAML fixture. ## Directory structure ``` integration_test/ -├── BUILD # test binaries + aggregated filegroups +├── BUILD # shared Rust test framework library ├── puml_fixture.bzl # Starlark rule: provider → category dirs -├── src/ +├── bazel_component/ # BazelComponent suite, cases, and test binary +├── component_class/ # ComponentClass suite, cases, and test binary +├── component_sequence/ # ComponentSequence suite, cases, and test binary +├── class_design_implementation/ # ClassDesignImplementation suite, cases, and test binary +├── src/ # Rust crate sources for shared test_framework │ ├── lib.rs # re-exports from test_framework -│ ├── test_framework.rs # shared helpers (CLI runner, assertions) -│ ├── bazel_component_suite.rs # tests for BazelComponent validator -│ ├── component_class_suite.rs # tests for ComponentClass validator -│ └── component_sequence_suite.rs # tests for ComponentSequence validator +│ └── test_framework.rs # shared helpers (CLI runner, assertions) ``` ## How it works @@ -37,15 +38,16 @@ The framework has three layers. ### Layer 1 — PlantUML parsing (Bazel rules) -Each test case BUILD calls the real production rules (`architectural_design`, -`unit_design`) on its `.puml` source files. Bazel runs the `puml_parser` binary -as a cached action and stores the result as a FlatBuffers binary (`.fbs.bin`). -The output is exposed through providers: +Each test case BUILD calls the real production rules, such as +`architectural_design`, `unit_design`, or `unit`, on its source files. Bazel +runs the parser actions and stores the result as FlatBuffers binaries +(`.fbs.bin`). The output is exposed through providers: | Rule | Provider | Fields used | |------|----------|-------------| | `architectural_design` | `ArchitecturalDesignInfo` | `static` (component), `dynamic` (sequence), `internal_api` (internal API) | -| `unit_design` | `UnitDesignInfo` | `static` (class), `dynamic` (sequence) | +| `unit_design` | `UnitDesignInfo` | `static` (unit design class), `dynamic` (unit design sequence) | +| `unit` | `UnitInfo` | `implementation_class_fbs`, `implementation_sequence_fbs` | ### Layer 2 — Fixture preparation (`puml_fixture.bzl`) @@ -53,38 +55,44 @@ The `provider_fbs_fixture_bundle` rule reads the provider fields from its `deps` and creates a predictable directory layout that the Rust test binary can navigate at runtime: -``` -fbs/ -├── component/ ← from ArchitecturalDesignInfo.static -├── class/ ← from UnitDesignInfo.static -├── internal_api/ ← from ArchitecturalDesignInfo.internal_api, when present -└── sequence/ ← from ArchitecturalDesignInfo.dynamic + UnitDesignInfo.dynamic -``` +| Category | Source provider field | +|----------|-----------------------| +| `component/` | `ArchitecturalDesignInfo.static` | +| `internal_api/` | `ArchitecturalDesignInfo.internal_api`, when present | +| `sequence/` | `ArchitecturalDesignInfo.dynamic` | +| `unit_design_class/` | `UnitDesignInfo.static` | +| `unit_design_sequence/` | `UnitDesignInfo.dynamic` | +| `unit_implementation_class/` | `UnitInfo.implementation_class_fbs` | +| `unit_implementation_sequence/` | `UnitInfo.implementation_sequence_fbs` | Each file in these directories is a **symlink** to the canonical `.fbs.bin` produced in layer 1. No copying or re-parsing occurs; the underlying Bazel action cache entry is reused. A `filegroup` named `case_data` then bundles the `fbs` target together with the -static fixture files (`architecture.json`, `expected.json`), making the whole -case available as a single Bazel dependency. +static fixture files (`architecture.json`, `expected.json` or `expected.yaml`), +making the whole case available as a single Bazel dependency. For `ComponentSequence` cases that exercise method-level validation, the suite -also reads `internal_api/*.fbs.bin` and forwards those files to the CLI as -`--internal-api-fbs`. +also reads `internal_api/*.fbs.bin` and forwards those files to the CLI in the +`internal_api_diagrams` input bundle field. For `ClassDesignImplementation`, +the suite reads `unit_design_class/*.fbs.bin` and +`unit_implementation_class/*.fbs.bin` and forwards them to the `unit` profile. ### Layer 3 — CLI invocation (Rust test binary) -There is one `rust_test` binary per validator. Each binary lists the relevant -`case_data` filegroups and the `validation_cli` binary in its `data` attribute -so that Bazel places them under `TEST_SRCDIR` at test time. +There is one `rust_test` binary per suite, defined in that suite's `BUILD` file. +Each binary lists the relevant suite-level `*_test_data` filegroup and the +`validation_cli` binary in its `data` attribute so that Bazel places them under +`TEST_SRCDIR` at test time. The shared `test_framework` library provides the following helpers: | Helper | Description | |--------|-------------| | `collect_case_fbs_files(suite, case, category)` | Returns sorted absolute paths to every `.fbs.bin` in a category subdirectory | -| `load_expected_fixture(suite, case)` | Deserialises `expected.json` into `ExpectedFixture` | +| `load_expected_fixture(suite, case)` | Deserializes `expected.json` into `ExpectedFixture` | +| `load_expected_yaml_fixture(suite, case)` | Deserializes `expected.yaml` into `ExpectedFixture` | | `run_validation_profile(case_name, profile, input_bundle)` | Writes a profile-owned input bundle, spawns the CLI binary, and returns `CliRunResult` | | `assert_cli_result(case, expected, result)` | Asserts exit code and checks each string in `error_contains` against the log | @@ -104,17 +112,17 @@ design/component_diagram.fbs.bin ← in ArchitecturalDesignInfo.static │ provider_fbs_fixture_bundle rule │ → symlink action (zero cost) ▼ -fbs/component/component_diagram.fbs.bin ← symlink → file above +component/component_diagram.fbs.bin ← symlink → file above │ filegroup case_data │ → bundles fbs + architecture.json + expected.json ▼ -bazel_component_test_data ← aggregated across all cases +//.../bazel_component:bazel_component_test_data ← aggregated across all cases │ rust_test data = [...] │ → placed under TEST_SRCDIR at test execution ▼ -bazel_component_integration_test +//.../bazel_component:integration_test │ │ collect_case_fbs_files() → absolute paths to .fbs.bin files │ load_expected_fixture() → ExpectedFixture @@ -127,8 +135,13 @@ PASS / FAIL `ComponentSequence` method-validation cases follow the same flow for `internal_api_diagram.puml`: the `architectural_design` rule produces `internal_api/*.fbs.bin`, `provider_fbs_fixture_bundle` materializes those -files under `fbs/internal_api/`, and the suite passes them to `validation_cli` -with `--internal-api-fbs`. +files under `internal_api/`, and the suite passes them to `validation_cli` +through `internal_api_diagrams`. + +`ClassDesignImplementation` cases use both `unit_design` and `unit`. The +`unit_design` rule produces design class diagrams under `unit_design_class/`, +while the `unit` rule runs the C++ parser for implementation targets and exposes +their class diagrams under `unit_implementation_class/`. ## Test case anatomy @@ -155,6 +168,17 @@ the validator under test. └── expected.json ``` +### ClassDesignImplementation cases + +``` +/ +├── BUILD # unit_design + implementation cc_library + unit + provider_fbs_fixture_bundle + case_data +├── class_diagram.puml # unit design class diagram +├── transport.cpp # or other implementation source(s) +├── transport.h # optional implementation header(s) +└── expected.yaml +``` + ### ComponentSequence cases ``` @@ -166,7 +190,7 @@ the validator under test. └── expected.json ``` -### `expected.json` format +### `expected.json` / `expected.yaml` format ```json { @@ -178,11 +202,13 @@ the validator under test. | Field | Type | Description | |-------|------|-------------| | `should_pass` | `bool` | Whether the CLI must exit with code 0 | -| `error_contains` | `string[]` | Substrings that must appear in the CLI log on failure. Empty for positive cases. | +| `error_contains` | `string` or `string[]` | Substrings that must appear in the CLI log on failure. Empty for positive cases. | The framework uses **substring matching** for `error_contains`, so entries do not need to reproduce exact formatting — just enough context to uniquely -identify the error. +identify the error. Existing suites use `expected.json`; the +`class_design_implementation` suite uses `expected.yaml` so larger multi-line +error fragments stay readable. ## Running the tests @@ -195,9 +221,10 @@ bazel test //validation/core/integration_test/... Run a single suite: ```bash -bazel test //validation/core/integration_test:bazel_component_integration_test -bazel test //validation/core/integration_test:component_class_integration_test -bazel test //validation/core/integration_test:component_sequence_integration_test +bazel test //validation/core/integration_test/bazel_component:integration_test +bazel test //validation/core/integration_test/component_class:integration_test +bazel test //validation/core/integration_test/component_sequence:integration_test +bazel test //validation/core/integration_test/class_design_implementation:integration_test ``` ## Adding a new test case @@ -210,17 +237,18 @@ bazel test //validation/core/integration_test:component_sequence_integration_tes 2. Add the `.puml` source file(s) and — for `bazel_component` — an `architecture.json`. -3. Write `expected.json`. For negative cases add the error substrings you - expect to see in the CLI log. +3. Write `expected.json` or `expected.yaml`. For negative cases add the error + substrings you expect to see in the CLI log. 4. Create a `BUILD` file following the pattern of an existing case in the same suite. -5. Add the new `case_data` target to the matching filegroup in - [`BUILD`](BUILD) (`bazel_component_test_data`, - `component_class_test_data`, or `component_sequence_test_data`). +5. Add the new `case_data` target to the matching suite-level filegroup + (`bazel_component_test_data`, `component_class_test_data`, + `component_sequence_test_data`, or `class_design_implementation_test_data`). -6. Add a `#[test]` function in the matching suite file under `src/`. +6. Add a `#[test]` function in the matching suite file, such as + `bazel_component_suite.rs` or `class_design_implementation_suite.rs`. ## Caching behaviour @@ -231,5 +259,6 @@ bazel test //validation/core/integration_test:component_sequence_integration_tes cache key for a test case only covers the underlying `puml_parser` action. - Changing one test case's `.puml` only invalidates actions for that case; the other cases and test binaries stay cached. -- The three test binaries are independent: touching a sequence test case does - not invalidate the component or class test binary. +- The suite test binaries are independent: touching a sequence test case does + not invalidate the Bazel component, component class, or class design + implementation test binaries. diff --git a/validation/core/integration_test/bazel_component/BUILD b/validation/core/integration_test/bazel_component/BUILD new file mode 100644 index 00000000..5f05ea5d --- /dev/null +++ b/validation/core/integration_test/bazel_component/BUILD @@ -0,0 +1,43 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("@rules_rust//rust:defs.bzl", "rust_test") + +filegroup( + name = "bazel_component_test_data", + srcs = [ + "//validation/core/integration_test/bazel_component/negative_extra_component:case_data", + "//validation/core/integration_test/bazel_component/negative_extra_unit:case_data", + "//validation/core/integration_test/bazel_component/negative_missing_component:case_data", + "//validation/core/integration_test/bazel_component/negative_missing_unit:case_data", + "//validation/core/integration_test/bazel_component/negative_wrong_stereotype:case_data", + "//validation/core/integration_test/bazel_component/positive_case_insensitive:case_data", + "//validation/core/integration_test/bazel_component/positive_component:case_data", + ], +) + +rust_test( + name = "integration_test", + srcs = ["bazel_component_suite.rs"], + crate_root = "bazel_component_suite.rs", + data = [ + ":bazel_component_test_data", + "//validation/core:validation_cli", + ], + deps = [ + "//validation/core:validation", + "//validation/core/integration_test:test_framework", + "@crates//:serde", + "@crates//:serde_json", + ], +) diff --git a/validation/core/integration_test/src/bazel_component_suite.rs b/validation/core/integration_test/bazel_component/bazel_component_suite.rs similarity index 100% rename from validation/core/integration_test/src/bazel_component_suite.rs rename to validation/core/integration_test/bazel_component/bazel_component_suite.rs diff --git a/validation/core/integration_test/class_design_implementation/BUILD b/validation/core/integration_test/class_design_implementation/BUILD new file mode 100644 index 00000000..b205484b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/BUILD @@ -0,0 +1,62 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("@rules_rust//rust:defs.bzl", "rust_test") + +filegroup( + name = "class_design_implementation_test_data", + srcs = [ + "//validation/core/integration_test/class_design_implementation/negative_class_member_missing:case_data", + "//validation/core/integration_test/class_design_implementation/negative_class_missing:case_data", + "//validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_enum_literal_missing:case_data", + "//validation/core/integration_test/class_design_implementation/negative_method_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_method_missing:case_data", + "//validation/core/integration_test/class_design_implementation/negative_relationship_missing:case_data", + "//validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_type_alias_missing:case_data", + "//validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/negative_variable_mismatch:case_data", + "//validation/core/integration_test/class_design_implementation/positive_class_features:case_data", + "//validation/core/integration_test/class_design_implementation/positive_method_features:case_data", + # "//validation/core/integration_test/class_design_implementation/positive_method_template_pack_features:case_data", + "//validation/core/integration_test/class_design_implementation/positive_relationship_features:case_data", + "//validation/core/integration_test/class_design_implementation/positive_variable_features:case_data", + ], +) + +rust_test( + name = "integration_test", + srcs = ["class_design_implementation_suite.rs"], + crate_root = "class_design_implementation_suite.rs", + data = [ + ":class_design_implementation_test_data", + "//validation/core:validation_cli", + ], + deps = [ + "//validation/core:validation", + "//validation/core/integration_test:test_framework", + "@crates//:serde", + "@crates//:serde_json", + ], +) diff --git a/validation/core/integration_test/class_design_implementation/class_design_implementation_suite.rs b/validation/core/integration_test/class_design_implementation/class_design_implementation_suite.rs new file mode 100644 index 00000000..ce9f8ba1 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/class_design_implementation_suite.rs @@ -0,0 +1,186 @@ +// ******************************************************************************* +// Copyright (c) 2026 Contributors to the Eclipse Foundation +// +// See the NOTICE file(s) distributed with this work for additional +// information regarding copyright ownership. +// +// This program and the accompanying materials are made available under the +// terms of the Apache License Version 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* + +use test_framework::{ + assert_cli_result, collect_case_fbs_files, load_expected_yaml_fixture, run_validation_profile, + CliRunResult, +}; + +const SUITE_DIR: &str = "class_design_implementation"; + +fn run_case_from_cli( + case_dir: &str, + design_class_fbs_paths: &[String], + implementation_class_fbs_paths: &[String], +) -> CliRunResult { + run_validation_profile( + &format!("class_design_implementation_{case_dir}"), + "unit", + serde_json::json!({ + "design_classes": design_class_fbs_paths, + "implementation_classes": implementation_class_fbs_paths, + }), + ) +} + +fn assert_case(case_dir: &str) { + let expected = load_expected_yaml_fixture(SUITE_DIR, case_dir); + let design_class_fbs_paths = collect_case_fbs_files(SUITE_DIR, case_dir, "unit_design_class"); + let implementation_class_fbs_paths = + collect_case_fbs_files(SUITE_DIR, case_dir, "unit_implementation_class"); + + let result = if !design_class_fbs_paths.is_empty() && !implementation_class_fbs_paths.is_empty() + { + run_case_from_cli( + case_dir, + &design_class_fbs_paths, + &implementation_class_fbs_paths, + ) + } else { + panic!( + "missing generated FBS fixtures for {case_dir}: expected at least one unit_design_class/*.fbs.bin and unit_implementation_class/*.fbs.bin", + ); + }; + + assert_cli_result(case_dir, &expected, &result); +} + +#[test] +fn positive_class_features() { + assert_case("positive_class_features"); +} + +#[test] +fn positive_method_features() { + assert_case("positive_method_features"); +} + +// #[test] +// fn positive_method_template_pack_features() { +// assert_case("positive_method_template_pack_features"); +// } + +#[test] +fn positive_relationship_features() { + assert_case("positive_relationship_features"); +} + +#[test] +fn positive_variable_features() { + assert_case("positive_variable_features"); +} + +#[test] +fn negative_class_missing() { + assert_case("negative_class_missing"); +} + +#[test] +fn negative_class_member_missing() { + assert_case("negative_class_member_missing"); +} + +#[test] +fn negative_entity_type_mismatch() { + assert_case("negative_entity_type_mismatch"); +} + +#[test] +fn negative_variable_mismatch() { + assert_case("negative_variable_mismatch"); +} + +#[test] +fn negative_variable_static_mismatch() { + assert_case("negative_variable_static_mismatch"); +} + +#[test] +fn negative_variable_visibility_mismatch() { + assert_case("negative_variable_visibility_mismatch"); +} + +#[test] +fn negative_method_missing() { + assert_case("negative_method_missing"); +} + +#[test] +fn negative_method_mismatch() { + assert_case("negative_method_mismatch"); +} + +#[test] +fn negative_method_modifier_mismatch() { + assert_case("negative_method_modifier_mismatch"); +} + +#[test] +fn negative_method_parameter_count_mismatch() { + assert_case("negative_method_parameter_count_mismatch"); +} + +#[test] +fn negative_method_parameter_name_mismatch() { + assert_case("negative_method_parameter_name_mismatch"); +} + +#[test] +fn negative_method_parameter_type_mismatch() { + assert_case("negative_method_parameter_type_mismatch"); +} + +#[test] +fn negative_method_parameter_variadic_mismatch() { + assert_case("negative_method_parameter_variadic_mismatch"); +} + +#[test] +fn negative_method_visibility_mismatch() { + assert_case("negative_method_visibility_mismatch"); +} + +#[test] +fn negative_relationship_missing() { + assert_case("negative_relationship_missing"); +} + +#[test] +fn negative_relationship_type_mismatch() { + assert_case("negative_relationship_type_mismatch"); +} + +#[test] +fn negative_type_alias_missing() { + assert_case("negative_type_alias_missing"); +} + +#[test] +fn negative_type_alias_mismatch() { + assert_case("negative_type_alias_mismatch"); +} + +#[test] +fn negative_enum_literal_missing() { + assert_case("negative_enum_literal_missing"); +} + +#[test] +fn negative_enum_literal_mismatch() { + assert_case("negative_enum_literal_mismatch"); +} + +#[test] +fn negative_template_parameter_mismatch() { + assert_case("negative_template_parameter_mismatch"); +} diff --git a/validation/core/integration_test/class_design_implementation/negative_class_member_missing/BUILD b/validation/core/integration_test/class_design_implementation/negative_class_member_missing/BUILD new file mode 100644 index 00000000..c3206a03 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_class_member_missing/BUILD @@ -0,0 +1,54 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_class_member_missing/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_class_member_missing/class_diagram.puml new file mode 100644 index 00000000..bbd7f4cc --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_class_member_missing/class_diagram.puml @@ -0,0 +1,26 @@ + +' Copyright (c) 2025 Contributors to the Eclipse Foundation +' +' See the NOTICE file(s) distributed with this work for additional +' information regarding copyright ownership. +' +' This program and the accompanying materials are made available under the +' terms of the Apache License Version 2.0 which is available at +' +' +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +skinparam classAttributeIconSize 0 + +struct Engine { + + cylinders : int + + displacement : double + + manufacturer : std::string + -- + + start(Engine *) : void + + stop(Engine *, force : int) : int +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_class_member_missing/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_class_member_missing/expected.yaml new file mode 100644 index 00000000..6e9bbe7a --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_class_member_missing/expected.yaml @@ -0,0 +1,20 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Missing implementation variable for unit design entity: + Entity ID : Engine + Member : manufacturer + Design source file : class_diagram.puml + Design source line : 17 + Required Action : Implement the member or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_class_member_missing/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_class_member_missing/transport.cpp new file mode 100644 index 00000000..150ce07a --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_class_member_missing/transport.cpp @@ -0,0 +1,21 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + int cylinders; + double displacement; + + void start(Engine*); + int stop(Engine*, int force); +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_class_missing/BUILD b/validation/core/integration_test/class_design_implementation/negative_class_missing/BUILD new file mode 100644 index 00000000..c3206a03 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_class_missing/BUILD @@ -0,0 +1,54 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_class_missing/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_class_missing/class_diagram.puml new file mode 100644 index 00000000..96c4251a --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_class_missing/class_diagram.puml @@ -0,0 +1,28 @@ +' Copyright (c) 2025 Contributors to the Eclipse Foundation +' +' See the NOTICE file(s) distributed with this work for additional +' information regarding copyright ownership. +' +' This program and the accompanying materials are made available under the +' terms of the Apache License Version 2.0 which is available at +' +' +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +skinparam classAttributeIconSize 0 + +class Manufacturer { + + name : const char * + + country_code : int +} + +class Engine { + + start(Engine *) : void + + stop(Engine *, force : int) : int +} + +Engine *-- Manufacturer : vendor + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_class_missing/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_class_missing/expected.yaml new file mode 100644 index 00000000..d4dd8126 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_class_missing/expected.yaml @@ -0,0 +1,19 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Missing implementation class for unit design entity: + Entity ID : Manufacturer + Design source file : class_diagram.puml + Design source line : 16 + Required Action : Add a matching implementation class or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_class_missing/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_class_missing/transport.cpp new file mode 100644 index 00000000..e854cfe8 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_class_missing/transport.cpp @@ -0,0 +1,26 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +class Factory +{ + public: + const char* name; + int country_code; +}; + +class Engine +{ + public: + void start(Engine*); + int stop(Engine*, int force); +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/BUILD new file mode 100644 index 00000000..c3206a03 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/BUILD @@ -0,0 +1,54 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/class_diagram.puml new file mode 100644 index 00000000..3f7d8a51 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/class_diagram.puml @@ -0,0 +1,16 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' +' See the NOTICE file(s) distributed with this work for additional +' information regarding copyright ownership. +' +' This program and the accompanying materials are made available under the +' terms of the Apache License Version 2.0 which is available at +' +' +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +class Engine + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/expected.yaml new file mode 100644 index 00000000..aa695031 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : entity_type + Design value : Class + Design source file : class_diagram.puml + Design source line : 14 + Implement value : Struct + Implement source file : validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/transport.cpp + Implement source line : 14 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/transport.cpp new file mode 100644 index 00000000..be3b207a --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_entity_type_mismatch/transport.cpp @@ -0,0 +1,16 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/class_diagram.puml new file mode 100644 index 00000000..00343051 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/class_diagram.puml @@ -0,0 +1,11 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +enum Mode { + Off = 0 + On = 2 +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/expected.yaml new file mode 100644 index 00000000..88b36719 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Mode + Field : "On" + Design value : EnumLiteral { name: "On", value: Some(2) } + Design source file : class_diagram.puml + Design source line : 6 + Implement value : EnumLiteral { name: "On", value: Some(1) } + Implement source file : validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/transport.cpp new file mode 100644 index 00000000..8d4c1ed4 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_enum_literal_mismatch/transport.cpp @@ -0,0 +1,10 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +enum class Mode +{ + Off = 0, + On = 1 +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/BUILD b/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/class_diagram.puml new file mode 100644 index 00000000..a115ece5 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/class_diagram.puml @@ -0,0 +1,11 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +enum Mode { + Off + On +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/expected.yaml new file mode 100644 index 00000000..466a9e73 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/expected.yaml @@ -0,0 +1,20 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Missing implementation enum_literal for unit design entity: + Entity ID : Mode + Member : On + Design source file : class_diagram.puml + Design source line : 6 + Required Action : Implement the member or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/transport.cpp new file mode 100644 index 00000000..42cd726d --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_enum_literal_missing/transport.cpp @@ -0,0 +1,9 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +enum class Mode +{ + Off +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_method_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_method_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_method_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_method_mismatch/class_diagram.puml new file mode 100644 index 00000000..73f64b91 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + stop(force : int) : int +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_method_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_method_mismatch/expected.yaml new file mode 100644 index 00000000..6759036f --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : method "stop" return_type + Design value : Some("int") + Design source file : class_diagram.puml + Design source line : 6 + Implement value : Some("void") + Implement source file : validation/core/integration_test/class_design_implementation/negative_method_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_method_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_method_mismatch/transport.cpp new file mode 100644 index 00000000..41438dd3 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_mismatch/transport.cpp @@ -0,0 +1,9 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + void stop(int force); +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_method_missing/BUILD b/validation/core/integration_test/class_design_implementation/negative_method_missing/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_missing/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_method_missing/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_method_missing/class_diagram.puml new file mode 100644 index 00000000..c1b64145 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_missing/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + restart() : void +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_method_missing/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_method_missing/expected.yaml new file mode 100644 index 00000000..a6aee43d --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_missing/expected.yaml @@ -0,0 +1,20 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Missing implementation method for unit design entity: + Entity ID : Engine + Member : restart() + Design source file : class_diagram.puml + Design source line : 6 + Required Action : Implement the member or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_method_missing/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_method_missing/transport.cpp new file mode 100644 index 00000000..2b20d6aa --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_missing/transport.cpp @@ -0,0 +1,8 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/class_diagram.puml new file mode 100644 index 00000000..2aed8b99 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + stop() : void +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/expected.yaml new file mode 100644 index 00000000..504cebd2 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/expected.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# SPDX-License-Identifier: Apache-2.0 +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : method "stop" modifiers + Design value : [] + Design source file : class_diagram.puml + Design source line : 6 + Implement value : [Static] + Implement source file : validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/transport.cpp new file mode 100644 index 00000000..5db54717 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_modifier_mismatch/transport.cpp @@ -0,0 +1,9 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + static void stop(); +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/class_diagram.puml new file mode 100644 index 00000000..8b98efcd --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + stop(mode : int, force : int) : int +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/expected.yaml new file mode 100644 index 00000000..59e89688 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/expected.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# SPDX-License-Identifier: Apache-2.0 +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : method "stop" parameter_count + Design value : 2 parameters (mode: int, force: int) + Design source file : class_diagram.puml + Design source line : 6 + Implement value : 1 parameter (mode: int) + Implement source file : validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/transport.cpp new file mode 100644 index 00000000..14818166 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_count_mismatch/transport.cpp @@ -0,0 +1,9 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + int stop(int mode); +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/class_diagram.puml new file mode 100644 index 00000000..7074a5d4 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + stop(mode : int, force : double) : int +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/expected.yaml new file mode 100644 index 00000000..8c5e5800 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : method "stop" parameter name + Design value : force: double + Design source file : class_diagram.puml + Design source line : 6 + Implement value : thrust: double + Implement source file : validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/transport.cpp new file mode 100644 index 00000000..946fe7a5 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_name_mismatch/transport.cpp @@ -0,0 +1,9 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + int stop(int mode, double thrust); +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/class_diagram.puml new file mode 100644 index 00000000..8b98efcd --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + stop(mode : int, force : int) : int +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/expected.yaml new file mode 100644 index 00000000..7c925b5f --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : method "stop" parameter type + Design value : force: int + Design source file : class_diagram.puml + Design source line : 6 + Implement value : force: double + Implement source file : validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/transport.cpp new file mode 100644 index 00000000..3fc447e6 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_type_mismatch/transport.cpp @@ -0,0 +1,9 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + int stop(int mode, double force); +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/class_diagram.puml new file mode 100644 index 00000000..8b98efcd --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + stop(mode : int, force : int) : int +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/expected.yaml new file mode 100644 index 00000000..c4832729 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : method "stop" parameter list + Design value : (mode: int, force: int) + Design source file : class_diagram.puml + Design source line : 6 + Implement value : (mode: int, force: int, ...) + Implement source file : validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/transport.cpp new file mode 100644 index 00000000..5f496c5a --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_parameter_variadic_mismatch/transport.cpp @@ -0,0 +1,9 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + int stop(int mode, int force, ...); +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/class_diagram.puml new file mode 100644 index 00000000..2aed8b99 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + stop() : void +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/expected.yaml new file mode 100644 index 00000000..d33caac7 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : method "stop" visibility + Design value : Public + Design source file : class_diagram.puml + Design source line : 6 + Implement value : Private + Implement source file : validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/transport.cpp new file mode 100644 index 00000000..d3f84d88 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_method_visibility_mismatch/transport.cpp @@ -0,0 +1,10 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + private: + void stop(); +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_relationship_missing/BUILD b/validation/core/integration_test/class_design_implementation/negative_relationship_missing/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_relationship_missing/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_relationship_missing/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_relationship_missing/class_diagram.puml new file mode 100644 index 00000000..43b9fbcd --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_relationship_missing/class_diagram.puml @@ -0,0 +1,11 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine +struct Manufacturer + +Engine *-- Manufacturer + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_relationship_missing/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_relationship_missing/expected.yaml new file mode 100644 index 00000000..6866ca60 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_relationship_missing/expected.yaml @@ -0,0 +1,20 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Missing implementation relationship for unit design entity: + Entity ID : Manufacturer + Member : Manufacturer -> Composition -> Engine + Design source file : class_diagram.puml + Design source line : 7 + Required Action : Implement the member or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_relationship_missing/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_relationship_missing/transport.cpp new file mode 100644 index 00000000..167c03c3 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_relationship_missing/transport.cpp @@ -0,0 +1,12 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Manufacturer +{ +}; + +struct Engine +{ +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/BUILD new file mode 100644 index 00000000..c3206a03 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/BUILD @@ -0,0 +1,54 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/class_diagram.puml new file mode 100644 index 00000000..82164c7d --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/class_diagram.puml @@ -0,0 +1,22 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' +' See the NOTICE file(s) distributed with this work for additional +' information regarding copyright ownership. +' +' This program and the accompanying materials are made available under the +' terms of the Apache License Version 2.0 which is available at +' +' +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Manufacturer + +struct Engine { + + vendor : Manufacturer +} + +Manufacturer o-- Engine + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/expected.yaml new file mode 100644 index 00000000..60cad939 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : relationship type + Design value : Engine -> Aggregation -> Manufacturer + Design source file : class_diagram.puml + Design source line : 16 + Implement value : Engine -> Composition -> Manufacturer + Implement source file : validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/transport.cpp + Implement source line : 18 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/transport.cpp new file mode 100644 index 00000000..7030d37f --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_relationship_type_mismatch/transport.cpp @@ -0,0 +1,21 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Manufacturer +{ +}; + +struct Engine +{ + Manufacturer vendor; +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/class_diagram.puml new file mode 100644 index 00000000..579d699e --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/class_diagram.puml @@ -0,0 +1,8 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +class Box + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/expected.yaml new file mode 100644 index 00000000..1adbf1dd --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Box + Field : template_parameters + Design value : Some(["T"]) + Design source file : class_diagram.puml + Design source line : 6 + Implement value : Some(["U"]) + Implement source file : validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/transport.cpp + Implement source line : 7 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/transport.cpp new file mode 100644 index 00000000..82d2366e --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_template_parameter_mismatch/transport.cpp @@ -0,0 +1,9 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +template +class Box +{ +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/class_diagram.puml new file mode 100644 index 00000000..4e0be002 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +class Engine { + using Speed = std::uint8_t; +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/expected.yaml new file mode 100644 index 00000000..627674d4 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : type_alias "Speed" original_type + Design value : std::uint8_t + Design source file : class_diagram.puml + Design source line : 6 + Implement value : std::uint16_t + Implement source file : validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/transport.cpp + Implement source line : 8 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/transport.cpp new file mode 100644 index 00000000..2c6ba353 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_type_alias_mismatch/transport.cpp @@ -0,0 +1,12 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#include + +class Engine +{ + public: + using Speed = std::uint16_t; +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/BUILD b/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/class_diagram.puml new file mode 100644 index 00000000..4e0be002 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +class Engine { + using Speed = std::uint8_t; +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/expected.yaml new file mode 100644 index 00000000..f0b75f4f --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/expected.yaml @@ -0,0 +1,20 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Missing implementation type_alias for unit design entity: + Entity ID : Engine + Member : Speed + Design source file : class_diagram.puml + Design source line : 6 + Required Action : Implement the member or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/transport.cpp new file mode 100644 index 00000000..47dbfe2c --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_type_alias_missing/transport.cpp @@ -0,0 +1,8 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +class Engine +{ +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/BUILD new file mode 100644 index 00000000..c3206a03 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/BUILD @@ -0,0 +1,54 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/class_diagram.puml new file mode 100644 index 00000000..7191d03e --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + speed : int +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/expected.yaml new file mode 100644 index 00000000..6fdaf8d3 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : variable "speed" data_type + Design value : Some("int") + Design source file : class_diagram.puml + Design source line : 6 + Implement value : Some("double") + Implement source file : validation/core/integration_test/class_design_implementation/negative_variable_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/transport.cpp new file mode 100644 index 00000000..1845ac96 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_mismatch/transport.cpp @@ -0,0 +1,9 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + double speed; +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/class_diagram.puml new file mode 100644 index 00000000..7191d03e --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + speed : int +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/expected.yaml new file mode 100644 index 00000000..b9d8f0b3 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : variable "speed" is_static + Design value : false + Design source file : class_diagram.puml + Design source line : 6 + Implement value : true + Implement source file : validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/transport.cpp new file mode 100644 index 00000000..b476d48c --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_static_mismatch/transport.cpp @@ -0,0 +1,9 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + static int speed; +}; diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/BUILD b/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/class_diagram.puml b/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/class_diagram.puml new file mode 100644 index 00000000..7191d03e --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + speed : int +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/expected.yaml b/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/expected.yaml new file mode 100644 index 00000000..0a3d6986 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/expected.yaml @@ -0,0 +1,24 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: false +error_contains: | + Implementation class data differs from unit design entity: + Entity ID : Engine + Field : variable "speed" visibility + Design value : Public + Design source file : class_diagram.puml + Design source line : 6 + Implement value : Private + Implement source file : validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/transport.cpp + Implement source line : 6 + Required Action : Align the implementation with the unit design or update the unit design diff --git a/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/transport.cpp b/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/transport.cpp new file mode 100644 index 00000000..27509d88 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/negative_variable_visibility_mismatch/transport.cpp @@ -0,0 +1,10 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + private: + int speed; +}; diff --git a/validation/core/integration_test/class_design_implementation/positive_class_features/BUILD b/validation/core/integration_test/class_design_implementation/positive_class_features/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_class_features/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/positive_class_features/class_diagram.puml b/validation/core/integration_test/class_design_implementation/positive_class_features/class_diagram.puml new file mode 100644 index 00000000..78edd550 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_class_features/class_diagram.puml @@ -0,0 +1,34 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +package vehicle { + struct Manufacturer { + + id : int + } + + enum Mode { + Off = 0 + On = 1 + } + + class Box + + struct Engine { + using Speed = std::uint8_t; + + speed : int + - status : int + {static} + instance_count : int + -- + + start(mode : int) : void + + configure(mode : int, force : int) : void + + current_speed() : vehicle::Engine::Speed + - calibrate() : void + {static} + Reset() : void + } + + Manufacturer *-- Engine +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/positive_class_features/expected.yaml b/validation/core/integration_test/class_design_implementation/positive_class_features/expected.yaml new file mode 100644 index 00000000..898ecba3 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_class_features/expected.yaml @@ -0,0 +1,13 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: true diff --git a/validation/core/integration_test/class_design_implementation/positive_class_features/transport.cpp b/validation/core/integration_test/class_design_implementation/positive_class_features/transport.cpp new file mode 100644 index 00000000..cd448881 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_class_features/transport.cpp @@ -0,0 +1,46 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#include + +namespace vehicle +{ +struct Manufacturer +{ + int id; +}; + +enum class Mode +{ + Off = 0, + On = 1, +}; + +template +class Box +{ +}; + +struct Engine +{ + using Speed = std::uint8_t; + + int speed; + static int instance_count; + Manufacturer vendor; + + void start(int mode); + void configure(int mode, int force); + Speed current_speed(); + static void Reset(); + + private: + // NOTE: this is not part of the puml file but the test still passes + // since we want to be able to ommit implementation details + int status; + void calibrate(); + int implementation_detail; +}; +} // namespace vehicle diff --git a/validation/core/integration_test/class_design_implementation/positive_method_features/BUILD b/validation/core/integration_test/class_design_implementation/positive_method_features/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_method_features/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/positive_method_features/class_diagram.puml b/validation/core/integration_test/class_design_implementation/positive_method_features/class_diagram.puml new file mode 100644 index 00000000..4c430c18 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_method_features/class_diagram.puml @@ -0,0 +1,17 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +struct Engine { + + Engine() + + ~Engine() + + build() : bool + ' + run(mode: int, payload: int, ...) : bool + + select(mode: int) : int + + select(mode: int, force: int) : int + {static} + Create(name: const char*) : Engine* + - reset(reason: int) : void +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/positive_method_features/expected.yaml b/validation/core/integration_test/class_design_implementation/positive_method_features/expected.yaml new file mode 100644 index 00000000..898ecba3 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_method_features/expected.yaml @@ -0,0 +1,13 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: true diff --git a/validation/core/integration_test/class_design_implementation/positive_method_features/transport.cpp b/validation/core/integration_test/class_design_implementation/positive_method_features/transport.cpp new file mode 100644 index 00000000..8ee196c4 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_method_features/transport.cpp @@ -0,0 +1,23 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +struct Engine +{ + Engine(); + ~Engine(); + + template + bool build(); + + // bool run(int mode, int payload, ...); + + int select(int mode); + int select(int mode, int force); + + static Engine* Create(const char* name); + + private: + void reset(int reason); +}; diff --git a/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/BUILD b/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/class_diagram.puml b/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/class_diagram.puml new file mode 100644 index 00000000..78c6c93f --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/class_diagram.puml @@ -0,0 +1,10 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +class DiagnosticJobCollectionBuilder { + + With(::ara::core::InstanceSpecifier, DiagnosticJobConstructorArgumentTypes...) : void +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/expected.yaml b/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/expected.yaml new file mode 100644 index 00000000..898ecba3 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/expected.yaml @@ -0,0 +1,13 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: true diff --git a/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/transport.cpp b/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/transport.cpp new file mode 100644 index 00000000..27242b3d --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_method_template_pack_features/transport.cpp @@ -0,0 +1,21 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace ara +{ +namespace core +{ +struct InstanceSpecifier +{ +}; +} // namespace core +} // namespace ara + +class DiagnosticJobCollectionBuilder +{ + public: + template + void With(ara::core::InstanceSpecifier, DiagnosticJobConstructorArgumentTypes...); +}; diff --git a/validation/core/integration_test/class_design_implementation/positive_relationship_features/BUILD b/validation/core/integration_test/class_design_implementation/positive_relationship_features/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_relationship_features/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/positive_relationship_features/class_diagram.puml b/validation/core/integration_test/class_design_implementation/positive_relationship_features/class_diagram.puml new file mode 100644 index 00000000..7ed8f55b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_relationship_features/class_diagram.puml @@ -0,0 +1,21 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +class Base + +struct Owned +struct Borrowed +struct Result +struct Context + +struct Worker + +Base <|-- Worker +Owned *-- Worker +Borrowed o-- Worker +Worker --> Result +Worker ..> Context + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/positive_relationship_features/expected.yaml b/validation/core/integration_test/class_design_implementation/positive_relationship_features/expected.yaml new file mode 100644 index 00000000..898ecba3 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_relationship_features/expected.yaml @@ -0,0 +1,13 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: true diff --git a/validation/core/integration_test/class_design_implementation/positive_relationship_features/transport.cpp b/validation/core/integration_test/class_design_implementation/positive_relationship_features/transport.cpp new file mode 100644 index 00000000..4523cbdd --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_relationship_features/transport.cpp @@ -0,0 +1,32 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +class Base +{ +}; + +struct Owned +{ +}; + +struct Borrowed +{ +}; + +struct Result +{ +}; + +struct Context +{ +}; + +struct Worker : Base +{ + Owned owned; + Borrowed* borrowed; + + Result make_result(const Context& context); +}; diff --git a/validation/core/integration_test/class_design_implementation/positive_variable_features/BUILD b/validation/core/integration_test/class_design_implementation/positive_variable_features/BUILD new file mode 100644 index 00000000..7c27590b --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_variable_features/BUILD @@ -0,0 +1,46 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("//bazel/rules/rules_score:rules_score.bzl", "unit", "unit_design") +load("//validation/core/integration_test:puml_fixture.bzl", "provider_fbs_fixture_bundle") + +unit_design( + name = "unit_design", + static = ["class_diagram.puml"], + visibility = ["//visibility:private"], +) + +cc_library( + name = "transport", + srcs = ["transport.cpp"], +) + +unit( + name = "unit", + testonly = False, + maturity = "development", + tests = [], + unit_design = [":unit_design"], + visibility = ["//visibility:private"], + implementation = [":transport"], +) + +provider_fbs_fixture_bundle( + name = "fbs", + visibility = ["//visibility:private"], + deps = [ + ":unit", + ":unit_design", + ], +) + +filegroup( + name = "case_data", + srcs = [ + "expected.yaml", + ":fbs", + ], + visibility = ["//validation/core/integration_test:__subpackages__"], +) diff --git a/validation/core/integration_test/class_design_implementation/positive_variable_features/class_diagram.puml b/validation/core/integration_test/class_design_implementation/positive_variable_features/class_diagram.puml new file mode 100644 index 00000000..5c1831a8 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_variable_features/class_diagram.puml @@ -0,0 +1,18 @@ +' Copyright (c) 2026 Contributors to the Eclipse Foundation +' SPDX-License-Identifier: Apache-2.0 + +@startuml + +skinparam classAttributeIconSize 0 + +struct Engine { + + cylinders : int + + displacement : double + + speed : uint8_t + + manufacturer : char[32] + + model : const char * + {static} + instance_count : int + - status : int +} + +@enduml diff --git a/validation/core/integration_test/class_design_implementation/positive_variable_features/expected.yaml b/validation/core/integration_test/class_design_implementation/positive_variable_features/expected.yaml new file mode 100644 index 00000000..898ecba3 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_variable_features/expected.yaml @@ -0,0 +1,13 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +should_pass: true diff --git a/validation/core/integration_test/class_design_implementation/positive_variable_features/transport.cpp b/validation/core/integration_test/class_design_implementation/positive_variable_features/transport.cpp new file mode 100644 index 00000000..0c50f5b4 --- /dev/null +++ b/validation/core/integration_test/class_design_implementation/positive_variable_features/transport.cpp @@ -0,0 +1,20 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#include + +struct Engine +{ + int cylinders; + double displacement; + std::uint8_t speed; + char manufacturer[32]; + const char* model; + static int instance_count; + + private: + int status; + int implementation_detail; +}; diff --git a/validation/core/integration_test/component_class/BUILD b/validation/core/integration_test/component_class/BUILD new file mode 100644 index 00000000..b619204b --- /dev/null +++ b/validation/core/integration_test/component_class/BUILD @@ -0,0 +1,44 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("@rules_rust//rust:defs.bzl", "rust_test") + +filegroup( + name = "component_class_test_data", + srcs = [ + "//validation/core/integration_test/component_class/negative_boundary_mismatch:case_data", + "//validation/core/integration_test/component_class/negative_case_sensitive_mismatch:case_data", + "//validation/core/integration_test/component_class/negative_missing_namespace_coverage:case_data", + "//validation/core/integration_test/component_class/negative_multi_class_files_with_mismatch:case_data", + "//validation/core/integration_test/component_class/positive_exact_match:case_data", + "//validation/core/integration_test/component_class/positive_multi_class_files:case_data", + "//validation/core/integration_test/component_class/positive_suffix_match:case_data", + ], +) + +rust_test( + name = "integration_test", + srcs = ["component_class_suite.rs"], + crate_root = "component_class_suite.rs", + data = [ + ":component_class_test_data", + "//validation/core:validation_cli", + ], + deps = [ + "//tools/metamodel/class:class_diagram", + "//validation/core:validation", + "//validation/core/integration_test:test_framework", + "@crates//:serde", + "@crates//:serde_json", + ], +) diff --git a/validation/core/integration_test/src/component_class_suite.rs b/validation/core/integration_test/component_class/component_class_suite.rs similarity index 100% rename from validation/core/integration_test/src/component_class_suite.rs rename to validation/core/integration_test/component_class/component_class_suite.rs diff --git a/validation/core/integration_test/component_sequence/BUILD b/validation/core/integration_test/component_sequence/BUILD new file mode 100644 index 00000000..38364b4d --- /dev/null +++ b/validation/core/integration_test/component_sequence/BUILD @@ -0,0 +1,49 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load("@rules_rust//rust:defs.bzl", "rust_test") + +filegroup( + name = "component_sequence_test_data", + srcs = [ + "//validation/core/integration_test/component_sequence/negative_interface_function_not_exercised:case_data", + "//validation/core/integration_test/component_sequence/negative_invalid_consumer_provider_direction:case_data", + "//validation/core/integration_test/component_sequence/negative_method_missing_from_internal_api:case_data", + "//validation/core/integration_test/component_sequence/negative_missing_interface_connection_for_sequence_connected_units:case_data", + "//validation/core/integration_test/component_sequence/negative_missing_method_in_related_interface:case_data", + "//validation/core/integration_test/component_sequence/negative_missing_participant:case_data", + "//validation/core/integration_test/component_sequence/negative_missing_sequence_interaction_for_interface_connected_units:case_data", + "//validation/core/integration_test/component_sequence/negative_missing_unit_interface_relation:case_data", + "//validation/core/integration_test/component_sequence/negative_mixed_mismatch:case_data", + "//validation/core/integration_test/component_sequence/negative_orphan_participant:case_data", + "//validation/core/integration_test/component_sequence/positive_exact_match:case_data", + "//validation/core/integration_test/component_sequence/positive_internal_api_method_match:case_data", + "//validation/core/integration_test/component_sequence/positive_self_call_method_match:case_data", + ], +) + +rust_test( + name = "integration_test", + srcs = ["component_sequence_suite.rs"], + crate_root = "component_sequence_suite.rs", + data = [ + ":component_sequence_test_data", + "//validation/core:validation_cli", + ], + deps = [ + "//validation/core:validation", + "//validation/core/integration_test:test_framework", + "@crates//:serde", + "@crates//:serde_json", + ], +) diff --git a/validation/core/integration_test/src/component_sequence_suite.rs b/validation/core/integration_test/component_sequence/component_sequence_suite.rs similarity index 100% rename from validation/core/integration_test/src/component_sequence_suite.rs rename to validation/core/integration_test/component_sequence/component_sequence_suite.rs diff --git a/validation/core/integration_test/puml_fixture.bzl b/validation/core/integration_test/puml_fixture.bzl index ba954f8a..cbb137fb 100644 --- a/validation/core/integration_test/puml_fixture.bzl +++ b/validation/core/integration_test/puml_fixture.bzl @@ -17,14 +17,18 @@ load( "//bazel/rules/rules_score:providers.bzl", "ArchitecturalDesignInfo", "UnitDesignInfo", + "UnitInfo", ) def _collect_fbs_files(deps): files_by_category = { "component": [], - "class": [], "internal_api": [], "sequence": [], + "unit_design_class": [], + "unit_design_sequence": [], + "unit_implementation_class": [], + "unit_implementation_sequence": [], } for dep in deps: @@ -41,8 +45,16 @@ def _collect_fbs_files(deps): class_files = dep[UnitDesignInfo].static.to_list() unit_dynamic_files = dep[UnitDesignInfo].dynamic.to_list() - files_by_category["class"].extend(class_files) - files_by_category["sequence"].extend(unit_dynamic_files) + files_by_category["unit_design_class"].extend(class_files) + files_by_category["unit_design_sequence"].extend(unit_dynamic_files) + + if UnitInfo in dep: + files_by_category["unit_implementation_class"].extend( + dep[UnitInfo].implementation_class_fbs.to_list(), + ) + files_by_category["unit_implementation_sequence"].extend( + dep[UnitInfo].implementation_sequence_fbs.to_list(), + ) return files_by_category @@ -77,9 +89,12 @@ def _provider_fbs_fixture_bundle_impl(ctx): generated.append(out) _materialize_category("component") - _materialize_category("class") _materialize_category("internal_api") _materialize_category("sequence") + _materialize_category("unit_design_class") + _materialize_category("unit_design_sequence") + _materialize_category("unit_implementation_class") + _materialize_category("unit_implementation_sequence") return [DefaultInfo(files = depset(generated))] diff --git a/validation/core/integration_test/src/lib.rs b/validation/core/integration_test/src/lib.rs index da19a184..e677b4f7 100644 --- a/validation/core/integration_test/src/lib.rs +++ b/validation/core/integration_test/src/lib.rs @@ -15,5 +15,6 @@ mod test_framework; pub use test_framework::{ assert_cli_result, case_file_path, collect_case_fbs_files, load_expected_fixture, - run_validation_profile, CliRunResult, ExpectedFixture, ValidationIntegrationCase, + load_expected_yaml_fixture, run_validation_profile, CliRunResult, ExpectedFixture, + ValidationIntegrationCase, }; diff --git a/validation/core/integration_test/src/test_framework.rs b/validation/core/integration_test/src/test_framework.rs index e137d13e..08946884 100644 --- a/validation/core/integration_test/src/test_framework.rs +++ b/validation/core/integration_test/src/test_framework.rs @@ -11,7 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 // ******************************************************************************* -use serde::Deserialize; +use serde::{Deserialize, Deserializer}; use serde_json::Value; use std::fs; use std::path::PathBuf; @@ -24,11 +24,33 @@ pub struct ValidationIntegrationCase { } #[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] pub struct ExpectedFixture { pub should_pass: bool, + #[serde(default, deserialize_with = "deserialize_error_contains")] pub error_contains: Vec, } +#[derive(Debug, Deserialize)] +#[serde(untagged)] +enum ExpectedErrorContains { + Single(String), + Multiple(Vec), +} + +fn deserialize_error_contains<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let expected_error_contains = Option::::deserialize(deserializer)?; + + Ok(match expected_error_contains { + Some(ExpectedErrorContains::Single(fragment)) => vec![fragment], + Some(ExpectedErrorContains::Multiple(fragments)) => fragments, + None => Vec::new(), + }) +} + pub struct CliRunResult { pub success: bool, pub stderr: String, @@ -97,6 +119,14 @@ pub fn load_expected_fixture(suite_dir: &str, case_dir: &str) -> ExpectedFixture serde_json::from_str(&expected_json).expect("failed to parse expected fixture") } +pub fn load_expected_yaml_fixture(suite_dir: &str, case_dir: &str) -> ExpectedFixture { + let expected_yaml = read_case_file(&format!( + "validation/core/integration_test/{suite_dir}/{case_dir}/expected.yaml" + )); + + serde_yaml::from_str(&expected_yaml).expect("failed to parse expected YAML fixture") +} + pub fn assert_cli_result(case_dir: &str, expected: &ExpectedFixture, result: &CliRunResult) { assert_eq!( result.success, expected.should_pass,