command arguments are now underlined if they match an existing path -m ran rustfmt on the entire codebase
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::parse::{
|
||||
lex::{LexFlags, LexStream},
|
||||
Node, NdRule, ParseStream, RedirType, Redir,
|
||||
NdRule, Node, ParseStream, Redir, RedirType,
|
||||
lex::{LexFlags, LexStream},
|
||||
};
|
||||
use crate::procio::{IoFrame, IoMode, IoStack};
|
||||
|
||||
@@ -11,187 +11,238 @@ use crate::procio::{IoFrame, IoMode, IoStack};
|
||||
// ============================================================================
|
||||
|
||||
fn parse_command(input: &str) -> Node {
|
||||
let source = Arc::new(input.to_string());
|
||||
let tokens = LexStream::new(source, LexFlags::empty())
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
let source = Arc::new(input.to_string());
|
||||
let tokens = LexStream::new(source, LexFlags::empty())
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut nodes = ParseStream::new(tokens)
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
let mut nodes = ParseStream::new(tokens).flatten().collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(nodes.len(), 1, "Expected exactly one node");
|
||||
let top_node = nodes.remove(0);
|
||||
assert_eq!(nodes.len(), 1, "Expected exactly one node");
|
||||
let top_node = nodes.remove(0);
|
||||
|
||||
// Navigate to the actual Command node within the AST structure
|
||||
// Structure is typically: Conjunction -> Pipeline -> Command
|
||||
match top_node.class {
|
||||
NdRule::Conjunction { elements } => {
|
||||
let first_element = elements.into_iter().next().expect("Expected at least one conjunction element");
|
||||
match first_element.cmd.class {
|
||||
NdRule::Pipeline { cmds, .. } => {
|
||||
let mut commands = cmds;
|
||||
assert_eq!(commands.len(), 1, "Expected exactly one command in pipeline");
|
||||
commands.remove(0)
|
||||
}
|
||||
NdRule::Command { .. } => *first_element.cmd,
|
||||
_ => panic!("Expected Command or Pipeline node, got {:?}", first_element.cmd.class),
|
||||
}
|
||||
}
|
||||
NdRule::Pipeline { cmds, .. } => {
|
||||
let mut commands = cmds;
|
||||
assert_eq!(commands.len(), 1, "Expected exactly one command in pipeline");
|
||||
commands.remove(0)
|
||||
}
|
||||
NdRule::Command { .. } => top_node,
|
||||
_ => panic!("Expected Conjunction, Pipeline, or Command node, got {:?}", top_node.class),
|
||||
}
|
||||
// Navigate to the actual Command node within the AST structure
|
||||
// Structure is typically: Conjunction -> Pipeline -> Command
|
||||
match top_node.class {
|
||||
NdRule::Conjunction { elements } => {
|
||||
let first_element = elements
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("Expected at least one conjunction element");
|
||||
match first_element.cmd.class {
|
||||
NdRule::Pipeline { cmds, .. } => {
|
||||
let mut commands = cmds;
|
||||
assert_eq!(
|
||||
commands.len(),
|
||||
1,
|
||||
"Expected exactly one command in pipeline"
|
||||
);
|
||||
commands.remove(0)
|
||||
}
|
||||
NdRule::Command { .. } => *first_element.cmd,
|
||||
_ => panic!(
|
||||
"Expected Command or Pipeline node, got {:?}",
|
||||
first_element.cmd.class
|
||||
),
|
||||
}
|
||||
}
|
||||
NdRule::Pipeline { cmds, .. } => {
|
||||
let mut commands = cmds;
|
||||
assert_eq!(
|
||||
commands.len(),
|
||||
1,
|
||||
"Expected exactly one command in pipeline"
|
||||
);
|
||||
commands.remove(0)
|
||||
}
|
||||
NdRule::Command { .. } => top_node,
|
||||
_ => panic!(
|
||||
"Expected Conjunction, Pipeline, or Command node, got {:?}",
|
||||
top_node.class
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_output_redirect() {
|
||||
let node = parse_command("echo hello > output.txt");
|
||||
let node = parse_command("echo hello > output.txt");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
|
||||
assert!(matches!(redir.class, RedirType::Output));
|
||||
assert!(matches!(redir.io_mode, IoMode::File { tgt_fd: 1, .. }));
|
||||
assert!(matches!(redir.class, RedirType::Output));
|
||||
assert!(matches!(redir.io_mode, IoMode::File { tgt_fd: 1, .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_append_redirect() {
|
||||
let node = parse_command("echo hello >> output.txt");
|
||||
let node = parse_command("echo hello >> output.txt");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
|
||||
assert!(matches!(redir.class, RedirType::Append));
|
||||
assert!(matches!(redir.io_mode, IoMode::File { tgt_fd: 1, .. }));
|
||||
assert!(matches!(redir.class, RedirType::Append));
|
||||
assert!(matches!(redir.io_mode, IoMode::File { tgt_fd: 1, .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_input_redirect() {
|
||||
let node = parse_command("cat < input.txt");
|
||||
let node = parse_command("cat < input.txt");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
|
||||
assert!(matches!(redir.class, RedirType::Input));
|
||||
assert!(matches!(redir.io_mode, IoMode::File { tgt_fd: 0, .. }));
|
||||
assert!(matches!(redir.class, RedirType::Input));
|
||||
assert!(matches!(redir.io_mode, IoMode::File { tgt_fd: 0, .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_stderr_redirect() {
|
||||
let node = parse_command("ls 2> errors.txt");
|
||||
let node = parse_command("ls 2> errors.txt");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
|
||||
assert!(matches!(redir.class, RedirType::Output));
|
||||
assert!(matches!(redir.io_mode, IoMode::File { tgt_fd: 2, .. }));
|
||||
assert!(matches!(redir.class, RedirType::Output));
|
||||
assert!(matches!(redir.io_mode, IoMode::File { tgt_fd: 2, .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_stderr_to_stdout() {
|
||||
let node = parse_command("ls 2>&1");
|
||||
let node = parse_command("ls 2>&1");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
|
||||
assert!(matches!(redir.io_mode, IoMode::Fd { tgt_fd: 2, src_fd: 1 }));
|
||||
assert!(matches!(
|
||||
redir.io_mode,
|
||||
IoMode::Fd {
|
||||
tgt_fd: 2,
|
||||
src_fd: 1
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_stdout_to_stderr() {
|
||||
let node = parse_command("echo test 1>&2");
|
||||
let node = parse_command("echo test 1>&2");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
|
||||
assert!(matches!(redir.io_mode, IoMode::Fd { tgt_fd: 1, src_fd: 2 }));
|
||||
assert!(matches!(
|
||||
redir.io_mode,
|
||||
IoMode::Fd {
|
||||
tgt_fd: 1,
|
||||
src_fd: 2
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_multiple_redirects() {
|
||||
let node = parse_command("cmd < input.txt > output.txt 2> errors.txt");
|
||||
let node = parse_command("cmd < input.txt > output.txt 2> errors.txt");
|
||||
|
||||
assert_eq!(node.redirs.len(), 3);
|
||||
assert_eq!(node.redirs.len(), 3);
|
||||
|
||||
// Input redirect
|
||||
assert!(matches!(node.redirs[0].class, RedirType::Input));
|
||||
assert!(matches!(node.redirs[0].io_mode, IoMode::File { tgt_fd: 0, .. }));
|
||||
// Input redirect
|
||||
assert!(matches!(node.redirs[0].class, RedirType::Input));
|
||||
assert!(matches!(
|
||||
node.redirs[0].io_mode,
|
||||
IoMode::File { tgt_fd: 0, .. }
|
||||
));
|
||||
|
||||
// Stdout redirect
|
||||
assert!(matches!(node.redirs[1].class, RedirType::Output));
|
||||
assert!(matches!(node.redirs[1].io_mode, IoMode::File { tgt_fd: 1, .. }));
|
||||
// Stdout redirect
|
||||
assert!(matches!(node.redirs[1].class, RedirType::Output));
|
||||
assert!(matches!(
|
||||
node.redirs[1].io_mode,
|
||||
IoMode::File { tgt_fd: 1, .. }
|
||||
));
|
||||
|
||||
// Stderr redirect
|
||||
assert!(matches!(node.redirs[2].class, RedirType::Output));
|
||||
assert!(matches!(node.redirs[2].io_mode, IoMode::File { tgt_fd: 2, .. }));
|
||||
// Stderr redirect
|
||||
assert!(matches!(node.redirs[2].class, RedirType::Output));
|
||||
assert!(matches!(
|
||||
node.redirs[2].io_mode,
|
||||
IoMode::File { tgt_fd: 2, .. }
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_custom_fd_redirect() {
|
||||
let node = parse_command("echo test 3> fd3.txt");
|
||||
let node = parse_command("echo test 3> fd3.txt");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
|
||||
assert!(matches!(redir.class, RedirType::Output));
|
||||
assert!(matches!(redir.io_mode, IoMode::File { tgt_fd: 3, .. }));
|
||||
assert!(matches!(redir.class, RedirType::Output));
|
||||
assert!(matches!(redir.io_mode, IoMode::File { tgt_fd: 3, .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_custom_fd_dup() {
|
||||
let node = parse_command("cmd 3>&4");
|
||||
let node = parse_command("cmd 3>&4");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
|
||||
assert!(matches!(redir.io_mode, IoMode::Fd { tgt_fd: 3, src_fd: 4 }));
|
||||
assert!(matches!(
|
||||
redir.io_mode,
|
||||
IoMode::Fd {
|
||||
tgt_fd: 3,
|
||||
src_fd: 4
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_heredoc() {
|
||||
let node = parse_command("cat << EOF");
|
||||
let node = parse_command("cat << EOF");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
|
||||
assert!(matches!(redir.class, RedirType::HereDoc));
|
||||
assert!(matches!(redir.class, RedirType::HereDoc));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_herestring() {
|
||||
let node = parse_command("cat <<< 'hello world'");
|
||||
let node = parse_command("cat <<< 'hello world'");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
let redir = &node.redirs[0];
|
||||
|
||||
assert!(matches!(redir.class, RedirType::HereString));
|
||||
assert!(matches!(redir.class, RedirType::HereString));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_redirect_with_no_space() {
|
||||
let node = parse_command("echo hello >output.txt");
|
||||
let node = parse_command("echo hello >output.txt");
|
||||
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
assert!(matches!(node.redirs[0].class, RedirType::Output));
|
||||
assert_eq!(node.redirs.len(), 1);
|
||||
assert!(matches!(node.redirs[0].class, RedirType::Output));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_redirect_order_preserved() {
|
||||
let node = parse_command("cmd 2>&1 > file.txt");
|
||||
let node = parse_command("cmd 2>&1 > file.txt");
|
||||
|
||||
assert_eq!(node.redirs.len(), 2);
|
||||
assert_eq!(node.redirs.len(), 2);
|
||||
|
||||
// First redirect: 2>&1
|
||||
assert!(matches!(node.redirs[0].io_mode, IoMode::Fd { tgt_fd: 2, src_fd: 1 }));
|
||||
// First redirect: 2>&1
|
||||
assert!(matches!(
|
||||
node.redirs[0].io_mode,
|
||||
IoMode::Fd {
|
||||
tgt_fd: 2,
|
||||
src_fd: 1
|
||||
}
|
||||
));
|
||||
|
||||
// Second redirect: > file.txt
|
||||
assert!(matches!(node.redirs[1].class, RedirType::Output));
|
||||
assert!(matches!(node.redirs[1].io_mode, IoMode::File { tgt_fd: 1, .. }));
|
||||
// Second redirect: > file.txt
|
||||
assert!(matches!(node.redirs[1].class, RedirType::Output));
|
||||
assert!(matches!(
|
||||
node.redirs[1].io_mode,
|
||||
IoMode::File { tgt_fd: 1, .. }
|
||||
));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -200,148 +251,148 @@ fn parse_redirect_order_preserved() {
|
||||
|
||||
#[test]
|
||||
fn iostack_new() {
|
||||
let stack = IoStack::new();
|
||||
let stack = IoStack::new();
|
||||
|
||||
assert_eq!(stack.len(), 1, "IoStack should start with one frame");
|
||||
assert_eq!(stack.curr_frame().len(), 0, "Initial frame should be empty");
|
||||
assert_eq!(stack.len(), 1, "IoStack should start with one frame");
|
||||
assert_eq!(stack.curr_frame().len(), 0, "Initial frame should be empty");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iostack_push_pop_frame() {
|
||||
let mut stack = IoStack::new();
|
||||
let mut stack = IoStack::new();
|
||||
|
||||
// Push a new frame
|
||||
stack.push_frame(IoFrame::new());
|
||||
assert_eq!(stack.len(), 2);
|
||||
// Push a new frame
|
||||
stack.push_frame(IoFrame::new());
|
||||
assert_eq!(stack.len(), 2);
|
||||
|
||||
// Pop it back
|
||||
let frame = stack.pop_frame();
|
||||
assert_eq!(frame.len(), 0);
|
||||
assert_eq!(stack.len(), 1);
|
||||
// Pop it back
|
||||
let frame = stack.pop_frame();
|
||||
assert_eq!(frame.len(), 0);
|
||||
assert_eq!(stack.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iostack_never_empties() {
|
||||
let mut stack = IoStack::new();
|
||||
let mut stack = IoStack::new();
|
||||
|
||||
// Try to pop the last frame
|
||||
let frame = stack.pop_frame();
|
||||
assert_eq!(frame.len(), 0);
|
||||
// Try to pop the last frame
|
||||
let frame = stack.pop_frame();
|
||||
assert_eq!(frame.len(), 0);
|
||||
|
||||
// Stack should still have one frame
|
||||
assert_eq!(stack.len(), 1);
|
||||
// Stack should still have one frame
|
||||
assert_eq!(stack.len(), 1);
|
||||
|
||||
// Pop again - should still have one frame
|
||||
let frame = stack.pop_frame();
|
||||
assert_eq!(frame.len(), 0);
|
||||
assert_eq!(stack.len(), 1);
|
||||
// Pop again - should still have one frame
|
||||
let frame = stack.pop_frame();
|
||||
assert_eq!(frame.len(), 0);
|
||||
assert_eq!(stack.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iostack_push_to_frame() {
|
||||
let mut stack = IoStack::new();
|
||||
let mut stack = IoStack::new();
|
||||
|
||||
let redir = crate::parse::Redir::new(
|
||||
IoMode::fd(1, 2),
|
||||
RedirType::Output,
|
||||
);
|
||||
let redir = crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output);
|
||||
|
||||
stack.push_to_frame(redir);
|
||||
assert_eq!(stack.curr_frame().len(), 1);
|
||||
stack.push_to_frame(redir);
|
||||
assert_eq!(stack.curr_frame().len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iostack_append_to_frame() {
|
||||
let mut stack = IoStack::new();
|
||||
let mut stack = IoStack::new();
|
||||
|
||||
let redirs = vec![
|
||||
crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output),
|
||||
crate::parse::Redir::new(IoMode::fd(2, 1), RedirType::Output),
|
||||
];
|
||||
let redirs = vec![
|
||||
crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output),
|
||||
crate::parse::Redir::new(IoMode::fd(2, 1), RedirType::Output),
|
||||
];
|
||||
|
||||
stack.append_to_frame(redirs);
|
||||
assert_eq!(stack.curr_frame().len(), 2);
|
||||
stack.append_to_frame(redirs);
|
||||
assert_eq!(stack.curr_frame().len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iostack_frame_isolation() {
|
||||
let mut stack = IoStack::new();
|
||||
let mut stack = IoStack::new();
|
||||
|
||||
// Add redir to first frame
|
||||
let redir1 = crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output);
|
||||
stack.push_to_frame(redir1);
|
||||
assert_eq!(stack.curr_frame().len(), 1);
|
||||
// Add redir to first frame
|
||||
let redir1 = crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output);
|
||||
stack.push_to_frame(redir1);
|
||||
assert_eq!(stack.curr_frame().len(), 1);
|
||||
|
||||
// Push new frame
|
||||
stack.push_frame(IoFrame::new());
|
||||
assert_eq!(stack.curr_frame().len(), 0, "New frame should be empty");
|
||||
// Push new frame
|
||||
stack.push_frame(IoFrame::new());
|
||||
assert_eq!(stack.curr_frame().len(), 0, "New frame should be empty");
|
||||
|
||||
// Add redir to second frame
|
||||
let redir2 = crate::parse::Redir::new(IoMode::fd(2, 1), RedirType::Output);
|
||||
stack.push_to_frame(redir2);
|
||||
assert_eq!(stack.curr_frame().len(), 1);
|
||||
// Add redir to second frame
|
||||
let redir2 = crate::parse::Redir::new(IoMode::fd(2, 1), RedirType::Output);
|
||||
stack.push_to_frame(redir2);
|
||||
assert_eq!(stack.curr_frame().len(), 1);
|
||||
|
||||
// Pop second frame
|
||||
let frame2 = stack.pop_frame();
|
||||
assert_eq!(frame2.len(), 1);
|
||||
// Pop second frame
|
||||
let frame2 = stack.pop_frame();
|
||||
assert_eq!(frame2.len(), 1);
|
||||
|
||||
// First frame should still have its redir
|
||||
assert_eq!(stack.curr_frame().len(), 1);
|
||||
// First frame should still have its redir
|
||||
assert_eq!(stack.curr_frame().len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iostack_flatten() {
|
||||
let mut stack = IoStack::new();
|
||||
let mut stack = IoStack::new();
|
||||
|
||||
// Add redir to first frame
|
||||
let redir1 = crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output);
|
||||
stack.push_to_frame(redir1);
|
||||
// Add redir to first frame
|
||||
let redir1 = crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output);
|
||||
stack.push_to_frame(redir1);
|
||||
|
||||
// Push new frame with redir
|
||||
let mut frame2 = IoFrame::new();
|
||||
frame2.push(crate::parse::Redir::new(IoMode::fd(2, 1), RedirType::Output));
|
||||
stack.push_frame(frame2);
|
||||
// Push new frame with redir
|
||||
let mut frame2 = IoFrame::new();
|
||||
frame2.push(crate::parse::Redir::new(
|
||||
IoMode::fd(2, 1),
|
||||
RedirType::Output,
|
||||
));
|
||||
stack.push_frame(frame2);
|
||||
|
||||
// Push third frame with redir
|
||||
let mut frame3 = IoFrame::new();
|
||||
frame3.push(crate::parse::Redir::new(IoMode::fd(0, 3), RedirType::Input));
|
||||
stack.push_frame(frame3);
|
||||
// Push third frame with redir
|
||||
let mut frame3 = IoFrame::new();
|
||||
frame3.push(crate::parse::Redir::new(IoMode::fd(0, 3), RedirType::Input));
|
||||
stack.push_frame(frame3);
|
||||
|
||||
assert_eq!(stack.len(), 3);
|
||||
assert_eq!(stack.len(), 3);
|
||||
|
||||
// Flatten
|
||||
stack.flatten();
|
||||
// Flatten
|
||||
stack.flatten();
|
||||
|
||||
// Should have one frame with all redirects
|
||||
assert_eq!(stack.len(), 1);
|
||||
assert_eq!(stack.curr_frame().len(), 3);
|
||||
// Should have one frame with all redirects
|
||||
assert_eq!(stack.len(), 1);
|
||||
assert_eq!(stack.curr_frame().len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ioframe_new() {
|
||||
let frame = IoFrame::new();
|
||||
assert_eq!(frame.len(), 0);
|
||||
let frame = IoFrame::new();
|
||||
assert_eq!(frame.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ioframe_from_redirs() {
|
||||
let redirs = vec![
|
||||
crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output),
|
||||
crate::parse::Redir::new(IoMode::fd(2, 1), RedirType::Output),
|
||||
];
|
||||
let redirs = vec![
|
||||
crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output),
|
||||
crate::parse::Redir::new(IoMode::fd(2, 1), RedirType::Output),
|
||||
];
|
||||
|
||||
let frame = IoFrame::from_redirs(redirs);
|
||||
assert_eq!(frame.len(), 2);
|
||||
let frame = IoFrame::from_redirs(redirs);
|
||||
assert_eq!(frame.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ioframe_push() {
|
||||
let mut frame = IoFrame::new();
|
||||
let mut frame = IoFrame::new();
|
||||
|
||||
let redir = crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output);
|
||||
frame.push(redir);
|
||||
let redir = crate::parse::Redir::new(IoMode::fd(1, 2), RedirType::Output);
|
||||
frame.push(redir);
|
||||
|
||||
assert_eq!(frame.len(), 1);
|
||||
assert_eq!(frame.len(), 1);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -350,28 +401,28 @@ fn ioframe_push() {
|
||||
|
||||
#[test]
|
||||
fn iomode_fd_construction() {
|
||||
let io_mode = IoMode::fd(2, 1);
|
||||
let io_mode = IoMode::fd(2, 1);
|
||||
|
||||
match io_mode {
|
||||
IoMode::Fd { tgt_fd, src_fd } => {
|
||||
assert_eq!(tgt_fd, 2);
|
||||
assert_eq!(src_fd, 1);
|
||||
}
|
||||
_ => panic!("Expected IoMode::Fd"),
|
||||
}
|
||||
match io_mode {
|
||||
IoMode::Fd { tgt_fd, src_fd } => {
|
||||
assert_eq!(tgt_fd, 2);
|
||||
assert_eq!(src_fd, 1);
|
||||
}
|
||||
_ => panic!("Expected IoMode::Fd"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iomode_tgt_fd() {
|
||||
let fd_mode = IoMode::fd(2, 1);
|
||||
assert_eq!(fd_mode.tgt_fd(), 2);
|
||||
let fd_mode = IoMode::fd(2, 1);
|
||||
assert_eq!(fd_mode.tgt_fd(), 2);
|
||||
|
||||
let file_mode = IoMode::file(1, std::path::PathBuf::from("test.txt"), RedirType::Output);
|
||||
assert_eq!(file_mode.tgt_fd(), 1);
|
||||
let file_mode = IoMode::file(1, std::path::PathBuf::from("test.txt"), RedirType::Output);
|
||||
assert_eq!(file_mode.tgt_fd(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iomode_src_fd() {
|
||||
let fd_mode = IoMode::fd(2, 1);
|
||||
assert_eq!(fd_mode.src_fd(), 1);
|
||||
let fd_mode = IoMode::fd(2, 1);
|
||||
assert_eq!(fd_mode.src_fd(), 1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user