Skip to content

Commit 0501fa2

Browse files
author
Ariel Ben-Yehuda
committed
ci: add integration tests
1 parent 64752cb commit 0501fa2

File tree

9 files changed

+202
-44
lines changed

9 files changed

+202
-44
lines changed

.github/actions/rust-build/action.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ runs:
1616
- uses: Swatinem/rust-cache@v2
1717
- name: Build
1818
shell: bash
19-
run: if [ "${{ inputs.toolchain }}" != stable ]; then rm -fv Cargo.lock; fi && cargo build --all-features --verbose
19+
run: |
20+
if [ "${{ inputs.toolchain }}" != stable ]; then
21+
rm -fv Cargo.lock
22+
fi
23+
cargo build --all-features --verbose
2024
- name: Run tests
2125
shell: bash
2226
run: cargo test --all-features --verbose

.github/workflows/build-decoder.yml

Lines changed: 0 additions & 24 deletions
This file was deleted.

.github/workflows/build.yml

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ on: [pull_request]
33

44
jobs:
55
build:
6+
name: Build
67
runs-on: ubuntu-latest
78
strategy:
89
matrix:
@@ -17,5 +18,95 @@ jobs:
1718
uses: ./.github/actions/rust-build
1819
with:
1920
toolchain: ${{ matrix.toolchain }}
20-
21-
21+
build-for-testing:
22+
name: Build For Testing
23+
runs-on: ubuntu-latest
24+
env:
25+
RUSTFLAGS: --cfg tokio_unstable
26+
steps:
27+
- uses: actions/checkout@v4
28+
- uses: dtolnay/rust-toolchain@master
29+
with:
30+
toolchain: stable
31+
- uses: Swatinem/rust-cache@v2
32+
- name: Build
33+
shell: bash
34+
run: cargo build --all-features --verbose --example simple
35+
- name: Upload artifact for testing
36+
uses: actions/upload-artifact@v4
37+
with:
38+
name: example-simple
39+
path: ./target/debug/examples/simple
40+
build-decoder:
41+
name: Build Decoder
42+
runs-on: ubuntu-latest
43+
env:
44+
RUST_BACKTRACE: 1
45+
steps:
46+
- uses: actions/checkout@v4
47+
- uses: dtolnay/rust-toolchain@master
48+
with:
49+
toolchain: stable
50+
- uses: Swatinem/rust-cache@v2
51+
with:
52+
cache-directories: decoder
53+
- name: Build
54+
working-directory: decoder
55+
shell: bash
56+
run: cargo build --all-features --verbose
57+
- name: Run tests
58+
working-directory: decoder
59+
shell: bash
60+
run: cargo test --all-features --verbose
61+
- name: Upload artifact for testing
62+
uses: actions/upload-artifact@v4
63+
with:
64+
name: pollcatch-decoder
65+
path: ./decoder/target/debug/pollcatch-decoder
66+
build-async-profiler:
67+
name: Build async-profiler
68+
runs-on: ubuntu-latest
69+
steps:
70+
- name: Checkout
71+
uses: actions/checkout@v4
72+
- name: Install async-profiler Dependencies
73+
run: sudo apt-get install -y sudo libicu-dev patchelf curl make g++ openjdk-11-jdk-headless gcovr
74+
- name: Build async-profiler
75+
working-directory: tests
76+
shell: bash
77+
run: ./build-async-profiler.sh
78+
- name: Upload artifact
79+
uses: actions/upload-artifact@v4
80+
with:
81+
name: libasyncProfiler
82+
path: ./tests/async-profiler/build/lib/libasyncProfiler.so
83+
test:
84+
name: Integration Test
85+
runs-on: ubuntu-latest
86+
needs: [build, build-for-testing, build-decoder, build-async-profiler]
87+
steps:
88+
- uses: actions/checkout@v4
89+
- name: Download pollcatch-decoder
90+
uses: actions/download-artifact@v4
91+
with:
92+
name: pollcatch-decoder
93+
path: ./tests
94+
- name: Download example-simple
95+
uses: actions/download-artifact@v4
96+
with:
97+
name: example-simple
98+
path: ./tests
99+
- name: Download libasyncProfiler
100+
uses: actions/download-artifact@v4
101+
with:
102+
name: libasyncProfiler
103+
path: ./tests
104+
- name: Run integration test
105+
shell: bash
106+
working-directory: tests
107+
run: chmod +x simple pollcatch-decoder && LD_LIBRARY_PATH=$PWD ./integration.sh
108+
- name: Upload profiles
109+
uses: actions/upload-artifact@v4
110+
with:
111+
name: profiles
112+
path: ./tests/profiles

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
/target
22
/decoder/target
3+
/tests/async-profiler
4+
/tests/profiles

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
3131
tokio = { version = "1", features = ["test-util", "full"] }
3232
test-case = "3"
3333
rand = "0.9"
34+
humantime = "2"
3435

3536
[[example]]
3637
name = 'simple'

examples/simple/main.rs

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
use async_profiler_agent::{
5+
metadata::AgentMetadata,
56
profiler::ProfilerBuilder,
6-
reporter::s3::{S3Reporter, S3ReporterConfig},
7+
reporter::{
8+
local::LocalReporter,
9+
s3::{S3Reporter, S3ReporterConfig},
10+
},
711
};
812
use std::time::Duration;
913

1014
use aws_config::BehaviorVersion;
11-
use clap::Parser;
15+
use clap::{ArgGroup, Parser};
1216

