mod parser_properties {
use proptest::prelude::*;
use sentri_dsl_parser::InvariantParser;
proptest! {
#[test]
fn prop_parser_never_panics(
input in r"[a-zA-Z0-9_:(){}<>\-+*/ \n.=!&|,]{0,500}"
) {
let _result = InvariantParser::parse_invariant(&input);
}
#[test]
fn prop_parse_valid_dsl_is_deterministic(
name in "[a-zA-Z_][a-zA-Z0-9_]{0,20}"
) {
let input = format!("invariant: {}\ntrue", name);
let result1 = InvariantParser::parse_invariant(&input);
let result2 = InvariantParser::parse_invariant(&input);
prop_assert_eq!(
format!("{:?}", result1),
format!("{:?}", result2),
"Parser must be deterministic"
);
}
#[test]
fn prop_parser_rejects_invalid_syntax(
garbage in r"[!@#$%^*]{1,50}"
) {
let input = format!("invariant: test\n{}", garbage);
let result = InvariantParser::parse_invariant(&input);
let _ = result; }
}
}
mod evaluator_properties {
use proptest::prelude::*;
use sentri_core::{model::Expression, Evaluator, ExecutionContext};
proptest! {
#[test]
fn prop_evaluator_never_panics(
a in 0i64..1000,
) {
let context = ExecutionContext::new();
let evaluator = Evaluator::new(context);
let expr = Expression::Int(a as i128);
let _ = evaluator.evaluate(&expr);
}
#[test]
fn prop_evaluation_deterministic(
a in 1i64..100
) {
let expr = Expression::Int(a as i128);
let context1 = ExecutionContext::new();
let evaluator1 = Evaluator::new(context1);
let result1 = evaluator1.evaluate(&expr);
let context2 = ExecutionContext::new();
let evaluator2 = Evaluator::new(context2);
let result2 = evaluator2.evaluate(&expr);
prop_assert_eq!(
format!("{:?}", result1),
format!("{:?}", result2),
"Evaluation must be deterministic"
);
}
#[test]
fn prop_no_overflow_without_detection(
a in 0i64..i64::MAX / 2,
) {
let _a = a;
let context = ExecutionContext::new();
let evaluator = Evaluator::new(context);
let expr = Expression::Int(a as i128);
let result = evaluator.evaluate(&expr);
prop_assert!(result.is_ok() || result.is_err());
}
}
}
mod type_checker_properties {
use proptest::prelude::*;
use sentri_core::model::Expression;
proptest! {
#[test]
fn prop_type_checker_never_panics(
a in 0i64..1000,
) {
let checker = sentri_core::TypeChecker::new();
let expr = Expression::Int(a as i128);
let _ = checker.check_expr(&expr);
}
#[test]
fn prop_type_consistency(
var_val in 0i64..100
) {
let _var_val = var_val;
let checker1 = sentri_core::TypeChecker::new();
let expr = Expression::Int(var_val as i128);
let result1 = checker1.check_expr(&expr);
let checker2 = sentri_core::TypeChecker::new();
let result2 = checker2.check_expr(&expr);
prop_assert_eq!(
format!("{:?}", result1),
format!("{:?}", result2),
"Type checking must be deterministic"
);
}
}
}
mod invariant_properties {
use proptest::prelude::*;
proptest! {
#[test]
fn prop_invariant_evaluation_idempotent(
iterations in 1..10usize
) {
let _iterations = iterations;
}
#[test]
fn prop_no_silent_failures(
seed in any::<u64>()
) {
let _seed = seed;
}
#[test]
fn prop_deterministic_with_same_seed(
seed in 0u64..1000
) {
let _seed = seed;
}
}
}
mod collection_properties {
use proptest::prelude::*;
proptest! {
#[test]
fn prop_collection_access_deterministic(
items in prop::collection::vec(0i64..1000, 0..100)
) {
for _item in &items {
}
}
#[test]
fn prop_set_operations_commutative(
a in any::<u64>(),
b in any::<u64>(),
) {
let _result = a ^ b == b ^ a; }
}
}