wmproxy
已用Rust
實現http/https
代理, socks5
代理, 反向代理, 靜態檔案伺服器,四層TCP/UDP轉發,七層負載均衡,內網穿透,後續將實現websocket
代理等,會將實現過程分享出來,感興趣的可以一起造個輪子
國內: https://gitee.com/tickbh/wmproxy
github: https://github.com/tickbh/wmproxy
在程式中,通常會寫一些自動化測試的功能,來保證我們的程式碼正確的執行符合預期的效果,隨著時間的變化,當程式碼變動的資料越來越多時,保證能實時的測試確保整個系統高概率的正常運轉,不會因為改一個Bug而產生另一個Bug
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 | | }
| |_____^
此處講的依賴tokio
的runtime
,其它的非同步為類似。
#[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的排查會節省大量的時間。
點選 [關注],[在看],[點贊] 是對作者最大的支援