<?php
 namespace MongoDB\Tests\Model;
 use Exception;
 use MongoDB\Model\CachingIterator;
 use MongoDB\Tests\TestCase;
 use function iterator_to_array;
 class CachingIteratorTest extends TestCase {
 public function testTraversingGeneratorConsumesIt() {
 $iterator = $this->getTraversable([1, 2, 3]);
 $this->assertSame([1, 2, 3], iterator_to_array($iterator));
 $this->expectException(Exception::class);
 $this->expectExceptionMessage('Cannot traverse an already closed generator');
 iterator_to_array($iterator);
 }
 public function testConstructorRewinds() {
 $iterator = new CachingIterator($this->getTraversable([1, 2, 3]));
 $this->assertTrue($iterator->valid());
 $this->assertSame(0, $iterator->key());
 $this->assertSame(1, $iterator->current());
 }
 public function testIteration() {
 $iterator = new CachingIterator($this->getTraversable([1, 2, 3]));
 $expectedKey = 0;
 $expectedItem = 1;
 foreach ($iterator as $key => $item) {
 $this->assertSame($expectedKey++, $key);
 $this->assertSame($expectedItem++, $item);
 }
 $this->assertFalse($iterator->valid());
 }
 public function testIterationWithEmptySet() {
 $iterator = new CachingIterator($this->getTraversable([]));
 $iterator->rewind();
 $this->assertFalse($iterator->valid());
 }
 public function testPartialIterationDoesNotExhaust() {
 $traversable = $this->getTraversable([1, 2, new Exception()]);
 $iterator = new CachingIterator($traversable);
 $expectedKey = 0;
 $expectedItem = 1;
 foreach ($iterator as $key => $item) {
 $this->assertSame($expectedKey++, $key);
 $this->assertSame($expectedItem++, $item);
 if ($key === 1) {
 break;
 }
 }
 $this->assertTrue($iterator->valid());
 }
 public function testRewindAfterPartialIteration() {
 $iterator = new CachingIterator($this->getTraversable([1, 2, 3]));
 $iterator->rewind();
 $this->assertTrue($iterator->valid());
 $this->assertSame(0, $iterator->key());
 $this->assertSame(1, $iterator->current());
 $iterator->next();
 $this->assertSame([1, 2, 3], iterator_to_array($iterator));
 }
 public function testCount() {
 $iterator = new CachingIterator($this->getTraversable([1, 2, 3]));
 $this->assertCount(3, $iterator);
 }
 public function testCountAfterPartialIteration() {
 $iterator = new CachingIterator($this->getTraversable([1, 2, 3]));
 $iterator->rewind();
 $this->assertTrue($iterator->valid());
 $this->assertSame(0, $iterator->key());
 $this->assertSame(1, $iterator->current());
 $iterator->next();
 $this->assertCount(3, $iterator);
 }
 public function testCountWithEmptySet() {
 $iterator = new CachingIterator($this->getTraversable([]));
 $this->assertCount(0, $iterator);
 }
 private function getTraversable($items) {
 foreach ($items as $item) {
 if ($item instanceof Exception) {
 throw $item;
 }
 else {
 yield $item;
 }
 }
 }
 }
 