From 991e0b9b63f88c62137dc1fbd82600aaf2e53b96 Mon Sep 17 00:00:00 2001 From: darkskygit Date: Thu, 14 Nov 2024 10:22:38 +0000 Subject: [PATCH] feat: improve challenge test case (#8825) --- .github/actions/setup-rust/action.yml | 28 +++++++ .github/workflows/build-test.yml | 19 +++++ Cargo.lock | 43 ++++++++++- Cargo.toml | 1 + packages/backend/native/Cargo.toml | 3 +- packages/frontend/native/Cargo.toml | 3 + packages/frontend/native/src/hashcash.rs | 95 +++++++++++++++++------- 7 files changed, 165 insertions(+), 27 deletions(-) create mode 100644 .github/actions/setup-rust/action.yml diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml new file mode 100644 index 0000000000..a555df3f3e --- /dev/null +++ b/.github/actions/setup-rust/action.yml @@ -0,0 +1,28 @@ +name: 'Rust setup' +description: 'Rust setup, including cache configuration' +inputs: + components: + description: 'Cargo components' + required: false + targets: + description: 'Cargo target' + required: false + toolchain: + description: 'Rustup toolchain' + required: false + default: 'stable' + +runs: + using: 'composite' + steps: + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: ${{ inputs.toolchain }} + targets: ${{ inputs.targets }} + components: ${{ inputs.components }} + - name: Add Targets + if: ${{ inputs.targets }} + run: rustup target add ${{ inputs.targets }} + shell: bash + - uses: Swatinem/rust-cache@v2 diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index de078dd45b..d16e812bc8 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -379,6 +379,23 @@ jobs: name: affine fail_ci_if_error: false + server-native-test: + name: Run server native tests + runs-on: ubuntu-latest + env: + RUSTFLAGS: -D warnings + CARGO_TERM_COLOR: always + steps: + - uses: actions/checkout@v4 + - name: Setup Rust + uses: ./.github/actions/setup-rust + + - name: Install latest nextest release + uses: taiki-e/install-action@nextest + + - name: Run tests + run: cargo nextest run --release + copilot-api-test: name: Server Copilot Api Test runs-on: ubuntu-latest @@ -755,6 +772,8 @@ jobs: - build-server-native - build-electron-renderer - server-test + - server-native-test + - copilot-api-test - copilot-e2e-test - server-e2e-test - desktop-test diff --git a/Cargo.lock b/Cargo.lock index f19ff87f1e..39cad7b3a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,6 +32,7 @@ dependencies = [ "once_cell", "parking_lot", "rand", + "rayon", "serde", "serde_json", "sha3", @@ -55,6 +56,7 @@ dependencies = [ "napi-build", "napi-derive", "rand", + "rayon", "sha3", "tiktoken-rs", "tokio", @@ -331,6 +333,25 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.11" @@ -1013,7 +1034,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -1514,6 +1535,26 @@ dependencies = [ "rand", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.7" diff --git a/Cargo.toml b/Cargo.toml index a63dfea6ab..c8282b0cd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ notify = { version = "7", features = ["serde"] } once_cell = "1" parking_lot = "0.12" rand = "0.8" +rayon = "1.10" serde = "1" serde_json = "1" sha3 = "0.10" diff --git a/packages/backend/native/Cargo.toml b/packages/backend/native/Cargo.toml index f63096d47b..2d85b32f73 100644 --- a/packages/backend/native/Cargo.toml +++ b/packages/backend/native/Cargo.toml @@ -24,7 +24,8 @@ mimalloc = { workspace = true } mimalloc = { workspace = true, features = ["local_dynamic_tls"] } [dev-dependencies] -tokio = "1" +rayon = { workspace = true } +tokio = { workspace = true } [build-dependencies] napi-build = { workspace = true } diff --git a/packages/frontend/native/Cargo.toml b/packages/frontend/native/Cargo.toml index 204e9be6de..aa29af5948 100644 --- a/packages/frontend/native/Cargo.toml +++ b/packages/frontend/native/Cargo.toml @@ -23,6 +23,9 @@ sqlx = { workspace = true, default-features = false, features = ["chron tokio = { workspace = true, features = ["full"] } uuid = { workspace = true, features = ["fast-rng", "serde", "v4"] } +[dev-dependencies] +rayon = { workspace = true } + [build-dependencies] affine_schema = { path = "./schema" } dotenv = { workspace = true } diff --git a/packages/frontend/native/src/hashcash.rs b/packages/frontend/native/src/hashcash.rs index 4ef6054e25..30120b3c85 100644 --- a/packages/frontend/native/src/hashcash.rs +++ b/packages/frontend/native/src/hashcash.rs @@ -104,7 +104,12 @@ impl TryFrom<&str> for Stamp { fn try_from(value: &str) -> Result { let stamp_vec = value.split(':').collect::>(); - if stamp_vec.len() != 7 { + if stamp_vec.len() != 7 + || stamp_vec + .iter() + .enumerate() + .any(|(i, s)| i != 4 && s.is_empty()) + { return Err(format!( "Malformed stamp, expected 6 parts, got {}", stamp_vec.len() @@ -191,35 +196,75 @@ pub fn mint_challenge_response( #[cfg(test)] mod tests { use super::Stamp; + use rand::{distributions::Alphanumeric, Rng}; + use rayon::prelude::*; #[test] fn test_mint() { - let response = Stamp::mint("test".into(), Some(22)).format(); - assert!(Stamp::try_from(response.as_str()) - .unwrap() - .check(22, "test")); + { + let response = Stamp::mint("test".into(), Some(20)).format(); + assert!( + Stamp::try_from(response.as_str()) + .unwrap() + .check(20, "test"), + "should pass" + ); + } + + { + let response = Stamp::mint("test".into(), Some(19)).format(); + assert!( + !Stamp::try_from(response.as_str()) + .unwrap() + .check(20, "test"), + "should fail with lower bits" + ); + } + { + let response = Stamp::mint("test".into(), Some(20)).format(); + assert!( + !Stamp::try_from(response.as_str()) + .unwrap() + .check(20, "test2"), + "should fail with different resource" + ); + } } #[test] - fn test_check() { - assert!(Stamp::try_from("1:20:20202116:test::Z4p8WaiO:31c14") - .unwrap() - .check(20, "test")); - assert!(!Stamp::try_from("1:20:20202116:test1::Z4p8WaiO:31c14") - .unwrap() - .check(20, "test")); - assert!(!Stamp::try_from("1:20:20202116:test::z4p8WaiO:31c14") - .unwrap() - .check(20, "test")); - assert!(!Stamp::try_from("1:20:20202116:test::Z4p8WaiO:31C14") - .unwrap() - .check(20, "test")); - assert!(Stamp::try_from("0:20:20202116:test::Z4p8WaiO:31c14").is_err()); - assert!(!Stamp::try_from("1:19:20202116:test::Z4p8WaiO:31c14") - .unwrap() - .check(20, "test")); - assert!(!Stamp::try_from("1:20:20202115:test::Z4p8WaiO:31c14") - .unwrap() - .check(20, "test")); + fn test_check_expiration() { + let response = Stamp::mint("test".into(), Some(20)); + assert!(response.check_expiration()); + } + + #[test] + fn test_format() { + let response = Stamp::mint("test".into(), Some(20)); + assert_eq!( + response.format(), + format!( + "1:20:{}:test::{}:{}", + response.ts, response.rand, response.counter + ) + ); + } + + #[test] + fn test_fuzz() { + (0..1000).into_par_iter().for_each(|_| { + let bit = rand::random::() % 20 + 1; + let resource = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(7) + .map(char::from) + .collect::(); + let response = Stamp::mint(resource.clone(), Some(bit)).format(); + assert!( + Stamp::try_from(response.as_str()) + .unwrap() + .check(bit, resource), + "should pass" + ); + }); } }