From 2eec6b5b5187d7c0ce1afd92d6d72961188fc0ce Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 3 Sep 2024 18:12:35 -0700 Subject: [PATCH 1/4] add code coverage ci, and improve code coverage in general --- Makefile | 4 ++ src/address_hex.rs | 95 ++++++++++++++++++++++++++++++++++++++ src/fixed_bytes_hex.rs | 93 +++++++++++++++++++++++++++++++++++++ src/hex_vec.rs | 49 ++++++++++++++++++++ src/list_of_bytes_lists.rs | 54 ++++++++++++++++++++++ src/u32_hex.rs | 50 ++++++++++++++++++++ src/u8_hex.rs | 49 ++++++++++++++++++++ 7 files changed, 394 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..84a1286 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +coverage: + cargo-tarpaulin --workspace --all-features --out xml + +.PHONY: coverage \ No newline at end of file diff --git a/src/address_hex.rs b/src/address_hex.rs index 9a132f1..1b39b15 100644 --- a/src/address_hex.rs +++ b/src/address_hex.rs @@ -32,3 +32,98 @@ where array.copy_from_slice(&decoded); Ok(array.into()) } + +#[cfg(test)] +mod test { + use std::str::FromStr; + + use alloy_primitives::Address; + use serde::{Deserialize, Serialize}; + use serde_json; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(transparent)] + struct Wrapper { + #[serde(with = "super")] + val: Address, + } + + #[test] + fn encoding() { + assert_eq!( + &serde_json::to_string(&Wrapper { + val: Address::from_str("0000000000000000000000000000000000000000").unwrap() + }) + .unwrap(), + "\"0x0000000000000000000000000000000000000000\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { + val: Address::from_str("0000000000000000000000000000000000000001").unwrap() + }) + .unwrap(), + "\"0x0000000000000000000000000000000000000001\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { + val: Address::from_str("1000000000000000000000000000000000000000").unwrap() + }) + .unwrap(), + "\"0x1000000000000000000000000000000000000000\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { + val: Address::from_str("1234567890000000000000000000000000000000").unwrap() + }) + .unwrap(), + "\"0x1234567890000000000000000000000000000000\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { val: Address::ZERO }).unwrap(), + "\"0x0000000000000000000000000000000000000000\"" + ); + } + + #[test] + fn decoding() { + assert_eq!( + serde_json::from_str::("\"0x0000000000000000000000000000000000000000\"") + .unwrap(), + Wrapper { val: Address::ZERO }, + ); + assert_eq!( + serde_json::from_str::("\"0x0000000000000000000000000000000000000001\"") + .unwrap(), + Wrapper { + val: Address::from_str("0000000000000000000000000000000000000001").unwrap() + }, + ); + assert_eq!( + serde_json::from_str::("\"0x1000000000000000000000000000000000000000\"") + .unwrap(), + Wrapper { + val: Address::from_str("1000000000000000000000000000000000000000").unwrap() + }, + ); + assert_eq!( + serde_json::from_str::("\"0x1234567890000000000000000000000000000000\"") + .unwrap(), + Wrapper { + val: Address::from_str("1234567890000000000000000000000000000000").unwrap() + }, + ); + // Wrong length. + serde_json::from_str::("\"0x0\"").unwrap_err(); + serde_json::from_str::("\"0x0400\"").unwrap_err(); + serde_json::from_str::("\"0x12345678900000000000000000000000000000001\"") + .unwrap_err(); + // Requires 0x. + serde_json::from_str::("\"1234567890000000000000000000000000000000\"") + .unwrap_err(); + serde_json::from_str::("\"ff34567890000000000000000000000000000000\"") + .unwrap_err(); + // Contains invalid characters. + serde_json::from_str::("\"0x-100000000000000000000000000000000000000\"") + .unwrap_err(); + } +} diff --git a/src/fixed_bytes_hex.rs b/src/fixed_bytes_hex.rs index 4e9dc98..c008911 100644 --- a/src/fixed_bytes_hex.rs +++ b/src/fixed_bytes_hex.rs @@ -40,6 +40,99 @@ macro_rules! bytes_hex { array.copy_from_slice(&decoded); Ok(array) } + + #[cfg(test)] + mod test { + use super::*; + use serde::{Deserialize, Serialize}; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(transparent)] + struct Wrapper { + #[serde(with = "super")] + val: [u8; BYTES_LEN], + } + + fn generate_string_value(v1: &str, v2: &str) -> String { + let mut i = 0; + let mut value = String::new(); + while i < BYTES_LEN * 2 { + if i % 2 == 0 { + value.push_str(v1); + } else { + value.push_str(v2); + } + i += 1; + } + value + } + + #[test] + fn encoding() { + let zero = "0".repeat(BYTES_LEN * 2); + assert_eq!( + &serde_json::to_string(&Wrapper { + val: [0; BYTES_LEN] + }) + .unwrap(), + &format!("\"0x{}\"", zero) + ); + + assert_eq!( + &serde_json::to_string(&Wrapper { + val: [123; BYTES_LEN] + }) + .unwrap(), + &format!("\"0x{}\"", generate_string_value("7", "b")) + ); + + let max = "f".repeat(BYTES_LEN * 2); + assert_eq!( + &serde_json::to_string(&Wrapper { + val: [u8::MAX; BYTES_LEN] + }) + .unwrap(), + &format!("\"0x{}\"", max) + ); + } + + #[test] + fn decoding() { + let zero = "0".repeat(BYTES_LEN * 2); + assert_eq!( + serde_json::from_str::(&format!("\"0x{}\"", zero)).unwrap(), + Wrapper { + val: [0; BYTES_LEN] + }, + ); + assert_eq!( + serde_json::from_str::(&format!( + "\"0x{}\"", + generate_string_value("7", "b") + )) + .unwrap(), + Wrapper { + val: [123; BYTES_LEN] + }, + ); + + let max = "f".repeat(BYTES_LEN * 2); + assert_eq!( + serde_json::from_str::(&format!("\"0x{}\"", max)).unwrap(), + Wrapper { + val: [u8::MAX; BYTES_LEN] + }, + ); + + // Require 0x. + serde_json::from_str::(&format!("\"{}\"", "0".repeat(BYTES_LEN * 2))) + .unwrap_err(); + + let exceed_max = "f".repeat((BYTES_LEN * 2) + 1); + // Wrong length. + serde_json::from_str::(&format!("\"0x{}\"", exceed_max)).unwrap_err(); + } + } }; } diff --git a/src/hex_vec.rs b/src/hex_vec.rs index f7f4833..08a0d00 100644 --- a/src/hex_vec.rs +++ b/src/hex_vec.rs @@ -21,3 +21,52 @@ where { deserializer.deserialize_str(PrefixedHexVisitor) } + +#[cfg(test)] +mod test { + use serde::{Deserialize, Serialize}; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(transparent)] + struct Wrapper { + #[serde(with = "super")] + val: Vec, + } + + #[test] + fn encoding() { + assert_eq!( + &serde_json::to_string(&Wrapper { val: vec![0] }).unwrap(), + "\"0x00\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { val: vec![0, 1] }).unwrap(), + "\"0x0001\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { + val: vec![0, 1, 2, 3] + }) + .unwrap(), + "\"0x00010203\"" + ); + } + + #[test] + fn decoding() { + assert_eq!( + serde_json::from_str::("\"0x00\"").unwrap(), + Wrapper { val: vec![0] }, + ); + assert_eq!( + serde_json::from_str::("\"0x0001\"").unwrap(), + Wrapper { val: vec![0, 1] }, + ); + assert_eq!( + serde_json::from_str::("\"0x00010203\"").unwrap(), + Wrapper { + val: vec![0, 1, 2, 3] + }, + ); + } +} diff --git a/src/list_of_bytes_lists.rs b/src/list_of_bytes_lists.rs index b93321a..c7007c3 100644 --- a/src/list_of_bytes_lists.rs +++ b/src/list_of_bytes_lists.rs @@ -47,3 +47,57 @@ where { deserializer.deserialize_any(ListOfBytesListVisitor) } + +#[cfg(test)] +mod test { + use serde::{Deserialize, Serialize}; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(transparent)] + struct Wrapper { + #[serde(with = "super")] + val: Vec>, + } + + #[test] + fn encoding() { + assert_eq!( + &serde_json::to_string(&Wrapper { val: vec![vec![0]] }).unwrap(), + "[\"0x00\"]" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { + val: vec![vec![0, 1, 2]] + }) + .unwrap(), + "[\"0x000102\"]" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { + val: vec![vec![0], vec![0, 1, 2]] + }) + .unwrap(), + "[\"0x00\",\"0x000102\"]" + ); + } + + #[test] + fn decoding() { + assert_eq!( + serde_json::from_str::("[\"0x00\"]").unwrap(), + Wrapper { val: vec![vec![0]] }, + ); + assert_eq!( + serde_json::from_str::("[\"0x000102\"]").unwrap(), + Wrapper { + val: vec![vec![0, 1, 2]] + }, + ); + assert_eq!( + serde_json::from_str::("[\"0x00\",\"0x000102\"]").unwrap(), + Wrapper { + val: vec![vec![0], vec![0, 1, 2]] + }, + ); + } +} diff --git a/src/u32_hex.rs b/src/u32_hex.rs index c1ab353..ab41eab 100644 --- a/src/u32_hex.rs +++ b/src/u32_hex.rs @@ -19,3 +19,53 @@ where { bytes_4_hex::deserialize(deserializer).map(u32::from_le_bytes) } + +#[cfg(test)] +pub mod test { + use serde::{Deserialize, Serialize}; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(transparent)] + struct Wrapper { + #[serde(with = "super")] + val: u32, + } + + #[test] + fn encoding() { + assert_eq!( + &serde_json::to_string(&Wrapper { val: 0 }).unwrap(), + "\"0x00000000\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { val: 5 }).unwrap(), + "\"0x05000000\"" + ); + + assert_eq!( + &serde_json::to_string(&Wrapper { val: u32::MAX }).unwrap(), + "\"0xffffffff\"" + ); + } + + #[test] + fn decoding() { + assert_eq!( + serde_json::from_str::("\"0x00000000\"").unwrap(), + Wrapper { val: 0 }, + ); + assert_eq!( + serde_json::from_str::("\"0x05000000\"").unwrap(), + Wrapper { val: 5 }, + ); + assert_eq!( + serde_json::from_str::("\"0xffffffff\"").unwrap(), + Wrapper { val: u32::MAX }, + ); + + // Wrong length. + serde_json::from_str::("\"0xfffffffff\"").unwrap_err(); + // Requires 0x. + serde_json::from_str::("\"00000000\"").unwrap_err(); + } +} diff --git a/src/u8_hex.rs b/src/u8_hex.rs index 8083e1d..c75d2af 100644 --- a/src/u8_hex.rs +++ b/src/u8_hex.rs @@ -27,3 +27,52 @@ where } Ok(bytes[0]) } + +#[cfg(test)] +mod test { + use serde::{Deserialize, Serialize}; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(transparent)] + struct Wrapper { + #[serde(with = "super")] + val: u8, + } + + #[test] + fn encoding() { + assert_eq!( + &serde_json::to_string(&Wrapper { val: 0 }).unwrap(), + "\"0x00\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { val: 109 }).unwrap(), + "\"0x6d\"" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { val: u8::MAX }).unwrap(), + "\"0xff\"" + ); + } + + #[test] + fn decoding() { + assert_eq!( + serde_json::from_str::("\"0x00\"").unwrap(), + Wrapper { val: 0 }, + ); + assert_eq!( + serde_json::from_str::("\"0x6d\"").unwrap(), + Wrapper { val: 109 }, + ); + assert_eq!( + serde_json::from_str::("\"0xff\"").unwrap(), + Wrapper { val: u8::MAX }, + ); + + // Require 0x. + serde_json::from_str::("\"ff\"").unwrap_err(); + // Wrong length. + serde_json::from_str::("\"0xfff\"").unwrap_err(); + } +} From a59906171e9e8ce1f06b58173b0c137f228b6c4f Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 3 Sep 2024 18:19:47 -0700 Subject: [PATCH 2/4] add testsuite changes --- .github/workflows/test-suite.yml | 17 +++++++++++++++++ .gitignore | 1 + 2 files changed, 18 insertions(+) diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 27792ae..43150f7 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -31,3 +31,20 @@ jobs: run: rustup update stable - name: Run tests run: cargo test --release + coverage: + runs-on: ubuntu-latest + name: cargo-tarpaulin + steps: + - uses: actions/checkout@v3 + - name: Get latest version of stable Rust + run: rustup update stable + - name: Install cargo-tarpaulin + uses: taiki-e/install-action@cargo-tarpaulin + - name: Check code coverage with cargo-tarpaulin + run: make coverage + - name: Upload to codecov.io + uses: codecov/codecov-action@v4 + with: + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + informational: true diff --git a/.gitignore b/.gitignore index 4fffb2f..932baf5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target /Cargo.lock +/*.xml From 47a4dfb49cc1873734292b0378e22a84b69104cf Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 3 Sep 2024 18:27:47 -0700 Subject: [PATCH 3/4] added json test coverage --- src/json_str.rs | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/json_str.rs b/src/json_str.rs index b9a1813..a30633e 100644 --- a/src/json_str.rs +++ b/src/json_str.rs @@ -23,3 +23,71 @@ where let json_str = String::deserialize(deserializer)?; serde_json::from_str(&json_str).map_err(D::Error::custom) } + + +#[cfg(test)] +mod test { + use serde::{Deserialize, Serialize}; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Wrapper { + val_1: String, + val_2: u8, + val_3: Vec, + val_4: Option + } + + #[test] + fn encoding() { + assert_eq!( + &serde_json::to_string(&Wrapper { + val_1: "Test".to_string(), + val_2: 5, + val_3: vec![9], + val_4: Some(10) + }).unwrap(), + "{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":10}" + ); + assert_eq!( + &serde_json::to_string(&Wrapper { + val_1: "Test".to_string(), + val_2: 5, + val_3: vec![9], + val_4: None + }).unwrap(), + "{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":null}" + ); + } + + #[test] + fn decoding() { + assert_eq!( + serde_json::from_str::("{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":10}").unwrap(), + Wrapper { + val_1: "Test".to_string(), + val_2: 5, + val_3: vec![9], + val_4: Some(10) + }, + ); + assert_eq!( + serde_json::from_str::("{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":null}").unwrap(), + Wrapper { + val_1: "Test".to_string(), + val_2: 5, + val_3: vec![9], + val_4: None + }, + ); + + // Violating type constraints. + serde_json::from_str::( + "{\"val_1\":1,\"val_2\":5,\"val_3\":[9],\"val_4\":null}", + ) + .unwrap_err(); + serde_json::from_str::( + "{\"val_1\":\"Test\",\"val_2\":5,\"val_4\":null}", + ) + .unwrap_err(); + } +} From 55742e8468d4981d7b0d0f3e651ef305785e0df1 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 3 Sep 2024 18:28:26 -0700 Subject: [PATCH 4/4] Fmt --- src/json_str.rs | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/json_str.rs b/src/json_str.rs index a30633e..d007cf5 100644 --- a/src/json_str.rs +++ b/src/json_str.rs @@ -24,7 +24,6 @@ where serde_json::from_str(&json_str).map_err(D::Error::custom) } - #[cfg(test)] mod test { use serde::{Deserialize, Serialize}; @@ -34,36 +33,41 @@ mod test { val_1: String, val_2: u8, val_3: Vec, - val_4: Option + val_4: Option, } #[test] fn encoding() { assert_eq!( - &serde_json::to_string(&Wrapper { + &serde_json::to_string(&Wrapper { val_1: "Test".to_string(), val_2: 5, val_3: vec![9], val_4: Some(10) - }).unwrap(), - "{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":10}" + }) + .unwrap(), + "{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":10}" ); assert_eq!( - &serde_json::to_string(&Wrapper { + &serde_json::to_string(&Wrapper { val_1: "Test".to_string(), val_2: 5, val_3: vec![9], val_4: None - }).unwrap(), - "{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":null}" + }) + .unwrap(), + "{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":null}" ); } #[test] fn decoding() { assert_eq!( - serde_json::from_str::("{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":10}").unwrap(), - Wrapper { + serde_json::from_str::( + "{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":10}" + ) + .unwrap(), + Wrapper { val_1: "Test".to_string(), val_2: 5, val_3: vec![9], @@ -71,23 +75,22 @@ mod test { }, ); assert_eq!( - serde_json::from_str::("{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":null}").unwrap(), - Wrapper { + serde_json::from_str::( + "{\"val_1\":\"Test\",\"val_2\":5,\"val_3\":[9],\"val_4\":null}" + ) + .unwrap(), + Wrapper { val_1: "Test".to_string(), val_2: 5, val_3: vec![9], val_4: None }, ); - + // Violating type constraints. - serde_json::from_str::( - "{\"val_1\":1,\"val_2\":5,\"val_3\":[9],\"val_4\":null}", - ) - .unwrap_err(); - serde_json::from_str::( - "{\"val_1\":\"Test\",\"val_2\":5,\"val_4\":null}", - ) - .unwrap_err(); + serde_json::from_str::("{\"val_1\":1,\"val_2\":5,\"val_3\":[9],\"val_4\":null}") + .unwrap_err(); + serde_json::from_str::("{\"val_1\":\"Test\",\"val_2\":5,\"val_4\":null}") + .unwrap_err(); } }