softprops / atty

are you or are you not a tty?
MIT License
271 stars 48 forks source link

Fails tests in captive environments where stdin is closed #39

Open kentfredric opened 4 years ago

kentfredric commented 4 years ago

Our vendor tooling builds and tests cargo stuff in its own private space, where direct stdin is not available.

But a simple way to emulate the situations that causes this failure is redirecting /dev/null into stdin.

A simple way to replicate this behaviour is:

RUST_BACKTRACE=full cargo test </dev/null
    Finished dev [unoptimized + debuginfo] target(s) in 0.07s
     Running target/debug/deps/atty-a5c6cbcdd7f2e95c

running 3 tests
test tests::is_err ... ok
test tests::is_out ... ok
test tests::is_in ... FAILED

failures:

---- tests::is_in stdout ----
thread 'tests::is_in' panicked at 'assertion failed: is(Stream::Stdin)', src/lib.rs:195:9
stack backtrace:
   0:     0x555ad16db314 - backtrace::backtrace::libunwind::trace::h4dc2f373699fbe93
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/libunwind.rs:88
   1:     0x555ad16db314 - backtrace::backtrace::trace_unsynchronized::h7b04f002610ccc35
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/mod.rs:66
   2:     0x555ad16db314 - std::sys_common::backtrace::_print_fmt::h0238c0a72ffc5be3
                               at src/libstd/sys_common/backtrace.rs:76
   3:     0x555ad16db314 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h40ab018276d013f4
                               at src/libstd/sys_common/backtrace.rs:60
   4:     0x555ad16f613c - core::fmt::write::h029a8d927db7b721
                               at src/libcore/fmt/mod.rs:1030
   5:     0x555ad1696895 - std::io::Write::write_fmt::h188f2aadaaf2e907
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libstd/io/mod.rs:1412
   6:     0x555ad16d6f71 - std::io::impls::<impl std::io::Write for alloc::boxed::Box<W>>::write_fmt::h4d5381185853a108
                               at src/libstd/io/impls.rs:141
   7:     0x555ad16dd7a5 - std::sys_common::backtrace::_print::he925af2d0a3180ad
                               at src/libstd/sys_common/backtrace.rs:64
   8:     0x555ad16dd7a5 - std::sys_common::backtrace::print::ha41b6194bcf8f6ce
                               at src/libstd/sys_common/backtrace.rs:49
   9:     0x555ad16dd7a5 - std::panicking::default_hook::{{closure}}::h659784bc3ca43626
                               at src/libstd/panicking.rs:196
  10:     0x555ad16dd42c - std::panicking::default_hook::h2f638ec54806c9d8
                               at src/libstd/panicking.rs:207
  11:     0x555ad16ddea5 - std::panicking::rust_panic_with_hook::h12d7650e86d2fcb0
                               at src/libstd/panicking.rs:473
  12:     0x555ad16dda42 - std::panicking::continue_panic_fmt::h70eeb0d1820fa233
                               at src/libstd/panicking.rs:380
  13:     0x555ad16dd936 - rust_begin_unwind
                               at src/libstd/panicking.rs:307
  14:     0x555ad16f382a - core::panicking::panic_fmt::hbbf14b8c86c6fc9d
                               at src/libcore/panicking.rs:85
  15:     0x555ad16f3769 - core::panicking::panic::h55ac7fee752f83d1
                               at src/libcore/panicking.rs:49
  16:     0x555ad16958a0 - atty::tests::is_in::h44535dbfe2769274
                               at src/lib.rs:195
  17:     0x555ad169533a - atty::tests::is_in::{{closure}}::hf66be9b54f1cebe2
                               at src/lib.rs:194
  18:     0x555ad169563e - core::ops::function::FnOnce::call_once::ha5f31d1376a1d459
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libcore/ops/function.rs:227
  19:     0x555ad16a078f - <alloc::boxed::Box<F> as core::ops::function::FnOnce<A>>::call_once::hc4223621e68f84c1
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/liballoc/boxed.rs:922
  20:     0x555ad16e05aa - __rust_maybe_catch_panic
                               at src/libpanic_unwind/lib.rs:80
  21:     0x555ad16baf9e - std::panicking::try::hc81bdd9007d9c5da
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libstd/panicking.rs:271
  22:     0x555ad16baf9e - std::panic::catch_unwind::hf7e7956e7e4c2bce
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libstd/panic.rs:394
  23:     0x555ad16baf9e - test::run_test::run_test_inner::{{closure}}::hc786e5a908160c30
                               at src/libtest/lib.rs:1413
  24:     0x555ad1696005 - std::sys_common::backtrace::__rust_begin_short_backtrace::h95b152913f9dfacb
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libstd/sys_common/backtrace.rs:126
  25:     0x555ad169a1b5 - std::thread::Builder::spawn_unchecked::{{closure}}::{{closure}}::he45de012a497b092
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libstd/thread/mod.rs:470
  26:     0x555ad169a1b5 - <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::hf68db3f5a78ee690
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libstd/panic.rs:315
  27:     0x555ad169a1b5 - std::panicking::try::do_call::hf5c86a524ef68531
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libstd/panicking.rs:292
  28:     0x555ad16e05aa - __rust_maybe_catch_panic
                               at src/libpanic_unwind/lib.rs:80
  29:     0x555ad169a832 - std::panicking::try::ha8e33b8d02e42b94
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libstd/panicking.rs:271
  30:     0x555ad169a832 - std::panic::catch_unwind::he00df3131fcbf67d
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libstd/panic.rs:394
  31:     0x555ad169a832 - std::thread::Builder::spawn_unchecked::{{closure}}::h677216b4f657bbdb
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libstd/thread/mod.rs:469
  32:     0x555ad169a832 - core::ops::function::FnOnce::call_once{{vtable.shim}}::hf34a76822ad504a1
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/libcore/ops/function.rs:227
  33:     0x555ad16d39cf - <alloc::boxed::Box<F> as core::ops::function::FnOnce<A>>::call_once::h1d0ecaf281abdf71
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/liballoc/boxed.rs:922
  34:     0x555ad16dfd00 - <alloc::boxed::Box<F> as core::ops::function::FnOnce<A>>::call_once::hfc866af69ec8f7e1
                               at /rustc/66bf391c3aabfc77f5f7139fc9e6944f995d574e/src/liballoc/boxed.rs:922
  35:     0x555ad16dfd00 - std::sys_common::thread::start_thread::h884843b1b0377783
                               at src/libstd/sys_common/thread.rs:13
  36:     0x555ad16dfd00 - std::sys::unix::thread::Thread::new::thread_start::hf370570edee1b7e3
                               at src/libstd/sys/unix/thread.rs:79
  37:     0x7f0722f1a3a7 - start_thread
                               at /var/tmp/portage/sys-libs/glibc-2.29-r5/work/glibc-2.29/nptl/pthread_create.c:486
  38:     0x7f0722e2f0ff - __clone
  39:                0x0 - <unknown>

failures:
    tests::is_in

test result: FAILED. 2 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--lib'

the stdout test can also be made to fail by redirecting the test output via:

 RUST_BACKTRACE=full cargo test | cat

And the stderr test can also be made to fail by redirecting the test output via:

RUST_BACKTRACE=full cargo test 2>/dev/null

I understand that this is the problem domain atty is targeted at solving, so its a bit tricky, but I suspect the "right" thing to do here is have the tests in question exec a common binary internally, where, supposedly, you can control the availability and state of the various IO handles, that way, you're testing the logic, not testing whether or not the user is consuming the tests in an approved way.

infinity0 commented 4 years ago

It's fine, we can just run the test as script -c 'cargo test' /dev/null which is the normal solution for this sort of thing.

sylvestre commented 4 years ago

Full log: https://ci.debian.net/data/autopkgtest/unstable/amd64/r/rust-atty/4863236/log.gz