-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add error module and wrap all valid module errors
Add the `error` module, defining an Error enum using `thiserror`. Create variants for all of the errors generated by the `valid` module, and replace its custom `ValidationError` enum. Includes tests for each variant. Then teach that module to return only our errors. Note the special treatment for these error conversions: * `boon::ValidationError`s use lifetimes to hang on to values from the boon compiler and from the JSON that fails validation. This makes it quite tricky to use separate from those values. But since, so far, we just want to print JSON Schema validation errors, add a `From` trait implementation that simply copies its string value into our error type. This allows all the lifetime annotations to be removed from the `valid` crate. * `wax::GlobError` is an enum that wraps the two types that the `wax` create generates. To coerce those two types, add a `From` trait for each. While at it, improve the error generation for the custom `license` format so that the error message generated by boon is more legible and useful. Previously it just showed the value that failed --- twice --- but now it also shows the "reason" for the error. Also: change the behavior of `is_license` and `is_path` to return `Ok(())` if the value is not a string, following the example of the format validation functions in boon itself. New tests for the `license` and `path` custom formats validate the usability of the error messages.
- Loading branch information
Showing
8 changed files
with
287 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
//! PGXN Meta Errors. | ||
|
||
#[cfg(test)] | ||
mod tests; | ||
|
||
/// Build errors. | ||
#[derive(thiserror::Error, Debug)] | ||
pub enum Error { | ||
/// License Error. | ||
#[error("{}", .0.reason)] | ||
License(#[from] spdx::error::ParseError), | ||
|
||
/// Validator cannot determine the version of the meta spec. | ||
#[error("Cannot determine meta-spec version")] | ||
UnknownSpec, | ||
|
||
/// A schema file has no `$id` property. | ||
#[error("No $id found in schema")] | ||
UnknownSchemaId, | ||
|
||
/// JSON Schema compile error. | ||
#[error(transparent)] | ||
#[allow(clippy::enum_variant_names)] | ||
CompileError(#[from] boon::CompileError), | ||
|
||
/// JSON Schema validation error. | ||
#[error("{0}")] | ||
#[allow(clippy::enum_variant_names)] | ||
ValidationError(String), | ||
|
||
/// Serde JSON error. | ||
#[error(transparent)] | ||
Serde(#[from] serde_json::Error), | ||
|
||
/// IO error. | ||
#[error(transparent)] | ||
Io(#[from] std::io::Error), | ||
|
||
/// Glob build error. | ||
#[error(transparent)] | ||
Glob(#[from] wax::GlobError), | ||
} | ||
|
||
impl<'s, 'v> From<boon::ValidationError<'s, 'v>> for Error { | ||
fn from(value: boon::ValidationError<'s, 'v>) -> Self { | ||
Self::ValidationError(value.to_string()) | ||
} | ||
} | ||
|
||
impl From<wax::BuildError> for Error { | ||
fn from(value: wax::BuildError) -> Self { | ||
wax::GlobError::Build(value).into() | ||
} | ||
} | ||
|
||
impl From<wax::WalkError> for Error { | ||
fn from(value: wax::WalkError) -> Self { | ||
wax::GlobError::Walk(value).into() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
use super::*; | ||
use serde_json::json; | ||
|
||
#[test] | ||
fn spdx() { | ||
let parse_error = spdx::Expression::parse("not a license").unwrap_err(); | ||
let exp = parse_error.reason.to_string(); | ||
let not_exp = parse_error.to_string(); | ||
let err: Error = parse_error.into(); | ||
assert!(matches!(err, Error::License { .. })); | ||
assert_eq!(exp, err.to_string()); | ||
assert_ne!(not_exp, err.to_string()); | ||
} | ||
|
||
#[test] | ||
fn unknown_spec() { | ||
assert_eq!( | ||
Error::UnknownSpec.to_string(), | ||
"Cannot determine meta-spec version" | ||
) | ||
} | ||
|
||
#[test] | ||
fn unknown_schema_id() { | ||
assert_eq!(Error::UnknownSchemaId.to_string(), "No $id found in schema") | ||
} | ||
|
||
#[test] | ||
fn compile() { | ||
let mut c = boon::Compiler::new(); | ||
c.add_resource("foo", json!("not a schema")).unwrap(); | ||
let mut s = boon::Schemas::new(); | ||
let compile_err = c.compile("foo", &mut s).unwrap_err(); | ||
let exp = compile_err.to_string(); | ||
let err: Error = compile_err.into(); | ||
assert!(matches!(err, Error::CompileError { .. })); | ||
assert_eq!(exp, err.to_string(),); | ||
} | ||
|
||
#[test] | ||
fn validation() { | ||
let mut c = boon::Compiler::new(); | ||
c.add_resource("foo", json!({"type": "object"})).unwrap(); | ||
let mut s = boon::Schemas::new(); | ||
let idx = c.compile("foo", &mut s).unwrap(); | ||
let json = json!([]); | ||
let valid_err = s.validate(&json, idx).unwrap_err(); | ||
let exp = valid_err.to_string(); | ||
let err: Error = valid_err.into(); | ||
assert!(matches!(err, Error::ValidationError { .. })); | ||
assert_eq!(exp, err.to_string()); | ||
} | ||
|
||
#[test] | ||
fn serde() { | ||
let serde_err = serde_json::from_str::<String>("[]").unwrap_err(); | ||
let exp = serde_err.to_string(); | ||
let err: Error = serde_err.into(); | ||
assert!(matches!(err, Error::Serde { .. })); | ||
assert_eq!(exp, err.to_string()); | ||
} | ||
|
||
#[test] | ||
fn io() { | ||
use std::io; | ||
let io_error = io::Error::new(io::ErrorKind::Other, "oh no!"); | ||
let exp = io_error.to_string(); | ||
let err: Error = io_error.into(); | ||
assert!(matches!(err, Error::Io { .. })); | ||
assert_eq!(exp, err.to_string()); | ||
} | ||
|
||
#[test] | ||
fn glob() { | ||
let build_err = wax::Glob::new("[].json").unwrap_err(); | ||
let exp = build_err.to_string(); | ||
let err: Error = build_err.into(); | ||
assert!(matches!(err, Error::Glob { .. })); | ||
assert_eq!(exp, err.to_string()); | ||
|
||
let glob = wax::Glob::new("*.json").unwrap(); | ||
for path in glob.walk("nonesuch 😇") { | ||
// Would be nice to just fetch the first, but should always be an | ||
// error anyway. | ||
let walk_err = path.unwrap_err(); | ||
let exp = walk_err.to_string(); | ||
let err: Error = walk_err.into(); | ||
assert!(matches!(err, Error::Glob { .. })); | ||
assert_eq!(exp, err.to_string()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.