@@ -379,20 +379,67 @@ public function testNoChangeAfterResumeBeforeInsert()
379379 $ this ->assertMatchesDocument ($ expectedResult , $ changeStream ->current ());
380380 }
381381
382- public function testResumeTokenIsUpdatedAfterResuming ()
382+ public function testResumeMultipleTimesInSuccession ()
383383 {
384- $ this ->insertDocument (['_id ' => 1 ]);
384+ $ operation = new CreateCollection ($ this ->getDatabaseName (), $ this ->getCollectionName ());
385+ $ operation ->execute ($ this ->getPrimaryServer ());
385386
386387 $ operation = new Watch ($ this ->manager , $ this ->getDatabaseName (), $ this ->getCollectionName (), [], $ this ->defaultOptions );
387388 $ changeStream = $ operation ->execute ($ this ->getPrimaryServer ());
388389
390+ /* Killing the cursor when there are no results will test that neither
391+ * the initial rewind() nor its resume attempt incremented the key. */
392+ $ this ->killChangeStreamCursor ($ changeStream );
393+
389394 $ changeStream ->rewind ();
395+ $ this ->assertFalse ($ changeStream ->valid ());
396+ $ this ->assertNull ($ changeStream ->key ());
390397 $ this ->assertNull ($ changeStream ->current ());
391398
399+ $ this ->insertDocument (['_id ' => 1 ]);
400+
401+ /* Killing the cursor a second time when there is a result will test
402+ * that the resume attempt picks up the latest change. */
403+ $ this ->killChangeStreamCursor ($ changeStream );
404+
405+ $ changeStream ->rewind ();
406+ $ this ->assertTrue ($ changeStream ->valid ());
407+ $ this ->assertSame (0 , $ changeStream ->key ());
408+
409+ $ expectedResult = [
410+ '_id ' => $ changeStream ->current ()->_id ,
411+ 'operationType ' => 'insert ' ,
412+ 'fullDocument ' => ['_id ' => 1 ],
413+ 'ns ' => ['db ' => $ this ->getDatabaseName (), 'coll ' => $ this ->getCollectionName ()],
414+ 'documentKey ' => ['_id ' => 1 ],
415+ ];
416+
417+ $ this ->assertMatchesDocument ($ expectedResult , $ changeStream ->current ());
418+
419+ /* Killing the cursor a second time will not trigger a resume until
420+ * ChangeStream::next() is called. A successive call to rewind() should
421+ * not change the iterator's state and preserve the current result. */
422+ $ this ->killChangeStreamCursor ($ changeStream );
423+
424+ $ changeStream ->rewind ();
425+ $ this ->assertTrue ($ changeStream ->valid ());
426+ $ this ->assertSame (0 , $ changeStream ->key ());
427+
428+ $ expectedResult = [
429+ '_id ' => $ changeStream ->current ()->_id ,
430+ 'operationType ' => 'insert ' ,
431+ 'fullDocument ' => ['_id ' => 1 ],
432+ 'ns ' => ['db ' => $ this ->getDatabaseName (), 'coll ' => $ this ->getCollectionName ()],
433+ 'documentKey ' => ['_id ' => 1 ],
434+ ];
435+
436+ $ this ->assertMatchesDocument ($ expectedResult , $ changeStream ->current ());
437+
392438 $ this ->insertDocument (['_id ' => 2 ]);
393439
394440 $ changeStream ->next ();
395441 $ this ->assertTrue ($ changeStream ->valid ());
442+ $ this ->assertSame (1 , $ changeStream ->key ());
396443
397444 $ expectedResult = [
398445 '_id ' => $ changeStream ->current ()->_id ,
@@ -410,6 +457,7 @@ public function testResumeTokenIsUpdatedAfterResuming()
410457
411458 $ changeStream ->next ();
412459 $ this ->assertTrue ($ changeStream ->valid ());
460+ $ this ->assertSame (2 , $ changeStream ->key ());
413461
414462 $ expectedResult = [
415463 '_id ' => $ changeStream ->current ()->_id ,
@@ -431,6 +479,7 @@ public function testResumeTokenIsUpdatedAfterResuming()
431479
432480 $ changeStream ->next ();
433481 $ this ->assertTrue ($ changeStream ->valid ());
482+ $ this ->assertSame (3 , $ changeStream ->key ());
434483
435484 $ expectedResult = [
436485 '_id ' => $ changeStream ->current ()->_id ,
0 commit comments