@@ -184,6 +184,78 @@ public function testRemoveStreamForWriteOnly()
184184 $ this ->tickLoop ($ this ->loop );
185185 }
186186
187+ public function testRemoveReadAndWriteStreamFromLoopOnceResourceClosesEndsLoop ()
188+ {
189+ list ($ stream , $ other ) = $ this ->createSocketPair ();
190+ stream_set_blocking ($ stream , false );
191+ stream_set_blocking ($ other , false );
192+
193+ // dummy writable handler
194+ $ this ->loop ->addWriteStream ($ stream , function () { });
195+
196+ // remove stream when the stream is readable (closes)
197+ $ this ->loop ->addReadStream ($ stream , function ($ stream ) {
198+ $ this ->loop ->removeReadStream ($ stream );
199+ $ this ->loop ->removeWriteStream ($ stream );
200+ fclose ($ stream );
201+ });
202+
203+ // close other side
204+ fclose ($ other );
205+
206+ $ this ->assertRunFasterThan ($ this ->tickTimeout );
207+ }
208+
209+ public function testRemoveReadAndWriteStreamFromLoopOnceResourceClosesOnEndOfFileEndsLoop ()
210+ {
211+ list ($ stream , $ other ) = $ this ->createSocketPair ();
212+ stream_set_blocking ($ stream , false );
213+ stream_set_blocking ($ other , false );
214+
215+ // dummy writable handler to fill outgoing buffer
216+ $ this ->loop ->addWriteStream ($ stream , function ($ stream ) use ($ other ) {
217+ fwrite ($ stream , str_repeat ('. ' , 60000 ));
218+
219+ // close other side once outgoing buffer is filled
220+ fclose ($ other );
221+ });
222+
223+ // remove stream when the stream is readable (closes)
224+ $ never = $ this ->expectCallableNever ();
225+ $ this ->loop ->addReadStream ($ stream , function ($ stream ) use ($ never ) {
226+ $ data = fread ($ stream , 1024 );
227+ if ($ data !== '' ) {
228+ // we expect to read an empty string => stream closed
229+ return $ never ();
230+ }
231+
232+ $ this ->loop ->removeReadStream ($ stream );
233+ $ this ->loop ->removeWriteStream ($ stream );
234+ fclose ($ stream );
235+ });
236+
237+ $ this ->assertRunFasterThan (0.1 );
238+ }
239+
240+ public function testRemoveReadAndWriteStreamFromLoopWithClosingResourceEndsLoop ()
241+ {
242+ // get only one part of the pair to ensure the other side will close immediately
243+ list ($ stream ) = $ this ->createSocketPair ();
244+ stream_set_blocking ($ stream , false );
245+
246+ // dummy writable handler
247+ $ this ->loop ->addWriteStream ($ stream , function () { });
248+
249+ // remove stream when the stream is readable (closes)
250+ $ this ->loop ->addReadStream ($ stream , function ($ stream ) {
251+ $ this ->loop ->removeReadStream ($ stream );
252+ $ this ->loop ->removeWriteStream ($ stream );
253+ fclose ($ stream );
254+ });
255+
256+ $ this ->assertRunFasterThan ($ this ->tickTimeout );
257+ }
258+
187259 public function testRemoveInvalid ()
188260 {
189261 list ($ stream ) = $ this ->createSocketPair ();
0 commit comments