use wx_rust_common::enums::WxType;
use wx_rust_common::error::WxError;
use wx_rust_common::util::crypto::WxCryptUtil;
use wx_rust_common::util::crypto::{Pkcs7Encoder, Sha1};
use sha1::Digest as _;
#[test]
fn sha1_gen_sorts_and_hashes() {
let result = Sha1::digest(&["c", "a", "b"]).unwrap();
assert_eq!(result, "a9993e364706816aba3e25717850c26c9cd0d89d");
}
#[test]
fn sha1_gen_with_amp_joins_with_ampersand() {
let result = Sha1::digest_with_amp(&["c", "a", "b"]).unwrap();
let expected = hex::encode(sha1::Sha1::digest(b"a&b&c"));
assert_eq!(result, expected);
}
#[test]
fn sha1_gen_rejects_empty_args() {
assert!(Sha1::digest(&["a", ""]).is_err());
assert!(Sha1::digest(&[]).is_err());
}
#[test]
fn pkcs7_encode_pads_to_32() {
let pad = Pkcs7Encoder::encode(20);
assert_eq!(pad.len(), 12);
assert!(pad.iter().all(|&b| b == 12));
}
#[test]
fn pkcs7_encode_exact_block_no_pad() {
let pad = Pkcs7Encoder::encode(32);
assert_eq!(pad.len(), 32);
}
#[test]
fn pkcs7_decode_removes_padding() {
let mut data = vec![1u8; 20];
data.extend(vec![12u8; 12]); let decoded = Pkcs7DecoderHelper::decode(&data);
assert_eq!(decoded.len(), 20);
}
struct Pkcs7DecoderHelper;
impl Pkcs7DecoderHelper {
fn decode(d: &[u8]) -> Vec<u8> {
Pkcs7Encoder::decode(d)
}
}
#[test]
fn wx_error_from_json_parses_code_and_msg() {
let err = WxError::from_json(r#"{"errcode":40001,"errmsg":"invalid credential"}"#);
assert_eq!(err.error_code, 40001);
assert_eq!(err.error_msg.as_deref(), Some("invalid credential"));
assert!(err.json.is_some());
}
#[test]
fn wx_error_translates_to_chinese_by_type() {
let err = WxError::from_json_with_type(
r#"{"errcode":40001,"errmsg":"invalid credential"}"#,
Some(WxType::Mp),
);
assert_eq!(err.error_code, 40001);
assert_eq!(err.error_msg_en.as_deref(), Some("invalid credential"));
let zh = err.error_msg.as_deref().unwrap();
assert!(
zh.contains("AppSecret 错误") || zh.contains("access_token"),
"实际: {zh}"
);
}
#[test]
fn wx_error_zero_code_no_translation() {
let err = WxError::from_json_with_type(r#"{"errcode":0,"errmsg":"ok"}"#, Some(WxType::Mp));
assert_eq!(err.error_code, 0);
assert_eq!(err.error_msg.as_deref(), Some("ok"));
}
#[test]
fn crypt_util_encrypt_decrypt_roundtrip() {
let aes_key = "kvuO9BLIAs5iFlXRfwOJXjh3z7O1psxaY6jY1pnFUBQ=";
let util = WxCryptUtil::new("test-token", aes_key, "wxappid123").expect("aesKey");
let plain = "<xml><Content><![CDATA[你好微信]]></Content></xml>";
let encrypted = util.encrypt(plain).expect("加密成功");
assert!(encrypted.contains("<Encrypt>"));
assert!(encrypted.contains("<MsgSignature>"));
let ctx = util.encrypt_context(plain).expect("加密上下文");
let full_xml = format!(
"<xml>\n<Encrypt><![CDATA[{}]]></Encrypt>\n<MsgSignature><![CDATA[{}]]></MsgSignature>\n<TimeStamp>{}</TimeStamp>\n<Nonce><![CDATA[{}]]></Nonce>\n</xml>",
ctx.encrypted_xml, ctx.signature, ctx.timestamp, ctx.nonce
);
let decrypted = util
.decrypt_xml(&ctx.signature, &ctx.timestamp, &ctx.nonce, &full_xml)
.expect("解密成功");
assert_eq!(decrypted, plain);
}
#[test]
fn crypt_util_wrong_signature_fails() {
let aes_key = "kvuO9BLIAs5iFlXRfwOJXjh3z7O1psxaY6jY1pnFUBQ=";
let util = WxCryptUtil::new("test-token", aes_key, "wxappid123").expect("aesKey");
let ctx = util.encrypt_context("hello").expect("encrypt");
let full_xml = format!(
"<xml>\n<Encrypt><![CDATA[{}]]></Encrypt>\n<MsgSignature><![CDATA[{}]]></MsgSignature>\n<TimeStamp>{}</TimeStamp>\n<Nonce><![CDATA[{}]]></Nonce>\n</xml>",
ctx.encrypted_xml, ctx.signature, ctx.timestamp, ctx.nonce
);
let result = util.decrypt_xml("bad-signature", &ctx.timestamp, &ctx.nonce, &full_xml);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("签名验证错误"));
}