dw-parser 1.9.0-alpha.3

DataWeave Parser
Documentation
// Copyright (c) 2026, Salesforce, Inc.,
// All rights reserved.
// For full license text, see the LICENSE.txt file
#[cfg(test)]
mod tck_pel {
    use crate::pel::{compile_to_pel_expr, InputContext};
    use std::path::PathBuf;

    #[test]
    fn null_literal() {
        assert_dw2pel("null", "[\":null\", \"0-4\"]");
    }

    #[test]
    fn string_literals() {
        assert_dw2pel("\"hi\"", "[\":str\", \"0-4\", \"hi\"]");
        assert_dw2pel(
            "\"hi \\\"tato\\\"\"",
            "[\":str\", \"0-13\", \"hi \\\"tato\\\"\"]",
        );
        assert_dw2pel("'hi \"pipo\"'", "[\":str\", \"0-11\", \"hi \\\"pipo\\\"\"]");
        assert_dw2pel("'wrapped in single quotes: \\', \", \\\\, \\b, \\f, \\n, \\r, \\t, \\u0000'",
                      "[\":str\", \"0-65\", \"wrapped in single quotes: ', \\\", \\\\, \\b, \\f, \\n, \\r, \\t, \\u0000\"]");
        assert_dw2pel("\"wrapped in double quotes: ', \\\", \\\\, \\b, \\f, \\n, \\r, \\t, \\u0000\"",
                      "[\":str\", \"0-65\", \"wrapped in double quotes: ', \\\", \\\\, \\b, \\f, \\n, \\r, \\t, \\u0000\"]");

        assert_dw2pel("\"hi $(12) $payload $(payload)\"", "[\":++\", \"0-30\", [\":++\", \"0-30\", [\":++\", \"0-30\", [\":++\", \"0-30\", [\":++\", \"0-30\", [\":str\", \"1-4\", \"hi \"], [\":nbr\", \"6-8\", \"12\"]], [\":str\", \"9-10\", \" \"]], [\":ref\", \"11-18\", \"payload\"]], [\":str\", \"18-19\", \" \"]], [\":ref\", \"21-28\", \"payload\"]]");
    }

    #[test]
    fn number_literals() {
        assert_dw2pel("123", "[\":nbr\", \"0-3\", \"123\"]");
        assert_dw2pel("-12.34", "[\":nbr\", \"0-6\", \"-12.34\"]");
    }

    #[test]
    fn boolean_literals() {
        assert_dw2pel("true", "[\":bool\", \"0-4\", \"true\"]");
        assert_dw2pel("false", "[\":bool\", \"0-5\", \"false\"]");
    }

    #[test]
    fn date_time_literals() {
        assert_dw2pel("|2021-09-06|", "[\":ldate\", \"0-12\", \"2021-09-06\"]");
        assert_dw2pel("|23:57:59|", "[\":ltime\", \"0-10\", \"23:57:59\"]");
        assert_dw2pel("|23:57:59Z|", "[\":time\", \"0-11\", \"23:57:59Z\"]");
        assert_dw2pel(
            "|2021-09-06T23:57:59|",
            "[\":ldatetime\", \"0-21\", \"2021-09-06T23:57:59\"]",
        );
        assert_dw2pel(
            "|2021-09-06T23:57:59Z|",
            "[\":datetime\", \"0-22\", \"2021-09-06T23:57:59Z\"]",
        );
    }

    #[test]
    fn array_literals() {
        assert_dw2pel("[]", "[\":array\", \"0-2\"]");
        assert_dw2pel("[\"one\", 2, payload]", "[\":array\", \"0-19\", [\":str\", \"1-6\", \"one\"], [\":nbr\", \"8-9\", \"2\"], [\":ref\", \"11-18\", \"payload\"]]");
    }

    #[test]
    fn comparison_operators() {
        assert_dw2pel(
            "3 > 6",
            "[\">\", \"0-5\", [\":nbr\", \"0-1\", \"3\"], [\":nbr\", \"4-5\", \"6\"]]",
        );
        assert_dw2pel(
            "1 < 5",
            "[\"<\", \"0-5\", [\":nbr\", \"0-1\", \"1\"], [\":nbr\", \"4-5\", \"5\"]]",
        );
        assert_dw2pel(
            "1 >= 3",
            "[\">=\", \"0-6\", [\":nbr\", \"0-1\", \"1\"], [\":nbr\", \"5-6\", \"3\"]]",
        );
        assert_dw2pel(
            "4 <= 6",
            "[\"<=\", \"0-6\", [\":nbr\", \"0-1\", \"4\"], [\":nbr\", \"5-6\", \"6\"]]",
        );
        assert_dw2pel(
            "76 == 234",
            "[\"==\", \"0-9\", [\":nbr\", \"0-2\", \"76\"], [\":nbr\", \"6-9\", \"234\"]]",
        );
        assert_dw2pel(
            "54 != 54",
            "[\"!=\", \"0-8\", [\":nbr\", \"0-2\", \"54\"], [\":nbr\", \"6-8\", \"54\"]]",
        );
    }