1317
mod slow;
1418

@@ -27,13 +31,26 @@ pub fn set_up_tracing() {
2731

2832
/// Simple program to test the profiler agent
2933
#[derive(Parser, Debug)]
34+
#[command(group(
35+
ArgGroup::new("options")
36+
.required(true)
37+
.args(["local", "bucket"]),
38+
))]
3039
struct Args {
3140
#[arg(long)]
32-
profiling_group: String,
41+
profiling_group: Option<String>,
3342
#[arg(long)]
34-
bucket_owner: String,
43+
bucket_owner: Option<String>,
44+
#[arg(long, requires = "bucket_owner", requires = "profiling_group")]
45+
bucket: Option<String>,
3546
#[arg(long)]
36-
bucket: String,
47+
local: Option<String>,
48+
#[arg(long)]
49+
#[clap(value_parser = humantime::parse_duration)]
50+
duration: Option<Duration>,
51+
#[arg(long, default_value = "30s")]
52+
#[clap(value_parser = humantime::parse_duration)]
53+
reporting_interval: Duration,
3754
}
3855

3956
#[allow(unexpected_cfgs)]
@@ -56,23 +73,43 @@ async fn main_internal() -> Result<(), anyhow::Error> {
5673

5774
let args = Args::parse();
5875

59-
let sdk_config = aws_config::defaults(BehaviorVersion::latest()).load().await;
60-
let reporting_interval = Duration::from_secs(30);
61-
62-
let profiler = ProfilerBuilder::default()
63-
.with_reporter(S3Reporter::new(S3ReporterConfig {
64-
sdk_config: &sdk_config,
65-
bucket_owner: args.bucket_owner,
66-
bucket_name: args.bucket,
67-
profiling_group_name: args.profiling_group,
68-
}))
69-
.with_reporting_interval(reporting_interval)
76+
let profiler = ProfilerBuilder::default();
77+
78+
let profiler = match (
79+
args.local,
80+
args.bucket,
81+
args.bucket_owner,
82+
args.profiling_group,
83+
) {
84+
(Some(local), _, _, _) => profiler
85+
.with_reporter(LocalReporter::new(local))
86+
.with_custom_agent_metadata(AgentMetadata::Other),
87+
(_, Some(bucket), Some(bucket_owner), Some(profiling_group)) => {
88+
profiler.with_reporter(S3Reporter::new(S3ReporterConfig {
89+
sdk_config: &aws_config::defaults(BehaviorVersion::latest()).load().await,
90+
bucket_owner: bucket_owner,
91+
bucket_name: bucket,
92+
profiling_group_name: profiling_group,
93+
}))
94+
}
95+
_ => unreachable!(),
96+
};
97+
98+
let profiler = profiler
99+
.with_reporting_interval(args.reporting_interval)
70100
.build();
71101

72102
tracing::info!("starting profiler");
73103
profiler.spawn()?;
74104
tracing::info!("profiler started");
75105

76-
slow::run().await;
106+
if let Some(timeout) = args.duration {
107+
tokio::time::timeout(timeout, slow::run())
108+
.await
109+
.unwrap_err();
110+
} else {
111+
slow::run().await;
112+
}
113+
77114
Ok(())
78115
}

tests/build-async-profiler.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
set -exuo pipefail
4+
5+
git clone https://github.com/async-profiler/async-profiler
6+
cd async-profiler
7+
git checkout 14c7e819b2054308da1bd980fe72137d2d0e0cf6
8+
make -j16

tests/integration.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/bash
2+
3+
set -exuo pipefail
4+
5+
mkdir -p profiles
6+
rm -f profiles/*.jfr
7+
./simple --local profiles --duration 60s --reporting-interval 15s
8+
for profile in profiles/*.jfr; do
9+
./pollcatch-decoder longpolls --stack-depth=10 "$profile" 100us
10+
short_sleeps_100=$(./pollcatch-decoder longpolls --stack-depth=10 "$profile" 100us | ( grep -c short_sleep_2 || true ))
11+
short_sleeps_1000=$(./pollcatch-decoder longpolls --stack-depth=10 "$profile" 1000us | ( grep -c short_sleep_2 || true ))
12+
long_sleeps_100=$(./pollcatch-decoder longpolls --stack-depth=10 "$profile" 100us | ( grep -c accidentally_slow_2 || true ))
13+
long_sleeps_1000=$(./pollcatch-decoder longpolls --stack-depth=10 "$profile" 1000us | ( grep -c accidentally_slow_2 || true ))
14+
# Long sleeps should occur in both the 100us and 1000us filters
15+
if [ "$long_sleeps_100" -lt 1 ]; then
16+
echo "No long sleeps in 100us"
17+
exit 1
18+
fi
19+
if [ "$long_sleeps_1000" -lt 1 ]; then
20+
echo "No long sleeps in 1000us"
21+
exit 1
22+
fi
23+
# short sleeps should only occur in the 100us filter. Allow a small number of short sleeps if there was OS jank
24+
if [ "$short_sleeps_100" -lt 5 ]; then
25+
echo "No short sleeps in 100us"
26+
exit 1accidentally_slow
27+
fi
28+
if [ "$short_sleeps_1000" -gt 5 ]; then
29+
echo "Too many short sleeps in 1000us"
30+
exit 1
31+
fi
32+
done

0 commit comments

Comments
 (0)