@@ -9,6 +9,7 @@ use ansi_term::Colour::{Green, Red};
9
9
use anyhow:: anyhow;
10
10
use base64:: Engine ;
11
11
use base64:: engine:: general_purpose:: STANDARD as BASE64 ;
12
+ use bytes:: Bytes ;
12
13
use itertools:: Itertools ;
13
14
#[ cfg( feature = "xml" ) ] use kiss_xml:: dom:: Element ;
14
15
use maplit:: hashmap;
@@ -250,6 +251,14 @@ impl NodeValue {
250
251
}
251
252
}
252
253
254
+ /// If this value is a byte array, returns it, otherwise returns None
255
+ pub fn as_bytes ( & self ) -> Option < & Vec < u8 > > {
256
+ match self {
257
+ NodeValue :: BARRAY ( b) => Some ( b) ,
258
+ _ => None
259
+ }
260
+ }
261
+
253
262
/// Calculates an AND of two values
254
263
pub fn and ( & self , other : & Self ) -> Self {
255
264
match self {
@@ -386,8 +395,14 @@ impl From<&Element> for NodeValue {
386
395
387
396
impl Matches < NodeValue > for NodeValue {
388
397
fn matches_with ( & self , actual : NodeValue , matcher : & MatchingRule , cascaded : bool ) -> anyhow:: Result < ( ) > {
398
+ self . matches_with ( & actual, matcher, cascaded)
399
+ }
400
+ }
401
+
402
+ impl Matches < & NodeValue > for NodeValue {
403
+ fn matches_with ( & self , actual : & NodeValue , matcher : & MatchingRule , cascaded : bool ) -> anyhow:: Result < ( ) > {
389
404
match self {
390
- NodeValue :: NULL => Value :: Null . matches_with ( actual. as_json ( ) . unwrap_or_default ( ) , matcher, cascaded) ,
405
+ NodeValue :: NULL => actual . matches_with ( actual, matcher, cascaded) ,
391
406
NodeValue :: STRING ( s) => if let Some ( actual_str) = actual. as_string ( ) {
392
407
s. matches_with ( actual_str, matcher, cascaded)
393
408
} else if let Some ( list) = actual. as_slist ( ) {
@@ -425,6 +440,7 @@ impl Matches<NodeValue> for NodeValue {
425
440
} else {
426
441
Err ( anyhow ! ( "Was expecting an XML value but got {}" , actual) )
427
442
} ,
443
+ NodeValue :: BARRAY ( b) => Bytes :: new ( ) . matches_with ( Bytes :: copy_from_slice ( b. as_slice ( ) ) , matcher, cascaded) ,
428
444
_ => Err ( anyhow ! ( "Matching rules can not be applied to {} values" , self . str_form( ) ) )
429
445
}
430
446
}
@@ -1298,6 +1314,22 @@ impl ExecutionPlan {
1298
1314
}
1299
1315
}
1300
1316
1317
+ impl From < ExecutionPlanNode > for ExecutionPlan {
1318
+ fn from ( value : ExecutionPlanNode ) -> Self {
1319
+ ExecutionPlan {
1320
+ plan_root : value
1321
+ }
1322
+ }
1323
+ }
1324
+
1325
+ impl From < & ExecutionPlanNode > for ExecutionPlan {
1326
+ fn from ( value : & ExecutionPlanNode ) -> Self {
1327
+ ExecutionPlan {
1328
+ plan_root : value. clone ( )
1329
+ }
1330
+ }
1331
+ }
1332
+
1301
1333
impl Into < Vec < Mismatch > > for ExecutionPlan {
1302
1334
fn into ( self ) -> Vec < Mismatch > {
1303
1335
let mut result = vec ! [ ] ;
@@ -1862,35 +1894,49 @@ fn setup_body_plan<T: HttpPart>(
1862
1894
) -> anyhow:: Result < ExecutionPlanNode > {
1863
1895
// TODO: Look at the matching rules and generators here
1864
1896
let mut plan_node = ExecutionPlanNode :: container ( "body" ) ;
1897
+ let body_path = DocPath :: body ( ) ;
1865
1898
1866
1899
match & expected. body ( ) {
1867
1900
OptionalBody :: Missing => { }
1868
1901
OptionalBody :: Empty | OptionalBody :: Null => {
1869
1902
plan_node. add ( ExecutionPlanNode :: action ( "expect:empty" )
1870
- . add ( ExecutionPlanNode :: resolve_value ( DocPath :: new ( "$.body" ) ? ) ) ) ;
1903
+ . add ( ExecutionPlanNode :: resolve_value ( body_path ) ) ) ;
1871
1904
}
1872
1905
OptionalBody :: Present ( content, _, _) => {
1873
1906
let content_type = expected. content_type ( ) . unwrap_or_else ( || TEXT . clone ( ) ) ;
1874
- let mut content_type_check_node = ExecutionPlanNode :: action ( "if" ) ;
1875
- content_type_check_node
1876
- . add (
1877
- ExecutionPlanNode :: action ( "match:equality" )
1878
- . add ( ExecutionPlanNode :: value_node ( content_type. to_string ( ) ) )
1879
- . add ( ExecutionPlanNode :: resolve_value ( DocPath :: new ( "$.content-type" ) ?) )
1880
- . add ( ExecutionPlanNode :: value_node ( NodeValue :: NULL ) )
1881
- . add (
1882
- ExecutionPlanNode :: action ( "error" )
1883
- . add ( ExecutionPlanNode :: value_node ( NodeValue :: STRING ( "Body type error - " . to_string ( ) ) ) )
1884
- . add ( ExecutionPlanNode :: action ( "apply" ) )
1885
- )
1886
- ) ;
1887
- if let Some ( plan_builder) = get_body_plan_builder ( & content_type) {
1888
- content_type_check_node. add ( plan_builder. build_plan ( content, context) ?) ;
1907
+ let root_matcher = expected. matching_rules ( )
1908
+ . rules_for_category ( "body" )
1909
+ . map ( |category| category. rules . get ( & DocPath :: root ( ) ) . cloned ( ) )
1910
+ . flatten ( ) ;
1911
+ if let Some ( root_matcher) = root_matcher && root_matcher. can_match ( & content_type) {
1912
+ plan_node. add ( build_matching_rule_node (
1913
+ & ExecutionPlanNode :: value_node ( NodeValue :: NULL ) ,
1914
+ & ExecutionPlanNode :: resolve_value ( body_path) ,
1915
+ & root_matcher,
1916
+ false
1917
+ ) ) ;
1889
1918
} else {
1890
- let plan_builder = PlainTextBuilder :: new ( ) ;
1891
- content_type_check_node. add ( plan_builder. build_plan ( content, context) ?) ;
1919
+ let mut content_type_check_node = ExecutionPlanNode :: action ( "if" ) ;
1920
+ content_type_check_node
1921
+ . add (
1922
+ ExecutionPlanNode :: action ( "match:equality" )
1923
+ . add ( ExecutionPlanNode :: value_node ( content_type. to_string ( ) ) )
1924
+ . add ( ExecutionPlanNode :: resolve_value ( DocPath :: new ( "$.content-type" ) ?) )
1925
+ . add ( ExecutionPlanNode :: value_node ( NodeValue :: NULL ) )
1926
+ . add (
1927
+ ExecutionPlanNode :: action ( "error" )
1928
+ . add ( ExecutionPlanNode :: value_node ( NodeValue :: STRING ( "Body type error - " . to_string ( ) ) ) )
1929
+ . add ( ExecutionPlanNode :: action ( "apply" ) )
1930
+ )
1931
+ ) ;
1932
+ if let Some ( plan_builder) = get_body_plan_builder ( & content_type) {
1933
+ content_type_check_node. add ( plan_builder. build_plan ( content, context) ?) ;
1934
+ } else {
1935
+ let plan_builder = PlainTextBuilder :: new ( ) ;
1936
+ content_type_check_node. add ( plan_builder. build_plan ( content, context) ?) ;
1937
+ }
1938
+ plan_node. add ( content_type_check_node) ;
1892
1939
}
1893
- plan_node. add ( content_type_check_node) ;
1894
1940
}
1895
1941
}
1896
1942
0 commit comments