    #[test]
    fn logical_operators() {
        assert_dw2pel(
            "true and false",
            "[\"&&\", \"0-14\", [\":bool\", \"0-4\", \"true\"], [\":bool\", \"9-14\", \"false\"]]",
        );
        assert_dw2pel("false or payload.b", "[\"||\", \"0-18\", [\":bool\", \"0-5\", \"false\"], [\".\", \"9-18\", [\":ref\", \"9-16\", \"payload\"], [\":str\", \"17-18\", \"b\"]]]");
        assert_dw2pel("!payload.a", "[\"!\", \"0-10\", [\".\", \"1-10\", [\":ref\", \"1-8\", \"payload\"], [\":str\", \"9-10\", \"a\"]]]");
        assert_dw2pel("not payload.a", "[\"!\", \"0-13\", [\".\", \"3-13\", [\":ref\", \"4-11\", \"payload\"], [\":str\", \"12-13\", \"a\"]]]");
    }

    #[test]
    fn selectors() {
        assert_dw2pel(
            "payload.a",
            "[\".\", \"0-9\", [\":ref\", \"0-7\", \"payload\"], [\":str\", \"8-9\", \"a\"]]",
        );
        assert_dw2pel("payload.a.b", "[\".\", \"0-11\", [\".\", \"0-9\", [\":ref\", \"0-7\", \"payload\"], [\":str\", \"8-9\", \"a\"]], [\":str\", \"10-11\", \"b\"]]");
        assert_dw2pel("payload.a.b.c", "[\".\", \"0-13\", [\".\", \"0-11\", [\".\", \"0-9\", [\":ref\", \"0-7\", \"payload\"], [\":str\", \"8-9\", \"a\"]], [\":str\", \"10-11\", \"b\"]], [\":str\", \"12-13\", \"c\"]]");
        assert_dw2pel("payload.a[0]", "[\".\", \"0-12\", [\".\", \"0-9\", [\":ref\", \"0-7\", \"payload\"], [\":str\", \"8-9\", \"a\"]], [\":nbr\", \"10-11\", \"0\"]]");
        assert_dw2pel("payload.a['b'][0]", "[\".\", \"0-17\", [\".\", \"0-14\", [\".\", \"0-9\", [\":ref\", \"0-7\", \"payload\"], [\":str\", \"8-9\", \"a\"]], [\":str\", \"10-13\", \"b\"]], [\":nbr\", \"15-16\", \"0\"]]");
        assert_dw2pel(
            "payload.a!",
            "[\".\", \"0-9\", [\":ref\", \"0-7\", \"payload\"], [\":str\", \"8-9\", \"a\"]]",
        );
    }

    #[test]
    fn functions() {
        assert_dw2pel(
            "uuid()",
            "[\":apply\", \"0-6\", [\":ref\", \"0-4\", \"uuid\"]]",
        );
        assert_dw2pel(
            "upper(\"hi\")",
            "[\":apply\", \"0-11\", [\":ref\", \"0-5\", \"upper\"], [\":str\", \"6-10\", \"hi\"]]",
        );
        assert_dw2pel("dw::core::Strings::substringBefore(attributes.headers.myParam, '.')", "[\":apply\", \"0-67\", [\":ref\", \"0-34\", \"substringBefore\"], [\".\", \"35-61\", [\".\", \"35-53\", [\":ref\", \"35-45\", \"attributes\"], [\":str\", \"46-53\", \"headers\"]], [\":str\", \"54-61\", \"myParam\"]], [\":str\", \"63-66\", \".\"]]");
        assert_dw2pel("import * from dw::core::Strings --- substringBefore(attributes.headers.myParam, '.')", "[\":apply\", \"36-84\", [\":ref\", \"36-51\", \"substringBefore\"], [\".\", \"52-78\", [\".\", \"52-70\", [\":ref\", \"52-62\", \"attributes\"], [\":str\", \"63-70\", \"headers\"]], [\":str\", \"71-78\", \"myParam\"]], [\":str\", \"80-83\", \".\"]]");
        assert_dw2pel("\"hi\" ++ \"by\"", "[\":apply\", \"0-12\", [\":ref\", \"5-7\", \"++\"], [\":str\", \"0-4\", \"hi\"], [\":str\", \"8-12\", \"by\"]]");
    }

