Skip to content

Commit 86a38cc

Browse files
committed
refactor(tests): share object pattern oracle transport
1 parent 1aee3bc commit 86a38cc

6 files changed

Lines changed: 121 additions & 121 deletions

File tree

tests/oracle/object/oracle_object_assignment.rs

Lines changed: 19 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
use std::ffi::OsStr;
2-
use std::process::{Command, Output};
3-
41
use quickjs_oxide::{Context, Runtime, RuntimeError, Value};
52

63
// Pins QuickJS 2026-06-04 ObjectAssignmentPattern lowering. Object binding
@@ -527,8 +524,13 @@ fn object_assignment_operation_stacks_match_pinned_quickjs() {
527524
return;
528525
};
529526
for &(description, source) in STACK_CASES {
530-
let rust = run_cli(env!("CARGO_BIN_EXE_qjs").as_ref(), source, description);
531-
let quickjs = run_cli(&oracle, source, description);
527+
let rust = super::quickjs_object_pattern_oracle::run_cli_exact(
528+
env!("CARGO_BIN_EXE_qjs").as_ref(),
529+
source,
530+
description,
531+
);
532+
let quickjs =
533+
super::quickjs_object_pattern_oracle::run_cli_exact(&oracle, source, description);
532534
assert_eq!(rust.status.code(), quickjs.status.code(), "{description}");
533535
assert_eq!(rust.stdout, quickjs.stdout, "{description}");
534536
assert_eq!(rust.stderr, quickjs.stderr, "{description}");
@@ -543,8 +545,13 @@ fn object_assignment_parser_diagnostics_match_pinned_quickjs() {
543545
};
544546
let mut failures = Vec::new();
545547
for &(description, source) in PARSER_CASES {
546-
let rust = run_cli(env!("CARGO_BIN_EXE_qjs").as_ref(), source, description);
547-
let quickjs = run_cli(&oracle, source, description);
548+
let rust = super::quickjs_object_pattern_oracle::run_cli_exact(
549+
env!("CARGO_BIN_EXE_qjs").as_ref(),
550+
source,
551+
description,
552+
);
553+
let quickjs =
554+
super::quickjs_object_pattern_oracle::run_cli_exact(&oracle, source, description);
548555
if rust.status.code() != quickjs.status.code()
549556
|| rust.stdout != quickjs.stdout
550557
|| rust.stderr != quickjs.stderr
@@ -587,7 +594,11 @@ fn compare_cases(group: &str, cases: &[(&str, &str)]) {
587594
let mut context = runtime.new_context();
588595
assert_eq!(
589596
observe_rust_eval(&runtime, &mut context, source, description),
590-
observe_oracle(&oracle, source, description),
597+
super::quickjs_object_pattern_oracle::observe_completion_strip_one_lf(
598+
&oracle,
599+
source,
600+
description,
601+
),
591602
"{group} drifted for {description}: {source:?}",
592603
);
593604
}
@@ -627,39 +638,6 @@ fn observe_rust_eval(
627638
}
628639
}
629640

630-
fn observe_oracle(oracle: &OsStr, source: &str, description: &str) -> String {
631-
let wrapper = r#"
632-
try {
633-
var value = std.evalScript(scriptArgs[0]);
634-
print('return|' + typeof value + '|' + String(value));
635-
} catch (error) {
636-
if (error !== null && typeof error === 'object')
637-
print('throw|object|' + error.name + '|' + error.message);
638-
else
639-
print('throw|' + typeof error + '|' + String(error));
640-
}
641-
"#;
642-
let output = Command::new(oracle)
643-
.args(["--std", "-e", wrapper, source])
644-
.output()
645-
.unwrap_or_else(|error| panic!("could not run QuickJS for {description}: {error}"));
646-
assert!(
647-
output.status.success(),
648-
"QuickJS observer failed for {description}: {}",
649-
String::from_utf8_lossy(&output.stderr),
650-
);
651-
let stdout = String::from_utf8(output.stdout)
652-
.unwrap_or_else(|error| panic!("QuickJS output was not UTF-8 for {description}: {error}"));
653-
stdout.strip_suffix('\n').unwrap_or(&stdout).to_owned()
654-
}
655-
656-
fn run_cli(program: &OsStr, source: &str, description: &str) -> Output {
657-
Command::new(program)
658-
.args(["-e", source])
659-
.output()
660-
.unwrap_or_else(|error| panic!("could not run CLI for {description}: {error}"))
661-
}
662-
663641
fn error_string_property(
664642
runtime: &Runtime,
665643
context: &mut Context,

tests/oracle/object/oracle_object_bindings.rs

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
use std::ffi::OsStr;
2-
use std::process::Command;
3-
41
use quickjs_oxide::{Context, Runtime, RuntimeError, Value};
52

63
// This target pins the object-binding declaration path shared by direct
@@ -401,8 +398,13 @@ fn object_binding_parser_diagnostics_match_pinned_quickjs() {
401398
return;
402399
};
403400
for &(description, source) in PARSER_CASES {
404-
let rust = run_cli(env!("CARGO_BIN_EXE_qjs").as_ref(), source, description);
405-
let quickjs = run_cli(&oracle, source, description);
401+
let rust = super::quickjs_object_pattern_oracle::run_cli_exact(
402+
env!("CARGO_BIN_EXE_qjs").as_ref(),
403+
source,
404+
description,
405+
);
406+
let quickjs =
407+
super::quickjs_object_pattern_oracle::run_cli_exact(&oracle, source, description);
406408
assert_eq!(rust.status.code(), quickjs.status.code(), "{description}");
407409
assert_eq!(rust.stdout, quickjs.stdout, "{description}");
408410
assert_eq!(rust.stderr, quickjs.stderr, "{description}");
@@ -419,7 +421,11 @@ fn compare_cases(group: &str, cases: &[(&str, &str)]) {
419421
let mut context = runtime.new_context();
420422
assert_eq!(
421423
observe_rust_eval(&runtime, &mut context, source, description),
422-
observe_oracle(&oracle, source, description),
424+
super::quickjs_object_pattern_oracle::observe_completion_strip_one_lf(
425+
&oracle,
426+
source,
427+
description,
428+
),
423429
"{group} drifted for {description}: {source:?}",
424430
);
425431
}
@@ -459,39 +465,6 @@ fn observe_rust_eval(
459465
}
460466
}
461467

462-
fn observe_oracle(oracle: &OsStr, source: &str, description: &str) -> String {
463-
let wrapper = r#"
464-
try {
465-
var value = std.evalScript(scriptArgs[0]);
466-
print('return|' + typeof value + '|' + String(value));
467-
} catch (error) {
468-
if (error !== null && typeof error === 'object')
469-
print('throw|object|' + error.name + '|' + error.message);
470-
else
471-
print('throw|' + typeof error + '|' + String(error));
472-
}
473-
"#;
474-
let output = Command::new(oracle)
475-
.args(["--std", "-e", wrapper, source])
476-
.output()
477-
.unwrap_or_else(|error| panic!("could not run QuickJS for {description}: {error}"));
478-
assert!(
479-
output.status.success(),
480-
"QuickJS observer failed for {description}: {}",
481-
String::from_utf8_lossy(&output.stderr),
482-
);
483-
let stdout = String::from_utf8(output.stdout)
484-
.unwrap_or_else(|error| panic!("QuickJS output was not UTF-8 for {description}: {error}"));
485-
stdout.strip_suffix('\n').unwrap_or(&stdout).to_owned()
486-
}
487-
488-
fn run_cli(program: &OsStr, source: &str, description: &str) -> std::process::Output {
489-
Command::new(program)
490-
.args(["-e", source])
491-
.output()
492-
.unwrap_or_else(|error| panic!("could not run CLI for {description}: {error}"))
493-
}
494-
495468
fn error_string_property(
496469
runtime: &Runtime,
497470
context: &mut Context,

tests/oracle/object/oracle_object_rest.rs

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
use std::ffi::OsStr;
2-
use std::process::{Command, Output};
3-
41
use quickjs_oxide::{Context, Runtime, RuntimeError, Value};
52

63
// Pins QuickJS 2026-06-04 ObjectBindingPattern rest lowering. The excluded-key
@@ -345,8 +342,13 @@ fn object_rest_parser_diagnostics_match_pinned_quickjs() {
345342
return;
346343
};
347344
for &(description, source) in PARSER_CASES {
348-
let rust = run_cli(env!("CARGO_BIN_EXE_qjs").as_ref(), source, description);
349-
let quickjs = run_cli(&oracle, source, description);
345+
let rust = super::quickjs_object_pattern_oracle::run_cli_exact(
346+
env!("CARGO_BIN_EXE_qjs").as_ref(),
347+
source,
348+
description,
349+
);
350+
let quickjs =
351+
super::quickjs_object_pattern_oracle::run_cli_exact(&oracle, source, description);
350352
assert_eq!(rust.status.code(), quickjs.status.code(), "{description}");
351353
assert_eq!(rust.stdout, quickjs.stdout, "{description}");
352354
assert_eq!(rust.stderr, quickjs.stderr, "{description}");
@@ -373,7 +375,11 @@ fn compare_cases(group: &str, cases: &[(&str, &str)]) {
373375
let mut context = runtime.new_context();
374376
assert_eq!(
375377
observe_rust_eval(&runtime, &mut context, source, description),
376-
observe_oracle(&oracle, source, description),
378+
super::quickjs_object_pattern_oracle::observe_completion_strip_one_lf(
379+
&oracle,
380+
source,
381+
description,
382+
),
377383
"{group} drifted for {description}: {source:?}",
378384
);
379385
}
@@ -413,39 +419,6 @@ fn observe_rust_eval(
413419
}
414420
}
415421

416-
fn observe_oracle(oracle: &OsStr, source: &str, description: &str) -> String {
417-
let wrapper = r#"
418-
try {
419-
var value = std.evalScript(scriptArgs[0]);
420-
print('return|' + typeof value + '|' + String(value));
421-
} catch (error) {
422-
if (error !== null && typeof error === 'object')
423-
print('throw|object|' + error.name + '|' + error.message);
424-
else
425-
print('throw|' + typeof error + '|' + String(error));
426-
}
427-
"#;
428-
let output = Command::new(oracle)
429-
.args(["--std", "-e", wrapper, source])
430-
.output()
431-
.unwrap_or_else(|error| panic!("could not run QuickJS for {description}: {error}"));
432-
assert!(
433-
output.status.success(),
434-
"QuickJS observer failed for {description}: {}",
435-
String::from_utf8_lossy(&output.stderr),
436-
);
437-
let stdout = String::from_utf8(output.stdout)
438-
.unwrap_or_else(|error| panic!("QuickJS output was not UTF-8 for {description}: {error}"));
439-
stdout.strip_suffix('\n').unwrap_or(&stdout).to_owned()
440-
}
441-
442-
fn run_cli(program: &OsStr, source: &str, description: &str) -> Output {
443-
Command::new(program)
444-
.args(["-e", source])
445-
.output()
446-
.unwrap_or_else(|error| panic!("could not run CLI for {description}: {error}"))
447-
}
448-
449422
fn error_string_property(
450423
runtime: &Runtime,
451424
context: &mut Context,

tests/oracle_object_semantics.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,61 @@
11
// Keep the Object oracle implementations in separate modules so their private
22
// helpers remain isolated while Cargo builds one integration target.
33

4+
#[path = "support/quickjs_object_pattern_oracle.rs"]
5+
mod quickjs_object_pattern_oracle;
46
#[path = "support/quickjs_oracle.rs"]
57
mod quickjs_oracle;
68

9+
#[cfg(test)]
10+
mod quickjs_object_pattern_oracle_contract {
11+
use super::quickjs_object_pattern_oracle::{observe_completion_strip_one_lf, run_cli_exact};
12+
13+
fn oracle() -> Option<std::ffi::OsString> {
14+
let oracle = std::env::var_os("QJS_ORACLE");
15+
if oracle.is_none() {
16+
eprintln!(
17+
"SKIP object-pattern oracle helper regressions: set QJS_ORACLE to upstream qjs"
18+
);
19+
}
20+
oracle
21+
}
22+
23+
#[test]
24+
fn completion_removes_only_the_print_line_feed() {
25+
let Some(oracle) = oracle() else {
26+
return;
27+
};
28+
assert_eq!(
29+
observe_completion_strip_one_lf(
30+
&oracle,
31+
"'tail \\n\\t'",
32+
"object-pattern trailing whitespace",
33+
),
34+
"return|string|tail \n\t",
35+
);
36+
}
37+
38+
#[test]
39+
fn exact_cli_keeps_stdout_and_cmdline_diagnostics() {
40+
let Some(oracle) = oracle() else {
41+
return;
42+
};
43+
44+
let success = run_cli_exact(&oracle, "print('ok')", "successful raw CLI contract");
45+
assert!(success.status.success());
46+
assert_eq!(String::from_utf8(success.stdout).unwrap(), "ok\n");
47+
assert!(success.stderr.is_empty());
48+
49+
let syntax = run_cli_exact(&oracle, "let {", "syntax raw CLI contract");
50+
assert!(!syntax.status.success());
51+
assert_eq!(syntax.status.code(), Some(1));
52+
assert!(syntax.stdout.is_empty());
53+
let stderr = String::from_utf8(syntax.stderr).unwrap();
54+
assert!(stderr.contains("SyntaxError: variable name expected"));
55+
assert!(stderr.contains("at <cmdline>:1:5"));
56+
}
57+
}
58+
759
#[path = "oracle/object/oracle_object_accessors.rs"]
860
mod oracle_object_accessors;
961
#[path = "oracle/object/oracle_object_assign.rs"]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use std::ffi::OsStr;
2+
use std::process::{Command, Output};
3+
4+
pub(super) fn observe_completion_strip_one_lf(
5+
oracle: &OsStr,
6+
source: &str,
7+
description: &str,
8+
) -> String {
9+
let stdout = super::quickjs_oracle::observe_completion_output(oracle, source, description);
10+
stdout.strip_suffix('\n').unwrap_or(&stdout).to_owned()
11+
}
12+
13+
// Keep source in argv so parser diagnostics retain qjs's <cmdline> filename,
14+
// line and column behavior. Callers compare the complete process result.
15+
pub(super) fn run_cli_exact(program: &OsStr, source: &str, description: &str) -> Output {
16+
Command::new(program)
17+
.args(["-e", source])
18+
.output()
19+
.unwrap_or_else(|error| panic!("could not run CLI for {description}: {error}"))
20+
}

tests/support/quickjs_oracle.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ const STD_LINES_EVALUATOR: &str = r#"
2727
"#;
2828

2929
pub(super) fn observe_completion(oracle: &OsStr, source: &str, description: &str) -> String {
30+
observe_completion_output(oracle, source, description)
31+
.trim_end()
32+
.to_owned()
33+
}
34+
35+
pub(super) fn observe_completion_output(oracle: &OsStr, source: &str, description: &str) -> String {
3036
run_stdin_utf8(
3137
oracle,
3238
COMPLETION_OBSERVER,
@@ -35,8 +41,6 @@ pub(super) fn observe_completion(oracle: &OsStr, source: &str, description: &str
3541
description,
3642
"observer",
3743
)
38-
.trim_end()
39-
.to_owned()
4044
}
4145

4246
pub(super) fn eval_std_lines(oracle: &OsStr, source: &str, description: &str) -> Vec<String> {

0 commit comments

Comments
 (0)