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

Use source-based code coverage #132

Merged
merged 9 commits into from
Jan 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 3 additions & 37 deletions .github/workflows/main.yml → .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Rust CI
name: CI
on:
push:
branches:
Expand All @@ -7,6 +7,8 @@ on:
branches:
- master
types: [opened, reopened, synchronize]
schedule:
- cron: '0 0 * * *' # every day at midnight

jobs:
tests:
Expand Down Expand Up @@ -98,42 +100,6 @@ jobs:
command: test
args: --manifest-path=core/Cargo.toml --features ${{ matrix.feature }} -- --ignored

codecov-grcov:
name: Generate code coverage
runs-on: ubuntu-latest
strategy:
fail-fast: true
steps:
- name: Install Protoc
uses: arduino/setup-protoc@v1
with:
version: '3.6.1'
- name: install toolchain according to rust-toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: default
override: true
- name: Checkout sources
uses: actions/checkout@v2
- name: Run tests for coverage
env:
CARGO_INCREMENTAL: 0
RUSTFLAGS: -Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests
RUSTDOCFLAGS: -Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests
run: |
cargo test
cargo test --manifest-path=core/Cargo.toml --no-default-features --features ser_id_8
cargo test --manifest-path=core/Cargo.toml --no-default-features --features ser_id_16
cargo test --manifest-path=core/Cargo.toml --no-default-features --features ser_id_32
cargo test --manifest-path=core/Cargo.toml --features thread_pinning
cargo test --manifest-path=core/Cargo.toml --features low_latency
cargo test --manifest-path=core/Cargo.toml --features type_erasure
- name: Compute coverage
uses: actions-rs/[email protected]
- name: Upload to codecov.io
uses: codecov/codecov-action@v1

clippy:
name: cargo clippy
runs-on: ubuntu-latest
Expand Down
63 changes: 63 additions & 0 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Codecov
on:
push:
branches:
- master
pull_request:
branches:
- master
types: [opened, reopened, synchronize]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want this to run with every single commit added to a PR? It's a 1h test suite. It'll take up a lot of resources on Klas' node.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It takes 13min on Klas machine 😃

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whooot?!?


jobs:
codecov-grcov:
name: Generate code coverage
runs-on: self-hosted
strategy:
fail-fast: true
steps:
- name: Install Protoc
uses: arduino/setup-protoc@v1
with:
version: '3.6.1'
- name: install toolchain according to rust-toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: default
override: true
components: llvm-tools-preview
- name: Checkout sources
uses: actions/checkout@v2
- name: Install grcov
run: if [[ ! -e ~/.cargo/bin/grcov ]]; then cargo install grcov; fi
- name: Build
uses: actions-rs/cargo@v1
with:
command: build
env:
RUSTFLAGS: '-Zinstrument-coverage'
RUSTDOCFLAGS: '-Zinstrument-coverage'
- name: Run tests
env:
RUSTFLAGS: '-Zinstrument-coverage'
RUSTDOCFLAGS: '-Zinstrument-coverage'
LLVM_PROFILE_FILE: 'codecov-instrumentation-%p-%m.profraw'
run: |
cargo test --features slog/max_level_error
cargo test --features slog/max_level_error -- --ignored
cargo test --manifest-path=core/Cargo.toml --no-default-features --features ser_id_8,slog/max_level_error
cargo test --manifest-path=core/Cargo.toml --no-default-features --features ser_id_8,slog/max_level_error -- --ignored
cargo test --manifest-path=core/Cargo.toml --no-default-features --features ser_id_16,slog/max_level_error
cargo test --manifest-path=core/Cargo.toml --no-default-features --features ser_id_16,slog/max_level_error -- --ignored
cargo test --manifest-path=core/Cargo.toml --no-default-features --features ser_id_32,slog/max_level_error
cargo test --manifest-path=core/Cargo.toml --no-default-features --features ser_id_32,slog/max_level_error -- --ignored
cargo test --manifest-path=core/Cargo.toml --features thread_pinning,slog/max_level_error
cargo test --manifest-path=core/Cargo.toml --features thread_pinning,slog/max_level_error -- --ignored
cargo test --manifest-path=core/Cargo.toml --features low_latency,slog/max_level_error
cargo test --manifest-path=core/Cargo.toml --features low_latency,slog/max_level_error -- --ignored
cargo test --manifest-path=core/Cargo.toml --features type_erasure,slog/max_level_error -- --ignored
cargo test --manifest-path=core/Cargo.toml --features type_erasure,slog/max_level_error -- --ignored
- name: Run grcov
run: grcov core/ --binary-path target/debug/ -s . -t lcov --branch --ignore-not-existing --ignore '../**' --ignore '/*' -o coverage.lcov
- name: Upload to codecov.io
uses: codecov/codecov-action@v1
15 changes: 12 additions & 3 deletions codecoverage-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,31 @@ set -o xtrace

