mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-19 14:57:15 +03:00
add stdin support for cli tests (currently unused)
This commit is contained in:
parent
999f3cfce6
commit
4bd9d417d1
@ -23,6 +23,24 @@ mod cli_run {
|
||||
flags: &[&str],
|
||||
expected_ending: &str,
|
||||
use_valgrind: bool,
|
||||
) {
|
||||
check_output_with_stdin(
|
||||
file,
|
||||
"",
|
||||
executable_filename,
|
||||
flags,
|
||||
expected_ending,
|
||||
use_valgrind,
|
||||
)
|
||||
}
|
||||
|
||||
fn check_output_with_stdin(
|
||||
file: &Path,
|
||||
stdin_str: &str,
|
||||
executable_filename: &str,
|
||||
flags: &[&str],
|
||||
expected_ending: &str,
|
||||
use_valgrind: bool,
|
||||
) {
|
||||
let compile_out = run_roc(&[&["build", file.to_str().unwrap()], flags].concat());
|
||||
if !compile_out.stderr.is_empty() {
|
||||
@ -31,8 +49,10 @@ mod cli_run {
|
||||
assert!(compile_out.status.success());
|
||||
|
||||
let out = if use_valgrind {
|
||||
let (valgrind_out, raw_xml) =
|
||||
run_with_valgrind(&[file.with_file_name(executable_filename).to_str().unwrap()]);
|
||||
let (valgrind_out, raw_xml) = run_with_valgrind(
|
||||
stdin_str,
|
||||
&[file.with_file_name(executable_filename).to_str().unwrap()],
|
||||
);
|
||||
|
||||
if valgrind_out.status.success() {
|
||||
let memory_errors = extract_valgrind_errors(&raw_xml).unwrap_or_else(|err| {
|
||||
@ -55,6 +75,7 @@ mod cli_run {
|
||||
} else {
|
||||
run_cmd(
|
||||
file.with_file_name(executable_filename).to_str().unwrap(),
|
||||
stdin_str,
|
||||
&[],
|
||||
)
|
||||
};
|
||||
@ -174,8 +195,9 @@ mod cli_run {
|
||||
#[test]
|
||||
#[serial(nqueens)]
|
||||
fn run_nqueens_not_optimized() {
|
||||
check_output(
|
||||
check_output_with_stdin(
|
||||
&example_file("benchmarks", "NQueens.roc"),
|
||||
"",
|
||||
"nqueens",
|
||||
&[],
|
||||
"4\n",
|
||||
|
@ -61,15 +61,29 @@ pub fn run_roc(args: &[&str]) -> Out {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn run_cmd(cmd_name: &str, args: &[&str]) -> Out {
|
||||
pub fn run_cmd(cmd_name: &str, stdin_str: &str, args: &[&str]) -> Out {
|
||||
let mut cmd = Command::new(cmd_name);
|
||||
|
||||
for arg in args {
|
||||
cmd.arg(arg);
|
||||
}
|
||||
|
||||
let output = cmd
|
||||
.output()
|
||||
let mut child = cmd
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap_or_else(|_| panic!("failed to execute cmd `{}` in CLI test", cmd_name));
|
||||
|
||||
{
|
||||
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
||||
stdin
|
||||
.write_all(stdin_str.as_bytes())
|
||||
.expect("Failed to write to stdin");
|
||||
}
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.unwrap_or_else(|_| panic!("failed to execute cmd `{}` in CLI test", cmd_name));
|
||||
|
||||
Out {
|
||||
@ -80,7 +94,7 @@ pub fn run_cmd(cmd_name: &str, args: &[&str]) -> Out {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn run_with_valgrind(args: &[&str]) -> (Out, String) {
|
||||
pub fn run_with_valgrind(stdin_str: &str, args: &[&str]) -> (Out, String) {
|
||||
//TODO: figure out if there is a better way to get the valgrind executable.
|
||||
let mut cmd = Command::new("valgrind");
|
||||
let named_tempfile =
|
||||
@ -114,8 +128,23 @@ pub fn run_with_valgrind(args: &[&str]) -> (Out, String) {
|
||||
cmd.arg(arg);
|
||||
}
|
||||
|
||||
let output = cmd
|
||||
.output()
|
||||
cmd.stdin(Stdio::piped());
|
||||
cmd.stdout(Stdio::piped());
|
||||
cmd.stderr(Stdio::piped());
|
||||
|
||||
let mut child = cmd
|
||||
.spawn()
|
||||
.expect("failed to execute compiled `valgrind` binary in CLI test");
|
||||
|
||||
{
|
||||
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
||||
stdin
|
||||
.write_all(stdin_str.as_bytes())
|
||||
.expect("Failed to write to stdin");
|
||||
}
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.expect("failed to execute compiled `valgrind` binary in CLI test");
|
||||
|
||||
let mut file = named_tempfile.into_file();
|
||||
|
@ -1791,14 +1791,12 @@ fn update<'a>(
|
||||
|
||||
Proc::insert_refcount_operations(arena, &mut state.procedures);
|
||||
|
||||
if false {
|
||||
Proc::optimize_refcount_operations(
|
||||
arena,
|
||||
module_id,
|
||||
&mut ident_ids,
|
||||
&mut state.procedures,
|
||||
);
|
||||
}
|
||||
Proc::optimize_refcount_operations(
|
||||
arena,
|
||||
module_id,
|
||||
&mut ident_ids,
|
||||
&mut state.procedures,
|
||||
);
|
||||
|
||||
state.constrained_ident_ids.insert(module_id, ident_ids);
|
||||
|
||||
|
@ -5,6 +5,7 @@ app "nqueens"
|
||||
|
||||
main : Task.Task {} []
|
||||
main =
|
||||
# Task.after Task.getInt \n ->
|
||||
queens 6
|
||||
|> Str.fromInt
|
||||
|> Task.putLine
|
||||
|
@ -6,7 +6,8 @@ platform folkertdev/foo
|
||||
provides [ mainForHost ]
|
||||
effects Effect
|
||||
{
|
||||
putLine : Str -> Effect {}
|
||||
putLine : Str -> Effect {},
|
||||
getInt : Effect { value: I64, errorCode: [ A, B ], isError: Bool }
|
||||
}
|
||||
|
||||
mainForHost : Task.Task {} [] as Fx
|
||||
|
@ -1,5 +1,5 @@
|
||||
interface Task
|
||||
exposes [ Task, succeed, fail, after, map, putLine ]
|
||||
exposes [ Task, succeed, fail, after, map, putLine, getInt ]
|
||||
imports [ Effect ]
|
||||
|
||||
|
||||
@ -15,7 +15,6 @@ fail : err -> Task * err
|
||||
fail = \val ->
|
||||
Effect.always (Err val)
|
||||
|
||||
|
||||
after : Task a err, (a -> Task b err) -> Task b err
|
||||
after = \effect, transform ->
|
||||
Effect.after effect \result ->
|
||||
@ -32,3 +31,16 @@ map = \effect, transform ->
|
||||
|
||||
putLine : Str -> Task {} *
|
||||
putLine = \line -> Effect.map (Effect.putLine line) (\_ -> Ok {})
|
||||
|
||||
getInt : Task I64 []
|
||||
getInt =
|
||||
Effect.after Effect.getInt \{ isError, value, errorCode } ->
|
||||
when isError is
|
||||
True ->
|
||||
when errorCode is
|
||||
# A -> Task.fail InvalidCharacter
|
||||
# B -> Task.fail IOError
|
||||
_ -> Task.succeed -1
|
||||
|
||||
False ->
|
||||
Task.succeed value
|
||||
|
@ -4,6 +4,7 @@ const RocStr = str.RocStr;
|
||||
const testing = std.testing;
|
||||
const expectEqual = testing.expectEqual;
|
||||
const expect = testing.expect;
|
||||
const maxInt = std.math.maxInt;
|
||||
|
||||
const mem = std.mem;
|
||||
const Allocator = mem.Allocator;
|
||||
@ -96,3 +97,39 @@ pub export fn roc_fx_putLine(rocPath: str.RocStr) i64 {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const GetInt = extern struct {
|
||||
value: i64,
|
||||
error_code: u8,
|
||||
is_error: bool,
|
||||
};
|
||||
|
||||
pub export fn roc_fx_getInt() GetInt {
|
||||
if (roc_fx_getInt_help()) |value| {
|
||||
const get_int = GetInt{ .is_error = false, .value = value, .error_code = 0 };
|
||||
return get_int;
|
||||
} else |err| switch (err) {
|
||||
error.InvalidCharacter => {
|
||||
return GetInt{ .is_error = true, .value = 0, .error_code = 0 };
|
||||
},
|
||||
else => {
|
||||
return GetInt{ .is_error = true, .value = 0, .error_code = 1 };
|
||||
},
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn roc_fx_getInt_help() !i64 {
|
||||
const stdin = std.io.getStdIn().inStream();
|
||||
var buf: [40]u8 = undefined;
|
||||
|
||||
const line: []u8 = (try stdin.readUntilDelimiterOrEof(&buf, '\n')) orelse "";
|
||||
|
||||
return std.fmt.parseInt(i64, line, 10);
|
||||
}
|
||||
|
||||
fn readLine() []u8 {
|
||||
const stdin = std.io.getStdIn().reader();
|
||||
return (stdin.readUntilDelimiterOrEof(&line_buf, '\n') catch unreachable) orelse "";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user