PageRenderTime 54ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/cases/data/source/MongoDbTest.php

https://github.com/Daikoun/lithium
PHP | 779 lines | 629 code | 137 blank | 13 comment | 2 complexity | 383c63d356a4a1f894cbf106d330aa72 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2012, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\tests\cases\data\source;
  9. use lithium\data\source\mongo_db\Schema;
  10. use lithium\data\source\MongoDb;
  11. use Exception;
  12. use stdClass;
  13. use MongoId;
  14. use MongoCode;
  15. use MongoDate;
  16. use MongoRegex;
  17. use lithium\data\model\Query;
  18. use lithium\data\entity\Document;
  19. use lithium\tests\mocks\data\MockPost;
  20. use lithium\tests\mocks\data\MockComment;
  21. use lithium\data\collection\DocumentSet;
  22. use lithium\tests\mocks\data\source\MockMongoSource;
  23. use lithium\tests\mocks\data\source\MockMongoConnection;
  24. use lithium\tests\mocks\data\source\mongo_db\MockResult;
  25. class MongoDbTest extends \lithium\test\Unit {
  26. protected $_model = 'lithium\tests\mocks\data\source\MockMongoPost';
  27. protected $_testConfig = array(
  28. 'adapter' => false,
  29. 'database' => 'lithium_test',
  30. 'host' => 'localhost',
  31. 'port' => '27017',
  32. 'persistent' => null,
  33. 'autoConnect' => false
  34. );
  35. protected $_schema = array(
  36. '_id' => 'id',
  37. 'guid' => 'id',
  38. 'title' => 'string',
  39. 'tags' => array('type' => 'string', 'array' => true),
  40. 'comments' => 'MongoId',
  41. 'authors' => array('type' => 'MongoId', 'array' => true),
  42. 'created' => 'MongoDate',
  43. 'modified' => 'datetime',
  44. 'voters' => array('type' => 'id', 'array' => true),
  45. 'rank_count' => array('type' => 'integer', 'default' => 0),
  46. 'rank' => array('type' => 'float', 'default' => 0.0),
  47. 'notifications.foo' => 'boolean',
  48. 'notifications.bar' => 'boolean',
  49. 'notifications.baz' => 'boolean'
  50. );
  51. protected $_configs = array();
  52. public function skip() {
  53. $this->skipIf(!MongoDb::enabled(), 'The `MongoDb` class is not enabled.');
  54. $db = new MongoDb($this->_testConfig);
  55. $message = "`{$this->_testConfig['database']}` database or connection unavailable";
  56. $this->skipIf(!$db->isConnected(array('autoConnect' => true)), $message);
  57. }
  58. public function setUp() {
  59. $model = $this->_model;
  60. $this->db = new MongoDb($this->_testConfig);
  61. $this->db->server = (object) array('connected' => true);
  62. $this->db->connection = new MockMongoConnection();
  63. MockPost::resetSchema(true);
  64. MockComment::resetSchema(true);
  65. $model::config(array('key' => '_id'));
  66. $model::$connection = $this->db;
  67. $this->query = new Query(compact('model') + array('entity' => new Document(compact('model'))));
  68. }
  69. public function tearDown() {
  70. unset($this->query);
  71. }
  72. public function testBadConnection() {
  73. $db = new MongoDb(array('host' => null, 'autoConnect' => false));
  74. $this->expectException('Could not connect to the database.');
  75. $this->assertFalse($db->connect());
  76. $this->assertTrue($db->disconnect());
  77. }
  78. public function testGoodConnectionBadDatabase() {
  79. $this->expectException('Could not connect to the database.');
  80. $db = new MongoDb(array('database' => null, 'autoConnnect' => false));
  81. }
  82. public function testGoodConnectionGoodDatabase() {
  83. $db = new MongoDb(array('autoConnect' => false) + $this->_testConfig);
  84. $this->assertFalse($db->isConnected());
  85. $this->assertTrue($db->connect());
  86. $this->assertTrue($db->isConnected());
  87. }
  88. public function testSources() {
  89. $this->db->connection->results = array(array());
  90. $this->assertEqual(array(), $this->db->sources());
  91. }
  92. public function testDescribe() {
  93. $result = $this->db->describe('test')->fields();
  94. $expected = array('_id' => array('type' => 'id'));
  95. $this->assertEqual($expected, $result);
  96. }
  97. public function testName() {
  98. $result = $this->db->name('{(\'Li\':"∆")}');
  99. $expected = '{(\'Li\':"∆")}';
  100. $this->assertEqual($expected, $result);
  101. }
  102. public function testSchema() {
  103. $result = $this->db->schema($this->query);
  104. $expected = array();
  105. $this->assertEqual($expected, $result);
  106. }
  107. public function testCreateSuccess() {
  108. array_push($this->db->connection->results, true);
  109. $this->query->data(array('title' => 'Test Post'));
  110. $this->assertTrue($this->db->create($this->query));
  111. $query = array_pop($this->db->connection->queries);
  112. $this->assertFalse($this->db->connection->queries);
  113. $this->assertEqual('insert', $query['type']);
  114. $this->assertEqual('posts', $query['collection']);
  115. $this->assertEqual(array('title', '_id'), array_keys($query['data']));
  116. $this->assertTrue($query['data']['_id'] instanceof MongoId);
  117. }
  118. public function testConditions() {
  119. $result = $this->db->conditions(null, null);
  120. $this->assertEqual(array(), $result);
  121. $function = 'function() { return this.x < y;}';
  122. $conditions = new MongoCode($function);
  123. $result = $this->db->conditions($conditions, null);
  124. $this->assertTrue(is_array($result));
  125. $this->assertTrue(isset($result['$where']));
  126. $this->assertEqual($conditions, $result['$where']);
  127. $conditions = $function;
  128. $result = $this->db->conditions($conditions, null);
  129. $this->assertTrue(is_array($result));
  130. $this->assertTrue(isset($result['$where']));
  131. $this->assertEqual($conditions, $result['$where']);
  132. $conditions = array('key' => 'value', 'anotherkey' => 'some other value');
  133. $result = $this->db->conditions($conditions, null);
  134. $this->assertTrue(is_array($result));
  135. $this->assertEqual($conditions, $result);
  136. $conditions = array('key' => array('one', 'two', 'three'));
  137. $result = $this->db->conditions($conditions, null);
  138. $this->assertTrue(is_array($result));
  139. $this->assertTrue(isset($result['key']));
  140. $this->assertTrue(isset($result['key']['$in']));
  141. $this->assertEqual($conditions['key'], $result['key']['$in']);
  142. $conditions = array('$or' => array(
  143. array('key' => 'value'),
  144. array('other key' => 'another value')
  145. ));
  146. $result = $this->db->conditions($conditions, null);
  147. $this->assertTrue(isset($result['$or']));
  148. $this->assertEqual($conditions['$or'][0]['key'], $result['$or'][0]['key']);
  149. $conditions = array('$and' => array(
  150. array('key' => 'value'),
  151. array('other key' => 'another value')
  152. ));
  153. $result = $this->db->conditions($conditions, null);
  154. $this->assertTrue(isset($result['$and']));
  155. $this->assertEqual($conditions['$and'][0]['key'], $result['$and'][0]['key']);
  156. $conditions = array('$nor' => array(
  157. array('key' => 'value'),
  158. array('other key' => 'another value')
  159. ));
  160. $result = $this->db->conditions($conditions, null);
  161. $this->assertTrue(isset($result['$nor']));
  162. $this->assertEqual($conditions['$nor'][0]['key'], $result['$nor'][0]['key']);
  163. $conditions = array('key' => array('or' => array(1, 2)));
  164. $result = $this->db->conditions($conditions, null);
  165. $this->assertEqual(array('key' => array('$or' => array(1, 2))), $result);
  166. }
  167. public function testMongoConditionalOperators() {
  168. $conditions = array('key' => array('<' => 10));
  169. $expected = array('key' => array('$lt' => 10));
  170. $result = $this->db->conditions($conditions, null);
  171. $this->assertEqual($expected, $result);
  172. $conditions = array('key' => array('<=' => 10));
  173. $expected = array('key' => array('$lte' => 10));
  174. $result = $this->db->conditions($conditions, null);
  175. $this->assertEqual($expected, $result);
  176. $conditions = array('key' => array('>' => 10));
  177. $expected = array('key' => array('$gt' => 10));
  178. $result = $this->db->conditions($conditions, null);
  179. $this->assertEqual($expected, $result);
  180. $conditions = array('key' => array('>=' => 10));
  181. $expected = array('key' => array('$gte' => 10));
  182. $result = $this->db->conditions($conditions, null);
  183. $this->assertEqual($expected, $result);
  184. $conditions = array('key' => array('!=' => 10));
  185. $expected = array('key' => array('$ne' => 10));
  186. $result = $this->db->conditions($conditions, null);
  187. $this->assertEqual($expected, $result);
  188. $conditions = array('key' => array('<>' => 10));
  189. $expected = array('key' => array('$ne' => 10));
  190. $result = $this->db->conditions($conditions, null);
  191. $this->assertEqual($expected, $result);
  192. $conditions = array('key' => array('!=' => array(10, 20, 30)));
  193. $expected = array('key' => array('$nin' => array(10, 20, 30)));
  194. $result = $this->db->conditions($conditions, null);
  195. $this->assertEqual($expected, $result);
  196. $conditions = array('key' => array('<>' => array(10, 20, 30)));
  197. $expected = array('key' => array('$nin' => array(10, 20, 30)));
  198. $result = $this->db->conditions($conditions, null);
  199. $this->assertEqual($expected, $result);
  200. $conditions = array('key' => array('like' => '/regex/i'));
  201. $result = $this->db->conditions($conditions, null);
  202. $expected = array('key' => new MongoRegex('/regex/i'));
  203. $this->assertEqual($expected, $result);
  204. }
  205. public function testReadNoConditions() {
  206. $this->db->connect();
  207. $connection = $this->db->connection;
  208. $this->db->connection = new MockMongoSource();
  209. $this->db->connection->resultSets = array(array('ok' => true));
  210. $data = array('title' => 'Test Post');
  211. $options = array('safe' => false, 'fsync' => false);
  212. $this->query->data($data);
  213. $this->assertIdentical(true, $this->db->create($this->query));
  214. $this->assertEqual(compact('data', 'options'), end($this->db->connection->queries));
  215. $this->db->connection->resultSets = array(array(array('_id' => new MongoId()) + $data));
  216. $result = $this->db->read($this->query);
  217. $this->assertTrue($result instanceof DocumentSet);
  218. $this->assertEqual(1, $result->count());
  219. $this->assertEqual('Test Post', $result->first()->title);
  220. $this->db->connection = $connection;
  221. }
  222. public function testReadWithConditions() {
  223. $this->db->connect();
  224. $connection = $this->db->connection;
  225. $this->db->connection = new MockMongoSource();
  226. $this->db->connection->resultSets = array(array('ok' => true));
  227. $data = array('title' => 'Test Post');
  228. $options = array('safe' => false, 'fsync' => false);
  229. $this->query->data($data);
  230. $this->assertTrue($this->db->create($this->query));
  231. $this->query->data(null);
  232. $this->db->connection->resultSets = array(array());
  233. $this->query->conditions(array('title' => 'Nonexistent Post'));
  234. $result = $this->db->read($this->query);
  235. $this->assertTrue($result == true);
  236. $this->assertEqual(0, $result->count());
  237. $this->db->connection->resultSets = array(array($data));
  238. $this->query->conditions($data);
  239. $result = $this->db->read($this->query);
  240. $this->assertTrue($result == true);
  241. $this->assertEqual(1, $result->count());
  242. $this->db->connection = $connection;
  243. }
  244. public function testUpdate() {
  245. $model = $this->_model;
  246. $data = array('title' => 'Test Post');
  247. $this->query->model($model);
  248. $this->query->data($data);
  249. $this->db->connection->results = array(true);
  250. $this->db->create($this->query);
  251. $result = array_pop($this->db->connection->queries);
  252. $data['_id'] = $result['data']['_id'];
  253. $expected = compact('data') + array(
  254. 'collection' => 'posts',
  255. 'type' => 'insert',
  256. 'options' => array('safe' => false, 'fsync' => false)
  257. );
  258. $this->assertEqual($expected, $result);
  259. $this->db->connection->results = array(
  260. new MockResult(array('data' => array($data))),
  261. new MockResult(array('data' => array($data)))
  262. );
  263. $this->db->connection->queries = array();
  264. $result = $this->db->read(new Query(compact('model')));
  265. $original = $result->first()->to('array');
  266. $this->assertEqual(array('title', '_id'), array_keys($original));
  267. $this->assertEqual('Test Post', $original['title']);
  268. $this->assertPattern('/^[0-9a-f]{24}$/', $original['_id']);
  269. $this->db->connection->results = array(true);
  270. $this->db->connection->queries = array();
  271. $update = array('title' => 'New Post Title');
  272. $this->query = new Query(compact('model') + array(
  273. 'data' => $update,
  274. 'conditions' => array('_id' => $original['_id'])
  275. ));
  276. $this->assertTrue($this->db->update($this->query));
  277. $result = array_pop($this->db->connection->queries);
  278. $expected = array(
  279. 'type' => 'update',
  280. 'collection' => 'posts',
  281. 'conditions' => array('_id' => '4f188fb17675ab167900010e'),
  282. 'update' => array('$set' => array('title' => 'New Post Title')),
  283. 'options' => array(
  284. 'upsert' => false, 'multiple' => true, 'safe' => false, 'fsync' => false
  285. )
  286. );
  287. array_push($this->db->connection->results, new MockResult(array(
  288. 'data' => array($update + $original)
  289. )));
  290. $this->db->connection->queries = array();
  291. $result = $this->db->read(new Query(compact('model') + array(
  292. 'conditions' => array('_id' => $original['_id'])
  293. )));
  294. $this->assertEqual(1, $result->count());
  295. $updated = $result->first();
  296. $updated = $updated ? $updated->to('array') : array();
  297. $this->assertEqual($original['_id'], $updated['_id']);
  298. $this->assertEqual('New Post Title', $updated['title']);
  299. $expected = array(
  300. 'type' => 'find',
  301. 'collection' => 'posts',
  302. 'fields' => array(),
  303. 'conditions' => array('_id' => $original['_id'])
  304. );
  305. $this->assertEqual($expected, array_pop($this->db->connection->queries));
  306. }
  307. public function testDelete() {
  308. $data = array('title' => 'Delete Me');
  309. array_push($this->db->connection->results, true);
  310. $this->query->data($data);
  311. $this->db->create($this->query);
  312. array_push($this->db->connection->results, new MockResult(array(
  313. 'data' => array()
  314. )));
  315. $this->assertNull($this->db->read($this->query)->first());
  316. $result = array_pop($this->db->connection->queries);
  317. $conditions = array('_id' => $this->query->entity()->_id);
  318. $this->assertEqual($conditions, $result['conditions']);
  319. $model = $this->_model;
  320. $this->query = new Query(compact('model') + array(
  321. 'entity' => new Document(compact('model'))
  322. ));
  323. array_push($this->db->connection->results, true);
  324. $this->query->conditions($conditions);
  325. $this->assertTrue($this->db->delete($this->query));
  326. $expected = compact('conditions') + array(
  327. 'type' => 'remove',
  328. 'collection' => 'posts',
  329. 'options' => array('justOne' => false, 'safe' => false, 'fsync' => false)
  330. );
  331. $this->assertEqual($expected, array_pop($this->db->connection->queries));
  332. }
  333. public function testItem() {
  334. $model = $this->_model;
  335. $data = array('title' => 'New Item');
  336. $result = $this->db->item($model, $data);
  337. $this->assertTrue($result instanceof Document);
  338. $expected = $data;
  339. $result = $result->to('array');
  340. $this->assertEqual($expected, $result);
  341. }
  342. public function testCalculation() {
  343. $this->db->connection->results = array(new MockResult(array('data' => array(5))));
  344. $this->assertIdentical(5, $this->db->calculation('count', $this->query));
  345. }
  346. public function testEnabled() {
  347. $this->assertTrue(MongoDb::enabled());
  348. $this->assertTrue(MongoDb::enabled('arrays'));
  349. $this->assertTrue(MongoDb::enabled('booleans'));
  350. $this->assertTrue(MongoDb::enabled('relationships'));
  351. }
  352. public function testArbitraryMethodCalls() {
  353. $db = new MongoDb($config = $this->_testConfig);
  354. $result = $db->__toString();
  355. $this->assertTrue(strpos($result, $config['host']) !== false);
  356. $this->assertTrue(strpos($result, $config['port']) !== false);
  357. $this->assertTrue(is_array($db->listDBs()));
  358. }
  359. public function testDocumentSorting() {
  360. $model = $this->_model;
  361. $model::config(array('source' => 'ordered_docs', 'locked' => false));
  362. $first = array('title' => 'First document', 'position' => 1);
  363. $second = array('title' => 'Second document', 'position' => 2);
  364. $third = array('title' => 'Third document', 'position' => 3);
  365. $model::create($third)->save();
  366. $model::create($first)->save();
  367. $model::create($second)->save();
  368. $result = $this->db->connection->queries;
  369. $createOpts = array(
  370. 'validate' => true,
  371. 'events' => 'create',
  372. 'whitelist' => null,
  373. 'callbacks' => true,
  374. 'locked' => false,
  375. 'safe' => false,
  376. 'fsync' => false
  377. );
  378. $baseInsert = array('type' => 'insert', 'collection' => 'ordered_docs', 'options' => $createOpts);
  379. $expected = array(
  380. $baseInsert + array('data' => array('_id' => $result[0]['data']['_id']) + $third),
  381. $baseInsert + array('data' => array('_id' => $result[1]['data']['_id']) + $first),
  382. $baseInsert + array('data' => array('_id' => $result[2]['data']['_id']) + $second)
  383. );
  384. $this->assertEqual($expected, $result);
  385. array_push($this->db->connection->results, new MockResult(array(
  386. 'data' => array($first, $second, $third)
  387. )));
  388. $this->db->connection->queries = array();
  389. $documents = $model::all(array('order' => 'position'));
  390. $this->assertEqual($first['title'], $documents[0]->title);
  391. $this->assertEqual($second['title'], $documents[1]->title);
  392. $this->assertEqual($third['title'], $documents[2]->title);
  393. $expected = array(
  394. 'type' => 'find', 'collection' => 'ordered_docs', 'conditions' => array(), 'fields' => array()
  395. );
  396. $this->assertEqual($expected, array_pop($this->db->connection->queries));
  397. $this->assertEqual(array('position' => 1), $documents->result()->resource()->query['sort']);
  398. array_push($this->db->connection->results, new MockResult(array(
  399. 'data' => array($first, $second, $third)
  400. )));
  401. $documents = $model::all(array('order' => array('position' => 'asc')));
  402. $this->assertEqual($first['title'], $documents[0]->title);
  403. $this->assertEqual($second['title'], $documents[1]->title);
  404. $this->assertEqual($third['title'], $documents[2]->title);
  405. $this->assertEqual($expected, array_pop($this->db->connection->queries));
  406. $this->assertEqual(array('position' => 1), $documents->result()->resource()->query['sort']);
  407. array_push($this->db->connection->results, new MockResult(array(
  408. 'data' => array($third, $second, $first)
  409. )));
  410. $documents = $model::all(array('order' => array('position' => 'desc')));
  411. $this->assertEqual($third['title'], $documents[0]->title);
  412. $this->assertEqual($second['title'], $documents[1]->title);
  413. $this->assertEqual($first['title'], $documents[2]->title);
  414. $this->assertEqual($expected, array_pop($this->db->connection->queries));
  415. $this->assertEqual(array('position' => -1), $documents->result()->resource()->query['sort']);
  416. }
  417. public function testMongoIdPreservation() {
  418. $model = $this->_model;
  419. $model::resetSchema(true);
  420. $model::config(array('locked' => false));
  421. $post = $model::create(array('_id' => new MongoId(), 'title' => 'A post'));
  422. $post->save();
  423. $result = array_pop($this->db->connection->queries);
  424. $data = $result['data'];
  425. $this->assertEqual('A post', $data['title']);
  426. $this->assertTrue($data['_id'] instanceof MongoId);
  427. $post->sync();
  428. $post->title = 'An updated post';
  429. $post->save();
  430. $result = array_pop($this->db->connection->queries);
  431. $this->assertEqual(array('_id' => $post->_id), $result['conditions']);
  432. $this->assertEqual(array('$set' => array('title' => 'An updated post')), $result['update']);
  433. }
  434. public function testRelationshipGeneration() {
  435. $from = 'lithium\tests\mocks\data\MockComment';
  436. $to = 'lithium\tests\mocks\data\MockPost';
  437. $from::$connection = $this->db;
  438. $to::$connection = $this->db;
  439. $to::config(array('key' => '_id'));
  440. $result = $this->db->relationship($from, 'belongsTo', 'MockPost');
  441. $expected = array(
  442. 'name' => 'MockPost',
  443. 'type' => 'belongsTo',
  444. 'key' => array('mockComment' => '_id'),
  445. 'from' => $from,
  446. 'link' => 'contained',
  447. 'to' => $to,
  448. 'fields' => true,
  449. 'fieldName' => 'mockPost',
  450. 'constraint' => null,
  451. 'init' => true
  452. );
  453. $this->assertEqual($expected, $result->data());
  454. }
  455. public function testCreateNoConnectionException() {
  456. $db = new MongoDb(array('host' => '__invalid__', 'autoConnect' => false));
  457. $this->expectException('Could not connect to the database.');
  458. $result = $db->create(null);
  459. }
  460. public function testReadNoConnectionException() {
  461. $db = new MongoDb(array('host' => '__invalid__', 'autoConnect' => false));
  462. $this->expectException('Could not connect to the database.');
  463. $result = $db->read(null);
  464. }
  465. public function testUpdateNoConnectionException() {
  466. $db = new MongoDb(array('host' => '__invalid__', 'autoConnect' => false));
  467. $this->expectException('Could not connect to the database.');
  468. $result = $db->update(null);
  469. }
  470. public function testDeleteNoConnectionException() {
  471. $db = new MongoDb(array('host' => '__invalid__', 'autoConnect' => false));
  472. $this->expectException('Could not connect to the database.');
  473. $result = $db->delete(null);
  474. }
  475. public function testSourcesNoConnectionException() {
  476. $db = new MongoDb(array('host' => null, 'autoConnect' => false));
  477. $this->expectException('Could not connect to the database.');
  478. $result = $db->sources(null);
  479. }
  480. public function testAtomicUpdate() {
  481. $model = $this->_model;
  482. $model::config(array('source' => 'posts'));
  483. $model::resetSchema();
  484. $data = array('initial' => 'one', 'values' => 'two');
  485. $this->db->connection = new MockMongoConnection();
  486. $this->db->connection->results = array(true, true);
  487. $document = $model::create($data);
  488. $this->assertTrue($document->save());
  489. $result = array_shift($this->db->connection->queries);
  490. $expected = array(
  491. 'type' => 'insert',
  492. 'collection' => 'posts',
  493. 'data' => array('initial' => 'one', 'values' => 'two', '_id' => $document->_id),
  494. 'options' => array(
  495. 'validate' => true, 'events' => 'create', 'whitelist' => null, 'callbacks' => true,
  496. 'locked' => false, 'safe' => false, 'fsync' => false
  497. )
  498. );
  499. $this->assertEqual($expected, $result);
  500. $duplicate = $model::create(array('_id' => $document->_id), array('exists' => true));
  501. $duplicate->values = 'new';
  502. $this->assertTrue($duplicate->save());
  503. $result = array_shift($this->db->connection->queries);
  504. $expected = array(
  505. 'type' => 'update',
  506. 'collection' => 'posts',
  507. 'conditions' => array('_id' => $document->_id),
  508. 'update' => array('$set' => array('values' => 'new')),
  509. 'options' => array(
  510. 'validate' => true, 'events' => 'update', 'whitelist' => null,
  511. 'callbacks' => true, 'locked' => false, 'upsert' => false, 'multiple' => true,
  512. 'safe' => false, 'fsync' => false,
  513. )
  514. );
  515. $this->assertEqual($expected, $result);
  516. array_push($this->db->connection->results, new MockResult(array('data' => array(
  517. array('_id' => $duplicate->_id, 'initial' => 'one', 'values' => 'new')
  518. ))));
  519. $document = $model::find($duplicate->_id);
  520. $expected = array('_id' => (string) $duplicate->_id, 'initial' => 'one', 'values' => 'new');
  521. $this->assertEqual($expected, $document->data());
  522. $result = array_shift($this->db->connection->queries);
  523. $expected = array(
  524. 'type' => 'find', 'collection' => 'posts', 'fields' => array(), 'conditions' => array(
  525. '_id' => $duplicate->_id
  526. )
  527. );
  528. $this->assertEqual($expected, $result);
  529. }
  530. /**
  531. * Tests that the MongoDB adapter will not attempt to overwrite the _id field on document
  532. * update.
  533. */
  534. public function testPreserveId() {
  535. $model = $this->_model;
  536. $document = $model::create(array('_id' => 'custom'), array('exists' => true));
  537. array_push($this->db->connection->results, true);
  538. $this->assertTrue($document->save(array('_id' => 'custom2', 'foo' => 'bar')));
  539. $result = array_shift($this->db->connection->queries);
  540. $expected = array('$set' => array('foo' => 'bar'));
  541. $this->assertEqual($expected, $result['update']);
  542. }
  543. public function testCastingConditionsValues() {
  544. $query = new Query(array('schema' => new Schema(array('fields' => $this->_schema))));
  545. $conditions = array('_id' => new MongoId("4c8f86167675abfabdbe0300"));
  546. $result = $this->db->conditions($conditions, $query);
  547. $this->assertEqual($conditions, $result);
  548. $conditions = array('_id' => "4c8f86167675abfabdbe0300");
  549. $result = $this->db->conditions($conditions, $query);
  550. $this->assertEqual(array_keys($conditions), array_keys($result));
  551. $this->assertTrue($result['_id'] instanceof MongoId);
  552. $this->assertEqual($conditions['_id'], (string) $result['_id']);
  553. $conditions = array('_id' => array(
  554. "4c8f86167675abfabdbe0300", "4c8f86167675abfabdbf0300", "4c8f86167675abfabdc00300"
  555. ));
  556. $result = $this->db->conditions($conditions, $query);
  557. $this->assertEqual(3, count($result['_id']['$in']));
  558. foreach (array(0, 1, 2) as $i) {
  559. $this->assertTrue($result['_id']['$in'][$i] instanceof MongoId);
  560. }
  561. $conditions = array('voters' => array('$all' => array(
  562. "4c8f86167675abfabdbf0300", "4c8f86167675abfabdc00300"
  563. )));
  564. $result = $this->db->conditions($conditions, $query);
  565. $this->assertEqual(2, count($result['voters']['$all']));
  566. $result = $result['voters']['$all'];
  567. foreach (array(0, 1) as $i) {
  568. $this->assertTrue($result[$i] instanceof MongoId);
  569. $this->assertEqual($conditions['voters']['$all'][$i], (string) $result[$i]);
  570. }
  571. $conditions = array('$or' => array(
  572. array('_id' => "4c8f86167675abfabdbf0300"),
  573. array('guid' => "4c8f86167675abfabdbf0300")
  574. ));
  575. $result = $this->db->conditions($conditions, $query);
  576. $this->assertEqual(array('$or'), array_keys($result));
  577. $this->assertEqual(2, count($result['$or']));
  578. foreach (array('_id', 'guid') as $i => $key) {
  579. $this->assertTrue($result['$or'][$i][$key] instanceof MongoId);
  580. $this->assertEqual($conditions['$or'][$i][$key], (string) $result['$or'][$i][$key]);
  581. }
  582. }
  583. public function testMultiOperationConditions() {
  584. $conditions = array('loc' => array('$near' => array(50, 50), '$maxDistance' => 5));
  585. $result = $this->db->conditions($conditions, $this->query);
  586. $this->assertEqual($conditions, $result);
  587. }
  588. public function testCreateWithEmbeddedObjects() {
  589. $data = array(
  590. '_id' => new MongoId(),
  591. 'created' => new MongoDate(strtotime('-1 hour')),
  592. 'list' => array('foo', 'bar', 'baz')
  593. );
  594. $entity = new Document(compact('data') + array('exists' => false));
  595. $query = new Query(array('type' => 'create') + compact('entity'));
  596. $result = $query->export($this->db);
  597. $this->assertIdentical($data, $result['data']['data']);
  598. }
  599. public function testUpdateWithEmbeddedObjects() {
  600. $data = array(
  601. '_id' => new MongoId(),
  602. 'created' => new MongoDate(strtotime('-1 hour')),
  603. 'list' => array('foo', 'bar', 'baz')
  604. );
  605. $model = $this->_model;
  606. $fields = array('updated' => array('type' => 'MongoDate'));
  607. $schema = new Schema(compact('fields'));
  608. $entity = new Document(compact('data', 'schema', 'model') + array('exists' => true));
  609. $entity->updated = time();
  610. $entity->list[] = 'dib';
  611. $query = new Query(array('type' => 'update') + compact('entity'));
  612. $result = $query->export($this->db);
  613. $expected = array('updated', '_id', 'created', 'list');
  614. $this->assertEqual($expected, array_keys($result['data']['update']));
  615. $this->assertTrue($result['data']['update']['updated'] instanceof MongoDate);
  616. }
  617. /**
  618. * Assert that Mongo and the Mongo Exporter don't mangle manual geospatial queries.
  619. */
  620. public function testGeoQueries() {
  621. $coords = array(84.13, 11.38);
  622. $coords2 = array_map(function($point) { return $point + 5; }, $coords);
  623. $conditions = array('location' => array('$near' => $coords));
  624. $query = new Query(compact('conditions') + array('model' => $this->_model));
  625. $result = $query->export($this->db);
  626. $this->assertEqual($result['conditions'], $conditions);
  627. $conditions = array('location' => array(
  628. '$within' => array('$box' => array($coords2, $coords))
  629. ));
  630. $query = new Query(compact('conditions') + array('model' => $this->_model));
  631. $result = $query->export($this->db);
  632. $this->assertEqual($conditions, $result['conditions']);
  633. }
  634. public function testSchemaCallback() {
  635. $schema = array('_id' => array('type' => 'id'), 'created' => array('type' => 'date'));
  636. $db = new MongoDb(array('autoConnect' => false, 'schema' => function() use ($schema) {
  637. return $schema;
  638. }));
  639. $this->assertEqual($schema, $db->describe(null)->fields());
  640. }
  641. }
  642. ?>