Skip to content

Commit 93c8c90

Browse files
committed
Tests for xmlrpc macros
1 parent 20870c5 commit 93c8c90

File tree

1 file changed

+80
-13
lines changed

1 file changed

+80
-13
lines changed

src/xmlrpc/macros.rs

Lines changed: 80 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,131 @@
11
use xmlrpc::common::Value;
22

3-
macro_rules! parse_xmlrpc_value_recursive {
3+
macro_rules! validate_xmlrpc_value_recursive {
44
( $v:ident, ( $($T:tt),* ) ) => (
55
match $v {
66
&Value::Array(ref a) => {
77
// Create a tuple whose elements are recursively filled in
88
let mut ii: isize = -1;
99
( $(
1010
if ii >= a.len() as isize {
11-
return Err("Not enough elements in array");
11+
return Err("Not enough elements in array".to_string());
1212
} else {
1313
ii += 1;
1414
let ref e = a[ii as usize];
15-
parse_xmlrpc_value_recursive!(e, $T)
15+
validate_xmlrpc_value_recursive!(e, $T)
1616
}
1717
),* )
1818
},
19-
_ => return Err("Expected array, found something else"),
19+
_ => return Err("Expected array, found something else".to_string()),
2020
}
2121
);
2222
( $v:ident, i32 ) => ( match $v {
2323
&Value::Int(ref x) => x.clone(),
24-
_ => return Err("Expected int; found something else"),
24+
_ => return Err("Expected int; found something else".to_string()),
2525
} );
2626
( $v:ident, String ) => ( match $v {
2727
&Value::String(ref x) => x.clone(),
28-
_ => return Err("Expected string; found something else"),
28+
_ => return Err("Expected string; found something else".to_string()),
29+
} );
30+
( $v:ident, f64 ) => ( match $v {
31+
&Value::Double(ref x) => x.clone(),
32+
_ => return Err("Expected double; found something else".to_string()),
2933
} );
3034
}
3135

3236
/// Just calls the macro that does the real parsing, and wraps the result in Ok()
3337
/// since we expect a Result<...> at the top level.
34-
macro_rules! parse_xmlrpc_value_top_level {
38+
macro_rules! validate_xmlrpc_value_top_level {
3539
( $v:ident, $T:tt ) => (
36-
Ok(parse_xmlrpc_value_recursive!($v, $T))
40+
Ok(validate_xmlrpc_value_recursive!($v, $T))
3741
);
3842
}
3943

40-
macro_rules! parse_xmlrpc_value {
44+
/// Validate an xmlrpc value using a type specified as nested tuples.
45+
macro_rules! validate_xmlrpc_value {
4146
( $v:ident, $T:tt ) => (
4247
{
4348
// From here on down, we pass references
4449
let v_ref: &Value = & $v;
45-
(|&:| {parse_xmlrpc_value_top_level!(v_ref, $T)})()
50+
51+
// Wrap the validation call in a closure so that we can return errors
52+
// when we want to stop validating early.
53+
(|&:| {validate_xmlrpc_value_top_level!(v_ref, $T)})()
4654
}
4755
);
4856
}
4957

58+
/// Validate an xmlrpc response using a type specified as nested tuples.
59+
macro_rules! validate_xmlrpc_response {
60+
( $response:ident, $T:tt ) => (
61+
match $response {
62+
Response::Fault {fault_code, fault_string} => Err(format!(
63+
"Fault: {} ({})", fault_string, fault_code)),
64+
Response::Success {param} => validate_xmlrpc_value!(param, $T),
65+
}
66+
);
67+
}
68+
69+
/// Validate an xmlrpc request using a type specified as nested tuples.
70+
macro_rules! validate_xmlrpc_request {
71+
( $request:ident, $T:tt ) => (
72+
validate_xmlrpc_value!(xmlrpc::Value::Array($request.params), $T),
73+
);
74+
}
75+
5076
#[cfg(test)]
5177
mod tests {
52-
use xmlrpc::common::Value;
78+
use xmlrpc::common::{Value, Request, Response};
5379

5480
#[test]
55-
fn test_parse_value() {
81+
fn test_validate_xmlrpc_value() {
5682
let v = Value::Array(vec![
5783
Value::Int(1i32),
5884
Value::Int(3i32)
5985
]);
6086

61-
let x = parse_xmlrpc_value!(v, (i32, i32));
87+
let x = validate_xmlrpc_value!(v, (i32, i32));
6288
assert_eq!(x, Ok((1i32, 3i32)));
6389
}
90+
91+
#[test]
92+
fn test_validate_xmlrpc_value_incorrect_types() {
93+
let v = Value::Array(vec![
94+
Value::Int(1i32),
95+
Value::Int(3i32)
96+
]);
97+
98+
let x = validate_xmlrpc_value!(v, (i32, String));
99+
match x {
100+
Ok(_) => panic!("Validation succeeded with incorrect types"),
101+
Err(_) => {},
102+
};
103+
}
104+
105+
#[test]
106+
fn test_validate_xmlrpc_response_success() {
107+
let v = Response::Success {
108+
param: Value::Array(vec![
109+
Value::String("foo".to_string()),
110+
Value::Array(vec![
111+
Value::Int(3i32),
112+
Value::Double(3.14) ])]) };
113+
114+
let x = validate_xmlrpc_response!(v, (String, (i32, f64)));
115+
match x {
116+
Ok((x0, (x1, x2))) => assert_eq!((x0, (x1, x2)), ("foo".to_string(), (3i32, 3.14))),
117+
Err(err) => panic!(err),
118+
}
119+
}
120+
121+
#[test]
122+
fn test_validate_xmlrpc_response_fault() {
123+
let v = Response::Fault {fault_code: 22, fault_string: "some_fault".to_string()};
124+
125+
let x = validate_xmlrpc_response!(v, (String, (i32, f64)));
126+
match x {
127+
Ok(_) => panic!("Validation succeeded when it should have found fault"),
128+
Err(_) => {},
129+
}
130+
}
64131
}

0 commit comments

Comments
 (0)