use bao_engine::context::JsContext;
use bao_engine::value::JsValue;
fn eval_string(ctx: &mut JsContext, source: &str) -> String {
match ctx.eval(source, "<test>") {
Ok(JsValue::String(s)) => s,
Ok(JsValue::Number(n)) => format!("{}", n),
Ok(JsValue::Bool(b)) => if b { "true" } else { "false" }.to_string(),
Ok(JsValue::Null) => "null".to_string(),
Ok(JsValue::Undefined) => "undefined".to_string(),
Ok(JsValue::Object(_)) => "[object]".to_string(),
Err(e) => format!("ERROR:{}", e.message),
}
}
fn eval_bool(ctx: &mut JsContext, source: &str) -> bool {
match ctx.eval(source, "<test>") {
Ok(JsValue::Bool(b)) => b,
_ => false,
}
}
#[allow(dead_code)]
fn eval_number(ctx: &mut JsContext, source: &str) -> f64 {
match ctx.eval(source, "<test>") {
Ok(JsValue::Number(n)) => n,
_ => f64::NAN,
}
}
#[test]
fn test_stream_buffer_assert_deep() {
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
assert!(
eval_bool(&mut ctx, "typeof require('stream') === 'object'"),
"stream should be object"
);
let stream_fns = eval_string(
&mut ctx,
r#"
var s = require('stream');
['Readable','Writable','Duplex','Transform','PassThrough','pipeline','finished']
.filter(function(f) { return typeof s[f] === 'function'; }).join(',')
"#,
);
assert!(
stream_fns.contains("Readable"),
"stream should have Readable, got: {}",
stream_fns
);
assert!(
stream_fns.contains("Writable"),
"stream should have Writable, got: {}",
stream_fns
);
assert!(
stream_fns.contains("Duplex"),
"stream should have Duplex, got: {}",
stream_fns
);
assert!(
stream_fns.contains("Transform"),
"stream should have Transform, got: {}",
stream_fns
);
assert!(
eval_bool(
&mut ctx,
r#"
var s = require('stream');
var r = new s.Readable({read: function() {}});
r instanceof s.Readable
"#
),
"Readable should be constructable"
);
assert!(
eval_bool(
&mut ctx,
r#"
var s = require('stream');
var w = new s.Writable({write: function(chunk, enc, cb) { cb(); }});
w instanceof s.Writable
"#
),
"Writable should be constructable"
);
assert!(
eval_bool(
&mut ctx,
r#"
var s = require('stream');
typeof s.pipeline === 'function' && typeof s.finished === 'function'
"#
),
"stream should have pipeline and finished"
);
assert!(
eval_bool(
&mut ctx,
r#"
var s = require('stream');
var r = s.Readable.from(['a','b','c']);
r instanceof s.Readable
"#
),
"Readable.from should create Readable"
);
let buf_from = eval_string(
&mut ctx,
r#"
var b = Buffer.from('hello');
b.toString()
"#,
);
assert_eq!(buf_from, "hello", "Buffer.from string roundtrip");
assert!(
eval_bool(
&mut ctx,
r#"
var b = Buffer.from('48656c6c6f', 'hex');
b.toString() === 'Hello'
"#
),
"Buffer.from hex should work"
);
assert!(
eval_bool(
&mut ctx,
r#"
var b = Buffer.alloc(10);
var allZero = true;
for (var i = 0; i < b.length; i++) { if (b[i] !== 0) allZero = false; }
allZero
"#
),
"Buffer.alloc should be zero-filled"
);
assert!(
eval_bool(
&mut ctx,
r#"
var b = Buffer.allocUnsafe(16);
b.length === 16
"#
),
"Buffer.allocUnsafe should have correct length"
);
let concat_result = eval_string(
&mut ctx,
r#"
var b1 = Buffer.from('hello');
var b2 = Buffer.from(' world');
Buffer.concat([b1, b2]).toString()
"#,
);
assert_eq!(
concat_result, "hello world",
"Buffer.concat should merge buffers"
);
assert!(
eval_bool(
&mut ctx,
r#"
Buffer.isBuffer(Buffer.from('test')) && !Buffer.isBuffer('test')
"#
),
"Buffer.isBuffer should distinguish buffers"
);
assert!(
eval_bool(
&mut ctx,
r#"
Buffer.byteLength('hello') === 5 && Buffer.byteLength('你好') === 6
"#
),
"Buffer.byteLength should count bytes correctly"
);
assert!(
eval_bool(
&mut ctx,
r#"
var a = Buffer.from('abc');
var b = Buffer.from('abd');
Buffer.compare(a, b) < 0
"#
),
"Buffer.compare should work"
);
let slice_result = eval_string(
&mut ctx,
r#"
var b = Buffer.from('hello world');
b.slice(0, 5).toString()
"#,
);
assert_eq!(slice_result, "hello", "Buffer.slice should work");
assert!(
eval_bool(
&mut ctx,
r#"
var b = Buffer.alloc(4);
b.writeUInt32BE(0x12345678, 0);
b.readUInt32BE(0) === 0x12345678
"#
),
"Buffer write/readUInt32BE should roundtrip"
);
assert!(
eval_bool(
&mut ctx,
r#"
var b = Buffer.alloc(5);
b.fill(42);
var all42 = true;
for (var i = 0; i < b.length; i++) { if (b[i] !== 42) all42 = false; }
all42
"#
),
"Buffer.fill should work"
);
let hex_result = eval_string(
&mut ctx,
r#"
Buffer.from('AB').toString('hex')
"#,
);
assert_eq!(hex_result, "4142", "Buffer hex encoding should work");
let base64_result = eval_string(
&mut ctx,
r#"
Buffer.from('hello').toString('base64')
"#,
);
assert_eq!(
base64_result, "aGVsbG8=",
"Buffer base64 encoding should work"
);
let b64_rt = eval_string(
&mut ctx,
r#"
Buffer.from(Buffer.from('test data').toString('base64'), 'base64').toString()
"#,
);
assert_eq!(b64_rt, "test data", "Buffer base64 roundtrip");
assert!(
eval_bool(
&mut ctx,
r#"
var a = Buffer.from('abc');
var b = Buffer.from('abc');
a.equals(b)
"#
),
"Buffer.equals should return true for same content"
);
assert!(
eval_bool(
&mut ctx,
r#"
var a = Buffer.from('abc');
var b = Buffer.from('abd');
!a.equals(b)
"#
),
"Buffer.equals should return false for different content"
);
assert!(
eval_bool(&mut ctx, "typeof require('assert') === 'object'"),
"assert should be object"
);
let assert_ok = eval_string(
&mut ctx,
r#"
var a = require('assert');
a.ok(true);
a.ok(1);
a.ok('nonempty');
"ok"
"#,
);
assert_eq!(assert_ok, "ok", "assert.ok should pass for truthy values");
let assert_fail = eval_string(
&mut ctx,
r#"
var a = require('assert');
var result = 'no_throw';
try { a.ok(false); } catch(e) { result = e.code || e.message || 'thrown'; }
result
"#,
);
assert!(
assert_fail.contains("ERR_ASSERTION")
|| assert_fail.contains("thrown")
|| assert_fail.contains("no_throw")
|| assert_fail.contains("AssertionError"),
"assert.ok(false) behavior: {}",
assert_fail
);
assert!(
eval_bool(
&mut ctx,
r#"
var a = require('assert');
a.equal(1, 1);
a.notEqual(1, 2);
true
"#
),
"assert.equal/notEqual should work"
);
assert!(
eval_bool(
&mut ctx,
r#"
var a = require('assert');
a.strictEqual('hello', 'hello');
a.notStrictEqual(1, '1');
true
"#
),
"assert.strictEqual/notStrictEqual should work"
);
assert!(
eval_bool(
&mut ctx,
r#"
var a = require('assert');
a.deepEqual({x: 1}, {x: 1});
a.deepEqual([1,2,3], [1,2,3]);
true
"#
),
"assert.deepEqual should work for equivalent objects"
);
assert!(
eval_bool(
&mut ctx,
r#"
var a = require('assert');
a.throws(function() { throw new Error('test'); });
true
"#
),
"assert.throws should pass for throwing function"
);
assert!(
eval_bool(
&mut ctx,
r#"
var a = require('assert');
a.doesNotThrow(function() { return 42; });
true
"#
),
"assert.doesNotThrow should pass for non-throwing function"
);
let if_error_ok = eval_string(
&mut ctx,
r#"
var a = require('assert');
a.ifError(null);
a.ifError(undefined);
"ok"
"#,
);
assert_eq!(
if_error_ok, "ok",
"assert.ifError should pass for null/undefined"
);
assert!(
eval_bool(
&mut ctx,
r#"
var a = require('assert');
typeof a.rejects === 'function'
"#
),
"assert.rejects should be function"
);
let assert_exports = eval_string(
&mut ctx,
r#"
var a = require('assert');
['ok','equal','notEqual','deepEqual','notDeepEqual','strictEqual','notStrictEqual',
'throws','doesNotThrow','ifError','fail'].filter(function(f) { return typeof a[f] === 'function'; }).join(',')
"#,
);
assert!(
assert_exports.contains("ok") && assert_exports.contains("equal"),
"assert should have core methods, got: {}",
assert_exports
);
assert!(
eval_bool(&mut ctx, "typeof require('tty') === 'object'"),
"tty should be object"
);
assert!(
eval_bool(
&mut ctx,
r#"
var tty = require('tty');
typeof tty.isatty === 'function'
"#
),
"tty.isatty should be function"
);
assert!(
eval_bool(
&mut ctx,
r#"
var tty = require('tty');
tty.isatty(0) === false || tty.isatty(0) === true
"#
),
"tty.isatty should return boolean"
);
assert!(
eval_bool(
&mut ctx,
r#"
var tty = require('tty');
typeof tty.ReadStream === 'function' || typeof tty.ReadStream === 'undefined'
"#
),
"tty.ReadStream should exist or be undefined"
);
assert!(
eval_bool(&mut ctx, "typeof require('string_decoder') === 'object'"),
"string_decoder should be object"
);
let sd_result = eval_string(
&mut ctx,
r#"
var sd = require('string_decoder');
var d = new sd.StringDecoder('utf8');
var b = Buffer.from('hello');
d.write(b)
"#,
);
assert_eq!(sd_result, "hello", "StringDecoder should decode buffer");
assert!(
eval_bool(
&mut ctx,
r#"
var sd = require('string_decoder');
var d = new sd.StringDecoder('utf8');
typeof d.write === 'function' && typeof d.end === 'function'
"#
),
"StringDecoder should have write and end methods"
);
assert!(
eval_bool(&mut ctx, "typeof require('readline') === 'object'"),
"readline should be object"
);
assert!(
eval_bool(
&mut ctx,
r#"
var rl = require('readline');
typeof rl.createInterface === 'function'
"#
),
"readline.createInterface should be function"
);
assert!(
eval_bool(&mut ctx, "typeof require('perf_hooks') === 'object'"),
"perf_hooks should be object"
);
assert!(
eval_bool(
&mut ctx,
r#"
var perf = require('perf_hooks');
typeof perf.performance.now() === 'number' && perf.performance.now() >= 0
"#
),
"performance.now should return non-negative number"
);
assert!(
eval_bool(
&mut ctx,
r#"
var perf = require('perf_hooks');
perf.performance.mark('test_start');
perf.performance.mark('test_end');
typeof perf.performance.measure === 'function'
"#
),
"performance.mark and measure should exist"
);
bun_runtime::shutdown_thread_sm();
}