    #[test]
    fn flow_control() {
        assert_dw2pel("if (false) \"payload.a\" else \"payload.b\"", "[\":if\", \"0-39\", [\":bool\", \"4-9\", \"false\"], [\":str\", \"11-22\", \"payload.a\"], [\":str\", \"28-39\", \"payload.b\"]]");
    }

    #[test]
    fn default_operator() {
        assert_dw2pel("payload.a default \"payload.b\"", "[\":default\", \"0-29\", [\".\", \"0-9\", [\":ref\", \"0-7\", \"payload\"], [\":str\", \"8-9\", \"a\"]], [\":str\", \"18-29\", \"payload.b\"]]");
    }

    #[test]
    fn namespace() {
        dwl_2_pel_scenario("namespace");
    }

    #[test]
    fn attribute() {
        dwl_2_pel_scenario("attribute");
    }

    #[test]
    fn attribute_with_ns() {
        dwl_2_pel_scenario("attribute_with_ns");
    }

    #[test]
    fn multivalue() {
        dwl_2_pel_scenario("multivalue");
    }

    fn dwl_2_pel_scenario(name: &str) {
        let buf = weave_code(name);
        let path = buf.as_os_str();
        let code = std::fs::read_to_string(path).unwrap();
        let pel_expected = std::fs::read_to_string(expected_ast(name).as_os_str()).unwrap();
        let expected = pel_expected.trim();
        assert_dw2pel(code.as_str(), expected);
    }

    fn expected_ast(name: &str) -> PathBuf {
        let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        d.push(format!("./resources/test/pel/{name}.pel"));
        d
    }

    fn weave_code(name: &str) -> PathBuf {
        let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        d.push(format!("./resources/test/pel/{name}.dwl"));
        d
    }

    #[ignore = "currently failing"]
    #[test]
    fn compilation_error() {
        let compilation_result = compile_to_pel_expr("", "uuid(", &InputContext::default());
        assert!(compilation_result.pel.is_none());
        assert_eq!(
            compilation_result.messages.first().unwrap().to_string(),
            "Expecting one of \"!\", \")\", \"[\", \"if\", Identifier, Literal Expression at 5:5"
        );
    }

    #[test]
    fn unknown_input() {
        let compilation_result = compile_to_pel_expr(
            "",
            "test",
            &InputContext {
                inputs: vec!["payload"],
                functions: vec![],
            },
        );
        assert_eq!(
            compilation_result.messages.first().unwrap().to_string(),
            "Unable to resolve reference of: `test`. at 0:4"
        );
    }

    #[test]
    fn invalid_function_input() {
        //dw::core::Strings::substringBefore
        let compilation_result = compile_to_pel_expr(
            "",
            "import substringBefore2 from dw::core::String --- substringBefore2('123','123')",
            &InputContext {
                inputs: vec!["payload"],
                functions: vec!["dw::core::Strings::substringBefore"],
            },
        );
        assert_eq!(
            compilation_result.messages.first().unwrap().to_string(),
            "Unable to resolve reference of: `substringBefore2`. at 50:66"
        );
    }

    fn assert_dw2pel(expression: &str, expected: &str) {
        let functions = vec![
            "dw::Core::++",
            "dw::Core::contains",
            "dw::Core::splitBy",
            "dw::Core::trim",
            "dw::Core::lower",
            "dw::Core::upper",
            "dw::Core::sizeOf",
            "dw::Core::uuid",
            "dw::Core::isEmpty",
            "dw::core::Strings::substringBefore",
            "dw::core::Strings::substringAfter",
            "dw::core::Strings::substringBeforeLast",
            "dw::core::Strings::substringAfterLast",
            "dw::core::Binaries::toBase64",
            "dw::core::Binaries::fromBase64",
        ];

        let compilation_result = compile_to_pel_expr(
            "",
            expression,
            &InputContext {
                inputs: vec!["payload", "attributes"],
                functions,
            },
        );
        assert!(
            compilation_result.messages.is_empty(),
            "{}",
            compilation_result.messages.first().unwrap().to_string()
        );
        assert_eq!(compilation_result.pel.unwrap(), expected)
    }
}