use super::*;
use crate::frontend::ast::{DataFrameOp, Expr, ExprKind, Literal, Span};
#[test]
fn test_dataframe_sum() {
let columns = vec![
DataFrameColumn {
name: "a".to_string(),
values: vec![Value::Integer(1), Value::Integer(2), Value::Integer(3)],
},
DataFrameColumn {
name: "b".to_string(),
values: vec![Value::Float(1.5), Value::Float(2.5), Value::Float(3.5)],
},
];
let result = eval_dataframe_sum(&columns, &[]).expect("operation should succeed in test");
assert_eq!(result, Value::Float(13.5));
}
#[test]
fn test_dataframe_sum_integer_only() {
let columns = vec![DataFrameColumn {
name: "integers".to_string(),
values: vec![Value::Integer(10), Value::Integer(20), Value::Integer(30)],
}];
let result = eval_dataframe_sum(&columns, &[]).expect("operation should succeed in test");
assert_eq!(result, Value::Integer(60));
}
#[test]
fn test_dataframe_sum_with_non_numeric() {
let columns = vec![DataFrameColumn {
name: "mixed".to_string(),
values: vec![
Value::Integer(5),
Value::from_string("text".to_string()),
Value::Float(2.5),
Value::Bool(true),
],
}];
let result = eval_dataframe_sum(&columns, &[]).expect("operation should succeed in test");
assert_eq!(result, Value::Float(7.5));
}
#[test]
fn test_dataframe_sum_empty() {
let columns = vec![];
let result = eval_dataframe_sum(&columns, &[]).expect("operation should succeed in test");
assert_eq!(result, Value::Integer(0));
}
#[test]
fn test_dataframe_sum_with_args_error() {
let columns = vec![];
let args = vec![Value::Integer(1)];
let result = eval_dataframe_sum(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("takes no arguments"));
}
#[test]
fn test_dataframe_select() {
let columns = vec![
DataFrameColumn {
name: "a".to_string(),
values: vec![Value::Integer(1), Value::Integer(2)],
},
DataFrameColumn {
name: "b".to_string(),
values: vec![Value::Integer(3), Value::Integer(4)],
},
];
let args = vec![Value::from_string("a".to_string())];
let result =
eval_dataframe_select(&columns, &args).expect("operation should succeed in test");
if let Value::DataFrame {
columns: result_cols,
} = result
{
assert_eq!(result_cols.len(), 1);
assert_eq!(result_cols[0].name, "a");
} else {
panic!("Expected DataFrame result");
}
}
#[test]
fn test_dataframe_select_column_not_found() {
let columns = vec![DataFrameColumn {
name: "a".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![Value::from_string("nonexistent".to_string())];
let result = eval_dataframe_select(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("not found in DataFrame"));
}
#[test]
fn test_dataframe_select_wrong_arg_count() {
let columns = vec![];
let args = vec![];
let result = eval_dataframe_select(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("expects exactly 1 argument"));
}
#[test]
fn test_dataframe_select_wrong_arg_type() {
let columns = vec![];
let args = vec![Value::Integer(1)];
let result = eval_dataframe_select(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("expects column name as string"));
}
#[test]
fn test_dataframe_slice() {
let columns = vec![DataFrameColumn {
name: "a".to_string(),
values: vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
Value::Integer(4),
],
}];
let args = vec![Value::Integer(1), Value::Integer(2)];
let result =
eval_dataframe_slice(&columns, &args).expect("operation should succeed in test");
if let Value::DataFrame {
columns: result_cols,
} = result
{
assert_eq!(result_cols[0].values.len(), 2);
assert_eq!(result_cols[0].values[0], Value::Integer(2));
assert_eq!(result_cols[0].values[1], Value::Integer(3));
} else {
panic!("Expected DataFrame result");
}
}
#[test]
fn test_dataframe_slice_start_beyond_length() {
let columns = vec![DataFrameColumn {
name: "a".to_string(),
values: vec![Value::Integer(1), Value::Integer(2)],
}];
let args = vec![Value::Integer(5), Value::Integer(2)];
let result =
eval_dataframe_slice(&columns, &args).expect("operation should succeed in test");
if let Value::DataFrame {
columns: result_cols,
} = result
{
assert_eq!(result_cols[0].values.len(), 0);
} else {
panic!("Expected DataFrame result");
}
}
#[test]
fn test_dataframe_slice_length_beyond_data() {
let columns = vec![DataFrameColumn {
name: "a".to_string(),
values: vec![Value::Integer(1), Value::Integer(2)],
}];
let args = vec![Value::Integer(1), Value::Integer(10)];
let result =
eval_dataframe_slice(&columns, &args).expect("operation should succeed in test");
if let Value::DataFrame {
columns: result_cols,
} = result
{
assert_eq!(result_cols[0].values.len(), 1);
assert_eq!(result_cols[0].values[0], Value::Integer(2));
} else {
panic!("Expected DataFrame result");
}
}
#[test]
fn test_dataframe_slice_wrong_arg_count() {
let columns = vec![];
let args = vec![Value::Integer(1)];
let result = eval_dataframe_slice(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("expects exactly 2 arguments"));
}
#[test]
fn test_dataframe_slice_wrong_start_type() {
let columns = vec![];
let args = vec![Value::from_string("not_int".to_string()), Value::Integer(1)];
let result = eval_dataframe_slice(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("expects start as integer"));
}
#[test]
fn test_dataframe_slice_wrong_length_type() {
let columns = vec![];
let args = vec![Value::Integer(1), Value::from_string("not_int".to_string())];
let result = eval_dataframe_slice(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("expects length as integer"));
}
#[test]
fn test_dataframe_join_basic() {
let left_columns = vec![
DataFrameColumn {
name: "id".to_string(),
values: vec![Value::Integer(1), Value::Integer(2)],
},
DataFrameColumn {
name: "name".to_string(),
values: vec![
Value::from_string("Alice".to_string()),
Value::from_string("Bob".to_string()),
],
},
];
let right_columns = vec![
DataFrameColumn {
name: "id".to_string(),
values: vec![Value::Integer(1), Value::Integer(3)],
},
DataFrameColumn {
name: "age".to_string(),
values: vec![Value::Integer(25), Value::Integer(30)],
},
];
let other_df = Value::DataFrame {
columns: right_columns,
};
let args = vec![other_df, Value::from_string("id".to_string())];
let result =
eval_dataframe_join(&left_columns, &args).expect("operation should succeed in test");
if let Value::DataFrame {
columns: result_cols,
} = result
{
assert_eq!(result_cols.len(), 3); assert_eq!(result_cols[0].name, "id");
assert_eq!(result_cols[1].name, "name");
assert_eq!(result_cols[2].name, "age_right");
assert_eq!(result_cols[0].values.len(), 1); } else {
panic!("Expected DataFrame result");
}
}
#[test]
fn test_dataframe_join_wrong_arg_count() {
let columns = vec![];
let args = vec![Value::Integer(1)];
let result = eval_dataframe_join(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("expects exactly 2 arguments"));
}
#[test]
fn test_dataframe_join_wrong_on_type() {
let columns = vec![];
let other_df = Value::DataFrame { columns: vec![] };
let args = vec![other_df, Value::Integer(1)];
let result = eval_dataframe_join(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("expects 'on' as string"));
}
#[test]
fn test_dataframe_join_wrong_df_type() {
let columns = vec![];
let args = vec![Value::Integer(1), Value::from_string("id".to_string())];
let result = eval_dataframe_join(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("expects first argument to be a DataFrame"));
}
#[test]
fn test_validate_and_find_join_columns_missing_left() {
let left_cols = vec![DataFrameColumn {
name: "a".to_string(),
values: vec![],
}];
let right_cols = vec![DataFrameColumn {
name: "id".to_string(),
values: vec![],
}];
let result = validate_and_find_join_columns(&left_cols, &right_cols, "id");
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("not found in left DataFrame"));
}
#[test]
fn test_validate_and_find_join_columns_missing_right() {
let left_cols = vec![DataFrameColumn {
name: "id".to_string(),
values: vec![],
}];
let right_cols = vec![DataFrameColumn {
name: "a".to_string(),
values: vec![],
}];
let result = validate_and_find_join_columns(&left_cols, &right_cols, "id");
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("not found in right DataFrame"));
}
#[test]
fn test_initialize_result_columns() {
let left_cols = vec![
DataFrameColumn {
name: "id".to_string(),
values: vec![],
},
DataFrameColumn {
name: "name".to_string(),
values: vec![],
},
];
let right_cols = vec![
DataFrameColumn {
name: "id".to_string(),
values: vec![],
},
DataFrameColumn {
name: "age".to_string(),
values: vec![],
},
];
let result = initialize_result_columns(&left_cols, &right_cols, "id");
assert_eq!(result.len(), 3);
assert_eq!(result[0].name, "id");
assert_eq!(result[1].name, "name");
assert_eq!(result[2].name, "age_right");
}
#[test]
fn test_dataframe_groupby_basic() {
let columns = vec![
DataFrameColumn {
name: "group".to_string(),
values: vec![
Value::from_string("A".to_string()),
Value::from_string("A".to_string()),
Value::from_string("B".to_string()),
],
},
DataFrameColumn {
name: "value".to_string(),
values: vec![Value::Integer(1), Value::Integer(2), Value::Integer(3)],
},
];
let args = vec![Value::from_string("group".to_string())];
let result =
eval_dataframe_groupby(&columns, &args).expect("operation should succeed in test");
if let Value::DataFrame {
columns: result_cols,
} = result
{
assert_eq!(result_cols.len(), 2); assert_eq!(result_cols[0].name, "group");
assert_eq!(result_cols[1].name, "value_sum");
} else {
panic!("Expected DataFrame result");
}
}
#[test]
fn test_dataframe_groupby_wrong_arg_count() {
let columns = vec![];
let args = vec![];
let result = eval_dataframe_groupby(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("expects exactly 1 argument"));
}
#[test]
fn test_dataframe_groupby_wrong_arg_type() {
let columns = vec![];
let args = vec![Value::Integer(1)];
let result = eval_dataframe_groupby(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("expects column name as string"));
}
#[test]
fn test_dataframe_groupby_column_not_found() {
let columns = vec![DataFrameColumn {
name: "a".to_string(),
values: vec![],
}];
let args = vec![Value::from_string("nonexistent".to_string())];
let result = eval_dataframe_groupby(&columns, &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("not found in DataFrame"));
}
#[test]
fn test_create_group_mapping_for_aggregation() {
let group_col = DataFrameColumn {
name: "group".to_string(),
values: vec![
Value::String("A".to_string().into()),
Value::String("B".to_string().into()),
Value::String("A".to_string().into()),
],
};
let groups = create_group_mapping_for_aggregation(&group_col);
assert_eq!(groups.len(), 2);
assert!(groups.contains_key("\"A\""));
assert!(groups.contains_key("\"B\""));
assert_eq!(
groups
.get("\"A\"")
.expect("operation should succeed in test"),
&vec![0, 2]
);
assert_eq!(
groups
.get("\"B\"")
.expect("operation should succeed in test"),
&vec![1]
);
}
#[test]
fn test_initialize_group_columns_for_aggregation() {
let mut groups = HashMap::new();
groups.insert("A".to_string(), vec![0, 2]);
groups.insert("B".to_string(), vec![1]);
let result = initialize_group_columns_for_aggregation(&groups, "group");
assert_eq!(result.len(), 1);
assert_eq!(result[0].name, "group");
assert_eq!(result[0].values.len(), 2);
}
#[test]
fn test_is_numeric_column_for_aggregation() {
let numeric_col = DataFrameColumn {
name: "numbers".to_string(),
values: vec![Value::Integer(1), Value::Float(2.5)],
};
assert!(is_numeric_column_for_aggregation(&numeric_col));
let non_numeric_col = DataFrameColumn {
name: "strings".to_string(),
values: vec![Value::from_string("text".to_string())],
};
assert!(!is_numeric_column_for_aggregation(&non_numeric_col));
let mixed_col = DataFrameColumn {
name: "mixed".to_string(),
values: vec![Value::from_string("text".to_string()), Value::Integer(1)],
};
assert!(is_numeric_column_for_aggregation(&mixed_col));
}
#[test]
fn test_calculate_group_sum_for_aggregation() {
let col = DataFrameColumn {
name: "values".to_string(),
values: vec![
Value::Integer(1),
Value::Integer(2),
Value::Float(3.5),
Value::from_string("text".to_string()),
],
};
let result = calculate_group_sum_for_aggregation(&col, &[0, 2]);
assert_eq!(result, Value::Float(4.5));
let result_no_numeric = calculate_group_sum_for_aggregation(&col, &[3]);
assert_eq!(result_no_numeric, Value::Nil);
let result_integer_only = calculate_group_sum_for_aggregation(&col, &[0, 1]);
assert_eq!(result_integer_only, Value::Integer(3));
}
#[test]
fn test_dataframe_filter() {
let columns = vec![
DataFrameColumn {
name: "age".to_string(),
values: vec![Value::Integer(25), Value::Integer(30), Value::Integer(35)],
},
DataFrameColumn {
name: "name".to_string(),
values: vec![
Value::from_string("Alice".to_string()),
Value::from_string("Bob".to_string()),
Value::from_string("Charlie".to_string()),
],
},
];
let condition = Expr::new(ExprKind::Literal(Literal::Bool(true)), Span::new(0, 0));
let mut eval_calls = 0;
let eval_with_context = |_expr: &Expr, _cols: &[DataFrameColumn], _row: usize| {
eval_calls += 1;
Ok(Value::Bool(eval_calls % 2 == 1)) };
let result = eval_dataframe_filter(&columns, &condition, eval_with_context)
.expect("operation should succeed in test");
if let Value::DataFrame {
columns: result_cols,
} = result
{
assert_eq!(result_cols[0].values.len(), 2); assert_eq!(result_cols[0].values[0], Value::Integer(25));
assert_eq!(result_cols[0].values[1], Value::Integer(35));
} else {
panic!("Expected DataFrame result");
}
}
#[test]
fn test_dataframe_filter_empty() {
let columns = vec![];
let condition = Expr::new(ExprKind::Literal(Literal::Bool(true)), Span::new(0, 0));
let eval_with_context =
|_expr: &Expr, _cols: &[DataFrameColumn], _row: usize| Ok(Value::Bool(true));
let result = eval_dataframe_filter(&columns, &condition, eval_with_context)
.expect("operation should succeed in test");
if let Value::DataFrame {
columns: result_cols,
} = result
{
assert_eq!(result_cols.len(), 0);
} else {
panic!("Expected DataFrame result");
}
}
#[test]
fn test_dataframe_filter_non_boolean_condition() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1)],
}];
let condition = Expr::new(ExprKind::Literal(Literal::Bool(true)), Span::new(0, 0));
let eval_with_context = |_expr: &Expr, _cols: &[DataFrameColumn], _row: usize| {
Ok(Value::Integer(1)) };
let result = eval_dataframe_filter(&columns, &condition, eval_with_context);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("must evaluate to boolean"));
}
#[test]
fn test_eval_dataframe_method_unknown() {
let columns = vec![];
let result = eval_dataframe_method(&columns, "unknown_method", &[]);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("Unknown DataFrame method"));
}
#[test]
fn test_eval_dataframe_method_select() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![Value::from_string("test".to_string())];
let result = eval_dataframe_method(&columns, "select", &args);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_method_sum() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1)],
}];
let result = eval_dataframe_method(&columns, "sum", &[]);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_method_slice() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![Value::Integer(0), Value::Integer(1)];
let result = eval_dataframe_method(&columns, "slice", &args);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_method_join() {
let columns = vec![DataFrameColumn {
name: "id".to_string(),
values: vec![Value::Integer(1)],
}];
let other_df = Value::DataFrame {
columns: vec![DataFrameColumn {
name: "id".to_string(),
values: vec![Value::Integer(1)],
}],
};
let args = vec![other_df, Value::from_string("id".to_string())];
let result = eval_dataframe_method(&columns, "join", &args);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_method_groupby() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![Value::from_string("test".to_string())];
let result = eval_dataframe_method(&columns, "groupby", &args);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_operation_select() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1)],
}];
let operation = DataFrameOp::Select(vec!["test".to_string()]);
let eval_with_context =
|_expr: &Expr, _cols: &[DataFrameColumn], _row: usize| Ok(Value::Bool(true));
let result = eval_dataframe_operation(columns, &operation, eval_with_context);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_operation_filter() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1)],
}];
let condition = Expr::new(ExprKind::Literal(Literal::Bool(true)), Span::new(0, 0));
let operation = DataFrameOp::Filter(Box::new(condition));
let eval_with_context =
|_expr: &Expr, _cols: &[DataFrameColumn], _row: usize| Ok(Value::Bool(true));
let result = eval_dataframe_operation(columns, &operation, eval_with_context);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_operation_groupby() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1)],
}];
let operation = DataFrameOp::GroupBy(vec!["test".to_string()]);
let eval_with_context =
|_expr: &Expr, _cols: &[DataFrameColumn], _row: usize| Ok(Value::Bool(true));
let result = eval_dataframe_operation(columns, &operation, eval_with_context);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_select_multiple() {
let columns = vec![
DataFrameColumn {
name: "a".to_string(),
values: vec![Value::Integer(1)],
},
DataFrameColumn {
name: "b".to_string(),
values: vec![Value::Integer(2)],
},
];
let column_names = vec!["a".to_string(), "b".to_string()];
let result = eval_dataframe_select_multiple(&columns, &column_names)
.expect("operation should succeed in test");
if let Value::DataFrame {
columns: result_cols,
} = result
{
assert_eq!(result_cols.len(), 2);
assert_eq!(result_cols[0].name, "a");
assert_eq!(result_cols[1].name, "b");
} else {
panic!("Expected DataFrame result");
}
}
#[test]
fn test_eval_dataframe_select_multiple_column_not_found() {
let columns = vec![DataFrameColumn {
name: "a".to_string(),
values: vec![Value::Integer(1)],
}];
let column_names = vec!["nonexistent".to_string()];
let result = eval_dataframe_select_multiple(&columns, &column_names);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("not found in DataFrame"));
}
#[test]
fn test_eval_dataframe_groupby_multiple_empty_columns() {
let columns = vec![];
let group_columns = vec![];
let result = eval_dataframe_groupby_multiple(&columns, &group_columns);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("Cannot group by empty DataFrame"));
}
#[test]
fn test_eval_dataframe_groupby_multiple_default_first_column() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1)],
}];
let group_columns = vec![];
let result = eval_dataframe_groupby_multiple(&columns, &group_columns);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_groupby_multiple_column_not_found() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1)],
}];
let group_columns = vec!["nonexistent".to_string()];
let result = eval_dataframe_groupby_multiple(&columns, &group_columns);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("not found in DataFrame"));
}
#[test]
fn test_eval_dataframe_method_rows() {
let columns = vec![DataFrameColumn {
name: "test".to_string(),
values: vec![Value::Integer(1), Value::Integer(2), Value::Integer(3)],
}];
let result = eval_dataframe_method(&columns, "rows", &[]);
assert!(result.is_ok());
assert_eq!(
result.expect("operation should succeed in test"),
Value::Integer(3)
);
}
#[test]
fn test_eval_dataframe_method_rows_empty() {
let columns: Vec<DataFrameColumn> = vec![];
let result = eval_dataframe_method(&columns, "rows", &[]);
assert!(result.is_ok());
assert_eq!(
result.expect("operation should succeed in test"),
Value::Integer(0)
);
}
#[test]
fn test_eval_dataframe_method_columns() {
let columns = vec![
DataFrameColumn {
name: "a".to_string(),
values: vec![Value::Integer(1)],
},
DataFrameColumn {
name: "b".to_string(),
values: vec![Value::Integer(2)],
},
];
let result = eval_dataframe_method(&columns, "columns", &[]);
assert!(result.is_ok());
assert_eq!(
result.expect("operation should succeed in test"),
Value::Integer(2)
);
}
#[test]
fn test_eval_dataframe_method_column_names() {
let columns = vec![
DataFrameColumn {
name: "col_a".to_string(),
values: vec![Value::Integer(1)],
},
DataFrameColumn {
name: "col_b".to_string(),
values: vec![Value::Integer(2)],
},
];
let result = eval_dataframe_method(&columns, "column_names", &[]);
assert!(result.is_ok());
match result.expect("operation should succeed in test") {
Value::Array(arr) => {
assert_eq!(arr.len(), 2);
}
_ => panic!("Expected array"),
}
}
#[test]
fn test_eval_dataframe_method_mean() {
let columns = vec![DataFrameColumn {
name: "values".to_string(),
values: vec![Value::Integer(10), Value::Integer(20), Value::Integer(30)],
}];
let result = eval_dataframe_method(&columns, "mean", &[]);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_method_max() {
let columns = vec![DataFrameColumn {
name: "values".to_string(),
values: vec![Value::Integer(10), Value::Integer(50), Value::Integer(30)],
}];
let result = eval_dataframe_method(&columns, "max", &[]);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_method_min() {
let columns = vec![DataFrameColumn {
name: "values".to_string(),
values: vec![Value::Integer(10), Value::Integer(50), Value::Integer(5)],
}];
let result = eval_dataframe_method(&columns, "min", &[]);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_method_std() {
let columns = vec![DataFrameColumn {
name: "values".to_string(),
values: vec![Value::Float(10.0), Value::Float(20.0), Value::Float(30.0)],
}];
let result = eval_dataframe_method(&columns, "std", &[]);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_method_var() {
let columns = vec![DataFrameColumn {
name: "values".to_string(),
values: vec![Value::Float(10.0), Value::Float(20.0), Value::Float(30.0)],
}];
let result = eval_dataframe_method(&columns, "var", &[]);
assert!(result.is_ok());
}
#[test]
fn test_eval_dataframe_method_sort_by_ascending() {
let columns = vec![DataFrameColumn {
name: "values".to_string(),
values: vec![Value::Integer(30), Value::Integer(10), Value::Integer(20)],
}];
let args = vec![Value::from_string("values".to_string())];
let result = eval_dataframe_method(&columns, "sort_by", &args);
assert!(result.is_ok());
match result.expect("operation should succeed in test") {
Value::DataFrame { columns: sorted } => {
assert_eq!(sorted[0].values[0], Value::Integer(10));
assert_eq!(sorted[0].values[1], Value::Integer(20));
assert_eq!(sorted[0].values[2], Value::Integer(30));
}
_ => panic!("Expected DataFrame"),
}
}
#[test]
fn test_eval_dataframe_method_sort_by_descending() {
let columns = vec![DataFrameColumn {
name: "values".to_string(),
values: vec![Value::Integer(10), Value::Integer(30), Value::Integer(20)],
}];
let args = vec![
Value::from_string("values".to_string()),
Value::Bool(true), ];
let result = eval_dataframe_method(&columns, "sort_by", &args);
assert!(result.is_ok());
match result.expect("operation should succeed in test") {
Value::DataFrame { columns: sorted } => {
assert_eq!(sorted[0].values[0], Value::Integer(30));
assert_eq!(sorted[0].values[1], Value::Integer(20));
assert_eq!(sorted[0].values[2], Value::Integer(10));
}
_ => panic!("Expected DataFrame"),
}
}
#[test]
fn test_eval_dataframe_method_sort_by_column_not_found() {
let columns = vec![DataFrameColumn {
name: "values".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![Value::from_string("nonexistent".to_string())];
let result = eval_dataframe_method(&columns, "sort_by", &args);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("not found in DataFrame"));
}
#[test]
fn test_eval_dataframe_method_get() {
let columns = vec![DataFrameColumn {
name: "values".to_string(),
values: vec![Value::Integer(10), Value::Integer(20), Value::Integer(30)],
}];
let args = vec![Value::from_string("values".to_string()), Value::Integer(1)];
let result = eval_dataframe_method(&columns, "get", &args);
assert!(result.is_ok());
assert_eq!(
result.expect("operation should succeed in test"),
Value::Integer(20)
);
}
#[test]
fn test_eval_dataframe_method_to_csv() {
let columns = vec![
DataFrameColumn {
name: "a".to_string(),
values: vec![Value::Integer(1), Value::Integer(2)],
},
DataFrameColumn {
name: "b".to_string(),
values: vec![Value::Integer(3), Value::Integer(4)],
},
];
let result = eval_dataframe_method(&columns, "to_csv", &[]);
assert!(result.is_ok());
match result.expect("operation should succeed in test") {
Value::String(csv) => {
assert!(csv.contains("a"));
assert!(csv.contains("b"));
}
_ => panic!("Expected string"),
}
}
#[test]
fn test_eval_dataframe_method_to_json() {
let columns = vec![DataFrameColumn {
name: "value".to_string(),
values: vec![Value::Integer(42)],
}];
let result = eval_dataframe_method(&columns, "to_json", &[]);
assert!(result.is_ok());
match result.expect("operation should succeed in test") {
Value::String(json) => {
assert!(json.contains("value"));
}
_ => panic!("Expected string"),
}
}
#[test]
fn test_compare_values_for_sort_integers() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(&Value::Integer(1), &Value::Integer(2)),
Ordering::Less
);
assert_eq!(
compare_values_for_sort(&Value::Integer(2), &Value::Integer(1)),
Ordering::Greater
);
assert_eq!(
compare_values_for_sort(&Value::Integer(1), &Value::Integer(1)),
Ordering::Equal
);
}
#[test]
fn test_compare_values_for_sort_floats() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(&Value::Float(1.0), &Value::Float(2.0)),
Ordering::Less
);
assert_eq!(
compare_values_for_sort(&Value::Float(2.0), &Value::Float(1.0)),
Ordering::Greater
);
}
#[test]
fn test_compare_values_for_sort_mixed() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(&Value::Integer(1), &Value::Float(2.0)),
Ordering::Less
);
let result = compare_values_for_sort(&Value::Float(1.0), &Value::Integer(2));
assert!(result == Ordering::Less || result == Ordering::Greater);
}
#[test]
fn test_compare_values_for_sort_strings() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(
&Value::from_string("apple".to_string()),
&Value::from_string("banana".to_string())
),
Ordering::Less
);
}
#[test]
fn test_compare_values_for_sort_booleans() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(&Value::Bool(false), &Value::Bool(true)),
Ordering::Less
);
}
#[test]
fn test_compare_sort_equal_integers() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(&Value::Integer(5), &Value::Integer(5)),
Ordering::Equal
);
}
#[test]
fn test_compare_sort_floats_less() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(&Value::Float(1.5), &Value::Float(2.5)),
Ordering::Less
);
}
#[test]
fn test_compare_sort_floats_equal() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(&Value::Float(3.14), &Value::Float(3.14)),
Ordering::Equal
);
}
#[test]
fn test_compare_sort_strings_order() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(
&Value::from_string("apple".to_string()),
&Value::from_string("banana".to_string())
),
Ordering::Less
);
}
#[test]
fn test_compare_sort_strings_equal() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(
&Value::from_string("same".to_string()),
&Value::from_string("same".to_string())
),
Ordering::Equal
);
}
#[test]
fn test_compare_sort_bools_equal() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(&Value::Bool(true), &Value::Bool(true)),
Ordering::Equal
);
}
#[test]
fn test_compare_sort_mixed_types() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(&Value::Integer(5), &Value::from_string("5".to_string())),
Ordering::Equal
);
}
#[test]
fn test_compare_sort_integers_greater() {
use std::cmp::Ordering;
assert_eq!(
compare_values_for_sort(&Value::Integer(10), &Value::Integer(5)),
Ordering::Greater
);
}
#[test]
fn test_eval_dataframe_get_basic() {
let columns = vec![
DataFrameColumn {
name: "name".to_string(),
values: vec![
Value::from_string("Alice".to_string()),
Value::from_string("Bob".to_string()),
],
},
DataFrameColumn {
name: "age".to_string(),
values: vec![Value::Integer(30), Value::Integer(25)],
},
];
let args = vec![
Value::from_string("age".to_string()),
Value::Integer(1),
];
let result = eval_dataframe_get(&columns, &args).expect("get should succeed");
assert_eq!(result, Value::Integer(25));
}
#[test]
fn test_eval_dataframe_get_first_row() {
let columns = vec![DataFrameColumn {
name: "x".to_string(),
values: vec![Value::Integer(42), Value::Integer(99)],
}];
let args = vec![
Value::from_string("x".to_string()),
Value::Integer(0),
];
let result = eval_dataframe_get(&columns, &args).expect("get first row should succeed");
assert_eq!(result, Value::Integer(42));
}
#[test]
fn test_eval_dataframe_get_wrong_arg_count() {
let columns = vec![DataFrameColumn {
name: "x".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![Value::from_string("x".to_string())];
let result = eval_dataframe_get(&columns, &args);
assert!(result.is_err());
}
#[test]
fn test_eval_dataframe_get_non_string_column_name() {
let columns = vec![DataFrameColumn {
name: "x".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![Value::Integer(0), Value::Integer(0)];
let result = eval_dataframe_get(&columns, &args);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("string (column name)"));
}
#[test]
fn test_eval_dataframe_get_non_integer_row_index() {
let columns = vec![DataFrameColumn {
name: "x".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![
Value::from_string("x".to_string()),
Value::from_string("zero".to_string()),
];
let result = eval_dataframe_get(&columns, &args);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("integer (row index)"));
}
#[test]
fn test_eval_dataframe_get_negative_row_index() {
let columns = vec![DataFrameColumn {
name: "x".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![
Value::from_string("x".to_string()),
Value::Integer(-1),
];
let result = eval_dataframe_get(&columns, &args);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("non-negative"));
}
#[test]
fn test_eval_dataframe_get_column_not_found() {
let columns = vec![DataFrameColumn {
name: "x".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![
Value::from_string("missing".to_string()),
Value::Integer(0),
];
let result = eval_dataframe_get(&columns, &args);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("not found"));
}
#[test]
fn test_eval_dataframe_get_row_out_of_bounds() {
let columns = vec![DataFrameColumn {
name: "x".to_string(),
values: vec![Value::Integer(1)],
}];
let args = vec![
Value::from_string("x".to_string()),
Value::Integer(5),
];
let result = eval_dataframe_get(&columns, &args);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("out of bounds"));
}
#[test]
fn test_eval_dataframe_get_string_value() {
let columns = vec![DataFrameColumn {
name: "city".to_string(),
values: vec![
Value::from_string("NYC".to_string()),
Value::from_string("LA".to_string()),
],
}];
let args = vec![
Value::from_string("city".to_string()),
Value::Integer(1),
];
let result = eval_dataframe_get(&columns, &args).expect("get string should succeed");
match result {
Value::String(s) => assert_eq!(s.as_ref(), "LA"),
_ => panic!("Expected String value"),
}
}