diff --git a/hipcheck/src/engine.rs b/hipcheck/src/engine.rs index 8a730381..9f69ff02 100644 --- a/hipcheck/src/engine.rs +++ b/hipcheck/src/engine.rs @@ -231,7 +231,6 @@ pub fn start_plugins( )?; let current_arch = get_current_arch(); - println!("CURRENT ARCH: {}", current_arch); // retrieve, verify and extract all required plugins let required_plugin_names = retrieve_plugins(&policy_file.plugins.0, plugin_cache)?; diff --git a/hipcheck/src/policy_exprs/env.rs b/hipcheck/src/policy_exprs/env.rs index f8f10835..8d36c457 100644 --- a/hipcheck/src/policy_exprs/env.rs +++ b/hipcheck/src/policy_exprs/env.rs @@ -142,6 +142,10 @@ fn partially_evaluate(fn_name: &'static str, arg: Expr) -> Result { Ok(lambda) } +pub fn upcast(i: i64) -> Primitive { + Float(F64::new(i as f64).unwrap()) +} + /// Define binary operations on primitives. fn binary_primitive_op(name: &'static str, env: &Env, args: &[Expr], op: F) -> Result where @@ -164,8 +168,9 @@ where }; let primitive = match (&arg_1, &arg_2) { - (Int(_), Int(_)) | (Float(_), Float(_)) | (Bool(_), Bool(_)) => op(arg_1, arg_2)?, - _ => return Err(Error::BadType(name)), + (Int(i), Float(_)) => op(upcast(*i), arg_2)?, + (Float(_), Int(i)) => op(arg_1, upcast(*i))?, + _ => op(arg_1, arg_2)?, }; Ok(Primitive(primitive)) @@ -454,9 +459,9 @@ fn add(env: &Env, args: &[Expr]) -> Result { let op = |arg_1, arg_2| match (arg_1, arg_2) { (Int(arg_1), Int(arg_2)) => Ok(Int(arg_1 + arg_2)), (Float(arg_1), Float(arg_2)) => Ok(Float(arg_1 + arg_2)), - (DateTime(arg_1), Span(arg_2)) => Ok(DateTime( - arg_1 - .checked_add(arg_2) + // Span or DateTime can come first + (DateTime(dt), Span(s)) | (Span(s), DateTime(dt)) => Ok(DateTime( + dt.checked_add(s) .map_err(|err| Error::Datetime(err.to_string()))?, )), (Span(arg_1), Span(arg_2)) => Ok(Span( diff --git a/hipcheck/src/policy_exprs/expr.rs b/hipcheck/src/policy_exprs/expr.rs index bde4a575..41f9adbb 100644 --- a/hipcheck/src/policy_exprs/expr.rs +++ b/hipcheck/src/policy_exprs/expr.rs @@ -17,6 +17,9 @@ use nom::{ use ordered_float::NotNan; use std::{fmt::Display, ops::Deref}; +#[cfg(test)] +use jiff::civil::Date; + /// A `deke` expression to evaluate. #[derive(Debug, PartialEq, Eq, Clone)] pub enum Expr { @@ -318,13 +321,25 @@ mod tests { let input = "2024-09-17T09:30:00-05"; let result = parse(input).unwrap(); - let ts: Timestamp = "2024-09-17T09:30:00-05".parse().unwrap(); + let ts: Timestamp = input.parse().unwrap(); let dt = Zoned::new(ts, TimeZone::UTC); let expected = datetime(dt).into_expr(); assert_eq!(result, expected); } + #[test] + fn parse_simple_datetime() { + let input = "2024-09-17"; + let result = parse(input).unwrap(); + + let ts: Date = input.parse().unwrap(); + let dt = ts.to_zoned(TimeZone::UTC).unwrap(); + let expected = datetime(dt).into_expr(); + + assert_eq!(result, expected); + } + #[test] fn parse_span() { let input = "P2W4DT1H30M"; @@ -336,6 +351,17 @@ mod tests { assert_eq!(result, expected); } + #[test] + fn parse_simple_span() { + let input = "P2w"; + let result = parse(input).unwrap(); + + let raw_span: Span = "P14d".parse().unwrap(); + let expected = span(raw_span).into_expr(); + + assert_eq!(result, expected); + } + #[test] fn parse_function() { let input = "(add 2 3)"; diff --git a/hipcheck/src/policy_exprs/mod.rs b/hipcheck/src/policy_exprs/mod.rs index c030275e..d5a08994 100644 --- a/hipcheck/src/policy_exprs/mod.rs +++ b/hipcheck/src/policy_exprs/mod.rs @@ -203,4 +203,37 @@ mod tests { ]) ); } + + #[test] + fn eval_upcasted_int() { + let program_and_expected = vec![ + ("(lte 3 3.0)", Expr::Primitive(Primitive::Bool(true))), + ( + "(add 3 5.5)", + Expr::Primitive(Primitive::Float(F64::new(8.5).unwrap())), + ), + ]; + let context = Value::Null; + for (program, expected) in program_and_expected.into_iter() { + let result = Executor::std().parse_and_eval(program, &context).unwrap(); + assert_eq!(result, expected); + } + } + + #[test] + fn eval_datetime_span_add() { + let date = "2024-09-26"; + let span = "P1w"; + let eval_fmt = "(add {} {})"; + let context = Value::Null; + let expected = parse("2024-10-03").unwrap(); + let result1 = Executor::std() + .parse_and_eval(format!("(add {} {})", date, span).as_str(), &context) + .unwrap(); + assert_eq!(expected, result1); + let result2 = Executor::std() + .parse_and_eval(format!("(add {} {})", span, date).as_str(), &context) + .unwrap(); + assert_eq!(expected, result2); + } }