lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit 9bca132bc98fcc3c13147a5f6e8f74aab831106b
parent eddf259ff2b4d679fba13265168c94a09d12da2a
Author: triesap <tyson@radroots.org>
Date:   Sat, 18 Jul 2026 08:44:35 +0000

mesh_agent_proto: close semantic schema coverage

- Cover lexer comments, escapes, malformed tokens, and ignored annotations.
- Reject duplicate declarations, parser edge cases, and schema ordinal drift.
- Remove redundant keyword validation after guarded parser dispatch.
- Verify strict Clippy, all tests, and the 100 percent coverage gate.

Diffstat:
Mcrates/mesh_agent_proto/src/lib.rs | 1+
Mcrates/mesh_agent_proto/src/schema_validation.rs | 16++++++----------
Mcrates/mesh_agent_proto/tests/schema.rs | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 79 insertions(+), 10 deletions(-)

diff --git a/crates/mesh_agent_proto/src/lib.rs b/crates/mesh_agent_proto/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(coverage_nightly, feature(coverage_attribute))] #![no_std] #![forbid(unsafe_code)] diff --git a/crates/mesh_agent_proto/src/schema_validation.rs b/crates/mesh_agent_proto/src/schema_validation.rs @@ -196,6 +196,7 @@ const ERROR_FIELDS: &[RequiredField] = &[ field("MeshAgentError", "message", 1, "Text"), ]; +#[cfg_attr(coverage_nightly, coverage(off))] const fn field( owner: &'static str, name: &'static str, @@ -210,6 +211,7 @@ const fn field( } } +#[cfg_attr(coverage_nightly, coverage(off))] const fn variant(owner: &'static str, name: &'static str, ordinal: u16) -> RequiredVariant { RequiredVariant { owner, @@ -218,10 +220,12 @@ const fn variant(owner: &'static str, name: &'static str, ordinal: u16) -> Requi } } +#[cfg_attr(coverage_nightly, coverage(off))] const fn forbidden_field(owner: &'static str, name: &'static str) -> ForbiddenField { ForbiddenField { owner, name } } +#[cfg_attr(coverage_nightly, coverage(off))] const fn forbidden_variant(owner: &'static str, name: &'static str) -> ForbiddenVariant { ForbiddenVariant { owner, name } } @@ -477,12 +481,14 @@ impl SchemaParser { Some(SchemaToken::Symbol('$')) => self.parse_annotation(&mut ast)?, Some(SchemaToken::Ident(value)) if value == "using" => self.skip_statement()?, Some(SchemaToken::Ident(value)) if value == "struct" => { + self.index += 1; let (name, decl) = self.parse_struct()?; if ast.structs.insert(name, decl).is_some() { return Err(RadrootsMeshAgentProtoError::InvalidSchema); } } Some(SchemaToken::Ident(value)) if value == "enum" => { + self.index += 1; let (name, decl) = self.parse_enum()?; if ast.enums.insert(name, decl).is_some() { return Err(RadrootsMeshAgentProtoError::InvalidSchema); @@ -526,7 +532,6 @@ impl SchemaParser { } fn parse_struct(&mut self) -> Result<(String, StructDecl), RadrootsMeshAgentProtoError> { - self.expect_ident_value("struct")?; let name = self.expect_ident()?; self.expect_symbol('{')?; let mut fields = BTreeMap::new(); @@ -555,7 +560,6 @@ impl SchemaParser { } fn parse_enum(&mut self) -> Result<(String, EnumDecl), RadrootsMeshAgentProtoError> { - self.expect_ident_value("enum")?; let name = self.expect_ident()?; self.expect_symbol('{')?; let mut variants = BTreeMap::new(); @@ -633,14 +637,6 @@ impl SchemaParser { } } - fn expect_ident_value(&mut self, expected: &str) -> Result<(), RadrootsMeshAgentProtoError> { - if self.consume_ident(expected) { - Ok(()) - } else { - Err(RadrootsMeshAgentProtoError::InvalidSchema) - } - } - fn expect_ident(&mut self) -> Result<String, RadrootsMeshAgentProtoError> { match self.peek().cloned() { Some(SchemaToken::Ident(value)) => { diff --git a/crates/mesh_agent_proto/tests/schema.rs b/crates/mesh_agent_proto/tests/schema.rs @@ -408,6 +408,10 @@ fn schema_validator_rejects_duplicate_incompatible_declarations() { fn schema_validator_rejects_type_drift() { let request_type_drift = RADROOTS_MESH_AGENT_SCHEMA.replace(" frameCbor @2 :Data;", " frameCbor @2 :Text;"); + let request_ordinal_drift = + RADROOTS_MESH_AGENT_SCHEMA.replace(" frameCbor @2 :Data;", " frameCbor @9 :Data;"); + let request_numeric_type_drift = + RADROOTS_MESH_AGENT_SCHEMA.replace(" frameCbor @2 :Data;", " frameCbor @2 :123;"); let status_type_drift = RADROOTS_MESH_AGENT_SCHEMA.replace( " includeTransports @0 :Bool;", " includeTransports @0 :Text;", @@ -418,12 +422,80 @@ fn schema_validator_rejects_type_drift() { Err(RadrootsMeshAgentProtoError::MissingRequest) ); assert_eq!( + validate_schema_text(request_ordinal_drift.as_str()), + Err(RadrootsMeshAgentProtoError::MissingRequest) + ); + assert_eq!( + validate_schema_text(request_numeric_type_drift.as_str()), + Err(RadrootsMeshAgentProtoError::MissingRequest) + ); + assert_eq!( validate_schema_text(status_type_drift.as_str()), Err(RadrootsMeshAgentProtoError::MissingStatusSurface) ); } #[test] +fn schema_validator_accepts_lexical_trivia_and_ignored_statements() { + let decorated = format!( + "# hash comment\n// slash comment\n/* *x*/\nusing Escaped = import \"schema\\\\\\\"name\";\n$Other.annotation(\"ignored\");\n;\n{RADROOTS_MESH_AGENT_SCHEMA}" + ); + + assert_eq!(validate_schema_text(decorated.as_str()), Ok(())); +} + +#[test] +fn schema_validator_rejects_malformed_lexical_and_parser_edges() { + let malformed = [ + "!", + "/", + "/* unterminated", + "\"unterminated", + "\"trailing\\", + "using Alias", + "@;", + "@1", + "$Cxx.namespace(value);", + "struct", + "struct A", + "struct A { field @x :Text; }", + "struct A { field @0 Text; }", + "struct A { field @0 :; }", + "struct A { field @0 :Text", + "struct A { field @0 :\"Text\"; }", + "struct A { field @0 :@; }", + "enum A { value @0 }", + "enum A { value @65536; }", + "bogus", + "@1; @2;", + "$Cxx.namespace(\"a\"); $Cxx.namespace(\"b\");", + "struct A {} struct A {}", + "enum A {} enum A {}", + "enum A { first @0; second @0; }", + "enum A { first @0; first @1; }", + ]; + + for schema in malformed { + assert_eq!( + validate_schema_text(schema), + Err(RadrootsMeshAgentProtoError::InvalidSchema), + "{schema}" + ); + } +} + +#[test] +fn schema_validator_ignores_non_namespace_annotations() { + for schema in ["#", "$Other;", "$Cxx;", "$Cxx.other;", "$Cxx.namespace;"] { + assert_eq!( + validate_schema_text(schema), + Err(RadrootsMeshAgentProtoError::MissingSchemaId), + "{schema}" + ); + } +} + +#[test] fn mesh_agent_proto_errors_have_stable_display_strings() { let cases = [ (