mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 19:27:44 +02:00
Implementing ByteStream interuption on infinite stream (#13552)
# Description This PR should address #13530 by explicitly handling ByteStreams. The issue can be replicated easily on linux by running: ```nushell open /dev/urandom | into binary | bytes at ..10 ``` Would leave the output hanging and with no way to cancel it, this was likely because it was trying to collect the input stream and would not complete. I have also put in an error to say that using negative offsets for a bytestream without a length cannot be used. ```nushell ~/git/nushell> open /dev/urandom | into binary | bytes at (-1).. Error: nu:🐚:incorrect_value × Incorrect value. ╭─[entry #3:1:35] 1 │ open /dev/urandom | into binary | bytes at (-1).. · ────┬─── ───┬── · │ ╰── encountered here · ╰── Negative range values cannot be used with streams that don't specify a length ╰──── ``` # User-Facing Changes No operation changes, only the warning you get back for negative offsets # Tests + Formatting Ran `toolkit check pr ` with no errors or warnings Manual testing of the example commands above --------- Co-authored-by: Ian Manske <ian.manske@pm.me> Co-authored-by: Simon Curtis <simon.curtis@candc-uk.com>
This commit is contained in:
268
crates/nu-protocol/tests/pipeline/byte_stream.rs
Normal file
268
crates/nu-protocol/tests/pipeline/byte_stream.rs
Normal file
@ -0,0 +1,268 @@
|
||||
use nu_protocol::{ast::RangeInclusion, ByteStream, IntRange, Signals, Span, Value};
|
||||
|
||||
#[test]
|
||||
pub fn test_simple_positive_slice_exclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(0, 5, RangeInclusion::RightExclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "Hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_negative_start_exclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(-5, 11, RangeInclusion::RightExclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "World");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_negative_end_exclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(0, -6, RangeInclusion::RightExclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "Hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_negative_start_and_end_exclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(-5, -2, RangeInclusion::RightExclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "Wor");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_empty_slice_exclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(5, 5, RangeInclusion::RightExclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_out_of_bounds_exclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(0, 20, RangeInclusion::RightExclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "Hello World");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_invalid_range_exclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(11, 5, RangeInclusion::RightExclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_max_end_exclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(6, i64::MAX, RangeInclusion::RightExclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "World");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_simple_positive_slice_inclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(0, 5, RangeInclusion::RightExclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "Hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_negative_start_inclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(-5, 11, RangeInclusion::Inclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "World");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_negative_end_inclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(0, -7, RangeInclusion::Inclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "Hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_negative_start_and_end_inclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(-5, -1, RangeInclusion::Inclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "World");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_empty_slice_inclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(5, 5, RangeInclusion::Inclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, " ");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_out_of_bounds_inclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(0, 20, RangeInclusion::Inclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "Hello World");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_invalid_range_inclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(11, 5, RangeInclusion::Inclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_max_end_inclusive() {
|
||||
let data = b"Hello World".to_vec();
|
||||
let stream = ByteStream::read_binary(data, Span::test_data(), Signals::empty());
|
||||
let sliced = stream
|
||||
.slice(
|
||||
Span::test_data(),
|
||||
Span::test_data(),
|
||||
create_range(6, i64::MAX, RangeInclusion::Inclusive),
|
||||
)
|
||||
.unwrap();
|
||||
let result = sliced.into_bytes().unwrap();
|
||||
let result = String::from_utf8(result).unwrap();
|
||||
assert_eq!(result, "World");
|
||||
}
|
||||
|
||||
fn create_range(start: i64, end: i64, inclusion: RangeInclusion) -> IntRange {
|
||||
IntRange::new(
|
||||
Value::int(start, Span::unknown()),
|
||||
Value::nothing(Span::test_data()),
|
||||
Value::int(end, Span::unknown()),
|
||||
inclusion,
|
||||
Span::unknown(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
Reference in New Issue
Block a user