@@ -6,128 +6,134 @@ use std::future::Future;
66use std:: task:: Context ;
77use wit_bindgen:: yield_async;
88
9- fn main ( ) {
10- println ! ( "test cancelling an import in progress" ) ;
11- wit_bindgen:: block_on ( async {
12- let ( tx, rx) = wit_future:: new ( || unreachable ! ( ) ) ;
13- let mut import = Box :: pin ( pending_import ( rx) ) ;
14- assert ! ( import
15- . as_mut( )
16- . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
17- . is_pending( ) ) ;
18- drop ( import) ;
19- tx. write ( ( ) ) . await . unwrap_err ( ) ;
20- } ) ;
21-
22- println ! ( "test cancelling an import before it starts" ) ;
23- wit_bindgen:: block_on ( async {
24- let ( tx, rx) = wit_future:: new ( || unreachable ! ( ) ) ;
25- let import = Box :: pin ( pending_import ( rx) ) ;
26- drop ( import) ;
27- tx. write ( ( ) ) . await . unwrap_err ( ) ;
28- } ) ;
29-
30- println ! ( "test cancelling an import in the started state" ) ;
31- wit_bindgen:: block_on ( async {
32- let ( tx1, rx1) = wit_future:: new ( || unreachable ! ( ) ) ;
33- let ( tx2, rx2) = wit_future:: new ( || unreachable ! ( ) ) ;
34-
35- // create a task in the "started" state, but don't complete it yet
36- let mut started_import = Box :: pin ( pending_import ( rx1) ) ;
37- assert ! ( started_import
38- . as_mut( )
39- . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
40- . is_pending( ) ) ;
41-
42- // request the other component sets its backpressure flag meaning we
43- // won't be able to create new tasks in the "started" state.
44- backpressure_set ( true ) ;
45- let mut starting_import = Box :: pin ( pending_import ( rx2) ) ;
46- assert ! ( starting_import
47- . as_mut( )
48- . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
49- . is_pending( ) ) ;
50-
51- // Now cancel the "starting" import. This should notably drop handles in
52- // arguments since they get re-acquired during cancellation
53- drop ( starting_import) ;
54-
55- // cancel our in-progress export
56- drop ( started_import) ;
57-
58- backpressure_set ( false ) ;
59-
60- // both channels should be dropped
61- tx1. write ( ( ) ) . await . unwrap_err ( ) ;
62- tx2. write ( ( ) ) . await . unwrap_err ( ) ;
63- } ) ;
64-
65- // Race an import's cancellation with a status code saying it's done.
66- println ! ( "test cancellation with a status code saying it's done" ) ;
67- wit_bindgen:: block_on ( async {
68- // Start a subtask and get it into the "started" state
69- let ( tx, rx) = wit_future:: new ( || unreachable ! ( ) ) ;
70- let mut import = Box :: pin ( pending_import ( rx) ) ;
71- assert ! ( import
72- . as_mut( )
73- . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
74- . is_pending( ) ) ;
75-
76- // Complete the subtask, but don't see the completion in Rust yet.
77- tx. write ( ( ) ) . await . unwrap ( ) ;
78-
79- // Let the subtask's completion notification make its way to our task
80- // here.
81- for _ in 0 ..5 {
82- yield_async ( ) . await ;
9+ struct Component ;
10+
11+ export ! ( Component ) ;
12+
13+ impl Guest for Component {
14+ async fn run ( ) {
15+ println ! ( "test cancelling an import in progress" ) ;
16+ {
17+ let ( tx, rx) = wit_future:: new ( || unreachable ! ( ) ) ;
18+ let mut import = Box :: pin ( pending_import ( rx) ) ;
19+ assert ! ( import
20+ . as_mut( )
21+ . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
22+ . is_pending( ) ) ;
23+ drop ( import) ;
24+ tx. write ( ( ) ) . await . unwrap_err ( ) ;
8325 }
8426
85- // Now cancel the import, despite it actually being done. This should
86- // realize that the cancellation is racing completion.
87- drop ( import) ;
88- } ) ;
89-
90- // Race an import's cancellation with a pending status code indicating that
91- // it's transitioning from started => returned.
92- println ! ( "race cancellation with pending status code" ) ;
93- wit_bindgen:: block_on ( async {
94- // Start a subtask and get it into the "started" state
95- let ( tx1, rx1) = wit_future:: new ( || unreachable ! ( ) ) ;
96- let mut started_import = Box :: pin ( pending_import ( rx1) ) ;
97- assert ! ( started_import
98- . as_mut( )
99- . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
100- . is_pending( ) ) ;
101-
102- // force the next subtask to start out in the "starting" state, not the
103- // "started" state.
104- backpressure_set ( true ) ;
105- let ( tx2, rx2) = wit_future:: new ( || unreachable ! ( ) ) ;
106- let mut starting_import = Box :: pin ( pending_import ( rx2) ) ;
107- assert ! ( starting_import
108- . as_mut( )
109- . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
110- . is_pending( ) ) ;
111-
112- // Disable backpressure in the other component which will let the
113- // `starting_import`, previously in the "STARTING" state, get a queued up
114- // notification that it's entered the "STARTED" state.
115- backpressure_set ( false ) ;
116- for _ in 0 ..5 {
117- yield_async ( ) . await ;
27+ println ! ( "test cancelling an import before it starts" ) ;
28+ {
29+ let ( tx, rx) = wit_future:: new ( || unreachable ! ( ) ) ;
30+ let import = Box :: pin ( pending_import ( rx) ) ;
31+ drop ( import) ;
32+ tx. write ( ( ) ) . await . unwrap_err ( ) ;
11833 }
11934
120- // Now cancel the `starting_import`. This should correctly pick up the
121- // STARTING => STARTED state transition and handle that correctly.
122- drop ( starting_import) ;
35+ println ! ( "test cancelling an import in the started state" ) ;
36+ {
37+ let ( tx1, rx1) = wit_future:: new ( || unreachable ! ( ) ) ;
38+ let ( tx2, rx2) = wit_future:: new ( || unreachable ! ( ) ) ;
39+
40+ // create a task in the "started" state, but don't complete it yet
41+ let mut started_import = Box :: pin ( pending_import ( rx1) ) ;
42+ assert ! ( started_import
43+ . as_mut( )
44+ . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
45+ . is_pending( ) ) ;
46+
47+ // request the other component sets its backpressure flag meaning we
48+ // won't be able to create new tasks in the "started" state.
49+ backpressure_set ( true ) ;
50+ let mut starting_import = Box :: pin ( pending_import ( rx2) ) ;
51+ assert ! ( starting_import
52+ . as_mut( )
53+ . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
54+ . is_pending( ) ) ;
55+
56+ // Now cancel the "starting" import. This should notably drop handles in
57+ // arguments since they get re-acquired during cancellation
58+ drop ( starting_import) ;
59+
60+ // cancel our in-progress export
61+ drop ( started_import) ;
62+
63+ backpressure_set ( false ) ;
64+
65+ // both channels should be dropped
66+ tx1. write ( ( ) ) . await . unwrap_err ( ) ;
67+ tx2. write ( ( ) ) . await . unwrap_err ( ) ;
68+ }
12369
124- // Our future to the import we cancelled shouldn't be able to complete
125- // its write.
126- tx2. write ( ( ) ) . await . unwrap_err ( ) ;
70+ // Race an import's cancellation with a status code saying it's done.
71+ println ! ( "test cancellation with a status code saying it's done" ) ;
72+ {
73+ // Start a subtask and get it into the "started" state
74+ let ( tx, rx) = wit_future:: new ( || unreachable ! ( ) ) ;
75+ let mut import = Box :: pin ( pending_import ( rx) ) ;
76+ assert ! ( import
77+ . as_mut( )
78+ . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
79+ . is_pending( ) ) ;
80+
81+ // Complete the subtask, but don't see the completion in Rust yet.
82+ tx. write ( ( ) ) . await . unwrap ( ) ;
83+
84+ // Let the subtask's completion notification make its way to our task
85+ // here.
86+ for _ in 0 ..5 {
87+ yield_async ( ) . await ;
88+ }
89+
90+ // Now cancel the import, despite it actually being done. This should
91+ // realize that the cancellation is racing completion.
92+ drop ( import) ;
93+ }
12794
128- // Complete the other import normally just to assert that it's not
129- // cancelled and able to proceed as usual.
130- tx1. write ( ( ) ) . await . unwrap ( ) ;
131- started_import. await ;
132- } ) ;
95+ // Race an import's cancellation with a pending status code indicating that
96+ // it's transitioning from started => returned.
97+ println ! ( "race cancellation with pending status code" ) ;
98+ {
99+ // Start a subtask and get it into the "started" state
100+ let ( tx1, rx1) = wit_future:: new ( || unreachable ! ( ) ) ;
101+ let mut started_import = Box :: pin ( pending_import ( rx1) ) ;
102+ assert ! ( started_import
103+ . as_mut( )
104+ . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
105+ . is_pending( ) ) ;
106+
107+ // force the next subtask to start out in the "starting" state, not the
108+ // "started" state.
109+ backpressure_set ( true ) ;
110+ let ( tx2, rx2) = wit_future:: new ( || unreachable ! ( ) ) ;
111+ let mut starting_import = Box :: pin ( pending_import ( rx2) ) ;
112+ assert ! ( starting_import
113+ . as_mut( )
114+ . poll( & mut Context :: from_waker( noop_waker_ref( ) ) )
115+ . is_pending( ) ) ;
116+
117+ // Disable backpressure in the other component which will let the
118+ // `starting_import`, previously in the "STARTING" state, get a queued up
119+ // notification that it's entered the "STARTED" state.
120+ backpressure_set ( false ) ;
121+ for _ in 0 ..5 {
122+ yield_async ( ) . await ;
123+ }
124+
125+ // Now cancel the `starting_import`. This should correctly pick up the
126+ // STARTING => STARTED state transition and handle that correctly.
127+ drop ( starting_import) ;
128+
129+ // Our future to the import we cancelled shouldn't be able to complete
130+ // its write.
131+ tx2. write ( ( ) ) . await . unwrap_err ( ) ;
132+
133+ // Complete the other import normally just to assert that it's not
134+ // cancelled and able to proceed as usual.
135+ tx1. write ( ( ) ) . await . unwrap ( ) ;
136+ started_import. await ;
137+ }
138+ }
133139}
0 commit comments