首页 > 其他分享 >34. 干货系列从零用Rust编写负载均衡及代理,异步测试在Rust中的实现

34. 干货系列从零用Rust编写负载均衡及代理,异步测试在Rust中的实现

时间:2023-12-16 10:22:21浏览次数:24  
标签:测试 零用 len 34 assert str test async Rust

wmproxy

wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起造个轮子

项目地址

国内: https://gitee.com/tickbh/wmproxy

github: https://github.com/tickbh/wmproxy

自动化测试

在程序中,通常会写一些自动化测试的功能,来保证我们的代码正确的执行符合预期的效果,随着时间的变化,当代码变动的数据越来越多时,保证能实时的测试确保整个系统高概率的正常运转,不会因为改一个Bug而产生另一个Bug

Rust中的测试

Rust中的测试分为两个部分

  • 文档测试

文档测试通常在函数前面或者类前面,通过文档测试来保证该函数的运行能符合我们的预期,通常/// ``` 包围,以下为测试示例,如果仅仅以///开头那么测试

/// 测试vec的大小 
///
/// use std::vec::Vec;
/// 
/// let mut vec = Vec::new();
/// assert_eq!(vec.len(), 0);
/// vec.push(1);
/// assert_eq!(vec.len(), 1);
fn show_test() {

}

此时我们运行cargo test可以看的到如下输出:

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

此时并不能识别我们的文档测试用例,那么我们在代码前后加上/// ```再来运行

/// 测试vec的大小 
///
/// ```
/// use std::vec::Vec;
/// 
/// let mut vec = Vec::new();
/// assert_eq!(vec.len(), 0);
/// vec.push(1);
/// assert_eq!(vec.len(), 1);
/// ```
fn show_test() {

}

将得到如下输出

running 1 test
test src\lib.rs - show_test (line 3) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.22s  

此时测试通过自动化模块

  • 测试模块
    这是每个模块下可以通过自定义测试函数来对每个类进行自动化测试,让我们来看下面一个例子:
fn str_len(s: &str) -> usize {
  s.len()
}

async fn str_len_async(s: &str) -> usize {
  // 做些异步的事情
  s.len()
}

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

  #[test]
  fn test_str_len() {
    assert_eq!(str_len("x5ff"), 4);
  }

此时运行测试结果很完美的通过测试

running 1 test
test tests::test_str_len ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s 

当我们将str_len->str_len_async时,那么他提示我们

error[E0369]: binary operation `==` cannot be applied to type `impl Future<Output = usize>`   
  --> src\lib.rs:29:9
   |
29 |         assert_eq!(str_len_async("x5ff"), 4);
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |         |
   |         impl Future<Output = usize>
   |         {integer}
   |
   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: `impl Future<Output = usize>` doesn't implement `Debug`
  --> src\lib.rs:29:9
   |
29 |         assert_eq!(str_len_async("x5ff"), 4);
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `impl Future<Output = usize>` cannot be formatted using `{:?}` because it doesn't implement `Debug`
   |
   = help: the trait `Debug` is not implemented for `impl Future<Output = usize>`
   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)

Some errors have detailed explanations: E0277, E0369.
For more information about an error, try `rustc --explain E0277`.

因为异步返回的结果是Future,所以我们无法通过编译。

那么异步的函数如何通过自动化测试呢?

我们尝试将测试函数改成异步

mod tests {
    use super::*;

    #[test]
    async fn test_str_len() {
        assert_eq!(str_len_async("x5ff").await, 4);
    }
}

编译器提示我们,因为编译器暂时不能支持异步的测试

error: async functions cannot be used for tests
  --> src\lib.rs:28:5
   |
28 |       async fn test_str_len() {
   |       ^----
   |       |
   |  _____`async` because of this
   | |
29 | |         assert_eq!(str_len_async("x5ff").await, 4);
30 | |     }
   | |_____^

异步测试的两种方法

此处讲的依赖tokioruntime,其它的异步为类似。

  • #[tokio::test]来完成异步测试
    首先我们依赖:
[dependencies]
tokio = { version = "*", features = [
    "macros",
    "test-util",
] }
tokio-test = "0.4.3"

此刻我们将代码改写成:

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

    #[tokio::test]
    async fn test_str_len() {
        assert_eq!(str_len_async("x5ff").await, 4);
    }
}

此时运行cargo test,将正常的运行通过

  • 用宏定义来完成异步测试

此方法运用的是通过同步函数中运行一个runtime来运行异步函数

以下是我们的宏定义及调用

