MongoCollectionTest.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. <?php
  2. namespace Alcaeus\MongoDbAdapter\Tests;
  3. use MongoDB\Driver\ReadPreference;
  4. /**
  5. * @author alcaeus <alcaeus@alcaeus.org>
  6. */
  7. class MongoCollectionTest extends TestCase
  8. {
  9. public function testGetNestedCollections()
  10. {
  11. $collection = $this->getCollection()->foo->bar;
  12. $this->assertSame('mongo-php-adapter.test.foo.bar', (string) $collection);
  13. }
  14. public function testCreateRecord()
  15. {
  16. $collection = $this->getCollection();
  17. $expected = [
  18. 'ok' => 1.0,
  19. 'n' => 0,
  20. 'err' => null,
  21. 'errmsg' => null,
  22. ];
  23. $document = ['foo' => 'bar'];
  24. $this->assertSame($expected, $collection->insert($document));
  25. $this->assertInstanceOf('MongoId', $document['_id']);
  26. $id = (string) $document['_id'];
  27. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  28. $this->assertSame(1, $newCollection->count());
  29. $object = $newCollection->findOne();
  30. $this->assertNotNull($object);
  31. $this->assertAttributeInstanceOf('MongoDB\BSON\ObjectID', '_id', $object);
  32. $this->assertSame($id, (string) $object->_id);
  33. $this->assertObjectHasAttribute('foo', $object);
  34. $this->assertAttributeSame('bar', 'foo', $object);
  35. }
  36. public function testUnacknowledgedWrite()
  37. {
  38. $document = ['foo' => 'bar'];
  39. $this->assertTrue($this->getCollection()->insert($document, ['w' => 0]));
  40. }
  41. public function testInsertMany()
  42. {
  43. $expected = [
  44. 'connectionId' => 0,
  45. 'n' => 0,
  46. 'syncMillis' => 0,
  47. 'writtenTo' => null,
  48. 'err' => null,
  49. 'errmsg' => null
  50. ];
  51. $documents = [
  52. ['foo' => 'bar'],
  53. ['bar' => 'foo']
  54. ];
  55. $this->assertSame($expected, $this->getCollection()->batchInsert($documents));
  56. foreach ($documents as $document) {
  57. $this->assertInstanceOf('MongoId', $document['_id']);
  58. }
  59. }
  60. public function testInsertManyWithNonNumericKeys()
  61. {
  62. $expected = [
  63. 'connectionId' => 0,
  64. 'n' => 0,
  65. 'syncMillis' => 0,
  66. 'writtenTo' => null,
  67. 'err' => null,
  68. 'errmsg' => null
  69. ];
  70. $documents = [
  71. 'a' => ['foo' => 'bar'],
  72. 'b' => ['bar' => 'foo']
  73. ];
  74. $this->assertSame($expected, $this->getCollection()->batchInsert($documents));
  75. }
  76. public function testUpdateOne()
  77. {
  78. $document = ['foo' => 'bar'];
  79. $this->getCollection()->insert($document);
  80. // Unset ID to re-insert
  81. unset($document['_id']);
  82. $this->getCollection()->insert($document);
  83. $expected = [
  84. 'ok' => 1.0,
  85. 'nModified' => 1,
  86. 'n' => 1,
  87. 'err' => null,
  88. 'errmsg' => null,
  89. 'updatedExisting' => true,
  90. ];
  91. $result = $this->getCollection()->update(['foo' => 'bar'], ['$set' => ['foo' => 'foo']]);
  92. $this->assertSame($expected, $result);
  93. $this->assertSame(1, $this->getCheckDatabase()->selectCollection('test')->count(['foo' => 'foo']));
  94. }
  95. public function testUpdateMany()
  96. {
  97. $document = ['change' => true, 'foo' => 'bar'];
  98. $this->getCollection()->insert($document);
  99. unset($document['_id']);
  100. $this->getCollection()->insert($document);
  101. $document = ['change' => true, 'foo' => 'foo'];
  102. $this->getCollection()->insert($document);
  103. $expected = [
  104. 'ok' => 1.0,
  105. 'nModified' => 2,
  106. 'n' => 3,
  107. 'err' => null,
  108. 'errmsg' => null,
  109. 'updatedExisting' => true,
  110. ];
  111. $result = $this->getCollection()->update(['change' => true], ['$set' => ['foo' => 'foo']], ['multiple' => true]);
  112. $this->assertSame($expected, $result);
  113. $this->assertSame(3, $this->getCheckDatabase()->selectCollection('test')->count(['foo' => 'foo']));
  114. }
  115. public function testUnacknowledgedUpdate()
  116. {
  117. $document = ['foo' => 'bar'];
  118. $this->getCollection()->insert($document);
  119. unset($document['_id']);
  120. $this->getCollection()->insert($document);
  121. $this->assertTrue($this->getCollection()->update($document, ['$set' => ['foo' => 'foo']], ['w' => 0]));
  122. }
  123. public function testRemoveMultiple()
  124. {
  125. $document = ['change' => true, 'foo' => 'bar'];
  126. $this->getCollection()->insert($document);
  127. unset($document['_id']);
  128. $this->getCollection()->insert($document);
  129. $document = ['change' => true, 'foo' => 'foo'];
  130. $this->getCollection()->insert($document);
  131. $expected = [
  132. 'ok' => 1.0,
  133. 'n' => 2,
  134. 'err' => null,
  135. 'errmsg' => null,
  136. ];
  137. $result = $this->getCollection()->remove(['foo' => 'bar']);
  138. $this->assertSame($expected, $result);
  139. $this->assertSame(1, $this->getCheckDatabase()->selectCollection('test')->count());
  140. }
  141. public function testRemoveSingle()
  142. {
  143. $document = ['change' => true, 'foo' => 'bar'];
  144. $this->getCollection()->insert($document);
  145. unset($document['_id']);
  146. $this->getCollection()->insert($document);
  147. unset($document['_id']);
  148. $this->getCollection()->insert($document);
  149. $expected = [
  150. 'ok' => 1.0,
  151. 'n' => 1,
  152. 'err' => null,
  153. 'errmsg' => null,
  154. ];
  155. $result = $this->getCollection()->remove(['foo' => 'bar'], ['justOne' => true]);
  156. $this->assertSame($expected, $result);
  157. $this->assertSame(2, $this->getCheckDatabase()->selectCollection('test')->count());
  158. }
  159. public function testRemoveUnacknowledged()
  160. {
  161. $document = ['change' => true, 'foo' => 'bar'];
  162. $this->getCollection()->insert($document);
  163. unset($document['_id']);
  164. $this->getCollection()->insert($document);
  165. unset($document['_id']);
  166. $this->getCollection()->insert($document);
  167. $this->assertTrue($this->getCollection()->remove(['foo' => 'bar'], ['w' => 0]));
  168. }
  169. public function testFindReturnsCursor()
  170. {
  171. $this->prepareData();
  172. $collection = $this->getCollection();
  173. $this->assertInstanceOf('MongoCursor', $collection->find());
  174. }
  175. public function testCount()
  176. {
  177. $this->prepareData();
  178. $collection = $this->getCollection();
  179. $this->assertSame(3, $collection->count());
  180. $this->assertSame(2, $collection->count(['foo' => 'bar']));
  181. }
  182. public function testFindOne()
  183. {
  184. $this->prepareData();
  185. $document = $this->getCollection()->findOne(['foo' => 'foo'], ['_id' => false]);
  186. $this->assertSame(['foo' => 'foo'], $document);
  187. }
  188. public function testDistinct()
  189. {
  190. $this->prepareData();
  191. $values = $this->getCollection()->distinct('foo');
  192. $this->assertInternalType('array', $values);
  193. sort($values);
  194. $this->assertEquals(['bar', 'foo'], $values);
  195. }
  196. public function testDistinctWithQuery()
  197. {
  198. $this->prepareData();
  199. $values = $this->getCollection()->distinct('foo', ['foo' => 'bar']);
  200. $this->assertInternalType('array', $values);
  201. $this->assertEquals(['bar'], $values);
  202. }
  203. public function testAggregate()
  204. {
  205. $collection = $this->getCollection();
  206. $this->prepareData();
  207. $pipeline = [
  208. [
  209. '$group' => [
  210. '_id' => '$foo',
  211. 'count' => [ '$sum' => 1 ],
  212. ],
  213. ],
  214. [
  215. '$sort' => ['_id' => 1]
  216. ]
  217. ];
  218. $result = $collection->aggregate($pipeline);
  219. $this->assertInternalType('array', $result);
  220. $this->assertArrayHasKey('result', $result);
  221. $this->assertEquals([
  222. ['_id' => 'bar', 'count' => 2],
  223. ['_id' => 'foo', 'count' => 1],
  224. ], $result['result']);
  225. }
  226. public function testAggregateCursor()
  227. {
  228. $collection = $this->getCollection();
  229. $this->prepareData();
  230. $pipeline = [
  231. [
  232. '$group' => [
  233. '_id' => '$foo',
  234. 'count' => [ '$sum' => 1 ],
  235. ],
  236. ],
  237. [
  238. '$sort' => ['_id' => 1]
  239. ]
  240. ];
  241. $cursor = $collection->aggregateCursor($pipeline);
  242. $this->assertInstanceOf('MongoCommandCursor', $cursor);
  243. $this->assertEquals([
  244. ['_id' => 'bar', 'count' => 2],
  245. ['_id' => 'foo', 'count' => 1],
  246. ], iterator_to_array($cursor));
  247. }
  248. public function testReadPreference()
  249. {
  250. $collection = $this->getCollection();
  251. $this->assertSame(['type' => \MongoClient::RP_PRIMARY], $collection->getReadPreference());
  252. $this->assertFalse($collection->getSlaveOkay());
  253. $this->assertTrue($collection->setReadPreference(\MongoClient::RP_SECONDARY, ['a' => 'b']));
  254. $this->assertSame(['type' => \MongoClient::RP_SECONDARY, 'tagsets' => ['a' => 'b']], $collection->getReadPreference());
  255. $this->assertTrue($collection->getSlaveOkay());
  256. // Only way to check whether options are passed down is through debugInfo
  257. $writeConcern = $collection->getCollection()->__debugInfo()['readPreference'];
  258. $this->assertSame(ReadPreference::RP_SECONDARY, $writeConcern->getMode());
  259. $this->assertSame(['a' => 'b'], $writeConcern->getTagSets());
  260. $this->assertTrue($collection->setSlaveOkay(true));
  261. $this->assertSame(['type' => \MongoClient::RP_SECONDARY_PREFERRED, 'tagsets' => ['a' => 'b']], $collection->getReadPreference());
  262. $this->assertTrue($collection->setSlaveOkay(false));
  263. $this->assertSame(['type' => \MongoClient::RP_PRIMARY], $collection->getReadPreference());
  264. }
  265. public function testReadPreferenceIsInherited()
  266. {
  267. $database = $this->getDatabase();
  268. $database->setReadPreference(\MongoClient::RP_SECONDARY, ['a' => 'b']);
  269. $collection = $database->selectCollection('test');
  270. $this->assertSame(['type' => \MongoClient::RP_SECONDARY, 'tagsets' => ['a' => 'b']], $collection->getReadPreference());
  271. }
  272. public function testWriteConcern()
  273. {
  274. $collection = $this->getCollection();
  275. $this->assertSame(['w' => 1, 'wtimeout' => 0], $collection->getWriteConcern());
  276. $this->assertSame(1, $collection->w);
  277. $this->assertSame(0, $collection->wtimeout);
  278. $this->assertTrue($collection->setWriteConcern('majority', 100));
  279. $this->assertSame(['w' => 'majority', 'wtimeout' => 100], $collection->getWriteConcern());
  280. $collection->w = 2;
  281. $this->assertSame(['w' => 2, 'wtimeout' => 100], $collection->getWriteConcern());
  282. $collection->wtimeout = -1;
  283. $this->assertSame(['w' => 2, 'wtimeout' => 0], $collection->getWriteConcern());
  284. // Only way to check whether options are passed down is through debugInfo
  285. $writeConcern = $collection->getCollection()->__debugInfo()['writeConcern'];
  286. $this->assertSame(2, $writeConcern->getW());
  287. $this->assertSame(0, $writeConcern->getWtimeout());
  288. }
  289. public function testWriteConcernIsInherited()
  290. {
  291. $database = $this->getDatabase();
  292. $database->setWriteConcern('majority', 100);
  293. $collection = $database->selectCollection('test');
  294. $this->assertSame(['w' => 'majority', 'wtimeout' => 100], $collection->getWriteConcern());
  295. }
  296. public function testSaveInsert()
  297. {
  298. $collection = $this->getCollection();
  299. $document = ['foo' => 'bar'];
  300. $collection->save($document);
  301. $this->assertInstanceOf('MongoId', $document['_id']);
  302. $id = (string) $document['_id'];
  303. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  304. $this->assertSame(1, $newCollection->count());
  305. $object = $newCollection->findOne();
  306. $this->assertNotNull($object);
  307. $this->assertAttributeInstanceOf('MongoDB\BSON\ObjectID', '_id', $object);
  308. $this->assertSame($id, (string) $object->_id);
  309. $this->assertObjectHasAttribute('foo', $object);
  310. $this->assertAttributeSame('bar', 'foo', $object);
  311. }
  312. public function testRemoveOne()
  313. {
  314. $id = '54203e08d51d4a1f868b456e';
  315. $collection = $this->getCollection();
  316. $document = ['_id' => new \MongoId($id), 'foo' => 'bar'];
  317. $collection->insert($document);
  318. $collection->remove(['_id' => new \MongoId($id)]);
  319. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  320. $this->assertSame(0, $newCollection->count());
  321. }
  322. public function testSaveUpdate()
  323. {
  324. $id = '54203e08d51d4a1f868b456e';
  325. $collection = $this->getCollection();
  326. $insertDocument = ['_id' => new \MongoId($id), 'foo' => 'bar'];
  327. $saveDocument = ['_id' => new \MongoId($id), 'foo' => 'foo'];
  328. $collection->insert($insertDocument);
  329. $collection->save($saveDocument);
  330. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  331. $this->assertSame(1, $newCollection->count());
  332. $object = $newCollection->findOne();
  333. $this->assertNotNull($object);
  334. $this->assertAttributeInstanceOf('MongoDB\BSON\ObjectID', '_id', $object);
  335. $this->assertSame($id, (string) $object->_id);
  336. $this->assertObjectHasAttribute('foo', $object);
  337. $this->assertAttributeSame('foo', 'foo', $object);
  338. }
  339. public function testGetDBRef()
  340. {
  341. $collection = $this->getCollection();
  342. $insertDocument = ['_id' => 1, 'foo' => 'bar'];
  343. $collection->insert($insertDocument);
  344. $document = $collection->getDBRef([
  345. '$ref' => 'test',
  346. '$id' => 1,
  347. ]);
  348. $this->assertEquals($insertDocument, $document);
  349. }
  350. public function testCreateDBRef()
  351. {
  352. $collection = $this->getCollection();
  353. $reference = $collection->createDBRef(['_id' => 'foo']);
  354. $this->assertSame(
  355. [
  356. '$ref' => 'test',
  357. '$id' => 'foo',
  358. ],
  359. $reference
  360. );
  361. }
  362. public function testCreateIndex()
  363. {
  364. $collection = $this->getCollection();
  365. $collection->createIndex(['foo' => 1]);
  366. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  367. $iterator = $newCollection->listIndexes();
  368. $indexes = iterator_to_array($iterator);
  369. $this->assertCount(2, $indexes);
  370. $index = $indexes[1];
  371. $this->assertSame(['foo' => 1], $index->getKey());
  372. $this->assertSame('mongo-php-adapter.test', $index->getNamespace());
  373. }
  374. public function testEnsureIndex()
  375. {
  376. $collection = $this->getCollection();
  377. $this->assertTrue($collection->ensureIndex(['bar' => 1], ['unique' => true]));
  378. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  379. $indexes = iterator_to_array($newCollection->listIndexes());
  380. $this->assertCount(2, $indexes);
  381. $index = $indexes[1];
  382. $this->assertSame(['bar' => 1], $index->getKey());
  383. $this->assertTrue($index->isUnique());
  384. $this->assertSame('mongo-php-adapter.test', $index->getNamespace());
  385. }
  386. public function testDeleteIndexUsingIndexName()
  387. {
  388. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  389. $newCollection->createIndex(['bar' => 1], ['name' => 'bar']);
  390. $expected = [
  391. 'nIndexesWas' => 2,
  392. 'ok' => 1.0,
  393. ];
  394. $this->assertSame($expected, $this->getCollection()->deleteIndex('bar'));
  395. $this->assertCount(1, iterator_to_array($newCollection->listIndexes()));
  396. }
  397. public function testDeleteIndexUsingKeys()
  398. {
  399. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  400. $newCollection->createIndex(['bar' => 1]);
  401. $expected = [
  402. 'nIndexesWas' => 2,
  403. 'ok' => 1.0,
  404. ];
  405. $this->assertSame($expected, $this->getcollection()->deleteIndex(['bar' => 1]));
  406. $this->assertCount(1, iterator_to_array($newCollection->listIndexes()));
  407. }
  408. public function testDeleteIndexes()
  409. {
  410. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  411. $newCollection->createIndex(['bar' => 1]);
  412. $expected = [
  413. 'nIndexesWas' => 2,
  414. 'msg' => 'non-_id indexes dropped for collection',
  415. 'ok' => 1.0,
  416. ];
  417. $this->assertSame($expected, $this->getcollection()->deleteIndexes());
  418. $this->assertCount(1, iterator_to_array($newCollection->listIndexes())); // ID index is present by default
  419. }
  420. public function testGetIndexInfo()
  421. {
  422. $collection = $this->getCollection();
  423. $collection->createIndex(['foo' => 1]);
  424. $expected = [
  425. [
  426. 'v' => 1,
  427. 'key' => ['_id' => 1],
  428. 'name' => '_id_',
  429. 'ns' => 'mongo-php-adapter.test',
  430. ],
  431. [
  432. 'v' => 1,
  433. 'key' => ['foo' => 1],
  434. 'name' => 'foo_1',
  435. 'ns' => 'mongo-php-adapter.test',
  436. ],
  437. ];
  438. $this->assertSame(
  439. $expected,
  440. $collection->getIndexInfo()
  441. );
  442. }
  443. public function testFindAndModifyUpdate()
  444. {
  445. $id = '54203e08d51d4a1f868b456e';
  446. $collection = $this->getCollection();
  447. $document = ['_id' => new \MongoId($id), 'foo' => 'bar'];
  448. $collection->insert($document);
  449. $document = $collection->findAndModify(
  450. ['_id' => new \MongoId($id)],
  451. ['$set' => ['foo' => 'foo']]
  452. );
  453. $this->assertSame('bar', $document['foo']);
  454. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  455. $this->assertSame(1, $newCollection->count());
  456. $object = $newCollection->findOne();
  457. $this->assertNotNull($object);
  458. $this->assertAttributeSame('foo', 'foo', $object);
  459. }
  460. public function testFindAndModifyUpdateReturnNew()
  461. {
  462. $id = '54203e08d51d4a1f868b456e';
  463. $collection = $this->getCollection();
  464. $document = ['_id' => new \MongoId($id), 'foo' => 'bar'];
  465. $collection->insert($document);
  466. $document = $collection->findAndModify(
  467. ['_id' => new \MongoId($id)],
  468. ['$set' => ['foo' => 'foo']],
  469. null,
  470. ['new' => true]
  471. );
  472. $this->assertSame('foo', $document['foo']);
  473. }
  474. public function testFindAndModifyWithFields()
  475. {
  476. $id = '54203e08d51d4a1f868b456e';
  477. $collection = $this->getCollection();
  478. $document = [
  479. '_id' => new \MongoId($id),
  480. 'foo' => 'bar',
  481. 'bar' => 'foo',
  482. ];
  483. $collection->insert($document);
  484. $document = $collection->findAndModify(
  485. ['_id' => new \MongoId($id)],
  486. ['$set' => ['foo' => 'foo']],
  487. ['foo' => true]
  488. );
  489. $this->assertArrayNotHasKey('bar', $document);
  490. $this->assertArrayHasKey('foo', $document);
  491. }
  492. public function testGroup()
  493. {
  494. $collection = $this->getCollection();
  495. $document1 = ['a' => 2];
  496. $collection->insert($document1);
  497. $document2 = ['b' => 5];
  498. $collection->insert($document2);
  499. $document3 = ['a' => 1];
  500. $collection->insert($document3);
  501. $keys = [];
  502. $initial = ["count" => 0];
  503. $reduce = "function (obj, prev) { prev.count++; }";
  504. $condition = ['condition' => ["a" => [ '$gt' => 1]]];
  505. $result = $collection->group($keys, $initial, $reduce, $condition);
  506. $this->assertArraySubset(
  507. [
  508. 'retval' => [['count' => 1.0]],
  509. 'count' => 1.0,
  510. 'keys' => 1,
  511. 'ok' => 1.0,
  512. ],
  513. $result
  514. );
  515. }
  516. public function testFindAndModifyRemove()
  517. {
  518. $id = '54203e08d51d4a1f868b456e';
  519. $collection = $this->getCollection();
  520. $document = ['_id' => new \MongoId($id), 'foo' => 'bar'];
  521. $collection->insert($document);
  522. $document = $collection->findAndModify(
  523. ['_id' => new \MongoId($id)],
  524. null,
  525. null,
  526. ['remove' => true]
  527. );
  528. $this->assertEquals('bar', $document['foo']);
  529. $newCollection = $this->getCheckDatabase()->selectCollection('test');
  530. $this->assertSame(0, $newCollection->count());
  531. }
  532. public function testValidate()
  533. {
  534. $collection = $this->getCollection();
  535. $document = ['foo' => 'bar'];
  536. $collection->insert($document);
  537. $result = $collection->validate();
  538. $this->assertArraySubset(
  539. [
  540. 'ns' => 'mongo-php-adapter.test',
  541. 'nrecords' => 1,
  542. 'nIndexes' => 1,
  543. 'keysPerIndex' => ['mongo-php-adapter.test.$_id_' => 1],
  544. 'valid' => true,
  545. 'errors' => [],
  546. 'warning' => 'Some checks omitted for speed. use {full:true} option to do more thorough scan.',
  547. 'ok' => 1.0
  548. ],
  549. $result
  550. );
  551. }
  552. public function testDrop()
  553. {
  554. $document = ['foo' => 'bar'];
  555. $this->getCollection()->insert($document);
  556. $expected = [
  557. 'ns' => (string) $this->getCollection(),
  558. 'nIndexesWas' => 1,
  559. 'ok' => 1.0
  560. ];
  561. $this->assertSame($expected, $this->getCollection()->drop());
  562. }
  563. }