首页 > 解决方案 > 在异步测试中重用昂贵的运行时生成的值

问题描述

我的 Rust 代码中有大量测试,我需要为每个测试提供一个 RSA 密钥对。但是,生成 RSA 密钥对的成本很高,需要 3-4 秒。我可以在所有测试中重复使用一个 RSA 密钥对,但我不知道该怎么做。目前,我正在为每个测试分别生成一个 RSA 密钥对。

更新:测试是异步测试,需要使用密钥对作为Arcs,所以lazy_static!不会工作(返回参考)

我现在拥有的:

use rsa::{hash, PaddingScheme, PublicKey, RSAPublicKey};

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

    #[tokio::test]
    async fn test_1() {
        let (pub_key, priv_key) = new_keypair();
        // ...
    }

    #[tokio::test]
    async fn test_2() {
        let (pub_key, priv_key) = new_keypair();
        // ...
    }

    // ...

    fn new_keypair() -> (RSAPublicKey, RSAPrivateKey) {
        use rand::rngs::OsRng;
        let mut rng = OsRng;
        let bits = 2048;
        let private_key =
            RSAPrivateKey::new(&mut rng, bits).expect("Failed to generate private key");
        let public_key = RSAPublicKey::from(&private_key);
        (public_key, private_key)
    }
}

(伪代码)我需要什么:

use rsa::{hash, PaddingScheme, PublicKey, RSAPublicKey};

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

    // Pseudo-code
    #[tokio::test_main]
    async fn main() {
        let (pub_key, priv_key) = new_keypair();
        run_tests(pub_key, priv_key);
    }

    #[tokio::test]
    async fn test_1(pub_key: RSAPublicKey, priv_key: RSAPrivateKey) {
        // ...
    }

    #[tokio::test]
    async fn test_2(pub_key: RSAPublicKey, priv_key: RSAPrivateKey) {
        // ...
    }

    // ...

    fn new_keypair() -> (RSAPublicKey, RSAPrivateKey) {
        use rand::rngs::OsRng;
        let mut rng = OsRng;
        let bits = 2048;
        let private_key =
            RSAPrivateKey::new(&mut rng, bits).expect("Failed to generate private key");
        let public_key = RSAPublicKey::from(&private_key);
        (public_key, private_key)
    }
}

标签: testingrustruntimersadynamically-generated

解决方案


您只能使用lazy_static一次来初始化密钥对。但是,使用这种方法,您将只能使用共享引用。如果这对您的用例来说不是问题,那么以下代码应该可以帮助您入门。

为响应更新而编辑:处理其他类型时也适用相同的原则。以下代码使用Arcasync测试。

use rsa::RSAPrivateKey;
use std::sync::Arc;

pub async fn consume(key: Arc<RSAPrivateKey>) {
    // unimplemented!("")
}

#[cfg(test)]
mod tests {
    use super::*;
    use lazy_static::lazy_static;
    use rsa::{RSAPrivateKey, RSAPublicKey};
    use std::sync::Arc;

    lazy_static! {
        static ref PRIV_KEY: Arc<RSAPrivateKey> = Arc::new(new_priv_key());
        static ref PUB_KEY: Arc<RSAPublicKey> = Arc::new(PRIV_KEY.to_public_key());
    }

    #[tokio::test]
    async fn test_1() {
        let priv_key = PRIV_KEY.clone();

        consume(priv_key).await
    }

    fn new_priv_key() -> RSAPrivateKey {
        use rand::rngs::OsRng;
        let mut rng = OsRng;
        let bits = 2048;
        let private_key =
            RSAPrivateKey::new(&mut rng, bits).expect("Failed to generate private key");
        private_key
    }
}

根据 的文档RSAPrivateKey,您甚至可能不需要RSAPublicKey, 因为RSAPrivateKey实现了PublicKeytrait。


推荐阅读