Skip to content

compiletest: may truncate compiler output before trying to parse it as json #96229

Description

@nagisa

Running a ui test will eventually invoke the following function:

fn into_bytes(self) -> Vec<u8> {
match self {
ProcOutput::Full(bytes) => bytes,
ProcOutput::Abbreviated { mut head, skipped, tail } => {
write!(&mut head, "\n\n<<<<<< SKIPPED {} BYTES >>>>>>\n\n", skipped).unwrap();
head.extend_from_slice(&tail);
head
}
}
}

through

let Output { status, stdout, stderr } =
read2_abbreviated(child).expect("failed to read output");
let result = ProcRes {
status,
stdout: String::from_utf8_lossy(&stdout).into_owned(),
stderr: String::from_utf8_lossy(&stderr).into_owned(),
cmdline,
};

which can truncate a long output from the compiler. The problem is that UI tests ask the compiler to output its output as json and then attempts to parse it later, for example here:

let rustfix_input = json::rustfix_diagnostics_only(&proc_res.stderr);

which can fail due to truncation and output very difficult to investigate output in e.g. CI.

Reference: https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm/topic/Legacy.20PM.20removal/near/279479951

Activity

  1. added
    E-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.
    A-testsuiteArea: The testsuite used to check the correctness of rustc
    on Apr 19, 2022
  2. ehuss commented on Apr 20, 2022

    @ehuss
    Contributor

    I think this is somewhat a duplicate of #94322 and #92211.

    It might be good to consolidate these issues, and come up with a specific suggestion on how to improve it. The limit needs to be there to prevent OOM, and also as a indicator that perhaps rustc is emitting too much data (as #94327 resolved). So I suspect what is desired is a better way to display the error. I haven't thought about it myself, but I think that should be easy to improve.

  3. removed
    E-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.
    on Apr 20, 2022
  4. nagisa commented on Apr 20, 2022

    @nagisa
    MemberAuthor

    Got it, removed E-easy.

    I feel like at least a part of this problem is in the fact that the truncation happens indiscriminately at a byte boundary. And another part is that the failure mode is non-deterministic (paths and such can have varying lengths.)

    If the intent is to make “too much output” a failure mode, then we should just straight up fail the test, I feel. Possibly kill/SIGPIPE the compilation process when it exceeds the amount of output bytes but don't truncate the output itself when showing it to the user…?

    Alternatively, for JSONL(ines) truncating on line boundaries would make things not fail as terribly. Not to mention, the rendered output is duplicated among other information with JSON output and a test will likely be interested in only parts of it, which will make truncation kick in earlier in some instances than others, so maybe giving an opportunity to map the output in a streaming fashion would help?

  5. emilyalbini commented on Apr 28, 2022

    @emilyalbini
    Member

    Also hit this due to #96362 (comment) on my local machine...

  6. self-assigned this
    on Apr 29, 2022
  7. emilyalbini commented on Apr 29, 2022

    @emilyalbini
    Member

    Opened a PR to remove the nondeterminism based on the length of the checkout path, which should at least alleviate the problem (abbreviations would still happen, but at least they'd show up on CI): #96551

  8. added a commit that references this issue on Jun 6, 2022
  9. added a commit that references this issue on Sep 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-testsuiteArea: The testsuite used to check the correctness of rustc

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions