#sink #mocking #async-stream #async #test

futures-test-sink

为 futures::sink 提供测试工具

2 个版本

0.1.1 2020 年 2 月 7 日
0.1.0 2020 年 2 月 6 日

#774 in 测试

Download history 8/week @ 2024-01-07 4/week @ 2024-01-28 14/week @ 2024-02-18 46/week @ 2024-02-25 13/week @ 2024-03-03 22/week @ 2024-03-10 22/week @ 2024-03-17

每月 104 次下载

MIT/Apache

37KB
475 代码行

crates.io Documentation CI master

futures-test-sink

此 crate 提供了方便的模拟接收器实现,可用于测试自己的 Sink。

示例

:MockSink 允许创建方便的测试

此示例包含 3 个测试。有关详细信息,请参阅 MockSink 的文档。

use async_task::waker_fn;
use std::iter;
use std::{
  task::{Poll, Context},
}
use futures::{self, stream};

   fn drain_test() {
       let e = iter::repeat::<Poll<Result<(), Never>>>(Poll::Ready(Ok(())));
       let sink = SinkMock::with_flush_feedback(e);

       let stream =
           stream::iter(vec![Ok::<u8, Never>(5u8), Ok(7), Ok(9), Ok(77), Ok(79)].into_iter());
       let send_all = stream.forward(sink);
       assert_eq!(Ok(()), futures::executor::block_on(send_all));
   }

   fn interleave_pending() {
       let e = vec![Poll::Ready(Ok::<_, Never>(())), Poll::Pending]
           .into_iter()
           .cycle();
       let sink = SinkMock::with_flush_feedback(e);

       let stream =
           stream::iter(vec![Ok::<u8, Never>(5u8), Ok(7), Ok(9), Ok(77), Ok(79)].into_iter());
       let send_all = stream.forward(sink);
       assert_eq!(Ok(()), futures::executor::block_on(send_all));
   }

   fn error() {
       let e = vec![Poll::Ready(Ok(())), Poll::Pending, Poll::Ready(Err(()))]
           .into_iter()
           .cycle();
       let sink = SinkMock::with_flush_feedback(e);

       let stream = stream::iter(vec![Ok(5u8), Ok(7), Ok(9), Ok(77), Ok(79)].into_iter());
       let send_all = stream.forward(sink);
       assert_eq!(Err(()), futures::executor::block_on(send_all));
   }

   fn main() {
    drain_test();
    interleave_pending();
    error();
   }

SinkFeedback 模拟提供对返回项的完全控制。

如果您不使用 MockSink,则此选项可能有用。

use async_task::waker_fn;
use futures::sink::Sink;
use futures_test_sink::from_iter;
use std::{
    pin::Pin,
    sync::{atomic, Arc},
    task::{Context, Poll},
};

// create a Context
let wake_cnt = Arc::new(atomic::AtomicUsize::new(0));
let cnt = wake_cnt.clone();
let waker = waker_fn(move || {
    wake_cnt.fetch_add(1, atomic::Ordering::SeqCst);
});
let mut cx = Context::from_waker(&waker);
// actual test
let poll_fallback = vec![
    Poll::Ready(Ok(())),
    Poll::Ready(Ok(())),
    Poll::Pending,
    Poll::Ready(Err(12)),
]
.into_iter();
let start_send_fallback = vec![Ok::<_, u32>(())].into_iter().cycle();
// ours sink implementation
let mut s = from_iter(poll_fallback, start_send_fallback);

let r1 = Pin::new(&mut s).poll_ready(&mut cx);
assert_eq!(r1, Poll::Ready(Ok(())));
let s1 = Pin::new(&mut s).start_send(1);
assert_eq!(s1, Ok(()));

let r2 = Pin::new(&mut s).poll_ready(&mut cx);
assert_eq!(r2, Poll::Ready(Ok(())));
// start send don't panic because start_send_fallback is cycle
let s2 = Pin::new(&mut s).start_send(2);
assert_eq!(s2, Ok(()));

// ctx.wake() wasn't called.
assert_eq!(0, cnt.load(atomic::Ordering::SeqCst));

let r3 = Pin::new(&mut s).poll_ready(&mut cx);
assert_eq!(r3, Poll::Pending);
assert_eq!(1, cnt.load(atomic::Ordering::SeqCst));

let r4 = Pin::new(&mut s).poll_ready(&mut cx);
assert_eq!(r4, Poll::Ready(Err(12)));
assert_eq!(1, cnt.load(atomic::Ordering::SeqCst));

您可能对 FuseLast 容器感兴趣,用于 Iterator。

use async_task::waker_fn;
use futures::sink::Sink;
use futures_test_sink::{from_iter, fuse_last::IteratorExt};
use std::{
    pin::Pin,
    sync::{atomic, Arc},
    task::{Context, Poll},
};

// create a Context
let wake_cnt = Arc::new(atomic::AtomicUsize::new(0));
let cnt = wake_cnt.clone();
let waker = waker_fn(move || {
    wake_cnt.fetch_add(1, atomic::Ordering::SeqCst);
});
let mut cx = Context::from_waker(&waker);
// actual test
let poll_fallback = vec![
    Poll::Ready(Ok(())),
    Poll::Ready(Err(12)),
    Poll::Ready(Ok(())),
]
.into_iter()
.fuse_last();
let start_send_fallback = vec![Ok::<_, u32>(())].into_iter().cycle();
// ours sink implementation
let mut s = from_iter(poll_fallback, start_send_fallback);

let r1 = Pin::new(&mut s).poll_ready(&mut cx);
assert_eq!(r1, Poll::Ready(Ok(())));
let s1 = Pin::new(&mut s).start_send(1);
assert_eq!(s1, Ok(()));

let r2 = Pin::new(&mut s).poll_ready(&mut cx);
assert_eq!(r2, Poll::Ready(Err(12)));

let r3 = Pin::new(&mut s).poll_ready(&mut cx);
assert_eq!(r3, Poll::Ready(Ok(())));

// if not `fuse_last` this would panic!
let r4 = Pin::new(&mut s).poll_ready(&mut cx);
assert_eq!(r3, Poll::Ready(Ok(())));

let r5 = Pin::new(&mut s).poll_ready(&mut cx);
assert_eq!(r3, Poll::Ready(Ok(())));

许可证

许可如下之一

任选其一。

贡献

除非您明确声明,否则您有意提交的任何贡献,根据 Apache-2.0 许可证定义,应作为上述双重许可,不附加任何其他条款或条件。

此项目尝试遵循以下规则

此 README 由 cargo-readme模板 生成

依赖项

~1MB
~16K SLoC