我在写一个扩展std::io::Write
和futures::io::AsyncWrite
(以及Read traits)的小型自定义协议时偶然发现了这个问题。我注意到写了很多重复的代码,因为无论是否异步,协议的行为都完全相同。这在详尽的测试中尤其糟糕,我使用了Cursor
的两个版本,需要测试两个变体一起工作。
有没有一种方法可以连接这两种特性?也许一个宏可以通过省略.await和async部分(如果适用的话)来生成这两种变体。
参考代码实现
这是一个有点麻木下来。
impl<W> ProtoWriteExt for W
where
W: Write,
{
fn proto_write<T>(&mut self, value: &T) -> Result<(), ProtocolError>
where
T: Serialize,
{
// lots of code...
// Only these calls change
self.write_all(&bytes)?;
// ...
}
}
#[async_trait]
impl<W> ProtoAsyncWriteExt for W
where
W: AsyncWrite + Unpin + Send + Sync,
{
async fn proto_write<T>(&mut self, value: &T) -> Result<(), ProtocolError>
where
T: Serialize + Sync,
{
// Same code as above...
// Only these calls change
self.write_all(&bytes).await?;
// ...
}
}
参考测试
以后还会有很多这样的测试,我也要测试非阻塞版本和阻塞版本。
/// Writing a primitive value and then reading it results in an unchanged value.
#[test]
fn transfers_primitive_correctly() -> Result<(), ProtocolError> {
let expected = 42;
let mut cursor = std::io::Cursor::new(Vec::<u8>::new());
cursor.proto_write(&expected)?;
cursor.set_position(0);
let result: i32 = cursor.proto_read()?;
assert_eq!(expected, result);
Ok(())
}
/// Writing a primitive value and then reading it results in an unchanged value.
#[tokio::test]
async fn async_transfers_primitive_correctly() -> Result<(), ProtocolError> {
let expected = 42;
let mut cursor = futures::io::Cursor::new(Vec::<u8>::new());
cursor.proto_write(&expected).await?;
cursor.set_position(0);
let result: i32 = cursor.proto_read().await?;
assert_eq!(expected, result);
Ok(())
}
2条答案
按热度按时间lxkprmvk1#
reqwest
crate在异步代码中完成了所有繁重的工作,而在blocking方法中只阻塞异步future,mongodb
和postgres
也是如此(基于tokio-postgres
crate)。有一个keyword generics initiative可以让你通用于
async
ness,但这只是早期阶段(另请参见the lang team meeting document)。您可能可以通过宏来实现这一点,但这非常困难:同步版本将不得不调用同步方法,而异步版本将需要调用异步方法不知何故。我相信这是可能的,但我不知道一个板条箱提供。
aurhwmvo2#
duplicate
crate可以创建包含目标替换的代码副本。这在您的测试中可能特别有用,测试可能如下所示:
这应该扩展到您所拥有的测试代码。
我很犹豫是否建议你用
duplicate
来代替impl
,因为在我看来,它们太不一样了,不适合duplicate
。我首先会探索重构代码的可能性,这样它们就可以简单地调用相同的函数。但是,如果这不可能,duplicate
仍然可以使用。