bun_runtime 0.1.0

Bao runtime integration — JS engine + Bun API + event loop
// @trace REQ-ENG-007 [level:integration]
// Conformance tests for node:util against Node.js / Bun reference behavior.
// Reference: ~/code/rust/bun/test/js/node/util/ (MIT, Bun project)

#[path = "../conformance_common.rs"]
mod common;

use common::{CHECK_SCAFFOLD, make_ctx, run_checks};

#[test]
fn test_util_conformance_suite() {
    let mut ctx = make_ctx();

    // ===== isXxx predicates =====
    let src = format!(
        r##"
        {scaffold}
        var util = require('util');
        check("isString", function() {{ return util.isString("a") === true && util.isString(1) === false; }});
        check("isNumber", function() {{ return util.isNumber(1) === true && util.isNumber("1") === false; }});
        check("isBoolean", function() {{ return util.isBoolean(true) === true && util.isBoolean(1) === false; }});
        check("isFunction", function() {{ return util.isFunction(function(){{}}) === true; }});
        check("isObject", function() {{ return util.isObject({{}}) === true && util.isObject(null) === false; }});
        check("isArray", function() {{ return util.isArray([]) === true && util.isArray({{}}) === false; }});
        check("isNull", function() {{ return util.isNull(null) === true && util.isNull(undefined) === false; }});
        check("isUndefined", function() {{ return util.isUndefined(undefined) === true && util.isUndefined(null) === false; }});
        check("isDate", function() {{ return util.isDate(new Date()) === true; }});
        check("isRegExp", function() {{ return util.isRegExp(/x/) === true; }});
        check("isError", function() {{ return util.isError(new Error()) === true; }});
        check("isSymbol", function() {{ return util.isSymbol(Symbol()) === true; }});
        results.join("|")
        "##,
        scaffold = CHECK_SCAFFOLD
    );
    run_checks(&mut ctx, &src);

    // ===== inspect =====
    // NOTE: bao_runtime's util.inspect returns "[Object]" for plain objects
    // instead of the property listing Node.js produces. Documented in GAP_REPORT.
    let src = format!(
        r##"
        {scaffold}
        var util = require('util');
        check("inspect_string", function() {{
            var s = util.inspect("hello");
            return typeof s === "string" && s.indexOf("hello") >= 0;
        }});
        check("inspect_object_returns_string", function() {{
            // bao deviation: returns "[Object]" not the property listing
            return typeof util.inspect({{a: 1}}) === "string";
        }});
        check("inspect_array", function() {{
            var s = util.inspect([1, 2, 3]);
            return typeof s === "string" && s.length > 0;
        }});
        check("inspect_null", function() {{
            return util.inspect(null) === "null" || util.inspect(null).indexOf("null") >= 0;
        }});
        results.join("|")
        "##,
        scaffold = CHECK_SCAFFOLD
    );
    run_checks(&mut ctx, &src);

    // ===== format =====
    let src = format!(
        r##"
        {scaffold}
        var util = require('util');
        check("format_no_specifier", function() {{
            return util.format("plain") === "plain";
        }});
        check("format_percent_s", function() {{
            var r = util.format("%s world", "hello");
            return typeof r === "string" && r.indexOf("hello") >= 0;
        }});
        check("format_percent_d", function() {{
            var r = util.format("%d", 42);
            return r.indexOf("42") >= 0;
        }});
        check("format_extra_args_appended", function() {{
            var r = util.format("a", "b", "c");
            return r.indexOf("a") >= 0 && r.indexOf("b") >= 0;
        }});
        results.join("|")
        "##,
        scaffold = CHECK_SCAFFOLD
    );
    run_checks(&mut ctx, &src);

    // ===== promisify / callbackify =====
    let src = format!(
        r##"
        {scaffold}
        var util = require('util');
        check("promisify_is_function", function() {{
            return typeof util.promisify === "function";
        }});
        check("callbackify_is_function", function() {{
            return typeof util.callbackify === "function";
        }});
        check("promisify_returns_function_deviation", function() {{
            // bao deviation: promisify returns a function, not a thenable/Promise.
            // Documented in GAP_REPORT. Just verify it doesn't crash.
            function cbStyle(x, cb) {{ setImmediate(function() {{ cb(null, x * 2); }}); }}
            var p = util.promisify(cbStyle);
            return typeof p === "function" || (p && typeof p.then === "function");
        }});
        results.join("|")
        "##,
        scaffold = CHECK_SCAFFOLD
    );
    run_checks(&mut ctx, &src);

    // ===== isDeepStrictEqual =====
    // NOTE: bao_runtime's isDeepStrictEqual only works for primitives, not objects.
    // Documented in GAP_REPORT.
    let src = format!(
        r##"
        {scaffold}
        var util = require('util');
        check("isDeepStrictEqual_primitives_same", function() {{
            return util.isDeepStrictEqual(1, 1) === true;
        }});
        check("isDeepStrictEqual_primitives_diff", function() {{
            return util.isDeepStrictEqual(1, 2) === false;
        }});
        check("isDeepStrictEqual_strict_types", function() {{
            return util.isDeepStrictEqual(1, "1") === false;
        }});
        results.join("|")
        "##,
        scaffold = CHECK_SCAFFOLD
    );
    run_checks(&mut ctx, &src);

    // ===== util.types submodule =====
    let src = format!(
        r##"
        {scaffold}
        var util = require('util');
        check("types_exists", function() {{
            return typeof util.types === "object";
        }});
        check("types_isPromise", function() {{
            return util.types.isPromise(Promise.resolve()) === true;
        }});
        check("types_isNativeError", function() {{
            return util.types.isNativeError(new Error()) === true;
        }});
        results.join("|")
        "##,
        scaffold = CHECK_SCAFFOLD
    );
    run_checks(&mut ctx, &src);

    // ===== misc =====
    let src = format!(
        r##"
        {scaffold}
        var util = require('util');
        check("deprecate_is_function", function() {{
            return typeof util.deprecate === "function";
        }});
        check("inherits_is_function", function() {{
            return typeof util.inherits === "function";
        }});
        check("getSystemErrorName_is_function", function() {{
            return typeof util.getSystemErrorName === "function";
        }});
        check("parseArgs_is_function", function() {{
            return typeof util.parseArgs === "function";
        }});
        results.join("|")
        "##,
        scaffold = CHECK_SCAFFOLD
    );
    run_checks(&mut ctx, &src);

    bun_runtime::shutdown_thread_sm();
}

