chore: Port `json-schema-test-suite` as a local dependency

Signed-off-by: Dmitry Dygalo <dadygalo@gmail.com>
This commit is contained in:
Dmitry Dygalo 2021-07-23 10:13:59 +02:00 committed by Dmitry Dygalo
parent 28b71f64e3
commit bf17e1c8e0
No known key found for this signature in database
GPG Key ID: E2FDD4885D799724
20 changed files with 786 additions and 1 deletions

2
.gitignore vendored
View File

@ -2,9 +2,11 @@
/jsonschema/target
/bindings/*/target
/bench_helpers/target
/jsonschema-test-suite/target
.hypothesis
.benchmarks
/jsonschema/Cargo.lock
/jsonschema-test-suite/Cargo.lock
# IDEs
/.idea

View File

@ -0,0 +1,14 @@
# Changelog
## 0.3.0 (2020-06-29)
* Ignore tests accepts regular expressions
## 0.2.0 (2020-06-22)
* Fix documentation links
* Fix test_name definition in case of mulitple nested directories
## 0.1.0 (2020-06-22)
* Initial Release

View File

@ -0,0 +1,31 @@
[package]
name = "json_schema_test_suite"
version = "0.3.0"
authors = ["Samuele Maci <macisamuele@gmail.com>"]
edition = "2018"
publish = true
readme = "README.md"
keywords = ["jsonschema"]
categories = ["development-tools::procedural-macro-helpers", "development-tools::testing"]
description = "Procedural Macro Attribute to run all the test cases described in JSON-Schema-Test-Suite"
repository = "https://github.com/macisamuele/json-schema-test-suite-rs"
documentation = "http://docs.rs/json-schema-test-suite"
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
path = "src/lib.rs"
[dev-dependencies]
lazy_static = "1"
mockito = "0"
reqwest = { version = "0", default-features = false, features = [ "blocking", "json" ] }
serde_json = "1"
[dependencies]
json_schema_test_suite_proc_macro = { path = "./proc_macro", version = "=0.3.0" }
json_schema_test_suite_test_case = { path = "./test_case", version = "=0.3.0" }
serde_json = "1"
[workspace]
members = ["proc_macro", "test_case"]

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Samuele Maci
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,75 @@
# json_schema_test_suite
[![ci](https://github.com/macisamuele/json-schema-test-suite-rs/workflows/ci/badge.svg)](https://github.com/macisamuele/json-schema-test-suite-rs/actions)
[![codecov](https://codecov.io/gh/macisamuele/json-schema-test-suite-rs/branch/master/graph/badge.svg)](https://codecov.io/gh/macisamuele/json-schema-test-suite-rs)
[![Crates.io](https://img.shields.io/crates/v/json-schema-test-suite.svg)](https://crates.io/crates/json-schema-test-suite)
[![docs.rs](https://docs.rs/json_schema_test_suite/badge.svg)](https://docs.rs/json-schema-test-suite/)
The crate provides a procedural macro attribute that allow to generate all the test cases
described by [JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite).
The main objective is to ensure that for each test a mock server is started and will be able to
capture all the requests, ensuring that tests can be ran only interacting with `cargo test`
In order to ude the procedural macro attribute there are few assumptions that are made:
* [`lazy_static`](https://crates.io/crates/lazy_static) dependency is added into your `[dev-dependencies]`
section of the `Cargo.toml` file
* [`mockito`](https://crates.io/crates/mockito) dependency is added into your `[dev-dependencies]`
section of the `Cargo.toml` file
* [`serde-json`](https://crates.io/crates/serde-json) dependency is added into your `[dev-dependencies]`
section of the `Cargo.toml` file
* the annotated method signature should be: `fn (&str, json_schema_test_suite::TestCase) -> ()`
## How to use
### Cargo.toml
```toml
# Ensure that the following lines are present into your Cargo.toml file
[dev-dependencies]
json_schema_test_suite = "0"
# Be careful with dependencies version (using `*` version is never recommended).
# The proc-macro uses nothing fancy with the dependencies, so any version should work well :)
lazy_static = "*"
mockito = "*"
serde_json = "*"
```
### Rust test file example
```rust
use json_schema_test_suite::{json_schema_test_suite, TestCase};
// If no tests should be ignored
#[json_schema_test_suite(
// path separator is assumed to be `/` (regardless of the run platform)
"path/to/JSON-Schema-Test-Suite/repository",
// test directory (in <JSON-Schema-Test-Suite>/tests/<test_directory>)
"draft7"
)]
// If some tests needs to be ignored, just defined them into `{ ... }` as follow
#[json_schema_test_suite(
// path separator is assumed to be `/` (regardless of the run platform)
"path/to/JSON-Schema-Test-Suite/repository",
// test directory (in <JSON-Schema-Test-Suite>/tests/<test_directory>)
"draft6",
{ // Names, as generated by the macro, of the tests to ignore
// NOTE: They can be regular expression as well.
"name of the tests to ignore",
}
)]
fn my_simple_test(
// address of the HTTP server providing the remote files of JSON-Schema-Test-Suite.
// The format will be: `hostname:port`.
// This parameter is passed because by starting a mock server we might not start it
// into `localhost:1234` as expected by JSON-Schema-Test-Suite
server_address: &str,
// Representation of the test case
test_case: TestCase,
) {
// TODO: Add here your testing logic
}
```
License: MIT

View File

@ -0,0 +1,2 @@
/Cargo.lock
/target

View File

@ -0,0 +1,31 @@
[package]
name = "json_schema_test_suite_proc_macro"
version = "0.3.0"
authors = ["Samuele Maci <macisamuele@gmail.com>"]
edition = "2018"
publish = true
keywords = ["jsonschema"]
categories = ["development-tools::procedural-macro-helpers", "development-tools::testing"]
description = "Procedural Macro Attribute to run all the test cases described in JSON-Schema-Test-Suite"
repository = "https://github.com/macisamuele/json-schema-test-suite-rs"
documentation = "http://docs.rs/json-schema-test-suite-proc-macro"
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc-macro = true
path = "src/lib.rs"
[dev-dependencies]
lazy_static = "1"
mockito = "0"
serde_json = "1"
[dependencies]
json_schema_test_suite_test_case = { path = "../test_case", version = "=0.3.0" }
proc-macro2 = "1"
regex = "1"
quote = "1"
serde = { version = "1", features = [ "derive" ] }
serde_json = "1"
syn = "1"

View File

@ -0,0 +1,8 @@
# json_schema_test_suite_proc_macro
This crate is supposed to support [`json_schema_test_suite`](https://crates.io/crates/json_schema_test_suite)
by exporting `json_schema_test_suite` procedural macro.
Please refer to [`json-schema-test-suite-proc-macro` docs](https://docs.rs/json-schema-test-suite) for more informaton.
License: MIT

View File

@ -0,0 +1,48 @@
use regex::Regex;
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
use syn::{
braced,
parse::{Parse, ParseStream},
LitStr, Token,
};
#[derive(Debug)]
pub(crate) struct AttrConfig {
pub(crate) json_schema_test_suite_path: PathBuf,
pub(crate) draft_folder: String,
pub(crate) tests_to_exclude_regex: Vec<Regex>,
}
impl Parse for AttrConfig {
fn parse(input: ParseStream) -> Result<Self, syn::Error> {
let json_schema_test_suite_path_str: String = input.parse::<LitStr>()?.value();
let _ = input.parse::<Token![,]>()?;
let draft_folder: String = input.parse::<LitStr>()?.value();
let tests_to_exclude_regex: Vec<Regex> = if input.parse::<Token![,]>().is_ok() {
let tests_to_exclude_tokens = {
let braced_content;
braced!(braced_content in input);
#[allow(clippy::redundant_closure_for_method_calls)]
let res: syn::punctuated::Punctuated<LitStr, Token![,]> =
braced_content.parse_terminated(|v| v.parse())?;
res
};
tests_to_exclude_tokens
.iter()
.filter_map(|content| Regex::new(&format!("^{}$", content.value())).ok())
.collect()
} else {
vec![]
};
let json_schema_test_suite_path =
Path::new(&json_schema_test_suite_path_str.replace("/", &MAIN_SEPARATOR.to_string()))
.to_path_buf();
Ok(Self {
json_schema_test_suite_path,
draft_folder,
tests_to_exclude_regex,
})
}
}

View File

@ -0,0 +1,138 @@
//! This crate is supposed to support [`json_schema_test_suite`](https://crates.io/crates/json_schema_test_suite)
//! by exporting `json_schema_test_suite` procedural macro.
//!
//! Please refer to [`json-schema-test-suite-proc-macro` docs](https://docs.rs/json-schema-test-suite) for more informaton.
#![warn(
clippy::cast_possible_truncation,
clippy::doc_markdown,
clippy::explicit_iter_loop,
clippy::match_same_arms,
clippy::needless_borrow,
clippy::needless_pass_by_value,
clippy::option_map_unwrap_or,
clippy::option_map_unwrap_or_else,
clippy::option_unwrap_used,
clippy::pedantic,
clippy::print_stdout,
clippy::redundant_closure,
clippy::result_map_unwrap_or_else,
clippy::result_unwrap_used,
clippy::trivially_copy_pass_by_ref,
missing_debug_implementations,
missing_docs,
trivial_casts,
unreachable_pub,
unsafe_code,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_results,
variant_size_differences
)]
mod attribute_config;
mod mockito_mocks;
mod test_case;
use json_schema_test_suite_test_case::TestCase;
use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{format_ident, quote};
use regex::Regex;
use syn::{parse_macro_input, Ident, ItemFn};
fn test_token_stream(
tests_to_ignore_regex: &[Regex],
wrapped_test_ident: &Ident,
test: &TestCase,
) -> TokenStream2 {
let name = Ident::new(&test.name, Span::call_site());
let maybe_ignore = if tests_to_ignore_regex
.iter()
.any(|regex| regex.is_match(&test.name))
{
quote! { #[ignore] }
} else {
quote! {}
};
let wrapped_test_case = test_case::WrappedTestCase::from(test);
quote! {
#[test]
#maybe_ignore
fn #name() {
setup_mocks();
super::#wrapped_test_ident(
&mockito::server_address().to_string(),
#wrapped_test_case,
);
}
}
}
/// Procedural macro that allows a test to be executed for all the configurations defined
/// by [JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite)
///
/// The `proc_macro_attribute` should be used on a function with the current signature
/// ```rust
/// # use json_schema_test_suite_test_case::TestCase;
/// fn my_simple_test(
/// // address of the HTTP server providing the remote files of JSON-Schema-Test-Suite. The format will be: `hostname:port`
/// // This parameter is passed because by starting a mock server we might not start it into `localhost:1234` as expected by JSON-Schema-Test-Suite
/// server_address: &str,
/// // Representation of the test case (includes draft_version, descriptions, schema, instance, expected_valid)
/// test_case: TestCase,
/// ) {
/// // TODO: Add here your testing logic
/// }
/// ```
#[proc_macro_attribute]
pub fn json_schema_test_suite(attr: TokenStream, item: TokenStream) -> TokenStream {
let proc_macro_attributes = parse_macro_input!(attr as attribute_config::AttrConfig);
let item_fn = parse_macro_input!(item as ItemFn);
let original_function_ident = &item_fn.sig.ident;
let tests_token_stream: Vec<TokenStream2> = test_case::load(
&proc_macro_attributes.json_schema_test_suite_path,
&proc_macro_attributes.draft_folder,
)
.iter()
.map(|test| {
test_token_stream(
&proc_macro_attributes.tests_to_exclude_regex,
original_function_ident,
test,
)
})
.collect();
let setup_mockito_mocks_token_stream =
mockito_mocks::setup(&proc_macro_attributes.json_schema_test_suite_path);
let mod_name = format_ident!(
"{}_{}",
original_function_ident,
proc_macro_attributes.draft_folder.replace("-", "_")
);
let output = quote! {
#item_fn
mod #mod_name {
lazy_static::lazy_static! {
static ref MOCKS: Vec<mockito::Mock> = vec![
#(#setup_mockito_mocks_token_stream),*
];
}
fn setup_mocks() {
// Dereference to ensure that lazy_static actually invokes the mocks creation
let _ = *MOCKS;
}
#(#tests_token_stream)*
}
};
output.into()
}

View File

@ -0,0 +1,59 @@
use proc_macro2::TokenStream;
use quote::quote;
use std::{fs, path::Path};
pub(crate) fn setup(json_schema_test_suite_path: &Path) -> Vec<TokenStream> {
fn remote_paths(dir: &Path) -> Vec<String> {
let mut paths = vec![];
for result_entry in fs::read_dir(dir)
.unwrap_or_else(|_| panic!("Remotes directory not found: {}", dir.display()))
{
if let Ok(entry) = result_entry {
let path = entry.path();
if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) {
paths.extend(remote_paths(&path));
} else {
paths.push(path.to_str().map_or_else(
|| {
panic!(
"No issues are expected while converting path={} to string",
path.display()
);
},
ToString::to_string,
));
}
}
}
paths
}
let remote_base_path = json_schema_test_suite_path.join("remotes");
let base_path = remote_base_path.to_str().unwrap_or_else(|| {
panic!(
"No issues are expected while converting remote_base_path={} to string",
remote_base_path.display()
);
});
remote_paths(&remote_base_path)
.iter()
.filter_map(|remote_path| {
let path = remote_path
.trim_start_matches(base_path)
.replace(std::path::MAIN_SEPARATOR, "/");
if let Ok(file_content) = std::fs::read_to_string(remote_path) {
Some(quote! {
mockito::mock("GET", #path)
.with_body(
#file_content
// Replace static links to localhost:1234 to the mockito generated server address
.replace("localhost:1234", &mockito::server_address().to_string())
)
.create()
})
} else {
None
}
})
.collect()
}

View File

@ -0,0 +1,147 @@
pub(crate) use json_schema_test_suite_test_case::TestCase;
use serde::Deserialize;
use serde_json::{from_reader, Value};
use std::{ffi::OsStr, fs, fs::File, path::Path};
#[derive(Debug, Deserialize)]
struct JSONSchemaTest {
data: Value,
description: String,
valid: bool,
}
#[derive(Debug, Deserialize)]
struct JSONSchemaTestGroup {
description: String,
schema: Value,
tests: Vec<JSONSchemaTest>,
}
/// Extract the draft version from the path of the test file.
fn draft_version(json_schema_test_suite_path: &Path, file_path: &Path) -> String {
file_path
.strip_prefix(json_schema_test_suite_path.join("tests"))
.ok()
.and_then(Path::to_str)
.map(|v| v.split(std::path::MAIN_SEPARATOR))
.and_then(|mut v| v.next())
.map_or_else(
|| {
panic!(
"No issues are expected while extracting the draft-version from the file_path. json_schema_test_suite_path={}, file_path={}",
json_schema_test_suite_path.display(),
file_path.display()
)
},
ToString::to_string,
)
}
fn load_inner(json_schema_test_suite_path: &Path, dir: &Path, prefix: &str) -> Vec<TestCase> {
let mut tests = vec![];
for result_entry in
fs::read_dir(dir).unwrap_or_else(|_| panic!("Tests directory not found: {}", dir.display()))
{
if let Ok(entry) = result_entry {
let path = entry.path();
if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) {
tests.extend(load_inner(
json_schema_test_suite_path,
&path,
&format!(
"{}{}_",
prefix,
path.file_name().and_then(OsStr::to_str).unwrap_or_else(|| {
panic!(
"No issues are expected while extracting the filename from path={}",
path.display()
)
})
),
));
} else if let Ok(file_reader) = File::open(&path) {
let test_groups: Vec<JSONSchemaTestGroup> = from_reader(file_reader).unwrap_or_else(|_| {
panic!(
r#"{} does not contain valid content. Expected something like [{{"schema": ..., "tests": [{{"data": ..., "is_valid": ...}}, ...]}}]"#,
path.display()
);
});
tests.extend(test_groups.iter().enumerate().flat_map(|(gid, test_group)| {
test_group
.tests
.iter()
.enumerate()
.map(|(tid, test_case)| TestCase {
name: format!(
"{}{}_{}_{}",
prefix,
path.file_stem()
.and_then(OsStr::to_str)
.unwrap_or_else(|| {
panic!(
"No issues are expected while extracting the filename (without extension) from path={}",
path.display()
);
})
.replace('-', "_"),
gid,
tid
),
draft_version: draft_version(json_schema_test_suite_path, &path),
group_description: test_group.description.clone(),
test_case_description: test_case.description.clone(),
schema: test_group.schema.clone(),
instance: test_case.data.clone(),
is_valid: test_case.valid,
})
.collect::<Vec<_>>()
}))
}
}
}
tests
}
/// Load all the test cases present into `draft_folder`
pub(crate) fn load(json_schema_test_suite_path: &Path, draft_folder: &str) -> Vec<TestCase> {
load_inner(
json_schema_test_suite_path,
&json_schema_test_suite_path.join("tests").join(draft_folder),
"",
)
}
pub(crate) struct WrappedTestCase<'a>(&'a TestCase);
impl<'a> From<&'a TestCase> for WrappedTestCase<'a> {
fn from(value: &'a TestCase) -> Self {
Self(value)
}
}
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
impl<'a> ToTokens for WrappedTestCase<'a> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let name = &self.0.name;
let draft_version = &self.0.draft_version;
let group_description = &self.0.group_description;
let test_case_description = &self.0.test_case_description;
let schema_str = self.0.schema.to_string();
let instance_str = self.0.instance.to_string();
let is_valid = self.0.is_valid;
let output = quote! {
json_schema_test_suite::TestCase {
name: #name.to_string(),
draft_version: #draft_version.to_string(),
group_description: #group_description.to_string(),
test_case_description: #test_case_description.to_string(),
schema: serde_json::from_str(#schema_str).unwrap(),
instance: serde_json::from_str(#instance_str).unwrap(),
is_valid: #is_valid,
}
};
tokens.extend(output);
}
}

View File

@ -0,0 +1,101 @@
//! [![ci](https://github.com/macisamuele/json-schema-test-suite-rs/workflows/ci/badge.svg)](https://github.com/macisamuele/json-schema-test-suite-rs/actions)
//! [![codecov](https://codecov.io/gh/macisamuele/json-schema-test-suite-rs/branch/master/graph/badge.svg)](https://codecov.io/gh/macisamuele/json-schema-test-suite-rs)
//! [![Crates.io](https://img.shields.io/crates/v/json-schema-test-suite.svg)](https://crates.io/crates/json-schema-test-suite)
//! [![docs.rs](https://docs.rs/json_schema_test_suite/badge.svg)](https://docs.rs/json-schema-test-suite/)
//!
//! The crate provides a procedural macro attribute that allow to generate all the test cases
//! described by [JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite).
//!
//! The main objective is to ensure that for each test a mock server is started and will be able to
//! capture all the requests, ensuring that tests can be ran only interacting with `cargo test`
//!
//! In order to ude the procedural macro attribute there are few assumptions that are made:
//!
//! * [`lazy_static`](https://crates.io/crates/lazy_static) dependency is added into your `[dev-dependencies]`
//! section of the `Cargo.toml` file
//! * [`mockito`](https://crates.io/crates/mockito) dependency is added into your `[dev-dependencies]`
//! section of the `Cargo.toml` file
//! * [`serde-json`](https://crates.io/crates/serde-json) dependency is added into your `[dev-dependencies]`
//! section of the `Cargo.toml` file
//! * the annotated method signature should be: `fn (&str, json_schema_test_suite::TestCase) -> ()`
//!
//! # How to use
//!
//! ## Cargo.toml
//!
//! ```toml
//! # Ensure that the following lines are present into your Cargo.toml file
//! [dev-dependencies]
//! json_schema_test_suite = "0"
//! # Be careful with dependencies version (using `*` version is never recommended).
//! # The proc-macro uses nothing fancy with the dependencies, so any version should work well :)
//! lazy_static = "*"
//! mockito = "*"
//! serde_json = "*"
//! ```
//!
//! ## Rust test file example
//!
//! ```rust
//! use json_schema_test_suite::{json_schema_test_suite, TestCase};
//!
//! // If no tests should be ignored
//! #[json_schema_test_suite(
//! // path separator is assumed to be `/` (regardless of the run platform)
//! "path/to/JSON-Schema-Test-Suite/repository",
//! // test directory (in <JSON-Schema-Test-Suite>/tests/<test_directory>)
//! "draft7"
//! )]
//! // If some tests needs to be ignored, just defined them into `{ ... }` as follow
//! #[json_schema_test_suite(
//! // path separator is assumed to be `/` (regardless of the run platform)
//! "path/to/JSON-Schema-Test-Suite/repository",
//! // test directory (in <JSON-Schema-Test-Suite>/tests/<test_directory>)
//! "draft6",
//! { // Names, as generated by the macro, of the tests to ignore
//! // NOTE: They can be regular expression as well.
//! "name of the tests to ignore",
//! }
//! )]
//! fn my_simple_test(
//! // address of the HTTP server providing the remote files of JSON-Schema-Test-Suite.
//! // The format will be: `hostname:port`.
//! // This parameter is passed because by starting a mock server we might not start it
//! // into `localhost:1234` as expected by JSON-Schema-Test-Suite
//! server_address: &str,
//! // Representation of the test case
//! test_case: TestCase,
//! ) {
//! // TODO: Add here your testing logic
//! }
//! ```
#![warn(
clippy::cast_possible_truncation,
clippy::doc_markdown,
clippy::explicit_iter_loop,
clippy::match_same_arms,
clippy::needless_borrow,
clippy::needless_pass_by_value,
clippy::option_map_unwrap_or,
clippy::option_map_unwrap_or_else,
clippy::option_unwrap_used,
clippy::pedantic,
clippy::print_stdout,
clippy::redundant_closure,
clippy::result_map_unwrap_or_else,
clippy::result_unwrap_used,
clippy::trivially_copy_pass_by_ref,
missing_debug_implementations,
missing_docs,
trivial_casts,
unreachable_pub,
unsafe_code,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_results,
variant_size_differences
)]
pub use json_schema_test_suite_proc_macro::json_schema_test_suite;
pub use json_schema_test_suite_test_case::TestCase;

View File

@ -0,0 +1,2 @@
/Cargo.lock
/target

View File

@ -0,0 +1,20 @@
[package]
name = "json_schema_test_suite_test_case"
version = "0.3.0"
authors = ["Samuele Maci <macisamuele@gmail.com>"]
edition = "2018"
publish = true
keywords = ["jsonschema"]
categories = ["development-tools::procedural-macro-helpers", "development-tools::testing"]
description = "Procedural Macro Attribute to run all the test cases described in JSON-Schema-Test-Suite"
repository = "https://github.com/macisamuele/json-schema-test-suite-rs"
documentation = "http://docs.rs/json-schema-test-suite-test-case"
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
path = "src/lib.rs"
[dependencies]
serde = { version = "1", features = [ "derive" ] }
serde_json = "1"

View File

@ -0,0 +1,9 @@
# json_schema_test_suite_test_case
This crate is supposed to support [`json_schema_test_suite`](https://crates.io/crates/json_schema_test_suite)
by exporting the base struct to allow users of `json_schema_test_suite` to have a single entity representing the test information.
This crate is needed because currently, at the time of writing, we are not allowed to export structs from a proc-macro library
Please refer to [`json-schema-test-suite` docs](https://docs.rs/json-schema-test-suite) for more informaton.
License: MIT

View File

@ -0,0 +1,54 @@
//! This crate is supposed to support [`json_schema_test_suite`](https://crates.io/crates/json_schema_test_suite)
//! by exporting the base struct to allow users of `json_schema_test_suite` to have a single entity representing the test information.
//!
//! This crate is needed because currently, at the time of writing, we are not allowed to export structs from a proc-macro library
//! Please refer to [`json-schema-test-suite` docs](https://docs.rs/json-schema-test-suite) for more informaton.
#![warn(
clippy::cast_possible_truncation,
clippy::doc_markdown,
clippy::explicit_iter_loop,
clippy::match_same_arms,
clippy::needless_borrow,
clippy::needless_pass_by_value,
clippy::option_map_unwrap_or,
clippy::option_map_unwrap_or_else,
clippy::option_unwrap_used,
clippy::pedantic,
clippy::print_stdout,
clippy::redundant_closure,
clippy::result_map_unwrap_or_else,
clippy::result_unwrap_used,
clippy::trivially_copy_pass_by_ref,
missing_debug_implementations,
missing_docs,
trivial_casts,
unreachable_pub,
unsafe_code,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_results,
variant_size_differences
)]
use serde_json::Value;
/// Detailed information about the individual test case in JSON-Schema-Test-Suite
#[derive(Clone, Debug)]
pub struct TestCase {
/// Test name (unique identifier)
pub name: String,
/// String representation of the draft version (equialent to the test directory)
/// This is usefull in case your test needs to be aware of the draft version under test
pub draft_version: String,
/// Description of the test group as provided by JSON-Schema-Test-Suite
pub group_description: String,
/// Description of the test group as provided by JSON-Schema-Test-Suite
pub test_case_description: String,
/// Schema to be tested
pub schema: Value,
/// Instance to be validated against the `schema
pub instance: Value,
/// Expected validity status as from JSON-Schema-Test-Suite
pub is_valid: bool,
}

View File

@ -0,0 +1,19 @@
use json_schema_test_suite::{json_schema_test_suite, TestCase};
#[json_schema_test_suite("path/to/JSON-Schema-Test-Suite/repository", "draft7", {"ref_0_0", r"optional_format_regex_0_\d+"})]
fn no_op_test_with_some_failures(server_address: &str, test_case: TestCase) {
if test_case.name == "ref_0_0" {
// Test that failure is properly ignored via the macro argument
panic!("The test should fail, but we ensure that this is ignored")
} else if test_case.name == "ref_0_1" {
// Test that mocks work as expected
match reqwest::blocking::get(&format!("http://{}/integer.json", server_address))
.and_then(reqwest::blocking::Response::json::<serde_json::Value>)
{
Ok(json_resp) => assert_eq!(json_resp, serde_json::json!({"type": "integer"})),
Err(err) => panic!("Issue while interacting with mocks: {:?}", err),
}
} else if test_case.name.starts_with("optional_format_regex_0_") {
panic!("We want to force a falure for all the test named like 'optional_format_regex_0_.*' to ensure that the test ignore list includes them")
}
}

View File

@ -0,0 +1,4 @@
use json_schema_test_suite::{json_schema_test_suite, TestCase};
#[json_schema_test_suite("path/to/JSON-Schema-Test-Suite/repository", "draft7")]
fn no_op_test(_server_address: &str, _test_case: TestCase) {}

View File

@ -39,7 +39,7 @@ fraction = { version = "0.8", default-features = false, features = ["with-bigint
[dev-dependencies]
criterion = ">= 0.1"
mockito = ">= 0"
json_schema_test_suite = ">= 0.3"
json_schema_test_suite = { version = ">= 0.3", path = "../jsonschema-test-suite"}
jsonschema-valid = "0.4.0"
bench_helpers = { path = "../bench_helpers" }
valico = "3.6.0"