linkrs-query 0.1.0

Query engine, parser, and executor for Linkrs
Documentation
use super::*;

#[test]
fn test_head_function() {
    let list = Value::list(List {
        values: vec![Value::Int(1), Value::Int(2), Value::Int(3)],
    });
    let result = ContainerFunction::Head
        .execute(&[list])
        .expect("head function should succeed");
    assert_eq!(result, Value::Int(1));
}

#[test]
fn test_head_empty_list() {
    let list = Value::list(List { values: vec![] });
    let result = ContainerFunction::Head
        .execute(&[list])
        .expect("head function should succeed");
    assert_eq!(result, Value::Null(NullType::Null));
}

#[test]
fn test_last_function() {
    let list = Value::list(List {
        values: vec![Value::Int(1), Value::Int(2), Value::Int(3)],
    });
    let result = ContainerFunction::Last
        .execute(&[list])
        .expect("last function should succeed");
    assert_eq!(result, Value::Int(3));
}

#[test]
fn test_tail_function() {
    let list = Value::list(List {
        values: vec![Value::Int(1), Value::Int(2), Value::Int(3)],
    });
    let result = ContainerFunction::Tail
        .execute(&[list])
        .expect("tail function should succeed");
    assert_eq!(
        result,
        Value::list(List {
            values: vec![Value::Int(2), Value::Int(3)]
        })
    );
}

#[test]
fn test_size_string() {
    let result = ContainerFunction::Size
        .execute(&[Value::string("hello")])
        .expect("size function should succeed");
    assert_eq!(result, Value::Int(5));
}

#[test]
fn test_size_list() {
    let list = Value::list(List {
        values: vec![Value::Int(1), Value::Int(2), Value::Int(3)],
    });
    let result = ContainerFunction::Size
        .execute(&[list])
        .expect("size function should succeed");
    assert_eq!(result, Value::Int(3));
}

#[test]
fn test_range_basic() {
    let result = ContainerFunction::Range
        .execute(&[Value::Int(1), Value::Int(5)])
        .expect("range function should succeed");
    assert_eq!(
        result,
        Value::list(List {
            values: vec![
                Value::Int(1),
                Value::Int(2),
                Value::Int(3),
                Value::Int(4),
                Value::Int(5)
            ]
        })
    );
}

#[test]
fn test_range_with_step() {
    let result = ContainerFunction::Range
        .execute(&[Value::Int(0), Value::Int(10), Value::Int(2)])
        .expect("range function should succeed");
    assert_eq!(
        result,
        Value::list(List {
            values: vec![
                Value::Int(0),
                Value::Int(2),
                Value::Int(4),
                Value::Int(6),
                Value::Int(8),
                Value::Int(10)
            ]
        })
    );
}

#[test]
fn test_null_handling() {
    let null_value = Value::Null(NullType::Null);

    assert_eq!(
        ContainerFunction::Head
            .execute(std::slice::from_ref(&null_value))
            .expect("head should handle NULL"),
        Value::Null(NullType::Null)
    );
    assert_eq!(
        ContainerFunction::Last
            .execute(std::slice::from_ref(&null_value))
            .expect("last should handle NULL"),
        Value::Null(NullType::Null)
    );
    assert_eq!(
        ContainerFunction::Tail
            .execute(std::slice::from_ref(&null_value))
            .expect("tail should handle NULL"),
        Value::Null(NullType::Null)
    );
    assert_eq!(
        ContainerFunction::Size
            .execute(std::slice::from_ref(&null_value))
            .expect("size should handle NULL"),
        Value::Null(NullType::Null)
    );
}

#[test]
fn test_list_distinct() {
    let list = Value::list(List {
        values: vec![
            Value::Int(1),
            Value::Int(2),
            Value::Int(1),
            Value::Int(3),
            Value::Int(2),
        ],
    });
    let result = ContainerFunction::ListDistinct
        .execute(&[list])
        .expect("list_distinct should succeed");
    assert_eq!(
        result,
        Value::list(List {
            values: vec![Value::Int(1), Value::Int(2), Value::Int(3)]
        })
    );
}

