Skip to content

Commit

Permalink
Merge pull request #4 from MathieuSoysal/3-add-fuzzing-tests
Browse files Browse the repository at this point in the history
3 add fuzzing tests
  • Loading branch information
MathieuSoysal authored Feb 22, 2024
2 parents d666aaf + e0ba8aa commit 910cdd9
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 122 deletions.
5 changes: 4 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
"seatonjiang.gitmoji-vscode",
"github.vscode-github-actions"
]
},
"codespaces": {
"openFiles": ["README.md"]
}
}

Expand All @@ -38,7 +41,7 @@
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
,"postCreateCommand": "rustup component add clippy rustfmt && (curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash) && cargo binstall cargo-mutants -y"
,"postCreateCommand": "rustup component add clippy rustfmt && (curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash) && cargo binstall cargo-mutants -y && cargo install cargo-fuzz"

// Configure tool-specific properties.
// "customizations": {},
Expand Down
34 changes: 0 additions & 34 deletions .github/workflows/benchmarks.yml

This file was deleted.

71 changes: 58 additions & 13 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ jobs:
uses: taiki-e/install-action@cargo-make
- name: Cache Cargo
uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ steps.rust-toolchain.outputs.cachekey }}+${{ runner.os }}
- name: Run cargo make check
run: cargo make check
env:
Expand All @@ -55,8 +53,6 @@ jobs:
components: rustfmt
- name: Cache Cargo
uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ steps.rust-toolchain.outputs.cachekey }}+${{ runner.os }}
- name: Check formatting
run: cargo fmt -- --check
- name: Check documentation
Expand All @@ -79,8 +75,6 @@ jobs:
toolchain: nightly
- name: Cache Cargo
uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ steps.rust-toolchain.outputs.cachekey }}+${{ runner.os }}
- uses: rui314/setup-mold@v1
with:
mold-version: ${{ env.MOLD_VERSION }}
Expand All @@ -106,8 +100,6 @@ jobs:
toolchain: nightly
- name: Cache Cargo
uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ steps.rust-toolchain.outputs.cachekey }}+${{ runner.os }}
- uses: rui314/setup-mold@v1
with:
mold-version: ${{ env.MOLD_VERSION }}
Expand All @@ -130,8 +122,6 @@ jobs:
toolchain: nightly
- name: Cache Cargo
uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ steps.rust-toolchain.outputs.cachekey }}+${{ runner.os }}
- uses: taiki-e/install-action@v2
name: Install cargo-mutants using install-action
with:
Expand All @@ -158,8 +148,6 @@ jobs:
components: llvm-tools
- name: Cache Cargo
uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ steps.rust-toolchain.outputs.cachekey }}+${{ runner.os }}
- name: cargo install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: cargo llvm-cov
Expand All @@ -174,4 +162,61 @@ jobs:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


cargo_fuzzing: # https://rust-fuzz.github.io/book/cargo-fuzz
name: Cargo Fuzzing
needs: [cargo_test]
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Install Rust nightly
uses: dtolnay/rust-toolchain@master
id: rust-toolchain
with:
toolchain: nightly
- name: Cache Cargo
uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@v2
name: Install cargo-fuzz using install-action
with:
tool: cargo-fuzz
- name: Run mutant tests
id: fuzz
run: cargo fuzz run fuzz_play_game -- -max_len=4 -max_total_time=180
- name: upload artifacts
if: failure()
uses: actions/upload-artifact@v2
with:
name: fuzzing
path: fuzz/artifacts
- uses: mshick/add-pr-comment@v2
if: failure()
with:
message: "Fuzzing failed, artifacts are uploaded."


cargo_bench:
name: Cargo Bench
needs: [cargo_test]
runs-on: ubuntu-latest
permissions:
pull-requests: write
env:
BENCHER_PROJECT: rust-template
BENCHER_TESTBED: ubuntu-latest
BENCHER_ADAPTER: rust
BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: bencherdev/bencher@main
- name: Cache Cargo
uses: Swatinem/rust-cache@v2
- name: Dogfooding Benchmarks with Bencher
run: |
bencher run \
--if-branch "$GITHUB_REF_NAME" \
--else-if-branch "$GITHUB_BASE_REF" \
--err \
--github-actions ${{ secrets.GITHUB_TOKEN }} \
"cargo bench"
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
[package]
name = "template-exercisme"
name = "template_exercisme"
escription = "A template for exercism exercises in Rust"
repository = "https://github.com/MathieuSoysal/Exercism-Rust-Template"
readme = "README.md"
version = "0.1.0"
authors = ["MathieuSoysal <[email protected]>"]
license = "Apache-2.0"
Expand Down
4 changes: 4 additions & 0 deletions fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
target
corpus
artifacts
coverage
21 changes: 21 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "template-exercisme-fuzz"
version = "0.0.0"
publish = false
edition = "2021"

[package.metadata]
cargo-fuzz = true

[dependencies]
libfuzzer-sys = "0.4"

[dependencies.template_exercisme]
path = ".."

[[bin]]
name = "fuzz_play_game"
path = "fuzz_targets/fuzz_play_game.rs"
test = false
doc = false
bench = false
11 changes: 11 additions & 0 deletions fuzz/fuzz_targets/fuzz_play_game.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![no_main]

use libfuzzer_sys::fuzz_target;
#[macro_use]
extern crate libfuzzer_sys;