#[test]
fn test_util_conformance_types_extras() {
    let mut ctx = make_ctx();
    let src = format!(
        r##"
        {scaffold}
        var util = require('util');
        check("types_isExternal", function() {{
            return typeof util.types.isExternal === "function";
        }});
        results.join("|")
        "##,
        scaffold = CHECK_SCAFFOLD
    );
    run_checks(&mut ctx, &src);
    bun_runtime::shutdown_thread_sm();
}

#[test]
fn test_util_conformance_style_text() {
    let mut ctx = make_ctx();
    let src = format!(
        r##"
        {scaffold}
        var util = require('util');
        check("styleText_exists", function() {{
            return typeof util.styleText === "function";
        }});
        results.join("|")
        "##,
        scaffold = CHECK_SCAFFOLD
    );
    run_checks(&mut ctx, &src);
    bun_runtime::shutdown_thread_sm();
}

#[test]
fn test_util_conformance_inspect_object_properties() {
    let mut ctx = make_ctx();
    use common::eval_string;
    let r = eval_string(
        &mut ctx,
        r##"require('util').inspect({a: 1}).indexOf("a") >= 0 ? "PASS" : "FAIL""##,
    );
    assert_eq!(r, "PASS");
    bun_runtime::shutdown_thread_sm();
}

#[test]
fn test_util_conformance_promisify_deviation() {
    let mut ctx = make_ctx();
    use common::eval_string;
    let r = eval_string(
        &mut ctx,
        r##"(function(){
            var p = require('util').promisify(function(cb){ cb(null, 1); });
            return (p && typeof p.then === "function") ? "PASS" : "FAIL";
        })()"##,
    );
    assert_eq!(r, "PASS");
    bun_runtime::shutdown_thread_sm();
}

#[test]
fn test_util_conformance_deep_strict_equal_object_deviation() {
    let mut ctx = make_ctx();
    use common::eval_string;
    let r = eval_string(
        &mut ctx,
        r##"require('util').isDeepStrictEqual({a: 1}, {a: 1}) === true ? "PASS" : "FAIL""##,
    );
    assert_eq!(r, "PASS");
    bun_runtime::shutdown_thread_sm();
}