xd009642 / tarpaulin

A code coverage tool for Rust projects
https://crates.io/crates/cargo-tarpaulin
Apache License 2.0
2.5k stars 180 forks source link

Segfault During Testing with --with-threads=1 #317

Closed maldrake closed 3 years ago

maldrake commented 4 years ago

Issue description

While running tarpaulin on an integration test with the --test-threads=1 flag, the test segfaults. I did try to cut the code base and test code down to a minimal test case. I suspect I only achieved minimal-ish, but it's much smaller than the original project.

Steps to reproduce the issue

  1. git clone git@github.com:jeffrey-howard/minimal.git
  2. cd minimal
  3. cargo tarpaulin --verbose -- --test-threads=1

What's the expected result?

What's the actual result?

[INFO tarpaulin] Running Tarpaulin [INFO tarpaulin] Building project Finished dev [unoptimized + debuginfo] target(s) in 0.10s [DEBUG tarpaulin] Processing Target(lib) [INFO tarpaulin] Launching test [INFO tarpaulin] running /home/ec2-user/environment/minimal/target/debug/deps/minimal-e862dd173fc29ea3

running 0 tests

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

[DEBUG tarpaulin] Processing Target(test: server_test) [INFO tarpaulin] Launching test [INFO tarpaulin] running /home/ec2-user/environment/minimal/target/debug/deps/server_test-9279f386a85d2063

running 1 test test server_bad_address ... Error: "Failed to get test coverage! Error: Failed to run tests: A segfault occurred while executing tests"

Additional details

Output from uname -a:

Linux [IP REMOVED] 4.14.146-93.123.amzn1.x86_64 #1 SMP Tue Sep 24 00:45:23 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Tarpaulin version: 0.10.0

Rustc version: rustc 1.40.0 (73528e339 2019-12-16)

As I was removing as much code as possible to try to get to a minimal project showing this behavior, I did try stripping out the error reporting, at which point the test seemed to run fine. That makes me wonder if it's the thread communication in lib.rs on lines 61 and 94 that might be causing the segfault.

xd009642 commented 4 years ago

This is a known issue and relates to #190 there was a change in how tests were launched for the the instance where test threads is 1 in cargo test and tarpaulin can't reliably follow the ptrace event. I think I have to find a way to improve the following down of executed binaries but that opens a whole can of worms with instrumenting the binaries when they're launched that needs to be figured out.

Is there a reason you need test-threads 1?

maldrake commented 4 years ago

Ah, my apologies for reporting a duplicate issue. I missed that one when looking through the issue list.

In our full test suite, it's a mix. We don't need it for the unit tests, but a goodly amount of our coverage is in integration tests that make queries against a database back-end. Setting test-threads=1 forces those integration tests to run serially, so that the database is always in a predictable state during each test case. That may be a naive approach, though. Until now we haven't had reason to look for a better way.

maldrake commented 4 years ago

I have found a work-around. There's a project at https://github.com/palfrey/serial_test that provides attribute-like procedural macros to force tests to be executed serially. With it, I can make sure the tests run serially, but without using test-threads=1, so tarpaulin runs just fine.

xd009642 commented 4 years ago

Another approach I've seen used is a static mutex for tests to acquire. Rust nix uses this for Unix signal based tests

maldrake commented 4 years ago

That makes sense. In fact, I'm pretty sure the serial_test project is a pretty syntactic wrapper around exactly that.

xd009642 commented 3 years ago

So I just came back and tested this out on the 0.1.18-alpha1 and there was no segfault though I could recreate it in 0.1.16. So looks like this is fixed - although I'll keep the issue open until the alpha is ready to transition away from alpha status and is released in a way most users will use it :grin: