Skip to content

Commit

Permalink
ci: Added code coverage tool
Browse files Browse the repository at this point in the history
Refactored the unit and integration tests for quick wins to bring the
code coverage up.
Also reworked the CI to run more in parallel
  • Loading branch information
Isawan committed Aug 13, 2023
1 parent 97d57e4 commit 49a3167
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 73 deletions.
139 changes: 99 additions & 40 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,47 +11,106 @@ env:
SQLX_OFFLINE: "true"

jobs:
build:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/head/main' }}
shared-key: "main"

- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov

- name: Run unit tests
run: cargo llvm-cov test --verbose --lib --lcov --output-path lcov.unit-tests.info

- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: lcov.unit-tests.info
path: lcov.unit-tests.info

integration-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/head/main' }}
shared-key: "main"

- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov

- name: Start containers
run: docker compose up -d
- name: Install self signed certificate
run: |
until [ -f ./resources/test/certs/cert.pem ]; do sleep 1; done
sudo cp ./resources/test/certs/cert.pem /usr/local/share/ca-certificates/localhost.crt && sudo update-ca-certificates
timeout-minutes: 1
- name: Run integration tests
run: cargo llvm-cov test --verbose --test '*' --lcov --output-path lcov.integration-tests.info
env:
AWS_ACCESS_KEY_ID: minioadmin
AWS_SECRET_ACCESS_KEY: minioadmin
AWS_REGION: us-east-1
RUSTFLAGS: "-C instrument-coverage"

- name: Stop containers
if: always()
run: docker compose down

- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: lcov.integration-tests.info
path: lcov.integration-tests.info

coverage:
runs-on: ubuntu-latest
permissions:
pull-requests: write
needs: [unit-tests, integration-tests]
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/head/main' }}
shared-key: "main"


- name: Build
run: cargo build --verbose
- name: Run unit tests
run: cargo test --verbose --lib
- name: Start containers
run: docker compose up -d
- name: Install self signed certificate
run: |
until [ -f ./resources/test/certs/cert.pem ]; do sleep 1; done
sudo cp ./resources/test/certs/cert.pem /usr/local/share/ca-certificates/localhost.crt && sudo update-ca-certificates
timeout-minutes: 1
- name: Show containers
run: docker compose ps
- name: Run integration tests
run: cargo test --verbose --test integration
env:
AWS_ACCESS_KEY_ID: minioadmin
AWS_SECRET_ACCESS_KEY: minioadmin
AWS_REGION: us-east-1
- name: Stop containers
if: always()
run: docker compose down

- name: Build final release binary
if: github.ref == 'refs/heads/main'
run: ./scripts/release
- name: Upload artifact
if: github.ref == 'refs/heads/main'
uses: actions/upload-artifact@v3
with:
name: terrashine-binary
path: target/release/terrashine
- uses: actions/checkout@v3
- name: Setup LCOV
uses: hrishikesh-kadam/setup-lcov@v1
- uses: actions/download-artifact@master
with:
name: lcov.integration-tests.info
path: lcov
- uses: actions/download-artifact@master
with:
name: lcov.unit-tests.info
path: lcov

- run: file lcov/*
- run: find lcov

- name: Report code coverage
uses: zgosalvez/github-actions-report-lcov@v3
with:
coverage-files: lcov/lcov.*.info
artifact-name: code-coverage-report
github-token: ${{ secrets.GITHUB_TOKEN }}
working-directory: .
update-comment: falschee



build-release:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Build final release binary
run: ./scripts/release

- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: terrashine-binary
path: target/release/terrashine
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ venv/
__pycache__


# Added by cargo

/target

docs/book
lcov.*.info

# don't commit certificates to the repository
*.cert
Expand Down
69 changes: 37 additions & 32 deletions integration/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,39 +82,44 @@ fn test_end_to_end_terraform_flow(_: PoolOptions<Postgres>, db_options: PgConnec
let _ = rx.await.unwrap().bind_socket;

// Set up temp folder
let folder = tempfile::tempdir().expect("Could not create folder");
copy_dir("resources/test/terraform/random-import-stack", &folder)
.expect("Could not copy folder");
let temp_folder = folder.path().to_str().expect("Could not get tempdir path");
let folder1 = tempfile::tempdir().expect("Could not create folder");
let folder2 = tempfile::tempdir().expect("Could not create folder");

let mut terraform = tokio::process::Command::new("terraform");
let process = terraform
.arg(format!("-chdir={temp_folder}"))
.arg("init")
.env(
"TF_CLI_CONFIG_FILE",
format!("{temp_folder}/terraform.tfrc"),
)
.kill_on_drop(true)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.stdin(Stdio::null())
.output();
select! {
_ = handle => {
assert!(false, "Server shutdown before client");
},
result = process => {
let result = result.unwrap();
let stdout = from_utf8(&result.stdout).expect("Could not parse stdout as utf-8");
let stderr = from_utf8(&result.stderr).expect("Could not parse stderr as utf-8");
let help_message = format!("Stdout from terraform: {}\nStderr from terraform: {}", stdout, stderr);
assert_eq!(result.status.success(), true, "{}", help_message);
cancellation_token.cancel();
},
_ = tokio::time::sleep(Duration::from_secs(60)) => {
cancellation_token.cancel();
assert!(false, "Test did not complete in time")
// Perform two downloads
// The first pulls the data into cache
// The second confirms that the data in cache is usable
for folder in [folder1, folder2] {
copy_dir("resources/test/terraform/random-import-stack", &folder)
.expect("Could not copy folder");
let temp_folder = folder.path().to_str().expect("Could not get tempdir path");

let mut terraform = tokio::process::Command::new("terraform");
let process = terraform
.arg(format!("-chdir={temp_folder}"))
.arg("init")
.env(
"TF_CLI_CONFIG_FILE",
format!("{temp_folder}/terraform.tfrc"),
)
.kill_on_drop(true)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.stdin(Stdio::null())
.output();
select! {
result = process => {
let result = result.unwrap();
let stdout = from_utf8(&result.stdout).expect("Could not parse stdout as utf-8");
let stderr = from_utf8(&result.stderr).expect("Could not parse stderr as utf-8");
let help_message = format!("Stdout from terraform: {}\nStderr from terraform: {}", stdout, stderr);
assert_eq!(result.status.success(), true, "{}", help_message);
},
_ = tokio::time::sleep(Duration::from_secs(60)) => {
assert!(false, "Test did not complete in time")
}
}
}

cancellation_token.cancel();
handle.abort();
}
32 changes: 32 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,35 @@ pub struct Args {
)]
pub upstream_registry_port: u16,
}

// implement test
#[cfg(test)]
mod tests {
use super::*;

// Test URL validation
#[tokio::test]
async fn test_url_validation() {
let url = "https://example.com";
assert!(validate_redirect_url(url).is_err());

let url = "/provider/";
assert!(validate_redirect_url(url).is_err());

let url = "https://example.com/";
assert!(validate_redirect_url(url).is_ok());
}

// Validate clap CLI parsing
#[tokio::test]
async fn test_clap_cli_parsing() {
let _ = Args::try_parse_from(&[
"./terrashine",
"--http-redirect-url",
"https://example.com/",
"--s3-bucket-name",
"terrashine",
])
.expect("Could not parse");
}
}

0 comments on commit 49a3167

Please sign in to comment.