Тестирование фьючерсов и потоков, как создать поддельный контекст? - PullRequest
1 голос
/ 05 августа 2020

Я пытаюсь понять, как провести модульное тестирование моего потока fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {todo!()}

Требуется контекст cx, который передается во вложенный поток. Мой тестовый и тестовый код может обойтись без него, но я должен предоставить некоторые, чтобы иметь возможность протестировать.

Ответы [ 2 ]

1 голос
/ 05 августа 2020

Я наконец нашел n oop waker:

Playground :

#[test]
fn test1() {
    let waker = futures::task::noop_waker_ref();
    let mut cx = std::task::Context::from_waker(waker);
    let setup = TestStream::from(vec![Poll::Ready(Some(true))]);
    let mut sut = MyStream(setup);

    assert_eq!(Pin::new(&mut sut).poll_next(&mut cx), Poll::Ready(Some(())))
}

Спасибо @ rodri go за тоже правильный ответ.

1 голос
/ 05 августа 2020

Создать Context просто: Context::from_waker(waker: &'a Waker).

Но где взять подделку Waker? Вы должны использовать небезопасный Waker::from_raw(waker: RawWaker).

Но ... и RawWaker? Ну вот такая RawWaker::new(data: *const (), vtable: &'static RawWakerVTable). Если вас не интересует фактический запуск фьючерсов, вы можете просто использовать stati c () указатель и фиктивную vtable:

use std::task::{
    RawWaker,
    RawWakerVTable,
    Waker,
};

static DUMMY_VTABLE: RawWakerVTable = RawWakerVTable::new(
    dummy_clone,
    dummy_wake,
    dummy_wake_by_ref,
    dummy_drop,
);
unsafe fn dummy_clone(ptr: *const ()) -> RawWaker {
    RawWaker::new(
        ptr,
        &DUMMY_VTABLE
    )
}
unsafe fn dummy_wake(_ptr: *const ()) {
}

unsafe fn dummy_wake_by_ref(_ptr: *const ()) {
}

unsafe fn dummy_drop(_ptr: *const ()) {
}

fn dummy_waker() -> Waker {
    unsafe {
        Waker::from_raw(
            RawWaker::new(
                &(),
                &DUMMY_VTABLE
            )
        )
    }
}

Затем вы создаете локальный waker и контекст, где вам нужно их:

let waker = dummy_waker();
let mut cx = Context::new(&waker);
assert_eq!(Pin::new(&mut sut).poll_next(&mut cx), Poll::Ready(Some(())))
...