fix(protocol): reject unknown root named types
This commit is contained in:
@@ -315,6 +315,8 @@ pub(crate) fn validate_root_value(
|
|||||||
) -> Result<(), ValidationError> {
|
) -> Result<(), ValidationError> {
|
||||||
descriptor.validate()?;
|
descriptor.validate()?;
|
||||||
let declarations = declaration_map(descriptor)?;
|
let declarations = declaration_map(descriptor)?;
|
||||||
|
validate_type_expr(ty, &declarations)
|
||||||
|
.map_err(|error| error.prepend(PathSegment::Interface(descriptor.name.clone())))?;
|
||||||
validate_value(ty, value, &declarations)
|
validate_value(ty, value, &declarations)
|
||||||
.map_err(|error| error.prepend(PathSegment::Interface(descriptor.name.clone())))
|
.map_err(|error| error.prepend(PathSegment::Interface(descriptor.name.clone())))
|
||||||
}
|
}
|
||||||
@@ -369,7 +371,12 @@ fn validate_value(
|
|||||||
_ => expect_kind(value, ValueKind::Json),
|
_ => expect_kind(value, ValueKind::Json),
|
||||||
},
|
},
|
||||||
TypeExpr::Named(name) => {
|
TypeExpr::Named(name) => {
|
||||||
validate_declared_value(declarations[name.as_str()], value, declarations)
|
let Some(declaration) = declarations.get(name.as_str()) else {
|
||||||
|
return Err(ValidationError::new(ValidationErrorKind::UnknownType {
|
||||||
|
name: name.clone(),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
validate_declared_value(declaration, value, declarations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,6 +233,44 @@ fn named_references_must_exist_and_must_not_cycle() {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let valid = descriptor("catalog");
|
||||||
|
let error = valid
|
||||||
|
.validate_value(&TypeExpr::Named("Elsewhere".into()), &Value::Record(vec![]))
|
||||||
|
.unwrap_err();
|
||||||
|
assert_eq!(
|
||||||
|
error.kind,
|
||||||
|
ValidationErrorKind::UnknownType {
|
||||||
|
name: "Elsewhere".into()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(error.path, vec![PathSegment::Interface("catalog".into())]);
|
||||||
|
|
||||||
|
let error = valid
|
||||||
|
.validate_value(
|
||||||
|
&TypeExpr::Entry {
|
||||||
|
key: Box::new(TypeExpr::String),
|
||||||
|
value: Box::new(TypeExpr::List(Box::new(TypeExpr::Named("Nested".into())))),
|
||||||
|
},
|
||||||
|
&Value::Entry {
|
||||||
|
key: Box::new(Value::String("key".into())),
|
||||||
|
value: Box::new(Value::List(vec![])),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap_err();
|
||||||
|
assert_eq!(
|
||||||
|
error.kind,
|
||||||
|
ValidationErrorKind::UnknownType {
|
||||||
|
name: "Nested".into()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
error.path,
|
||||||
|
vec![
|
||||||
|
PathSegment::Interface("catalog".into()),
|
||||||
|
PathSegment::EntryValue,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
let cyclic = InterfaceDescriptor {
|
let cyclic = InterfaceDescriptor {
|
||||||
name: "cyclic".into(),
|
name: "cyclic".into(),
|
||||||
documentation: None,
|
documentation: None,
|
||||||
|
|||||||
Reference in New Issue
Block a user