macro_rules! aw {
    ($e:expr) => {
        tokio_test::block_on($e)
    };
}
#[test]
fn test_str_len_async_2() {
    assert_eq!(aw!(str_len_async("x5ff")), 4);
}

此时运行cargo test,将正常的运行通过

running 2 tests
test tests::test_str_len_async_2 ... ok
test tests::test_str_len ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s 

但是此时如果是局部测试,该方法有另一个好处,编辑器的识别度较高,能更好的显示支持

小结

测试是编程中不可缺少的伙伴,他可以让我们更早的发现问题解决问题,编写测试用例可能看起来会慢一些,但是对后期可能潜在的Bug的排查会节省大量的时间。

点击 [关注][在看][点赞] 是对作者最大的支持

标签:测试,零用,len,34,assert,str,test,async,Rust
From: https://www.cnblogs.com/wmproxy/p/wmproxy34.html

相关文章

  • https://avoid.overfit.cn/post/979f42aebee34d8cab04bf591e58d782
    在本文中,我将介绍matplotlib一个非常有价值的用于管理子图的函数——subplot_mosaic()。如果你想处理多个图的,那么subplot_mosaic()将成为最佳解决方案。我们将用四个不同的图实现不同的布局。首先使用Importmatplotlib行导入必要的库。https://avoid.overfit.cn/post/979f42a......
  • 为什么 Go 和 Rust 语言都舍弃了继承?
    为什么go和rust语言都舍弃了继承?❎舍弃了Class✅舍弃或弱化子类型类的继承是一段儿弯路OO发明了继承,然后发现真正有意义的是interface的组合(更准确的说,是Producttypeofinterfacesorabstractclasses),语义上相当于组合,但在Cpp,Java等语言中,还是使用继承来实现),具体......
  • Win 10 Rust Installtion in D Disk with VSCode
    (只记录了必须要内容,日后完善!)1.rust的安装与环境变量:要提前把下面两个环境变量配置好,这样是为了指定安装路径。否则会默认安装在C盘下。CARGO_HOME:D:\Soft\Language\Rust\.cargoRUSTUP_HOME:D:\Soft\Language\Rust\.rustup然后,在这个:Rust,Get-Start界面上下载rust......
  • 通过match看rust
    最常见的逻辑控制流比如if-else,switch,while等常用编程语言都支持,但恰巧rust语法中没有switch,取而代之的是更加强大适用的match匹配,我们就来看看rust的match有何奇特之处。 一、介绍先来看一个简单的rust的match用法enumRole{Admin,User,Guest,Unkow......
  • cbindgen rust 代码生成c binding 的工具
    rust与c以及c与rust的互调用还是比较常见的需求,很多时候自己写可能比较费事,但是使用一些工具就比较方便了cbindgen是一个对于rust代码生成cbinding的工具参考使用基于cbindgen将rust的代码生成对应的c头文件,之后基于cmake构建项目项目结构 ├──......
  • 聊一聊Rust的enum
    enum在实际编程中是非常常用的,enum的目的就是为了清晰定义出散落在系统各个角落的相同概念的有限固定值。一、enum介绍如果是简单定义固定值,我们可以使用常量const。比如publicconstintMAX_THREAD_COUNT=100;在C语言中,我们可以这样定义一个枚举方便各处使用,比如:enumDi......
  • RustDesk 部署
    一、通过编译好的文件安装1、下载服务端程序wget-P/usr/local/srchttps://github.com/rustdesk/rustdesk-server/releases/download/1.1.9/rustdesk-server-linux-amd64.zip2、解压文件并创建用户#解压tarxf/usr/local/src/rustdesk-server-linux-amd64.zi......
  • 关于Rust的简单总结(一)
    0.前言这是一个关于Rust的简单总结。(待续)资料学习网址:学习Rust-Rust程序设计语言(rust-lang.org)官网:Rust程序设计语言(rust-lang.org)Rust介绍[[Rust]]程序设计语言的本质实际在于 赋能(empowerment):无论你现在编写的是何种代码,Rust能让你在更为广泛的编程......
  • iwtgm-34
    EducationalCodeforcesRound159(RatedforDiv.2)A.只要有0就是yes因为若只有0,显然满足条件若0和1都有,一定会有01相邻的情况,我们插入0后,仍有01相邻的情况,即我们可以无限+0,那么最后0的个数一定可以大于1voidsolve(){intn;cin>>n;strings;cin>>s;intc......
  • ACwing343.排序
    1.Floyd写法:#include<cstring>#include<iostream>#include<algorithm>usingnamespacestd;constintN=26;intn,m;boold[N][N];boolst[N];intcheck(){for(inti=0;i<n;i++)if(d[i][i])re......