Skip to content

Commit 6f4d44c

Browse files
authored
paasio: Prevent non-unwinding panic in tests (#2099)
Related forum post: https://forum.exercism.org/t/test-runner-fail-on-paas/19426 [no important files changed]
1 parent 3d87f6e commit 6f4d44c

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

exercises/practice/paasio/tests/paasio.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,22 @@ mod write_string {
136136
fn sink_buffered_windowed() {
137137
let data = INPUT;
138138
let size = data.len();
139-
let mut writer = BufWriter::new(WriteStats::new(io::sink()));
139+
140+
// We store the inner writer in a separate variable so its destructor
141+
// is called correctly. We then wrap a mutable reference to it in a
142+
// buffered writer. The destructor of the buffered writer is suppressed,
143+
// because it tries to flush the inner writer. (It doesn't do anything
144+
// else, so it's fine to skip it.) This would cause a non-unwinding
145+
// panic if the inner writer hasn't implemented `write` yet. The
146+
// standard library implementation of `BufWriter` does try to keep track
147+
// of a panic by the inner writer, but it's not perfect. We access the
148+
// inner writer later with `.get_ref()`. If there is a panic in that
149+
// situation, the buffered writer cannot observe and track it.
150+
//
151+
// Related forum discussion:
152+
// https://forum.exercism.org/t/test-runner-fail-on-paas/19426
153+
let mut inner_writer = WriteStats::new(io::sink());
154+
let mut writer = std::mem::ManuallyDrop::new(BufWriter::new(&mut inner_writer));
140155

141156
for chunk in data.chunks(CHUNK_SIZE) {
142157
let written = writer.write(chunk);
@@ -286,7 +301,22 @@ mod write_byte_literal {
286301
fn sink_buffered_windowed() {
287302
let data = INPUT;
288303
let size = data.len();
289-
let mut writer = BufWriter::new(WriteStats::new(io::sink()));
304+
305+
// We store the inner writer in a separate variable so its destructor
306+
// is called correctly. We then wrap a mutable reference to it in a
307+
// buffered writer. The destructor of the buffered writer is suppressed,
308+
// because it tries to flush the inner writer. (It doesn't do anything
309+
// else, so it's fine to skip it.) This would cause a non-unwinding
310+
// panic if the inner writer hasn't implemented `write` yet. The
311+
// standard library implementation of `BufWriter` does try to keep track
312+
// of a panic by the inner writer, but it's not perfect. We access the
313+
// inner writer later with `.get_ref()`. If there is a panic in that
314+
// situation, the buffered writer cannot observe and track it.
315+
//
316+
// Related forum discussion:
317+
// https://forum.exercism.org/t/test-runner-fail-on-paas/19426
318+
let mut inner_writer = WriteStats::new(io::sink());
319+
let mut writer = std::mem::ManuallyDrop::new(BufWriter::new(&mut inner_writer));
290320

291321
for chunk in data.chunks(CHUNK_SIZE) {
292322
let written = writer.write(chunk);

0 commit comments

Comments
 (0)