nushell/crates/nu-parser/tests/test_parser.rs

668 lines
19 KiB
Rust
Raw Normal View History

2021-09-02 10:25:22 +02:00
use nu_parser::ParseError;
2021-08-30 20:36:07 +02:00
use nu_parser::*;
2021-09-02 20:21:37 +02:00
use nu_protocol::{
ast::{Expr, Expression},
2021-10-25 08:31:39 +02:00
engine::{Command, EngineState, Stack, StateWorkingSet},
2021-09-02 20:21:37 +02:00
Signature, SyntaxShape,
};
2021-08-30 20:36:07 +02:00
2021-09-13 10:19:05 +02:00
#[cfg(test)]
2021-10-25 06:01:02 +02:00
#[derive(Clone)]
2021-09-13 10:19:05 +02:00
pub struct Let;
#[cfg(test)]
impl Command for Let {
fn name(&self) -> &str {
"let"
}
fn usage(&self) -> &str {
"Create a variable and give it a value."
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build("let")
.required("var_name", SyntaxShape::VarWithOptType, "variable name")
.required(
"initial_value",
SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::Expression)),
"equals sign followed by value",
)
}
fn run(
&self,
2021-10-25 08:31:39 +02:00
_engine_state: &EngineState,
_stack: &mut Stack,
2021-09-13 10:19:05 +02:00
_call: &nu_protocol::ast::Call,
2021-10-25 06:01:02 +02:00
_input: nu_protocol::PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
2021-09-13 10:19:05 +02:00
todo!()
}
}
2021-08-30 20:36:07 +02:00
#[test]
pub fn parse_int() {
2021-09-02 10:25:22 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-08-30 20:36:07 +02:00
let (block, err) = parse(&mut working_set, None, b"3", true, &[]);
2021-08-30 20:36:07 +02:00
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Int(3),
..
2021-09-03 04:15:01 +02:00
}
))
2021-08-30 20:36:07 +02:00
}
#[test]
pub fn parse_binary_with_hex_format() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"0x[13]", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert_eq!(expressions[0].expr, Expr::Binary(vec![0x13]))
}
#[test]
pub fn parse_binary_with_incomplete_hex_format() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"0x[3]", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert_eq!(expressions[0].expr, Expr::Binary(vec![0x03]))
}
#[test]
pub fn parse_binary_with_binary_format() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"0b[1010 1000]", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert_eq!(expressions[0].expr, Expr::Binary(vec![0b10101000]))
}
#[test]
pub fn parse_binary_with_incomplete_binary_format() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"0b[10]", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert_eq!(expressions[0].expr, Expr::Binary(vec![0b00000010]))
}
#[test]
pub fn parse_binary_with_octal_format() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"0o[250]", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert_eq!(expressions[0].expr, Expr::Binary(vec![0o250]))
}
#[test]
pub fn parse_binary_with_incomplete_octal_format() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"0o[2]", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert_eq!(expressions[0].expr, Expr::Binary(vec![0o2]))
}
#[test]
pub fn parse_binary_with_invalid_octal_format() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"0b[90]", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(match &expressions[0].expr {
Expr::Binary(_) => false,
_ => true,
})
}
#[test]
pub fn parse_string() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"\"hello nushell\"", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert_eq!(
expressions[0].expr,
Expr::String("hello nushell".to_string())
)
}
#[test]
pub fn parse_escaped_string() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(
&mut working_set,
None,
b"\"hello \\u006e\\u0075\\u0073hell\"",
true,
&[],
);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert_eq!(
expressions[0].expr,
Expr::String("hello nushell".to_string())
)
}
2021-08-30 20:36:07 +02:00
#[test]
pub fn parse_call() {
2021-09-02 10:25:22 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-08-30 20:36:07 +02:00
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
2021-09-02 20:21:37 +02:00
working_set.add_decl(sig.predeclare());
2021-08-30 20:36:07 +02:00
let (block, err) = parse(&mut working_set, None, b"foo", true, &[]);
2021-08-30 20:36:07 +02:00
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert_eq!(expressions.len(), 1);
2021-09-03 04:15:01 +02:00
if let Expression {
expr: Expr::Call(call),
..
} = &expressions[0]
{
assert_eq!(call.decl_id, 0);
2021-08-30 20:36:07 +02:00
}
}
#[test]
pub fn parse_call_missing_flag_arg() {
2021-09-02 10:25:22 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-08-30 20:36:07 +02:00
2021-10-13 19:53:27 +02:00
let sig = Signature::build("foo").named("jazz", SyntaxShape::Int, "jazz!!", Some('j'));
2021-09-02 20:21:37 +02:00
working_set.add_decl(sig.predeclare());
2021-08-30 20:36:07 +02:00
let (_, err) = parse(&mut working_set, None, b"foo --jazz", true, &[]);
2021-08-30 20:36:07 +02:00
assert!(matches!(err, Some(ParseError::MissingFlagParam(..))));
}
#[test]
pub fn parse_call_missing_short_flag_arg() {
2021-09-02 10:25:22 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-08-30 20:36:07 +02:00
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
2021-09-02 20:21:37 +02:00
working_set.add_decl(sig.predeclare());
2021-08-30 20:36:07 +02:00
let (_, err) = parse(&mut working_set, None, b"foo -j", true, &[]);
2021-08-30 20:36:07 +02:00
assert!(matches!(err, Some(ParseError::MissingFlagParam(..))));
}
#[test]
pub fn parse_call_too_many_shortflag_args() {
2021-09-02 10:25:22 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-08-30 20:36:07 +02:00
let sig = Signature::build("foo")
.named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'))
.named("--math", SyntaxShape::Int, "math!!", Some('m'));
2021-09-02 20:21:37 +02:00
working_set.add_decl(sig.predeclare());
let (_, err) = parse(&mut working_set, None, b"foo -mj", true, &[]);
2021-08-30 20:36:07 +02:00
assert!(matches!(
err,
Some(ParseError::ShortFlagBatchCantTakeArg(..))
));
}
#[test]
pub fn parse_call_unknown_shorthand() {
2021-09-02 10:25:22 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-08-30 20:36:07 +02:00
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
2021-09-02 20:21:37 +02:00
working_set.add_decl(sig.predeclare());
let (_, err) = parse(&mut working_set, None, b"foo -mj", true, &[]);
2021-08-30 20:36:07 +02:00
assert!(matches!(err, Some(ParseError::UnknownFlag(..))));
}
#[test]
pub fn parse_call_extra_positional() {
2021-09-02 10:25:22 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-08-30 20:36:07 +02:00
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
2021-09-02 20:21:37 +02:00
working_set.add_decl(sig.predeclare());
let (_, err) = parse(&mut working_set, None, b"foo -j 100", true, &[]);
2021-08-30 20:36:07 +02:00
assert!(matches!(err, Some(ParseError::ExtraPositional(..))));
}
#[test]
pub fn parse_call_missing_req_positional() {
2021-09-02 10:25:22 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-08-30 20:36:07 +02:00
let sig = Signature::build("foo").required("jazz", SyntaxShape::Int, "jazz!!");
2021-09-02 20:21:37 +02:00
working_set.add_decl(sig.predeclare());
let (_, err) = parse(&mut working_set, None, b"foo", true, &[]);
2021-08-30 20:36:07 +02:00
assert!(matches!(err, Some(ParseError::MissingPositional(..))));
}
#[test]
pub fn parse_call_missing_req_flag() {
2021-09-02 10:25:22 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-08-30 20:36:07 +02:00
let sig = Signature::build("foo").required_named("--jazz", SyntaxShape::Int, "jazz!!", None);
2021-09-02 20:21:37 +02:00
working_set.add_decl(sig.predeclare());
let (_, err) = parse(&mut working_set, None, b"foo", true, &[]);
2021-08-30 20:36:07 +02:00
assert!(matches!(err, Some(ParseError::MissingRequiredFlag(..))));
}
2021-09-05 00:25:31 +02:00
#[test]
fn test_nothing_comparisson_eq() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"2 == $nothing", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
&expressions[0],
Expression {
expr: Expr::BinaryOp(..),
..
}
))
}
#[test]
fn test_nothing_comparisson_neq() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"2 != $nothing", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
&expressions[0],
Expression {
expr: Expr::BinaryOp(..),
..
}
))
}
2021-09-05 00:25:31 +02:00
mod range {
use super::*;
use nu_protocol::ast::{RangeInclusion, RangeOperator};
#[test]
fn parse_inclusive_range() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"0..10", true, &[]);
2021-09-05 00:25:31 +02:00
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Range(
Some(_),
None,
Some(_),
RangeOperator {
inclusion: RangeInclusion::Inclusive,
2021-09-05 00:25:31 +02:00
..
}
),
..
2021-09-05 00:25:31 +02:00
}
))
2021-09-05 00:25:31 +02:00
}
#[test]
fn parse_exclusive_range() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"0..<10", true, &[]);
2021-09-05 00:25:31 +02:00
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Range(
Some(_),
None,
Some(_),
RangeOperator {
inclusion: RangeInclusion::RightExclusive,
2021-09-05 00:25:31 +02:00
..
}
),
..
2021-09-05 00:25:31 +02:00
}
))
2021-09-05 00:25:31 +02:00
}
#[test]
fn parse_reverse_range() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"10..0", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Range(
Some(_),
None,
Some(_),
RangeOperator {
inclusion: RangeInclusion::Inclusive,
..
}
),
..
}
))
}
2021-09-05 00:25:31 +02:00
#[test]
fn parse_subexpression_range() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"(3 - 3)..<(8 + 2)", true, &[]);
2021-09-05 00:25:31 +02:00
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Range(
Some(_),
None,
Some(_),
RangeOperator {
inclusion: RangeInclusion::RightExclusive,
2021-09-05 00:25:31 +02:00
..
}
),
..
2021-09-05 00:25:31 +02:00
}
))
2021-09-05 00:25:31 +02:00
}
#[test]
fn parse_variable_range() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-09-13 10:19:05 +02:00
working_set.add_decl(Box::new(Let));
let (block, err) = parse(&mut working_set, None, b"let a = 2; $a..10", true, &[]);
2021-09-05 00:25:31 +02:00
assert!(err.is_none());
assert!(block.len() == 2);
let expressions = &block[1];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Range(
Some(_),
None,
Some(_),
RangeOperator {
inclusion: RangeInclusion::Inclusive,
2021-09-05 00:25:31 +02:00
..
}
),
..
2021-09-05 00:25:31 +02:00
}
))
2021-09-05 00:25:31 +02:00
}
#[test]
fn parse_subexpression_variable_range() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
2021-09-13 10:19:05 +02:00
working_set.add_decl(Box::new(Let));
let (block, err) = parse(
&mut working_set,
None,
b"let a = 2; $a..<($a + 10)",
true,
&[],
);
2021-09-05 00:25:31 +02:00
assert!(err.is_none());
assert!(block.len() == 2);
let expressions = &block[1];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Range(
Some(_),
None,
Some(_),
RangeOperator {
inclusion: RangeInclusion::RightExclusive,
2021-09-05 00:25:31 +02:00
..
}
),
..
2021-09-05 00:25:31 +02:00
}
))
2021-09-05 00:25:31 +02:00
}
#[test]
2021-09-05 20:44:18 +02:00
fn parse_right_unbounded_range() {
2021-09-05 00:25:31 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"0..", true, &[]);
2021-09-05 00:25:31 +02:00
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Range(
Some(_),
None,
None,
RangeOperator {
inclusion: RangeInclusion::Inclusive,
2021-09-05 00:25:31 +02:00
..
}
),
..
2021-09-05 00:25:31 +02:00
}
))
2021-09-05 00:25:31 +02:00
}
#[test]
fn parse_left_unbounded_range() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"..10", true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Range(
None,
None,
Some(_),
RangeOperator {
inclusion: RangeInclusion::Inclusive,
..
}
),
..
}
))
}
2021-09-05 00:25:31 +02:00
#[test]
2021-09-05 20:44:18 +02:00
fn parse_negative_range() {
2021-09-05 00:25:31 +02:00
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"-10..-3", true, &[]);
2021-09-05 00:25:31 +02:00
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Range(
Some(_),
None,
Some(_),
RangeOperator {
inclusion: RangeInclusion::Inclusive,
2021-09-05 00:25:31 +02:00
..
}
),
..
2021-09-05 00:25:31 +02:00
}
))
2021-09-05 00:25:31 +02:00
}
2021-09-12 14:36:54 +02:00
#[test]
fn parse_float_range() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (block, err) = parse(&mut working_set, None, b"2.0..4.0..10.0", true, &[]);
2021-09-12 14:36:54 +02:00
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
assert!(expressions.len() == 1);
assert!(matches!(
expressions[0],
Expression {
expr: Expr::Range(
Some(_),
Some(_),
Some(_),
RangeOperator {
inclusion: RangeInclusion::Inclusive,
2021-09-12 14:36:54 +02:00
..
}
),
..
2021-09-12 14:36:54 +02:00
}
))
2021-09-12 14:36:54 +02:00
}
#[test]
2021-09-05 20:44:18 +02:00
fn bad_parse_does_crash() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let (_, err) = parse(&mut working_set, None, b"(0)..\"a\"", true, &[]);
2021-09-05 20:44:18 +02:00
assert!(err.is_some());
}
2021-09-05 00:25:31 +02:00
}