mirror of
https://gitlab.com/msrd0/gotham-restful.git
synced 2025-02-23 04:52:28 +00:00
add first tests
This commit is contained in:
parent
5c5c7fc4fb
commit
df3b735429
7 changed files with 108 additions and 22 deletions
|
@ -1,36 +1,38 @@
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- check
|
- test
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
CARGO_HOME: $CI_PROJECT_DIR/cargo
|
CARGO_HOME: $CI_PROJECT_DIR/cargo
|
||||||
|
|
||||||
check-none:
|
test-none:
|
||||||
stage: check
|
stage: test
|
||||||
image: msrd0/rust:alpine
|
image: msrd0/rust:alpine
|
||||||
before_script:
|
before_script:
|
||||||
- cargo -V
|
- cargo -V
|
||||||
script:
|
script:
|
||||||
- cargo check --all --no-default-features
|
- cargo test --all --no-default-features
|
||||||
cache:
|
cache:
|
||||||
paths:
|
paths:
|
||||||
- cargo/
|
- cargo/
|
||||||
- target/
|
- target/
|
||||||
|
|
||||||
check-all:
|
test-all:
|
||||||
stage: check
|
stage: test
|
||||||
image: msrd0/rust:alpine
|
image: msrd0/rust:alpine-tarpaulin
|
||||||
before_script:
|
before_script:
|
||||||
|
- apk add --no-cache bash curl
|
||||||
- cargo -V
|
- cargo -V
|
||||||
script:
|
script:
|
||||||
- cargo check --all --all-features
|
- cargo tarpaulin --all --all-features --exclude-files 'cargo/*' --exclude-files 'example/*' --out Xml
|
||||||
|
- wget -qO- https://codecov.io/bash | bash -s -- -X gcov
|
||||||
cache:
|
cache:
|
||||||
paths:
|
paths:
|
||||||
- cargo/
|
- cargo/
|
||||||
- target/
|
- target/
|
||||||
|
|
||||||
readme:
|
readme:
|
||||||
stage: check
|
stage: test
|
||||||
image: msrd0/rust:alpine-readme
|
image: msrd0/rust:alpine-readme
|
||||||
script:
|
script:
|
||||||
- cargo readme -r gotham_restful -t ../README.tpl >README.md.new
|
- cargo readme -r gotham_restful -t ../README.tpl >README.md.new
|
||||||
|
|
|
@ -30,6 +30,9 @@ openapiv3 = { version = "0.3", optional = true }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
thiserror = "1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
openapi = ["gotham_restful_derive/openapi", "indexmap", "log", "openapiv3"]
|
openapi = ["gotham_restful_derive/openapi", "indexmap", "log", "openapiv3"]
|
||||||
|
|
|
@ -174,7 +174,7 @@ impl<E : Error> ResourceResult for Result<NoContent, E>
|
||||||
fn to_json(&self) -> Result<(StatusCode, String), SerdeJsonError>
|
fn to_json(&self) -> Result<(StatusCode, String), SerdeJsonError>
|
||||||
{
|
{
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Ok(_) => (StatusCode::NO_CONTENT, "".to_string()),
|
Ok(_) => (Self::default_status(), "".to_string()),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err : ResourceError = e.into();
|
let err : ResourceError = e.into();
|
||||||
(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?)
|
(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?)
|
||||||
|
@ -185,12 +185,75 @@ impl<E : Error> ResourceResult for Result<NoContent, E>
|
||||||
#[cfg(feature = "openapi")]
|
#[cfg(feature = "openapi")]
|
||||||
fn schema() -> OpenapiSchema
|
fn schema() -> OpenapiSchema
|
||||||
{
|
{
|
||||||
<()>::schema()
|
<NoContent as ResourceResult>::schema()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "openapi")]
|
#[cfg(feature = "openapi")]
|
||||||
fn default_status() -> StatusCode
|
fn default_status() -> StatusCode
|
||||||
{
|
{
|
||||||
StatusCode::NO_CONTENT
|
NoContent::default_status()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test
|
||||||
|
{
|
||||||
|
use super::*;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
|
#[cfg_attr(feature = "openapi", derive(OpenapiType))]
|
||||||
|
struct Msg
|
||||||
|
{
|
||||||
|
msg : String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Error)]
|
||||||
|
#[error("An Error")]
|
||||||
|
struct MsgError;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn resource_result_ok()
|
||||||
|
{
|
||||||
|
let ok : Result<Msg, MsgError> = Ok(Msg::default());
|
||||||
|
let (status, json) = ok.to_json().expect("didn't expect error response");
|
||||||
|
assert_eq!(status, StatusCode::OK);
|
||||||
|
assert_eq!(json, r#"{"msg":""}"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn resource_result_err()
|
||||||
|
{
|
||||||
|
let err : Result<Msg, MsgError> = Err(MsgError::default());
|
||||||
|
let (status, json) = err.to_json().expect("didn't expect error response");
|
||||||
|
assert_eq!(status, StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
assert_eq!(json, format!(r#"{{"error":true,"message":"{}"}}"#, err.unwrap_err()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn success_always_successfull()
|
||||||
|
{
|
||||||
|
let success : Success<Msg> = Msg::default().into();
|
||||||
|
let (status, json) = success.to_json().expect("didn't expect error response");
|
||||||
|
assert_eq!(status, StatusCode::OK);
|
||||||
|
assert_eq!(json, r#"{"msg":""}"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_content_has_empty_json()
|
||||||
|
{
|
||||||
|
let no_content = NoContent::default();
|
||||||
|
let (status, json) = no_content.to_json().expect("didn't expect error response");
|
||||||
|
assert_eq!(status, StatusCode::NO_CONTENT);
|
||||||
|
assert_eq!(json, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_content_result()
|
||||||
|
{
|
||||||
|
let no_content = NoContent::default();
|
||||||
|
let res_def = no_content.to_json().expect("didn't expect error response");
|
||||||
|
let res_err = Result::<NoContent, MsgError>::Ok(no_content).to_json().expect("didn't expect error response");
|
||||||
|
assert_eq!(res_def, res_err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
|
use quote::quote;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
mod method;
|
mod method;
|
||||||
use method::{expand_method, Method};
|
use method::{expand_method, Method};
|
||||||
|
@ -9,6 +12,18 @@ use resource::expand_resource;
|
||||||
#[cfg(feature = "openapi")]
|
#[cfg(feature = "openapi")]
|
||||||
mod openapi_type;
|
mod openapi_type;
|
||||||
|
|
||||||
|
fn krate() -> TokenStream2
|
||||||
|
{
|
||||||
|
if env::var("CARGO_PKG_NAME").unwrap() == "gotham_restful"
|
||||||
|
{
|
||||||
|
quote!(crate)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
quote!(::gotham_restful)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "openapi")]
|
#[cfg(feature = "openapi")]
|
||||||
#[proc_macro_derive(OpenapiType)]
|
#[proc_macro_derive(OpenapiType)]
|
||||||
pub fn derive_openapi_type(tokens : TokenStream) -> TokenStream
|
pub fn derive_openapi_type(tokens : TokenStream) -> TokenStream
|
||||||
|
|
|
@ -84,11 +84,12 @@ impl Method
|
||||||
|
|
||||||
pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -> TokenStream
|
pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -> TokenStream
|
||||||
{
|
{
|
||||||
|
let krate = super::krate();
|
||||||
let ident = parse_macro_input!(attrs as Ident);
|
let ident = parse_macro_input!(attrs as Ident);
|
||||||
let fun = parse_macro_input!(item as ItemFn);
|
let fun = parse_macro_input!(item as ItemFn);
|
||||||
|
|
||||||
let (ret, is_no_content) = match fun.sig.output {
|
let (ret, is_no_content) = match fun.sig.output {
|
||||||
ReturnType::Default => (quote!(::gotham_restful::NoContent), true),
|
ReturnType::Default => (quote!(#krate::NoContent), true),
|
||||||
ReturnType::Type(_, ty) => (quote!(#ty), false)
|
ReturnType::Type(_, ty) => (quote!(#ty), false)
|
||||||
};
|
};
|
||||||
let args : Vec<(TokenStream2, TokenStream2)> = fun.sig.inputs.iter().map(|arg| match arg {
|
let args : Vec<(TokenStream2, TokenStream2)> = fun.sig.inputs.iter().map(|arg| match arg {
|
||||||
|
@ -103,15 +104,15 @@ pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -
|
||||||
generics.push(quote!(#ret));
|
generics.push(quote!(#ret));
|
||||||
let args : Vec<TokenStream2> = args.into_iter().map(|(pat, ty)| quote!(#pat : #ty)).collect();
|
let args : Vec<TokenStream2> = args.into_iter().map(|(pat, ty)| quote!(#pat : #ty)).collect();
|
||||||
let block = fun.block.stmts;
|
let block = fun.block.stmts;
|
||||||
let ret_stmt = if is_no_content { Some(quote!(#ret::default())) } else { None };
|
let ret_stmt = if is_no_content { Some(quote!(Default::default())) } else { None };
|
||||||
|
|
||||||
let trait_ident = method.trait_ident();
|
let trait_ident = method.trait_ident();
|
||||||
let fn_ident = method.fn_ident();
|
let fn_ident = method.fn_ident();
|
||||||
let setup_ident = method.setup_ident();
|
let setup_ident = method.setup_ident();
|
||||||
|
|
||||||
let output = quote! {
|
let output = quote! {
|
||||||
impl ::gotham_restful::#trait_ident<#(#generics),*> for #ident
|
impl #krate::#trait_ident<#(#generics),*> for #ident
|
||||||
where #ident : ::gotham_restful::Resource
|
where #ident : #krate::Resource
|
||||||
{
|
{
|
||||||
fn #fn_ident(#(#args),*) -> #ret
|
fn #fn_ident(#(#args),*) -> #ret
|
||||||
{
|
{
|
||||||
|
@ -121,7 +122,7 @@ pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deny(dead_code)]
|
#[deny(dead_code)]
|
||||||
fn #setup_ident<D : ::gotham_restful::DrawResourceRoutes>(route : &mut D)
|
fn #setup_ident<D : #krate::DrawResourceRoutes>(route : &mut D)
|
||||||
{
|
{
|
||||||
route.#fn_ident::<#ident, #(#generics),*>();
|
route.#fn_ident::<#ident, #(#generics),*>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,7 @@ fn expand_field(field : &Field) -> TokenStream2
|
||||||
|
|
||||||
pub fn expand_struct(input : ItemStruct) -> TokenStream2
|
pub fn expand_struct(input : ItemStruct) -> TokenStream2
|
||||||
{
|
{
|
||||||
|
let krate = super::krate();
|
||||||
let ident = input.ident;
|
let ident = input.ident;
|
||||||
let generics = input.generics;
|
let generics = input.generics;
|
||||||
|
|
||||||
|
@ -126,11 +127,11 @@ pub fn expand_struct(input : ItemStruct) -> TokenStream2
|
||||||
};
|
};
|
||||||
|
|
||||||
quote!{
|
quote!{
|
||||||
impl #generics ::gotham_restful::OpenapiType for #ident #generics
|
impl #generics #krate::OpenapiType for #ident #generics
|
||||||
{
|
{
|
||||||
fn schema() -> ::gotham_restful::OpenapiSchema
|
fn schema() -> #krate::OpenapiSchema
|
||||||
{
|
{
|
||||||
use ::gotham_restful::{export::{openapi::*, IndexMap}, OpenapiSchema};
|
use #krate::{export::{openapi::*, IndexMap}, OpenapiSchema};
|
||||||
|
|
||||||
let mut properties : IndexMap<String, ReferenceOr<Box<Schema>>> = IndexMap::new();
|
let mut properties : IndexMap<String, ReferenceOr<Box<Schema>>> = IndexMap::new();
|
||||||
let mut required : Vec<String> = Vec::new();
|
let mut required : Vec<String> = Vec::new();
|
||||||
|
|
|
@ -28,6 +28,7 @@ impl Parse for MethodList
|
||||||
|
|
||||||
pub fn expand_resource(tokens : TokenStream) -> TokenStream
|
pub fn expand_resource(tokens : TokenStream) -> TokenStream
|
||||||
{
|
{
|
||||||
|
let krate = super::krate();
|
||||||
let input = parse_macro_input!(tokens as ItemStruct);
|
let input = parse_macro_input!(tokens as ItemStruct);
|
||||||
let ident = input.ident;
|
let ident = input.ident;
|
||||||
|
|
||||||
|
@ -43,14 +44,14 @@ pub fn expand_resource(tokens : TokenStream) -> TokenStream
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
let output = quote! {
|
let output = quote! {
|
||||||
impl ::gotham_restful::Resource for #ident
|
impl #krate::Resource for #ident
|
||||||
{
|
{
|
||||||
fn name() -> String
|
fn name() -> String
|
||||||
{
|
{
|
||||||
stringify!(#ident).to_string()
|
stringify!(#ident).to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup<D : ::gotham_restful::DrawResourceRoutes>(mut route : D)
|
fn setup<D : #krate::DrawResourceRoutes>(mut route : D)
|
||||||
{
|
{
|
||||||
#(#methods)*
|
#(#methods)*
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue