Fix close/1 messing up stream_aliases when user_input or user_output aren't set to Stdin and Stdout

This commit is contained in:
Emilie Burgun
2025-02-03 00:07:39 +01:00
parent c548b14f50
commit 2fe7b55343
2 changed files with 73 additions and 40 deletions

View File

@@ -1288,11 +1288,10 @@ impl Stream {
))
}
/// Drops the stream handle and marks the arena pointer as [`ArenaHeaderTag::Dropped`].
#[inline]
pub(crate) fn close(&mut self) -> Result<(), std::io::Error> {
let mut stream = std::mem::replace(self, Stream::Null(StreamOptions::default()));
match stream {
match self {
Stream::NamedTcp(ref mut tcp_stream) => {
tcp_stream.inner_mut().tcp_stream.shutdown(Shutdown::Both)
}
@@ -1322,7 +1321,20 @@ impl Stream {
Ok(())
}
_ => Ok(()),
Stream::Byte(mut stream) => {
stream.drop_payload();
Ok(())
}
Stream::StaticString(mut stream) => {
stream.drop_payload();
Ok(())
}
Stream::Null(_) => Ok(()),
Stream::Readline(_) | Stream::StandardOutput(_) | Stream::StandardError(_) => {
unreachable!();
}
}
}
@@ -1893,3 +1905,45 @@ impl MachineState {
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::machine::config::*;
#[test]
#[cfg_attr(miri, ignore)]
fn close_memory_user_output_stream() {
let mut machine = MachineBuilder::new()
.with_streams(StreamConfig::in_memory())
.build();
let results = machine
.run_query(
"\\+ \\+ (current_output(Stream), close(Stream)), write(user_output, hello).",
)
.collect::<Vec<_>>();
assert_eq!(results.len(), 1);
assert!(results[0].is_ok());
let mut actual = String::new();
machine.user_output.read_to_string(&mut actual).unwrap();
assert_eq!(actual, "hello");
}
#[test]
#[cfg_attr(miri, ignore)]
fn close_memory_user_output_stream_twice() {
let mut machine = MachineBuilder::new()
.with_streams(StreamConfig::in_memory())
.build();
let results = machine
.run_query("\\+ \\+ (current_output(Stream), close(Stream), close(Stream)).")
.collect::<Vec<_>>();
assert_eq!(results.len(), 1);
assert!(results[0].is_ok());
}
}