What changed, and why it matters
This commit only adds unit tests to the Aptos Rust app. It does not change any production code, so it cannot introduce a security vulnerability or fix one. The tests exercise existing functions for address generation, transaction parsing, message decoding, signing, and various data-type helpers.
No security action needed. Treat as routine test-coverage improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff is entirely additions of #[cfg(test)] modules across eight Rust source files in rust/apps/aptos. No runtime logic is modified. The tests cover AccountAddress, ChainId, Identifier, language storage types, Module/ModuleBundle, error conversions, top-level lib functions (generate_address, parse_tx, parse_msg, sign), and parser helpers (decode_utf8, is_tx, AptosTx). All added code is test-only and gated by the test configuration.
Changed components
rust/apps/aptos/src/aptos_type/account_address.rsrust/apps/aptos/src/aptos_type/chain_id.rsrust/apps/aptos/src/aptos_type/identifier.rsrust/apps/aptos/src/aptos_type/language_storage.rsrust/apps/aptos/src/aptos_type/module.rsrust/apps/aptos/src/errors.rsrust/apps/aptos/src/lib.rsrust/apps/aptos/src/parser.rsInspect captured patch +1312 / −0
diff --git a/rust/apps/aptos/src/aptos_type/account_address.rs b/rust/apps/aptos/src/aptos_type/account_address.rs
index d30c5f0..548e066 100644
--- a/rust/apps/aptos/src/aptos_type/account_address.rs
+++ b/rust/apps/aptos/src/aptos_type/account_address.rs
@@ -255,3 +255,264 @@ impl Serialize for AccountAddress {
}
}
}
+
+#[cfg(test)]
+mod tests {
+ extern crate std;
+ use super::*;
+
+ #[test]
+ fn test_account_address_new() {
+ let bytes = [0u8; AccountAddress::LENGTH];
+ let addr = AccountAddress::new(bytes);
+ assert_eq!(addr.into_bytes(), bytes);
+ }
+
+ #[test]
+ fn test_account_address_zero() {
+ let zero = AccountAddress::ZERO;
+ assert_eq!(zero.into_bytes(), [0u8; AccountAddress::LENGTH]);
+ }
+
+ #[test]
+ fn test_account_address_one() {
+ let one = AccountAddress::ONE;
+ let bytes = one.into_bytes();
+ assert_eq!(bytes[AccountAddress::LENGTH - 1], 1);
+ for i in 0..AccountAddress::LENGTH - 1 {
+ assert_eq!(bytes[i], 0);
+ }
+ }
+
+ #[test]
+ fn test_account_address_short_str_lossless() {
+ let addr = AccountAddress::ZERO;
+ assert_eq!(addr.short_str_lossless(), "0");
+
+ let mut bytes = [0u8; AccountAddress::LENGTH];
+ bytes[AccountAddress::LENGTH - 1] = 0x42;
+ let addr = AccountAddress::new(bytes);
+ assert_eq!(addr.short_str_lossless(), "42");
+ }
+
+ #[test]
+ fn test_account_address_to_vec() {
+ let addr = AccountAddress::ONE;
+ let vec = addr.to_vec();
+ assert_eq!(vec.len(), AccountAddress::LENGTH);
+ }
+
+ #[test]
+ fn test_account_address_from_hex_literal() {
+ let addr = AccountAddress::from_hex_literal("0x1").unwrap();
+ assert_eq!(addr, AccountAddress::ONE);
+
+ let addr = AccountAddress::from_hex_literal("0x0").unwrap();
+ assert_eq!(addr, AccountAddress::ZERO);
+ }
+
+ #[test]
+ fn test_account_address_from_hex_literal_no_prefix() {
+ let result = AccountAddress::from_hex_literal("1");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_account_address_from_hex_literal_short() {
+ let addr = AccountAddress::from_hex_literal("0xa").unwrap();
+ let bytes = addr.into_bytes();
+ assert_eq!(bytes[AccountAddress::LENGTH - 1], 0xa);
+ }
+
+ #[test]
+ fn test_account_address_to_hex_literal() {
+ let addr = AccountAddress::ONE;
+ let hex = addr.to_hex_literal();
+ assert!(hex.starts_with("0x"));
+ }
+
+ #[test]
+ fn test_account_address_from_hex() {
+ let hex_str = "00".repeat(AccountAddress::LENGTH);
+ let addr = AccountAddress::from_hex(hex_str).unwrap();
+ assert_eq!(addr, AccountAddress::ZERO);
+ }
+
+ #[test]
+ fn test_account_address_from_hex_invalid() {
+ let result = AccountAddress::from_hex("zz");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_account_address_to_hex() {
+ let addr = AccountAddress::ONE;
+ let hex = addr.to_hex();
+ assert_eq!(hex.len(), AccountAddress::LENGTH * 2);
+ }
+
+ #[test]
+ fn test_account_address_from_bytes() {
+ let bytes = [0u8; AccountAddress::LENGTH];
+ let addr = AccountAddress::from_bytes(bytes).unwrap();
+ assert_eq!(addr.into_bytes(), bytes);
+ }
+
+ #[test]
+ fn test_account_address_from_bytes_invalid_length() {
+ let bytes = vec![0u8; 31];
+ let result = AccountAddress::from_bytes(bytes);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_account_address_as_ref() {
+ let addr = AccountAddress::ONE;
+ let slice: &[u8] = addr.as_ref();
+ assert_eq!(slice.len(), AccountAddress::LENGTH);
+ }
+
+ #[test]
+ fn test_account_address_deref() {
+ let addr = AccountAddress::ONE;
+ let bytes: &[u8; AccountAddress::LENGTH] = &*addr;
+ assert_eq!(bytes[AccountAddress::LENGTH - 1], 1);
+ }
+
+ #[test]
+ fn test_account_address_display() {
+ let addr = AccountAddress::ONE;
+ let s = format!("{}", addr);
+ assert!(!s.is_empty());
+ }
+
+ #[test]
+ fn test_account_address_debug() {
+ let addr = AccountAddress::ONE;
+ let s = format!("{:?}", addr);
+ assert!(!s.is_empty());
+ }
+
+ #[test]
+ fn test_account_address_lower_hex() {
+ let addr = AccountAddress::ONE;
+ let s = format!("{:x}", addr);
+ assert_eq!(s.len(), AccountAddress::LENGTH * 2);
+ }
+
+ #[test]
+ fn test_account_address_lower_hex_alternate() {
+ let addr = AccountAddress::ONE;
+ let s = format!("{:#x}", addr);
+ assert!(s.starts_with("0x"));
+ }
+
+ #[test]
+ fn test_account_address_upper_hex() {
+ let addr = AccountAddress::ONE;
+ let s = format!("{:X}", addr);
+ assert_eq!(s.len(), AccountAddress::LENGTH * 2);
+ }
+
+ #[test]
+ fn test_account_address_upper_hex_alternate() {
+ let addr = AccountAddress::ONE;
+ let s = format!("{:#X}", addr);
+ assert!(s.starts_with("0x"));
+ }
+
+ #[test]
+ fn test_account_address_from_array() {
+ let bytes = [0u8; AccountAddress::LENGTH];
+ let addr: AccountAddress = bytes.into();
+ assert_eq!(addr.into_bytes(), bytes);
+ }
+
+ #[test]
+ fn test_account_address_try_from_slice() {
+ let bytes = vec![0u8; AccountAddress::LENGTH];
+ let addr = AccountAddress::try_from(bytes.as_slice()).unwrap();
+ let expected: [u8; AccountAddress::LENGTH] = bytes.try_into().unwrap();
+ assert_eq!(addr.into_bytes(), expected);
+ }
+
+ #[test]
+ fn test_account_address_try_from_vec() {
+ let bytes = vec![0u8; AccountAddress::LENGTH];
+ let addr = AccountAddress::try_from(bytes).unwrap();
+ assert_eq!(addr.into_bytes(), [0u8; AccountAddress::LENGTH]);
+ }
+
+ #[test]
+ fn test_account_address_into_vec() {
+ let addr = AccountAddress::ONE;
+ let vec: Vec<u8> = addr.into();
+ assert_eq!(vec.len(), AccountAddress::LENGTH);
+ }
+
+ #[test]
+ fn test_account_address_ref_into_vec() {
+ let addr = AccountAddress::ONE;
+ let vec: Vec<u8> = (&addr).into();
+ assert_eq!(vec.len(), AccountAddress::LENGTH);
+ }
+
+ #[test]
+ fn test_account_address_into_array() {
+ let addr = AccountAddress::ONE;
+ let arr: [u8; AccountAddress::LENGTH] = addr.into();
+ assert_eq!(arr[AccountAddress::LENGTH - 1], 1);
+ }
+
+ #[test]
+ fn test_account_address_ref_into_array() {
+ let addr = AccountAddress::ONE;
+ let arr: [u8; AccountAddress::LENGTH] = (&addr).into();
+ assert_eq!(arr[AccountAddress::LENGTH - 1], 1);
+ }
+
+ #[test]
+ fn test_account_address_ref_into_string() {
+ let addr = AccountAddress::ONE;
+ let s: String = (&addr).into();
+ assert_eq!(s.len(), AccountAddress::LENGTH * 2);
+ }
+
+ #[test]
+ fn test_account_address_try_from_string() {
+ let hex_str = "00".repeat(AccountAddress::LENGTH);
+ let addr = AccountAddress::try_from(hex_str).unwrap();
+ assert_eq!(addr, AccountAddress::ZERO);
+ }
+
+ #[test]
+ fn test_account_address_from_str() {
+ let addr = AccountAddress::from_str("0x1").unwrap();
+ assert_eq!(addr, AccountAddress::ONE);
+
+ let hex_str = "00".repeat(AccountAddress::LENGTH);
+ let addr = AccountAddress::from_str(&hex_str).unwrap();
+ assert_eq!(addr, AccountAddress::ZERO);
+ }
+
+ #[test]
+ fn test_account_address_ord() {
+ let addr1 = AccountAddress::ZERO;
+ let addr2 = AccountAddress::ONE;
+ assert!(addr1 < addr2);
+ }
+
+ #[test]
+ fn test_account_address_eq() {
+ let addr1 = AccountAddress::ONE;
+ let addr2 = AccountAddress::ONE;
+ assert_eq!(addr1, addr2);
+ }
+
+ #[test]
+ fn test_account_address_clone() {
+ let addr1 = AccountAddress::ONE;
+ let addr2 = addr1.clone();
+ assert_eq!(addr1, addr2);
+ }
+}
diff --git a/rust/apps/aptos/src/aptos_type/chain_id.rs b/rust/apps/aptos/src/aptos_type/chain_id.rs
index 4d55955..313ca38 100644
--- a/rust/apps/aptos/src/aptos_type/chain_id.rs
+++ b/rust/apps/aptos/src/aptos_type/chain_id.rs
@@ -184,3 +184,156 @@ impl ChainId {
ChainId::new(NamedChain::MAINNET.id())
}
}
+
+#[cfg(test)]
+mod tests {
+ extern crate std;
+ use super::*;
+
+ #[test]
+ fn test_named_chain_id() {
+ assert_eq!(NamedChain::MAINNET.id(), 1);
+ assert_eq!(NamedChain::TESTNET.id(), 2);
+ assert_eq!(NamedChain::DEVNET.id(), 3);
+ assert_eq!(NamedChain::TESTING.id(), 4);
+ assert_eq!(NamedChain::PREMAINNET.id(), 5);
+ }
+
+ #[test]
+ fn test_named_chain_from_chain_id() {
+ let chain_id = ChainId::new(1);
+ let named = NamedChain::from_chain_id(&chain_id).unwrap();
+ assert_eq!(named as u8, NamedChain::MAINNET as u8);
+
+ let chain_id = ChainId::new(2);
+ let named = NamedChain::from_chain_id(&chain_id).unwrap();
+ assert_eq!(named as u8, NamedChain::TESTNET as u8);
+ }
+
+ #[test]
+ fn test_named_chain_from_chain_id_invalid() {
+ let chain_id = ChainId::new(99);
+ let result = NamedChain::from_chain_id(&chain_id);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_named_chain_display() {
+ assert_eq!(format!("{}", NamedChain::MAINNET), "mainnet");
+ assert_eq!(format!("{}", NamedChain::TESTNET), "testnet");
+ assert_eq!(format!("{}", NamedChain::DEVNET), "devnet");
+ assert_eq!(format!("{}", NamedChain::TESTING), "testing");
+ assert_eq!(format!("{}", NamedChain::PREMAINNET), "premainnet");
+ }
+
+ #[test]
+ fn test_chain_id_new() {
+ let chain_id = ChainId::new(1);
+ assert_eq!(chain_id.id(), 1);
+ }
+
+ #[test]
+ #[should_panic(expected = "cannot have chain ID with 0")]
+ fn test_chain_id_new_zero() {
+ ChainId::new(0);
+ }
+
+ #[test]
+ fn test_chain_id_id() {
+ let chain_id = ChainId::new(42);
+ assert_eq!(chain_id.id(), 42);
+ }
+
+ #[test]
+ fn test_chain_id_test() {
+ let chain_id = ChainId::test();
+ assert_eq!(chain_id.id(), NamedChain::TESTING.id());
+ }
+
+ #[test]
+ fn test_chain_id_mainnet() {
+ let chain_id = ChainId::mainnet();
+ assert_eq!(chain_id.id(), NamedChain::MAINNET.id());
+ }
+
+ #[test]
+ fn test_chain_id_default() {
+ let chain_id = ChainId::default();
+ assert_eq!(chain_id.id(), NamedChain::TESTING.id());
+ }
+
+ #[test]
+ fn test_chain_id_display_named() {
+ let chain_id = ChainId::mainnet();
+ let s = format!("{}", chain_id);
+ assert_eq!(s, "mainnet");
+ }
+
+ #[test]
+ fn test_chain_id_display_numeric() {
+ let chain_id = ChainId::new(99);
+ let s = format!("{}", chain_id);
+ assert_eq!(s, "99");
+ }
+
+ #[test]
+ fn test_chain_id_debug() {
+ let chain_id = ChainId::mainnet();
+ let s = format!("{:?}", chain_id);
+ assert!(!s.is_empty());
+ }
+
+ #[test]
+ fn test_chain_id_from_str_named() {
+ let chain_id = ChainId::from_str("mainnet").unwrap();
+ assert_eq!(chain_id.id(), 1);
+
+ let chain_id = ChainId::from_str("TESTNET").unwrap();
+ assert_eq!(chain_id.id(), 2);
+ }
+
+ #[test]
+ fn test_chain_id_from_str_numeric() {
+ let chain_id = ChainId::from_str("42").unwrap();
+ assert_eq!(chain_id.id(), 42);
+ }
+
+ #[test]
+ fn test_chain_id_from_str_empty() {
+ let result = ChainId::from_str("");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_chain_id_from_str_zero() {
+ let result = ChainId::from_str("0");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_chain_id_from_str_invalid() {
+ let result = ChainId::from_str("invalid");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_chain_id_eq() {
+ let chain_id1 = ChainId::new(1);
+ let chain_id2 = ChainId::new(1);
+ assert_eq!(chain_id1, chain_id2);
+ }
+
+ #[test]
+ fn test_chain_id_ne() {
+ let chain_id1 = ChainId::new(1);
+ let chain_id2 = ChainId::new(2);
+ assert_ne!(chain_id1, chain_id2);
+ }
+
+ #[test]
+ fn test_chain_id_clone() {
+ let chain_id1 = ChainId::new(1);
+ let chain_id2 = chain_id1.clone();
+ assert_eq!(chain_id1, chain_id2);
+ }
+}
diff --git a/rust/apps/aptos/src/aptos_type/identifier.rs b/rust/apps/aptos/src/aptos_type/identifier.rs
index 65c8916..e9277b1 100644
--- a/rust/apps/aptos/src/aptos_type/identifier.rs
+++ b/rust/apps/aptos/src/aptos_type/identifier.rs
@@ -190,3 +190,200 @@ macro_rules! ident_str {
}
}};
}
+
+#[cfg(test)]
+mod tests {
+ extern crate std;
+ use super::*;
+
+ #[test]
+ fn test_is_valid_identifier_char() {
+ assert!(is_valid_identifier_char('a'));
+ assert!(is_valid_identifier_char('Z'));
+ assert!(is_valid_identifier_char('0'));
+ assert!(is_valid_identifier_char('_'));
+ assert!(!is_valid_identifier_char('-'));
+ assert!(!is_valid_identifier_char(' '));
+ }
+
+ #[test]
+ fn test_is_valid() {
+ assert!(is_valid("valid"));
+ assert!(is_valid("Valid123"));
+ assert!(is_valid("_valid"));
+ assert!(is_valid("<SELF>"));
+ assert!(!is_valid("invalid-identifier"));
+ assert!(!is_valid(""));
+ assert!(!is_valid("_"));
+ }
+
+ #[test]
+ fn test_identifier_new() {
+ let ident = Identifier::new("valid").unwrap();
+ assert_eq!(ident.as_str(), "valid");
+
+ let result = Identifier::new("invalid-identifier");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_identifier_is_valid() {
+ assert!(Identifier::is_valid("valid"));
+ assert!(!Identifier::is_valid("invalid-identifier"));
+ }
+
+ #[test]
+ fn test_identifier_is_self() {
+ let ident = Identifier::new("<SELF>").unwrap();
+ assert!(ident.is_self());
+
+ let ident = Identifier::new("notself").unwrap();
+ assert!(!ident.is_self());
+ }
+
+ #[test]
+ fn test_identifier_from_utf8() {
+ let bytes = b"valid".to_vec();
+ let ident = Identifier::from_utf8(bytes).unwrap();
+ assert_eq!(ident.as_str(), "valid");
+ }
+
+ #[test]
+ fn test_identifier_as_ident_str() {
+ let ident = Identifier::new("test").unwrap();
+ let ident_str = ident.as_ident_str();
+ assert_eq!(ident_str.as_str(), "test");
+ }
+
+ #[test]
+ fn test_identifier_into_string() {
+ let ident = Identifier::new("test").unwrap();
+ let s = ident.into_string();
+ assert_eq!(s, "test");
+ }
+
+ #[test]
+ fn test_identifier_into_bytes() {
+ let ident = Identifier::new("test").unwrap();
+ let bytes = ident.into_bytes();
+ assert_eq!(bytes, b"test".to_vec());
+ }
+
+ #[test]
+ fn test_identifier_from_str() {
+ let ident = Identifier::from_str("valid").unwrap();
+ assert_eq!(ident.as_str(), "valid");
+
+ let result = Identifier::from_str("invalid-identifier");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_identifier_from_ident_str() {
+ let ident_str = IdentStr::new("valid").unwrap();
+ let ident: Identifier = ident_str.into();
+ assert_eq!(ident.as_str(), "valid");
+ }
+
+ #[test]
+ fn test_identifier_as_ref_ident_str() {
+ let ident = Identifier::new("test").unwrap();
+ let ident_str: &IdentStr = ident.as_ref();
+ assert_eq!(ident_str.as_str(), "test");
+ }
+
+ #[test]
+ fn test_identifier_deref() {
+ let ident = Identifier::new("test").unwrap();
+ let ident_str: &IdentStr = &*ident;
+ assert_eq!(ident_str.as_str(), "test");
+ }
+
+ #[test]
+ fn test_identifier_display() {
+ let ident = Identifier::new("test").unwrap();
+ let s = format!("{}", ident);
+ assert_eq!(s, "test");
+ }
+
+ #[test]
+ fn test_ident_str_new() {
+ let ident_str = IdentStr::new("valid").unwrap();
+ assert_eq!(ident_str.as_str(), "valid");
+
+ let result = IdentStr::new("invalid-identifier");
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_ident_str_is_valid() {
+ assert!(IdentStr::is_valid("valid"));
+ assert!(!IdentStr::is_valid("invalid-identifier"));
+ }
+
+ #[test]
+ fn test_ident_str_len() {
+ let ident_str = IdentStr::new("test").unwrap();
+ assert_eq!(ident_str.len(), 4);
+ }
+
+ #[test]
+ fn test_ident_str_is_empty() {
+ let ident_str = IdentStr::new("test").unwrap();
+ assert!(!ident_str.is_empty());
+ }
+
+ #[test]
+ fn test_ident_str_as_str() {
+ let ident_str = IdentStr::new("test").unwrap();
+ assert_eq!(ident_str.as_str(), "test");
+ }
+
+ #[test]
+ fn test_ident_str_as_bytes() {
+ let ident_str = IdentStr::new("test").unwrap();
+ assert_eq!(ident_str.as_bytes(), b"test");
+ }
+
+ #[test]
+ fn test_identifier_borrow_ident_str() {
+ let ident = Identifier::new("test").unwrap();
+ let ident_str: &IdentStr = ident.borrow();
+ assert_eq!(ident_str.as_str(), "test");
+ }
+
+ #[test]
+ fn test_ident_str_to_owned() {
+ let ident_str = IdentStr::new("test").unwrap();
+ let ident: Identifier = ident_str.to_owned();
+ assert_eq!(ident.as_str(), "test");
+ }
+
+ #[test]
+ fn test_ident_str_display() {
+ let ident_str = IdentStr::new("test").unwrap();
+ let s = format!("{}", ident_str);
+ assert_eq!(s, "test");
+ }
+
+ #[test]
+ fn test_identifier_eq() {
+ let ident1 = Identifier::new("test").unwrap();
+ let ident2 = Identifier::new("test").unwrap();
+ assert_eq!(ident1, ident2);
+ }
+
+ #[test]
+ fn test_identifier_ord() {
+ let ident1 = Identifier::new("a").unwrap();
+ let ident2 = Identifier::new("b").unwrap();
+ assert!(ident1 < ident2);
+ }
+
+ #[test]
+ fn test_identifier_clone() {
+ let ident1 = Identifier::new("test").unwrap();
+ let ident2 = ident1.clone();
+ assert_eq!(ident1, ident2);
+ }
+}
diff --git a/rust/apps/aptos/src/aptos_type/language_storage.rs b/rust/apps/aptos/src/aptos_type/language_storage.rs
index ef369c0..277a49f 100644
--- a/rust/apps/aptos/src/aptos_type/language_storage.rs
+++ b/rust/apps/aptos/src/aptos_type/language_storage.rs
@@ -210,3 +210,295 @@ impl From<StructTag> for TypeTag {
TypeTag::Struct(Box::new(t))
}
}
+
+#[cfg(test)]
+mod tests {
+ extern crate std;
+ use super::*;
+ use crate::aptos_type::account_address::AccountAddress;
+ use crate::aptos_type::identifier::Identifier;
+
+ #[test]
+ fn test_struct_tag_access_vector() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module,
+ name,
+ type_params: vec![],
+ };
+ let access_vector = struct_tag.access_vector();
+ assert!(!access_vector.is_empty());
+ assert_eq!(access_vector[0], RESOURCE_TAG);
+ }
+
+ #[test]
+ fn test_struct_tag_module_id() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module: module.clone(),
+ name,
+ type_params: vec![],
+ };
+ let module_id = struct_tag.module_id();
+ assert_eq!(module_id.address(), &AccountAddress::ONE);
+ assert_eq!(module_id.name().as_str(), "test");
+ }
+
+ #[test]
+ fn test_resource_key_new() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module,
+ name,
+ type_params: vec![],
+ };
+ let resource_key = ResourceKey::new(address, struct_tag);
+ assert_eq!(resource_key.address(), AccountAddress::ONE);
+ }
+
+ #[test]
+ fn test_resource_key_address() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module,
+ name,
+ type_params: vec![],
+ };
+ let resource_key = ResourceKey::new(address, struct_tag);
+ assert_eq!(resource_key.address(), AccountAddress::ONE);
+ }
+
+ #[test]
+ fn test_resource_key_type() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module,
+ name,
+ type_params: vec![],
+ };
+ let resource_key = ResourceKey::new(address, struct_tag);
+ assert_eq!(resource_key.type_().module.as_str(), "test");
+ }
+
+ #[test]
+ fn test_module_id_new() {
+ let address = AccountAddress::ONE;
+ let name = Identifier::new("test").unwrap();
+ let module_id = ModuleId::new(address, name);
+ assert_eq!(module_id.address(), &AccountAddress::ONE);
+ }
+
+ #[test]
+ fn test_module_id_name() {
+ let address = AccountAddress::ONE;
+ let name = Identifier::new("test").unwrap();
+ let module_id = ModuleId::new(address, name);
+ assert_eq!(module_id.name().as_str(), "test");
+ }
+
+ #[test]
+ fn test_module_id_address() {
+ let address = AccountAddress::ONE;
+ let name = Identifier::new("test").unwrap();
+ let module_id = ModuleId::new(address, name);
+ assert_eq!(module_id.address(), &AccountAddress::ONE);
+ }
+
+ #[test]
+ fn test_module_id_access_vector() {
+ let address = AccountAddress::ONE;
+ let name = Identifier::new("test").unwrap();
+ let module_id = ModuleId::new(address, name);
+ let access_vector = module_id.access_vector();
+ assert!(!access_vector.is_empty());
+ assert_eq!(access_vector[0], CODE_TAG);
+ }
+
+ #[test]
+ fn test_module_id_display() {
+ let address = AccountAddress::ONE;
+ let name = Identifier::new("test").unwrap();
+ let module_id = ModuleId::new(address, name);
+ let s = format!("{}", module_id);
+ assert!(s.contains("test"));
+ }
+
+ #[test]
+ fn test_module_id_short_str_lossless() {
+ let address = AccountAddress::ONE;
+ let name = Identifier::new("test").unwrap();
+ let module_id = ModuleId::new(address, name);
+ let s = module_id.short_str_lossless();
+ assert!(s.contains("test"));
+ assert!(s.starts_with("0x"));
+ }
+
+ #[test]
+ fn test_module_id_from_tuple() {
+ let address = AccountAddress::ONE;
+ let name = Identifier::new("test").unwrap();
+ let module_id = ModuleId::new(address, name.clone());
+ let (addr, ident): (AccountAddress, Identifier) = module_id.into();
+ assert_eq!(addr, AccountAddress::ONE);
+ assert_eq!(ident.as_str(), "test");
+ }
+
+ #[test]
+ fn test_struct_tag_display() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module,
+ name,
+ type_params: vec![],
+ };
+ let s = format!("{}", struct_tag);
+ assert!(s.contains("test"));
+ assert!(s.contains("Test"));
+ }
+
+ #[test]
+ fn test_struct_tag_display_with_type_params() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module,
+ name,
+ type_params: vec![TypeTag::Bool],
+ };
+ let s = format!("{}", struct_tag);
+ assert!(s.contains("<"));
+ }
+
+ #[test]
+ fn test_type_tag_display() {
+ assert_eq!(format!("{}", TypeTag::Bool), "bool");
+ assert_eq!(format!("{}", TypeTag::U8), "u8");
+ assert_eq!(format!("{}", TypeTag::U64), "u64");
+ assert_eq!(format!("{}", TypeTag::U128), "u128");
+ assert_eq!(format!("{}", TypeTag::Address), "address");
+ assert_eq!(format!("{}", TypeTag::Signer), "signer");
+ }
+
+ #[test]
+ fn test_type_tag_display_vector() {
+ let vec_tag = TypeTag::Vector(Box::new(TypeTag::Bool));
+ let s = format!("{}", vec_tag);
+ assert!(s.contains("vector"));
+ assert!(s.contains("bool"));
+ }
+
+ #[test]
+ fn test_type_tag_display_struct() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module,
+ name,
+ type_params: vec![],
+ };
+ let struct_type = TypeTag::Struct(Box::new(struct_tag));
+ let s = format!("{}", struct_type);
+ assert!(s.contains("test"));
+ }
+
+ #[test]
+ fn test_type_tag_from_struct_tag() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module,
+ name,
+ type_params: vec![],
+ };
+ let type_tag: TypeTag = struct_tag.into();
+ match type_tag {
+ TypeTag::Struct(_) => {}
+ _ => panic!("Expected Struct variant"),
+ }
+ }
+
+ #[test]
+ fn test_resource_key_display() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module,
+ name,
+ type_params: vec![],
+ };
+ let resource_key = ResourceKey::new(address, struct_tag);
+ let s = format!("{}", resource_key);
+ assert!(s.contains("test"));
+ }
+
+ #[test]
+ fn test_struct_tag_eq() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag1 = StructTag {
+ address,
+ module: module.clone(),
+ name: name.clone(),
+ type_params: vec![],
+ };
+ let struct_tag2 = StructTag {
+ address,
+ module,
+ name,
+ type_params: vec![],
+ };
+ assert_eq!(struct_tag1, struct_tag2);
+ }
+
+ #[test]
+ fn test_resource_key_eq() {
+ let address = AccountAddress::ONE;
+ let module = Identifier::new("test").unwrap();
+ let name = Identifier::new("Test").unwrap();
+ let struct_tag = StructTag {
+ address,
+ module: module.clone(),
+ name: name.clone(),
+ type_params: vec![],
+ };
+ let key1 = ResourceKey::new(address, struct_tag.clone());
+ let key2 = ResourceKey::new(address, struct_tag);
+ assert_eq!(key1, key2);
+ }
+
+ #[test]
+ fn test_module_id_eq() {
+ let address = AccountAddress::ONE;
+ let name = Identifier::new("test").unwrap();
+ let module_id1 = ModuleId::new(address, name.clone());
+ let module_id2 = ModuleId::new(address, name);
+ assert_eq!(module_id1, module_id2);
+ }
+}
diff --git a/rust/apps/aptos/src/aptos_type/module.rs b/rust/apps/aptos/src/aptos_type/module.rs
index 5e43c5d..c62ae91 100644
--- a/rust/apps/aptos/src/aptos_type/module.rs
+++ b/rust/apps/aptos/src/aptos_type/module.rs
@@ -84,3 +84,140 @@ impl IntoIterator for ModuleBundle {
self.codes.into_iter()
}
}
+
+#[cfg(test)]
+mod tests {
+ extern crate std;
+ use super::*;
+
+ #[test]
+ fn test_module_new() {
+ let code = vec![0x01, 0x02, 0x03];
+ let module = Module::new(code.clone());
+ assert_eq!(module.code(), &[0x01, 0x02, 0x03]);
+ }
+
+ #[test]
+ fn test_module_code() {
+ let code = vec![0x42];
+ let module = Module::new(code);
+ assert_eq!(module.code(), &[0x42]);
+ }
+
+ #[test]
+ fn test_module_into_inner() {
+ let code = vec![0x01, 0x02];
+ let module = Module::new(code.clone());
+ let inner = module.into_inner();
+ assert_eq!(inner, code);
+ }
+
+ #[test]
+ fn test_module_debug() {
+ let code = vec![0x01, 0x02];
+ let module = Module::new(code);
+ let s = format!("{:?}", module);
+ assert!(s.contains("Module"));
+ assert!(s.contains("code"));
+ }
+
+ #[test]
+ fn test_module_bundle_new() {
+ let codes = vec![vec![0x01], vec![0x02, 0x03]];
+ let bundle = ModuleBundle::new(codes);
+ assert_eq!(bundle.iter().count(), 2);
+ }
+
+ #[test]
+ fn test_module_bundle_singleton() {
+ let code = vec![0x01, 0x02];
+ let bundle = ModuleBundle::singleton(code.clone());
+ let modules: Vec<_> = bundle.iter().collect();
+ assert_eq!(modules.len(), 1);
+ assert_eq!(modules[0].code(), code.as_slice());
+ }
+
+ #[test]
+ fn test_module_bundle_into_inner() {
+ let codes = vec![vec![0x01], vec![0x02]];
+ let bundle = ModuleBundle::new(codes.clone());
+ let inner = bundle.into_inner();
+ assert_eq!(inner, codes);
+ }
+
+ #[test]
+ fn test_module_bundle_iter() {
+ let codes = vec![vec![0x01], vec![0x02]];
+ let bundle = ModuleBundle::new(codes);
+ let mut iter = bundle.iter();
+ assert!(iter.next().is_some());
+ assert!(iter.next().is_some());
+ assert!(iter.next().is_none());
+ }
+
+ #[test]
+ fn test_module_bundle_debug() {
+ let codes = vec![vec![0x01]];
+ let bundle = ModuleBundle::new(codes);
+ let s = format!("{:?}", bundle);
+ assert!(s.contains("ModuleBundle"));
+ }
+
+ #[test]
+ fn test_module_from_module_bundle() {
+ let code = vec![0x01];
+ let module = Module::new(code);
+ let bundle: ModuleBundle = module.into();
+ assert_eq!(bundle.iter().count(), 1);
+ }
+
+ #[test]
+ fn test_module_bundle_into_iterator() {
+ let codes = vec![vec![0x01], vec![0x02]];
+ let bundle = ModuleBundle::new(codes);
+ let modules: Vec<Module> = bundle.into_iter().collect();
+ assert_eq!(modules.len(), 2);
+ }
+
+ #[test]
+ fn test_module_eq() {
+ let code1 = vec![0x01];
+ let code2 = vec![0x01];
+ let module1 = Module::new(code1);
+ let module2 = Module::new(code2);
+ assert_eq!(module1, module2);
+ }
+
+ #[test]
+ fn test_module_ne() {
+ let code1 = vec![0x01];
+ let code2 = vec![0x02];
+ let module1 = Module::new(code1);
+ let module2 = Module::new(code2);
+ assert_ne!(module1, module2);
+ }
+
+ #[test]
+ fn test_module_clone() {
+ let code = vec![0x01];
+ let module1 = Module::new(code);
+ let module2 = module1.clone();
+ assert_eq!(module1, module2);
+ }
+
+ #[test]
+ fn test_module_bundle_eq() {
+ let codes = vec![vec![0x01]];
+ let bundle1 = ModuleBundle::new(codes.clone());
+ let bundle2 = ModuleBundle::new(codes);
+ assert_eq!(bundle1, bundle2);
+ }
+
+ #[test]
+ fn test_module_bundle_clone() {
+ let codes = vec![vec![0x01]];
+ let bundle1 = ModuleBundle::new(codes);
+ let bundle2 = bundle1.clone();
+ assert_eq!(bundle1, bundle2);
+ }
+}
diff --git a/rust/apps/aptos/src/errors.rs b/rust/apps/aptos/src/errors.rs
index 1b105ca..fd1e27f 100644
--- a/rust/apps/aptos/src/errors.rs
+++ b/rust/apps/aptos/src/errors.rs
@@ -47,3 +47,47 @@ impl From<bcs::Error> for AptosError {
Self::InvalidData(format!("bsc operation failed {value}"))
}
}
+
+#[cfg(test)]
+mod tests {
+ extern crate std;
+ use super::*;
+ use hex;
+
+ #[test]
+ fn test_from_keystore_error() {
+ let keystore_err = KeystoreError::InvalidDerivationPath("test".to_string());
+ let aptos_err: AptosError = keystore_err.into();
+ assert!(matches!(aptos_err, AptosError::KeystoreError(_)));
+ }
+
+ #[test]
+ fn test_from_hex_error() {
+ let hex_err = hex::FromHexError::InvalidHexCharacter { c: 'z', index: 0 };
+ let aptos_err: AptosError = hex_err.into();
+ assert!(matches!(aptos_err, AptosError::InvalidData(_)));
+ }
+
+ #[test]
+ fn test_from_utf8_error() {
+ let invalid_utf8 = vec![0xff, 0xfe];
+ let utf8_err = String::from_utf8(invalid_utf8).unwrap_err();
+ let aptos_err: AptosError = utf8_err.into();
+ assert!(matches!(aptos_err, AptosError::InvalidData(_)));
+ }
+
+ #[test]
+ fn test_from_parse_int_error() {
+ let parse_err = "abc".parse::<u32>().unwrap_err();
+ let aptos_err: AptosError = parse_err.into();
+ assert!(matches!(aptos_err, AptosError::InvalidData(_)));
+ }
+
+ #[test]
+ fn test_from_bcs_error() {
+ let invalid_bcs = vec![0xff, 0xff, 0xff];
+ let bcs_err = bcs::from_bytes::<u32>(&invalid_bcs).unwrap_err();
+ let aptos_err: AptosError = bcs_err.into();
+ assert!(matches!(aptos_err, AptosError::InvalidData(_)));
+ }
+}
diff --git a/rust/apps/aptos/src/lib.rs b/rust/apps/aptos/src/lib.rs
index 8e47cd4..ab02f27 100644
--- a/rust/apps/aptos/src/lib.rs
+++ b/rust/apps/aptos/src/lib.rs
@@ -106,4 +106,125 @@ mod tests {
let cjk_out = parse_msg(&cjk).unwrap();
assert_eq!(cjk_out, hex::encode(&cjk));
}
+
+ #[test]
+ fn test_generate_address_invalid_length() {
+ // Test with 31 bytes (too short)
+ let pubkey_31 = "00".repeat(31);
+ let res = generate_address(&pubkey_31);
+ assert!(res.is_err());
+ assert!(matches!(
+ res.unwrap_err(),
+ errors::AptosError::InvalidData(_)
+ ));
+
+ // Test with 33 bytes (too long)
+ let pubkey_33 = "00".repeat(33);
+ let res = generate_address(&pubkey_33);
+ assert!(res.is_err());
+ }
+
+ #[test]
+ fn test_generate_address_with_prefix() {
+ // Test with 0x prefix (should fail hex decoding)
+ let pubkey = "0x0000000000000000000000000000000000000000000000000000000000000000";
+ let res = generate_address(pubkey);
+ assert!(res.is_err());
+ }
+
+ #[test]
+ fn test_generate_address_different_keys() {
+ let key1 = "0000000000000000000000000000000000000000000000000000000000000000";
+ let key2 = "0000000000000000000000000000000000000000000000000000000000000001";
+ let addr1 = generate_address(key1).unwrap();
+ let addr2 = generate_address(key2).unwrap();
+ assert_ne!(addr1, addr2);
+ assert!(addr1.starts_with("0x"));
+ assert!(addr2.starts_with("0x"));
+ }
+
+ #[test]
+ fn test_parse_tx_with_prefix() {
+ // Test parse_tx with TX_PREFIX
+ let tx_data = hex::decode("8bbbb70ae8b90a8686b2a27f10e21e44f2fb64ffffcaa4bb0242e9f1ea698659010000000000000002000000000000000000000000000000000000000000000000000000000000000104636f696e087472616e73666572010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e000220834f4b75dcaacbd7c549a993cdd3140676e172d1fee0609bf6876c74aaa7116008400d0300000000009a0e0000000000006400000000000000b6b747630000000021").unwrap();
+ let tx_prefix: [u8; 32] = [
+ 0xb5, 0xe9, 0x7d, 0xb0, 0x7f, 0xa0, 0xbd, 0x0e, 0x55, 0x98, 0xaa, 0x36, 0x43, 0xa9,
+ 0xbc, 0x6f, 0x66, 0x93, 0xbd, 0xdc, 0x1a, 0x9f, 0xec, 0x9e, 0x67, 0x4a, 0x46, 0x1e,
+ 0xaa, 0x00, 0xb1, 0x93,
+ ];
+ let mut prefixed_data = tx_prefix.to_vec();
+ prefixed_data.extend_from_slice(&tx_data);
+ let result = parse_tx(&prefixed_data);
+ assert!(result.is_ok());
+ }
+
+ #[test]
+ fn test_parse_tx_invalid_data() {
+ let invalid_data = vec![0xff, 0xff, 0xff];
+ let result = parse_tx(&invalid_data);
+ assert!(result.is_err());
+ assert!(matches!(
+ result.unwrap_err(),
+ errors::AptosError::ParseTxError(_)
+ ));
+ }
+
+ #[test]
+ fn test_parse_msg_empty() {
+ let empty = vec![];
+ let result = parse_msg(&empty);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), "");
+ }
+
+ #[test]
+ fn test_parse_msg_invalid_utf8_fallback() {
+ // Invalid UTF-8 should fallback to hex encoding
+ let invalid_utf8 = vec![0xff, 0xfe, 0xfd];
+ let result = parse_msg(&invalid_utf8);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), hex::encode(&invalid_utf8));
+ }
+
+ #[test]
+ fn test_sign_different_paths() {
+ let hd_path1 = "m/44'/637'/0'/0'/0'".to_string();
+ let hd_path2 = "m/44'/637'/0'/0'/1'".to_string();
+ let tx_hex = Vec::from_hex("b5e97db07fa0bd0e5598aa3643a9bc6f6693bddc1a9fec9e674a461eaa00b193f007dbb60994463db95b80fad4259ec18767a5bb507f9e048da84b75ea793ef500000000000000000200000000000000000000000000000000000000000000000000000000000000010d6170746f735f6163636f756e740e7472616e736665725f636f696e73010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e000220f007dbb60994463db95b80fad4259ec18767a5bb507f9e048da84b75ea793ef50800000000000000000a00000000000000640000000000000061242e650000000002").unwrap();
+ let seed = hex::decode("5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4").unwrap();
+ let sig1 = sign(tx_hex.clone(), &hd_path1, seed.as_slice()).unwrap();
+ let sig2 = sign(tx_hex, &hd_path2, seed.as_slice()).unwrap();
+ assert_ne!(sig1, sig2);
+ }
+
+ #[test]
+ fn test_sign_deterministic() {
+ let hd_path = "m/44'/637'/0'/0'/0'".to_string();
+ let tx_hex = Vec::from_hex("b5e97db07fa0bd0e5598aa3643a9bc6f6693bddc1a9fec9e674a461eaa00b193f007dbb60994463db95b80fad4259ec18767a5bb507f9e048da84b75ea793ef500000000000000000200000000000000000000000000000000000000000000000000000000000000010d6170746f735f6163636f756e740e7472616e736665725f636f696e73010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e000220f007dbb60994463db95b80fad4259ec18767a5bb507f9e048da84b75ea793ef50800000000000000000a00000000000000640000000000000061242e650000000002").unwrap();
+ let seed = hex::decode("5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4").unwrap();
+ let sig1 = sign(tx_hex.clone(), &hd_path, seed.as_slice()).unwrap();
+ let sig2 = sign(tx_hex, &hd_path, seed.as_slice()).unwrap();
+ assert_eq!(sig1, sig2); // Should be deterministic
+ }
+
+ #[test]
+ fn test_aptos_tx_get_raw_json() {
+ let data = "8bbbb70ae8b90a8686b2a27f10e21e44f2fb64ffffcaa4bb0242e9f1ea698659010000000000000002000000000000000000000000000000000000000000000000000000000000000104636f696e087472616e73666572010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e000220834f4b75dcaacbd7c549a993cdd3140676e172d1fee0609bf6876c74aaa7116008400d0300000000009a0e0000000000006400000000000000b6b747630000000021";
+ let buf_message = Vec::from_hex(data).unwrap();
+ let aptos_tx = parse_tx(&buf_message).unwrap();
+ let raw_json = aptos_tx.get_raw_json().unwrap();
+ assert!(raw_json.is_object());
+ assert!(raw_json.get("sender").is_some());
+ }
+
+ #[test]
+ fn test_aptos_tx_get_formatted_json() {
+ let data = "8bbbb70ae8b90a8686b2a27f10e21e44f2fb64ffffcaa4bb0242e9f1ea698659010000000000000002000000000000000000000000000000000000000000000000000000000000000104636f696e087472616e73666572010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e000220834f4b75dcaacbd7c549a993cdd3140676e172d1fee0609bf6876c74aaa7116008400d0300000000009a0e0000000000006400000000000000b6b747630000000021";
+ let buf_message = Vec::from_hex(data).unwrap();
+ let aptos_tx = parse_tx(&buf_message).unwrap();
+ let formatted_json = aptos_tx.get_formatted_json().unwrap();
+ assert!(formatted_json.is_string());
+ let json_str = formatted_json.as_str().unwrap();
+ assert!(json_str.contains("sender"));
+ }
}
diff --git a/rust/apps/aptos/src/parser.rs b/rust/apps/aptos/src/parser.rs
index 1ddccf4..465a213 100644
--- a/rust/apps/aptos/src/parser.rs
+++ b/rust/apps/aptos/src/parser.rs
@@ -86,3 +86,110 @@ impl AptosTx {
Ok(result.to_string())
}
}
+
+#[cfg(test)]
+mod tests {
+ extern crate std;
+ use super::*;
+ use hex;
+
+ #[test]
+ fn test_decode_utf8_valid_ascii() {
+ let ascii = b"hello, aptos";
+ let result = decode_utf8(ascii);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), "hello, aptos");
+ }
+
+ #[test]
+ fn test_decode_utf8_valid_utf8() {
+ let utf8 = "hello, мир".as_bytes();
+ let result = decode_utf8(utf8);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), "hello, мир");
+ }
+
+ #[test]
+ fn test_decode_utf8_cjk_rejected() {
+ let cjk = "中文".as_bytes();
+ let result = decode_utf8(cjk);
+ assert!(result.is_err());
+ assert!(matches!(result.unwrap_err(), AptosError::InvalidData(_)));
+ }
+
+ #[test]
+ fn test_decode_utf8_japanese_rejected() {
+ let japanese = "日本語".as_bytes();
+ let result = decode_utf8(japanese);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_decode_utf8_korean_rejected() {
+ let korean = "한국어".as_bytes();
+ let result = decode_utf8(korean);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_decode_utf8_invalid_utf8() {
+ let invalid = vec![0xff, 0xfe, 0xfd];
+ let result = decode_utf8(&invalid);
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_decode_utf8_empty() {
+ let empty = vec![];
+ let result = decode_utf8(&empty);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), "");
+ }
+
+ #[test]
+ fn test_is_tx_with_prefix() {
+ let tx_prefix: [u8; 32] = [
+ 0xb5, 0xe9, 0x7d, 0xb0, 0x7f, 0xa0, 0xbd, 0x0e, 0x55, 0x98, 0xaa, 0x36, 0x43, 0xa9,
+ 0xbc, 0x6f, 0x66, 0x93, 0xbd, 0xdc, 0x1a, 0x9f, 0xec, 0x9e, 0x67, 0x4a, 0x46, 0x1e,
+ 0xaa, 0x00, 0xb1, 0x93,
+ ];
+ let mut data = tx_prefix.to_vec();
+ data.push(0x00);
+ assert!(is_tx(&data));
+ }
+
+ #[test]
+ fn test_is_tx_without_prefix() {
+ let data = vec![0x00; 33];
+ assert!(!is_tx(&data));
+ }
+
+ #[test]
+ fn test_is_tx_too_short() {
+ let data = vec![0xb5, 0xe9, 0x7d, 0xb0];
+ assert!(!is_tx(&data));
+ }
+
+ #[test]
+ fn test_is_tx_exact_length() {
+ let tx_prefix: [u8; 32] = [
+ 0xb5, 0xe9, 0x7d, 0xb0, 0x7f, 0xa0, 0xbd, 0x0e, 0x55, 0x98, 0xaa, 0x36, 0x43, 0xa9,
+ 0xbc, 0x6f, 0x66, 0x93, 0xbd, 0xdc, 0x1a, 0x9f, 0xec, 0x9e, 0x67, 0x4a, 0x46, 0x1e,
+ 0xaa, 0x00, 0xb1, 0x93,
+ ];
+ // Exactly 32 bytes should return false (needs > 32)
+ assert!(!is_tx(&tx_prefix));
+ }
+
+ #[test]
+ fn test_aptos_tx_new() {
+ let tx_data = hex::decode("8bbbb70ae8b90a8686b2a27f10e21e44f2fb64ffffcaa4bb0242e9f1ea698659010000000000000002000000000000000000000000000000000000000000000000000000000000000104636f696e087472616e73666572010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e000220834f4b75dcaacbd7c549a993cdd3140676e172d1fee0609bf6876c74aaa7116008400d0300000000009a0e0000000000006400000000000000b6b747630000000021").unwrap();
+ let tx: RawTransaction = bcs::from_bytes(&tx_data).unwrap();
+ let aptos_tx = AptosTx::new(tx);
+ let result = aptos_tx.get_result();
+ assert!(result.is_ok());
+ let json_str = result.unwrap();
+ assert!(json_str.contains("raw_json"));
+ assert!(json_str.contains("formatted_json"));
+ }
+}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.