2021-09-29 09:16:28 +03:00
use anyhow ::{ bail , Error } ;
use serde_json ::{ json , Value } ;
2021-10-07 10:36:06 +03:00
use proxmox_schema ::* ;
2021-09-29 09:16:28 +03:00
static STRING_SCHEMA : Schema = StringSchema ::new ( " A test string " ) . schema ( ) ;
2021-12-07 13:53:18 +03:00
static SIMPLE_OBJECT_SCHEMA : Schema = ObjectSchema ::new (
2021-09-29 09:16:28 +03:00
" simple object schema " ,
& [
( " prop1 " , false , & STRING_SCHEMA ) ,
( " prop2 " , true , & STRING_SCHEMA ) ,
( " prop3 " , false , & STRING_SCHEMA ) ,
2021-12-07 13:53:18 +03:00
] ,
)
. schema ( ) ;
2021-09-29 09:16:28 +03:00
2021-09-29 09:59:28 +03:00
static SIMPLE_PROPERTY_STRING_SCHEMA : Schema = StringSchema ::new ( " simple property string " )
. format ( & ApiStringFormat ::PropertyString ( & SIMPLE_OBJECT_SCHEMA ) )
. schema ( ) ;
2021-09-29 09:16:28 +03:00
static SIMPLE_ARRAY_SCHEMA : Schema = ArraySchema ::new ( " String list. " , & STRING_SCHEMA ) . schema ( ) ;
2021-12-07 13:53:18 +03:00
static NESTED_OBJECT_SCHEMA : Schema = ObjectSchema ::new (
2021-09-29 09:16:28 +03:00
" nested object schema " ,
& [
( " arr1 " , false , & SIMPLE_ARRAY_SCHEMA ) ,
( " obj1 " , false , & SIMPLE_OBJECT_SCHEMA ) ,
( " prop1 " , false , & STRING_SCHEMA ) ,
2021-12-07 13:53:18 +03:00
] ,
)
. schema ( ) ;
2021-09-29 09:16:28 +03:00
2021-12-07 13:53:18 +03:00
static NESTED_PROPERTY_SCHEMA : Schema = ObjectSchema ::new (
2021-09-29 09:59:28 +03:00
" object with property strings " ,
2021-12-07 13:53:18 +03:00
& [ ( " ps1 " , false , & SIMPLE_PROPERTY_STRING_SCHEMA ) ] ,
)
. schema ( ) ;
2021-09-29 09:59:28 +03:00
2021-12-07 13:53:18 +03:00
fn compare_error ( expected : & [ ( & str , & str ) ] , err : Error ) -> Result < ( ) , Error > {
2021-09-29 09:16:28 +03:00
let err = match err . downcast_ref ::< ParameterError > ( ) {
Some ( err ) = > err ,
None = > bail! ( " unable to downcast error: {} " , err ) ,
} ;
2021-10-07 10:36:06 +03:00
let result = ( move | | {
2021-09-29 09:16:28 +03:00
let errors = err . errors ( ) ;
if errors . len ( ) ! = expected . len ( ) {
2021-12-07 13:53:18 +03:00
bail! (
" error list has different length: {} != {} " ,
expected . len ( ) ,
errors . len ( )
) ;
2021-09-29 09:16:28 +03:00
}
for i in 0 .. expected . len ( ) {
if expected [ i ] . 0 ! = errors [ i ] . 0 {
2021-12-07 13:53:18 +03:00
bail! (
" error {} path differs: '{}' != '{}' " ,
i ,
expected [ i ] . 0 ,
errors [ i ] . 0
) ;
2021-09-29 09:16:28 +03:00
}
if expected [ i ] . 1 ! = errors [ i ] . 1. to_string ( ) {
2021-12-07 13:53:18 +03:00
bail! (
" error {} message differs: '{}' != '{}' " ,
i ,
expected [ i ] . 1 ,
errors [ i ] . 1
) ;
2021-09-29 09:16:28 +03:00
}
}
Ok ( ( ) )
2021-10-07 10:36:06 +03:00
} ) ( ) ;
2021-09-29 09:16:28 +03:00
if result . is_err ( ) {
println! ( " GOT: {:?} " , err ) ;
}
result
}
fn test_verify (
schema : & Schema ,
data : & Value ,
expected_errors : & [ ( & str , & str ) ] ,
) -> Result < ( ) , Error > {
2021-12-17 10:07:02 +03:00
match schema . verify_json ( data ) {
2021-09-29 09:16:28 +03:00
Ok ( _ ) = > bail! ( " expected errors, but got Ok() " ) ,
Err ( err ) = > compare_error ( expected_errors , err ) ? ,
}
Ok ( ( ) )
}
#[ test ]
fn verify_simple_object ( ) -> Result < ( ) , Error > {
let simple_value = json! ( { " prop1 " : 1 , " prop4 " : " abc " } ) ;
test_verify (
& SIMPLE_OBJECT_SCHEMA ,
& simple_value ,
& [
( " prop1 " , " Expected string value. " ) ,
( " prop4 " , " schema does not allow additional properties. " ) ,
( " prop3 " , " property is missing and it is not optional. " ) ,
] ,
) ? ;
Ok ( ( ) )
}
#[ test ]
fn verify_nested_object1 ( ) -> Result < ( ) , Error > {
let nested_value = json! ( { " prop1 " : 1 , " prop4 " : " abc " } ) ;
test_verify (
& NESTED_OBJECT_SCHEMA ,
& nested_value ,
& [
( " prop1 " , " Expected string value. " ) ,
( " prop4 " , " schema does not allow additional properties. " ) ,
( " arr1 " , " property is missing and it is not optional. " ) ,
( " obj1 " , " property is missing and it is not optional. " ) ,
] ,
) ? ;
Ok ( ( ) )
}
#[ test ]
fn verify_nested_object2 ( ) -> Result < ( ) , Error > {
let nested_value = json! ( { " prop1 " : 1 , " prop4 " : " abc " , " obj1 " : { } , " arr1 " : [ " abc " , 0 ] } ) ;
test_verify (
& NESTED_OBJECT_SCHEMA ,
& nested_value ,
& [
( " arr1/[1] " , " Expected string value. " ) ,
( " obj1/prop1 " , " property is missing and it is not optional. " ) ,
( " obj1/prop3 " , " property is missing and it is not optional. " ) ,
( " prop1 " , " Expected string value. " ) ,
( " prop4 " , " schema does not allow additional properties. " ) ,
] ,
) ? ;
Ok ( ( ) )
}
2021-09-29 09:59:28 +03:00
#[ test ]
fn verify_nested_property1 ( ) -> Result < ( ) , Error > {
let value = json! ( { " ps1 " : " abc " } ) ;
test_verify (
& NESTED_PROPERTY_SCHEMA ,
& value ,
2021-12-07 13:53:18 +03:00
& [ (
" ps1 " ,
2023-03-06 18:21:17 +03:00
" value without key, but schema does not define a default key " ,
2021-12-07 13:53:18 +03:00
) ] ,
2021-09-29 09:59:28 +03:00
) ? ;
Ok ( ( ) )
}
#[ test ]
fn verify_nested_property2 ( ) -> Result < ( ) , Error > {
let value = json! ( { " ps1 " : " abc=1 " } ) ;
test_verify (
& NESTED_PROPERTY_SCHEMA ,
& value ,
2023-03-06 18:21:17 +03:00
& [
( " ps1/abc " , " schema does not allow additional properties " ) ,
( " ps1/prop1 " , " property is missing and it is not optional " ) ,
( " ps1/prop3 " , " property is missing and it is not optional " ) ,
] ,
2021-09-29 09:59:28 +03:00
) ? ;
Ok ( ( ) )
}
#[ test ]
fn verify_nested_property3 ( ) -> Result < ( ) , Error > {
let value = json! ( { " ps1 " : " " } ) ;
test_verify (
& NESTED_PROPERTY_SCHEMA ,
& value ,
& [
2023-03-06 18:21:17 +03:00
( " ps1/prop1 " , " property is missing and it is not optional " ) ,
( " ps1/prop3 " , " property is missing and it is not optional " ) ,
2021-12-07 13:53:18 +03:00
] ,
2021-09-29 09:59:28 +03:00
) ? ;
Ok ( ( ) )
}