use nu_protocol::{ByteStreamType, PipelineData, Span};
use nu_test_support::{fs::fixtures, prelude::*};
use pretty_assertions::assert_eq;
use rstest::rstest;
#[derive(Debug, FromValue, PartialEq)]
struct PeekRecord {
r#type: String,
stream: bool,
value: Option<Vec<Value>>,
}
#[test]
fn peek_works_with_list_stream() -> Result {
let code = "seq 1 5 | peek 2";
let outcome = test().run_raw_with_data(code, PipelineData::Empty)?;
let PipelineData::ListStream(stream, Some(metadata)) = outcome.body else {
panic!("Output must be a stream with metadata")
};
let peek_record = PeekRecord::from_value(metadata.custom.get("peek").unwrap().clone())?;
assert_eq!(
peek_record,
PeekRecord {
r#type: "list".into(),
stream: true,
value: Some(
[1, 2]
.into_iter()
.map(|x| x.into_value(Span::test_data()))
.collect::<Vec<_>>()
),
},
);
stream
.into_value()
.map_err(Error::from)
.expect_value_eq([1, 2, 3, 4, 5])
}
#[test]
fn peek_works_with_list_value() -> Result {
let code = "[1 2 3 4 5] | peek 2";
let outcome = test().run_raw_with_data(code, PipelineData::Empty)?;
let PipelineData::Value(value, Some(metadata)) = outcome.body else {
panic!("Output must be a value with metadata")
};
let peek_record = PeekRecord::from_value(metadata.custom.get("peek").unwrap().clone())?;
assert_eq!(
peek_record,
PeekRecord {
r#type: "list".into(),
stream: false,
value: Some(
[1, 2]
.into_iter()
.map(|x| x.into_value(Span::test_data()))
.collect::<Vec<_>>()
),
},
);
Ok(value).expect_value_eq([1, 2, 3, 4, 5])
}
#[rstest]
#[case::string("'hello' | peek 2", "string")]
#[case::binary("0x[de ad be ef] | peek 2", "binary")]
#[case::int("42 | peek 2", "int")]
fn peek_with_value(#[case] code: &str, #[case] expected_type: &str) -> Result {
let outcome = test().run_raw(code)?;
let PipelineData::Value(_, Some(metadata)) = outcome.body else {
panic!("Output must be a value with metadata")
};
let peek_record = PeekRecord::from_value(metadata.custom.get("peek").unwrap().clone())?;
assert_eq!(
peek_record,
PeekRecord {
r#type: expected_type.into(),
stream: false,
value: None,
},
);
Ok(())
}
#[rstest]
#[case::binary("random binary 16b | peek 2", ByteStreamType::Binary, PeekRecord {r#type: "binary".into(), stream: true, value: None})]
#[case::string("random chars --length 16 | peek 2", ByteStreamType::String, PeekRecord {r#type: "string".into(), stream: true, value: None})]
#[case::unknown("open --raw cp/existing_file.txt | peek 2", ByteStreamType::Unknown, PeekRecord {r#type: "byte stream".into(), stream: true, value: None})]
fn peek_with_byte_streams(
#[case] code: &str,
#[case] byte_stream_type: ByteStreamType,
#[case] expected_peek_record: PeekRecord,
) -> Result {
let outcome = test()
.cwd(fixtures())
.run_raw_with_data(code, PipelineData::Empty)?;
let PipelineData::ByteStream(stream, Some(metadata)) = outcome.body else {
panic!("Output must be a binary stream with metadata")
};
let peek_record = PeekRecord::from_value(metadata.custom.get("peek").unwrap().clone())?;
assert_eq!(peek_record, expected_peek_record);
assert_eq!(stream.type_(), byte_stream_type);
Ok(())
}