extern crate fraction;
extern crate num;
#[macro_use]
extern crate over;
use fraction::BigFraction;
use num::ToPrimitive;
use over::OverError;
use over::obj::Obj;
use over::value::Value;
fn get_int(obj: &Obj, field: &str) -> i64 {
obj.get_int(field).unwrap().to_i64().unwrap()
}
#[test]
fn empty() {
let obj = Obj::from_file("tests/test_files/empty.over").unwrap();
assert_eq!(obj.len(), 0);
}
#[test]
fn basic() {
let obj = Obj::from_file("tests/test_files/basic.over").unwrap();
assert_eq!(get_int(&obj, "a1"), 1);
assert_eq!(get_int(&obj, "a2"), 2);
assert_eq!(get_int(&obj, "aa"), 0);
assert_eq!(obj.get("b").unwrap(), "Smörgåsbord");
assert_eq!(get_int(&obj, "c"), 10);
assert_eq!(get_int(&obj, "d"), 20);
assert_eq!(get_int(&obj, "eee"), 2);
assert_eq!(get_int(&obj, "f"), 3);
assert_eq!(get_int(&obj, "g_"), 4);
assert_eq!(obj.get("Hello").unwrap(), "Hello");
assert_eq!(obj.get("i_robot").unwrap(), "not #a comment");
assert_eq!(get_int(&obj, "j"), 4);
assert_eq!(obj.get("k").unwrap(), "hi");
assert_eq!(obj.get("l").unwrap(), "$\\\"");
assert_eq!(obj.get("m").unwrap(), "m");
assert_eq!(obj.get("n").unwrap(), true);
assert_eq!(obj.get("o").unwrap(), false);
assert_eq!(obj.get("p").unwrap(), "Hello");
assert_eq!(get_int(&obj, "q"), 0);
assert_eq!(obj.get("r").unwrap(), Value::Null);
assert_eq!(obj.get("s").unwrap(), '\'');
assert_eq!(obj.get("t").unwrap(), '\n');
assert_eq!(obj.get("u").unwrap(), ' ');
}
#[test]
fn example() {
let obj = Obj::from_file("tests/test_files/example.over").unwrap();
assert_eq!(obj.get("receipt").unwrap(), "Oz-Ware Purchase Invoice");
assert_eq!(obj.get("date").unwrap(), "2012-08-06");
assert_eq!(
obj.get("customer").unwrap(),
obj!{"first_name" => "Dorothy",
"family_name" => "Gale"}
);
assert_eq!(
obj.get("items").unwrap(),
arr![
obj!{"part_no" => "A4786",
"descrip" => "Water Bucket (Filled)",
"price" => 1.47,
"quantity" => 4},
obj!{"part_no" => "E1628",
"descrip" => "High Heeled \"Ruby\" Slippers",
"size" => 8,
"price" => 133.7,
"quantity" => 1},
]
);
assert_eq!(
obj.get("bill_to").unwrap(),
obj!{"street" => "123 Tornado Alley\nSuite 16",
"city" => "East Centerville",
"state" => "KS",
}
);
assert_eq!(obj.get("ship_to").unwrap(), obj.get("bill_to").unwrap());
assert_eq!(
obj.get("specialDelivery").unwrap(),
"Follow the Yellow Brick Road to the Emerald City. \
Pay no attention to the man behind the curtain."
);
}
#[test]
fn obj() {
let obj = Obj::from_file("tests/test_files/obj.over").unwrap();
assert_eq!(obj.get_obj("empty").unwrap().len(), 0);
assert_eq!(obj.get_obj("empty2").unwrap().len(), 0);
assert!(!obj.contains("bools"));
let mut bools = Obj::new();
bools.set("t", true.into());
bools.set("f", false.into());
let outie = obj.get_obj("outie").unwrap();
assert_eq!(outie.get_parent().unwrap(), bools);
assert_eq!(get_int(&outie, "z"), 0);
let inner = outie.get_obj("inner").unwrap();
assert_eq!(get_int(&inner, "z"), 1);
let innie = inner.get_obj("innie").unwrap();
assert_eq!(get_int(&innie, "a"), 1);
assert_eq!(inner.get("b").unwrap(), tup!(1, 2,));
assert_eq!(get_int(&outie, "c"), 3);
assert_eq!(outie.get("d").unwrap(), Obj::new());
let obj_arr = obj.get_obj("obj_arr").unwrap();
assert_eq!(obj_arr.get("arr").unwrap(), arr![1, 2, 3]);
}
#[test]
fn globals() {
let obj = Obj::from_file("tests/test_files/globals.over").unwrap();
let sub = obj.get_obj("sub").unwrap();
assert_eq!(sub.get_int("a").unwrap().to_i64(), Some(1));
assert_eq!(get_int(&sub, "b"), 2);
assert_eq!(sub.len(), 2);
assert_eq!(get_int(&obj, "c"), 2);
assert_eq!(obj.len(), 2);
}
#[test]
fn numbers() {
let obj = Obj::from_file("tests/test_files/numbers.over").unwrap();
assert_eq!(get_int(&obj, "neg"), -4);
assert_eq!(obj.get_frac("pos").unwrap().to_f32(), Some(4f32));
assert_eq!(obj.get_frac("neg_zero").unwrap().to_f32(), Some(0f32));
assert_eq!(obj.get_frac("pos_zero").unwrap().to_f32(), Some(0f32));
assert_eq!(
obj.get("frac_from_dec").unwrap(),
BigFraction::new(13u8, 10u8)
);
assert_eq!(
obj.get("neg_ffd").unwrap(),
BigFraction::new_neg(13u8, 10u8)
);
assert_eq!(obj.get("pos_ffd").unwrap(), BigFraction::new(13u8, 10u8));
let frac = obj.get_frac("big_frac").unwrap();
assert!(frac > BigFraction::new(91_000_000u64, 1u8));
assert!(frac < BigFraction::new(92_000_000u64, 1u8));
}
#[test]
fn fuzz() {
let _ = Obj::from_file("tests/test_files/fuzz1.over").unwrap();
}
#[test]
fn errors() {
macro_rules! error_helper {
( $filename:expr, $error:expr ) => {
{
match Obj::from_file(&format!("tests/test_files/errors/{}", $filename)) {
Err(OverError::ParseError(s)) => {
if s != $error {
panic!("Error in {}: {:?}", $filename, s);
}
}
res => panic!("{:?}", res),
}
}
}
}
error_helper!(
"arr_types.over",
"Arr inner types do not match: found Arr(Tup(Int, Char)), \
expected Arr(Tup(Int, Int))"
);
error_helper!("decimal.over", "Invalid numeric value at line 1, column 10");
error_helper!(
"deep.over",
"Exceeded maximum depth (128) for a container at line 1, column 142"
);
error_helper!(
"dup_global.over",
"Duplicate global \"@global\" at line 2, column 1"
);
error_helper!(
"empty_field.over",
"Invalid character \':\' for field at line 1, column 1"
);
error_helper!(
"empty_number.over",
"Invalid numeric value at line 1, column 6"
);
error_helper!(
"field_true.over",
"Invalid field name \"true\" at line 1, column 1"
);
error_helper!(
"field_whitespace.over",
"No whitespace after field at line 1, column 6"
);
error_helper!(
"fuzz1.over",
"Invalid closing bracket \')\' at line 20, column 1; expected \']\'"
);
error_helper!(
"fuzz2.over",
"Invalid closing bracket \')\' at line 22, column 2; expected none"
);
error_helper!(
"fuzz3.over",
"Invalid closing bracket \')\' at line 8, column 4; expected \']\'"
);
error_helper!("fuzz4.over", "Duplicate field \"M\" at line 22, column 1");
error_helper!(
"fuzz5.over",
"Invalid character \'(\' for value at line 27, column 4"
);
error_helper!(
"fuzz6.over",
"Arr inner types do not match: found Frac, expected Int"
);
error_helper!(
"fuzz7.over",
"Invalid character \'\\n\' for field at line 8, column 0"
);
error_helper!(
"fuzz8.over",
"Invalid character \'\"\' for value at line 34, column 3"
);
error_helper!(
"unexpected_end1.over",
"Unexpected end when reading value at line 2"
);
error_helper!(
"unexpected_end2.over",
"Unexpected end when reading value at line 3"
);
error_helper!("value_amp.over", "Invalid value \"@\" at line 1, column 8");
}