<?php
require_once 'PHPUnit/Framework.php';
/**
* Test class for MongoCursor.
* Generated by PHPUnit on 2009-04-09 at 18:09:02.
*/
class MongoCursorTest extends PHPUnit_Framework_TestCase
{
/**
* @var MongoCursor
* @access protected
*/
protected $object;
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*
* @access protected
*/
protected function setUp()
{
$m = new Mongo();
$this->object = $m->selectCollection('phpunit', 'c');
$this->object->drop();
// $this->object->start = memory_get_usage(true);
}
protected function tearDown() {
// $this->assertEquals($start, memory_get_usage(true));
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public function test__construct() {
$c = $this->object->find(null);
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public function test__construct1() {
$c = $this->object->find(null, null);
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public function test__construct2() {
$c = $this->object->find(array(), null);
}
/**
* @expectedException PHPUnit_Framework_Error
*/
public function test__construct3() {
$c = new MongoCursor(new Mongo(), "foo.bar", null);
}
/**
* @expectedException MongoException
*/
public function test__construct4() {
$this->object->findOne(array(), array("id", 123));
}
public function testHasNext() {
$c = $this->object->find();
$this->assertFalse($c->hasNext());
$this->object->insert(array('foo' => 'bar'));
$c = $this->object->find();
$this->assertTrue($c->hasNext());
$c->getNext();
$this->assertFalse($c->hasNext());
}
public function testInfo()
{
$filter = array(
'property1' => 'value1',
'property2' => array('$in' => array(1,2)),
);
$cursor = $this->object->find($filter);
$query = $cursor->info();
foreach (array('limit', 'skip', 'query', 'ns') as $property) {
$this->assertTrue(isset($query[$property]));
}
$this->assertEquals($query['ns'], 'phpunit.c');
$this->assertEquals($query['limit'], 0);
$this->assertEquals($query['skip'], 0);
$this->assertEquals($query['query'], $filter);
$this->assertEquals((object)$query['fields'], (object)array());
$this->assertEquals($query['started_iterating'], false);
$cursor->next();
$query = $cursor->info();
$this->assertEquals($query['started_iterating'], true);
}
public function testGetNext() {
$c = $this->object->find();
$this->assertEquals($c->getNext(), null);
for ($i=0; $i<10; $i++) {
$this->object->insert(array('z' => $i));
}
$c = $this->object->find();
for ($i=0; $i<10; $i++) {
$c->getNext();
$this->assertNotNull($c);
}
$this->assertEquals($c->getNext(), null);
}
public function testLimit() {
for ($i=0; $i<20; $i++) {
$this->object->insert(array('z' => $i));
}
$c = $this->object->find()->limit(0);
$count = 0;
foreach ($c as $obj) {
$count++;
}
$this->assertEquals($count, 20);
$c = $this->object->find()->limit(null);
$count = 0;
foreach ($c as $obj) {
$count++;
}
$this->assertEquals($count, 20);
$c = $this->object->find()->limit(5);
$count = 0;
foreach ($c as $obj) {
$count++;
}
$this->assertEquals($count, 5);
$c = $this->object->find()->limit(20);
$count = 0;
foreach ($c as $obj) {
$count++;
}
$this->assertEquals($count, 20);
$c = $this->object->find()->limit(200);
$count = 0;
foreach ($c as $obj) {
$count++;
}
$this->assertEquals($count, 20);
$c = $this->object->find()->limit("12");
$count = 0;
foreach ($c as $obj) {
$count++;
}
$this->assertEquals($count, 12);
}
public function testSkip()
{
for ($i=0; $i<20; $i++) {
$this->object->insert(array('z' => $i));
}
$c = $this->object->find()->sort(array('z'=>1))->skip(4);
$count = 4;
foreach ($c as $obj) {
$this->assertEquals($count, $obj['z']);
$count++;
}
$this->assertEquals($count, 20);
$c = $this->object->find()->sort(array('z'=>1))->skip(0);
$count = 0;
foreach ($c as $obj) {
$this->assertEquals($count, $obj['z']);
$count++;
}
$this->assertEquals($count, 20);
$c = $this->object->find()->sort(array('z'=>1))->skip(null);
$count = 0;
foreach ($c as $obj) {
$this->assertEquals($count, $obj['z']);
$count++;
}
$this->assertEquals($count, 20);
}
public function testSort() {
for ($i=0; $i<20; $i++) {
if ($i % 2 == 0) {
$this->object->insert(array('z' => $i, 'x' => 'a'));
}
else if($i % 3 == 0) {
$this->object->insert(array('z' => $i, 'x' => 'b'));
}
else {
$this->object->insert(array('z' => $i, 'x' => 'c'));
}
}
$c = $this->object->find()->sort(array('z'=>1));
$count = 0;
foreach ($c as $obj) {
$this->assertEquals($count, $obj['z']);
$count++;
}
$this->assertEquals($count, 20);
$c = $this->object->find()->sort(array('x'=>1, 'z'=>-1));
for ($i=18;$i>=0;$i-=2) {
$obj = $c->getNext();
$this->assertEquals($obj['z'], $i);
$this->assertEquals($obj['x'], 'a');
}
$obj = $c->getNext();
$this->assertEquals($obj['z'], 15);
$this->assertEquals($obj['x'], 'b');
$obj = $c->getNext();
$this->assertEquals($obj['z'], 9);
$this->assertEquals($obj['x'], 'b');
$obj = $c->getNext();
$this->assertEquals($obj['z'], 3);
$this->assertEquals($obj['x'], 'b');
for ($i=19;$i>=0;$i-=2) {
if ($i % 3 == 0) {
continue;
}
$obj = $c->getNext();
$this->assertEquals($obj['z'], $i);
$this->assertEquals($obj['x'], 'c');
}
$this->assertFalse($c->hasNext());
}
public function testHint() {
$c = $this->object->find();
$d = $c->hint(array('x'=>1));
$this->assertSame($c, $d);
}
public function testCurrent() {
for ($i=0; $i<20; $i++) {
$this->object->insert(array('z' => $i));
}
$c = $this->object->find()->sort(array('z' => -1));
$this->assertEquals($c->current(), null);
for ($i=19; $i>=0; $i--) {
$c->next();
$obj = $c->current();
$this->assertEquals($obj['z'], $i);
}
$c->next();
$this->assertEquals($c->current(), null);
}
public function testKey() {
if (preg_match("/5\.1\../", phpversion())) {
$this->markTestSkipped("No implicit __toString in 5.1");
return;
}
for ($i=0; $i<20; $i++) {
$this->object->insert(array('z' => $i));
}
$c = $this->object->find();
foreach ($c as $k=>$v) {
$this->assertEquals($k, (string)$v['_id']);
}
$ns = $this->object->db->selectCollection("system.indexes");
$cursor = $ns->find();
foreach ($cursor as $k => $v) {
if (!array_key_exists('_id', $v)) {
$this->assertEquals("", $k, json_encode($v));
}
}
}
public function testNext() {
for ($i=0; $i<20; $i++) {
$this->object->insert(array('z' => $i));
}
$c = $this->object->find()->skip(3)->sort(array('z'=>1))->limit(3);
$c->next();
$c->next();
$c->next();
$x = $c->current();
$this->assertEquals($x['z'], 5);
// don't crash
$c->next();
$this->assertEquals($c->current(), null);
$c->next();
$this->assertEquals($c->current(), null);
$c->next();
$this->assertEquals($c->current(), null);
}
public function testRewind() {
for ($i=0; $i<5; $i++) {
$this->object->insert(array('z' => $i));
}
$c = $this->object->find()->sort(array('z'=>1));
$c->next();
$x = $c->current();
$this->assertEquals($x['z'], 0);
$c->next();
$x = $c->current();
$this->assertEquals($x['z'], 1);
$c->rewind();
$x = $c->current();
$this->assertEquals($x['z'], 0);
}
public function testValid() {
$this->object->insert(array('z' => 0));
$c = $this->object->find();
$this->assertFalse($c->valid());
$c->next();
$this->assertTrue($c->valid());
$c->next();
$this->assertFalse($c->valid());
}
public function testReset() {
for ($i=0; $i<5; $i++) {
$this->object->insert(array('z' => $i));
}
$c = $this->object->find()->sort(array('z'=>1));
$x = $c->current();
$this->assertEquals($x, null);
$c->next();
$x = $c->current();
$this->assertEquals($x['z'], 0);
$c->reset();
// this should be ok
$c->limit(1)->skip(2);
$obj = $c->getNext();
$this->assertEquals($obj['z'], 2);
$this->assertFalse($c->hasNext());
}
/**
* @expectedException MongoCursorException
*/
public function testCursorException1() {
$c = $this->object->find();
$c->hasNext();
$c->limit(4);
}
/**
* @expectedException MongoCursorException
*/
public function testCursorException3() {
$c = $this->object->find();
$c->hasNext();
$c->sort(array('x' => 1));
}
/**
* @expectedException MongoCursorException
*/
public function testCursorException4() {
$c = $this->object->find();
$c->getNext();
$c->skip(4);
}
public function testCount() {
$this->object->insert(array('x'=>1));
$this->object->insert(array('x'=>2));
$this->object->insert(array('x'=>3, 'y'=>1));
$cursor = $this->object->find();
$this->assertEquals(3, $cursor->count());
$cursor = $this->object->find(array('x'=>1));
$count = $cursor->count();
$str = json_encode(iterator_to_array($cursor));
$this->assertEquals(1, $count, $str);
}
public function testExplain() {
$c = $this->object->find();
$x = $c->explain();
$this->assertEquals(0, $x['n'], json_encode($x));
$c->next();
$x = $c->explain();
$this->assertEquals(0, $x['n'], json_encode($x));
}
public function testReset2() {
for ($i=0; $i<20; $i++) {
$this->object->insert(array('x'=>$i, "b$i" => 'foo'));
}
$cursor = $this->object->find();
for ($i=0; $i<20; $i++) {
$this->assertNotNull($cursor->getNext());
}
$cursor->reset();
$cursor->limit(1);
$this->assertNotNull($cursor->getNext());
$this->assertEquals(NULL, $cursor->getNext());
$cursor->reset();
$cursor->limit(0);
for ($i=0; $i<20; $i++) {
$this->assertNotNull($cursor->getNext());
}
}
public function testResetRealloc() {
for ($i=0; $i<20; $i++) {
$this->object->insert(array('x'=>$i, "b$i" => 'foo'));
}
$cursor = $this->object->find()->limit(1);
$this->assertNotNull($cursor->getNext());
$this->assertEquals(NULL, $cursor->getNext());
$cursor->reset();
$cursor->limit(0);
for ($i=0; $i<20; $i++) {
$this->assertNotNull($cursor->getNext());
}
}
/*
* TODO: add actual functionality testing
* BLOCKED BY: buildbot support for master/slave
*/
public function testSlaveOkay() {
$m = new Mongo();
$m->foo->drop();
$c = $m->foo->createCollection("foo", true, 20);
$c->findOne();
$cursor = $c->find()->slaveOkay()->tailable();
$cursor->getNext();
$cursor->reset();
$cursor = $c->find()->slaveOkay(false)->tailable(false);
$cursor->slaveOkay(true)->tailable(true);
$cursor->getNext();
$c->drop();
}
public function testSlaveOkay2() {
$this->assertFalse(MongoCursor::$slaveOkay);
MongoCursor::$slaveOkay = true;
$this->assertTrue(MongoCursor::$slaveOkay);
}
public function testImmortal() {
$this->object->find()->immortal()->next();
$this->object->find()->immortal(true)->next();
$this->object->find()->immortal(false)->next();
}
/*
* Doesn't actually test functionality
*/
public function testSnapshot() {
$this->object->insert(array('foo'=>'bar'));
$cursor = $this->object->find()->snapshot();
$this->assertNotNull($cursor->getNext());
}
/**
* @expectedException MongoCursorException
*/
public function testErr1() {
$this->object->insert(array("num" => 1, "foo" => 1));
var_dump($this->object->find()->hint(array("num" => 1))->explain());
}
/**
* @expectedException MongoCursorException
*/
public function testErr2() {
$this->object->insert(array("num" => 1, "foo" => 1));
var_dump($this->object->find()->hint(array("num" => 1))->next());
}
/**
* @expectedException MongoCursorException
*/
public function testErr3() {
$this->object->insert(array("num" => 1, "foo" => 1));
var_dump($this->object->find()->hint(array("num" => 1))->getNext());
}
public function testDead() {
$this->object->insert(array('x' => 1));
$cursor = $this->object->find();
$this->assertFalse($cursor->dead());
$cursor->next();
$this->assertTrue($cursor->dead());
}
public function testExplainLimit() {
for ($i=0;$i<100;$i++) {
$this->object->save(array("x" => $i));
}
$q = array("x" => array('$gt' => 50));
$soft = $this->object->find($q)->limit(20)->explain();
$hard = $this->object->find($q)->limit(-20)->explain();
$this->assertEquals(20, $soft['n']);
$this->assertEquals(20, $hard['n']);
}
public function testSpecial() {
$this->object->insert(array("name" => "joe", "age" => 14));
$this->object->insert(array("name" => "karen", "age" => 20));
$this->object->insert(array("name" => "bill", "age" => 30));
$query = array('age' => array('$lt' => 15));
$names = $this->object->db->command(array('distinct' => 'c', 'key' => 'name', 'query' => $query));
$this->assertEquals(1, count($names['values']), json_encode($names));
$this->assertEquals("joe", $names['values'][0], json_encode($names));
}
public function testKillConnection() {
$m = new Mongo();
$c = $m->phpunit->kill;
$c->drop();
for($i=0; $i<10; $i++) {
$c->insert(array("x" => $i));
}
$cursor = $c->find();
$cursor->next();
unset($m);
sleep(1);
while($cursor->next()) {}
$m = new Mongo();
$m->phpunit->kill->drop();
}
public function testKillCursors() {
$c = $this->object;
for ($i=0; $i<100; $i++) {
$c->insert(array("x" => $i));
}
$carr = array();
$carr[] = $c->find(array("x" => array('$gt' => 80)));
$carr[] = $c->find(array("x" => array('$lt' => 40)));
$carr[] = $c->find(array("x" => array('$gt' => 40, '$lt' => 80)));
foreach ($carr as $cursor) {
$this->assertFalse($cursor->valid());
$cursor->next();
$this->assertTrue($cursor->valid());
}
}
public function testFatalForEach() {
if (preg_match("/5\.1\../", phpversion())) {
$this->markTestSkipped("who knows what 5.1 does with fatal errors? probably something stupid.");
return;
}
$output = "";
$exit_code = 0;
exec("php tests/fatal3.php", $output, $exit_code);
$uncallable = "Fatal error: Call to a member function foo() on a non-object";
if (count($output) > 0) {
$this->assertEquals($uncallable, substr($output[1], 0, strlen($uncallable)), json_encode($output));
}
}
public function testManualDtor1() {
$mongo = new Mongo();
$cursor = $mongo->phpunit->c->find();
unset($mongo);
$this->assertNull($cursor->getNext());
}
public function testManualDtor2() {
$mongo = new Mongo();
$c = $mongo->phpunit->bar;
$c->insert(array("x"=>1));
$cursor = $c->find();
$cursor->next();
unset($cursor);
$cursor = $c->find();
$this->assertNotNull($cursor->getNext());
}
public function testAddOption() {
$this->object->ensureIndex(array("x" => 1));
for ($i=0; $i<20; $i++) {
$this->object->insert(array("x" => $i));
}
$cursor = $this->object->find()->addOption('$min', array("x" => 15));
$this->assertTrue($cursor instanceof MongoCursor, get_class($cursor));
foreach($cursor as $v) {
$this->assertGreaterThanOrEqual(15, $v['x']);
}
}
public function testGeoBox() {
$this->markTestSkipped("server bug");
return;
$this->object->ensureIndex(array("loc" => "2d"), array("min" => 0, "max" => 10));
for($i=1; $i<10; $i++) {
for ($j=1; $j<10; $j++) {
$this->object->insert(array("loc" => array($i, $j)));
}
}
$cursor = $this->object->find(array("loc" => array('$within' => array('$box' => array(array(4,4), array(6,6))))))->sort(array("loc" => 1));
for ($i=4; $i<7; $i++) {
for ($j=4; $j<7; $j++) {
$val = $cursor->getNext();
$this->assertEquals($i, $val['loc'][0]);
$this->assertEquals($j, $val['loc'][1]);
}
}
}
public function testFields() {
$this->object->insert(array("x" => 1, "y" => 1));
$cursor = $this->object->find()->fields(array("x"=>1));
$x = $cursor->getNext();
$this->assertTrue(array_key_exists('x', $x));
$this->assertTrue(array_key_exists('_id', $x));
$this->assertFalse(array_key_exists('y', $x));
$cursor = $this->object->find(array(), array("y" => 1))->fields(array("x"=>1));
$x = $cursor->getNext();
$this->assertTrue(array_key_exists('x', $x));
$this->assertTrue(array_key_exists('_id', $x));
$this->assertFalse(array_key_exists('y', $x));
$cursor = $this->object->find(array(), array("y" => 1))->fields(array("x"=>1))->fields(array("y"=>1));
$x = $cursor->getNext();
$this->assertTrue(array_key_exists('y', $x));
$this->assertTrue(array_key_exists('_id', $x));
$this->assertFalse(array_key_exists('x', $x));
$fields = array("y" => 1);
$cursor = $this->object->find(array(), $fields)->fields($fields)->fields($fields);
$x = $cursor->getNext();
$this->assertTrue(array_key_exists('y', $x));
$this->assertTrue(array_key_exists('_id', $x));
$this->assertFalse(array_key_exists('x', $x));
}
public function testErrorCode() {
$code = 0;
$this->object->insert(array("_id" => 1), array("safe" => true));
try {
$this->object->insert(array("_id" => 1), array("safe" => true));
}
catch(MongoCursorException $e) {
$code = $e->getCode();
}
$this->assertEquals(11000, $code);
}
public function testBatchSize() {
for ($i = 0; $i<2000; $i++) {
$this->object->insert(array("x" => 1, "y" => $i, "z" => new MongoDate(), "w" => "all the talk on the market"));
}
$cursor = $this->object->find();
// b: 7 l: 20
$batch = 7;
$count = 0;
$cursor->batchSize($batch)->limit(20);
while ($cursor->hasNext()) {
$cursor->getNext();
$info = $cursor->info();
$this->assertEquals($batch, $info['numReturned']);
$count++;
if ($count % 7 == 0) {
if ($batch == 7) {
$batch = 14;
}
else {
$batch=20;
}
}
}
$this->assertEquals(20, $count);
// b: 20 l: 7
$count = 0;
$cursor->reset();
$cursor->batchSize(20)->limit(7);
while ($cursor->hasNext()) {
$cursor->getNext();
$info = $cursor->info();
$this->assertEquals(7, $info['numReturned']);
$count++;
}
$this->assertEquals(7, $count);
// b: 0 l: 20
$count = 0;
$cursor->reset();
$cursor->batchSize(0)->limit(20);
while ($cursor->hasNext()) {
$cursor->getNext();
$info = $cursor->info();
$this->assertEquals(20, $info['numReturned']);
$count++;
}
$this->assertEquals(20, $count);
// b: 20 l: 0
$count = 0;
$cursor->reset();
$cursor->batchSize(20)->limit(0);
while ($cursor->hasNext()) {
$cursor->getNext();
$info = $cursor->info();
$this->assertEquals($batch, $info['numReturned']);
$count++;
if ($count % 20 == 0) {
$batch+=20;
}
}
$this->assertEquals(2000, $count);
}
public function testExplainReset() {
$this->object->insert(array("x"=>"abc"), array('safe' => true));
$cursor = $this->object->find();
$qp = $cursor->explain();
$info = $cursor->info();
$this->assertTrue(!array_key_exists('$explain', $info['query']));
$this->assertTrue(array_key_exists('$query', $info['query']));
$doc = $cursor->getNext();
$this->assertEquals('abc', $doc['x'], json_encode($doc));
}
public function testPartial() {
$cursor = $this->object->find();
$cursor->partial()->partial(true)->partial(false);
$cursor->hasNext();
$cursor->reset();
$cursor->partial(true);
$cursor->hasNext();
}
public function testExceptionHost() {
$host = "";
$this->object->insert(array("_id"=>1), array("safe" => true));
try {
$this->object->insert(array("_id"=>1), array("safe" => true));
}
catch (MongoCursorException $e) {
$host = $e->getHost();
}
$this->assertEquals("localhost:27017", $host);
}
public function resetHelper($c) {
$cursor = $c->find();
for ($i=0; $i<50; $i++) {
$cursor->getNext();
}
// reset cursor that is still alive on db
$cursor->reset();
// requery db for a single batch of results
$cursor->limit(-1);
$cursor->getNext();
return $cursor;
}
public function testResetOnPartialResults() {
$m = new Mongo();
$c = $m->phpunit->c;
// insert more than 1 batch of results
for ($i=0; $i<200; $i++) {
$c->insert(array("x" => $i));
}
$cursor = $this->resetHelper($c);
// clean up cursor and connection
}
}
?>