#[test]
fn test_list_extract() {
    let list = Value::list(List {
        values: vec![Value::Int(10), Value::Int(20), Value::Int(30)],
    });
    assert_eq!(
        ContainerFunction::ListExtract
            .execute(&[list.clone(), Value::Int(0)])
            .unwrap(),
        Value::Int(10)
    );
    assert_eq!(
        ContainerFunction::ListExtract
            .execute(&[list.clone(), Value::Int(1)])
            .unwrap(),
        Value::Int(20)
    );
    assert_eq!(
        ContainerFunction::ListExtract
            .execute(&[list.clone(), Value::Int(-1)])
            .unwrap(),
        Value::Int(30)
    );
}

#[test]
fn test_list_extract_out_of_bounds() {
    let list = Value::list(List {
        values: vec![Value::Int(1)],
    });
    let result = ContainerFunction::ListExtract
        .execute(&[list, Value::Int(5)])
        .expect("list_extract should handle out of bounds");
    assert_eq!(result, Value::Null(NullType::Null));
}

#[test]
fn test_struct_pack() {
    let result = ContainerFunction::StructPack
        .execute(&[
            Value::string("name"),
            Value::string("Alice"),
            Value::string("age"),
            Value::Int(30),
        ])
        .expect("struct_pack should succeed");
    assert!(matches!(result, Value::Map(_)));
}

#[test]
fn test_struct_extract() {
    let mut map: std::collections::HashMap<String, Value> = std::collections::HashMap::new();
    map.insert("name".into(), Value::string("Alice"));
    map.insert("age".into(), Value::Int(30));
    let result = ContainerFunction::StructExtract
        .execute(&[Value::string_map(map), Value::string("name")])
        .expect("struct_extract should succeed");
    assert_eq!(result, Value::string("Alice"));
}

#[test]
fn test_map_creation() {
    let result = ContainerFunction::MapCreation
        .execute(&[
            Value::string("x"),
            Value::Int(1),
            Value::string("y"),
            Value::Int(2),
        ])
        .expect("map should succeed");
    assert!(matches!(result, Value::Map(_)));
}

#[test]
fn test_element_at_list() {
    let list = Value::list(List {
        values: vec![Value::Int(10), Value::Int(20), Value::Int(30)],
    });
    let result = ContainerFunction::ElementAt
        .execute(&[list, Value::Int(1)])
        .expect("element_at should succeed");
    assert_eq!(result, Value::Int(20));
}

#[test]
fn test_element_at_map() {
    let mut map: std::collections::HashMap<String, Value> = std::collections::HashMap::new();
    map.insert("key".into(), Value::string("value"));
    let result = ContainerFunction::ElementAt
        .execute(&[Value::string_map(map), Value::string("key")])
        .expect("element_at should succeed");
    assert_eq!(result, Value::string("value"));
}

#[test]
fn test_cardinality() {
    let map: std::collections::HashMap<String, Value> = std::collections::HashMap::new();
    let result = ContainerFunction::Cardinality
        .execute(&[Value::string_map(map)])
        .expect("cardinality should succeed");
    assert_eq!(result, Value::Int(0));
}

#[test]
fn test_map_keys() {
    let mut map: std::collections::HashMap<String, Value> = std::collections::HashMap::new();
    map.insert("a".into(), Value::Int(1));
    map.insert("b".into(), Value::Int(2));
    let result = ContainerFunction::MapKeys
        .execute(&[Value::string_map(map)])
        .expect("map_keys should succeed");
    assert!(matches!(result, Value::List(_)));
}

#[test]
fn test_map_values() {
    let mut map: std::collections::HashMap<String, Value> = std::collections::HashMap::new();
    map.insert("a".into(), Value::Int(1));
    map.insert("b".into(), Value::Int(2));
    let result = ContainerFunction::MapValues
        .execute(&[Value::string_map(map)])
        .expect("map_values should succeed");
    assert!(matches!(result, Value::List(_)));
}

#[test]
fn test_size_non_ascii_counts_chars() {
    let result = ContainerFunction::Size
        .execute(&[Value::string("你好世界")])
        .expect("size function should succeed");
    assert_eq!(result, Value::BigInt(4));
}

#[test]
fn test_size_arity() {
    use crate::executor::expression::ExpressionErrorType;
    let err = ContainerFunction::Size.execute(&[]).unwrap_err();
    assert_eq!(err.error_type, ExpressionErrorType::InvalidArgumentCount);
    assert!(err.message.contains("size"));
}