PageRenderTime 132ms CodeModel.GetById 31ms app.highlight 71ms RepoModel.GetById 19ms app.codeStats 1ms

/tests/Shanty/Mongo/DocumentTest.php

https://github.com/joedevon/Shanty-Mongo
PHP | 1202 lines | 906 code | 186 blank | 110 comment | 3 complexity | 3facb97d1da19ec2e01c3c0a57a377e0 MD5 | raw file
   1<?php
   2require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'TestSetup.php';
   3
   4require_once 'Shanty/Mongo/Collection.php';
   5require_once 'Shanty/Mongo/Document.php';
   6require_once 'Shanty/Mongo/Connection/StackTest.php';
   7require_once 'Shanty/Mongo/Connection/GroupTest.php';
   8 
   9class Shanty_Mongo_DocumentTest extends Shanty_Mongo_TestSetup
  10{
  11	public function setUp()
  12	{
  13		parent::setUp();
  14		
  15		$this->_bob = My_ShantyMongo_User::find('4c04516a1f5f5e21361e3ab0');
  16		$this->_cherry = My_ShantyMongo_User::find('4c04516f1f5f5e21361e3ab1');
  17		$this->_roger = My_ShantyMongo_User::find('4c0451791f5f5e21361e3ab2');
  18		
  19		$this->_articleRegular = My_ShantyMongo_Article::find('4c04516f1f5f5e21361e3ac1');
  20		$this->_articleBroken = My_ShantyMongo_Article::find('4c04516f1f5f5e21361e3ac2');
  21	}
  22
  23    public function testHasReference()
  24    {
  25        $this->assertFalse($this->_roger->hasReference('bestFriend'));
  26        $this->assertTrue($this->_bob->hasReference('bestFriend'));
  27    }
  28
  29	public function testConstruct()
  30	{
  31		$student = new My_ShantyMongo_Student();
  32		$this->assertTrue($student->isNewDocument());
  33		$this->assertTrue($student->isRootDocument());
  34		$this->assertTrue($student->isConnected());
  35		$this->assertTrue($student->hasKey());
  36		$this->assertTrue($student->hasId());
  37		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $student->getId());
  38		$this->assertEquals('MongoId', get_class($student->getId()));
  39		$this->assertEquals(My_ShantyMongo_Student::getCollectionRequirements(), $student->getRequirements());
  40		
  41		$type = array(
  42			'My_ShantyMongo_Student',
  43			'My_ShantyMongo_User'
  44		);
  45		
  46		$this->assertEquals($type, $student->getInheritance());
  47		
  48		$criteria = $student->getCriteria();
  49		$this->assertTrue(array_key_exists('_id', $criteria));
  50		$this->assertEquals($student->getId()->__toString(), $criteria['_id']->__toString());
  51		
  52		$name = new My_ShantyMongo_Name();
  53		$this->assertTrue($name->isNewDocument());
  54		$this->assertTrue($name->isRootDocument());
  55		$this->assertFalse($name->isConnected());
  56		$this->assertFalse($name->hasKey());
  57		$this->assertFalse($name->hasId());
  58		$this->assertEquals(array(), $name->getInheritance());
  59		
  60		$config = array(
  61			'new' => false,
  62			'connectionGroup' => 'default',
  63			'db' => TESTS_SHANTY_MONGO_DB,
  64			'collection' => 'user',
  65			'pathToDocument' => 'name',
  66			'requirementModifiers' => array(
  67				'middle' => array('Required' => null)
  68			)
  69		);
  70		
  71		$name = new My_ShantyMongo_Name(array('first'=>'Jerry'), $config);
  72		$this->assertFalse($name->isNewDocument());
  73		$this->assertFalse($name->isRootDocument());
  74		$this->assertTrue($name->isConnected());
  75		$this->assertEquals($name->first, 'Jerry');
  76
  77		$requirements = array(
  78			'_id' => array('Validator:MongoId' => null),
  79			'_type' => array('Array' => null),
  80			'first' => array('Required' => null),
  81			'last' => array('Required' => null),
  82			'middle' => array('Required' => null),
  83		);
  84		$this->assertEquals($requirements, $name->getRequirements());
  85
  86		// Test input data initialisation
  87		$data = array(
  88			'name' => array('first'=>'Jerry', 'last' => 'Springer'),
  89			'addresses' => array(
  90				array(
  91					'street' => '35 Sheep Lane',
  92					'suburb' => 'Sheep Heaven',
  93					'state' => 'New Zealand',
  94					'postcode' => '2345',
  95					'country' => 'New Zealand',
  96				)
  97			),
  98			'friends' => array(
  99				MongoDBRef::create('user', new MongoId('4c04516f1f5f5e21361e3ab1')),
 100				MongoDBRef::create('user', new MongoId('4c0451791f5f5e21361e3ab2')),
 101			),
 102		);
 103
 104		$student = new My_ShantyMongo_Student($data);
 105		$this->assertNotNull($student->name);
 106		$this->assertEquals('My_ShantyMongo_Name', get_class($student->name));
 107		$this->assertEquals('Sheep Heaven', $student->addresses[0]->suburb);
 108		$this->assertEquals('My_ShantyMongo_ArtStudent', get_class($student->friends[1]));
 109
 110	}
 111	
 112	public function testGetHasId()
 113	{
 114		$this->assertTrue($this->_bob->hasId());
 115		
 116		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $this->_bob->getId());
 117		$this->assertEquals('MongoId', get_class($this->_bob->getId()));
 118	}
 119	
 120	public function testGetInheritance()
 121	{
 122		$type = array(
 123			'My_ShantyMongo_Teacher',
 124			'My_ShantyMongo_User'
 125		);
 126		
 127		$this->assertEquals($type, $this->_bob->getInheritance());
 128	}
 129	
 130	public function testGetSetHasConfigAttribute()
 131	{
 132		$this->assertFalse($this->_bob->hasConfigAttribute('magic'));
 133		$this->assertNull($this->_bob->getConfigAttribute('magic'));
 134		
 135		$this->_bob->setConfigAttribute('magic', 'somevalue');
 136		
 137		$this->assertTrue($this->_bob->hasConfigAttribute('magic'));
 138		$this->assertEquals('somevalue', $this->_bob->getConfigAttribute('magic'));
 139	}
 140
 141	public function testGetPathToDocument()
 142	{
 143		$this->assertNull($this->_bob->getPathToDocument());
 144		$this->_bob->setPathToDocument('stange path');
 145		$this->assertEquals('stange path', $this->_bob->getPathToDocument());
 146	}
 147	
 148	public function testGetPathToProperty()
 149	{
 150		$this->assertEquals('name', $this->_bob->getPathToProperty('name'));
 151		$this->assertEquals('name.first', $this->_bob->name->getPathToProperty('first'));
 152	}
 153	
 154	public function testIsRootDocument()
 155	{
 156		$this->assertTrue($this->_bob->isRootDocument());
 157		$this->assertFalse($this->_bob->name->isRootDocument());
 158	}
 159	
 160	public function hasKey()
 161	{
 162		$this->assertTrue($this->_bob->hasKey());
 163		$this->assertFalse($this->_bob->name->hasKey());
 164	}
 165	
 166	public function testIsParentDocumentSet()
 167	{
 168		$this->assertFalse($this->_bob->isParentDocumentSet());
 169		
 170		// Butcher an instance so it thinks it's parent is a document set
 171		$sarah = new My_ShantyMongo_User(null, array('parentIsDocumentSet' => true));
 172		$this->assertTrue($sarah->isParentDocumentSet());
 173	}
 174	
 175	public function testGetSetHasCriteria()
 176	{
 177		$this->assertEquals(array('_id' => new MongoId('4c04516a1f5f5e21361e3ab0')), $this->_bob->getCriteria());
 178		$this->assertFalse($this->_bob->hasCriteria('username'));
 179		$this->_bob->setCriteria('username', 'bobjones');
 180		$this->assertTrue($this->_bob->hasCriteria('username'));
 181		$this->assertEquals('bobjones', $this->_bob->getCriteria('username'));
 182		$this->assertEquals(array('_id' => new MongoId('4c04516a1f5f5e21361e3ab0'), 'username' => 'bobjones'), $this->_bob->getCriteria());
 183	}
 184	
 185	public function test_GetMongoDb()
 186	{
 187		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $this->_bob->_getMongoDb());
 188		$this->assertEquals(TESTS_SHANTY_MONGO_DB, $this->_bob->_getMongoDb()->__toString());
 189		
 190		$connection = new Shanty_Mongo_Connection('localhost');
 191		Shanty_Mongo::addSlave($connection);
 192		
 193		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $this->_bob->_getMongoDb(false));
 194		$this->assertEquals(TESTS_SHANTY_MONGO_DB, $this->_bob->_getMongoDb(false)->__toString());
 195	}
 196
 197	/**
 198     * @expectedException Shanty_Mongo_Exception
 199     */
 200	public function test_GetMongoDbException()
 201	{
 202		$name = new My_ShantyMongo_Name();
 203		$name->_getMongoDb();
 204	}
 205	
 206	public function test_GetMongoCollection()
 207	{
 208		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $this->_bob->_getMongoCollection());
 209		$this->assertEquals(TESTS_SHANTY_MONGO_DB.'.user', $this->_bob->_getMongoCollection()->__toString());
 210	}
 211
 212	/**
 213     * @expectedException Shanty_Mongo_Exception
 214     */
 215	public function testGetMongoCollectionException()
 216	{
 217		$name = new My_ShantyMongo_Name();
 218		$name->_getMongoCollection();
 219	}
 220	
 221	public function testGetRequirements()
 222	{
 223		$requirements = array(
 224			'_id' => array('Validator:MongoId' => null),
 225			'_type' => array('Array' => null),
 226			'name' => array('Document:My_ShantyMongo_Name' => null, 'Required' => null),
 227			'email' => array('Required' => null, 'Validator:EmailAddress' => null),
 228			'addresses' => array('DocumentSet' => null),
 229			'addresses.$.street' => array('Required' => null),
 230			'addresses.$.state' => array('Required' => null),
 231			'addresses.$.suburb' => array('Required' => null),
 232			'addresses.$.postcode' => array('Required' => null),
 233			'friends' => array('DocumentSet:My_ShantyMongo_Users' => null),
 234			'friends.$' => array('Document:My_ShantyMongo_User' => null, 'AsReference' => null),
 235			'sex' => array('Required' => null, 'Validator:InArray' => array('F', 'M')),
 236			'partner' => array('Document:My_ShantyMongo_User' => null, 'AsReference' => null),
 237			'faculty' => array('Required' => null)
 238		);
 239		
 240		$this->assertEquals($requirements, $this->_bob->getRequirements());
 241		
 242		$requirements2 = $requirements = array(
 243			'$.street' => array('Required' => null),
 244			'$.state' => array('Required' => null),
 245			'$.suburb' => array('Required' => null),
 246			'$.postcode' => array('Required' => null),
 247		);
 248		
 249		$this->assertEquals($requirements2, $this->_bob->getRequirements('addresses.'));
 250	}
 251	
 252	public function testHasRequirement()
 253	{
 254		$this->assertTrue($this->_bob->hasRequirement('name', 'Required'));
 255		$this->assertEquals('My_ShantyMongo_Name', $this->_bob->hasRequirement('name', 'Document'));
 256		$this->assertEquals('My_ShantyMongo_Users', $this->_bob->hasRequirement('friends', 'DocumentSet'));
 257		$this->assertEquals('Shanty_Mongo_DocumentSet', $this->_bob->hasRequirement('addresses', 'DocumentSet'));
 258		
 259		$this->assertFalse($this->_bob->hasRequirement('age', 'Required'));
 260		$this->assertFalse($this->_bob->hasRequirement('name', 'Validator:EmailAddress'));
 261		$this->assertFalse($this->_bob->hasRequirement('sex', 'Document'));
 262	}
 263	
 264	/**
 265     * @expectedException Shanty_Mongo_Exception
 266     */
 267	public function testHasRequirementNoClassException()
 268	{
 269		$this->_bob->addRequirement('preferences', 'Document:My_ShantyMongo_Preferences');
 270		$this->_bob->hasRequirement('preferences', 'Document');
 271	}
 272	
 273	/**
 274     * @expectedException Shanty_Mongo_Exception
 275     */
 276	public function testHasRequirementInvalidDocumentException()
 277	{
 278		$this->_bob->addRequirement('preferences', 'Document:My_ShantyMongo_InvalidDocument');
 279		$this->_bob->hasRequirement('preferences', 'Document');
 280	}
 281	
 282	/**
 283	 * @depends testGetRequirements
 284	 */
 285	public function testApplyRequirementsDirty()
 286	{
 287		$totalRequirements = array(
 288			'_id' => array('Validator:MongoId' => null),
 289			'_type' => array('Array' => null),
 290			'name' => array('Document:My_ShantyMongo_Name' => null, 'Required' => null),
 291			'email' => array('Required' => null, 'Validator:EmailAddress' => null),
 292			'addresses' => array('DocumentSet' => null),
 293			'addresses.$.street' => array('Required' => null),
 294			'addresses.$.state' => array('Required' => null),
 295			'addresses.$.suburb' => array('Required' => null),
 296			'addresses.$.postcode' => array('Required' => null),
 297			'friends' => array('DocumentSet:My_ShantyMongo_Users' => null),
 298			'friends.$' => array('Document:My_ShantyMongo_User' => null, 'AsReference' => null),
 299			'sex' => array('Required' => null, 'Validator:InArray' => array('F', 'M')),
 300			'partner' => array('Document:My_ShantyMongo_User' => null, 'AsReference' => null),
 301			'faculty' => array('Required' => null),
 302			'birthday' => array('Required' => null),
 303			'mobile' => array('Required' => null, 'Validator:Digits' => null)
 304		);
 305		
 306		$this->_bob->applyRequirements(array(
 307			'birthday' => 'Required',
 308			'mobile' => array('Required', 'Validator:Digits')
 309		));
 310		
 311		$this->assertEquals($totalRequirements, $this->_bob->getRequirements());
 312	}
 313	
 314	/**
 315	 * @depends testGetRequirements
 316	 */
 317	public function testApplyRequirementsClean()
 318	{
 319		$totalRequirements = array(
 320			'_id' => array('Validator:MongoId' => null),
 321			'_type' => array('Array' => null),
 322			'name' => array('Document:My_ShantyMongo_Name' => null, 'Required' => null),
 323			'email' => array('Required' => null, 'Validator:EmailAddress' => null),
 324			'addresses' => array('DocumentSet' => null),
 325			'addresses.$.street' => array('Required' => null),
 326			'addresses.$.state' => array('Required' => null),
 327			'addresses.$.suburb' => array('Required' => null),
 328			'addresses.$.postcode' => array('Required' => null),
 329			'friends' => array('DocumentSet:My_ShantyMongo_Users' => null),
 330			'friends.$' => array('Document:My_ShantyMongo_User' => null, 'AsReference' => null),
 331			'sex' => array('Required' => null, 'Validator:InArray' => array('F', 'M')),
 332			'partner' => array('Document:My_ShantyMongo_User' => null, 'AsReference' => null),
 333			'faculty' => array('Required' => null),
 334			'birthday' => array('Required' => null),
 335			'mobile' => array('Required' => null, 'Validator:Digits' => null)
 336		);
 337		
 338		$this->_bob->applyRequirements(array(
 339			'birthday' => array('Required' => null),
 340			'mobile' => array('Required' => null, 'Validator:Digits' => null)
 341		), false);
 342		
 343		$this->assertEquals($totalRequirements, $this->_bob->getRequirements());
 344	}
 345	
 346	/**
 347	 * @depends testHasRequirement
 348	 */
 349	public function testAddRequirement()
 350	{
 351		$this->assertFalse($this->_bob->hasRequirement('mobile', 'Validator:Digits'));
 352		$this->_bob->addRequirement('mobile', 'Validator:Digits');
 353		$this->assertTrue($this->_bob->hasRequirement('mobile', 'Validator:Digits'));
 354	}
 355	
 356	/**
 357	 * @depends testHasRequirement
 358	 */
 359	public function testRemoveRequirement()
 360	{
 361		$this->assertTrue($this->_bob->hasRequirement('name', 'Required'));
 362		$this->_bob->removeRequirement('name', 'Required');
 363		$this->assertFalse($this->_bob->hasRequirement('name', 'Required'));
 364	}
 365	
 366	public function testGetPropertiesWithRequirement()
 367	{
 368		$reqiredProperties = array(
 369			'name', 
 370			'email', 
 371			'sex',
 372			'faculty'
 373		);
 374		
 375		$this->assertEquals($reqiredProperties, $this->_bob->getPropertiesWithRequirement('Required'));
 376	}
 377	
 378	public function testGetValidators()
 379	{
 380		$validatorChain = $this->_bob->getValidators('email');
 381		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $validatorChain);
 382		$this->assertEquals('Zend_Validate', get_class($validatorChain));
 383		$this->assertTrue($validatorChain->isValid('email@domain.com'));
 384		$this->assertFalse($validatorChain->isValid('email#domain.com'));
 385	}
 386	
 387	public function testGetFilters()
 388	{
 389		$this->_bob->addRequirement('username', 'Filter:StringToUpper');
 390		
 391		$filterChain = $this->_bob->getFilters('username');
 392		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $filterChain);
 393		$this->assertEquals('Zend_Filter', get_class($filterChain));
 394		$this->assertEquals('BOBJONES', $filterChain->filter('bobjones'));
 395	}
 396	
 397	public function testIsValid()
 398	{
 399		$this->assertTrue($this->_bob->isValid('email', 'email@domain.com'));
 400		$this->assertFalse($this->_bob->isValid('email', 'email#domain.com'));
 401	}
 402	
 403	public function testGetProperty()
 404	{
 405		// $bob->email
 406		$this->assertEquals('bob.jones@domain.com', $this->_bob->getProperty('email'));
 407		
 408		// $bob->name->first
 409		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $this->_bob->getProperty('name'));
 410		$this->assertEquals('My_ShantyMongo_Name', get_class($this->_bob->getProperty('name')));
 411		$this->assertEquals('Bob', $this->_bob->getProperty('name')->getProperty('first'));
 412		$this->assertTrue($this->_bob->getProperty('name')->isConnected());
 413		$this->assertEquals('default', $this->_bob->getProperty('name')->getConfigAttribute('connectionGroup'));
 414		$this->assertEquals(TESTS_SHANTY_MONGO_DB, $this->_bob->getProperty('name')->getConfigAttribute('db'));
 415		$this->assertEquals('user', $this->_bob->getProperty('name')->getConfigAttribute('collection'));
 416		$this->assertEquals('name', $this->_bob->getProperty('name')->getPathToDocument());
 417		$this->assertFalse($this->_bob->getProperty('name')->getConfigAttribute('hasId'));
 418		$this->assertFalse($this->_bob->getProperty('name')->isNewDocument());
 419		
 420		// $bob->partner->name->first
 421		$cherry = $this->_bob->getProperty('partner');
 422		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $cherry);
 423		$this->assertEquals('My_ShantyMongo_User', get_class($cherry));
 424		$this->assertEquals('Cherry', $cherry->getProperty('name')->getProperty('first'));
 425		$this->assertTrue($cherry->isRootDocument());
 426		$this->assertEquals('default', $cherry->getProperty('name')->getConfigAttribute('connectionGroup'));
 427		$this->assertEquals(TESTS_SHANTY_MONGO_DB, $cherry->getProperty('name')->getConfigAttribute('db'));
 428		$this->assertEquals('user', $cherry->getProperty('name')->getConfigAttribute('collection'));
 429		
 430		// $bob->addresses[1]->street
 431		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $this->_bob->getProperty('addresses'));
 432		$this->assertEquals('Shanty_Mongo_DocumentSet', get_class($this->_bob->getProperty('addresses')));
 433		$this->assertEquals('addresses', $this->_bob->getProperty('addresses')->getPathToDocument());
 434		$this->assertEquals(2, count($this->_bob->getProperty('addresses')));
 435		$this->assertEquals('742 Evergreen Terrace', $this->_bob->getProperty('addresses')->getProperty(1)->getProperty('street'));
 436		$this->assertEquals('default', $this->_bob->getProperty('addresses')->getConfigAttribute('connectionGroup'));
 437		$this->assertEquals(TESTS_SHANTY_MONGO_DB, $this->_bob->getProperty('addresses')->getConfigAttribute('db'));
 438		$this->assertEquals('user', $this->_bob->getProperty('addresses')->getConfigAttribute('collection'));
 439		
 440		// Test get on new documents
 441		$sarah = new My_ShantyMongo_User();
 442		
 443		// $sarah->email
 444		$this->assertNull($sarah->getProperty('email'));
 445		
 446		// $sarah->name
 447		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $sarah->getProperty('name'));
 448		$this->assertEquals('My_ShantyMongo_Name', get_class($sarah->getProperty('name')));
 449		
 450		// $sarah->addresses
 451		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $sarah->getProperty('addresses'));
 452		$this->assertEquals('Shanty_Mongo_DocumentSet', get_class($sarah->getProperty('addresses')));
 453		$this->assertEquals(0, count($sarah->getProperty('addresses')));
 454		
 455		// Test Array's
 456		$this->assertTrue(is_array($this->_articleRegular->tags));
 457		$this->assertEquals(array('awesome', 'howto', 'mongodb'), $this->_articleRegular->tags);
 458		
 459		// Test broken references
 460		$this->assertNull($this->_articleBroken->author);
 461		
 462	}
 463	
 464	/**
 465	 * @depends testGetProperty
 466	 */
 467	public function testSetProperty()
 468	{
 469		$this->_bob->email = null;
 470		$this->assertNull($this->_bob->email);
 471		
 472		$objStorage = new SplObjectStorage();
 473		$objStorage->attach($this->_cherry);
 474		
 475		$this->_articleRegular->stakeholder = $this->_cherry;
 476		$this->assertFalse($objStorage->contains($this->_articleRegular->stakeholder));
 477		$this->assertFalse($this->_articleRegular->stakeholder->isNewDocument());
 478		$this->assertEquals($this->_users['cherry'], $this->_articleRegular->stakeholder->export());
 479		$this->assertEquals('default', $this->_articleRegular->stakeholder->getConfigAttribute('connectionGroup'));
 480		$this->assertEquals(TESTS_SHANTY_MONGO_DB, $this->_articleRegular->stakeholder->getConfigAttribute('db'));
 481		$this->assertEquals('article', $this->_articleRegular->stakeholder->getConfigAttribute('collection'));
 482		$this->assertEquals('stakeholder', $this->_articleRegular->stakeholder->getPathToDocument());
 483		
 484		$article = new My_ShantyMongo_Article();
 485		$article->title = 'Mongodb Awesomeness';
 486		
 487		$objStorage = new SplObjectStorage();
 488		$objStorage->attach($article);
 489		
 490		$this->_roger->favouriteArticle = $article;
 491		$this->assertTrue($objStorage->contains($this->_roger->favouriteArticle));
 492		$this->assertTrue($this->_roger->favouriteArticle->isNewDocument());
 493		$this->assertEquals($article->export(), $this->_roger->favouriteArticle->export());
 494		$this->assertEquals('default', $this->_roger->favouriteArticle->getConfigAttribute('connectionGroup'));
 495		$this->assertEquals(TESTS_SHANTY_MONGO_DB, $this->_roger->favouriteArticle->getConfigAttribute('db'));
 496		$this->assertEquals('user', $this->_roger->favouriteArticle->getConfigAttribute('collection'));
 497		$this->assertEquals('favouriteArticle', $this->_roger->favouriteArticle->getPathToDocument());
 498		
 499		$this->_bob->addRequirement('config', 'Document');
 500		$this->_bob->addRequirement('config.date', 'Required');
 501		
 502		$this->_bob->config = new Shanty_Mongo_Document();
 503		
 504		$requirements = array(
 505			'_id' => array('Validator:MongoId' => null),
 506			'_type' => array('Array' => null),
 507			'date' => array('Required' => null)
 508		);
 509		
 510		$this->assertEquals($requirements, $this->_bob->config->getRequirements());
 511		
 512	}
 513	
 514	/**
 515     * @expectedException Shanty_Mongo_Exception
 516     */
 517	public function testSetPropertyPrivateProperty()
 518	{
 519		$this->_bob->_private = 'invalid email';
 520	}
 521	
 522	/**
 523     * @expectedException Shanty_Mongo_Exception
 524     */
 525	public function testSetPropertyInvalidValueException()
 526	{
 527		$this->_bob->email = 'invalid email';
 528	}
 529	
 530	public function testHasProperty()
 531	{
 532		$this->assertTrue($this->_bob->hasProperty('email'));
 533		$this->assertFalse($this->_bob->hasProperty('birthday'));
 534		$this->_bob->email = null;
 535		$this->assertFalse($this->_bob->hasProperty('email'));
 536		$this->_bob->email = 'email@domain.com';
 537		$this->assertTrue($this->_bob->hasProperty('email'));
 538	}
 539	
 540	public function testGetPropertyKeys()
 541	{
 542		$properties = array(
 543			'_id',
 544			'_type',
 545			'name',
 546			'addresses',
 547			'friends',
 548			'faculty',
 549			'email',
 550			'sex',
 551			'partner',
 552			'bestFriend'
 553		);
 554		
 555		$this->assertEquals($properties, $this->_bob->getPropertyKeys());
 556		
 557		$properties = array(
 558			'_id',
 559			'birthday',
 560			'preferences',
 561			'_type',
 562			'name',
 563			'addresses',
 564			'friends',
 565			'faculty',
 566			'sex',
 567			'partner',
 568			'bestFriend'
 569		);
 570		
 571		$this->_bob->email = null;
 572		$this->_bob->birthday = 'November';
 573		$this->_bob->preferences = new Shanty_Mongo_Document();
 574		$this->_bob->preferences->color = 'Blue';
 575		$this->_bob->crimes = new Shanty_Mongo_Document();
 576		
 577		$this->assertEquals($properties, $this->_bob->getPropertyKeys());
 578	}
 579	
 580	public function testCreateReference()
 581	{
 582		$reference = $this->_bob->createReference();
 583		$this->assertTrue(MongoDBRef::isRef($reference));
 584		$this->assertEquals('user', $reference['$ref']);;
 585		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $reference['$id']);
 586		$this->assertEquals('MongoId', get_class($reference['$id']));
 587		$this->assertEquals('4c04516a1f5f5e21361e3ab0', $reference['$id']->__toString());
 588	}
 589	
 590	/**
 591     * @expectedException Shanty_Mongo_Exception
 592     */
 593	public function testCreateReferenceNotRootDocumentException()
 594	{
 595		$this->_bob->name->createReference();
 596	}
 597	
 598	/**
 599     * @expectedException Shanty_Mongo_Exception
 600     */
 601	public function testCreateReferenceNoCollectionException()
 602	{
 603		$name = new My_ShantyMongo_Name();
 604		$name->createReference();
 605	}
 606	
 607	
 608	public function testIsReference()
 609	{
 610		$roger = $this->_bob->bestFriend;
 611		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $roger);
 612		$this->assertEquals('Shanty_Mongo_Document', get_class($roger));
 613		
 614		$this->assertTrue($this->_bob->isReference($roger));
 615	}
 616
 617	public function testExport()
 618	{
 619		$this->assertEquals($this->_users['bob'], $this->_bob->export());
 620		
 621		$this->_bob->name->first = 'Bobby';
 622		$this->_bob->addresses = null;
 623		$this->_bob->favouriteColour = 'Blue';
 624		$this->_bob->config = new Shanty_Mongo_Document(); // Empty documents don't get saved
 625
 626		// Load references into memory to make sure they are exported correctly as references
 627		$this->_bob->partner;
 628		$this->_bob->bestFriend;
 629
 630		$bobRaw = $this->_users['bob'];
 631		$bobRaw['name']['first'] = 'Bobby';
 632		unset($bobRaw['addresses']);
 633		$bobRaw['favouriteColour'] = 'Blue';
 634
 635		$this->assertEquals($bobRaw, $this->_bob->export());
 636	}
 637	
 638	/**
 639     * @expectedException Shanty_Mongo_Exception
 640     */
 641	public function testExportRequiredException()
 642	{
 643		$this->_bob->email = null;
 644		$this->_bob->export();
 645	}
 646	
 647	public function testIsNewDocument()
 648	{
 649		$this->assertFalse($this->_bob->isNewDocument());
 650		$this->assertFalse($this->_bob->name->isNewDocument());
 651		
 652		$sarah = new My_ShantyMongo_User();
 653		$this->assertTrue($sarah->isNewDocument());
 654		$this->assertTrue($sarah->name->isNewDocument());
 655	}
 656	
 657	public function testIsEmpty()
 658	{
 659		$this->assertFalse($this->_bob->isEmpty());
 660		$this->assertFalse($this->_bob->name->isEmpty());
 661		$this->_bob->name->first = null;
 662		$this->_bob->name->last = null;
 663		$this->assertTrue($this->_bob->name->isEmpty());
 664		$this->_bob->name->first = 'Bob';
 665		$this->assertFalse($this->_bob->name->isEmpty());
 666		$this->assertFalse($this->_bob->addresses->isEmpty());
 667		$this->_bob->addresses[0]->street = null;
 668		$this->_bob->addresses[0]->suburb = null;
 669		$this->_bob->addresses[0]->state = null;
 670		$this->_bob->addresses[0]->postcode = null;
 671		$this->_bob->addresses[0]->country = null;
 672		$this->_bob->addresses[1] = null;
 673		$this->assertTrue($this->_bob->addresses->isEmpty());
 674		
 675		$user = new My_ShantyMongo_User();
 676		$this->assertFalse($user->isEmpty());
 677		$user->name->first = 'Madeline';
 678		$this->assertFalse($user->name->isEmpty());
 679		$this->assertFalse($user->isEmpty());
 680		$user->name->first = null;
 681		$this->assertTrue($user->name->isEmpty());
 682		
 683	}
 684	
 685	public function testSaveBasic()
 686	{
 687		$this->_bob->name->first = 'Bobby';
 688		$this->_bob->addresses = null;
 689		$this->_bob->save();
 690
 691		$bobRaw = $this->_users['bob'];
 692		$bobRaw['name']['first'] = 'Bobby';
 693		unset($bobRaw['addresses']);
 694
 695		$this->assertEquals($bobRaw, $this->_userCollection->findOne(array('_id' => new MongoId('4c04516a1f5f5e21361e3ab0'))));
 696	}
 697	
 698	public function testSaveWholeDocument()
 699	{
 700		$this->_bob->name->last = 'Johnes';
 701		$this->_bob->addresses = null;
 702		$this->_bob->save(true);
 703
 704		$bobRaw = $this->_users['bob'];
 705		$bobRaw['name']['last'] = 'Johnes';
 706		unset($bobRaw['addresses']);
 707
 708		$this->assertEquals($bobRaw, $this->_userCollection->findOne(array('_id' => new MongoId('4c04516a1f5f5e21361e3ab0'))));
 709	}
 710	
 711	public function testSaveUnchangedDocument()
 712	{
 713		$this->_bob->save();
 714		$this->assertEquals($this->_users['bob'], $this->_userCollection->findOne(array('_id' => new MongoId('4c04516a1f5f5e21361e3ab0'))));
 715	}
 716	
 717	/**
 718	 * Test newly added documents to a document set
 719	 */
 720	public function testSaveChildOfDocumentSet()
 721	{
 722		$address = $this->_bob->addresses->new();
 723		$address->street = '35 Sheep Lane';
 724		$address->suburb = 'Sheep Heaven';
 725		$address->state = 'New Zealand';
 726		$address->postcode = '2345';
 727		$address->country = 'New Zealand';
 728		$address->save();
 729
 730		$bobRaw = $this->_users['bob'];
 731		$addressRaw = array(
 732			'street' => '35 Sheep Lane',
 733			'suburb' => 'Sheep Heaven',
 734			'state' => 'New Zealand',
 735			'postcode' => '2345',
 736			'country' => 'New Zealand',
 737		);
 738		$bobRaw['addresses'][] = $addressRaw;
 739		
 740		$this->assertEquals($bobRaw, $this->_userCollection->findOne(array('_id' => new MongoId('4c04516a1f5f5e21361e3ab0'))));
 741	}
 742	
 743	/**
 744	 * @expectedException Shanty_Mongo_Exception
 745	 */
 746	public function testSaveChildOfDocumentSetSaveException()
 747	{
 748		$address = $this->_bob->addresses->new();
 749		$address->street = '35 Sheep Lane';
 750		$address->suburb = 'Sheep Heaven';
 751		$address->state = 'New Zealand';
 752		$address->postcode = '2345';
 753		$address->country = 'New Zealand';
 754		$address->save();
 755		$address->save(); // Should throw an exception because this document will be locked
 756	}
 757	
 758	/**
 759	 * @expectedException Shanty_Mongo_Exception
 760	 */
 761	public function testSaveChildOfDocumentSetDeleteException()
 762	{
 763		$address = $this->_bob->addresses->new();
 764		$address->street = '35 Sheep Lane';
 765		$address->suburb = 'Sheep Heaven';
 766		$address->state = 'New Zealand';
 767		$address->postcode = '2345';
 768		$address->country = 'New Zealand';
 769		$address->save();
 770		$address->delete(); // Should throw an exception because this document will be locked
 771	}
 772	
 773	public function testSaveNewDocument()
 774	{
 775		$user = new My_ShantyMongo_User();
 776		$user->email = 'email@domain.com';
 777		$user->sex = 'F';
 778		$user->name->first = 'Madeline';
 779		$user->name->last = 'Veenstra';
 780		$user->save();
 781		
 782		$userId = $user->getId();
 783		$userRaw = array(
 784			'_id' => new MongoId($userId->__toString()),
 785			'_type' => array(
 786				'My_ShantyMongo_User'
 787			),
 788			'name' => array(
 789				'first' => 'Madeline',
 790				'last' => 'Veenstra',
 791			),
 792			'email' => 'email@domain.com',
 793			'sex' => 'F'
 794		);
 795		
 796		$this->assertEquals($userRaw, $this->_userCollection->findOne(array('_id' => new MongoId($userId->__toString()))));
 797	}
 798
 799	public function testSaveSafe() {
 800		$reader = new Mongo('mongodb://' . TESTS_SHANTY_MONGO_CONNECTIONSTRING);
 801		$readerDB = $reader->{TESTS_SHANTY_MONGO_DB};
 802
 803		for($nr = 0; $nr < 1000; $nr++) {
 804			$entry = new My_ShantyMongo_Simple(array('data' => '123'));
 805			$entry->save();
 806			$found = $readerDB->simple->findOne(array('_id' => $entry->getId()));
 807			$this->assertTrue(is_array($found));
 808			$this->assertEquals($entry->export(), $found);
 809		}
 810	}
 811	
 812	/**
 813     * @expectedException Shanty_Mongo_Exception
 814     */
 815	public function testSaveNotConnectedException()
 816	{
 817		$name = new My_ShantyMongo_Name();
 818		$name->save();
 819	}
 820	
 821	public function testDelete()
 822	{
 823		// Delete subdocument
 824		$this->_roger->name->delete();
 825		
 826		$roger = $this->_userCollection->findOne(array('_id' => new MongoId('4c0451791f5f5e21361e3ab2')));
 827		
 828		$rogerData = array(
 829			'_id' => new MongoId('4c0451791f5f5e21361e3ab2'),
 830			'_type' => array(
 831				'My_ShantyMongo_ArtStudent',
 832				'My_ShantyMongo_Student',
 833				'My_ShantyMongo_User'
 834			),
 835			'concession' => false,
 836			'email' => 'roger.smith@domain.com',
 837			'sex' => 'M'
 838		);
 839		
 840		$this->assertEquals($rogerData, $roger);
 841		
 842		$this->_roger->delete();
 843		$this->assertNull($this->_userCollection->findOne(array('_id' => new MongoId('4c0451791f5f5e21361e3ab2'))));
 844	}
 845	
 846	/**
 847	 * Make sure an exception is thrown if document does not belong to a collection
 848	 * 
 849     * @expectedException Shanty_Mongo_Exception
 850     */
 851	public function testDeleteException()
 852	{
 853		$name = new My_ShantyMongo_Name();
 854		$name->delete();
 855	}
 856
 857	public function testDeleteSafe() {
 858		$reader = new Mongo('mongodb://' . TESTS_SHANTY_MONGO_CONNECTIONSTRING);
 859		$readerDB = $reader->{TESTS_SHANTY_MONGO_DB};
 860
 861		for($nr = 0; $nr < 1000; $nr++) {
 862			$entry = new My_ShantyMongo_Simple(array('data' => '123'));
 863			$entry->save();
 864			$entry->delete();
 865			$found = $readerDB->simple->findOne(array('_id' => $entry->getId()));
 866			if (!is_null($found)) {
 867				print($nr);
 868				die();
 869			}
 870			$this->assertNull($found);
 871		}
 872	}
 873
 874	public function testMagicGetAndSet()
 875	{
 876		$this->assertEquals('bob.jones@domain.com', $this->_bob->email);
 877		$this->_bob->email = 'newemail@domain.com';
 878		$this->assertEquals('newemail@domain.com', $this->_bob->email);
 879	}
 880	
 881	public function testMagicIssetAndUnset()
 882	{
 883		$this->assertTrue(isset($this->_bob->email));
 884		unset($this->_bob->email);
 885		$this->assertFalse(isset($this->_bob->email));
 886	}
 887	
 888	public function testOffsetGetAndSet()
 889	{
 890		$this->assertEquals('bob.jones@domain.com', $this->_bob['email']);
 891		$this->_bob['email'] = 'newemail@domain.com';
 892		$this->assertEquals('newemail@domain.com', $this->_bob['email']);
 893	}
 894	
 895	public function testOffsetExistsAndUnset()
 896	{
 897		$this->assertTrue(isset($this->_bob['email']));
 898		unset($this->_bob['email']);
 899		$this->assertFalse(isset($this->_bob['email']));
 900	}
 901	
 902	public function testGetIterator()
 903	{
 904		$iterator = $this->_bob->getIterator();
 905		$this->assertInternalType(PHPUnit_Framework_Constraint_IsType::TYPE_OBJECT, $iterator);
 906		$this->assertEquals('Shanty_Mongo_Iterator_Default', get_class($iterator));
 907	}
 908	
 909	public function testOperations()
 910	{
 911		$this->assertEquals(array(), $this->_bob->getOperations(true));
 912		
 913		$this->assertEquals(array(), $this->_bob->name->getOperations());
 914		$this->_bob->name->addOperation('$set', 'first', 'Bobster');
 915		$this->_bob->addOperation('$set', 'email', 'email@domain.com');
 916		
 917		$operations = array(
 918			'$set' => array(
 919				'name.first' => 'Bobster',
 920			)
 921		);
 922		
 923		$this->assertEquals($operations, $this->_bob->name->getOperations());
 924		
 925		$operations = array(
 926			'$set' => array(
 927				'name.first' => 'Bobster',
 928				'email' => 'email@domain.com'
 929			)
 930		);
 931		
 932		$this->assertEquals($operations, $this->_bob->getOperations(true));
 933		
 934		$this->_bob->addOperation('$inc', 'count', 3);
 935		$this->_bob->addOperation('$inc', 'age', 1);
 936		
 937		$address = array(
 938			'street' => '2352 Long St',
 939			'suburb' => 'Brisbane',
 940			'state' => 'QLD',
 941			'postcode' => '4000',
 942			'country' => 'Australia'
 943		);
 944		$this->_bob->addOperation('$push', 'addresses', $address);
 945		
 946		$operations = array(
 947			'$inc' => array(
 948				'count' => 3,
 949				'age' => 1,
 950			),
 951			'$push' => array(
 952				'addresses' => $address
 953			),
 954			'$set' => array(
 955				'name.first' => 'Bobster',
 956				'email' => 'email@domain.com'
 957			)
 958		);
 959		
 960		$this->assertEquals($operations, $this->_bob->getOperations(true));
 961		$this->_bob->purgeOperations(true);
 962		$this->assertEquals(array(), $this->_bob->getOperations(true));
 963		
 964		// Test operations of the document it's self.
 965		$address = array(
 966			'street' => '2352 Long St',
 967			'suburb' => 'Brisbane',
 968			'state' => 'QLD',
 969			'postcode' => '4000',
 970			'country' => 'Australia'
 971		);
 972		
 973		$this->_bob->addresses->addOperation('$push', null, $address);
 974		
 975		$operations = array(
 976			'$push' => array(
 977				'addresses' => $address
 978			)
 979		);
 980		$this->assertEquals($operations, $this->_bob->getOperations(true));
 981	}
 982	
 983	/**
 984     * @expectedException Shanty_Mongo_Exception
 985     */
 986	public function testInvalidOperation()
 987	{
 988		$this->_bob->addOperation('invalid operation', 'count', 3);
 989	}
 990	
 991	/**
 992	 * @depends testOperations
 993	 */
 994	public function testIncOperation()
 995	{
 996		$this->_bob->inc('count', 3);
 997		
 998		$operations = array(
 999			'$inc' => array(
1000				'count' => 3
1001			)
1002		);
1003		
1004		$this->assertEquals($operations, $this->_bob->getOperations());
1005	}
1006	
1007	/**
1008	 * @depends testOperations
1009	 */
1010	public function testPushOperation()
1011	{
1012		$address = array(
1013			'street' => '2352 Long St',
1014			'suburb' => 'Brisbane',
1015			'state' => 'QLD',
1016			'postcode' => '4000',
1017			'country' => 'Australia'
1018		);
1019		$this->_bob->push('addresses', $address);
1020		
1021		$operations = array(
1022			'$pushAll' => array(
1023				'addresses' => array($address)
1024			)
1025		);
1026		
1027		$this->assertEquals($operations, $this->_bob->getOperations());
1028		
1029		$this->_bob->purgeOperations();
1030		
1031		$address = new Shanty_Mongo_Document();
1032		$address->street = '2352 Long St';
1033		$address->suburb = 'Brisbane';
1034		$address->state = 'QLD';
1035		$address->postcode = '4000';
1036		$address->country = 'Australia';
1037		
1038		$this->_bob->push('addresses', $address);
1039		
1040		$this->assertEquals($operations, $this->_bob->getOperations());
1041	}
1042	
1043	/**
1044	 * @depends testOperations
1045	 */
1046	public function testPullOperation()
1047	{
1048		$this->_bob->pull('tags', 'sexy');
1049		
1050		$operations = array(
1051			'$pullAll' => array(
1052				'tags' => 'sexy'
1053			)
1054		);
1055		
1056		$this->assertEquals($operations, $this->_bob->getOperations());
1057	}
1058	
1059	/**
1060	 * @depends testOperations
1061	 */
1062	public function testAddToSetOperation()
1063	{
1064		$this->_bob->addToSet('tags', 'sexy');
1065		
1066		$operations = array(
1067			'$addToSet' => array(
1068				'tags' => 'sexy'
1069			)
1070		);
1071		
1072		$this->assertEquals($operations, $this->_bob->getOperations());
1073	}
1074	
1075	/**
1076	 * @depends testOperations
1077	 */
1078	public function testPopOperation()
1079	{
1080		$this->_bob->pop('addresses', 1);
1081		
1082		$operations = array(
1083			'$pop' => array(
1084				'addresses' => 1
1085			)
1086		);
1087		
1088		$this->assertEquals($operations, $this->_bob->getOperations());
1089	}
1090	
1091	/**
1092	 * @depends testOperations
1093	 */
1094	public function testProcessChanges()
1095	{
1096		$newRoger = $this->_users['roger'];
1097		
1098		$newRoger['name']['first'] = 'Bagger';
1099		$newRoger['favouriteColour'] = 'Blue';
1100		unset($newRoger['email']);
1101		
1102		$this->_roger->processChanges($newRoger);
1103		
1104		$operations = array(
1105			'$set' => array(
1106				'name' => array(
1107					'first' => 'Bagger',
1108					'last' => 'Smith'
1109				),
1110				'favouriteColour' => 'Blue'
1111			),
1112			'$unset' => array(
1113				'email' => 1
1114			)
1115		);
1116		
1117		$this->assertEquals($operations, $this->_roger->getOperations());
1118	}
1119	
1120	/**
1121	 * @depends testOperations
1122	 * @depends testExport
1123	 */
1124	public function testProcessChangesNoChanges()
1125	{
1126		$this->_bob->processChanges($this->_bob->export());
1127		$this->assertEquals(array(), $this->_bob->getOperations(true));
1128	}
1129	
1130	/**
1131	 * @depends testOperations
1132	 * @depends testExport
1133	 */
1134	public function testProcessChangesNoChangesDataInit()
1135	{
1136		// Initialise all properties
1137		foreach ($this->_bob as $property => $value) {
1138			
1139		}
1140		
1141		$this->_bob->processChanges($this->_bob->export());
1142		$this->assertEquals(array(), $this->_bob->getOperations(true));
1143	}
1144	
1145	public function testInitHook()
1146	{
1147		$this->assertEquals(1, $this->_bob->_hookCounter['init']);
1148	}
1149	
1150	public function testPrePostInsertUpdateSaveHook()
1151	{
1152		$user = new My_ShantyMongo_User();
1153		$user->name->first = 'Stranger';
1154		$user->name->last = 'Jill';
1155		$user->email = 'jill@domain.com';
1156		$user->sex = 'M';
1157		$user->save();
1158		
1159		$user->email = 'jill@address.com';
1160		$user->save();
1161		
1162		$this->assertEquals(1, $user->_hookCounter['preInsert']);
1163		$this->assertEquals(1, $user->_hookCounter['postInsert']);
1164		$this->assertEquals(1, $user->_hookCounter['preUpdate']);
1165		$this->assertEquals(1, $user->_hookCounter['postUpdate']);
1166		$this->assertEquals(2, $user->_hookCounter['preSave']);
1167		$this->assertEquals(2, $user->_hookCounter['postSave']);
1168	}
1169	
1170	/**
1171	 * Test for issue https://github.com/coen-hyde/Shanty-Mongo/issues/50
1172	 *
1173	 * @return void
1174	 * @author Tom Holder
1175	 **/
1176	public function testConcreteClassFromArray()
1177	{
1178		$data = array(
1179	       'title' => '101 reasons mongo is the bomb digidy',
1180	       'relatedArticles' => array(
1181	           array(
1182				   'title' => '102 reasons mongo is the bomb digidy',
1183	               'relatedArticles' => array(
1184						array(
1185							'title' => '103 reasons mongo is the bomb digidy',
1186						)
1187				   )
1188	           )
1189	       )
1190	    );
1191
1192	    $article = new My_ShantyMongo_Article($data);
1193
1194        $this->assertInstanceOf('Shanty_Mongo_DocumentSet', $article->relatedArticles);
1195        $this->assertInstanceOf('My_ShantyMongo_Article', $article->relatedArticles[0]);
1196	    $this->assertEquals('102 reasons mongo is the bomb digidy', $article->relatedArticles[0]->title);
1197	    $this->assertEquals('103 reasons mongo is the bomb digidy', $article->relatedArticles[0]->relatedArticles[0]->title);
1198
1199	    $exportedData = $article->export();
1200	    $this->assertEquals('102 reasons mongo is the bomb digidy', $exportedData['relatedArticles'][0]['title']);
1201	}
1202}