使用正确的参数验证方法是否被调用了预期的次数[重复]

问题描述 投票:0回答:1

摘要

我有一个应用程序启动另一个进程,并使用log包将其StdOut / StdErr传输到日志文件。我的应用程序逐行传输输出(buf_read.read_line())。因为它可以是任意的进程,我的应用程序假设其他进程可能是恶意的,并且可能尝试在没有单个换行符的情况下打印到stdout / sterr大量数据,从而在我的应用程序中导致OOM。因此,我的应用程序使用BufReader限制BufReader.take()一次可读取的字节数。

问题

忽略有关分块输入的所有细节,如何使用正确的参数测试我的记录器被调用X次?让我们假设我的应用已阅读了一条巨大的线,并将其拆分为3个部分,如下面的MCVE。

MCVE:

use std::thread::JoinHandle;

fn main() {
    let handle = start_transfer_thread(&|x| {
        println!("X={}", x);
    }).join();
}

fn start_transfer_thread<F>(logger: &'static F) -> JoinHandle<()> where F: Send + Sync + Fn(&str) -> () {
    std::thread::spawn(move || {
        logger("1");
        logger("2");
        logger("3");
    })
}

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

    #[test]
    fn test_logged_in_order() {
        let result = start_transfer_thread(&|x| {
            match x {
                "1" => (),
                "2" => (),
                "3" => (),
                x => panic!("unexpected token: {}", x)
            }
        }).join();
        assert!(result.is_ok());
    }
}
rust
1个回答
1
投票

我能够通过用特征对象替换函数/闭包来做到这一点:

trait Logger: Send + Sync {
    fn log(&mut self, log_name: &str, data: &str);
}

struct StandardLogger;

impl Logger for StandardLogger {
    fn log(&mut self, log_name: &str, data: &str) {
        log::logger().log(
            &log::Record::builder()
                .level(log::Level::Info)
                .target(log_name)
                .args(format_args!("{}", data))
                .build(),
        );
    }
}

对于测试,我使用另一个实现:

struct DummyLogger {
    tx: Mutex<Sender<String>>,
}

impl DummyLogger {
    pub fn new() -> (DummyLogger, Receiver<String>) {
        let (tx, rx) = std::sync::mpsc::channel();
        let logger = DummyLogger { tx: Mutex::new(tx) };
        (logger, rx)
    }
}

impl Logger for DummyLogger {
    fn log(&mut self, log_name: &str, data: &str) {
        let tx = self.tx.lock().unwrap();
        tx.send(data.to_owned());
    }
}

这允许我使用正确的参数验证它被称为正确的次数:

let actual: Vec<String> = rx.iter().collect();
assert_eq!(actual, vec!["1", "2", "3", "4"]);
© www.soinside.com 2019 - 2024. All rights reserved.