nushell/tests/nu_repl/mod.rs
Jakub Žádník 07ac3c3aab
Add Nushell REPL simulator; Fix bug in overlay add (#5478)
* Add Nushell REPL simulator; Fix bug in overlay add

The `nu_repl` function takes an array of strings and processes them as
if they were REPL lines entered one by one. This helps to discover bugs
due to the state changes between the parse and eval stages.

* Fix REPL tests on Windows
2022-05-08 16:09:39 +03:00

97 lines
2.9 KiB
Rust

use nu_command::create_default_context;
use nu_engine::eval_block;
use nu_parser::parse;
use nu_protocol::engine::{Stack, StateDelta, StateWorkingSet};
use nu_protocol::{PipelineData, Span, Value};
use nu_test_support::fs::in_directory;
use nu_test_support::Outcome;
fn outcome_err(msg: String) -> Outcome {
Outcome {
out: String::new(),
err: msg,
}
}
fn outcome_ok(msg: String) -> Outcome {
Outcome {
out: msg,
err: String::new(),
}
}
pub fn nu_repl(cwd: &str, source_lines: &[&str]) -> Outcome {
let cwd = in_directory(cwd);
let mut engine_state = create_default_context(&cwd);
let mut stack = Stack::new();
stack.add_env_var(
"PWD".to_string(),
Value::String {
val: cwd.to_string(),
span: Span::test_data(),
},
);
let delta = StateDelta::new(&engine_state);
if let Err(err) = engine_state.merge_delta(delta, Some(&mut stack), cwd) {
return outcome_err(format!("{:?}", &err));
}
let mut last_output = String::new();
for (i, line) in source_lines.iter().enumerate() {
let (block, delta) = {
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(
&mut working_set,
Some(&format!("line{}", i)),
line.as_bytes(),
false,
&[],
);
if let Some(err) = err {
return outcome_err(format!("{:?}", err));
}
(block, working_set.render())
};
let cwd = match nu_engine::env::current_dir(&engine_state, &stack) {
Ok(p) => p,
Err(e) => {
return outcome_err(format!("{:?}", &e));
}
};
if let Err(err) = engine_state.merge_delta(delta, Some(&mut stack), &cwd) {
return outcome_err(format!("{:?}", err));
}
let input = PipelineData::new(Span::test_data());
let config = engine_state.get_config();
match eval_block(&engine_state, &mut stack, &block, input, false, false) {
Ok(pipeline_data) => match pipeline_data.collect_string("", config) {
Ok(s) => last_output = s,
Err(err) => return outcome_err(format!("{:?}", err)),
},
Err(err) => return outcome_err(format!("{:?}", err)),
}
// FIXME: permanent state changes like this hopefully in time can be removed
// and be replaced by just passing the cwd in where needed
if let Some(cwd) = stack.get_env_var(&engine_state, "PWD") {
let path = match cwd.as_string() {
Ok(p) => p,
Err(err) => return outcome_err(format!("{:?}", err)),
};
let _ = std::env::set_current_dir(path);
engine_state.add_env_var("PWD".into(), cwd);
}
}
outcome_ok(last_output)
}