1use crate::ast::*;
20use crate::entities::{Dereference, Entities};
21use crate::extensions::Extensions;
22use std::collections::HashMap;
23use std::sync::Arc;
24
25mod err;
26pub use err::EvaluationError;
27pub(crate) use err::*;
28use itertools::Either;
29use smol_str::SmolStr;
30
31const REQUIRED_STACK_SPACE: usize = 1024 * 100;
32
33pub struct Evaluator<'e> {
39 principal: EntityUIDEntry,
41 action: EntityUIDEntry,
43 resource: EntityUIDEntry,
45 context: PartialValue,
47 entities: &'e Entities,
53 extensions: &'e Extensions<'e>,
55 entity_attr_values: EntityAttrValues<'e>,
59}
60
61#[derive(Debug)]
63pub struct RestrictedEvaluator<'e> {
64 extensions: &'e Extensions<'e>,
66}
67
68impl<'e> RestrictedEvaluator<'e> {
69 pub fn new(extensions: &'e Extensions<'e>) -> Self {
71 Self { extensions }
72 }
73
74 pub fn interpret(&self, e: BorrowedRestrictedExpr<'_>) -> Result<Value> {
78 match self.partial_interpret(e)? {
79 PartialValue::Value(v) => Ok(v),
80 PartialValue::Residual(r) => Err(EvaluationError::NonValue(r)),
81 }
82 }
83
84 pub fn partial_interpret(&self, e: BorrowedRestrictedExpr<'_>) -> Result<PartialValue> {
88 stack_size_check()?;
89
90 match e.as_ref().expr_kind() {
91 ExprKind::Lit(lit) => Ok(lit.clone().into()),
92 ExprKind::Set(items) => {
93 let vals = items
94 .iter()
95 .map(|item| self.partial_interpret(BorrowedRestrictedExpr::new_unchecked(item))) .collect::<Result<Vec<_>>>()?;
97 match split(vals) {
98 Either::Left(values) => Ok(Value::Set(values.collect()).into()),
99 Either::Right(residuals) => Ok(Expr::set(residuals).into()),
100 }
101 }
102 ExprKind::Unknown{name, type_annotation} => Ok(PartialValue::Residual(Expr::unknown_with_type(name.clone(), type_annotation.clone()))),
103 ExprKind::Record { pairs } => {
104 let map = pairs
105 .iter()
106 .map(|(k, v)| Ok((k.clone(), self.partial_interpret(BorrowedRestrictedExpr::new_unchecked(v))?))) .collect::<Result<Vec<_>>>()?;
108 let (names, attrs) : (Vec<_>, Vec<_>) = map.into_iter().unzip();
109 match split(attrs) {
110 Either::Left(values) => Ok(Value::Record(Arc::new(names.into_iter().zip(values).collect())).into()),
111 Either::Right(residuals) => Ok(Expr::record(names.into_iter().zip(residuals)).into()),
112 }
113 }
114 ExprKind::ExtensionFunctionApp { op, args } => {
115 let args = args
116 .iter()
117 .map(|arg| self.partial_interpret(BorrowedRestrictedExpr::new_unchecked(arg))) .collect::<Result<Vec<_>>>()?;
119 match split(args) {
120 Either::Left(values) => {
121 let values : Vec<_> = values.collect();
122 let efunc = self.extensions.func(&op.function_name)?;
123 efunc.call(&values)
124 },
125 Either::Right(residuals) => Ok(Expr::call_extension_fn(op.function_name.clone(), residuals.collect()).into()),
126 }
127 },
128 expr => panic!("internal invariant violation: BorrowedRestrictedExpr somehow contained this expr case: {expr:?}"),
129 }
130 }
131}
132
133struct EntityAttrValues<'a> {
134 attrs: HashMap<EntityUID, HashMap<SmolStr, PartialValue>>,
135 entities: &'a Entities,
136}
137
138impl<'a> EntityAttrValues<'a> {
139 pub fn new<'e>(entities: &'a Entities, extensions: &'e Extensions<'e>) -> Result<Self> {
140 let restricted_eval = RestrictedEvaluator::new(extensions);
141 let attrs = entities
143 .iter()
144 .map(|entity| {
145 Ok((
146 entity.uid(),
147 entity
148 .attrs()
149 .iter()
150 .map(|(attr, v)| {
151 Ok((
152 attr.to_owned(),
153 restricted_eval.partial_interpret(v.as_borrowed())?,
154 ))
155 })
156 .collect::<Result<HashMap<SmolStr, PartialValue>>>()?,
157 ))
158 })
159 .collect::<Result<HashMap<EntityUID, HashMap<SmolStr, PartialValue>>>>()?;
160 Ok(Self { attrs, entities })
161 }
162
163 pub fn get(&self, uid: &EntityUID) -> Dereference<'_, HashMap<SmolStr, PartialValue>> {
164 match self.entities.entity(uid) {
165 Dereference::NoSuchEntity => Dereference::NoSuchEntity,
166 Dereference::Residual(r) => Dereference::Residual(r),
167 Dereference::Data(_) => self
168 .attrs
169 .get(uid)
170 .map(Dereference::Data)
171 .unwrap_or_else(|| Dereference::NoSuchEntity),
172 }
173 }
174}
175
176impl<'q, 'e> Evaluator<'e> {
177 pub fn new(
187 q: &'q Request,
188 entities: &'e Entities,
189 extensions: &'e Extensions<'e>,
190 ) -> Result<Self> {
191 let entity_attr_values = EntityAttrValues::new(entities, extensions)?;
193 Ok(Self {
194 principal: q.principal().clone(),
195 action: q.action().clone(),
196 resource: q.resource().clone(),
197 context: {
198 let restricted_eval = RestrictedEvaluator::new(extensions);
204 match &q.context {
205 None => PartialValue::Residual(Expr::unknown("context")),
206 Some(ctxt) => restricted_eval.partial_interpret(ctxt.as_ref().as_borrowed())?,
207 }
208 },
209 entities,
210 extensions,
211 entity_attr_values,
212 })
213 }
214
215 pub fn evaluate(&self, p: &Policy) -> Result<bool> {
222 self.interpret(&p.condition(), p.env())?.get_as_bool()
223 }
224
225 pub fn partial_evaluate(&self, p: &Policy) -> Result<Either<bool, Expr>> {
235 match self.partial_interpret(&p.condition(), p.env())? {
236 PartialValue::Value(v) => v.get_as_bool().map(Either::Left),
237 PartialValue::Residual(e) => Ok(Either::Right(e)),
238 }
239 }
240
241 pub fn run_to_error(
245 &self,
246 e: &Expr,
247 slots: &SlotEnv,
248 ) -> (PartialValue, Option<EvaluationError>) {
249 match self.partial_interpret(e, slots) {
250 Ok(e) => (e, None),
251 Err(err) => {
252 let arg = Expr::val(format!("{err}"));
253 (
254 PartialValue::Residual(Expr::call_extension_fn(
255 "error".parse().unwrap(),
256 vec![arg],
257 )),
258 Some(err),
259 )
260 }
261 }
262 }
263
264 pub fn interpret(&self, e: &Expr, slots: &SlotEnv) -> Result<Value> {
270 match self.partial_interpret(e, slots)? {
271 PartialValue::Value(v) => Ok(v),
272 PartialValue::Residual(r) => Err(EvaluationError::NonValue(r)),
273 }
274 }
275
276 pub fn partial_interpret(&self, e: &Expr, slots: &SlotEnv) -> Result<PartialValue> {
282 stack_size_check()?;
283
284 match e.expr_kind() {
285 ExprKind::Lit(lit) => Ok(lit.clone().into()),
286 ExprKind::Slot(id) => slots
287 .get(id)
288 .ok_or_else(|| err::EvaluationError::TemplateInstantiationError(*id))
289 .map(|euid| PartialValue::from(euid.clone())),
290 ExprKind::Var(v) => match v {
291 Var::Principal => Ok(self.principal.evaluate(*v)),
292 Var::Action => Ok(self.action.evaluate(*v)),
293 Var::Resource => Ok(self.resource.evaluate(*v)),
294 Var::Context => Ok(self.context.clone()),
295 },
296 ExprKind::Unknown { .. } => Ok(PartialValue::Residual(e.clone())),
297 ExprKind::If {
298 test_expr,
299 then_expr,
300 else_expr,
301 } => self.eval_if(test_expr, then_expr, else_expr, slots),
302 ExprKind::And { left, right } => {
303 match self.partial_interpret(left, slots)? {
304 PartialValue::Residual(e) => Ok(PartialValue::Residual(Expr::and(
306 e,
307 self.run_to_error(right.as_ref(), slots).0.into(),
308 ))),
309 PartialValue::Value(v) => {
311 if v.get_as_bool()? {
312 match self.partial_interpret(right, slots)? {
313 PartialValue::Residual(right) => {
317 Ok(PartialValue::Residual(Expr::and(Expr::val(true), right)))
318 }
319 PartialValue::Value(v) => Ok(v.get_as_bool()?.into()),
321 }
322 } else {
323 Ok(false.into())
325 }
326 }
327 }
328 }
329 ExprKind::Or { left, right } => {
330 match self.partial_interpret(left, slots)? {
331 PartialValue::Residual(r) => Ok(PartialValue::Residual(Expr::or(
333 r,
334 self.run_to_error(right, slots).0.into(),
335 ))),
336 PartialValue::Value(lhs) => {
338 if lhs.get_as_bool()? {
339 Ok(true.into())
341 } else {
342 match self.partial_interpret(right, slots)? {
343 PartialValue::Residual(rhs) =>
344 {
348 Ok(PartialValue::Residual(Expr::or(Expr::val(false), rhs)))
349 }
350 PartialValue::Value(v) => Ok(v.get_as_bool()?.into()),
351 }
352 }
353 }
354 }
355 }
356 ExprKind::UnaryApp { op, arg } => match self.partial_interpret(arg, slots)? {
357 PartialValue::Value(arg) => match op {
358 UnaryOp::Not => match arg.get_as_bool()? {
359 true => Ok(false.into()),
360 false => Ok(true.into()),
361 },
362 UnaryOp::Neg => {
363 let i = arg.get_as_long()?;
364 match i.checked_neg() {
365 Some(v) => Ok(v.into()),
366 None => Err(EvaluationError::IntegerOverflow(
367 IntegerOverflowError::UnaryOp { op: *op, arg },
368 )),
369 }
370 }
371 },
372 PartialValue::Residual(r) => Ok(PartialValue::Residual(Expr::unary_app(*op, r))),
375 },
376 ExprKind::BinaryApp { op, arg1, arg2 } => {
377 let (arg1, arg2) = match (
381 self.partial_interpret(arg1, slots)?,
382 self.partial_interpret(arg2, slots)?,
383 ) {
384 (PartialValue::Value(v1), PartialValue::Value(v2)) => (v1, v2),
385 (PartialValue::Value(v1), PartialValue::Residual(e2)) => {
386 return Ok(PartialValue::Residual(Expr::binary_app(*op, v1.into(), e2)))
387 }
388 (PartialValue::Residual(e1), PartialValue::Value(v2)) => {
389 return Ok(PartialValue::Residual(Expr::binary_app(*op, e1, v2.into())))
390 }
391 (PartialValue::Residual(e1), PartialValue::Residual(e2)) => {
392 return Ok(PartialValue::Residual(Expr::binary_app(*op, e1, e2)))
393 }
394 };
395 match op {
396 BinaryOp::Eq => Ok((arg1 == arg2).into()),
397 BinaryOp::Less | BinaryOp::LessEq | BinaryOp::Add | BinaryOp::Sub => {
399 let i1 = arg1.get_as_long()?;
400 let i2 = arg2.get_as_long()?;
401 match op {
402 BinaryOp::Less => Ok((i1 < i2).into()),
403 BinaryOp::LessEq => Ok((i1 <= i2).into()),
404 BinaryOp::Add => match i1.checked_add(i2) {
405 Some(sum) => Ok(sum.into()),
406 None => Err(EvaluationError::IntegerOverflow(
407 IntegerOverflowError::BinaryOp {
408 op: *op,
409 arg1,
410 arg2,
411 },
412 )),
413 },
414 BinaryOp::Sub => match i1.checked_sub(i2) {
415 Some(diff) => Ok(diff.into()),
416 None => Err(EvaluationError::IntegerOverflow(
417 IntegerOverflowError::BinaryOp {
418 op: *op,
419 arg1,
420 arg2,
421 },
422 )),
423 },
424 _ => panic!("Should have already checked that op was one of these"),
425 }
426 }
427 BinaryOp::In => {
429 let uid1 = arg1.get_as_entity()?;
430 match self.entities.entity(uid1) {
431 Dereference::Residual(r) => Ok(PartialValue::Residual(
432 Expr::binary_app(BinaryOp::In, r, arg2.into()),
433 )),
434 Dereference::NoSuchEntity => self.eval_in(uid1, None, arg2),
435 Dereference::Data(e) => self.eval_in(uid1, Some(e), arg2),
436 }
437 }
438 BinaryOp::Contains => match arg1 {
440 Value::Set(Set { fast: Some(h), .. }) => match arg2.try_as_lit() {
441 Some(lit) => Ok((h.contains(lit)).into()),
442 None => Ok(false.into()), },
444 Value::Set(Set { authoritative, .. }) => {
445 Ok((authoritative.contains(&arg2)).into())
446 }
447 _ => Err(EvaluationError::TypeError {
448 expected: vec![Type::Set],
449 actual: arg1.type_of(),
450 }),
451 },
452 BinaryOp::ContainsAll | BinaryOp::ContainsAny => {
454 let arg1_set = arg1.get_as_set()?;
455 let arg2_set = arg2.get_as_set()?;
456 match (&arg1_set.fast, &arg2_set.fast) {
457 (Some(arg1_set), Some(arg2_set)) => {
458 match op {
461 BinaryOp::ContainsAll => {
462 Ok((arg2_set.is_subset(arg1_set)).into())
463 }
464 BinaryOp::ContainsAny => {
465 Ok((!arg1_set.is_disjoint(arg2_set)).into())
466 }
467 _ => panic!(
468 "Should have already checked that op was one of these"
469 ),
470 }
471 }
472 (_, _) => {
473 match op {
476 BinaryOp::ContainsAll => {
477 let is_subset = arg2_set
478 .authoritative
479 .iter()
480 .all(|item| arg1_set.authoritative.contains(item));
481 Ok(is_subset.into())
482 }
483 BinaryOp::ContainsAny => {
484 let not_disjoint = arg1_set
485 .authoritative
486 .iter()
487 .any(|item| arg2_set.authoritative.contains(item));
488 Ok(not_disjoint.into())
489 }
490 _ => panic!(
491 "Should have already checked that op was one of these"
492 ),
493 }
494 }
495 }
496 }
497 }
498 }
499 ExprKind::MulByConst { arg, constant } => match self.partial_interpret(arg, slots)? {
500 PartialValue::Value(arg) => {
501 let i1 = arg.get_as_long()?;
502 match i1.checked_mul(*constant) {
503 Some(prod) => Ok(prod.into()),
504 None => Err(EvaluationError::IntegerOverflow(
505 IntegerOverflowError::Multiplication {
506 arg,
507 constant: *constant,
508 },
509 )),
510 }
511 }
512 PartialValue::Residual(r) => Ok(PartialValue::Residual(Expr::mul(r, *constant))),
513 },
514 ExprKind::ExtensionFunctionApp { op, args } => {
515 let args = args
516 .iter()
517 .map(|arg| self.partial_interpret(arg, slots))
518 .collect::<Result<Vec<_>>>()?;
519 match split(args) {
520 Either::Left(vals) => {
521 let vals: Vec<_> = vals.collect();
522 let efunc = self.extensions.func(&op.function_name)?;
523 efunc.call(&vals)
524 }
525 Either::Right(residuals) => Ok(PartialValue::Residual(
526 Expr::call_extension_fn(op.function_name.clone(), residuals.collect()),
527 )),
528 }
529 }
530 ExprKind::GetAttr { expr, attr } => self.get_attr(expr.as_ref(), attr, slots),
531 ExprKind::HasAttr { expr, attr } => match self.partial_interpret(expr, slots)? {
532 PartialValue::Value(Value::Record(record)) => Ok(record.get(attr).is_some().into()),
533 PartialValue::Value(Value::Lit(Literal::EntityUID(uid))) => {
534 match self.entities.entity(&uid) {
535 Dereference::NoSuchEntity => Ok(false.into()),
536 Dereference::Residual(r) => {
537 Ok(PartialValue::Residual(Expr::has_attr(r, attr.clone())))
538 }
539 Dereference::Data(e) => Ok(e.get(attr).is_some().into()),
540 }
541 }
542 PartialValue::Value(val) => Err(err::EvaluationError::TypeError {
543 expected: vec![
544 Type::Record,
545 Type::entity_type(
546 Name::parse_unqualified_name("any_entity_type")
547 .expect("should be a valid identifier"),
548 ),
549 ],
550 actual: val.type_of(),
551 }),
552 PartialValue::Residual(r) => Ok(Expr::has_attr(r, attr.clone()).into()),
553 },
554 ExprKind::Like { expr, pattern } => {
555 let v = self.partial_interpret(expr, slots)?;
556 match v {
557 PartialValue::Value(v) => {
558 Ok((pattern.wildcard_match(v.get_as_string()?)).into())
559 }
560 PartialValue::Residual(r) => Ok(Expr::like(r, pattern.iter().cloned()).into()),
561 }
562 }
563 ExprKind::Set(items) => {
564 let vals = items
565 .iter()
566 .map(|item| self.partial_interpret(item, slots))
567 .collect::<Result<Vec<_>>>()?;
568 match split(vals) {
569 Either::Left(vals) => Ok(Value::set(vals).into()),
570 Either::Right(r) => Ok(Expr::set(r).into()),
571 }
572 }
573 ExprKind::Record { pairs } => {
574 let map = pairs
575 .iter()
576 .map(|(k, v)| Ok((k.clone(), self.partial_interpret(v, slots)?)))
577 .collect::<Result<Vec<_>>>()?;
578 let (names, evalled): (Vec<SmolStr>, Vec<PartialValue>) = map.into_iter().unzip();
579 match split(evalled) {
580 Either::Left(vals) => {
581 Ok(Value::Record(Arc::new(names.into_iter().zip(vals).collect())).into())
582 }
583 Either::Right(rs) => Ok(Expr::record(names.into_iter().zip(rs)).into()),
584 }
585 }
586 }
587 }
588
589 fn eval_in(
590 &self,
591 uid1: &EntityUID,
592 entity1: Option<&Entity>,
593 arg2: Value,
594 ) -> Result<PartialValue> {
595 let rhs = match arg2 {
598 Value::Lit(Literal::EntityUID(uid)) => vec![(*uid).clone()],
599 Value::Set(Set { authoritative, .. }) => authoritative
602 .iter()
603 .map(|val| Ok(val.get_as_entity()?.clone()))
604 .collect::<Result<Vec<EntityUID>>>()?,
605 _ => {
606 return Err(EvaluationError::TypeError {
607 expected: vec![
608 Type::Set,
609 Type::entity_type(
610 Name::parse_unqualified_name("any_entity_type")
611 .expect("should be a valid identifier"),
612 ),
613 ],
614 actual: arg2.type_of(),
615 })
616 }
617 };
618 for uid2 in rhs {
619 if uid1 == &uid2
620 || entity1
621 .map(|e1| e1.is_descendant_of(&uid2))
622 .unwrap_or(false)
623 {
624 return Ok(true.into());
625 }
626 }
627 Ok(false.into())
630 }
631
632 fn eval_if(
635 &self,
636 guard: &Expr,
637 consequent: &Expr,
638 alternative: &Expr,
639 slots: &SlotEnv,
640 ) -> Result<PartialValue> {
641 match self.partial_interpret(guard, slots)? {
642 PartialValue::Value(v) => {
643 if v.get_as_bool()? {
644 self.partial_interpret(consequent, slots)
645 } else {
646 self.partial_interpret(alternative, slots)
647 }
648 }
649 PartialValue::Residual(_) => {
650 let (consequent, consequent_errored) = self.run_to_error(consequent, slots);
651 let (alternative, alternative_errored) = self.run_to_error(alternative, slots);
652 match (consequent_errored, alternative_errored) {
654 (Some(e), Some(_)) => Err(e),
655 _ => Ok(Expr::ite(guard.clone(), consequent.into(), alternative.into()).into()),
656 }
657 }
658 }
659 }
660
661 fn get_attr(&self, expr: &Expr, attr: &SmolStr, slots: &SlotEnv) -> Result<PartialValue> {
662 match self.partial_interpret(expr, slots)? {
663 PartialValue::Residual(e) => {
665 match e.expr_kind() {
666 ExprKind::Record { pairs } => {
667 if e.is_projectable() {
672 pairs
673 .as_ref()
674 .iter()
675 .filter_map(|(k, v)| if k == attr { Some(v) } else { None })
676 .next()
677 .ok_or_else(|| {
678 EvaluationError::RecordAttrDoesNotExist(attr.clone())
679 })
680 .and_then(|e| self.partial_interpret(e, slots))
681 } else if pairs.iter().any(|(k, _v)| k == attr) {
682 Ok(PartialValue::Residual(Expr::get_attr(
683 Expr::record(pairs.as_ref().clone()), attr.clone(),
685 )))
686 } else {
687 Err(EvaluationError::RecordAttrDoesNotExist(attr.clone()))
688 }
689 }
690 _ => Ok(PartialValue::Residual(Expr::get_attr(e, attr.clone()))),
692 }
693 }
694 PartialValue::Value(Value::Record(attrs)) => attrs
695 .as_ref()
696 .get(attr)
697 .ok_or_else(|| EvaluationError::RecordAttrDoesNotExist(attr.clone()))
698 .map(|v| PartialValue::Value(v.clone())),
699 PartialValue::Value(Value::Lit(Literal::EntityUID(uid))) => {
700 match self.entity_attr_values.get(uid.as_ref()) {
701 Dereference::NoSuchEntity => Err(match *uid.entity_type() {
702 EntityType::Unspecified => {
703 EvaluationError::UnspecifiedEntityAccess(attr.clone())
704 }
705 EntityType::Concrete(_) => EvaluationError::EntityDoesNotExist(uid.clone()),
706 }),
707 Dereference::Residual(r) => {
708 Ok(PartialValue::Residual(Expr::get_attr(r, attr.clone())))
709 }
710 Dereference::Data(attrs) => attrs
711 .get(attr)
712 .ok_or_else(|| EvaluationError::EntityAttrDoesNotExist {
713 entity: uid,
714 attr: attr.clone(),
715 })
716 .cloned(),
717 }
718 }
719 PartialValue::Value(v) => Err(EvaluationError::TypeError {
720 expected: vec![
721 Type::Record,
722 Type::entity_type(Name::parse_unqualified_name("any_entity_type").unwrap()),
723 ],
724 actual: v.type_of(),
725 }),
726 }
727 }
728
729 #[cfg(test)]
730 pub fn interpret_inline_policy(&self, e: &Expr) -> Result<Value> {
731 match self.partial_interpret(e, &HashMap::new())? {
732 PartialValue::Value(v) => Ok(v),
733 PartialValue::Residual(r) => Err(err::EvaluationError::NonValue(r)),
734 }
735 }
736
737 #[cfg(test)]
739 pub fn partial_eval_expr(&self, p: &Expr) -> Result<Either<Value, Expr>> {
740 let env = SlotEnv::new();
741 match self.partial_interpret(p, &env)? {
742 PartialValue::Value(v) => Ok(Either::Left(v)),
743 PartialValue::Residual(r) => Ok(Either::Right(r)),
744 }
745 }
746 }
752
753impl<'e> std::fmt::Debug for Evaluator<'e> {
754 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
755 write!(
756 f,
757 "<Evaluator with principal = {:?}, action = {:?}, resource = {:?}",
758 &self.principal, &self.action, &self.resource
759 )
760 }
761}
762
763impl Value {
764 pub(crate) fn get_as_bool(&self) -> Result<bool> {
767 match self {
768 Value::Lit(Literal::Bool(b)) => Ok(*b),
769 _ => Err(EvaluationError::TypeError {
770 expected: vec![Type::Bool],
771 actual: self.type_of(),
772 }),
773 }
774 }
775
776 pub(crate) fn get_as_long(&self) -> Result<i64> {
779 match self {
780 Value::Lit(Literal::Long(i)) => Ok(*i),
781 _ => Err(EvaluationError::TypeError {
782 expected: vec![Type::Long],
783 actual: self.type_of(),
784 }),
785 }
786 }
787
788 pub(crate) fn get_as_string(&self) -> Result<&SmolStr> {
791 match self {
792 Value::Lit(Literal::String(s)) => Ok(s),
793 _ => Err(EvaluationError::TypeError {
794 expected: vec![Type::String],
795 actual: self.type_of(),
796 }),
797 }
798 }
799
800 pub(crate) fn get_as_set(&self) -> Result<&Set> {
802 match self {
803 Value::Set(s) => Ok(s),
804 _ => Err(EvaluationError::TypeError {
805 expected: vec![Type::Set],
806 actual: self.type_of(),
807 }),
808 }
809 }
810
811 pub(crate) fn get_as_entity(&self) -> Result<&EntityUID> {
814 match self {
815 Value::Lit(Literal::EntityUID(uid)) => Ok(uid.as_ref()),
816 _ => Err(EvaluationError::TypeError {
817 expected: vec![Type::entity_type(
818 Name::parse_unqualified_name("any_entity_type").expect("valid identifier"),
819 )],
820 actual: self.type_of(),
821 }),
822 }
823 }
824}
825
826#[inline(always)]
827fn stack_size_check() -> Result<()> {
828 #[cfg(not(target_arch = "wasm32"))]
829 {
830 if stacker::remaining_stack().unwrap_or(0) < REQUIRED_STACK_SPACE {
831 return Err(EvaluationError::RecursionLimit);
832 }
833 }
834 Ok(())
835}
836
837#[cfg(test)]
838pub mod test {
839 use std::str::FromStr;
840
841 use super::*;
842
843 use crate::{
844 entities::{EntityJsonParser, TCComputation},
845 parser::{self, parse_policyset},
846 parser::{parse_expr, parse_policy_template},
847 };
848
849 pub fn basic_request() -> Request {
851 Request::new(
852 EntityUID::with_eid("test_principal"),
853 EntityUID::with_eid("test_action"),
854 EntityUID::with_eid("test_resource"),
855 Context::from_pairs([
856 ("cur_time".into(), RestrictedExpr::val("03:22:11")),
857 (
858 "device_properties".into(),
859 RestrictedExpr::record(vec![
860 ("os_name".into(), RestrictedExpr::val("Windows")),
861 ("manufacturer".into(), RestrictedExpr::val("ACME Corp")),
862 ]),
863 ),
864 ]),
865 )
866 }
867
868 pub fn basic_entities() -> Entities {
870 Entities::from_entities(
871 vec![
872 Entity::with_uid(EntityUID::with_eid("foo")),
873 Entity::with_uid(EntityUID::with_eid("test_principal")),
874 Entity::with_uid(EntityUID::with_eid("test_action")),
875 Entity::with_uid(EntityUID::with_eid("test_resource")),
876 ],
877 TCComputation::ComputeNow,
878 )
879 .expect("failed to create basic entities")
880 }
881
882 pub fn rich_entities() -> Entities {
884 let entity_no_attrs_no_parents =
885 Entity::with_uid(EntityUID::with_eid("entity_no_attrs_no_parents"));
886 let mut entity_with_attrs = Entity::with_uid(EntityUID::with_eid("entity_with_attrs"));
887 entity_with_attrs.set_attr("spoon".into(), RestrictedExpr::val(787));
888 entity_with_attrs.set_attr(
889 "tags".into(),
890 RestrictedExpr::set(vec![
891 RestrictedExpr::val("fun"),
892 RestrictedExpr::val("good"),
893 RestrictedExpr::val("useful"),
894 ]),
895 );
896 entity_with_attrs.set_attr(
897 "address".into(),
898 RestrictedExpr::record(vec![
899 ("street".into(), RestrictedExpr::val("234 magnolia")),
900 ("town".into(), RestrictedExpr::val("barmstadt")),
901 ("country".into(), RestrictedExpr::val("amazonia")),
902 ]),
903 );
904 let mut child = Entity::with_uid(EntityUID::with_eid("child"));
905 let mut parent = Entity::with_uid(EntityUID::with_eid("parent"));
906 let grandparent = Entity::with_uid(EntityUID::with_eid("grandparent"));
907 let mut sibling = Entity::with_uid(EntityUID::with_eid("sibling"));
908 let unrelated = Entity::with_uid(EntityUID::with_eid("unrelated"));
909 child.add_ancestor(parent.uid());
910 sibling.add_ancestor(parent.uid());
911 parent.add_ancestor(grandparent.uid());
912 let mut child_diff_type = Entity::with_uid(
913 EntityUID::with_eid_and_type("other_type", "other_child")
914 .expect("should be a valid identifier"),
915 );
916 child_diff_type.add_ancestor(parent.uid());
917 child_diff_type.add_ancestor(grandparent.uid());
918 Entities::from_entities(
919 vec![
920 entity_no_attrs_no_parents,
921 entity_with_attrs,
922 child,
923 child_diff_type,
924 parent,
925 grandparent,
926 sibling,
927 unrelated,
928 ],
929 TCComputation::ComputeNow,
930 )
931 .expect("Failed to create rich entities")
932 }
933
934 #[test]
935 fn partial_entity_stores_in_set() {
936 let q = basic_request();
937 let entities = rich_entities().partial();
938 let exts = Extensions::none();
939 let child = EntityUID::with_eid("child");
940 let second = EntityUID::with_eid("joseph");
941 let missing = EntityUID::with_eid("non-present");
942 let parent = EntityUID::with_eid("parent");
943 let eval = Evaluator::new(&q, &entities, &exts).unwrap();
944
945 let e = Expr::binary_app(
946 BinaryOp::In,
947 Expr::val(child),
948 Expr::set([Expr::val(parent.clone()), Expr::val(second.clone())]),
949 );
950 let r = eval.partial_eval_expr(&e).unwrap();
951 assert_eq!(r, Either::Left(true.into()));
952
953 let e = Expr::binary_app(
954 BinaryOp::In,
955 Expr::val(missing.clone()),
956 Expr::set([Expr::val(parent.clone()), Expr::val(second.clone())]),
957 );
958 let r = eval.partial_eval_expr(&e).unwrap();
959 let expected_residual = Expr::binary_app(
960 BinaryOp::In,
961 Expr::unknown(format!("{missing}")),
962 Expr::set([Expr::val(parent.clone()), Expr::val(second.clone())]),
963 );
964 let expected_residual2 = Expr::binary_app(
965 BinaryOp::In,
966 Expr::unknown(format!("{missing}")),
967 Expr::set([Expr::val(second), Expr::val(parent)]),
968 );
969
970 assert!(r == Either::Right(expected_residual) || r == Either::Right(expected_residual2));
972 }
973
974 #[test]
975 fn partial_entity_stores_in() {
976 let q = basic_request();
977 let entities = rich_entities().partial();
978 let exts = Extensions::none();
979 let child = EntityUID::with_eid("child");
980 let missing = EntityUID::with_eid("non-present");
981 let parent = EntityUID::with_eid("parent");
982 let eval = Evaluator::new(&q, &entities, &exts).unwrap();
983
984 let e = Expr::binary_app(BinaryOp::In, Expr::val(child), Expr::val(parent.clone()));
985 let r = eval.partial_eval_expr(&e).unwrap();
986 assert_eq!(r, Either::Left(true.into()));
987
988 let e = Expr::binary_app(
989 BinaryOp::In,
990 Expr::val(missing.clone()),
991 Expr::val(parent.clone()),
992 );
993 let r = eval.partial_eval_expr(&e).unwrap();
994 let expected_residual = Expr::binary_app(
995 BinaryOp::In,
996 Expr::unknown(format!("{missing}")),
997 Expr::val(parent),
998 );
999 assert_eq!(r, Either::Right(expected_residual));
1000 }
1001
1002 #[test]
1003 fn partial_entity_stores_hasattr() {
1004 let q = basic_request();
1005 let entities = rich_entities().partial();
1006 let exts = Extensions::none();
1007 let has_attr = EntityUID::with_eid("entity_with_attrs");
1008 let missing = EntityUID::with_eid("missing");
1009 let eval = Evaluator::new(&q, &entities, &exts).unwrap();
1010
1011 let e = Expr::has_attr(Expr::val(has_attr), "spoon".into());
1012 let r = eval.partial_eval_expr(&e).unwrap();
1013 assert_eq!(r, Either::Left(true.into()));
1014
1015 let e = Expr::has_attr(Expr::val(missing.clone()), "spoon".into());
1016 let r = eval.partial_eval_expr(&e).unwrap();
1017 let expected_residual = Expr::has_attr(Expr::unknown(format!("{missing}")), "spoon".into());
1018 assert_eq!(r, Either::Right(expected_residual));
1019 }
1020
1021 #[test]
1022 fn partial_entity_stores_getattr() {
1023 let q = basic_request();
1024 let entities = rich_entities().partial();
1025 let exts = Extensions::none();
1026 let has_attr = EntityUID::with_eid("entity_with_attrs");
1027 let missing = EntityUID::with_eid("missing");
1028 let eval = Evaluator::new(&q, &entities, &exts).unwrap();
1029
1030 let e = Expr::get_attr(Expr::val(has_attr), "spoon".into());
1031 let r = eval.partial_eval_expr(&e).unwrap();
1032 assert_eq!(r, Either::Left(787.into()));
1033
1034 let e = Expr::get_attr(Expr::val(missing.clone()), "spoon".into());
1035 let r = eval.partial_eval_expr(&e).unwrap();
1036 let expected_residual = Expr::get_attr(Expr::unknown(format!("{missing}")), "spoon".into());
1037 assert_eq!(r, Either::Right(expected_residual));
1038 }
1039
1040 #[test]
1041 fn interpret_primitives() {
1042 let request = basic_request();
1043 let entities = basic_entities();
1044 let exts = Extensions::none();
1045 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
1046 assert_eq!(
1047 eval.interpret_inline_policy(&Expr::val(false)),
1048 Ok(Value::Lit(Literal::Bool(false)))
1049 );
1050 assert_eq!(
1051 eval.interpret_inline_policy(&Expr::val(true)),
1052 Ok(Value::Lit(Literal::Bool(true)))
1053 );
1054 assert_eq!(
1055 eval.interpret_inline_policy(&Expr::val(57)),
1056 Ok(Value::Lit(Literal::Long(57)))
1057 );
1058 assert_eq!(
1059 eval.interpret_inline_policy(&Expr::val(-3)),
1060 Ok(Value::Lit(Literal::Long(-3)))
1061 );
1062 assert_eq!(
1063 eval.interpret_inline_policy(&Expr::val("")),
1064 Ok(Value::Lit(Literal::String("".into())))
1065 );
1066 assert_eq!(
1067 eval.interpret_inline_policy(&Expr::val("Hello")),
1068 Ok(Value::Lit(Literal::String("Hello".into())))
1069 );
1070 }
1071
1072 #[test]
1073 fn interpret_entities() {
1074 let request = basic_request();
1075 let entities = basic_entities();
1076 let exts = Extensions::none();
1077 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
1078 assert_eq!(
1079 eval.interpret_inline_policy(&Expr::val(EntityUID::with_eid("foo"))),
1080 Ok(Value::Lit(Literal::EntityUID(Arc::new(
1081 EntityUID::with_eid("foo")
1082 ))))
1083 );
1084 assert_eq!(
1087 eval.interpret_inline_policy(&Expr::val(EntityUID::with_eid("doesnotexist"))),
1088 Ok(Value::Lit(Literal::EntityUID(Arc::new(
1089 EntityUID::with_eid("doesnotexist")
1090 ))))
1091 );
1092 assert_eq!(
1094 eval.interpret_inline_policy(&Expr::val(EntityUID::unspecified_from_eid(Eid::new(
1095 "foo"
1096 )))),
1097 Ok(Value::Lit(Literal::EntityUID(Arc::new(
1098 EntityUID::unspecified_from_eid(Eid::new("foo"))
1099 ))))
1100 );
1101 }
1102
1103 #[test]
1104 fn interpret_builtin_vars() {
1105 let request = basic_request();
1106 let entities = basic_entities();
1107 let exts = Extensions::none();
1108 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
1109 assert_eq!(
1110 eval.interpret_inline_policy(&Expr::var(Var::Principal)),
1111 Ok(Value::Lit(Literal::EntityUID(Arc::new(
1112 EntityUID::with_eid("test_principal")
1113 ))))
1114 );
1115 assert_eq!(
1116 eval.interpret_inline_policy(&Expr::var(Var::Action)),
1117 Ok(Value::Lit(Literal::EntityUID(Arc::new(
1118 EntityUID::with_eid("test_action")
1119 ))))
1120 );
1121 assert_eq!(
1122 eval.interpret_inline_policy(&Expr::var(Var::Resource)),
1123 Ok(Value::Lit(Literal::EntityUID(Arc::new(
1124 EntityUID::with_eid("test_resource")
1125 ))))
1126 );
1127 }
1128
1129 #[test]
1130 fn interpret_entity_attrs() {
1131 let request = basic_request();
1132 let entities = rich_entities();
1133 let exts = Extensions::none();
1134 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
1135 assert_eq!(
1137 eval.interpret_inline_policy(&Expr::has_attr(
1138 Expr::val(EntityUID::with_eid("entity_no_attrs_no_parents")),
1139 "doesnotexist".into()
1140 )),
1141 Ok(Value::Lit(Literal::Bool(false)))
1142 );
1143 assert_eq!(
1145 eval.interpret_inline_policy(&Expr::has_attr(
1146 Expr::val(EntityUID::with_eid("entity_with_attrs")),
1147 "doesnotexist".into()
1148 )),
1149 Ok(Value::Lit(Literal::Bool(false)))
1150 );
1151 assert_eq!(
1153 eval.interpret_inline_policy(&Expr::has_attr(
1154 Expr::val(EntityUID::with_eid("entity_with_attrs")),
1155 "tags".into()
1156 )),
1157 Ok(Value::Lit(Literal::Bool(true)))
1158 );
1159 assert_eq!(
1161 eval.interpret_inline_policy(&Expr::get_attr(
1162 Expr::val(EntityUID::with_eid("entity_with_attrs")),
1163 "doesnotexist".into()
1164 )),
1165 Err(EvaluationError::EntityAttrDoesNotExist {
1166 entity: Arc::new(EntityUID::with_eid("entity_with_attrs")),
1167 attr: "doesnotexist".into()
1168 })
1169 );
1170 assert_eq!(
1172 eval.interpret_inline_policy(&Expr::get_attr(
1173 Expr::val(EntityUID::with_eid("entity_with_attrs")),
1174 "spoon".into()
1175 )),
1176 Ok(Value::Lit(Literal::Long(787)))
1177 );
1178 assert_eq!(
1180 eval.interpret_inline_policy(&Expr::contains(
1181 Expr::get_attr(
1182 Expr::val(EntityUID::with_eid("entity_with_attrs")),
1183 "tags".into()
1184 ),
1185 Expr::val("useful")
1186 )),
1187 Ok(Value::from(true))
1188 );
1189 assert_eq!(
1191 eval.interpret_inline_policy(&Expr::has_attr(
1192 Expr::val(EntityUID::with_eid("doesnotexist")),
1193 "foo".into()
1194 )),
1195 Ok(Value::from(false))
1196 );
1197 assert_eq!(
1199 eval.interpret_inline_policy(&Expr::get_attr(
1200 Expr::val(EntityUID::with_eid("doesnotexist")),
1201 "foo".into()
1202 )),
1203 Err(EvaluationError::EntityDoesNotExist(Arc::new(
1204 EntityUID::with_eid("doesnotexist")
1205 )))
1206 );
1207 assert_eq!(
1209 eval.interpret_inline_policy(&Expr::has_attr(
1210 Expr::val(EntityUID::unspecified_from_eid(Eid::new("foo"))),
1211 "foo".into()
1212 )),
1213 Ok(Value::from(false))
1214 );
1215 assert_eq!(
1217 eval.interpret_inline_policy(&Expr::get_attr(
1218 Expr::val(EntityUID::unspecified_from_eid(Eid::new("foo"))),
1219 "bar".into()
1220 )),
1221 Err(EvaluationError::UnspecifiedEntityAccess("bar".into()))
1222 );
1223 }
1224
1225 #[test]
1226 fn interpret_ternaries() {
1227 let request = basic_request();
1228 let entities = basic_entities();
1229 let exts = Extensions::none();
1230 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
1231 assert_eq!(
1233 eval.interpret_inline_policy(&Expr::ite(Expr::val(true), Expr::val(3), Expr::val(8))),
1234 Ok(Value::Lit(Literal::Long(3)))
1235 );
1236 assert_eq!(
1238 eval.interpret_inline_policy(&Expr::ite(Expr::val(false), Expr::val(3), Expr::val(8))),
1239 Ok(Value::Lit(Literal::Long(8)))
1240 );
1241 assert_eq!(
1243 eval.interpret_inline_policy(&Expr::ite(
1244 Expr::val(false),
1245 Expr::val(false),
1246 Expr::val(true)
1247 )),
1248 Ok(Value::Lit(Literal::Bool(true)))
1249 );
1250 assert_eq!(
1252 eval.interpret_inline_policy(&Expr::ite(
1253 Expr::val(false),
1254 Expr::var(Var::Principal),
1255 Expr::var(Var::Resource)
1256 )),
1257 Ok(Value::from(EntityUID::with_eid("test_resource")))
1258 );
1259 assert_eq!(
1261 eval.interpret_inline_policy(&Expr::ite(
1262 Expr::val("hello"),
1263 Expr::val(3),
1264 Expr::val(8)
1265 )),
1266 Err(EvaluationError::TypeError {
1267 expected: vec![Type::Bool],
1268 actual: Type::String
1269 })
1270 );
1271 assert_eq!(
1273 eval.interpret_inline_policy(&Expr::ite(
1274 Expr::var(Var::Principal),
1275 Expr::val(3),
1276 Expr::val(8)
1277 )),
1278 Err(EvaluationError::TypeError {
1279 expected: vec![Type::Bool],
1280 actual: Type::Entity {
1281 ty: EntityUID::test_entity_type(),
1282 }
1283 })
1284 );
1285 assert_eq!(
1287 eval.interpret_inline_policy(&Expr::ite(
1288 Expr::val(true),
1289 Expr::val("hello"),
1290 Expr::val(2)
1291 )),
1292 Ok(Value::from("hello"))
1293 );
1294 assert_eq!(
1296 eval.interpret_inline_policy(&Expr::ite(
1297 Expr::val(false),
1298 Expr::val("hello"),
1299 Expr::val(2)
1300 )),
1301 Ok(Value::Lit(Literal::Long(2)))
1302 );
1303 assert_eq!(
1305 eval.interpret_inline_policy(&Expr::ite(
1306 Expr::val(true),
1307 Expr::ite(Expr::val(true), Expr::val(3), Expr::val(8)),
1308 Expr::val(-10)
1309 )),
1310 Ok(Value::Lit(Literal::Long(3)))
1311 );
1312 assert_eq!(
1314 eval.interpret_inline_policy(&Expr::ite(
1315 Expr::val(true),
1316 Expr::ite(Expr::val(false), Expr::val(3), Expr::val(8)),
1317 Expr::val(-10)
1318 )),
1319 Ok(Value::Lit(Literal::Long(8)))
1320 );
1321 assert_eq!(
1323 eval.interpret_inline_policy(&Expr::ite(
1324 Expr::val(false),
1325 Expr::ite(Expr::val(false), Expr::val(3), Expr::val(8)),
1326 Expr::val(-10)
1327 )),
1328 Ok(Value::Lit(Literal::Long(-10)))
1329 );
1330 assert_eq!(
1332 eval.interpret_inline_policy(&Expr::ite(
1333 Expr::val(false),
1334 Expr::ite(Expr::val("hello"), Expr::val(3), Expr::val(8)),
1335 Expr::val(-10)
1336 )),
1337 Ok(Value::Lit(Literal::Long(-10)))
1338 );
1339 assert_eq!(
1341 eval.interpret_inline_policy(&Expr::ite(
1342 Expr::val(true),
1343 Expr::val(3),
1344 Expr::ite(Expr::val(true), Expr::val(8), Expr::val(-10))
1345 )),
1346 Ok(Value::Lit(Literal::Long(3)))
1347 );
1348 assert_eq!(
1350 eval.interpret_inline_policy(&Expr::ite(
1351 Expr::ite(Expr::val(true), Expr::val(false), Expr::val(true)),
1352 Expr::val(3),
1353 Expr::val(8)
1354 )),
1355 Ok(Value::Lit(Literal::Long(8)))
1356 );
1357 assert_eq!(
1359 eval.interpret_inline_policy(&Expr::ite(
1360 Expr::val(true),
1361 Expr::val(3),
1362 Expr::get_attr(Expr::record(vec![]), "foo".into()),
1363 )),
1364 Ok(Value::Lit(Literal::Long(3)))
1365 );
1366 assert_eq!(
1368 eval.interpret_inline_policy(&Expr::ite(
1369 Expr::val(false),
1370 Expr::val(3),
1371 Expr::get_attr(Expr::record(vec![]), "foo".into()),
1372 )),
1373 Err(EvaluationError::RecordAttrDoesNotExist("foo".into()))
1374 );
1375 assert_eq!(
1377 eval.interpret_inline_policy(&Expr::ite(
1378 Expr::val(true),
1379 Expr::get_attr(Expr::record(vec![]), "foo".into()),
1380 Expr::val(3),
1381 )),
1382 Err(EvaluationError::RecordAttrDoesNotExist("foo".into()))
1383 );
1384 assert_eq!(
1386 eval.interpret_inline_policy(&Expr::ite(
1387 Expr::val(false),
1388 Expr::get_attr(Expr::record(vec![]), "foo".into()),
1389 Expr::val(3),
1390 )),
1391 Ok(Value::Lit(Literal::Long(3)))
1392 );
1393 }
1394
1395 #[test]
1396 fn interpret_sets() {
1397 let request = basic_request();
1398 let entities = basic_entities();
1399 let exts = Extensions::none();
1400 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
1401 assert_eq!(
1403 eval.interpret_inline_policy(&Expr::set(vec![Expr::val(8)])),
1404 Ok(Value::set(vec![Value::Lit(Literal::Long(8))]))
1405 );
1406 assert_eq!(
1408 eval.interpret_inline_policy(&Expr::set(vec![
1409 Expr::val(8),
1410 Expr::val(2),
1411 Expr::val(101)
1412 ])),
1413 Ok(Value::set(vec![
1414 Value::Lit(Literal::Long(8)),
1415 Value::Lit(Literal::Long(2)),
1416 Value::Lit(Literal::Long(101))
1417 ]))
1418 );
1419 assert_eq!(
1421 eval.interpret_inline_policy(&Expr::set(vec![])),
1422 Ok(Value::empty_set())
1423 );
1424 assert_eq!(
1425 eval.interpret_inline_policy(&Expr::set(vec![])),
1426 Ok(Value::empty_set())
1427 );
1428 assert_eq!(
1430 eval.interpret_inline_policy(&Expr::get_attr(
1431 Expr::set(vec![Expr::val(8)]),
1432 "hello".into()
1433 )),
1434 Err(EvaluationError::TypeError {
1435 expected: vec![
1436 Type::Record,
1437 Type::entity_type(
1438 Name::parse_unqualified_name("any_entity_type")
1439 .expect("should be a valid identifier")
1440 ),
1441 ],
1442 actual: Type::Set,
1443 })
1444 );
1445 assert_eq!(
1447 eval.interpret_inline_policy(&Expr::get_attr(Expr::set(vec![]), "hello".into())),
1448 Err(EvaluationError::TypeError {
1449 expected: vec![
1450 Type::Record,
1451 Type::entity_type(
1452 Name::parse_unqualified_name("any_entity_type")
1453 .expect("should be a valid identifier")
1454 ),
1455 ],
1456 actual: Type::Set,
1457 })
1458 );
1459 let mixed_set = Expr::set(vec![
1461 Expr::val("hello"),
1462 Expr::val(2),
1463 Expr::val(true),
1464 Expr::val(EntityUID::with_eid("foo")),
1465 ]);
1466 assert_eq!(
1467 eval.interpret_inline_policy(&mixed_set),
1468 Ok(Value::set(vec![
1469 Value::Lit(Literal::String("hello".into())),
1470 Value::Lit(Literal::Long(2)),
1471 Value::Lit(Literal::Bool(true)),
1472 Value::Lit(Literal::EntityUID(Arc::new(EntityUID::with_eid("foo")))),
1473 ]))
1474 );
1475 assert_eq!(
1477 eval.interpret_inline_policy(&Expr::get_attr(mixed_set, "hello".into())),
1478 Err(EvaluationError::TypeError {
1479 expected: vec![
1480 Type::Record,
1481 Type::entity_type(
1482 Name::parse_unqualified_name("any_entity_type")
1483 .expect("should be a valid identifier")
1484 ),
1485 ],
1486 actual: Type::Set
1487 })
1488 );
1489 let set_of_sets = Expr::set(vec![
1491 Expr::set(vec![Expr::val(8), Expr::val(2)]),
1492 Expr::set(vec![Expr::val(13), Expr::val(702)]),
1493 Expr::set(vec![Expr::val(3)]),
1494 ]);
1495 assert_eq!(
1496 eval.interpret_inline_policy(&set_of_sets),
1497 Ok(Value::set(vec![
1498 Value::set(vec![
1499 Value::Lit(Literal::Long(8)),
1500 Value::Lit(Literal::Long(2))
1501 ]),
1502 Value::set(vec![
1503 Value::Lit(Literal::Long(13)),
1504 Value::Lit(Literal::Long(702))
1505 ]),
1506 Value::set(vec![Value::Lit(Literal::Long(3))]),
1507 ]))
1508 );
1509 assert_eq!(
1511 eval.interpret_inline_policy(&Expr::get_attr(set_of_sets.clone(), "hello".into())),
1512 Err(EvaluationError::TypeError {
1513 expected: vec![
1514 Type::Record,
1515 Type::entity_type(
1516 Name::parse_unqualified_name("any_entity_type")
1517 .expect("should be a valid identifier")
1518 ),
1519 ],
1520 actual: Type::Set
1521 })
1522 );
1523 assert_eq!(
1525 eval.interpret_inline_policy(&Expr::get_attr(
1526 Expr::get_attr(set_of_sets, "ham".into()),
1527 "eggs".into()
1528 )),
1529 Err(EvaluationError::TypeError {
1530 expected: vec![
1531 Type::Record,
1532 Type::entity_type(
1533 Name::parse_unqualified_name("any_entity_type")
1534 .expect("should be a valid identifier")
1535 ),
1536 ],
1537 actual: Type::Set
1538 })
1539 );
1540 }
1541
1542 #[test]
1543 fn interpret_records() {
1544 let request = basic_request();
1545 let entities = rich_entities();
1546 let exts = Extensions::none();
1547 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
1548 let string_key = Expr::record(vec![("key".into(), Expr::val(3))]);
1550 assert_eq!(
1551 eval.interpret_inline_policy(&Expr::get_attr(string_key, "key".into())),
1552 Ok(Value::Lit(Literal::Long(3)))
1553 );
1554 let ham_and_eggs = Expr::record(vec![
1556 ("ham".into(), Expr::val(3)),
1557 ("eggs".into(), Expr::val(7)),
1558 ]);
1559 assert_eq!(
1560 eval.interpret_inline_policy(&Expr::get_attr(ham_and_eggs.clone(), "ham".into())),
1561 Ok(Value::Lit(Literal::Long(3)))
1562 );
1563 assert_eq!(
1565 eval.interpret_inline_policy(&Expr::get_attr(ham_and_eggs.clone(), "eggs".into())),
1566 Ok(Value::Lit(Literal::Long(7)))
1567 );
1568 assert_eq!(
1570 eval.interpret_inline_policy(&Expr::get_attr(ham_and_eggs, "what".into())),
1571 Err(EvaluationError::RecordAttrDoesNotExist("what".into()))
1572 );
1573
1574 let ham_and_eggs_2 = Expr::record(vec![
1576 ("ham".into(), Expr::val(3)),
1577 ("eggs".into(), Expr::val("why")),
1578 ]);
1579 assert_eq!(
1580 eval.interpret_inline_policy(&Expr::get_attr(ham_and_eggs_2.clone(), "ham".into())),
1581 Ok(Value::Lit(Literal::Long(3)))
1582 );
1583 assert_eq!(
1585 eval.interpret_inline_policy(&Expr::get_attr(ham_and_eggs_2, "eggs".into())),
1586 Ok(Value::from("why"))
1587 );
1588 let ham_and_eggs_3 = Expr::record(vec![
1590 ("ham".into(), Expr::val(3)),
1591 ("eggs".into(), Expr::val("why")),
1592 ("else".into(), Expr::val(EntityUID::with_eid("foo"))),
1593 ]);
1594 assert_eq!(
1595 eval.interpret_inline_policy(&Expr::get_attr(ham_and_eggs_3, "else".into())),
1596 Ok(Value::from(EntityUID::with_eid("foo")))
1597 );
1598 let hams_and_eggs = Expr::record(vec![
1600 (
1601 "hams".into(),
1602 Expr::record(vec![
1603 ("some".into(), Expr::val(1)),
1604 ("more".into(), Expr::val(2)),
1605 ]),
1606 ),
1607 ("eggs".into(), Expr::val("why")),
1608 ]);
1609 assert_eq!(
1610 eval.interpret_inline_policy(&Expr::get_attr(
1611 Expr::get_attr(hams_and_eggs, "hams".into()),
1612 "more".into()
1613 )),
1614 Ok(Value::Lit(Literal::Long(2)))
1615 );
1616 let weird_key = Expr::record(vec![(
1618 "this is a valid map key+.-_%() ".into(),
1619 Expr::val(7),
1620 )]);
1621 assert_eq!(
1622 eval.interpret_inline_policy(&Expr::get_attr(
1623 weird_key,
1624 "this is a valid map key+.-_%() ".into()
1625 )),
1626 Ok(Value::Lit(Literal::Long(7)))
1627 );
1628 assert_eq!(
1630 eval.interpret_inline_policy(&Expr::get_attr(
1631 Expr::record(vec![
1632 ("foo".into(), Expr::val(2)),
1633 (
1634 "bar".into(),
1635 Expr::set(vec!(Expr::val(3), Expr::val(33), Expr::val(333)))
1636 )
1637 ]),
1638 "bar".into()
1639 )),
1640 Ok(Value::set(vec![
1641 Value::from(3),
1642 Value::from(33),
1643 Value::from(333)
1644 ]))
1645 );
1646 assert_eq!(
1648 eval.interpret_inline_policy(&Expr::get_attr(
1649 Expr::get_attr(
1650 Expr::record(vec![
1651 ("foo".into(), Expr::val(2)),
1652 (
1653 "bar".into(),
1654 Expr::record(vec![
1655 ("a+b".into(), Expr::val(5)),
1656 ("jkl;".into(), Expr::val(10)),
1657 ])
1658 ),
1659 ]),
1660 "bar".into()
1661 ),
1662 "a+b".into()
1663 )),
1664 Ok(Value::Lit(Literal::Long(5)))
1665 );
1666 assert_eq!(
1668 eval.interpret_inline_policy(&Expr::get_attr(
1669 Expr::get_attr(
1670 Expr::record(vec![
1671 ("foo".into(), Expr::val(2)),
1672 (
1673 "bar".into(),
1674 Expr::record(vec![
1675 ("foo".into(), Expr::val(4)),
1676 ("cake".into(), Expr::val(77)),
1677 ])
1678 ),
1679 ]),
1680 "bar".into(),
1681 ),
1682 "foo".into(),
1683 )),
1684 Ok(Value::Lit(Literal::Long(4)))
1685 );
1686 assert_eq!(
1688 eval.interpret_inline_policy(&Expr::get_attr(
1689 Expr::get_attr(
1690 Expr::val(EntityUID::with_eid("entity_with_attrs")),
1691 "address".into()
1692 ),
1693 "street".into()
1694 )),
1695 Ok(Value::Lit(Literal::String("234 magnolia".into())))
1696 );
1697 assert_eq!(
1699 eval.interpret_inline_policy(&Expr::get_attr(
1700 Expr::var(Var::Context),
1701 "cur_time".into()
1702 )),
1703 Ok(Value::Lit(Literal::String("03:22:11".into())))
1704 );
1705 assert_eq!(
1707 eval.interpret_inline_policy(&Expr::get_attr(
1708 Expr::get_attr(Expr::var(Var::Context), "device_properties".into()),
1709 "os_name".into()
1710 )),
1711 Ok(Value::Lit(Literal::String("Windows".into())))
1712 );
1713 assert_eq!(
1716 eval.interpret_inline_policy(&Expr::has_attr(
1717 Expr::record(vec![
1718 ("foo".into(), Expr::val(77)),
1719 ("bar".into(), Expr::val("pancakes")),
1720 ]),
1721 "foo".into()
1722 )),
1723 Ok(Value::Lit(Literal::Bool(true)))
1724 );
1725 assert_eq!(
1728 eval.interpret_inline_policy(&Expr::has_attr(
1729 Expr::record(vec![
1730 ("foo".into(), Expr::val(77)),
1731 ("bar".into(), Expr::val("pancakes")),
1732 ]),
1733 "pancakes".into()
1734 )),
1735 Ok(Value::Lit(Literal::Bool(false)))
1736 );
1737 assert_eq!(
1739 eval.interpret_inline_policy(&Expr::has_attr(
1740 Expr::record(vec![("2".into(), Expr::val("ham"))]),
1741 "2".into()
1742 )),
1743 Ok(Value::Lit(Literal::Bool(true)))
1744 );
1745 assert_eq!(
1747 eval.interpret_inline_policy(&Expr::has_attr(
1748 Expr::record(vec![
1749 ("ham".into(), Expr::val(17)),
1750 (
1751 "eggs".into(),
1752 Expr::ite(
1753 Expr::has_attr(
1754 Expr::val(EntityUID::with_eid("foo")),
1755 "spaghetti".into()
1756 ),
1757 Expr::val(3),
1758 Expr::val(7)
1759 )
1760 ),
1761 ]),
1762 "ham".into()
1763 )),
1764 Ok(Value::Lit(Literal::Bool(true)))
1765 );
1766 assert_eq!(
1768 eval.interpret_inline_policy(&Expr::get_attr(Expr::val(1010122), "hello".into())),
1769 Err(EvaluationError::TypeError {
1770 expected: vec![
1771 Type::Record,
1772 Type::entity_type(
1773 Name::parse_unqualified_name("any_entity_type")
1774 .expect("should be a valid identifier")
1775 ),
1776 ],
1777 actual: Type::Long
1778 })
1779 );
1780 assert_eq!(
1782 eval.interpret_inline_policy(&Expr::get_attr(Expr::val("hello"), "eggs".into())),
1783 Err(EvaluationError::TypeError {
1784 expected: vec![
1785 Type::Record,
1786 Type::entity_type(
1787 Name::parse_unqualified_name("any_entity_type")
1788 .expect("should be a valid identifier")
1789 ),
1790 ],
1791 actual: Type::String
1792 })
1793 );
1794 assert_eq!(
1796 eval.interpret_inline_policy(&Expr::has_attr(Expr::val(1010122), "hello".into())),
1797 Err(EvaluationError::TypeError {
1798 expected: vec![
1799 Type::Record,
1800 Type::entity_type(
1801 Name::parse_unqualified_name("any_entity_type")
1802 .expect("should be a valid identifier")
1803 ),
1804 ],
1805 actual: Type::Long
1806 })
1807 );
1808 assert_eq!(
1810 eval.interpret_inline_policy(&Expr::has_attr(Expr::val("hello"), "eggs".into())),
1811 Err(EvaluationError::TypeError {
1812 expected: vec![
1813 Type::Record,
1814 Type::entity_type(
1815 Name::parse_unqualified_name("any_entity_type")
1816 .expect("should be a valid identifier")
1817 ),
1818 ],
1819 actual: Type::String
1820 })
1821 );
1822 }
1823
1824 #[test]
1825 fn interpret_nots() {
1826 let request = basic_request();
1827 let entities = basic_entities();
1828 let exts = Extensions::none();
1829 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
1830 assert_eq!(
1832 eval.interpret_inline_policy(&Expr::not(Expr::val(true))),
1833 Ok(Value::Lit(Literal::Bool(false)))
1834 );
1835 assert_eq!(
1837 eval.interpret_inline_policy(&Expr::not(Expr::val(false))),
1838 Ok(Value::Lit(Literal::Bool(true)))
1839 );
1840 assert_eq!(
1842 eval.interpret_inline_policy(&Expr::not(Expr::val(8))),
1843 Err(EvaluationError::TypeError {
1844 expected: vec![Type::Bool],
1845 actual: Type::Long
1846 })
1847 );
1848 assert_eq!(
1850 eval.interpret_inline_policy(&Expr::not(Expr::var(Var::Action))),
1851 Err(EvaluationError::TypeError {
1852 expected: vec![Type::Bool],
1853 actual: Type::Entity {
1854 ty: EntityUID::test_entity_type(),
1855 }
1856 })
1857 );
1858 assert_eq!(
1860 eval.interpret_inline_policy(&Expr::not(Expr::not(Expr::val(true)))),
1861 Ok(Value::Lit(Literal::Bool(true)))
1862 );
1863 assert_eq!(
1865 eval.interpret_inline_policy(&Expr::not(Expr::ite(
1866 Expr::val(true),
1867 Expr::val(false),
1868 Expr::val(true)
1869 ))),
1870 Ok(Value::Lit(Literal::Bool(true)))
1871 );
1872 assert_eq!(
1874 eval.interpret_inline_policy(&Expr::ite(
1875 Expr::not(Expr::val(true)),
1876 Expr::val("hello"),
1877 Expr::val("goodbye")
1878 )),
1879 Ok(Value::from("goodbye"))
1880 );
1881 }
1882
1883 #[test]
1884 fn interpret_negs() {
1885 let request = basic_request();
1886 let entities = basic_entities();
1887 let exts = Extensions::none();
1888 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
1889 assert_eq!(
1891 eval.interpret_inline_policy(&Expr::neg(Expr::val(101))),
1892 Ok(Value::Lit(Literal::Long(-101)))
1893 );
1894 assert_eq!(
1896 eval.interpret_inline_policy(&Expr::neg(Expr::val(-101))),
1897 Ok(Value::Lit(Literal::Long(101)))
1898 );
1899 assert_eq!(
1901 eval.interpret_inline_policy(&Expr::neg(Expr::val(0))),
1902 Ok(Value::Lit(Literal::Long(0)))
1903 );
1904 assert_eq!(
1906 eval.interpret_inline_policy(&Expr::neg(Expr::neg(Expr::val(7)))),
1907 Ok(Value::Lit(Literal::Long(7)))
1908 );
1909 assert_eq!(
1911 eval.interpret_inline_policy(&Expr::ite(
1912 Expr::val(true),
1913 Expr::neg(Expr::val(8)),
1914 Expr::neg(Expr::val(1))
1915 )),
1916 Ok(Value::Lit(Literal::Long(-8)))
1917 );
1918 assert_eq!(
1920 eval.interpret_inline_policy(&Expr::neg(Expr::val(std::i64::MIN))),
1921 Err(EvaluationError::IntegerOverflow(
1922 IntegerOverflowError::UnaryOp {
1923 op: UnaryOp::Neg,
1924 arg: Value::from(std::i64::MIN)
1925 }
1926 )),
1927 );
1928 assert_eq!(
1930 eval.interpret_inline_policy(&Expr::neg(Expr::val(false))),
1931 Err(EvaluationError::TypeError {
1932 expected: vec![Type::Long],
1933 actual: Type::Bool
1934 })
1935 );
1936 assert_eq!(
1938 eval.interpret_inline_policy(&Expr::neg(Expr::set([
1939 Expr::val(1),
1940 Expr::val(2),
1941 Expr::val(3)
1942 ]))),
1943 Err(EvaluationError::TypeError {
1944 expected: vec![Type::Long],
1945 actual: Type::Set
1946 })
1947 );
1948 }
1949
1950 #[test]
1951 fn interpret_eqs() {
1952 let request = basic_request();
1953 let entities = basic_entities();
1954 let exts = Extensions::none();
1955 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
1956 assert_eq!(
1958 eval.interpret_inline_policy(&Expr::is_eq(Expr::val(33), Expr::val(33))),
1959 Ok(Value::Lit(Literal::Bool(true)))
1960 );
1961 assert_eq!(
1963 eval.interpret_inline_policy(&Expr::is_eq(Expr::val(33), Expr::val(-12))),
1964 Ok(Value::Lit(Literal::Bool(false)))
1965 );
1966 assert_eq!(
1968 eval.interpret_inline_policy(&Expr::ite(
1969 Expr::is_eq(Expr::val("foo"), Expr::val("foo")),
1970 Expr::val(12),
1971 Expr::val(97),
1972 )),
1973 Ok(Value::Lit(Literal::Long(12)))
1974 );
1975 assert_eq!(
1977 eval.interpret_inline_policy(&Expr::ite(
1978 Expr::is_eq(
1979 Expr::set(vec![Expr::val(1), Expr::val(-33), Expr::val(707)]),
1980 Expr::set(vec![Expr::val(1), Expr::val(-33)])
1981 ),
1982 Expr::val(12),
1983 Expr::val(97),
1984 )),
1985 Ok(Value::Lit(Literal::Long(97)))
1986 );
1987 assert_eq!(
1989 eval.interpret_inline_policy(&Expr::is_eq(
1990 Expr::greater(Expr::val(2), Expr::val(0)),
1991 Expr::greater(Expr::val(0), Expr::val(-2))
1992 )),
1993 Ok(Value::Lit(Literal::Bool(true)))
1994 );
1995 assert_eq!(
1997 eval.interpret_inline_policy(&Expr::is_eq(
1998 Expr::add(Expr::val(12), Expr::val(33)),
1999 Expr::sub(Expr::val(50), Expr::val(5)),
2000 )),
2001 Ok(Value::Lit(Literal::Bool(true)))
2002 );
2003 assert_eq!(
2005 eval.interpret_inline_policy(&Expr::is_eq(
2006 Expr::set(vec![Expr::val(1), Expr::val(2), Expr::val(40)]),
2007 Expr::set(vec![Expr::val(1), Expr::val(2), Expr::val(40)])
2008 )),
2009 Ok(Value::Lit(Literal::Bool(true)))
2010 );
2011 assert_eq!(
2013 eval.interpret_inline_policy(&Expr::is_eq(
2014 Expr::set(vec![Expr::val(1), Expr::val(2), Expr::val(40)]),
2015 Expr::set(vec![Expr::val(1), Expr::val(40), Expr::val(2)])
2016 )),
2017 Ok(Value::Lit(Literal::Bool(true)))
2018 );
2019 assert_eq!(
2021 eval.interpret_inline_policy(&Expr::is_eq(
2022 Expr::set(vec![Expr::val(1), Expr::val(-2), Expr::val(40)]),
2023 Expr::set(vec![Expr::val(1), Expr::val(40)])
2024 )),
2025 Ok(Value::Lit(Literal::Bool(false)))
2026 );
2027 assert_eq!(
2029 eval.interpret_inline_policy(&Expr::is_eq(
2030 Expr::set(vec![
2031 Expr::val(1),
2032 Expr::val(1),
2033 Expr::val(1),
2034 Expr::val(2),
2035 Expr::val(40)
2036 ]),
2037 Expr::set(vec![Expr::val(40), Expr::val(1), Expr::val(2)])
2038 )),
2039 Ok(Value::Lit(Literal::Bool(true)))
2040 );
2041 assert_eq!(
2043 eval.interpret_inline_policy(&Expr::is_eq(
2044 Expr::set(vec![
2045 Expr::val(1),
2046 Expr::val(1),
2047 Expr::val(2),
2048 Expr::val(1),
2049 Expr::val(40),
2050 Expr::val(2),
2051 Expr::val(1),
2052 Expr::val(2),
2053 Expr::val(40),
2054 Expr::val(1)
2055 ]),
2056 Expr::set(vec![
2057 Expr::val(1),
2058 Expr::val(40),
2059 Expr::val(1),
2060 Expr::val(2)
2061 ])
2062 )),
2063 Ok(Value::Lit(Literal::Bool(true)))
2064 );
2065 assert_eq!(
2067 eval.interpret_inline_policy(&Expr::is_eq(
2068 Expr::get_attr(Expr::var(Var::Context), "device_properties".into()),
2069 Expr::record(vec![
2070 ("os_name".into(), Expr::val("Windows")),
2071 ("manufacturer".into(), Expr::val("ACME Corp")),
2072 ])
2073 )),
2074 Ok(Value::Lit(Literal::Bool(true)))
2075 );
2076 assert_eq!(
2078 eval.interpret_inline_policy(&Expr::is_eq(
2079 Expr::get_attr(Expr::var(Var::Context), "device_properties".into()),
2080 Expr::record(vec![("os_name".into(), Expr::val("Windows")),])
2081 )),
2082 Ok(Value::Lit(Literal::Bool(false)))
2083 );
2084 assert_eq!(
2086 eval.interpret_inline_policy(&Expr::is_eq(
2087 Expr::get_attr(Expr::var(Var::Context), "device_properties".into()),
2088 Expr::record(vec![
2089 ("os_name".into(), Expr::val("Windows")),
2090 ("manufacturer".into(), Expr::val("ACME Corp")),
2091 ("extrafield".into(), Expr::val(true)),
2092 ])
2093 )),
2094 Ok(Value::Lit(Literal::Bool(false)))
2095 );
2096 assert_eq!(
2098 eval.interpret_inline_policy(&Expr::is_eq(
2099 Expr::get_attr(Expr::var(Var::Context), "device_properties".into()),
2100 Expr::record(vec![
2101 ("os_name".into(), Expr::val("Windows")),
2102 ("manufacturer".into(), Expr::val("ACME Corp")),
2103 ])
2104 )),
2105 Ok(Value::Lit(Literal::Bool(true)))
2106 );
2107 assert_eq!(
2109 eval.interpret_inline_policy(&Expr::is_eq(
2110 Expr::val(EntityUID::with_eid("foo")),
2111 Expr::val(EntityUID::with_eid("foo")),
2112 )),
2113 Ok(Value::Lit(Literal::Bool(true)))
2114 );
2115 assert_eq!(
2117 eval.interpret_inline_policy(&Expr::is_eq(
2118 Expr::val(EntityUID::with_eid("doesnotexist")),
2119 Expr::val(EntityUID::with_eid("doesnotexist")),
2120 )),
2121 Ok(Value::Lit(Literal::Bool(true)))
2122 );
2123 assert_eq!(
2125 eval.interpret_inline_policy(&Expr::is_eq(
2126 Expr::val(EntityUID::with_eid("foo")),
2127 Expr::val(EntityUID::with_eid("bar")),
2128 )),
2129 Ok(Value::Lit(Literal::Bool(false)))
2130 );
2131 assert_eq!(
2133 eval.interpret_inline_policy(&Expr::is_eq(
2134 Expr::val(
2135 EntityUID::with_eid_and_type("type1", "foo")
2136 .expect("should be a valid identifier")
2137 ),
2138 Expr::val(
2139 EntityUID::with_eid_and_type("type2", "bar")
2140 .expect("should be a valid identifier")
2141 ),
2142 )),
2143 Ok(Value::Lit(Literal::Bool(false)))
2144 );
2145 assert_eq!(
2148 eval.interpret_inline_policy(&Expr::is_eq(
2149 Expr::val(
2150 EntityUID::with_eid_and_type("type1", "foo")
2151 .expect("should be a valid identifier")
2152 ),
2153 Expr::val(
2154 EntityUID::with_eid_and_type("type2", "foo")
2155 .expect("should be a valid identifier")
2156 ),
2157 )),
2158 Ok(Value::Lit(Literal::Bool(false)))
2159 );
2160 assert_eq!(
2162 eval.interpret_inline_policy(&Expr::is_eq(
2163 Expr::val(EntityUID::with_eid("foo")),
2164 Expr::val(EntityUID::with_eid("doesnotexist")),
2165 )),
2166 Ok(Value::Lit(Literal::Bool(false)))
2167 );
2168 assert_eq!(
2170 eval.interpret_inline_policy(&Expr::is_eq(
2171 Expr::val("foo"),
2172 Expr::val(EntityUID::with_eid("foo"))
2173 )),
2174 Ok(Value::Lit(Literal::Bool(false)))
2175 );
2176 }
2177
2178 #[test]
2179 fn interpret_compares() {
2180 let request = basic_request();
2181 let entities = basic_entities();
2182 let exts = Extensions::none();
2183 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
2184 assert_eq!(
2186 eval.interpret_inline_policy(&Expr::less(Expr::val(3), Expr::val(303))),
2187 Ok(Value::Lit(Literal::Bool(true)))
2188 );
2189 assert_eq!(
2191 eval.interpret_inline_policy(&Expr::less(Expr::val(3), Expr::val(-303))),
2192 Ok(Value::Lit(Literal::Bool(false)))
2193 );
2194 assert_eq!(
2196 eval.interpret_inline_policy(&Expr::less(Expr::val(-303), Expr::val(-1))),
2197 Ok(Value::Lit(Literal::Bool(true)))
2198 );
2199 assert_eq!(
2201 eval.interpret_inline_policy(&Expr::less(Expr::val(3), Expr::val(3))),
2202 Ok(Value::Lit(Literal::Bool(false)))
2203 );
2204 assert_eq!(
2206 eval.interpret_inline_policy(&Expr::lesseq(Expr::val(-33), Expr::val(0))),
2207 Ok(Value::Lit(Literal::Bool(true)))
2208 );
2209 assert_eq!(
2211 eval.interpret_inline_policy(&Expr::lesseq(Expr::val(3), Expr::val(3))),
2212 Ok(Value::Lit(Literal::Bool(true)))
2213 );
2214 assert_eq!(
2216 eval.interpret_inline_policy(&Expr::greater(Expr::val(7), Expr::val(3))),
2217 Ok(Value::Lit(Literal::Bool(true)))
2218 );
2219 assert_eq!(
2221 eval.interpret_inline_policy(&Expr::greater(Expr::val(7), Expr::val(-3))),
2222 Ok(Value::Lit(Literal::Bool(true)))
2223 );
2224 assert_eq!(
2226 eval.interpret_inline_policy(&Expr::greater(Expr::val(7), Expr::val(7))),
2227 Ok(Value::Lit(Literal::Bool(false)))
2228 );
2229 assert_eq!(
2231 eval.interpret_inline_policy(&Expr::greatereq(Expr::val(0), Expr::val(-7))),
2232 Ok(Value::Lit(Literal::Bool(true)))
2233 );
2234 assert_eq!(
2236 eval.interpret_inline_policy(&Expr::greatereq(Expr::val(-1), Expr::val(7))),
2237 Ok(Value::Lit(Literal::Bool(false)))
2238 );
2239 assert_eq!(
2241 eval.interpret_inline_policy(&Expr::greatereq(Expr::val(7), Expr::val(7))),
2242 Ok(Value::Lit(Literal::Bool(true)))
2243 );
2244 assert_eq!(
2246 eval.interpret_inline_policy(&Expr::less(Expr::val(false), Expr::val(true))),
2247 Err(EvaluationError::TypeError {
2248 expected: vec![Type::Long],
2249 actual: Type::Bool
2250 })
2251 );
2252 assert_eq!(
2254 eval.interpret_inline_policy(&Expr::less(Expr::val(false), Expr::val(false))),
2255 Err(EvaluationError::TypeError {
2256 expected: vec![Type::Long],
2257 actual: Type::Bool
2258 })
2259 );
2260 assert_eq!(
2262 eval.interpret_inline_policy(&Expr::lesseq(Expr::val(true), Expr::val(false))),
2263 Err(EvaluationError::TypeError {
2264 expected: vec![Type::Long],
2265 actual: Type::Bool
2266 })
2267 );
2268 assert_eq!(
2270 eval.interpret_inline_policy(&Expr::lesseq(Expr::val(false), Expr::val(false))),
2271 Err(EvaluationError::TypeError {
2272 expected: vec![Type::Long],
2273 actual: Type::Bool
2274 })
2275 );
2276 assert_eq!(
2278 eval.interpret_inline_policy(&Expr::greater(Expr::val(false), Expr::val(true))),
2279 Err(EvaluationError::TypeError {
2280 expected: vec![Type::Long],
2281 actual: Type::Bool
2282 })
2283 );
2284 assert_eq!(
2286 eval.interpret_inline_policy(&Expr::greater(Expr::val(true), Expr::val(true))),
2287 Err(EvaluationError::TypeError {
2288 expected: vec![Type::Long],
2289 actual: Type::Bool
2290 })
2291 );
2292 assert_eq!(
2294 eval.interpret_inline_policy(&Expr::greatereq(Expr::val(true), Expr::val(false))),
2295 Err(EvaluationError::TypeError {
2296 expected: vec![Type::Long],
2297 actual: Type::Bool
2298 })
2299 );
2300 assert_eq!(
2302 eval.interpret_inline_policy(&Expr::greatereq(Expr::val(true), Expr::val(true))),
2303 Err(EvaluationError::TypeError {
2304 expected: vec![Type::Long],
2305 actual: Type::Bool
2306 })
2307 );
2308 assert_eq!(
2310 eval.interpret_inline_policy(&Expr::less(Expr::val("bc"), Expr::val("zzz"))),
2311 Err(EvaluationError::TypeError {
2312 expected: vec![Type::Long],
2313 actual: Type::String
2314 })
2315 );
2316 assert_eq!(
2318 eval.interpret_inline_policy(&Expr::less(Expr::val("banana"), Expr::val("zzz"))),
2319 Err(EvaluationError::TypeError {
2320 expected: vec![Type::Long],
2321 actual: Type::String
2322 })
2323 );
2324 assert_eq!(
2326 eval.interpret_inline_policy(&Expr::less(Expr::val(""), Expr::val("zzz"))),
2327 Err(EvaluationError::TypeError {
2328 expected: vec![Type::Long],
2329 actual: Type::String
2330 })
2331 );
2332 assert_eq!(
2334 eval.interpret_inline_policy(&Expr::less(Expr::val("a"), Expr::val("1"))),
2335 Err(EvaluationError::TypeError {
2336 expected: vec![Type::Long],
2337 actual: Type::String
2338 })
2339 );
2340 assert_eq!(
2342 eval.interpret_inline_policy(&Expr::less(Expr::val("a"), Expr::val("A"))),
2343 Err(EvaluationError::TypeError {
2344 expected: vec![Type::Long],
2345 actual: Type::String
2346 })
2347 );
2348 assert_eq!(
2350 eval.interpret_inline_policy(&Expr::less(Expr::val("A"), Expr::val("A"))),
2351 Err(EvaluationError::TypeError {
2352 expected: vec![Type::Long],
2353 actual: Type::String
2354 })
2355 );
2356 assert_eq!(
2358 eval.interpret_inline_policy(&Expr::less(Expr::val("zebra"), Expr::val("zebras"))),
2359 Err(EvaluationError::TypeError {
2360 expected: vec![Type::Long],
2361 actual: Type::String
2362 })
2363 );
2364 assert_eq!(
2366 eval.interpret_inline_policy(&Expr::lesseq(Expr::val("zebra"), Expr::val("zebras"))),
2367 Err(EvaluationError::TypeError {
2368 expected: vec![Type::Long],
2369 actual: Type::String
2370 })
2371 );
2372 assert_eq!(
2374 eval.interpret_inline_policy(&Expr::lesseq(Expr::val("zebras"), Expr::val("zebras"))),
2375 Err(EvaluationError::TypeError {
2376 expected: vec![Type::Long],
2377 actual: Type::String
2378 })
2379 );
2380 assert_eq!(
2382 eval.interpret_inline_policy(&Expr::lesseq(Expr::val("zebras"), Expr::val("Zebras"))),
2383 Err(EvaluationError::TypeError {
2384 expected: vec![Type::Long],
2385 actual: Type::String
2386 })
2387 );
2388 assert_eq!(
2390 eval.interpret_inline_policy(&Expr::greater(Expr::val("123"), Expr::val("78"))),
2391 Err(EvaluationError::TypeError {
2392 expected: vec![Type::Long],
2393 actual: Type::String
2394 })
2395 );
2396 assert_eq!(
2398 eval.interpret_inline_policy(&Expr::greatereq(
2399 Expr::val(" zebras"),
2400 Expr::val("zebras")
2401 )),
2402 Err(EvaluationError::TypeError {
2403 expected: vec![Type::Long],
2404 actual: Type::String
2405 })
2406 );
2407 assert_eq!(
2409 eval.interpret_inline_policy(&Expr::greatereq(Expr::val(""), Expr::val(""))),
2410 Err(EvaluationError::TypeError {
2411 expected: vec![Type::Long],
2412 actual: Type::String
2413 })
2414 );
2415 assert_eq!(
2417 eval.interpret_inline_policy(&Expr::greatereq(Expr::val(""), Expr::val("_hi"))),
2418 Err(EvaluationError::TypeError {
2419 expected: vec![Type::Long],
2420 actual: Type::String
2421 })
2422 );
2423 assert_eq!(
2425 eval.interpret_inline_policy(&Expr::greatereq(Expr::val("🦀"), Expr::val("_hi"))),
2426 Err(EvaluationError::TypeError {
2427 expected: vec![Type::Long],
2428 actual: Type::String
2429 })
2430 );
2431 assert_eq!(
2433 eval.interpret_inline_policy(&Expr::less(Expr::val(2), Expr::val("4"))),
2434 Err(EvaluationError::TypeError {
2435 expected: vec![Type::Long],
2436 actual: Type::String
2437 })
2438 );
2439 assert_eq!(
2441 eval.interpret_inline_policy(&Expr::less(Expr::val("4"), Expr::val(2))),
2442 Err(EvaluationError::TypeError {
2443 expected: vec![Type::Long],
2444 actual: Type::String
2445 })
2446 );
2447 assert_eq!(
2449 eval.interpret_inline_policy(&Expr::less(Expr::val(false), Expr::val(1))),
2450 Err(EvaluationError::TypeError {
2451 expected: vec![Type::Long],
2452 actual: Type::Bool
2453 })
2454 );
2455 assert_eq!(
2457 eval.interpret_inline_policy(&Expr::less(Expr::val(1), Expr::val(false))),
2458 Err(EvaluationError::TypeError {
2459 expected: vec![Type::Long],
2460 actual: Type::Bool
2461 })
2462 );
2463 assert_eq!(
2465 eval.interpret_inline_policy(&Expr::less(
2466 Expr::set(vec![Expr::val(1), Expr::val(2)]),
2467 Expr::set(vec![Expr::val(47), Expr::val(0)])
2468 )),
2469 Err(EvaluationError::TypeError {
2470 expected: vec![Type::Long],
2471 actual: Type::Set
2472 })
2473 );
2474 }
2475
2476 #[test]
2477 fn interpret_arithmetic() {
2478 let request = basic_request();
2479 let entities = basic_entities();
2480 let exts = Extensions::none();
2481 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
2482 assert_eq!(
2484 eval.interpret_inline_policy(&Expr::add(Expr::val(11), Expr::val(22))),
2485 Ok(Value::Lit(Literal::Long(33)))
2486 );
2487 assert_eq!(
2489 eval.interpret_inline_policy(&Expr::add(Expr::val(11), Expr::val(0))),
2490 Ok(Value::Lit(Literal::Long(11)))
2491 );
2492 assert_eq!(
2494 eval.interpret_inline_policy(&Expr::add(Expr::val(-1), Expr::val(1))),
2495 Ok(Value::Lit(Literal::Long(0)))
2496 );
2497 assert_eq!(
2499 eval.interpret_inline_policy(&Expr::add(Expr::val(std::i64::MAX), Expr::val(1))),
2500 Err(EvaluationError::IntegerOverflow(
2501 IntegerOverflowError::BinaryOp {
2502 op: BinaryOp::Add,
2503 arg1: Value::from(std::i64::MAX),
2504 arg2: Value::from(1),
2505 }
2506 ))
2507 );
2508 assert_eq!(
2510 eval.interpret_inline_policy(&Expr::add(Expr::val(7), Expr::val("3"))),
2511 Err(EvaluationError::TypeError {
2512 expected: vec![Type::Long],
2513 actual: Type::String
2514 })
2515 );
2516 assert_eq!(
2518 eval.interpret_inline_policy(&Expr::sub(Expr::val(44), Expr::val(31))),
2519 Ok(Value::Lit(Literal::Long(13)))
2520 );
2521 assert_eq!(
2523 eval.interpret_inline_policy(&Expr::sub(Expr::val(5), Expr::val(-3))),
2524 Ok(Value::Lit(Literal::Long(8)))
2525 );
2526 assert_eq!(
2528 eval.interpret_inline_policy(&Expr::sub(Expr::val(std::i64::MIN + 2), Expr::val(3))),
2529 Err(EvaluationError::IntegerOverflow(
2530 IntegerOverflowError::BinaryOp {
2531 op: BinaryOp::Sub,
2532 arg1: Value::from(std::i64::MIN + 2),
2533 arg2: Value::from(3),
2534 }
2535 ))
2536 );
2537 assert_eq!(
2539 eval.interpret_inline_policy(&Expr::sub(Expr::val("ham"), Expr::val("ha"))),
2540 Err(EvaluationError::TypeError {
2541 expected: vec![Type::Long],
2542 actual: Type::String
2543 })
2544 );
2545 assert_eq!(
2547 eval.interpret_inline_policy(&Expr::mul(Expr::val(5), -3)),
2548 Ok(Value::Lit(Literal::Long(-15)))
2549 );
2550 assert_eq!(
2552 eval.interpret_inline_policy(&Expr::mul(Expr::val(5), 0)),
2553 Ok(Value::Lit(Literal::Long(0)))
2554 );
2555 assert_eq!(
2557 eval.interpret_inline_policy(&Expr::mul(Expr::val("5"), 0)),
2558 Err(EvaluationError::TypeError {
2559 expected: vec![Type::Long],
2560 actual: Type::String
2561 })
2562 );
2563 assert_eq!(
2565 eval.interpret_inline_policy(&Expr::mul(Expr::val(std::i64::MAX - 1), 3)),
2566 Err(EvaluationError::IntegerOverflow(
2567 IntegerOverflowError::Multiplication {
2568 arg: Value::from(std::i64::MAX - 1),
2569 constant: 3,
2570 }
2571 ))
2572 );
2573 }
2574
2575 #[test]
2576 fn interpret_set_and_map_membership() {
2577 let request = basic_request();
2578 let entities = rich_entities();
2579 let exts = Extensions::none();
2580 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
2581
2582 assert_eq!(
2584 eval.interpret_inline_policy(&Expr::contains(
2585 Expr::set(vec![Expr::val(2), Expr::val(3), Expr::val(4)]),
2586 Expr::val(2)
2587 )),
2588 Ok(Value::Lit(Literal::Bool(true)))
2589 );
2590 assert_eq!(
2592 eval.interpret_inline_policy(&Expr::contains(
2593 Expr::set(vec![Expr::val(34), Expr::val(2), Expr::val(-7)]),
2594 Expr::val(2)
2595 )),
2596 Ok(Value::Lit(Literal::Bool(true)))
2597 );
2598 assert_eq!(
2600 eval.interpret_inline_policy(&Expr::contains(
2601 Expr::set(vec![Expr::val(34), Expr::val(2), Expr::val(-7)]),
2602 Expr::val(3)
2603 )),
2604 Ok(Value::Lit(Literal::Bool(false)))
2605 );
2606 assert_eq!(
2608 eval.interpret_inline_policy(&Expr::contains(Expr::set(vec![]), Expr::val(7))),
2609 Ok(Value::Lit(Literal::Bool(false)))
2610 );
2611 assert_eq!(
2613 eval.interpret_inline_policy(&Expr::contains(
2614 Expr::set(vec![
2615 Expr::val("some"),
2616 Expr::val("useful"),
2617 Expr::val("tags")
2618 ]),
2619 Expr::val("foo")
2620 )),
2621 Ok(Value::Lit(Literal::Bool(false)))
2622 );
2623 assert_eq!(
2625 eval.interpret_inline_policy(&Expr::contains(
2626 Expr::set(vec![
2627 Expr::val("some"),
2628 Expr::val("useful"),
2629 Expr::val("tags")
2630 ]),
2631 Expr::val("useful")
2632 )),
2633 Ok(Value::Lit(Literal::Bool(true)))
2634 );
2635 assert_eq!(
2637 eval.interpret_inline_policy(&Expr::contains(
2638 Expr::set(vec![
2639 Expr::val(EntityUID::with_eid("child")),
2640 Expr::val(EntityUID::with_eid("sibling"))
2641 ]),
2642 Expr::val(EntityUID::with_eid("child"))
2643 )),
2644 Ok(Value::Lit(Literal::Bool(true)))
2645 );
2646 assert_eq!(
2648 eval.interpret_inline_policy(&Expr::contains(
2649 Expr::set(vec![
2650 Expr::val(EntityUID::with_eid("parent")),
2651 Expr::val(EntityUID::with_eid("sibling"))
2652 ]),
2653 Expr::val(EntityUID::with_eid("child"))
2654 )),
2655 Ok(Value::Lit(Literal::Bool(false)))
2656 );
2657 assert_eq!(
2659 eval.interpret_inline_policy(&Expr::contains(
2660 Expr::set(vec![Expr::val("foo"), Expr::val("bar")]),
2661 Expr::val(3)
2662 )),
2663 Ok(Value::Lit(Literal::Bool(false)))
2664 );
2665 assert_eq!(
2667 eval.interpret_inline_policy(&Expr::contains(
2668 Expr::set(vec![Expr::val("foo"), Expr::val("bar")]),
2669 Expr::set(vec![Expr::val(3)])
2670 )),
2671 Ok(Value::Lit(Literal::Bool(false)))
2672 );
2673 assert_eq!(
2675 eval.interpret_inline_policy(&Expr::contains(
2676 Expr::set(vec![
2677 Expr::set(vec![Expr::val(7)]),
2678 Expr::val("eggs"),
2679 Expr::set(vec![Expr::val(3)])
2680 ]),
2681 Expr::set(vec![Expr::val(3)])
2682 )),
2683 Ok(Value::Lit(Literal::Bool(true)))
2684 );
2685
2686 assert_eq!(
2688 eval.interpret_inline_policy(&Expr::contains(
2689 Expr::set(vec![
2690 Expr::val("2"),
2691 Expr::val(20),
2692 Expr::val(true),
2693 Expr::val(EntityUID::with_eid("foo")),
2694 ]),
2695 Expr::val(2)
2696 )),
2697 Ok(Value::Lit(Literal::Bool(false)))
2698 );
2699 assert_eq!(
2701 eval.interpret_inline_policy(&Expr::contains(
2702 Expr::set(vec![
2703 Expr::val("ham"),
2704 Expr::get_attr(
2705 Expr::get_attr(
2706 Expr::val(EntityUID::with_eid("entity_with_attrs")),
2707 "address".into()
2708 ),
2709 "town".into()
2710 ),
2711 Expr::val(-1),
2712 ]),
2713 Expr::val("barmstadt")
2714 )),
2715 Ok(Value::Lit(Literal::Bool(true)))
2716 );
2717 assert_eq!(
2719 eval.interpret_inline_policy(&Expr::contains(Expr::val(3), Expr::val(7))),
2720 Err(EvaluationError::TypeError {
2721 expected: vec![Type::Set],
2722 actual: Type::Long
2723 })
2724 );
2725 assert_eq!(
2727 eval.interpret_inline_policy(&Expr::contains(
2728 Expr::record(vec![("ham".into(), Expr::val("eggs"))]),
2729 Expr::val("ham")
2730 )),
2731 Err(EvaluationError::TypeError {
2732 expected: vec![Type::Set],
2733 actual: Type::Record,
2734 })
2735 );
2736 assert_eq!(
2738 eval.interpret_inline_policy(&Expr::contains(
2739 Expr::val(3),
2740 Expr::set(vec![Expr::val(1), Expr::val(3), Expr::val(7)])
2741 )),
2742 Err(EvaluationError::TypeError {
2743 expected: vec![Type::Set],
2744 actual: Type::Long,
2745 })
2746 );
2747 }
2748
2749 #[test]
2750 fn interpret_hierarchy_membership() {
2751 let request = basic_request();
2752 let entities = rich_entities();
2753 let exts = Extensions::none();
2754 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
2755 assert_eq!(
2757 eval.interpret_inline_policy(&Expr::is_in(
2758 Expr::val(EntityUID::with_eid("child")),
2759 Expr::val(EntityUID::with_eid("unrelated"))
2760 )),
2761 Ok(Value::Lit(Literal::Bool(false)))
2762 );
2763 assert_eq!(
2765 eval.interpret_inline_policy(&Expr::is_in(
2766 Expr::val(EntityUID::with_eid("child")),
2767 Expr::val(EntityUID::with_eid("parent"))
2768 )),
2769 Ok(Value::Lit(Literal::Bool(true)))
2770 );
2771 assert_eq!(
2773 eval.interpret_inline_policy(&Expr::is_in(
2774 Expr::val(
2775 EntityUID::with_eid_and_type("other_type", "other_child")
2776 .expect("should be a valid identifier")
2777 ),
2778 Expr::val(EntityUID::with_eid("parent"))
2779 )),
2780 Ok(Value::Lit(Literal::Bool(true)))
2781 );
2782 assert_eq!(
2784 eval.interpret_inline_policy(&Expr::is_in(
2785 Expr::val(
2786 EntityUID::with_eid_and_type("other_type", "other_child")
2787 .expect("should be a valid identifier")
2788 ),
2789 Expr::val(EntityUID::with_eid("unrelated"))
2790 )),
2791 Ok(Value::Lit(Literal::Bool(false)))
2792 );
2793 assert_eq!(
2795 eval.interpret_inline_policy(&Expr::is_in(
2796 Expr::val(EntityUID::with_eid("child")),
2797 Expr::val(EntityUID::with_eid("sibling"))
2798 )),
2799 Ok(Value::Lit(Literal::Bool(false)))
2800 );
2801 assert_eq!(
2803 eval.interpret_inline_policy(&Expr::is_in(
2804 Expr::val(EntityUID::with_eid("parent")),
2805 Expr::val(EntityUID::with_eid("parent"))
2806 )),
2807 Ok(Value::Lit(Literal::Bool(true)))
2808 );
2809 assert_eq!(
2811 eval.interpret_inline_policy(&Expr::is_in(
2812 Expr::val(EntityUID::with_eid("doesnotexist")),
2813 Expr::val(EntityUID::with_eid("doesnotexist")),
2814 )),
2815 Ok(Value::Lit(Literal::Bool(true)))
2816 );
2817 assert_eq!(
2819 eval.interpret_inline_policy(&Expr::is_in(
2820 Expr::val(EntityUID::unspecified_from_eid(Eid::new("foo"))),
2821 Expr::val(EntityUID::unspecified_from_eid(Eid::new("foo"))),
2822 )),
2823 Ok(Value::Lit(Literal::Bool(true)))
2824 );
2825 assert_eq!(
2827 eval.interpret_inline_policy(&Expr::is_in(
2828 Expr::val(EntityUID::with_eid("parent")),
2829 Expr::val(EntityUID::with_eid("child"))
2830 )),
2831 Ok(Value::Lit(Literal::Bool(false)))
2832 );
2833 assert_eq!(
2835 eval.interpret_inline_policy(&Expr::is_in(
2836 Expr::val(EntityUID::with_eid("child")),
2837 Expr::val(EntityUID::with_eid("grandparent"))
2838 )),
2839 Ok(Value::Lit(Literal::Bool(true)))
2840 );
2841 assert_eq!(
2843 eval.interpret_inline_policy(&Expr::is_in(
2844 Expr::val(EntityUID::with_eid("doesnotexist")),
2845 Expr::val(EntityUID::with_eid("parent"))
2846 )),
2847 Ok(Value::Lit(Literal::Bool(false)))
2848 );
2849 assert_eq!(
2851 eval.interpret_inline_policy(&Expr::is_in(
2852 Expr::val(EntityUID::with_eid("parent")),
2853 Expr::val(EntityUID::with_eid("doesnotexist"))
2854 )),
2855 Ok(Value::Lit(Literal::Bool(false)))
2856 );
2857 assert_eq!(
2859 eval.interpret_inline_policy(&Expr::is_in(
2860 Expr::val(EntityUID::unspecified_from_eid(Eid::new("foo"))),
2861 Expr::val(EntityUID::with_eid("parent"))
2862 )),
2863 Ok(Value::Lit(Literal::Bool(false)))
2864 );
2865 assert_eq!(
2867 eval.interpret_inline_policy(&Expr::is_in(
2868 Expr::val(EntityUID::with_eid("parent")),
2869 Expr::val(EntityUID::unspecified_from_eid(Eid::new("foo")))
2870 )),
2871 Ok(Value::Lit(Literal::Bool(false)))
2872 );
2873 assert_eq!(
2875 eval.interpret_inline_policy(&Expr::is_in(
2876 Expr::val(EntityUID::with_eid("child")),
2877 Expr::set(vec![
2878 Expr::val(EntityUID::with_eid("grandparent")),
2879 Expr::val(EntityUID::with_eid("sibling")),
2880 ])
2881 )),
2882 Ok(Value::Lit(Literal::Bool(true)))
2883 );
2884 assert_eq!(
2886 eval.interpret_inline_policy(&Expr::is_in(
2887 Expr::val(EntityUID::with_eid("child")),
2888 Expr::set(vec![
2889 Expr::val(EntityUID::with_eid("sibling")),
2890 Expr::val(EntityUID::with_eid("grandparent")),
2891 ])
2892 )),
2893 Ok(Value::Lit(Literal::Bool(true)))
2894 );
2895 assert_eq!(
2897 eval.interpret_inline_policy(&Expr::is_in(
2898 Expr::val(EntityUID::with_eid("child")),
2899 Expr::set(vec![
2900 Expr::val(EntityUID::with_eid("sibling")),
2901 Expr::val(EntityUID::with_eid("unrelated")),
2902 ])
2903 )),
2904 Ok(Value::Lit(Literal::Bool(false)))
2905 );
2906 assert_eq!(
2908 eval.interpret_inline_policy(&Expr::is_in(
2909 Expr::val(EntityUID::with_eid("child")),
2910 Expr::set(vec![
2911 Expr::val(EntityUID::with_eid("unrelated")),
2912 Expr::val(EntityUID::with_eid("child")),
2913 ])
2914 )),
2915 Ok(Value::Lit(Literal::Bool(true)))
2916 );
2917 assert_eq!(
2919 eval.interpret_inline_policy(&Expr::is_in(
2920 Expr::val(EntityUID::with_eid("child")),
2921 Expr::set(vec![
2922 Expr::val(EntityUID::with_eid("child")),
2923 Expr::val(EntityUID::with_eid("unrelated")),
2924 ])
2925 )),
2926 Ok(Value::Lit(Literal::Bool(true)))
2927 );
2928 assert_eq!(
2930 eval.interpret_inline_policy(&Expr::is_in(
2931 Expr::val(EntityUID::with_eid("child")),
2932 Expr::set(vec![
2933 Expr::val(EntityUID::with_eid("child")),
2934 Expr::val(true),
2935 ])
2936 )),
2937 Err(EvaluationError::TypeError {
2938 expected: vec![Type::entity_type(
2939 Name::parse_unqualified_name("any_entity_type")
2940 .expect("should be a valid identifier")
2941 )],
2942 actual: Type::Bool,
2943 })
2944 );
2945 assert_eq!(
2947 eval.interpret_inline_policy(&Expr::is_in(
2948 Expr::val(EntityUID::with_eid("doesnotexistA")),
2949 Expr::set(vec![
2950 Expr::val(EntityUID::with_eid("doesnotexistA")),
2951 Expr::val(EntityUID::with_eid("doesnotexistB")),
2952 ])
2953 )),
2954 Ok(Value::Lit(Literal::Bool(true)))
2955 );
2956 assert_eq!(
2958 eval.interpret_inline_policy(&Expr::is_in(
2959 Expr::val(EntityUID::with_eid("doesnotexistA")),
2960 Expr::set(vec![
2961 Expr::val(EntityUID::with_eid("doesnotexistB")),
2962 Expr::val(EntityUID::with_eid("doesnotexistC")),
2963 ])
2964 )),
2965 Ok(Value::Lit(Literal::Bool(false)))
2966 );
2967 assert_eq!(
2969 eval.interpret_inline_policy(&Expr::is_in(
2970 Expr::val(EntityUID::with_eid("child")),
2971 Expr::set(vec![
2972 Expr::val(EntityUID::with_eid("doesnotexistB")),
2973 Expr::val(EntityUID::with_eid("doesnotexistC")),
2974 ])
2975 )),
2976 Ok(Value::Lit(Literal::Bool(false)))
2977 );
2978 assert_eq!(
2980 eval.interpret_inline_policy(&Expr::is_in(
2981 Expr::val(EntityUID::with_eid("doesnotexistA")),
2982 Expr::set(vec![
2983 Expr::val(EntityUID::with_eid("child")),
2984 Expr::val(EntityUID::with_eid("grandparent")),
2985 ])
2986 )),
2987 Ok(Value::Lit(Literal::Bool(false)))
2988 );
2989 assert_eq!(
2991 eval.interpret_inline_policy(&Expr::is_in(Expr::val("foo"), Expr::val("foobar"))),
2992 Err(EvaluationError::TypeError {
2993 expected: vec![Type::entity_type(
2994 Name::parse_unqualified_name("any_entity_type")
2995 .expect("should be a valid identifier")
2996 )],
2997 actual: Type::String
2998 })
2999 );
3000 assert_eq!(
3002 eval.interpret_inline_policy(&Expr::is_in(
3003 Expr::val("spoon"),
3004 Expr::val(EntityUID::with_eid("entity_with_attrs"))
3005 )),
3006 Err(EvaluationError::TypeError {
3007 expected: vec![Type::entity_type(
3008 Name::parse_unqualified_name("any_entity_type")
3009 .expect("should be a valid identifier")
3010 )],
3011 actual: Type::String
3012 })
3013 );
3014 assert_eq!(
3016 eval.interpret_inline_policy(&Expr::is_in(
3017 Expr::val(3),
3018 Expr::set(vec![Expr::val(34), Expr::val(-2), Expr::val(7)])
3019 )),
3020 Err(EvaluationError::TypeError {
3021 expected: vec![Type::entity_type(
3022 Name::parse_unqualified_name("any_entity_type")
3023 .expect("should be a valid identifier")
3024 )],
3025 actual: Type::Long
3026 })
3027 );
3028 assert_eq!(
3030 eval.interpret_inline_policy(&Expr::is_in(
3031 Expr::val("foo"),
3032 Expr::record(vec![
3033 ("foo".into(), Expr::val(2)),
3034 ("bar".into(), Expr::val(true)),
3035 ])
3036 )),
3037 Err(EvaluationError::TypeError {
3038 expected: vec![Type::entity_type(
3039 Name::parse_unqualified_name("any_entity_type")
3040 .expect("should be a valid identifier")
3041 )],
3042 actual: Type::String
3043 })
3044 );
3045 assert_eq!(
3047 eval.interpret_inline_policy(&Expr::is_in(
3048 Expr::val(EntityUID::with_eid("child")),
3049 Expr::record(vec![
3050 ("foo".into(), Expr::val(2)),
3051 ("bar".into(), Expr::val(true)),
3052 ])
3053 )),
3054 Err(EvaluationError::TypeError {
3055 expected: vec![
3056 Type::Set,
3057 Type::entity_type(
3058 Name::parse_unqualified_name("any_entity_type")
3059 .expect("should be a valid identifier")
3060 )
3061 ],
3062 actual: Type::Record
3063 })
3064 );
3065 }
3066
3067 #[test]
3068 fn interpret_hierarchy_membership_slice() {
3069 let request = Request::new(
3075 EntityUID::with_eid("Alice"),
3076 EntityUID::with_eid("test_action"),
3077 EntityUID::with_eid("test_resource"),
3078 Context::empty(),
3079 );
3080 let mut alice = Entity::with_uid(EntityUID::with_eid("Alice"));
3082 let parent = Entity::with_uid(EntityUID::with_eid("Friends"));
3083 alice.add_ancestor(parent.uid());
3084 let entities = Entities::from_entities(vec![alice], TCComputation::AssumeAlreadyComputed)
3085 .expect("failed to create basic entities");
3086 let exts = Extensions::none();
3087 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
3088 assert_eq!(
3089 eval.interpret_inline_policy(&Expr::is_in(
3090 Expr::val(EntityUID::with_eid("Alice")),
3091 Expr::val(EntityUID::with_eid("Friends"))
3092 )),
3093 Ok(Value::Lit(Literal::Bool(true)))
3094 );
3095 assert_eq!(
3096 eval.interpret_inline_policy(&Expr::is_in(
3097 Expr::val(EntityUID::with_eid("Bob")),
3098 Expr::val(EntityUID::with_eid("Friends"))
3099 )),
3100 Ok(Value::Lit(Literal::Bool(false)))
3101 );
3102 assert_eq!(
3103 eval.interpret_inline_policy(&Expr::is_in(
3104 Expr::val(EntityUID::with_eid("Alice")),
3105 Expr::set(vec![
3106 Expr::val(EntityUID::with_eid("Friends")),
3107 Expr::val(EntityUID::with_eid("Bob"))
3108 ])
3109 )),
3110 Ok(Value::Lit(Literal::Bool(true)))
3111 );
3112 assert_eq!(
3113 eval.interpret_inline_policy(&Expr::is_in(
3114 Expr::val(EntityUID::with_eid("Bob")),
3115 Expr::set(vec![
3116 Expr::val(EntityUID::with_eid("Friends")),
3117 Expr::val(EntityUID::with_eid("Alice"))
3118 ])
3119 )),
3120 Ok(Value::Lit(Literal::Bool(false)))
3121 );
3122 }
3123
3124 #[test]
3125 fn interpret_string_like() {
3126 let request = basic_request();
3127 let entities = basic_entities();
3128 let exts = Extensions::none();
3129 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
3130 assert_eq!(
3132 eval.interpret_inline_policy(
3133 &parse_expr(r#""eggs" like "ham*""#).expect("parsing error")
3134 ),
3135 Ok(Value::Lit(Literal::Bool(false)))
3136 );
3137 assert_eq!(
3138 eval.interpret_inline_policy(
3139 &parse_expr(r#""eggs" like "*ham""#).expect("parsing error")
3140 ),
3141 Ok(Value::Lit(Literal::Bool(false)))
3142 );
3143 assert_eq!(
3144 eval.interpret_inline_policy(
3145 &parse_expr(r#""eggs" like "*ham*""#).expect("parsing error")
3146 ),
3147 Ok(Value::Lit(Literal::Bool(false)))
3148 );
3149 assert_eq!(
3151 eval.interpret_inline_policy(
3152 &parse_expr(r#""ham and eggs" like "ham*""#).expect("parsing error")
3153 ),
3154 Ok(Value::Lit(Literal::Bool(true)))
3155 );
3156 assert_eq!(
3157 eval.interpret_inline_policy(
3158 &parse_expr(r#""ham and eggs" like "*ham""#).expect("parsing error")
3159 ),
3160 Ok(Value::Lit(Literal::Bool(false)))
3161 );
3162 assert_eq!(
3163 eval.interpret_inline_policy(
3164 &parse_expr(r#""ham and eggs" like "*ham*""#).expect("parsing error")
3165 ),
3166 Ok(Value::Lit(Literal::Bool(true)))
3167 );
3168 assert_eq!(
3169 eval.interpret_inline_policy(
3170 &parse_expr(r#""ham and eggs" like "*h*a*m*""#).expect("parsing error")
3171 ),
3172 Ok(Value::Lit(Literal::Bool(true)))
3173 );
3174 assert_eq!(
3176 eval.interpret_inline_policy(
3177 &parse_expr(r#""eggs and ham" like "ham*""#).expect("parsing error")
3178 ),
3179 Ok(Value::Lit(Literal::Bool(false)))
3180 );
3181 assert_eq!(
3182 eval.interpret_inline_policy(
3183 &parse_expr(r#""eggs and ham" like "*ham""#).expect("parsing error")
3184 ),
3185 Ok(Value::Lit(Literal::Bool(true)))
3186 );
3187 assert_eq!(
3189 eval.interpret_inline_policy(
3190 &parse_expr(r#""eggs, ham, and spinach" like "ham*""#).expect("parsing error")
3191 ),
3192 Ok(Value::Lit(Literal::Bool(false)))
3193 );
3194 assert_eq!(
3195 eval.interpret_inline_policy(
3196 &parse_expr(r#""eggs, ham, and spinach" like "*ham""#).expect("parsing error")
3197 ),
3198 Ok(Value::Lit(Literal::Bool(false)))
3199 );
3200 assert_eq!(
3201 eval.interpret_inline_policy(
3202 &parse_expr(r#""eggs, ham, and spinach" like "*ham*""#).expect("parsing error")
3203 ),
3204 Ok(Value::Lit(Literal::Bool(true)))
3205 );
3206 assert_eq!(
3208 eval.interpret_inline_policy(
3209 &parse_expr(r#""Gotham" like "ham*""#).expect("parsing error")
3210 ),
3211 Ok(Value::Lit(Literal::Bool(false)))
3212 );
3213 assert_eq!(
3214 eval.interpret_inline_policy(
3215 &parse_expr(r#""Gotham" like "*ham""#).expect("parsing error")
3216 ),
3217 Ok(Value::Lit(Literal::Bool(true)))
3218 );
3219 assert_eq!(
3221 eval.interpret_inline_policy(
3222 &parse_expr(r#""ham" like "ham""#).expect("parsing error")
3223 ),
3224 Ok(Value::Lit(Literal::Bool(true)))
3225 );
3226 assert_eq!(
3227 eval.interpret_inline_policy(
3228 &parse_expr(r#""ham" like "ham*""#).expect("parsing error")
3229 ),
3230 Ok(Value::Lit(Literal::Bool(true)))
3231 );
3232 assert_eq!(
3233 eval.interpret_inline_policy(
3234 &parse_expr(r#""ham" like "*ham""#).expect("parsing error")
3235 ),
3236 Ok(Value::Lit(Literal::Bool(true)))
3237 );
3238 assert_eq!(
3239 eval.interpret_inline_policy(
3240 &parse_expr(r#""ham" like "*h*a*m*""#).expect("parsing error")
3241 ),
3242 Ok(Value::Lit(Literal::Bool(true)))
3243 );
3244 assert_eq!(
3246 eval.interpret_inline_policy(
3247 &parse_expr(r#""ham and ham" like "ham*""#).expect("parsing error")
3248 ),
3249 Ok(Value::Lit(Literal::Bool(true)))
3250 );
3251 assert_eq!(
3252 eval.interpret_inline_policy(
3253 &parse_expr(r#""ham and ham" like "*ham""#).expect("parsing error")
3254 ),
3255 Ok(Value::Lit(Literal::Bool(true)))
3256 );
3257 assert_eq!(
3259 eval.interpret_inline_policy(
3260 &parse_expr(r#""ham" like "*ham and eggs*""#).expect("parsing error")
3261 ),
3262 Ok(Value::Lit(Literal::Bool(false)))
3263 );
3264 assert_eq!(
3266 eval.interpret_inline_policy(&Expr::like(Expr::val(354), vec![])),
3267 Err(EvaluationError::TypeError {
3268 expected: vec![Type::String],
3269 actual: Type::Long
3270 })
3271 );
3272 assert_eq!(
3274 eval.interpret_inline_policy(&Expr::contains(
3275 Expr::val("ham and ham"),
3276 Expr::val("ham")
3277 )),
3278 Err(EvaluationError::TypeError {
3279 expected: vec![Type::Set],
3280 actual: Type::String
3281 })
3282 );
3283 assert_eq!(
3285 eval.interpret_inline_policy(&Expr::like(
3286 Expr::val("*"),
3287 vec![PatternElem::Char('\u{0000}')]
3288 )),
3289 Ok(Value::Lit(Literal::Bool(false)))
3290 );
3291
3292 assert_eq!(
3293 eval.interpret_inline_policy(
3294 &parse_expr(r#" "\\afterslash" like "\\*" "#).expect("parsing error")
3295 ),
3296 Ok(Value::Lit(Literal::Bool(true)))
3297 );
3298 }
3299
3300 #[test]
3301 fn interpret_string_like_escaped_chars() {
3302 let request = basic_request();
3303 let entities = basic_entities();
3304 let exts = Extensions::none();
3305 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
3306 assert_eq!(
3308 eval.interpret_inline_policy(
3309 &parse_expr(r#""string\\with\\backslashes" like "string\\with\\backslashes""#)
3310 .expect("parsing error")
3311 ),
3312 Ok(Value::Lit(Literal::Bool(true)))
3313 );
3314 assert_eq!(
3315 eval.interpret_inline_policy(
3316 &parse_expr(
3317 r#""string\\with\\backslashes" like "string\u{0000}with\u{0000}backslashe""#
3318 )
3319 .expect("parsing error")
3320 ),
3321 Ok(Value::Lit(Literal::Bool(false)))
3322 );
3323 assert_eq!(
3324 eval.interpret_inline_policy(
3325 &parse_expr(r#""string\\with\\backslashes" like "string*with*backslashes""#)
3326 .expect("parsing error")
3327 ),
3328 Ok(Value::Lit(Literal::Bool(true)))
3329 );
3330 assert_eq!(
3331 eval.interpret_inline_policy(
3332 &parse_expr(r#""string*with*stars" like "string\*with\*stars""#)
3333 .expect("parsing error")
3334 ),
3335 Ok(Value::Lit(Literal::Bool(true)))
3336 );
3337 assert_eq!(eval.interpret_inline_policy(&parse_expr(r#""string\\*with\\*backslashes\\*and\\*stars" like "string\\*with\\*backslashes\\*and\\*stars""#).expect("parsing error")), Ok(Value::Lit(Literal::Bool(true))));
3338 }
3339
3340 #[test]
3341 fn interpret_contains_all_and_contains_any() -> Result<()> {
3342 let request = basic_request();
3343 let entities = basic_entities();
3344 let exts = Extensions::none();
3345 let eval = Evaluator::new(&request, &entities, &exts).expect("failed to create evaluator");
3346 assert_eq!(
3348 eval.interpret_inline_policy(&Expr::contains_all(
3349 Expr::set(vec![Expr::val(1), Expr::val(-22), Expr::val(34)]),
3350 Expr::set(vec![Expr::val(1), Expr::val(-22)])
3351 )),
3352 Ok(Value::Lit(Literal::Bool(true)))
3353 );
3354 assert_eq!(
3356 eval.interpret_inline_policy(&Expr::contains_all(
3357 Expr::set(vec![Expr::val(1), Expr::val(-22), Expr::val(34)]),
3358 Expr::set(vec![Expr::val(-22), Expr::val(1)])
3359 )),
3360 Ok(Value::Lit(Literal::Bool(true)))
3361 );
3362 assert_eq!(
3364 eval.interpret_inline_policy(&Expr::contains_all(
3365 Expr::set(vec![Expr::val(1), Expr::val(-22), Expr::val(34)]),
3366 Expr::set(vec![Expr::val(-22)])
3367 )),
3368 Ok(Value::Lit(Literal::Bool(true)))
3369 );
3370 assert_eq!(
3372 eval.interpret_inline_policy(&Expr::contains_all(
3373 Expr::set(vec![Expr::val(43), Expr::val(34)]),
3374 Expr::set(vec![Expr::val(34), Expr::val(43)])
3375 )),
3376 Ok(Value::Lit(Literal::Bool(true)))
3377 );
3378 assert_eq!(
3380 eval.interpret_inline_policy(&Expr::contains_all(
3381 Expr::set(vec![Expr::val(1), Expr::val(-2), Expr::val(34)]),
3382 Expr::set(vec![Expr::val(1), Expr::val(-22)])
3383 )),
3384 Ok(Value::Lit(Literal::Bool(false)))
3385 );
3386 assert_eq!(
3388 eval.interpret_inline_policy(&Expr::contains_all(
3389 Expr::set(vec![Expr::val(1), Expr::val(34)]),
3390 Expr::set(vec![Expr::val(1), Expr::val(101), Expr::val(34)])
3391 )),
3392 Ok(Value::Lit(Literal::Bool(false)))
3393 );
3394 assert_eq!(
3396 eval.interpret_inline_policy(&Expr::contains_all(
3397 Expr::set(vec![Expr::val(1), Expr::val(34), Expr::val(102)]),
3398 Expr::set(vec![Expr::val(1), Expr::val(101), Expr::val(34)])
3399 )),
3400 Ok(Value::Lit(Literal::Bool(false)))
3401 );
3402 assert_eq!(
3404 eval.interpret_inline_policy(&Expr::contains_all(
3405 Expr::set(vec![Expr::val(2), Expr::val(-7), Expr::val(387)]),
3406 Expr::set(vec![Expr::val(1), Expr::val(101), Expr::val(34)])
3407 )),
3408 Ok(Value::Lit(Literal::Bool(false)))
3409 );
3410 assert_eq!(
3412 eval.interpret_inline_policy(&Expr::contains_all(
3413 Expr::set(vec![Expr::val(2), Expr::val(43)]),
3414 Expr::set(vec![])
3415 )),
3416 Ok(Value::Lit(Literal::Bool(true)))
3417 );
3418 assert_eq!(
3420 eval.interpret_inline_policy(&Expr::contains_all(
3421 Expr::set(vec![]),
3422 Expr::set(vec![Expr::val(2), Expr::val(43)])
3423 )),
3424 Ok(Value::Lit(Literal::Bool(false)))
3425 );
3426 assert_eq!(
3428 eval.interpret_inline_policy(&Expr::contains_all(
3429 Expr::set(vec![
3430 Expr::val(EntityUID::with_eid("bar")),
3431 Expr::val(EntityUID::with_eid("foo"))
3432 ]),
3433 Expr::set(vec![Expr::val(EntityUID::with_eid("foo"))])
3434 )),
3435 Ok(Value::Lit(Literal::Bool(true)))
3436 );
3437 assert_eq!(
3439 eval.interpret_inline_policy(&Expr::contains_all(
3440 Expr::set(vec![
3441 Expr::val(false),
3442 Expr::val(3),
3443 Expr::set(vec![Expr::val(47), Expr::val(0)]),
3444 Expr::record(vec![("2".into(), Expr::val("ham"))])
3445 ]),
3446 Expr::set(vec![
3447 Expr::val(3),
3448 Expr::record(vec![("2".into(), Expr::val("ham"))])
3449 ])
3450 )),
3451 Ok(Value::Lit(Literal::Bool(true)))
3452 );
3453 assert_eq!(
3455 eval.interpret_inline_policy(&Expr::contains_all(
3456 Expr::val("ham"),
3457 Expr::val("ham and eggs")
3458 )),
3459 Err(EvaluationError::TypeError {
3460 expected: vec![Type::Set],
3461 actual: Type::String
3462 })
3463 );
3464 assert_eq!(
3466 eval.interpret_inline_policy(&Expr::contains_all(
3467 Expr::record(vec![("2".into(), Expr::val("ham"))]),
3468 Expr::record(vec![
3469 ("2".into(), Expr::val("ham")),
3470 ("3".into(), Expr::val("eggs"))
3471 ])
3472 )),
3473 Err(EvaluationError::TypeError {
3474 expected: vec![Type::Set],
3475 actual: Type::Record
3476 })
3477 );
3478 assert_eq!(
3480 eval.interpret_inline_policy(&Expr::contains_any(
3481 Expr::set(vec![Expr::val(1), Expr::val(-22)]),
3482 Expr::set(vec![Expr::val(1), Expr::val(-22), Expr::val(34)])
3483 )),
3484 Ok(Value::Lit(Literal::Bool(true)))
3485 );
3486 assert_eq!(
3488 eval.interpret_inline_policy(&Expr::contains_any(
3489 Expr::set(vec![Expr::val(1), Expr::val(-22), Expr::val(34)]),
3490 Expr::set(vec![Expr::val(1), Expr::val(-22)])
3491 )),
3492 Ok(Value::Lit(Literal::Bool(true)))
3493 );
3494 assert_eq!(
3496 eval.interpret_inline_policy(&Expr::contains_any(
3497 Expr::set(vec![Expr::val(-22)]),
3498 Expr::set(vec![Expr::val(1), Expr::val(-22), Expr::val(34)])
3499 )),
3500 Ok(Value::Lit(Literal::Bool(true)))
3501 );
3502 assert_eq!(
3504 eval.interpret_inline_policy(&Expr::contains_any(
3505 Expr::set(vec![Expr::val(1), Expr::val(101)]),
3506 Expr::set(vec![Expr::val(1), Expr::val(-22), Expr::val(34)])
3507 )),
3508 Ok(Value::Lit(Literal::Bool(true)))
3509 );
3510 assert_eq!(
3512 eval.interpret_inline_policy(&Expr::contains_any(
3513 Expr::set(vec![Expr::val(1), Expr::val(101)]),
3514 Expr::set(vec![Expr::val(-22), Expr::val(34)])
3515 )),
3516 Ok(Value::Lit(Literal::Bool(false)))
3517 );
3518 assert_eq!(
3520 eval.interpret_inline_policy(&Expr::contains_any(
3521 Expr::set(vec![]),
3522 Expr::set(vec![Expr::val(-22), Expr::val(34)])
3523 )),
3524 Ok(Value::Lit(Literal::Bool(false)))
3525 );
3526 assert_eq!(
3528 eval.interpret_inline_policy(&Expr::contains_any(
3529 Expr::set(vec![Expr::val(-22), Expr::val(34)]),
3530 Expr::set(vec![])
3531 )),
3532 Ok(Value::Lit(Literal::Bool(false)))
3533 );
3534 assert_eq!(
3536 eval.interpret_inline_policy(&Expr::contains_any(
3537 Expr::set(vec![
3538 Expr::val(EntityUID::with_eid("foo")),
3539 Expr::val(EntityUID::with_eid("bar"))
3540 ]),
3541 Expr::set(vec![
3542 Expr::val(EntityUID::with_eid("ham")),
3543 Expr::val(EntityUID::with_eid("eggs"))
3544 ])
3545 )),
3546 Ok(Value::Lit(Literal::Bool(false)))
3547 );
3548 assert_eq!(
3550 eval.interpret_inline_policy(&Expr::contains_any(
3551 Expr::set(vec![
3552 Expr::val(3),
3553 Expr::record(vec![
3554 ("2".into(), Expr::val("ham")),
3555 ("1".into(), Expr::val("eggs"))
3556 ])
3557 ]),
3558 Expr::set(vec![
3559 Expr::val(7),
3560 Expr::val(false),
3561 Expr::set(vec![Expr::val(-22), Expr::val(true)]),
3562 Expr::record(vec![
3563 ("1".into(), Expr::val("eggs")),
3564 ("2".into(), Expr::val("ham"))
3565 ])
3566 ])
3567 )),
3568 Ok(Value::Lit(Literal::Bool(true)))
3569 );
3570 assert_eq!(
3572 eval.interpret_inline_policy(&Expr::contains_any(
3573 Expr::val("ham"),
3574 Expr::val("ham and eggs")
3575 )),
3576 Err(EvaluationError::TypeError {
3577 expected: vec![Type::Set],
3578 actual: Type::String
3579 })
3580 );
3581 assert_eq!(
3583 eval.interpret_inline_policy(&Expr::contains_any(
3584 Expr::record(vec![("2".into(), Expr::val("ham"))]),
3585 Expr::record(vec![
3586 ("2".into(), Expr::val("ham")),
3587 ("3".into(), Expr::val("eggs"))
3588 ])
3589 )),
3590 Err(EvaluationError::TypeError {
3591 expected: vec![Type::Set],
3592 actual: Type::Record
3593 })
3594 );
3595 Ok(())
3596 }
3597
3598 #[test]
3599 fn eval_and_or() -> Result<()> {
3600 use crate::parser;
3601 let request = basic_request();
3602 let eparser: EntityJsonParser<'_, '_> =
3603 EntityJsonParser::new(None, Extensions::none(), TCComputation::ComputeNow);
3604 let entities = eparser.from_json_str("[]").expect("empty slice");
3605 let exts = Extensions::none();
3606 let evaluator = Evaluator::new(&request, &entities, &exts).expect("empty slice");
3607
3608 let raw_expr = "(false && 3)";
3610 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3611 assert!(evaluator.interpret_inline_policy(&expr).is_ok());
3612
3613 let raw_expr = "(true || 3)";
3614 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3615 assert!(evaluator.interpret_inline_policy(&expr).is_ok());
3616
3617 let raw_expr = "(false && 3) == 3";
3619 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3620 assert!(evaluator.interpret_inline_policy(&expr).is_ok());
3621
3622 let raw_expr = "(true || 3) == 3";
3623 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3624 assert!(evaluator.interpret_inline_policy(&expr).is_ok());
3625
3626 let raw_expr = "(false && 3 && true) == 3";
3627 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3628 assert!(evaluator.interpret_inline_policy(&expr).is_ok());
3629
3630 let raw_expr = "(true || 3 || true) == 3";
3631 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3632 assert!(evaluator.interpret_inline_policy(&expr).is_ok());
3633
3634 let raw_expr = "(true && 3)";
3636 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3637 let t = evaluator.interpret_inline_policy(&expr);
3638 println!("EXPR={:?}", t);
3639 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3640
3641 let raw_expr = "(3 && true)";
3642 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3643 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3644
3645 let raw_expr = "(3 && false)";
3646 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3647 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3648
3649 let raw_expr = "(3 || true)";
3650 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3651 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3652
3653 let raw_expr = "(3 || false)";
3654 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3655 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3656
3657 let raw_expr = "(false || 3)";
3658 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3659 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3660
3661 let raw_expr = "(true && 3) == 3";
3662 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3663 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3664
3665 let raw_expr = "(3 && true) == 3";
3666 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3667 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3668
3669 let raw_expr = "(3 && false) == 3";
3670 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3671 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3672
3673 let raw_expr = "(3 || true) == 3";
3674 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3675 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3676
3677 let raw_expr = "(3 || false) == 3";
3678 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3679 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3680
3681 let raw_expr = "(false || 3) == 3";
3682 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3683 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3684
3685 let raw_expr = "(true && 3 && true) == 3";
3686 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3687 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3688
3689 let raw_expr = "(3 && true && true) == 3";
3690 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3691 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3692
3693 let raw_expr = "(3 && false && true) == 3";
3694 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3695 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3696
3697 let raw_expr = "(3 || true || true) == 3";
3698 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3699 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3700
3701 let raw_expr = "(3 || false || true) == 3";
3702 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3703 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3704
3705 let raw_expr = "(false || 3 || true) == 3";
3706 let expr = parser::parse_expr(raw_expr).expect("parse fail");
3707 assert!(evaluator.interpret_inline_policy(&expr).is_err());
3708
3709 Ok(())
3710 }
3711
3712 #[test]
3713 fn template_env_tests() {
3714 let request = basic_request();
3715 let eparser: EntityJsonParser<'_, '_> =
3716 EntityJsonParser::new(None, Extensions::none(), TCComputation::ComputeNow);
3717 let entities = eparser.from_json_str("[]").expect("empty slice");
3718 let exts = Extensions::none();
3719 let evaluator = Evaluator::new(&request, &entities, &exts).expect("empty slice");
3720 let e = Expr::slot(SlotId::principal());
3721
3722 let slots = HashMap::new();
3723 let r = evaluator.partial_interpret(&e, &slots);
3724 match r {
3725 Err(EvaluationError::TemplateInstantiationError(slotid)) => {
3726 assert_eq!(slotid, SlotId::principal())
3727 }
3728 Err(e) => panic!("Got wrong error: {e}"),
3729 Ok(v) => panic!("Got wrong response: {v}"),
3730 };
3731
3732 let mut slots = HashMap::new();
3733 slots.insert(SlotId::principal(), EntityUID::with_eid("eid"));
3734 let r = evaluator.partial_interpret(&e, &slots);
3735 match r {
3736 Ok(e) => assert_eq!(
3737 e,
3738 PartialValue::Value(Value::Lit(Literal::EntityUID(Arc::new(
3739 EntityUID::with_eid("eid")
3740 ))))
3741 ),
3742 Err(e) => panic!("Got unexpected error {e}"),
3743 };
3744 }
3745
3746 #[test]
3747 fn template_interp() {
3748 let t = parse_policy_template(
3749 Some("template".to_string()),
3750 r#"permit(principal == ?principal, action, resource);"#,
3751 )
3752 .expect("Parse Error");
3753 let mut pset = PolicySet::new();
3754 pset.add_template(t)
3755 .expect("Template already present in PolicySet");
3756 let mut values = HashMap::new();
3757 values.insert(SlotId::principal(), EntityUID::with_eid("p"));
3758 pset.link(
3759 PolicyID::from_string("template"),
3760 PolicyID::from_string("instance"),
3761 values,
3762 )
3763 .expect("Instantiation failed!");
3764 let q = Request::new(
3765 EntityUID::with_eid("p"),
3766 EntityUID::with_eid("a"),
3767 EntityUID::with_eid("r"),
3768 Context::empty(),
3769 );
3770 let eparser: EntityJsonParser<'_, '_> =
3771 EntityJsonParser::new(None, Extensions::none(), TCComputation::ComputeNow);
3772 let entities = eparser.from_json_str("[]").expect("empty slice");
3773 let exts = Extensions::none();
3774 let eval = Evaluator::new(&q, &entities, &exts).expect("Failed to start evaluator");
3775
3776 let ir = pset.policies().next().expect("No linked policies");
3777 assert!(
3778 match eval.partial_evaluate(ir).expect("evaluation_failed") {
3779 Either::Left(b) => b,
3780 Either::Right(_) => false,
3781 },
3782 "Should be enforced"
3783 );
3784 }
3785
3786 #[test]
3787 fn restricted_expressions() {
3788 let exts = Extensions::all_available();
3789 let evaluator = RestrictedEvaluator::new(&exts);
3790
3791 assert_eq!(
3793 BorrowedRestrictedExpr::new(&Expr::val(true))
3794 .map_err(Into::into)
3795 .and_then(|e| evaluator.partial_interpret(e)),
3796 Ok(Value::from(true).into())
3797 );
3798 assert_eq!(
3799 BorrowedRestrictedExpr::new(&Expr::val(-2))
3800 .map_err(Into::into)
3801 .and_then(|e| evaluator.partial_interpret(e)),
3802 Ok(Value::from(-2).into())
3803 );
3804 assert_eq!(
3805 BorrowedRestrictedExpr::new(&Expr::val("hello world"))
3806 .map_err(Into::into)
3807 .and_then(|e| evaluator.partial_interpret(e)),
3808 Ok(Value::from("hello world").into())
3809 );
3810 assert_eq!(
3811 BorrowedRestrictedExpr::new(&Expr::val(EntityUID::with_eid("alice")))
3812 .map_err(Into::into)
3813 .and_then(|e| evaluator.partial_interpret(e)),
3814 Ok(Value::from(EntityUID::with_eid("alice")).into())
3815 );
3816 assert!(matches!(
3817 BorrowedRestrictedExpr::new(&Expr::var(Var::Principal))
3818 .map_err(Into::into)
3819 .and_then(|e| evaluator.partial_interpret(e)),
3820 Err(EvaluationError::InvalidRestrictedExpression { .. })
3821 ));
3822 assert!(matches!(
3823 BorrowedRestrictedExpr::new(&Expr::var(Var::Action))
3824 .map_err(Into::into)
3825 .and_then(|e| evaluator.partial_interpret(e)),
3826 Err(EvaluationError::InvalidRestrictedExpression { .. })
3827 ));
3828 assert!(matches!(
3829 BorrowedRestrictedExpr::new(&Expr::var(Var::Resource))
3830 .map_err(Into::into)
3831 .and_then(|e| evaluator.partial_interpret(e)),
3832 Err(EvaluationError::InvalidRestrictedExpression { .. })
3833 ));
3834 assert!(matches!(
3835 BorrowedRestrictedExpr::new(&Expr::var(Var::Context))
3836 .map_err(Into::into)
3837 .and_then(|e| evaluator.partial_interpret(e)),
3838 Err(EvaluationError::InvalidRestrictedExpression { .. })
3839 ));
3840 assert!(matches!(
3841 BorrowedRestrictedExpr::new(&Expr::ite(Expr::val(true), Expr::val(7), Expr::val(12)),)
3842 .map_err(Into::into)
3843 .and_then(|e| evaluator.partial_interpret(e)),
3844 Err(EvaluationError::InvalidRestrictedExpression { .. })
3845 ));
3846 assert!(matches!(
3847 BorrowedRestrictedExpr::new(&Expr::and(Expr::val("bogus"), Expr::val(true)))
3848 .map_err(Into::into)
3849 .and_then(|e| evaluator.partial_interpret(e)),
3850 Err(EvaluationError::InvalidRestrictedExpression { .. })
3851 ));
3852 assert!(matches!(
3853 BorrowedRestrictedExpr::new(&Expr::or(Expr::val("bogus"), Expr::val(true)))
3854 .map_err(Into::into)
3855 .and_then(|e| evaluator.partial_interpret(e)),
3856 Err(EvaluationError::InvalidRestrictedExpression { .. })
3857 ));
3858 assert!(matches!(
3859 BorrowedRestrictedExpr::new(&Expr::not(Expr::val(true)))
3860 .map_err(Into::into)
3861 .and_then(|e| evaluator.partial_interpret(e)),
3862 Err(EvaluationError::InvalidRestrictedExpression { .. })
3863 ));
3864 assert!(matches!(
3865 BorrowedRestrictedExpr::new(&Expr::is_in(
3866 Expr::val(EntityUID::with_eid("alice")),
3867 Expr::val(EntityUID::with_eid("some_group"))
3868 ))
3869 .map_err(Into::into)
3870 .and_then(|e| evaluator.partial_interpret(e)),
3871 Err(EvaluationError::InvalidRestrictedExpression { .. })
3872 ));
3873 assert!(matches!(
3874 BorrowedRestrictedExpr::new(&Expr::is_eq(
3875 Expr::val(EntityUID::with_eid("alice")),
3876 Expr::val(EntityUID::with_eid("some_group"))
3877 ))
3878 .map_err(Into::into)
3879 .and_then(|e| evaluator.partial_interpret(e)),
3880 Err(EvaluationError::InvalidRestrictedExpression { .. })
3881 ));
3882 assert!(matches!(
3883 BorrowedRestrictedExpr::new(&Expr::call_extension_fn(
3884 "ip".parse().expect("should be a valid Name"),
3885 vec![Expr::val("222.222.222.222")]
3886 ))
3887 .map_err(Into::into)
3888 .and_then(|e| evaluator.partial_interpret(e)),
3889 Ok(PartialValue::Value(Value::ExtensionValue(_)))
3890 ));
3891 assert!(matches!(
3892 BorrowedRestrictedExpr::new(&Expr::get_attr(
3893 Expr::val(EntityUID::with_eid("alice")),
3894 "pancakes".into()
3895 ),)
3896 .map_err(Into::into)
3897 .and_then(|e| evaluator.partial_interpret(e)),
3898 Err(EvaluationError::InvalidRestrictedExpression { .. })
3899 ));
3900 assert!(matches!(
3901 BorrowedRestrictedExpr::new(&Expr::has_attr(
3902 Expr::val(EntityUID::with_eid("alice")),
3903 "pancakes".into()
3904 ),)
3905 .map_err(Into::into)
3906 .and_then(|e| evaluator.partial_interpret(e)),
3907 Err(EvaluationError::InvalidRestrictedExpression { .. })
3908 ));
3909 assert!(matches!(
3910 BorrowedRestrictedExpr::new(&Expr::like(
3911 Expr::val("abcdefg12"),
3912 vec![
3913 PatternElem::Char('a'),
3914 PatternElem::Char('b'),
3915 PatternElem::Char('c'),
3916 PatternElem::Wildcard
3917 ]
3918 ),)
3919 .map_err(Into::into)
3920 .and_then(|e| evaluator.partial_interpret(e)),
3921 Err(EvaluationError::InvalidRestrictedExpression { .. })
3922 ));
3923 assert!(matches!(
3924 BorrowedRestrictedExpr::new(&Expr::set([Expr::val("hi"), Expr::val("there")]))
3925 .map_err(Into::into)
3926 .and_then(|e| evaluator.partial_interpret(e)),
3927 Ok(PartialValue::Value(Value::Set(_)))
3928 ));
3929 assert!(matches!(
3930 BorrowedRestrictedExpr::new(&Expr::record([
3931 ("hi".into(), Expr::val(1001)),
3932 ("foo".into(), Expr::val("bar"))
3933 ]),)
3934 .map_err(Into::into)
3935 .and_then(|e| evaluator.partial_interpret(e)),
3936 Ok(PartialValue::Value(Value::Record(_)))
3937 ));
3938
3939 assert!(matches!(
3941 BorrowedRestrictedExpr::new(&Expr::set([
3942 Expr::val("hi"),
3943 Expr::and(Expr::val("bogus"), Expr::val(false))
3944 ]),)
3945 .map_err(Into::into)
3946 .and_then(|e| evaluator.partial_interpret(e)),
3947 Err(EvaluationError::InvalidRestrictedExpression { .. })
3948 ));
3949 assert!(matches!(
3950 BorrowedRestrictedExpr::new(&Expr::call_extension_fn(
3951 "ip".parse().expect("should be a valid Name"),
3952 vec![Expr::var(Var::Principal)],
3953 ),)
3954 .map_err(Into::into)
3955 .and_then(|e| evaluator.partial_interpret(e)),
3956 Err(EvaluationError::InvalidRestrictedExpression { .. })
3957 ));
3958 }
3959
3960 #[test]
3961 fn simple_partial() {
3962 let pset = parse_policyset(
3963 r#"
3964 permit(principal == Principal::"alice", action, resource);
3965 "#,
3966 )
3967 .expect("Failed to parse");
3968 let euid =
3969 Arc::new(EntityUID::from_str(r#"Principal::"alice""#).expect("EUID failed to parse"));
3970 let p = pset
3971 .get(&PolicyID::from_string("policy0"))
3972 .expect("No such policy");
3973 let q = Request::new_with_unknowns(
3974 EntityUIDEntry::Unknown,
3975 EntityUIDEntry::Unknown,
3976 EntityUIDEntry::Unknown,
3977 Some(Context::empty()),
3978 );
3979 let es = Entities::new();
3980 let exts = Extensions::none();
3981 let e = Evaluator::new(&q, &es, &exts).expect("failed to create evaluator");
3982 match e.partial_evaluate(p).expect("eval error") {
3983 Either::Left(_) => panic!("Evalled to a value"),
3984 Either::Right(expr) => {
3985 println!("{expr}");
3986 assert!(expr.is_unknown());
3987 let m: HashMap<_, _> = [("principal".into(), Value::Lit(Literal::EntityUID(euid)))]
3988 .into_iter()
3989 .collect();
3990 let new_expr = expr.substitute(&m).unwrap();
3991 assert_eq!(
3992 e.partial_interpret(&new_expr, &HashMap::new())
3993 .expect("Failed to eval"),
3994 PartialValue::Value(true.into())
3995 );
3996 }
3997 }
3998 }
3999
4000 fn partial_context_test(context_expr: Expr, e: Expr) -> Either<Value, Expr> {
4001 let euid: EntityUID = r#"Test::"test""#.parse().unwrap();
4002 let rexpr = RestrictedExpr::new(context_expr)
4003 .expect("Context Expression was not a restricted expression");
4004 let context = Context::from_expr(rexpr);
4005 let q = Request::new(euid.clone(), euid.clone(), euid, context);
4006 let es = Entities::new();
4007 let exts = Extensions::none();
4008 let eval = Evaluator::new(&q, &es, &exts).expect("Failed to instantiate evaluator");
4009 eval.partial_eval_expr(&e).unwrap()
4010 }
4011
4012 #[test]
4013 fn partial_contexts1() {
4014 let c_expr = Expr::record([("cell".into(), Expr::unknown("cell"))]);
4016 let expr = Expr::binary_app(
4017 BinaryOp::Eq,
4018 Expr::get_attr(Expr::var(Var::Context), "cell".into()),
4019 Expr::val(2),
4020 );
4021 let expected = Expr::binary_app(
4022 BinaryOp::Eq,
4023 Expr::unknown("cell".to_string()),
4024 Expr::val(2),
4025 );
4026
4027 let r = partial_context_test(c_expr, expr);
4028
4029 assert_eq!(r, Either::Right(expected));
4030 }
4031
4032 #[test]
4033 fn partial_contexts2() {
4034 let c_expr = Expr::record([
4036 ("loc".into(), Expr::val("test")),
4037 ("cell".into(), Expr::unknown("cell")),
4038 ]);
4039 let expr = Expr::binary_app(
4041 BinaryOp::Eq,
4042 Expr::get_attr(Expr::var(Var::Context), "cell".into()),
4043 Expr::val(2),
4044 );
4045 let r = partial_context_test(c_expr.clone(), expr);
4046 let expected = Expr::binary_app(
4047 BinaryOp::Eq,
4048 Expr::unknown("cell".to_string()),
4049 Expr::val(2),
4050 );
4051 assert_eq!(r, Either::Right(expected));
4052
4053 let expr = Expr::binary_app(
4055 BinaryOp::Eq,
4056 Expr::get_attr(Expr::var(Var::Context), "loc".into()),
4057 Expr::val(2),
4058 );
4059 let r = partial_context_test(c_expr, expr);
4060 assert_eq!(r, Either::Left(false.into()));
4061 }
4062
4063 #[test]
4064 fn partial_contexts3() {
4065 let row = Expr::record([("row".into(), Expr::unknown("row"))]);
4067 let c_expr = Expr::record([("loc".into(), Expr::val("test")), ("cell".into(), row)]);
4069 let expr = Expr::binary_app(
4072 BinaryOp::Eq,
4073 Expr::get_attr(
4074 Expr::get_attr(Expr::var(Var::Context), "cell".into()),
4075 "row".into(),
4076 ),
4077 Expr::val(2),
4078 );
4079 let r = partial_context_test(c_expr, expr);
4080 let expected =
4081 Expr::binary_app(BinaryOp::Eq, Expr::unknown("row".to_string()), Expr::val(2));
4082 assert_eq!(r, Either::Right(expected));
4083 }
4084
4085 #[test]
4086 fn partial_contexts4() {
4087 let row = Expr::record([
4089 ("row".into(), Expr::unknown("row")),
4090 ("col".into(), Expr::unknown("col")),
4091 ]);
4092 let c_expr = Expr::record([("loc".into(), Expr::val("test")), ("cell".into(), row)]);
4094 let expr = Expr::binary_app(
4097 BinaryOp::Eq,
4098 Expr::get_attr(
4099 Expr::get_attr(Expr::var(Var::Context), "cell".into()),
4100 "row".into(),
4101 ),
4102 Expr::val(2),
4103 );
4104 let r = partial_context_test(c_expr.clone(), expr);
4105 let expected = Expr::binary_app(BinaryOp::Eq, Expr::unknown("row"), Expr::val(2));
4106 assert_eq!(r, Either::Right(expected));
4107 let expr = Expr::binary_app(
4109 BinaryOp::Eq,
4110 Expr::get_attr(
4111 Expr::get_attr(Expr::var(Var::Context), "cell".into()),
4112 "col".into(),
4113 ),
4114 Expr::val(2),
4115 );
4116 let r = partial_context_test(c_expr, expr);
4117 let expected =
4118 Expr::binary_app(BinaryOp::Eq, Expr::unknown("col".to_string()), Expr::val(2));
4119 assert_eq!(r, Either::Right(expected));
4120 }
4121
4122 #[test]
4123 fn partial_context_fail() {
4124 let context = Context::from_expr(RestrictedExpr::new_unchecked(Expr::record([
4125 ("a".into(), Expr::val(3)),
4126 ("b".into(), Expr::unknown("b".to_string())),
4127 ])));
4128 let euid: EntityUID = r#"Test::"test""#.parse().unwrap();
4129 let q = Request::new(euid.clone(), euid.clone(), euid, context);
4130 let es = Entities::new();
4131 let exts = Extensions::none();
4132 let eval = Evaluator::new(&q, &es, &exts).expect("Failed to instantiate evaluator");
4133 let e = Expr::get_attr(Expr::var(Var::Context), "foo".into());
4134 assert!(eval.partial_eval_expr(&e).is_err())
4135 }
4136
4137 #[test]
4138 fn mikes_test() {
4139 let policyset = parse_policyset(
4140 r#"
4141 permit(
4142 principal == Principal::"p",
4143 action == Action::"a",
4144 resource == Table::"t"
4145 ) when {
4146 context.cell.row > 5 && context.cell.col < 2
4147 };
4148 "#,
4149 )
4150 .expect("Failed to parse");
4151 let policy = policyset
4152 .get(&PolicyID::from_string("policy0"))
4153 .expect("No such policy");
4154
4155 let es = Entities::new();
4156
4157 let p: EntityUID = r#"Principal::"p""#.parse().expect("Failed to parse");
4158 let a: EntityUID = r#"Action::"a""#.parse().expect("Failed to parse");
4159 let r: EntityUID = r#"Table::"t""#.parse().expect("Failed to parse");
4160
4161 let c_expr = RestrictedExpr::new(Expr::record([(
4162 "cell".into(),
4163 Expr::unknown("cell".to_string()),
4164 )]))
4165 .expect("should qualify as restricted");
4166 let context = Context::from_expr(c_expr);
4167
4168 let q = Request::new(p, a, r, context);
4169 let exts = Extensions::none();
4170 let eval = Evaluator::new(&q, &es, &exts).expect("Could not create evaluator");
4171
4172 let result = eval.partial_evaluate(policy).expect("Eval error");
4173 match result {
4174 Either::Left(_) => panic!("Got a value"),
4175 Either::Right(r) => {
4176 println!("{r}");
4177 }
4178 }
4179 }
4180
4181 fn empty_request() -> Request {
4182 let p: EntityUID = r#"p::"Principal""#.parse().unwrap();
4183 let a: EntityUID = r#"a::"Action""#.parse().unwrap();
4184 let r: EntityUID = r#"r::"Resource""#.parse().unwrap();
4185 let c = Context::empty();
4186 Request::new(p, a, r, c)
4187 }
4188
4189 #[test]
4190 fn if_semantics_residual_guard() {
4191 let a = Expr::unknown("guard".to_string());
4192 let b = Expr::and(Expr::val(1), Expr::val(2));
4193 let c = Expr::val(true);
4194
4195 let e = Expr::ite(a, b, c);
4196
4197 let es = Entities::new();
4198
4199 let exts = Extensions::none();
4200 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4201
4202 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4203
4204 assert_eq!(
4205 r,
4206 PartialValue::Residual(Expr::ite(
4207 Expr::unknown("guard".to_string()),
4208 Expr::call_extension_fn(
4209 "error".parse().unwrap(),
4210 vec![Expr::val("type error: expected bool, got long")]
4211 ),
4212 Expr::val(true)
4213 ))
4214 )
4215 }
4216
4217 #[test]
4218 fn if_semantics_both_err() {
4219 let a = Expr::unknown("guard".to_string());
4220 let b = Expr::and(Expr::val(1), Expr::val(2));
4221 let c = Expr::or(Expr::val(1), Expr::val(3));
4222
4223 let e = Expr::ite(a, b, c);
4224
4225 let es = Entities::new();
4226
4227 let exts = Extensions::none();
4228 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4229
4230 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4231 }
4232
4233 #[test]
4234 fn and_semantics1() {
4235 let e = Expr::and(
4237 Expr::binary_app(BinaryOp::Eq, Expr::val(1), Expr::val(2)),
4238 Expr::and(Expr::unknown("a".to_string()), Expr::val(false)),
4239 );
4240
4241 let es = Entities::new();
4242 let exts = Extensions::none();
4243 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4244
4245 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4246
4247 assert_eq!(r, PartialValue::Value(Value::Lit(Literal::Bool(false))));
4248 }
4249
4250 #[test]
4251 fn and_semantics2() {
4252 let e = Expr::and(
4254 Expr::binary_app(BinaryOp::Eq, Expr::val(2), Expr::val(2)),
4255 Expr::and(Expr::unknown("a".to_string()), Expr::val(false)),
4256 );
4257
4258 let es = Entities::new();
4259 let exts = Extensions::none();
4260 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4261
4262 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4263
4264 assert_eq!(
4265 r,
4266 PartialValue::Residual(Expr::and(
4267 Expr::val(true),
4268 Expr::and(Expr::unknown("a".to_string()), Expr::val(false))
4269 ))
4270 );
4271 }
4272
4273 #[test]
4274 fn and_semantics3() {
4275 let e = Expr::and(
4277 Expr::binary_app(BinaryOp::Add, Expr::val("hello"), Expr::val(2)),
4278 Expr::and(Expr::unknown("a".to_string()), Expr::val(false)),
4279 );
4280
4281 let es = Entities::new();
4282 let exts = Extensions::none();
4283 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4284
4285 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4286 }
4287
4288 #[test]
4289 fn and_semantics4() {
4290 let e = Expr::and(
4292 Expr::binary_app(BinaryOp::Eq, Expr::unknown("a".to_string()), Expr::val(2)),
4293 Expr::and(Expr::val("hello"), Expr::val("bye")),
4294 );
4295
4296 let es = Entities::new();
4297 let exts = Extensions::none();
4298 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4299
4300 assert!(eval.partial_interpret(&e, &HashMap::new()).is_ok());
4301 }
4302
4303 #[test]
4304 fn or_semantics1() {
4305 let e = Expr::or(
4308 Expr::binary_app(BinaryOp::Eq, Expr::val(2), Expr::val(2)),
4309 Expr::and(Expr::unknown("a".to_string()), Expr::val(false)),
4310 );
4311
4312 let es = Entities::new();
4313 let exts = Extensions::none();
4314 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4315
4316 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4317
4318 assert_eq!(r, PartialValue::Value(Value::Lit(Literal::Bool(true))));
4319 }
4320
4321 #[test]
4322 fn or_semantics2() {
4323 let e = Expr::or(
4325 Expr::binary_app(BinaryOp::Eq, Expr::val(1), Expr::val(2)),
4326 Expr::and(Expr::unknown("a".to_string()), Expr::val(false)),
4327 );
4328
4329 let es = Entities::new();
4330 let exts = Extensions::none();
4331 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4332
4333 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4334
4335 assert_eq!(
4336 r,
4337 PartialValue::Residual(Expr::or(
4338 Expr::val(false),
4339 Expr::and(Expr::unknown("a".to_string()), Expr::val(false))
4340 ))
4341 );
4342 }
4343
4344 #[test]
4345 fn or_semantics3() {
4346 let e = Expr::or(
4348 Expr::binary_app(BinaryOp::Add, Expr::val("hello"), Expr::val(2)),
4349 Expr::and(Expr::unknown("a".to_string()), Expr::val(false)),
4350 );
4351
4352 let es = Entities::new();
4353 let exts = Extensions::none();
4354 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4355
4356 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4357 }
4358
4359 #[test]
4360 fn or_semantics4() {
4361 let e = Expr::or(
4363 Expr::binary_app(BinaryOp::Eq, Expr::unknown("a".to_string()), Expr::val(2)),
4364 Expr::and(Expr::val("hello"), Expr::val("bye")),
4365 );
4366
4367 let es = Entities::new();
4368 let exts = Extensions::none();
4369 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4370
4371 assert!(eval.partial_interpret(&e, &HashMap::new()).is_ok());
4372 }
4373
4374 #[test]
4375 fn record_semantics_err() {
4376 let a = Expr::get_attr(
4377 Expr::record([("value".into(), Expr::unknown("test".to_string()))]),
4378 "notpresent".into(),
4379 );
4380
4381 let es = Entities::new();
4382 let exts = Extensions::none();
4383 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4384
4385 assert!(eval.partial_interpret(&a, &HashMap::new()).is_err());
4386 }
4387
4388 #[test]
4389 fn record_semantics_key_present() {
4390 let a = Expr::get_attr(
4391 Expr::record([("value".into(), Expr::unknown("test".to_string()))]),
4392 "value".into(),
4393 );
4394
4395 let es = Entities::new();
4396 let exts = Extensions::none();
4397 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4398
4399 let r = eval.partial_interpret(&a, &HashMap::new()).unwrap();
4400
4401 let expected = PartialValue::Residual(Expr::unknown("test"));
4402
4403 assert_eq!(r, expected);
4404 }
4405
4406 #[test]
4407 fn record_semantics_missing_attr() {
4408 let a = Expr::get_attr(
4409 Expr::record([
4410 ("a".into(), Expr::unknown("a")),
4411 ("b".into(), Expr::unknown("c")),
4412 ]),
4413 "c".into(),
4414 );
4415
4416 let es = Entities::new();
4417 let exts = Extensions::none();
4418 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4419
4420 assert!(eval.partial_interpret(&a, &HashMap::new()).is_err());
4421 }
4422
4423 #[test]
4424 fn record_semantics_mult_unknowns() {
4425 let a = Expr::get_attr(
4426 Expr::record([
4427 ("a".into(), Expr::unknown("a")),
4428 ("b".into(), Expr::unknown("b")),
4429 ]),
4430 "b".into(),
4431 );
4432
4433 let es = Entities::new();
4434 let exts = Extensions::none();
4435 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4436
4437 let r = eval.partial_interpret(&a, &HashMap::new()).unwrap();
4438
4439 let expected = PartialValue::Residual(Expr::unknown("b"));
4440
4441 assert_eq!(r, expected);
4442 }
4443
4444 #[test]
4445 fn parital_if_noerrors() {
4446 let guard = Expr::get_attr(Expr::unknown("a"), "field".into());
4447 let cons = Expr::val(1);
4448 let alt = Expr::val(2);
4449 let e = Expr::ite(guard.clone(), cons, alt);
4450
4451 let es = Entities::new();
4452 let exts = Extensions::none();
4453 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4454
4455 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4456
4457 let expected = Expr::ite(guard, Expr::val(1), Expr::val(2));
4458
4459 assert_eq!(r, PartialValue::Residual(expected));
4460 }
4461
4462 #[test]
4463 fn parital_if_cons_error() {
4464 let guard = Expr::get_attr(Expr::unknown("a"), "field".into());
4465 let cons = Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val(true));
4466 let alt = Expr::val(2);
4467 let e = Expr::ite(guard.clone(), cons, alt);
4468
4469 let es = Entities::new();
4470 let exts = Extensions::none();
4471 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4472
4473 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4474
4475 let expected = Expr::ite(
4476 guard,
4477 Expr::call_extension_fn(
4478 "error".parse().unwrap(),
4479 vec![Expr::val("type error: expected long, got bool")],
4480 ),
4481 Expr::val(2),
4482 );
4483
4484 assert_eq!(r, PartialValue::Residual(expected));
4485 }
4486
4487 #[test]
4488 fn parital_if_alt_error() {
4489 let guard = Expr::get_attr(Expr::unknown("a"), "field".into());
4490 let cons = Expr::val(2);
4491 let alt = Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val(true));
4492 let e = Expr::ite(guard.clone(), cons, alt);
4493
4494 let es = Entities::new();
4495 let exts = Extensions::none();
4496 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4497
4498 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4499
4500 let expected = Expr::ite(
4501 guard,
4502 Expr::val(2),
4503 Expr::call_extension_fn(
4504 "error".parse().unwrap(),
4505 vec![Expr::val("type error: expected long, got bool")],
4506 ),
4507 );
4508 assert_eq!(r, PartialValue::Residual(expected));
4509 }
4510
4511 #[test]
4512 fn parital_if_both_error() {
4513 let guard = Expr::get_attr(Expr::unknown("a"), "field".into());
4514 let cons = Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val(true));
4515 let alt = Expr::less(Expr::val("hello"), Expr::val("bye"));
4516 let e = Expr::ite(guard, cons, alt);
4517
4518 let es = Entities::new();
4519 let exts = Extensions::none();
4520 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4521
4522 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4523 }
4524
4525 #[test]
4527 fn partial_and_err_res() {
4528 let lhs = Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val("test"));
4529 let rhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4530 let e = Expr::and(lhs, rhs);
4531 let es = Entities::new();
4532 let exts = Extensions::none();
4533 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4534
4535 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4536 }
4537
4538 #[test]
4540 fn partial_or_err_res() {
4541 let lhs = Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val("test"));
4542 let rhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4543 let e = Expr::or(lhs, rhs);
4544 let es = Entities::new();
4545 let exts = Extensions::none();
4546 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4547
4548 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4549 }
4550
4551 #[test]
4553 fn partial_and_true_res() {
4554 let lhs = Expr::binary_app(BinaryOp::Eq, Expr::val(1), Expr::val(1));
4555 let rhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4556 let e = Expr::and(lhs, rhs);
4557 let es = Entities::new();
4558 let exts = Extensions::none();
4559 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4560
4561 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4562
4563 let expected = Expr::and(
4564 Expr::val(true),
4565 Expr::get_attr(Expr::unknown("test"), "field".into()),
4566 );
4567 assert_eq!(r, PartialValue::Residual(expected));
4568 }
4569
4570 #[test]
4572 fn partial_and_false_res() {
4573 let lhs = Expr::binary_app(BinaryOp::Eq, Expr::val(2), Expr::val(1));
4574 let rhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4575 let e = Expr::and(lhs, rhs);
4576 let es = Entities::new();
4577 let exts = Extensions::none();
4578 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4579
4580 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4581 assert_eq!(r, PartialValue::Value(Value::Lit(false.into())));
4582 }
4583
4584 #[test]
4586 fn partial_and_res_true() {
4587 let lhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4588 let rhs = Expr::binary_app(BinaryOp::Eq, Expr::val(2), Expr::val(2));
4589 let e = Expr::and(lhs.clone(), rhs);
4590 let es = Entities::new();
4591 let exts = Extensions::none();
4592 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4593
4594 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4595 let expected = Expr::and(lhs, Expr::val(true));
4596 assert_eq!(r, PartialValue::Residual(expected));
4597 }
4598
4599 #[test]
4600 fn partial_and_res_false() {
4601 let lhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4602 let rhs = Expr::binary_app(BinaryOp::Eq, Expr::val(2), Expr::val(1));
4603 let e = Expr::and(lhs.clone(), rhs);
4604 let es = Entities::new();
4605 let exts = Extensions::none();
4606 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4607
4608 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4609 let expected = Expr::and(lhs, Expr::val(false));
4610 assert_eq!(r, PartialValue::Residual(expected));
4611 }
4612
4613 #[test]
4615 fn partial_and_res_res() {
4616 let lhs = Expr::unknown("b");
4617 let rhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4618 let e = Expr::and(lhs, rhs);
4619 let es = Entities::new();
4620 let exts = Extensions::none();
4621 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4622
4623 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4624
4625 let expected = Expr::and(
4626 Expr::unknown("b"),
4627 Expr::get_attr(Expr::unknown("test"), "field".into()),
4628 );
4629 assert_eq!(r, PartialValue::Residual(expected));
4630 }
4631
4632 #[test]
4634 fn partial_and_res_err() {
4635 let lhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4636 let rhs = Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val("oops"));
4637 let e = Expr::and(lhs, rhs);
4638 let es = Entities::new();
4639 let exts = Extensions::none();
4640 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4641
4642 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4643
4644 let expected = Expr::and(
4645 Expr::get_attr(Expr::unknown("test"), "field".into()),
4646 Expr::call_extension_fn(
4647 "error".parse().unwrap(),
4648 vec![Expr::val("type error: expected long, got string")],
4649 ),
4650 );
4651 assert_eq!(r, PartialValue::Residual(expected));
4652 }
4653
4654 #[test]
4656 fn partial_or_true_res() {
4657 let lhs = Expr::binary_app(BinaryOp::Eq, Expr::val(1), Expr::val(1));
4658 let rhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4659 let e = Expr::or(lhs, rhs);
4660 let es = Entities::new();
4661 let exts = Extensions::none();
4662 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4663
4664 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4665 assert_eq!(r, PartialValue::Value(Value::Lit(true.into())));
4666 }
4667
4668 #[test]
4670 fn partial_or_false_res() {
4671 let lhs = Expr::binary_app(BinaryOp::Eq, Expr::val(2), Expr::val(1));
4672 let rhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4673 let e = Expr::or(lhs, rhs);
4674 let es = Entities::new();
4675 let exts = Extensions::none();
4676 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4677
4678 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4679 let expected = Expr::or(
4680 Expr::val(false),
4681 Expr::get_attr(Expr::unknown("test"), "field".into()),
4682 );
4683 assert_eq!(r, PartialValue::Residual(expected));
4684 }
4685
4686 #[test]
4688 fn partial_or_res_true() {
4689 let lhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4690 let rhs = Expr::binary_app(BinaryOp::Eq, Expr::val(2), Expr::val(2));
4691 let e = Expr::or(lhs.clone(), rhs);
4692 let es = Entities::new();
4693 let exts = Extensions::none();
4694 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4695
4696 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4697 let expected = Expr::or(lhs, Expr::val(true));
4698 assert_eq!(r, PartialValue::Residual(expected));
4699 }
4700
4701 #[test]
4702 fn partial_or_res_false() {
4703 let lhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4704 let rhs = Expr::binary_app(BinaryOp::Eq, Expr::val(2), Expr::val(1));
4705 let e = Expr::or(lhs.clone(), rhs);
4706 let es = Entities::new();
4707 let exts = Extensions::none();
4708 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4709
4710 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4711 let expected = Expr::or(lhs, Expr::val(false));
4712 assert_eq!(r, PartialValue::Residual(expected));
4713 }
4714
4715 #[test]
4717 fn partial_or_res_res() {
4718 let lhs = Expr::unknown("b");
4719 let rhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4720 let e = Expr::or(lhs, rhs);
4721 let es = Entities::new();
4722 let exts = Extensions::none();
4723 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4724
4725 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4726
4727 let expected = Expr::or(
4728 Expr::unknown("b"),
4729 Expr::get_attr(Expr::unknown("test"), "field".into()),
4730 );
4731 assert_eq!(r, PartialValue::Residual(expected));
4732 }
4733
4734 #[test]
4736 fn partial_or_res_err() {
4737 let lhs = Expr::get_attr(Expr::unknown("test"), "field".into());
4738 let rhs = Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val("oops"));
4739 let e = Expr::or(lhs, rhs);
4740 let es = Entities::new();
4741 let exts = Extensions::none();
4742 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4743
4744 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4745
4746 let expected = Expr::or(
4747 Expr::get_attr(Expr::unknown("test"), "field".into()),
4748 Expr::call_extension_fn(
4749 "error".parse().unwrap(),
4750 vec![Expr::val("type error: expected long, got string")],
4751 ),
4752 );
4753 assert_eq!(r, PartialValue::Residual(expected));
4754 }
4755
4756 #[test]
4757 fn partial_unop() {
4758 let es = Entities::new();
4759 let exts = Extensions::none();
4760 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4761
4762 let e = Expr::unary_app(UnaryOp::Neg, Expr::unknown("a"));
4763 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4764 assert_eq!(r, PartialValue::Residual(e));
4765
4766 let e = Expr::unary_app(UnaryOp::Not, Expr::unknown("a"));
4767 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4768 assert_eq!(r, PartialValue::Residual(e));
4769 }
4770
4771 #[test]
4772 fn partial_binop() {
4773 let es = Entities::new();
4774 let exts = Extensions::none();
4775 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4776
4777 let binops = [
4778 BinaryOp::Add,
4779 BinaryOp::Contains,
4780 BinaryOp::ContainsAll,
4781 BinaryOp::ContainsAny,
4782 BinaryOp::Eq,
4783 BinaryOp::In,
4784 BinaryOp::Less,
4785 BinaryOp::LessEq,
4786 BinaryOp::Sub,
4787 ];
4788
4789 for binop in binops {
4790 let e = Expr::binary_app(
4792 binop,
4793 Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val(2)),
4794 Expr::unknown("a"),
4795 );
4796 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4797 let expected = Expr::binary_app(binop, Expr::val(3), Expr::unknown("a"));
4798 assert_eq!(r, PartialValue::Residual(expected));
4799 let e = Expr::binary_app(
4801 binop,
4802 Expr::binary_app(BinaryOp::Add, Expr::val("hello"), Expr::val(2)),
4803 Expr::unknown("a"),
4804 );
4805 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4806 let e = Expr::binary_app(
4808 binop,
4809 Expr::unknown("a"),
4810 Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val(2)),
4811 );
4812 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4813 let expected = Expr::binary_app(binop, Expr::unknown("a"), Expr::val(3));
4814 assert_eq!(r, PartialValue::Residual(expected));
4815 let e = Expr::binary_app(
4817 binop,
4818 Expr::unknown("a"),
4819 Expr::binary_app(BinaryOp::Add, Expr::val("hello"), Expr::val(2)),
4820 );
4821 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4822 let e = Expr::binary_app(binop, Expr::unknown("a"), Expr::unknown("b"));
4824 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4825 let expected = Expr::binary_app(binop, Expr::unknown("a"), Expr::unknown("b"));
4826 assert_eq!(r, PartialValue::Residual(expected));
4827 }
4828 }
4829
4830 #[test]
4831 fn partial_mul() {
4832 let es = Entities::new();
4833 let exts = Extensions::none();
4834 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4835
4836 let e = Expr::mul(Expr::unknown("a"), 32);
4837 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4838 assert_eq!(r, PartialValue::Residual(e));
4839 }
4840
4841 #[test]
4842 fn partial_ext_constructors() {
4843 let es = Entities::new();
4844 let exts = Extensions::all_available();
4845 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4846
4847 let e = Expr::call_extension_fn("ip".parse().unwrap(), vec![Expr::unknown("a")]);
4848
4849 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4850
4851 assert_eq!(r, PartialValue::Residual(e));
4852 }
4853
4854 #[test]
4855 fn partial_ext_unfold() {
4856 let es = Entities::new();
4857 let exts = Extensions::all_available();
4858 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4859
4860 let a = Expr::call_extension_fn("ip".parse().unwrap(), vec![Expr::val("127.0.0.1")]);
4861 let b = Expr::unknown("a");
4862 let e = Expr::call_extension_fn("isInRange".parse().unwrap(), vec![a, b]);
4863
4864 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4865
4866 assert_eq!(r, PartialValue::Residual(e));
4867
4868 let b = Expr::call_extension_fn("ip".parse().unwrap(), vec![Expr::val("127.0.0.1")]);
4869 let a = Expr::unknown("a");
4870 let e = Expr::call_extension_fn("isInRange".parse().unwrap(), vec![a, b]);
4871
4872 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4873
4874 assert_eq!(r, PartialValue::Residual(e));
4875
4876 let b = Expr::call_extension_fn("ip".parse().unwrap(), vec![Expr::val("invalid")]);
4877 let a = Expr::unknown("a");
4878 let e = Expr::call_extension_fn("isInRange".parse().unwrap(), vec![a, b]);
4879
4880 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4881 }
4882
4883 #[test]
4884 fn partial_like() {
4885 let es = Entities::new();
4886 let exts = Extensions::none();
4887 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4888
4889 let e = Expr::like(Expr::unknown("a"), []);
4890
4891 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4892
4893 assert_eq!(r, PartialValue::Residual(e));
4894 }
4895
4896 #[test]
4897 fn partial_hasattr() {
4898 let es = Entities::new();
4899 let exts = Extensions::none();
4900 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4901
4902 let e = Expr::has_attr(Expr::unknown("a"), "test".into());
4903
4904 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4905
4906 assert_eq!(r, PartialValue::Residual(e));
4907 }
4908
4909 #[test]
4910 fn partial_set() {
4911 let es = Entities::new();
4912 let exts = Extensions::none();
4913 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4914
4915 let e = Expr::set([Expr::val(1), Expr::unknown("a"), Expr::val(2)]);
4916 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4917 assert_eq!(r, PartialValue::Residual(e));
4918
4919 let e = Expr::set([
4920 Expr::val(1),
4921 Expr::unknown("a"),
4922 Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val(2)),
4923 ]);
4924 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4925 assert_eq!(
4926 r,
4927 PartialValue::Residual(Expr::set([Expr::val(1), Expr::unknown("a"), Expr::val(3)]))
4928 );
4929
4930 let e = Expr::set([
4931 Expr::val(1),
4932 Expr::unknown("a"),
4933 Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val("a")),
4934 ]);
4935 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4936 }
4937
4938 #[test]
4939 fn partial_record() {
4940 let es = Entities::new();
4941 let exts = Extensions::none();
4942 let eval = Evaluator::new(&empty_request(), &es, &exts).unwrap();
4943
4944 let e = Expr::record([
4945 ("a".into(), Expr::val(1)),
4946 ("b".into(), Expr::unknown("a")),
4947 ("c".into(), Expr::val(2)),
4948 ]);
4949 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4950 assert_eq!(r, PartialValue::Residual(e));
4951
4952 let e = Expr::record([("a".into(), Expr::val(1)), ("a".into(), Expr::unknown("a"))]);
4953 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4954 assert_eq!(
4955 r,
4956 PartialValue::Residual(Expr::record([
4957 ("a".into(), Expr::val(1)),
4958 ("a".into(), Expr::unknown("a"))
4959 ]))
4960 );
4961
4962 let e = Expr::record([("a".into(), Expr::unknown("a")), ("a".into(), Expr::val(1))]);
4963 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4964 assert_eq!(
4965 r,
4966 PartialValue::Residual(Expr::record([
4967 ("a".into(), Expr::unknown("a")),
4968 ("a".into(), Expr::val(1))
4969 ]))
4970 );
4971
4972 let e = Expr::record([
4973 ("a".into(), Expr::val(1)),
4974 ("b".into(), Expr::unknown("a")),
4975 (
4976 "c".into(),
4977 Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val(2)),
4978 ),
4979 ]);
4980 let r = eval.partial_interpret(&e, &HashMap::new()).unwrap();
4981 assert_eq!(
4982 r,
4983 PartialValue::Residual(Expr::record([
4984 ("a".into(), Expr::val(1)),
4985 ("b".into(), Expr::unknown("a")),
4986 ("c".into(), Expr::val(3))
4987 ]))
4988 );
4989
4990 let e = Expr::record([
4991 ("a".into(), Expr::val(1)),
4992 ("b".into(), Expr::unknown("a")),
4993 (
4994 "c".into(),
4995 Expr::binary_app(BinaryOp::Add, Expr::val(1), Expr::val("hello")),
4996 ),
4997 ]);
4998 assert!(eval.partial_interpret(&e, &HashMap::new()).is_err());
4999 }
5000
5001 #[test]
5002 fn small() {
5003 let e = parser::parse_expr("[[1]]").unwrap();
5004 let re = RestrictedExpr::new(e).unwrap();
5005 let exts = Extensions::none();
5006 let eval = RestrictedEvaluator::new(&exts);
5007 let r = eval.partial_interpret(re.as_borrowed()).unwrap();
5008 match r {
5009 PartialValue::Value(Value::Set(s)) => assert_eq!(s.len(), 1),
5010 PartialValue::Value(_) => panic!("wrong value"),
5011 PartialValue::Residual(_) => panic!("Wrong residual"),
5012 }
5013 }
5014
5015 #[test]
5016 fn unprojectable_residual() {
5017 let q = basic_request();
5018 let entities = basic_entities();
5019 let exts = Extensions::none();
5020 let eval = Evaluator::new(&q, &entities, &exts).unwrap();
5021
5022 let e = Expr::get_attr(
5023 Expr::record([
5024 (
5025 "a".into(),
5026 Expr::binary_app(BinaryOp::Add, Expr::unknown("a"), Expr::val(3)),
5027 ),
5028 ("b".into(), Expr::val(83)),
5029 ]),
5030 "b".into(),
5031 );
5032 let r = eval.partial_eval_expr(&e).unwrap();
5033 assert_eq!(r, Either::Right(e));
5034
5035 let e = Expr::get_attr(
5036 Expr::record([(
5037 "a".into(),
5038 Expr::binary_app(BinaryOp::Add, Expr::unknown("a"), Expr::val(3)),
5039 )]),
5040 "b".into(),
5041 );
5042 assert!(eval.partial_eval_expr(&e).is_err());
5043 }
5044}