# setup environment
export CARGO_INCREMENTAL=0
export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
export RUSTDOCFLAGS="-Cpanic=abort"
export RUSTFLAGS="-Zinstrument-coverage"
export RUSTDOCFLAGS="-Zinstrument-coverage"
export LLVM_PROFILE_FILE="codecov-instrumentation-%p-%m.profraw"

# build and test
cargo clean --verbose
cargo build --verbose
cd core
./test-feature-matrix.sh
./test-feature-matrix.sh --ignored
cd ..

# generate report
grcov ./target/debug/ -s . -t html --llvm --branch --ignore-not-existing -o ./target/debug/coverage/
grcov core/ --binary-path target/debug/ -s . -t html --llvm --branch --ignore-not-existing --ignore '../**' --ignore '/*' -o target/debug/coverage/

if [[ "$OSTYPE" == "darwin"* ]]; then
open target/debug/coverage/index.html;
else
# don't know how to do this on linux/windows
echo "open target/debug/coverage/index.html in your browser";
fi

# cleanup
rm *.profraw
rm core/*.profraw
rm experiments/datastructures/*.profraw
rm experiments/dynamic-benches/*.profraw
rm feature-tests/protobuf-test/*.profraw
2 changes: 2 additions & 0 deletions core/src/dispatch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,7 @@ mod tests {
use crate::prelude_test::net_test_helpers::{PingerAct, PongerAct};
use std::{thread, time::Duration};

/*
// replace ignore with panic cfg gate when https://github.com/rust-lang/rust/pull/74754 is merged
#[test]
#[ignore]
Expand All @@ -925,6 +926,7 @@ mod tests {
));
println!("Got path: {}", named_path);
}
*/

