Skip to content

Commit

Permalink
Add a test for waker-updating behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
goffrie committed Jul 24, 2024
1 parent 89c3928 commit ff35ff3
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
1 change: 1 addition & 0 deletions crates/tests/winrt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ features = [
"Foundation_Numerics",
"Storage_Streams",
"System",
"System_Threading",
"UI_Composition",
"Win32_System_Com",
"Win32_System_WinRT",
Expand Down
52 changes: 48 additions & 4 deletions crates/tests/winrt/tests/async.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
use std::future::IntoFuture;

use futures::{executor::LocalPool, future, task::SpawnExt};
use windows::{
Storage::Streams::*,
System::Threading::{ThreadPool, WorkItemHandler},
};

#[test]
fn async_get() -> windows::core::Result<()> {
use windows::Storage::Streams::*;

let stream = &InMemoryRandomAccessStream::new()?;

let writer = DataWriter::CreateDataWriter(stream)?;
Expand All @@ -25,8 +31,6 @@ fn async_get() -> windows::core::Result<()> {
}

async fn async_await() -> windows::core::Result<()> {
use windows::Storage::Streams::*;

let stream = &InMemoryRandomAccessStream::new()?;

let writer = DataWriter::CreateDataWriter(stream)?;
Expand All @@ -53,3 +57,43 @@ async fn async_await() -> windows::core::Result<()> {
fn test_async_await() -> windows::core::Result<()> {
futures::executor::block_on(async_await())
}

#[test]
fn test_async_updates_waker() -> windows::core::Result<()> {
let mut pool = LocalPool::new();

let (tx, rx) = std::sync::mpsc::channel::<()>();

let winrt_future = ThreadPool::RunAsync(&WorkItemHandler::new(move |_| {
rx.recv().unwrap();
Ok(())
}))?
.into_future();

let task = pool
.spawner()
.spawn_with_handle(async move {
// Poll the future once on a LocalPool task
match future::select(winrt_future, future::ready(())).await {
future::Either::Left(_) => panic!("threadpool action can't finish yet"),
future::Either::Right(((), future)) => future,
}
})
.unwrap();
let winrt_future = pool.run_until(task);

pool.spawner()
.spawn(async move {
// Now run the future to completion on a *different* LocalPool task.
// This will hang unless winrt_future properly updates its saved waker to the new task.
let (result, ()) = future::join(winrt_future, async {
tx.send(()).unwrap();
})
.await;
result.unwrap();
})
.unwrap();
pool.run();

Ok(())
}

0 comments on commit ff35ff3

Please sign in to comment.