ResultSetTest.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.0.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\ORM;
  16. use Cake\Core\Configure;
  17. use Cake\Datasource\ConnectionManager;
  18. use Cake\ORM\Entity;
  19. use Cake\ORM\Query;
  20. use Cake\ORM\ResultSet;
  21. use Cake\ORM\Table;
  22. use Cake\ORM\TableRegistry;
  23. use Cake\TestSuite\TestCase;
  24. /**
  25. * ResultSet test case.
  26. */
  27. class ResultSetTest extends TestCase {
  28. public $fixtures = ['core.articles', 'core.comments'];
  29. /**
  30. * setup
  31. *
  32. * @return void
  33. */
  34. public function setUp() {
  35. parent::setUp();
  36. $this->connection = ConnectionManager::get('test');
  37. $this->table = new Table([
  38. 'table' => 'articles',
  39. 'connection' => $this->connection,
  40. ]);
  41. $this->fixtureData = [
  42. ['id' => 1, 'author_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y'],
  43. ['id' => 2, 'author_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y'],
  44. ['id' => 3, 'author_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y']
  45. ];
  46. }
  47. /**
  48. * Test that result sets can be rewound and re-used.
  49. *
  50. * @return void
  51. */
  52. public function testRewind() {
  53. $query = $this->table->find('all');
  54. $results = $query->all();
  55. $first = $second = [];
  56. foreach ($results as $result) {
  57. $first[] = $result;
  58. }
  59. foreach ($results as $result) {
  60. $second[] = $result;
  61. }
  62. $this->assertEquals($first, $second);
  63. }
  64. /**
  65. * Test that streaming results cannot be rewound
  66. *
  67. * @return void
  68. */
  69. public function testRewindStreaming() {
  70. $query = $this->table->find('all')->bufferResults(false);
  71. $results = $query->all();
  72. $first = $second = [];
  73. foreach ($results as $result) {
  74. $first[] = $result;
  75. }
  76. $this->setExpectedException('Cake\Database\Exception');
  77. foreach ($results as $result) {
  78. $second[] = $result;
  79. }
  80. }
  81. /**
  82. * An integration test for testing serialize and unserialize features.
  83. *
  84. * Compare the results of a query with the results iterated, with
  85. * those of a different query that have been serialized/unserialized.
  86. *
  87. * @return void
  88. */
  89. public function testSerialization() {
  90. $query = $this->table->find('all');
  91. $results = $query->all();
  92. $expected = $results->toArray();
  93. $query2 = $this->table->find('all');
  94. $results2 = $query2->all();
  95. $serialized = serialize($results2);
  96. $outcome = unserialize($serialized);
  97. $this->assertEquals($expected, $outcome->toArray());
  98. }
  99. /**
  100. * Test iteration after serialization
  101. *
  102. * @return void
  103. */
  104. public function testIteratorAfterSerializationNoHydration() {
  105. $query = $this->table->find('all')->hydrate(false);
  106. $results = unserialize(serialize($query->all()));
  107. // Use a loop to test Iterator implementation
  108. foreach ($results as $i => $row) {
  109. $this->assertEquals($this->fixtureData[$i], $row, "Row $i does not match");
  110. }
  111. }
  112. /**
  113. * Test iteration after serialization
  114. *
  115. * @return void
  116. */
  117. public function testIteratorAfterSerializationHydrated() {
  118. $query = $this->table->find('all');
  119. $results = unserialize(serialize($query->all()));
  120. // Use a loop to test Iterator implementation
  121. foreach ($results as $i => $row) {
  122. $expected = new \Cake\ORM\Entity($this->fixtureData[$i]);
  123. $expected->isNew(false);
  124. $expected->source($this->table->alias());
  125. $expected->clean();
  126. $this->assertEquals($expected, $row, "Row $i does not match");
  127. }
  128. }
  129. /**
  130. * Test converting resultsets into json
  131. *
  132. * @return void
  133. */
  134. public function testJsonSerialize() {
  135. $query = $this->table->find('all');
  136. $results = $query->all();
  137. $expected = json_encode($this->fixtureData);
  138. $this->assertEquals($expected, json_encode($results));
  139. }
  140. /**
  141. * Test first() method with a statement backed result set.
  142. *
  143. * @return void
  144. */
  145. public function testFirst() {
  146. $query = $this->table->find('all');
  147. $results = $query->hydrate(false)->all();
  148. $row = $results->first();
  149. $this->assertEquals($this->fixtureData[0], $row);
  150. $row = $results->first();
  151. $this->assertEquals($this->fixtureData[0], $row);
  152. }
  153. /**
  154. * Test first() method with a result set that has been unserialized
  155. *
  156. * @return void
  157. */
  158. public function testFirstAfterSerialize() {
  159. $query = $this->table->find('all');
  160. $results = $query->hydrate(false)->all();
  161. $results = unserialize(serialize($results));
  162. $row = $results->first();
  163. $this->assertEquals($this->fixtureData[0], $row);
  164. $this->assertSame($row, $results->first());
  165. $this->assertSame($row, $results->first());
  166. }
  167. /**
  168. * Test the countable interface.
  169. *
  170. * @return void
  171. */
  172. public function testCount() {
  173. $query = $this->table->find('all');
  174. $results = $query->all();
  175. $this->assertCount(3, $results, 'Should be countable and 3');
  176. }
  177. /**
  178. * Test the countable interface after unserialize
  179. *
  180. * @return void
  181. */
  182. public function testCountAfterSerialize() {
  183. $query = $this->table->find('all');
  184. $results = $query->all();
  185. $results = unserialize(serialize($results));
  186. $this->assertCount(3, $results, 'Should be countable and 3');
  187. }
  188. /**
  189. * Integration test to show methods from CollectionTrait work
  190. *
  191. * @return void
  192. */
  193. public function testGroupBy() {
  194. $query = $this->table->find('all');
  195. $results = $query->all()->groupBy('author_id')->toArray();
  196. $options = [
  197. 'markNew' => false,
  198. 'markClean' => true,
  199. 'source' => $this->table->alias()
  200. ];
  201. $expected = [
  202. 1 => [
  203. new Entity($this->fixtureData[0], $options),
  204. new Entity($this->fixtureData[2], $options)
  205. ],
  206. 3 => [
  207. new Entity($this->fixtureData[1], $options),
  208. ]
  209. ];
  210. $this->assertEquals($expected, $results);
  211. }
  212. /**
  213. * Tests __debugInfo
  214. *
  215. * @return void
  216. */
  217. public function testDebugInfo() {
  218. $query = $this->table->find('all');
  219. $results = $query->all();
  220. $expected = [
  221. 'query' => $query,
  222. 'items' => $results->toArray()
  223. ];
  224. $this->assertSame($expected, $results->__debugInfo());
  225. }
  226. /**
  227. * Test that eagerLoader leaves empty associations unpopulated.
  228. *
  229. * @return void
  230. */
  231. public function testBelongsToEagerLoaderLeavesEmptyAssocation() {
  232. $comments = TableRegistry::get('Comments');
  233. $comments->belongsTo('Articles');
  234. // Clear the articles table so we can trigger an empty belongsTo
  235. $this->table->deleteAll([]);
  236. $comment = $comments->find()->where(['Comments.id' => 1])
  237. ->contain(['Articles'])
  238. ->hydrate(false)
  239. ->first();
  240. $this->assertEquals(1, $comment['id']);
  241. $this->assertNotEmpty($comment['comment']);
  242. $this->assertNull($comment['article']);
  243. $comment = $comments->get(1, ['contain' => ['Articles']]);
  244. $this->assertNull($comment->article);
  245. $this->assertEquals(1, $comment->id);
  246. $this->assertNotEmpty($comment->comment);
  247. }
  248. /**
  249. * Test that eagerLoader leaves empty associations unpopulated.
  250. *
  251. * @return void
  252. */
  253. public function testHasOneEagerLoaderLeavesEmptyAssocation() {
  254. $this->table->hasOne('Comments');
  255. // Clear the comments table so we can trigger an empty hasOne.
  256. $comments = TableRegistry::get('Comments');
  257. $comments->deleteAll([]);
  258. $article = $this->table->get(1, ['contain' => ['Comments']]);
  259. $this->assertNull($article->comment);
  260. $this->assertEquals(1, $article->id);
  261. $this->assertNotEmpty($article->title);
  262. $article = $this->table->find()->where(['articles.id' => 1])
  263. ->contain(['Comments'])
  264. ->hydrate(false)
  265. ->first();
  266. $this->assertNull($article['comment']);
  267. $this->assertEquals(1, $article['id']);
  268. $this->assertNotEmpty($article['title']);
  269. }
  270. }