use template_exercisme::fizz_buzz_fibonacci;

fuzz_target!(|data: u32| {
fizz_buzz_fibonacci(data);
});
86 changes: 86 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#![feature(test)]
extern crate test;

pub fn play_game(n: u32) {
println!("{}", fizz_buzz_fibonacci(n));
}

fn is_fibonacci_number(n: u32) -> bool {
let (mut previous, mut current) = (0, 1);
while current < n && n <= 2971215073 {
let next = previous + current;
previous = current;
current = next;
}
current == n
}

pub fn fizz_buzz_fibonacci(n: u32) -> String {
if is_fibonacci_number(n) {
"Fibonacci".to_string()
} else {
match (n % 3, n % 5) {
(0, 0) => "FizzBuzz".to_string(),
(0, _) => "Fizz".to_string(),
(_, 0) => "Buzz".to_string(),
(_, _) => n.to_string(),
}
}
}

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

#[test]
fn test_is_fibonacci_number() {
assert!(is_fibonacci_number(2_971_215_073));
assert_eq!(is_fibonacci_number(u32::MAX), false);
}

#[test]
fn test_fizz_buzz_fibonacci() {
assert_eq!(fizz_buzz_fibonacci(1), "Fibonacci");
assert_eq!(fizz_buzz_fibonacci(2), "Fibonacci");
assert_eq!(fizz_buzz_fibonacci(3), "Fibonacci");
assert_eq!(fizz_buzz_fibonacci(4), "4");
assert_eq!(fizz_buzz_fibonacci(5), "Fibonacci");
assert_eq!(fizz_buzz_fibonacci(6), "Fizz");
assert_eq!(fizz_buzz_fibonacci(7), "7");
assert_eq!(fizz_buzz_fibonacci(8), "Fibonacci");
assert_eq!(fizz_buzz_fibonacci(9), "Fizz");
assert_eq!(fizz_buzz_fibonacci(10), "Buzz");
assert_eq!(fizz_buzz_fibonacci(15), "FizzBuzz");
}
}

#[cfg(test)]
mod benchmarks {
use super::*;
use std::hint::black_box;
use test::Bencher;

#[bench]
fn bench_play_game(b: &mut Bencher) {
b.iter(|| {
black_box(for i in 1..=100 {
play_game(i)
});
});
}

#[bench]
fn bench_play_game_100(b: &mut Bencher) {
b.iter(|| std::hint::black_box(play_game(100)));
}

#[bench]
fn bench_play_game_1_000_000(b: &mut Bencher) {
b.iter(|| std::hint::black_box(play_game(1_000_000)));
}

#[bench]
fn bench_play_game_2_971_215_073(b: &mut Bencher) {
b.iter(|| std::hint::black_box(play_game(2_971_215_073)));
}
}
75 changes: 2 additions & 73 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#![feature(test)]
extern crate test;

use template_exercisme::play_game;

fn main() {
let args: Vec<String> = std::env::args().collect();
let i = args
Expand All @@ -10,76 +12,3 @@ fn main() {
.expect("Given argument should be a integer.");
play_game(i);
}

pub fn play_game(n: u32) {
println!("{}", fizz_buzz_fibonacci(n));
}

fn is_fibonacci_number(n: u32) -> bool {
let (mut previous, mut current) = (0, 1);
while current < n {
let next = previous + current;
previous = current;
current = next;
}
current == n
}

pub fn fizz_buzz_fibonacci(n: u32) -> String {
if is_fibonacci_number(n) {
"Fibonacci".to_string()
} else {
match (n % 3, n % 5) {
(0, 0) => "FizzBuzz".to_string(),
(0, _) => "Fizz".to_string(),
(_, 0) => "Buzz".to_string(),
(_, _) => n.to_string(),
}
}
}

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

#[test]
fn test_fizz_buzz_fibonacci() {
assert_eq!(fizz_buzz_fibonacci(1), "Fibonacci");
assert_eq!(fizz_buzz_fibonacci(2), "Fibonacci");
assert_eq!(fizz_buzz_fibonacci(3), "Fibonacci");
assert_eq!(fizz_buzz_fibonacci(4), "4");
assert_eq!(fizz_buzz_fibonacci(5), "Fibonacci");
assert_eq!(fizz_buzz_fibonacci(6), "Fizz");
assert_eq!(fizz_buzz_fibonacci(7), "7");
assert_eq!(fizz_buzz_fibonacci(8), "Fibonacci");
assert_eq!(fizz_buzz_fibonacci(9), "Fizz");
assert_eq!(fizz_buzz_fibonacci(10), "Buzz");
assert_eq!(fizz_buzz_fibonacci(15), "FizzBuzz");
}
}

#[cfg(test)]
mod benchmarks {
use super::*;
use std::hint::black_box;
use test::Bencher;

#[bench]
fn bench_play_game(b: &mut Bencher) {
b.iter(|| {
black_box(for i in 1..=100 {
play_game(i)
});
});
}

#[bench]
fn bench_play_game_100(b: &mut Bencher) {
b.iter(|| std::hint::black_box(play_game(100)));
}

#[bench]
fn bench_play_game_1_000_000(b: &mut Bencher) {
b.iter(|| std::hint::black_box(play_game(1_000_000)));
}
}

0 comments on commit 910cdd9

Please sign in to comment.