@@ -144,26 +144,36 @@ describeAdversarial('Adversarial playground', () => {
144144 testTimeoutMs
145145 ) ;
146146
147- it . fails (
148- 'handles mixed concurrency with a timeout and a fast success ' ,
147+ it (
148+ 'settles every call loudly when a timeout interleaves with a queued call ' ,
149149 async ( ) => {
150- const bridge = await createBridge ( { timeoutMs : 250 } ) ;
150+ // Whether the queued fast call starves into its own timeout or completes
151+ // once the worker frees up depends on scheduler timing under the serial
152+ // pool default — both are loud, and asserting one side made this test
153+ // flap between environments (it passed on fast CI runners while marked
154+ // it.fails from local behavior). The deterministic invariants: the slow
155+ // call times out, the fast call settles either way with a real
156+ // value/error, and the bridge stays usable afterwards.
157+ const bridge = await createBridge ( { timeoutMs : 4_000 } ) ;
151158 if ( ! bridge ) return ;
152159
153160 try {
154- const slow = callAdversarial ( bridge , 'sleep_and_return' , [ 'slow' , 0.5 ] ) ;
161+ const slow = callAdversarial ( bridge , 'sleep_and_return' , [ 'slow' , 6.0 ] ) ;
155162 const fast = callAdversarial ( bridge , 'echo' , [ 'fast' ] ) ;
156163 const results = await Promise . allSettled ( [ slow , fast ] ) ;
157164
158- // Known limitation: the subprocess bridge is serial, so a slow call can
159- // starve subsequent calls and time them out.
160165 expect ( results [ 0 ] . status ) . toBe ( 'rejected' ) ;
161- expect ( results [ 1 ] . status ) . toBe ( 'fulfilled' ) ;
166+ if ( results [ 0 ] . status === 'rejected' ) {
167+ expect ( String ( results [ 0 ] . reason ) ) . toMatch ( / t i m e d o u t / i) ;
168+ }
162169 if ( results [ 1 ] . status === 'fulfilled' ) {
163170 expect ( results [ 1 ] . value ) . toBe ( 'fast' ) ;
171+ } else {
172+ expect ( String ( results [ 1 ] . reason ) ) . toMatch ( / t i m e d o u t / i) ;
164173 }
165174
166- await delay ( 600 ) ;
175+ // Why: let the slow worker drain (or restart) before probing recovery.
176+ await delay ( 6_000 ) ;
167177 const again = await callAdversarial ( bridge , 'echo' , [ 'after-timeout' ] ) ;
168178 expect ( again ) . toBe ( 'after-timeout' ) ;
169179 } finally {
0 commit comments