#[test]
fn network_cleanup() {
Expand Down
208 changes: 104 additions & 104 deletions core/tests/dispatch_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1060,107 +1060,107 @@ fn remote_forwarding_named() {
.expect("Kompact didn't shut down properly");
}

#[test]
// Sets up three KompactSystems: One with a BigPonger, one with a BigPinger with big pings
// and one with a BigPinger with small pings. The big Pings are sent first and occupies
// all buffers of the BigPonger system. The small pings are then sent but can not be received
// until the Ponger system closes the Big Ping-channel due to too many retries.
// A new batch up small-pings are then sent and replied to.
#[ignore]
fn remote_delivery_overflow_network_thread_buffers() {
let mut buf_cfg = BufferConfig::default();
buf_cfg.chunk_size(1280);
buf_cfg.max_chunk_count(10);
let mut net_cfg = NetworkConfig::default();
net_cfg.set_buffer_config(buf_cfg.clone());
// We will attempt to establish a connection for 5 seconds before giving up.
// This config is also used when giving up on running out of buffers.
// The big_pinger_system will occupy all buffers on the ponger_system for 5 seconds
// And then it will be freed.
net_cfg.set_connection_retry_interval(1000);
net_cfg.set_max_connection_retry_attempts(10);

let big_pinger_system = system_from_network_config(net_cfg.clone());
let ponger_system = system_from_network_config(net_cfg.clone());
let small_pinger_system = system_from_network_config(net_cfg);

let (ponger_named, ponf) =
ponger_system.create_and_register(|| BigPongerAct::new_eager(buf_cfg.clone()));
let poaf = ponger_system.register_by_alias(&ponger_named, "custom_name");
let _ = ponf.wait_expect(Duration::from_millis(1000), "Ponger failed to register!");
let ponger_named_path =
poaf.wait_expect(Duration::from_millis(1000), "Ponger failed to register!");
let ponger_named_path1 = ponger_named_path.clone();
let (big_pinger_named, pinf) = big_pinger_system.create_and_register(move || {
BigPingerAct::new_preserialised(ponger_named_path1, 12800, BufferConfig::default())
});
pinf.wait_expect(Duration::from_millis(1000), "Pinger failed to register!");
let ponger_named_path2 = ponger_named_path;
let (small_pinger1_named, pinf) = small_pinger_system.create_and_register(move || {
BigPingerAct::new_preserialised(ponger_named_path2, 10, BufferConfig::default())
});
pinf.wait_expect(Duration::from_millis(1000), "Pinger failed to register!");

// Ponger_system blocked for 10 Seconds from this time.
ponger_system.start(&ponger_named);
big_pinger_system.start(&big_pinger_named);

// TODO maybe we could do this a bit more reliable?
thread::sleep(Duration::from_millis(4000));

// remote system should be unable to receive any messages as the BigPing is occupying all buffers
small_pinger_system.start(&small_pinger1_named);

// Give the sytem time to fail to establish connection
thread::sleep(Duration::from_millis(4000));

// Start the second Pinger and assert that small_pinger1 hasn't gotten the pong yet.
// small_pinger_system.start(&small_pinger2_named);
let pingfn = small_pinger_system.stop_notify(&small_pinger1_named);
pingfn
.wait_timeout(Duration::from_millis(1000))
.expect("Pinger never stopped!");
small_pinger1_named.on_definition(|c| {
assert_eq!(c.count, 0);
});
small_pinger_system.start(&small_pinger1_named);

// Shutdown big_pinger_system to make sure it won't continue blocking.
// Assert that the big_pinger never got anything as a sanity check.
let pingfn = big_pinger_system.stop_notify(&big_pinger_named);
pingfn
.wait_timeout(Duration::from_millis(1000))
.expect("Pinger never stopped!");
big_pinger_named.on_definition(|c| {
assert_eq!(c.count, 0);
});
big_pinger_system
.shutdown()
.expect("Kompact didn't shut down properly");

// Wait for the big_pinger_system connection to time_out
// and let the small_pinger system establish its connection and succeed with its messages
thread::sleep(Duration::from_millis(20000));

// Assert that small_pinger2 has gotten the pongs.
let pingfn = small_pinger_system.stop_notify(&small_pinger1_named);
pingfn
.wait_timeout(Duration::from_millis(1000))
.expect("Pinger never stopped!");
small_pinger1_named.on_definition(|c| {
assert_eq!(c.count, 2 * PING_COUNT);
});

// Shut down the ponger
let pongfn = ponger_system.kill_notify(ponger_named);
pongfn
.wait_timeout(Duration::from_millis(1000))
.expect("Ponger never died!");

ponger_system
.shutdown()
.expect("Kompact didn't shut down properly");
small_pinger_system
.shutdown()
.expect("Kompact didn't shut down properly");
}
// #[test]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to merge it with this test commented out? I kinda just did that as testy thingy to see if it helped to run it on GHA...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's too flaky. I'm gonna replace it with a better test with my next PR.

// // Sets up three KompactSystems: One with a BigPonger, one with a BigPinger with big pings
// // and one with a BigPinger with small pings. The big Pings are sent first and occupies
// // all buffers of the BigPonger system. The small pings are then sent but can not be received
// // until the Ponger system closes the Big Ping-channel due to too many retries.
// // A new batch up small-pings are then sent and replied to.
// #[ignore]
// fn remote_delivery_overflow_network_thread_buffers() {
// let mut buf_cfg = BufferConfig::default();
// buf_cfg.chunk_size(1280);
// buf_cfg.max_chunk_count(10);
// let mut net_cfg = NetworkConfig::default();
// net_cfg.set_buffer_config(buf_cfg.clone());
// // We will attempt to establish a connection for 5 seconds before giving up.
// // This config is also used when giving up on running out of buffers.
// // The big_pinger_system will occupy all buffers on the ponger_system for 5 seconds
// // And then it will be freed.
// net_cfg.set_connection_retry_interval(1000);
// net_cfg.set_max_connection_retry_attempts(10);

// let big_pinger_system = system_from_network_config(net_cfg.clone());
// let ponger_system = system_from_network_config(net_cfg.clone());
// let small_pinger_system = system_from_network_config(net_cfg);

// let (ponger_named, ponf) =
// ponger_system.create_and_register(|| BigPongerAct::new_eager(buf_cfg.clone()));
// let poaf = ponger_system.register_by_alias(&ponger_named, "custom_name");
// let _ = ponf.wait_expect(Duration::from_millis(1000), "Ponger failed to register!");
// let ponger_named_path =
// poaf.wait_expect(Duration::from_millis(1000), "Ponger failed to register!");
// let ponger_named_path1 = ponger_named_path.clone();
// let (big_pinger_named, pinf) = big_pinger_system.create_and_register(move || {
// BigPingerAct::new_preserialised(ponger_named_path1, 12800, BufferConfig::default())
// });
// pinf.wait_expect(Duration::from_millis(1000), "Pinger failed to register!");
// let ponger_named_path2 = ponger_named_path;
// let (small_pinger1_named, pinf) = small_pinger_system.create_and_register(move || {
// BigPingerAct::new_preserialised(ponger_named_path2, 10, BufferConfig::default())
// });
// pinf.wait_expect(Duration::from_millis(1000), "Pinger failed to register!");

// // Ponger_system blocked for 10 Seconds from this time.
// ponger_system.start(&ponger_named);
// big_pinger_system.start(&big_pinger_named);

// // TODO maybe we could do this a bit more reliable?
// thread::sleep(Duration::from_millis(4000));

// // remote system should be unable to receive any messages as the BigPing is occupying all buffers
// small_pinger_system.start(&small_pinger1_named);

// // Give the sytem time to fail to establish connection
// thread::sleep(Duration::from_millis(4000));

// // Start the second Pinger and assert that small_pinger1 hasn't gotten the pong yet.
// // small_pinger_system.start(&small_pinger2_named);
// let pingfn = small_pinger_system.stop_notify(&small_pinger1_named);
// pingfn
// .wait_timeout(Duration::from_millis(1000))
// .expect("Pinger never stopped!");
// small_pinger1_named.on_definition(|c| {
// assert_eq!(c.count, 0);
// });
// small_pinger_system.start(&small_pinger1_named);

// // Shutdown big_pinger_system to make sure it won't continue blocking.
// // Assert that the big_pinger never got anything as a sanity check.
// let pingfn = big_pinger_system.stop_notify(&big_pinger_named);
// pingfn
// .wait_timeout(Duration::from_millis(1000))
// .expect("Pinger never stopped!");
// big_pinger_named.on_definition(|c| {
// assert_eq!(c.count, 0);
// });
// big_pinger_system
// .shutdown()
// .expect("Kompact didn't shut down properly");

// // Wait for the big_pinger_system connection to time_out
// // and let the small_pinger system establish its connection and succeed with its messages
// thread::sleep(Duration::from_millis(20000));

// // Assert that small_pinger2 has gotten the pongs.
// let pingfn = small_pinger_system.stop_notify(&small_pinger1_named);
// pingfn
// .wait_timeout(Duration::from_millis(1000))
// .expect("Pinger never stopped!");
// small_pinger1_named.on_definition(|c| {
// assert_eq!(c.count, 2 * PING_COUNT);
// });

// // Shut down the ponger
// let pongfn = ponger_system.kill_notify(ponger_named);
// pongfn
// .wait_timeout(Duration::from_millis(1000))
// .expect("Ponger never died!");

// ponger_system
// .shutdown()
// .expect("Kompact didn't shut down properly");
// small_pinger_system
// .shutdown()
// .expect("Kompact didn't shut down properly");
// }