use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn test_span_merge(start1 in 0usize..1000, end1 in 0usize..1000,
start2 in 0usize..1000, end2 in 0usize..1000) {
let span1 = Span::new(start1, end1);
let span2 = Span::new(start2, end2);
let merged = span1.merge(span2);
prop_assert!(merged.start <= span1.start);
prop_assert!(merged.start <= span2.start);
prop_assert!(merged.end >= span1.end);
prop_assert!(merged.end >= span2.end);
}
}
#[test]
fn test_ast_size() {
let expr_size = std::mem::size_of::<Expr>();
let kind_size = std::mem::size_of::<ExprKind>();
assert!(expr_size <= 400, "Expr too large: {expr_size} bytes");
assert!(kind_size <= 280, "ExprKind too large: {kind_size} bytes");
}
#[test]
fn test_span_creation() {
let span = Span::new(10, 20);
assert_eq!(span.start, 10);
assert_eq!(span.end, 20);
}
#[test]
fn test_span_merge_simple() {
let span1 = Span::new(5, 10);
let span2 = Span::new(8, 15);
let merged = span1.merge(span2);
assert_eq!(merged.start, 5);
assert_eq!(merged.end, 15);
}
#[test]
fn test_span_merge_disjoint() {
let span1 = Span::new(0, 5);
let span2 = Span::new(10, 15);
let merged = span1.merge(span2);
assert_eq!(merged.start, 0);
assert_eq!(merged.end, 15);
}
#[test]
fn test_expr_creation() {
let span = Span::new(0, 10);
let expr = Expr::new(ExprKind::Literal(Literal::Integer(42, None)), span);
assert_eq!(expr.span.start, 0);
assert_eq!(expr.span.end, 10);
match expr.kind {
ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 42),
_ => panic!("Wrong expression kind"),
}
}
#[test]
fn test_literal_variants() {
let literals = vec![
Literal::Integer(42, None),
#[allow(clippy::approx_constant)]
Literal::Float(3.15), Literal::String("hello".to_string()),
Literal::Bool(true),
Literal::Unit,
];
for lit in literals {
let expr = Expr::new(ExprKind::Literal(lit.clone()), Span::new(0, 0));
match expr.kind {
ExprKind::Literal(l) => assert_eq!(l, lit),
_ => panic!("Expected literal"),
}
}
}
#[test]
fn test_binary_op_display() {
assert_eq!(BinaryOp::Add.to_string(), "+");
assert_eq!(BinaryOp::Subtract.to_string(), "-");
assert_eq!(BinaryOp::Multiply.to_string(), "*");
assert_eq!(BinaryOp::Divide.to_string(), "/");
assert_eq!(BinaryOp::Modulo.to_string(), "%");
assert_eq!(BinaryOp::Power.to_string(), "**");
assert_eq!(BinaryOp::Equal.to_string(), "==");
assert_eq!(BinaryOp::NotEqual.to_string(), "!=");
assert_eq!(BinaryOp::Less.to_string(), "<");
assert_eq!(BinaryOp::LessEqual.to_string(), "<=");
assert_eq!(BinaryOp::Greater.to_string(), ">");
assert_eq!(BinaryOp::GreaterEqual.to_string(), ">=");
assert_eq!(BinaryOp::And.to_string(), "&&");
assert_eq!(BinaryOp::Or.to_string(), "||");
assert_eq!(BinaryOp::BitwiseAnd.to_string(), "&");
assert_eq!(BinaryOp::BitwiseOr.to_string(), "|");
assert_eq!(BinaryOp::BitwiseXor.to_string(), "^");
assert_eq!(BinaryOp::LeftShift.to_string(), "<<");
}
#[test]
fn test_unary_op_display() {
assert_eq!(UnaryOp::Not.to_string(), "!");
assert_eq!(UnaryOp::Negate.to_string(), "-");
assert_eq!(UnaryOp::BitwiseNot.to_string(), "~");
assert_eq!(UnaryOp::Reference.to_string(), "&");
}
#[test]
fn test_binary_expression() {
let left = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::new(0, 1),
));
let right = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Span::new(4, 5),
));
let expr = Expr::new(
ExprKind::Binary {
left,
op: BinaryOp::Add,
right,
},
Span::new(0, 5),
);
match expr.kind {
ExprKind::Binary {
left: l,
op,
right: r,
} => {
assert_eq!(op, BinaryOp::Add);
match l.kind {
ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 1),
_ => panic!("Wrong left operand"),
}
match r.kind {
ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 2),
_ => panic!("Wrong right operand"),
}
}
_ => panic!("Expected binary expression"),
}
}
#[test]
fn test_unary_expression() {
let operand = Box::new(Expr::new(
ExprKind::Literal(Literal::Bool(true)),
Span::new(1, 5),
));
let expr = Expr::new(
ExprKind::Unary {
op: UnaryOp::Not,
operand,
},
Span::new(0, 5),
);
match expr.kind {
ExprKind::Unary { op, operand } => {
assert_eq!(op, UnaryOp::Not);
match operand.kind {
ExprKind::Literal(Literal::Bool(b)) => assert!(b),
_ => panic!("Wrong operand"),
}
}
_ => panic!("Expected unary expression"),
}
}
#[test]
fn test_if_expression() {
let condition = Box::new(Expr::new(
ExprKind::Literal(Literal::Bool(true)),
Span::new(3, 7),
));
let then_branch = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::new(10, 11),
));
let else_branch = Some(Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Span::new(17, 18),
)));
let expr = Expr::new(
ExprKind::If {
condition,
then_branch,
else_branch,
},
Span::new(0, 18),
);
match expr.kind {
ExprKind::If {
condition: c,
then_branch: t,
else_branch: e,
} => {
match c.kind {
ExprKind::Literal(Literal::Bool(b)) => assert!(b),
_ => panic!("Wrong condition"),
}
match t.kind {
ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 1),
_ => panic!("Wrong then branch"),
}
assert!(e.is_some());
if let Some(else_expr) = e {
match else_expr.kind {
ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 2),
_ => panic!("Wrong else branch"),
}
}
}
_ => panic!("Expected if expression"),
}
}
#[test]
fn test_let_expression() {
let value = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Span::new(8, 10),
));
let body = Box::new(Expr::new(
ExprKind::Identifier("x".to_string()),
Span::new(14, 15),
));
let expr = Expr::new(
ExprKind::Let {
name: "x".to_string(),
type_annotation: None,
value,
body,
is_mutable: false,
else_block: None,
},
Span::new(0, 15),
);
match expr.kind {
ExprKind::Let {
name,
value: v,
body: b,
..
} => {
assert_eq!(name, "x");
match v.kind {
ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 42),
_ => panic!("Wrong value"),
}
match b.kind {
ExprKind::Identifier(id) => assert_eq!(id, "x"),
_ => panic!("Wrong body"),
}
}
_ => panic!("Expected let expression"),
}
}
#[test]
fn test_function_expression() {
let params = vec![Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::new(10, 13),
},
span: Span::new(8, 13),
is_mutable: false,
default_value: None,
}];
let body = Box::new(Expr::new(
ExprKind::Identifier("x".to_string()),
Span::new(20, 21),
));
let expr = Expr::new(
ExprKind::Function {
name: "identity".to_string(),
type_params: vec![],
params,
return_type: Some(Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::new(16, 19),
}),
body,
is_async: false,
is_pub: false,
},
Span::new(0, 22),
);
match expr.kind {
ExprKind::Function {
name,
params: p,
return_type,
body: b,
..
} => {
assert_eq!(name, "identity");
assert_eq!(p.len(), 1);
assert_eq!(p[0].name(), "x");
assert!(return_type.is_some());
match b.kind {
ExprKind::Identifier(id) => assert_eq!(id, "x"),
_ => panic!("Wrong body"),
}
}
_ => panic!("Expected function expression"),
}
}
#[test]
fn test_call_expression() {
let func = Box::new(Expr::new(
ExprKind::Identifier("add".to_string()),
Span::new(0, 3),
));
let args = vec![
Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::new(4, 5),
),
Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Span::new(7, 8),
),
];
let expr = Expr::new(ExprKind::Call { func, args }, Span::new(0, 9));
match expr.kind {
ExprKind::Call { func: f, args: a } => {
match f.kind {
ExprKind::Identifier(name) => assert_eq!(name, "add"),
_ => panic!("Wrong function"),
}
assert_eq!(a.len(), 2);
}
_ => panic!("Expected call expression"),
}
}
#[test]
fn test_block_expression() {
let exprs = vec![
Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::new(2, 3),
),
Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Span::new(5, 6),
),
];
let expr = Expr::new(ExprKind::Block(exprs), Span::new(0, 8));
match expr.kind {
ExprKind::Block(block) => {
assert_eq!(block.len(), 2);
}
_ => panic!("Expected block expression"),
}
}
#[test]
fn test_list_expression() {
let items = vec![
Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::new(1, 2),
),
Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Span::new(4, 5),
),
Expr::new(
ExprKind::Literal(Literal::Integer(3, None)),
Span::new(7, 8),
),
];
let expr = Expr::new(ExprKind::List(items), Span::new(0, 9));
match expr.kind {
ExprKind::List(list) => {
assert_eq!(list.len(), 3);
}
_ => panic!("Expected list expression"),
}
}
#[test]
fn test_for_expression() {
let iter = Box::new(Expr::new(
ExprKind::Range {
start: Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(0, None)),
Span::new(10, 11),
)),
end: Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(10, None)),
Span::new(13, 15),
)),
inclusive: false,
},
Span::new(10, 15),
));
let body = Box::new(Expr::new(
ExprKind::Identifier("i".to_string()),
Span::new(20, 21),
));
let expr = Expr::new(
ExprKind::For {
label: None,
var: "i".to_string(),
pattern: None,
iter,
body,
},
Span::new(0, 22),
);
match expr.kind {
ExprKind::For {
label: None,
var,
iter: it,
body: b,
..
} => {
assert_eq!(var, "i");
match it.kind {
ExprKind::Range { .. } => {}
_ => panic!("Wrong iterator"),
}
match b.kind {
ExprKind::Identifier(id) => assert_eq!(id, "i"),
_ => panic!("Wrong body"),
}
}
_ => panic!("Expected for expression"),
}
}
#[test]
fn test_range_expression() {
let start = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::new(0, 1),
));
let end = Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(10, None)),
Span::new(3, 5),
));
let expr = Expr::new(
ExprKind::Range {
start,
end,
inclusive: false,
},
Span::new(0, 5),
);
match expr.kind {
ExprKind::Range {
start: s,
end: e,
inclusive,
} => {
assert!(!inclusive);
match s.kind {
ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 1),
_ => panic!("Wrong start"),
}
match e.kind {
ExprKind::Literal(Literal::Integer(n, None)) => assert_eq!(n, 10),
_ => panic!("Wrong end"),
}
}
_ => panic!("Expected range expression"),
}
}
#[test]
fn test_pipeline_expression() {
let expr_start = Box::new(Expr::new(
ExprKind::List(vec![
Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::new(1, 2),
),
Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Span::new(4, 5),
),
]),
Span::new(0, 6),
));
let stages = vec![PipelineStage {
op: Box::new(Expr::new(
ExprKind::Identifier("filter".to_string()),
Span::new(10, 16),
)),
span: Span::new(10, 16),
}];
let expr = Expr::new(
ExprKind::Pipeline {
expr: expr_start,
stages,
},
Span::new(0, 16),
);
match expr.kind {
ExprKind::Pipeline { expr: e, stages: s } => {
assert_eq!(s.len(), 1);
match e.kind {
ExprKind::List(list) => assert_eq!(list.len(), 2),
_ => panic!("Wrong pipeline start"),
}
}
_ => panic!("Expected pipeline expression"),
}
}
#[test]
fn test_match_expression() {
let expr_to_match = Box::new(Expr::new(
ExprKind::Identifier("x".to_string()),
Span::new(6, 7),
));
let arms = vec![
MatchArm {
pattern: Pattern::Literal(Literal::Integer(1, None)),
guard: None,
body: Box::new(Expr::new(
ExprKind::Literal(Literal::String("one".to_string())),
Span::new(15, 20),
)),
span: Span::new(10, 20),
},
MatchArm {
pattern: Pattern::Wildcard,
guard: None,
body: Box::new(Expr::new(
ExprKind::Literal(Literal::String("other".to_string())),
Span::new(28, 35),
)),
span: Span::new(25, 35),
},
];
let expr = Expr::new(
ExprKind::Match {
expr: expr_to_match,
arms,
},
Span::new(0, 36),
);
match expr.kind {
ExprKind::Match { expr: e, arms: a } => {
assert_eq!(a.len(), 2);
match e.kind {
ExprKind::Identifier(id) => assert_eq!(id, "x"),
_ => panic!("Wrong match expression"),
}
}
_ => panic!("Expected match expression"),
}
}
#[test]
fn test_pattern_variants() {
let patterns = vec![
Pattern::Wildcard,
Pattern::Literal(Literal::Integer(42, None)),
Pattern::Identifier("x".to_string()),
Pattern::Tuple(vec![
Pattern::Literal(Literal::Integer(1, None)),
Pattern::Identifier("x".to_string()),
]),
Pattern::List(vec![
Pattern::Literal(Literal::Integer(1, None)),
Pattern::Literal(Literal::Integer(2, None)),
]),
Pattern::Struct {
name: "Point".to_string(),
fields: vec![StructPatternField {
name: "x".to_string(),
pattern: Some(Pattern::Identifier("x".to_string())),
}],
has_rest: false,
},
Pattern::Range {
start: Box::new(Pattern::Literal(Literal::Integer(1, None))),
end: Box::new(Pattern::Literal(Literal::Integer(10, None))),
inclusive: true,
},
Pattern::Or(vec![
Pattern::Literal(Literal::Integer(1, None)),
Pattern::Literal(Literal::Integer(2, None)),
]),
Pattern::Rest,
];
for pattern in patterns {
match pattern {
Pattern::Tuple(list) | Pattern::List(list) => assert!(!list.is_empty()),
Pattern::Struct { fields, .. } => assert!(!fields.is_empty()),
Pattern::Or(patterns) => assert!(!patterns.is_empty()),
Pattern::Range { .. }
| Pattern::Wildcard
| Pattern::Literal(_)
| Pattern::Identifier(_)
| Pattern::Rest
| Pattern::RestNamed(_)
| Pattern::Ok(_)
| Pattern::Err(_)
| Pattern::Some(_)
| Pattern::None
| Pattern::QualifiedName(_)
| Pattern::AtBinding { .. }
| Pattern::WithDefault { .. }
| Pattern::Mut(_)
| Pattern::TupleVariant { .. } => {} }
}
}
#[test]
fn test_type_kinds() {
let types = vec![
Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::new(0, 3),
},
Type {
kind: TypeKind::Optional(Box::new(Type {
kind: TypeKind::Named("String".to_string()),
span: Span::new(0, 6),
})),
span: Span::new(0, 7),
},
Type {
kind: TypeKind::List(Box::new(Type {
kind: TypeKind::Named("f64".to_string()),
span: Span::new(1, 4),
})),
span: Span::new(0, 5),
},
Type {
kind: TypeKind::Function {
params: vec![Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::new(0, 3),
}],
ret: Box::new(Type {
kind: TypeKind::Named("String".to_string()),
span: Span::new(7, 13),
}),
},
span: Span::new(0, 13),
},
];
for ty in types {
match ty.kind {
TypeKind::Named(name) => assert!(!name.is_empty()),
TypeKind::Generic { base, params } => {
assert!(!base.is_empty());
assert!(!params.is_empty());
}
TypeKind::Optional(_) | TypeKind::List(_) | TypeKind::Series { .. } => {}
TypeKind::Function { params, .. } => assert!(!params.is_empty()),
TypeKind::DataFrame { columns } => assert!(!columns.is_empty()),
TypeKind::Refined { .. } => {} TypeKind::Tuple(ref types) => assert!(!types.is_empty()),
TypeKind::Reference {
is_mut: _,
lifetime: _,
ref inner,
} => {
if let TypeKind::Named(ref name) = inner.kind {
assert!(!name.is_empty());
}
}
TypeKind::Array { elem_type: _, size } => {
assert!(size > 0);
}
}
}
}
#[test]
fn test_param_creation() {
let param = Param {
pattern: Pattern::Identifier("count".to_string()),
ty: Type {
kind: TypeKind::Named("usize".to_string()),
span: Span::new(6, 11),
},
span: Span::new(0, 11),
is_mutable: false,
default_value: None,
};
assert_eq!(param.name(), "count");
match param.ty.kind {
TypeKind::Named(name) => assert_eq!(name, "usize"),
_ => panic!("Wrong type kind"),
}
}
#[test]
fn test_string_interpolation_parts() {
let parts = vec![
StringPart::Text("Hello, ".to_string()),
StringPart::Expr(Box::new(Expr::new(
ExprKind::Identifier("name".to_string()),
Span::new(8, 12),
))),
StringPart::Text("!".to_string()),
];
let expr = Expr::new(ExprKind::StringInterpolation { parts }, Span::new(0, 13));
if let ExprKind::StringInterpolation { parts } = expr.kind {
assert_eq!(parts.len(), 3);
match &parts[0] {
StringPart::Text(s) => assert_eq!(s, "Hello, "),
_ => panic!("Expected static part"),
}
match &parts[1] {
StringPart::Expr(e) => {
if let ExprKind::Identifier(id) = &e.kind {
assert_eq!(id, "name");
}
}
_ => panic!("Expected dynamic part"),
}
}
}
#[test]
fn test_async_function_creation() {
let func = Expr::new(
ExprKind::Function {
name: "fetch_data".to_string(),
type_params: vec![],
params: vec![],
return_type: None,
body: Box::new(Expr::new(
ExprKind::Await {
expr: Box::new(Expr::new(
ExprKind::Identifier("api_call".to_string()),
Span::new(0, 8),
)),
},
Span::new(0, 14),
)),
is_async: true,
is_pub: false,
},
Span::new(0, 30),
);
if let ExprKind::Function { is_async, body, .. } = func.kind {
assert!(is_async);
if let ExprKind::Await { .. } = body.kind {
} else {
panic!("Expected await in async function");
}
}
}
#[test]
fn test_try_catch_finally() {
let try_catch = Expr::new(
ExprKind::TryCatch {
try_block: Box::new(Expr::new(
ExprKind::Identifier("risky_operation".to_string()),
Span::new(4, 19),
)),
catch_clauses: vec![CatchClause {
pattern: Pattern::Identifier("e".to_string()),
body: Box::new(Expr::new(
ExprKind::Identifier("handle_error".to_string()),
Span::new(25, 37),
)),
}],
finally_block: Some(Box::new(Expr::new(
ExprKind::Identifier("cleanup".to_string()),
Span::new(45, 52),
))),
},
Span::new(0, 52),
);
if let ExprKind::TryCatch {
catch_clauses,
finally_block,
..
} = try_catch.kind
{
assert_eq!(catch_clauses.len(), 1);
assert!(finally_block.is_some());
}
}
#[test]
fn test_result_option_types() {
let ok_val = Expr::new(
ExprKind::Ok {
value: Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Span::new(3, 5),
)),
},
Span::new(0, 6),
);
let err_val = Expr::new(
ExprKind::Err {
error: Box::new(Expr::new(
ExprKind::Literal(Literal::String("error".to_string())),
Span::new(4, 11),
)),
},
Span::new(0, 12),
);
let some_val = Expr::new(
ExprKind::Some {
value: Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::new(5, 6),
)),
},
Span::new(0, 7),
);
let none_val = Expr::new(ExprKind::None, Span::new(0, 4));
assert!(matches!(ok_val.kind, ExprKind::Ok { .. }));
assert!(matches!(err_val.kind, ExprKind::Err { .. }));
assert!(matches!(some_val.kind, ExprKind::Some { .. }));
assert!(matches!(none_val.kind, ExprKind::None));
}
#[test]
fn test_destructuring_patterns() {
let tuple_pattern = Pattern::Tuple(vec![
Pattern::Identifier("x".to_string()),
Pattern::Identifier("y".to_string()),
Pattern::Rest,
]);
let struct_pattern = Pattern::Struct {
name: "User".to_string(),
fields: vec![
StructPatternField {
name: "name".to_string(),
pattern: Some(Pattern::Identifier("n".to_string())),
},
StructPatternField {
name: "age".to_string(),
pattern: None,
},
],
has_rest: true,
};
if let Pattern::Tuple(elements) = tuple_pattern {
assert_eq!(elements.len(), 3);
assert!(matches!(elements[2], Pattern::Rest));
}
if let Pattern::Struct {
fields, has_rest, ..
} = struct_pattern
{
assert_eq!(fields.len(), 2);
assert!(has_rest);
}
}
#[test]
fn test_qualified_names() {
let qualified = Expr::new(
ExprKind::QualifiedName {
module: "std".to_string(),
name: "println".to_string(),
},
Span::new(0, 11),
);
if let ExprKind::QualifiedName { module, name } = qualified.kind {
assert_eq!(module, "std");
assert_eq!(name, "println");
}
}
#[test]
fn test_decorator_attributes() {
let decorated = Expr::with_attributes(
ExprKind::Function {
name: "test_func".to_string(),
type_params: vec![],
params: vec![],
return_type: None,
body: Box::new(Expr::new(ExprKind::Literal(Literal::Unit), Span::new(0, 0))),
is_async: false,
is_pub: false,
},
Span::new(0, 20),
vec![
Attribute {
name: "test".to_string(),
args: vec![],
span: Span::new(0, 5),
},
Attribute {
name: "bench".to_string(),
args: vec![],
span: Span::new(0, 6),
},
],
);
assert_eq!(decorated.attributes.len(), 2);
assert_eq!(decorated.attributes[0].name, "test");
assert_eq!(decorated.attributes[1].name, "bench");
}
#[test]
fn test_dataframe_operations() {
let df = Expr::new(
ExprKind::DataFrame {
columns: vec![
DataFrameColumn {
name: "name".to_string(),
values: vec![
Expr::new(
ExprKind::Literal(Literal::String("Alice".to_string())),
Span::new(0, 7),
),
Expr::new(
ExprKind::Literal(Literal::String("Bob".to_string())),
Span::new(8, 13),
),
],
},
DataFrameColumn {
name: "age".to_string(),
values: vec![
Expr::new(
ExprKind::Literal(Literal::Integer(25, None)),
Span::new(14, 16),
),
Expr::new(
ExprKind::Literal(Literal::Integer(30, None)),
Span::new(17, 19),
),
],
},
],
},
Span::new(0, 50),
);
if let ExprKind::DataFrame { columns } = df.kind {
assert_eq!(columns.len(), 2);
assert_eq!(columns[0].name, "name");
assert_eq!(columns[0].values.len(), 2);
assert_eq!(columns[1].name, "age");
assert_eq!(columns[1].values.len(), 2);
}
}
#[test]
fn test_type_cast_operations() {
let cast = Expr::new(
ExprKind::TypeCast {
expr: Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Span::new(0, 2),
)),
target_type: "f64".to_string(),
},
Span::new(0, 10),
);
if let ExprKind::TypeCast { target_type, .. } = cast.kind {
assert_eq!(target_type, "f64");
}
}
#[test]
fn test_binary_operators_complete() {
let ops = vec![
BinaryOp::Add,
BinaryOp::Subtract,
BinaryOp::Multiply,
BinaryOp::Divide,
BinaryOp::Modulo,
BinaryOp::Power,
BinaryOp::Equal,
BinaryOp::NotEqual,
BinaryOp::Less,
BinaryOp::Greater,
BinaryOp::LessEqual,
BinaryOp::GreaterEqual,
BinaryOp::And,
BinaryOp::Or,
BinaryOp::BitwiseAnd,
BinaryOp::BitwiseOr,
BinaryOp::BitwiseXor,
BinaryOp::LeftShift,
];
for op in ops {
let expr = Expr::new(
ExprKind::Binary {
left: Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(1, None)),
Span::new(0, 1),
)),
op,
right: Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(2, None)),
Span::new(2, 3),
)),
},
Span::new(0, 3),
);
if let ExprKind::Binary { op: test_op, .. } = expr.kind {
assert_eq!(test_op, op);
}
}
}
#[test]
fn test_span_operations() {
let span1 = Span::new(0, 10);
let span2 = Span::new(5, 15);
let merged = span1.merge(span2);
assert_eq!(merged.start, 0);
assert_eq!(merged.end, 15);
let merged2 = span2.merge(span1);
assert_eq!(merged2.start, 0);
assert_eq!(merged2.end, 15);
}
#[test]
fn test_pattern_with_default() {
let pattern = Pattern::WithDefault {
pattern: Box::new(Pattern::Identifier("count".to_string())),
default: Box::new(Expr::new(
ExprKind::Literal(Literal::Integer(0, None)),
Span::new(0, 1),
)),
};
if let Pattern::WithDefault { pattern, default } = pattern {
match *pattern {
Pattern::Identifier(name) => assert_eq!(name, "count"),
_ => panic!("Expected identifier pattern"),
}
match default.kind {
ExprKind::Literal(Literal::Integer(val, None)) => assert_eq!(val, 0),
_ => panic!("Expected integer literal"),
}
}
}