1#![feature(box_syntax, box_patterns)]2#![feature(type_alias_impl_trait)]3#![feature(debug_non_exhaustive)]4#![allow(macro_expanded_macro_exports_accessed_by_absolute_paths)]5mod ctx;6mod dynamic;7mod evaluate;8mod obj;9mod val;1011pub use ctx::*;12pub use dynamic::*;13pub use evaluate::*;14use jsonnet_parser::*;15pub use obj::*;16pub use val::*;1718rc_fn_helper!(19 Binding,20 binding,21 dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Val22);23rc_fn_helper!(FunctionRhs, function_rhs, dyn Fn(Context) -> Val);24rc_fn_helper!(25 FunctionDefault,26 function_default,27 dyn Fn(Context, Expr) -> Val28);2930#[cfg(test)]31pub mod tests {32 use super::{evaluate, Context, Val};33 use jsonnet_parser::*;3435 macro_rules! eval {36 ($str: expr) => {37 evaluate(Context::new(), &parse($str).unwrap())38 };39 }4041 macro_rules! eval_stdlib {42 ($str: expr) => {43 let std = "local std = ".to_owned() + jsonnet_stdlib::STDLIB_STR + ";";44 evaluate(Context::new(), &parse(&(std + $str)).unwrap())45 };46 }4748 macro_rules! assert_eval {49 ($str: expr) => {50 assert_eq!(51 evaluate(Context::new(), &parse($str).unwrap()),52 Val::Literal(LiteralType::True)53 )54 };55 }56 macro_rules! assert_json {57 ($str: expr, $out: expr) => {58 assert_eq!(59 format!("{}", evaluate(Context::new(), &parse($str).unwrap())),60 $out61 )62 };63 }64 macro_rules! assert_eval_neg {65 ($str: expr) => {66 assert_eq!(67 evaluate(Context::new(), &parse($str).unwrap()),68 Val::Literal(LiteralType::False)69 )70 };71 }7273 74 #[test]75 fn equality_operator() {76 assert_eval!("2 == 2");77 assert_eval_neg!("2 != 2");78 assert_eval!("2 != 3");79 assert_eval_neg!("2 == 3");80 assert_eval!("'Hello' == 'Hello'");81 assert_eval_neg!("'Hello' != 'Hello'");82 assert_eval!("'Hello' != 'World'");83 assert_eval_neg!("'Hello' == 'World'");84 }8586 #[test]87 fn math_evaluation() {88 assert_eval!("2 + 2 * 2 == 6");89 assert_eval!("3 + (2 + 2 * 2) == 9");90 }9192 #[test]93 fn string_concat() {94 assert_eval!("'Hello' + 'World' == 'HelloWorld'");95 assert_eval!("'Hello' * 3 == 'HelloHelloHello'");96 assert_eval!("'Hello' + 'World' * 3 == 'HelloWorldWorldWorld'");97 }9899 #[test]100 fn local() {101 assert_eval!("local a = 2; local b = 3; a + b == 5");102 assert_eval!("local a = 1, b = a + 1; a + b == 3");103 assert_eval!("local a = 1; local a = 2; a == 2");104 }105106 #[test]107 fn object_lazyness() {108 assert_json!("local a = {a:error 'test'}; {}", r#"{}"#);109 }110111 #[test]112 fn object_inheritance() {113 assert_json!("{a:self.b} + {b:3}", r#"{"a":3,"b":3}"#);114 }115116 #[test]117 fn test_object() {118 assert_json!("{a:2}", r#"{"a":2}"#);119 assert_json!("{a:2+2}", r#"{"a":4}"#);120 assert_json!("{a:2}+{b:2}", r#"{"a":2,"b":2}"#);121 assert_json!("{b:3}+{b:2}", r#"{"b":2}"#);122 assert_json!("{b:3}+{b+:2}", r#"{"b":5}"#);123 assert_json!("local test='a'; {[test]:2}", r#"{"a":2}"#);124 assert_json!(125 r#"126 {127 name: "Alice",128 welcome: "Hello " + self.name + "!",129 }130 "#,131 r#"{"name":"Alice","welcome":"Hello Alice!"}"#132 );133 assert_json!(134 r#"135 {136 name: "Alice",137 welcome: "Hello " + self.name + "!",138 } + {139 name: "Bob"140 }141 "#,142 r#"{"name":"Bob","welcome":"Hello Bob!"}"#143 );144 }145146 #[test]147 fn functions() {148 assert_json!(r#"local a = function(b, c = 2) b + c; a(2)"#, "4");149 assert_json!(150 r#"local a = function(b, c = "Dear") b + c + d, d = "World"; a("Hello")"#,151 r#""HelloDearWorld""#152 );153 }154155 #[test]156 fn local_methods() {157 assert_json!(r#"local a(b, c = 2) = b + c; a(2)"#, "4");158 assert_json!(159 r#"local a(b, c = "Dear") = b + c + d, d = "World"; a("Hello")"#,160 r#""HelloDearWorld""#161 );162 }163164 #[test]165 fn object_locals() {166 assert_json!(r#"{local a = 3, b: a}"#, r#"{"b":3}"#);167 assert_json!(r#"{local a = 3, local c = a, b: c}"#, r#"{"b":3}"#);168 assert_json!(169 r#"{local a = function (b) {[b]:4}, test: a("test")}"#,170 r#"{"test":{"test":4}}"#171 );172 }173174 #[test]175 fn direct_self() {176 println!(177 "{:#?}",178 eval!(179 r#"180 {181 local me = self,182 a: 3,183 b(): me.a,184 }185 "#186 )187 );188 }189190 #[test]191 fn indirect_self() {192 193 194 eval_stdlib!(195 r#"{196 local me = std.trace("test", self),197 b: me,198 }.b"#199 );200 }201202 203 #[test]204 fn std_assert_ok() {205 eval_stdlib!("std.assertEqual(4.5 << 2, 16)");206 }207208 #[test]209 #[should_panic]210 fn std_assert_failure() {211 eval_stdlib!("std.assertEqual(4.5 << 2, 15)");212 }213214 #[test]215 fn base64_works() {216 eval_stdlib!(r#"std.base64("test")"#);217 }218}