Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#![windows_subsystem = "windows"] hides cargo test output #67159

Open
utoalex opened this issue Dec 8, 2019 · 12 comments
Open

#![windows_subsystem = "windows"] hides cargo test output #67159

utoalex opened this issue Dec 8, 2019 · 12 comments
Labels
A-libtest Area: #[test] related C-bug Category: This is a bug. O-windows Operating system: Windows T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@utoalex
Copy link

utoalex commented Dec 8, 2019

Problem
Calling cargo test on a project that has the #![windows_subsystem = "windows"] global attribute does not show the expected human-readable output.

Instead of showing

> cargo test
   Compiling no_output v0.1.0 (C:\Programming\no_output)
    Finished dev [unoptimized + debuginfo] target(s) in 0.71s
     Running target\debug\deps\no_output-c8b57bda8502ba55.exe

running 1 test
test tests::test_panic ... FAILED

failures:

---- tests::test_panic stdout ----
thread 'tests::test_panic' panicked at 'This tape has just self-destructed!', src\main.rs:9:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.


failures:
    tests::test_panic

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

error: test failed, to rerun pass '--bin no_output'

it shows

> cargo test
   Compiling no_output v0.1.0 (C:\Programming\no_output)
    Finished dev [unoptimized + debuginfo] target(s) in 1.40s
     Running target\debug\deps\no_output-c8b57bda8502ba55.exe
error: test failed, to rerun pass '--bin no_output'

which not quite as informative as the former message (it does not tell which tests failed).

Steps
This requires a Windows computer.

  1. Create a new project with cargo new.
  2. Copy-paste the following into your main.rs file:
#![windows_subsystem = "windows"]

fn main() {
    println!("Hello, world!");
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_panic() {
        panic!("This tape has just self-destructed!");
    }
}
  1. call cargo test on your project.

Possible Solution(s)
My guess is that this is due to executables targeting the Windows subsystem having no console and standard output initialized by default on Windows. Therefore, 2 possible solutions come to my mind:

  • forcing cargo test-compiled executables to target the console subsystem when compiled for Windows;
  • or having cargo explicitly initialize the console in the test framework automatically included in test executables: AFAIK this can be achieved by calling the AllocConsole() function provided by the Windows API.

Notes

Output of cargo version: this happens on pretty much any cargo version.
Tested on cargo 1.39.0 (1c6ec66d5 2019-09-30) and cargo 1.41.0-nightly (626f0f40e 2019-12-03).

Apologies if this has already been reported. I was unable to find a similar issue in the repository 😅

@ehuss ehuss transferred this issue from rust-lang/cargo Dec 8, 2019
@ehuss
Copy link
Contributor

ehuss commented Dec 8, 2019

Thanks for the report. I have moved this to rust-lang/rust, as that is where issues for libtest are tracked. This looks to be an issue with the libtest harness.

Interestingly, the output works when run from a cygwin/msys shell, but doesn't with cmd or powershell.

As a workaround, perhaps something like this well help:

#![cfg_attr(not(test), windows_subsystem = "windows")]

@jonas-schievink jonas-schievink added A-libtest Area: #[test] related C-bug Category: This is a bug. O-windows-msvc Toolchain: MSVC, Operating system: Windows T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Dec 8, 2019
@jonas-schievink
Copy link
Contributor

Isn't this expected behavior?

@ehuss
Copy link
Contributor

ehuss commented Dec 8, 2019

Good question, I have no idea! I could see an argument that when built with --test that rustc could ignore the windows_subsystem attribute, since the intent is to write to the console. But I do not know what the consequences would be.

@retep998
Copy link
Member

retep998 commented Dec 9, 2019

I'm pretty sure this is due to defaults regarding how console and windows processes inherit stdout/stdin differently. By default console processes will inherit stdout/stdin from the parent process while windows processes do not. I believe the reason we allow stdout/stdin to be inherited instead of explicitly piping it is to allow console processes to emit colors using the conhost color API, because otherwise colors would not work in some situations on Windows.

@retep998 retep998 added O-windows Operating system: Windows and removed O-windows-msvc Toolchain: MSVC, Operating system: Windows labels Dec 9, 2019
@Songtronix
Copy link

This issue isn't limited to tests only. I build a GUI currently and want to avoid popping up a console on start. However using the cli version is not possible anymore because it does not output anything due to stdout/stdin not being attached to anything.
It would be very helpful if there is a winapi call to make which allows to attach stdout/stdin to the parent. This can be used for cargo test too.

@phiresky
Copy link

phiresky commented Dec 7, 2021

Here's a workaround to not show a console on start, but still output the normal output when started from powershell or cmd:

#![windows_subsystem = "windows"]
fn main() {
    #[cfg(target_os = "windows")]
    {
        use winapi::um::wincon::{AttachConsole, ATTACH_PARENT_PROCESS};
        unsafe {
            AttachConsole(ATTACH_PARENT_PROCESS);
        }
        // ...
    }

from here: https://www.reddit.com/r/learnrust/comments/jaqfcx/windows_print_to_hidden_console_window/

@ChrisDenton
Copy link
Contributor

ChrisDenton commented Dec 7, 2021

That'll work but be aware that the console will not be waiting for output. This means the prompt may switch back to interactive mode while the program is still running.

EDIT: Just clarify the "may" there, it should be fine when running from cargo or another console process that will wait for the "windows" process to exit. But if you run it directly from powershell or cmd then it won't wait.

@phiresky
Copy link

phiresky commented Dec 7, 2021

After testing, i can not recommend the above workaround. Like you said it doesn't make the console wait for the output, leading to weird output intermingling and undesired behaviour when the console is closed (program might get killed with broken pipe or it might not)

@MunchyYDL
Copy link

This problem had me on a wild goose chase for a couple of hours yesterday. 🙂

As a relative newbie to Rust, it was a bit hard to know what to look for when I suddenly couldn't run my newly added tests.

After some digging around, my solution to this specific problem is to attribute only the main() function instead of setting it as a crate level attribute.

Maybe this needs to be mentioned somewhere in some docs relating to either cargo test and/or the docs for the attribute, not only here in the problem report?

Example:

My example is a bit contrived, as I really don't need to switch the subsystem for this example, but it exists there only to show how you can place the attribute on the main function only, instead of as a crate level attribute.

#[windows_subsystem = "windows"]  // Just on main, not a crate level attribute (# vs #!)
fn main() {
    println!("Works fine with cargo test!");
}

#[cfg(test)]
mod main_tests {

    #[test]
    fn it_works() {
        let result = 2 + 2;
        assert_eq!(result, 4);
    }
}

@ehuss
Copy link
Contributor

ehuss commented Jan 9, 2022

@MunchyYDL #[windows_subsystem] is only valid at the crate root. I have posted #92701 to fix the warning for that.

@MunchyYDL
Copy link

Ah, yes, my bad, I tricked myself into thinking it worked, but I only started the program from within VS Code, not as a standalone. DOH!

Thanks for clearing that up for me! :)

@04041b
Copy link

04041b commented May 28, 2024

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
Allows console to show up in debug build but not release build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-libtest Area: #[test] related C-bug Category: This is a bug. O-windows Operating system: Windows T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
Status: No status
Development

No branches or pull requests

9 participants