PageRenderTime 29ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/test/testsuite/generator/builder/om/GeneratedObjectTest.php

https://github.com/1989gaurav/Propel
PHP | 1338 lines | 896 code | 249 blank | 193 comment | 10 complexity | b0708a5935334b93eea783c8f6a71831 MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the Propel package.
  4. * For the full copyright and license information, please view the LICENSE
  5. * file that was distributed with this source code.
  6. *
  7. * @license MIT License
  8. */
  9. require_once dirname(__FILE__) . '/../../../../tools/helpers/bookstore/BookstoreEmptyTestBase.php';
  10. /**
  11. * Tests the generated Object classes.
  12. *
  13. * This test uses generated Bookstore classes to test the behavior of various
  14. * object operations. The _idea_ here is to test every possible generated method
  15. * from Object.tpl; if necessary, bookstore will be expanded to accommodate this.
  16. *
  17. * The database is relaoded before every test and flushed after every test. This
  18. * means that you can always rely on the contents of the databases being the same
  19. * for each test method in this class. See the BookstoreDataPopulator::populate()
  20. * method for the exact contents of the database.
  21. *
  22. * @see BookstoreDataPopulator
  23. * @author Hans Lellelid <hans@xmpl.org>
  24. * @package generator.builder.om
  25. */
  26. class GeneratedObjectTest extends BookstoreEmptyTestBase
  27. {
  28. protected function setUp()
  29. {
  30. parent::setUp();
  31. require_once dirname(__FILE__) . '/../../../../tools/helpers/bookstore/behavior/TestAuthor.php';
  32. }
  33. /**
  34. * Test saving an object after setting default values for it.
  35. */
  36. public function testSaveWithDefaultValues()
  37. {
  38. // From the schema.xml, I am relying on the following:
  39. // - that 'Penguin' is the default Name for a Publisher
  40. // - that 2001-01-01 is the default ReviewDate for a Review
  41. // 1) check regular values (VARCHAR)
  42. $pub = new Publisher();
  43. $pub->setName('Penguin');
  44. $pub->save();
  45. $this->assertTrue($pub->getId() !== null, "Expect Publisher to have been saved when default value set.");
  46. // 2) check date/time values
  47. $review = new Review();
  48. // note that this is different from how it's represented in schema, but should resolve to same unix timestamp
  49. $review->setReviewDate('2001-01-01');
  50. $this->assertTrue($review->isModified(), "Expect Review to have been marked 'modified' after default date/time value set.");
  51. }
  52. /**
  53. * Test isModified() to be false after setting default value second time
  54. */
  55. public function testDefaultValueSetTwice()
  56. {
  57. $pub = new Publisher();
  58. $pub->setName('Penguin');
  59. $pub->save();
  60. $pubId = $pub->getId();
  61. PublisherPeer::clearInstancePool();
  62. $pub2 = PublisherPeer::retrieveByPK($pubId);
  63. $pub2->setName('Penguin');
  64. $this->assertFalse($pub2->isModified(), "Expect Publisher to be not modified after setting default value second time.");
  65. }
  66. public function testHasApplyDefaultValues()
  67. {
  68. $this->assertTrue(method_exists('Publisher', 'applyDefaultValues'), 'Tables with default values should have an applyDefaultValues() method');
  69. $this->assertFalse(method_exists('Book', 'applyDefaultValues'), 'Tables with no default values should not have an applyDefaultValues() method');
  70. }
  71. /**
  72. * Test default return values.
  73. */
  74. public function testDefaultValues()
  75. {
  76. $r = new Review();
  77. $this->assertEquals('2001-01-01', $r->getReviewDate('Y-m-d'));
  78. $this->assertFalse($r->isModified(), "expected isModified() to be false");
  79. $acct = new BookstoreEmployeeAccount();
  80. $this->assertEquals(true, $acct->getEnabled());
  81. $this->assertFalse($acct->isModified());
  82. $acct->setLogin("testuser");
  83. $acct->setPassword("testpass");
  84. $this->assertTrue($acct->isModified());
  85. }
  86. /**
  87. * Tests the use of default expressions and the reloadOnInsert and reloadOnUpdate attributes.
  88. *
  89. * @link http://propel.phpdb.org/trac/ticket/378
  90. * @link http://propel.phpdb.org/trac/ticket/555
  91. */
  92. public function testDefaultExpresions()
  93. {
  94. if (Propel::getDb(BookstoreEmployeePeer::DATABASE_NAME) instanceof DBSqlite) {
  95. $this->markTestSkipped("Cannot test default expressions with SQLite");
  96. }
  97. $b = new Bookstore();
  98. $b->setStoreName("Foo!");
  99. $b->save();
  100. $employee = new BookstoreEmployee();
  101. $employee->setName("Johnny Walker");
  102. $acct = new BookstoreEmployeeAccount();
  103. $acct->setBookstoreEmployee($employee);
  104. $acct->setLogin("test-login");
  105. $this->assertNull($acct->getCreated(), "Expected created column to be NULL.");
  106. $this->assertNull($acct->getAuthenticator(), "Expected authenticator column to be NULL.");
  107. $acct->save();
  108. $acct = BookstoreEmployeeAccountPeer::retrieveByPK($acct->getEmployeeId());
  109. $this->assertNotNull($acct->getAuthenticator(), "Expected a valid (non-NULL) authenticator column after save.");
  110. $this->assertEquals('Password', $acct->getAuthenticator(), "Expected authenticator='Password' after save.");
  111. $this->assertNotNull($acct->getCreated(), "Expected a valid date after retrieving saved object.");
  112. $now = new DateTime("now");
  113. $this->assertEquals($now->format("Y-m-d"), $acct->getCreated("Y-m-d"));
  114. $acct->setCreated($now);
  115. $this->assertEquals($now->format("Y-m-d"), $acct->getCreated("Y-m-d"));
  116. // Unfortunately we can't really test the conjunction of reloadOnInsert and reloadOnUpdate when using just
  117. // default values. (At least not in a cross-db way.)
  118. }
  119. /**
  120. * Tests the use of default expressions and the reloadOnInsert attribute.
  121. *
  122. * @link http://propel.phpdb.org/trac/ticket/378
  123. * @link http://propel.phpdb.org/trac/ticket/555
  124. */
  125. public function testDefaultExpresions_ReloadOnInsert()
  126. {
  127. if (Propel::getDb(BookstoreEmployeePeer::DATABASE_NAME) instanceof DBSqlite) {
  128. $this->markTestSkipped("Cannot test default date expressions with SQLite");
  129. }
  130. // Create a new bookstore, contest, bookstore_contest, and bookstore_contest_entry
  131. $b = new Bookstore();
  132. $b->setStoreName("Barnes & Noble");
  133. $b->save();
  134. $c = new Contest();
  135. $c->setName("Bookathon Contest");
  136. $c->save();
  137. $bc = new BookstoreContest();
  138. $bc->setBookstore($b);
  139. $bc->setContest($c);
  140. $bc->save();
  141. $c = new Customer();
  142. $c->setName("Happy Customer");
  143. $c->save();
  144. $bce = new BookstoreContestEntry();
  145. $bce->setBookstore($b);
  146. $bce->setBookstoreContest($bc);
  147. $bce->setCustomer($c);
  148. $bce->save();
  149. $this->assertNotNull($bce->getEntryDate(), "Expected a non-null entry_date after save.");
  150. }
  151. /**
  152. * Tests the overriding reloadOnInsert at runtime.
  153. *
  154. * @link http://propel.phpdb.org/trac/ticket/378
  155. * @link http://propel.phpdb.org/trac/ticket/555
  156. */
  157. public function testDefaultExpresions_ReloadOnInsert_Override()
  158. {
  159. if (Propel::getDb(BookstoreEmployeePeer::DATABASE_NAME) instanceof DBSqlite) {
  160. $this->markTestSkipped("Cannot test default date expressions with SQLite");
  161. }
  162. // Create a new bookstore, contest, bookstore_contest, and bookstore_contest_entry
  163. $b = new Bookstore();
  164. $b->setStoreName("Barnes & Noble");
  165. $b->save();
  166. $c = new Contest();
  167. $c->setName("Bookathon Contest");
  168. $c->save();
  169. $bc = new BookstoreContest();
  170. $bc->setBookstore($b);
  171. $bc->setContest($c);
  172. $bc->save();
  173. $c = new Customer();
  174. $c->setName("Happy Customer");
  175. $c->save();
  176. $bce = new BookstoreContestEntry();
  177. $bce->setBookstore($b);
  178. $bce->setBookstoreContest($bc);
  179. $bce->setCustomer($c);
  180. $bce->save(null, $skipReload=true);
  181. $this->assertNull($bce->getEntryDate(), "Expected a NULL entry_date after save.");
  182. }
  183. /**
  184. * Tests the use of default expressions and the reloadOnUpdate attribute.
  185. *
  186. * @link http://propel.phpdb.org/trac/ticket/555
  187. */
  188. public function testDefaultExpresions_ReloadOnUpdate()
  189. {
  190. $b = new Bookstore();
  191. $b->setStoreName("Foo!");
  192. $b->save();
  193. $sale = new BookstoreSale();
  194. $sale->setBookstore(BookstorePeer::doSelectOne(new Criteria()));
  195. $sale->setSaleName("Spring Sale");
  196. $sale->save();
  197. // Expect that default values are set, but not default expressions
  198. $this->assertNull($sale->getDiscount(), "Expected discount to be NULL.");
  199. $sale->setSaleName("Winter Clearance");
  200. $sale->save();
  201. // Since reloadOnUpdate = true, we expect the discount to be set now.
  202. $this->assertNotNull($sale->getDiscount(), "Expected discount to be non-NULL after save.");
  203. }
  204. /**
  205. * Tests the overriding reloadOnUpdate at runtime.
  206. *
  207. * @link http://propel.phpdb.org/trac/ticket/378
  208. * @link http://propel.phpdb.org/trac/ticket/555
  209. */
  210. public function testDefaultExpresions_ReloadOnUpdate_Override()
  211. {
  212. $b = new Bookstore();
  213. $b->setStoreName("Foo!");
  214. $b->save();
  215. $sale = new BookstoreSale();
  216. $sale->setBookstore(BookstorePeer::doSelectOne(new Criteria()));
  217. $sale->setSaleName("Spring Sale");
  218. $sale->save();
  219. // Expect that default values are set, but not default expressions
  220. $this->assertNull($sale->getDiscount(), "Expected discount to be NULL.");
  221. $sale->setSaleName("Winter Clearance");
  222. $sale->save(null, $skipReload=true);
  223. // Since reloadOnUpdate = true, we expect the discount to be set now.
  224. $this->assertNull($sale->getDiscount(), "Expected NULL value for discount after save.");
  225. }
  226. /**
  227. * Testing creating & saving new object & instance pool.
  228. */
  229. public function testObjectInstances_New()
  230. {
  231. $emp = new BookstoreEmployee();
  232. $emp->setName(md5(microtime()));
  233. $emp->save();
  234. $id = $emp->getId();
  235. $retrieved = BookstoreEmployeePeer::retrieveByPK($id);
  236. $this->assertSame($emp, $retrieved, "Expected same object (from instance pool)");
  237. }
  238. /**
  239. *
  240. */
  241. public function testObjectInstances_Fkeys()
  242. {
  243. // Establish a relationship between one employee and account
  244. // and then change the employee_id and ensure that the account
  245. // is not pulling the old employee.
  246. $pub1 = new Publisher();
  247. $pub1->setName('Publisher 1');
  248. $pub1->save();
  249. $pub2 = new Publisher();
  250. $pub2->setName('Publisher 2');
  251. $pub2->save();
  252. $book = new Book();
  253. $book->setTitle("Book Title");
  254. $book->setISBN("1234");
  255. $book->setPublisher($pub1);
  256. $book->save();
  257. $this->assertSame($pub1, $book->getPublisher());
  258. // now change values behind the scenes
  259. $con = Propel::getConnection(BookstoreEmployeeAccountPeer::DATABASE_NAME);
  260. $con->exec("UPDATE " . BookPeer::TABLE_NAME . " SET "
  261. . " publisher_id = " . $pub2->getId()
  262. . " WHERE id = " . $book->getId());
  263. $book2 = BookPeer::retrieveByPK($book->getId());
  264. $this->assertSame($book, $book2, "Expected same book object instance");
  265. $this->assertEquals($pub1->getId(), $book->getPublisherId(), "Expected book to have OLD publisher id before reload()");
  266. $book->reload();
  267. $this->assertEquals($pub2->getId(), $book->getPublisherId(), "Expected book to have new publisher id");
  268. $this->assertSame($pub2, $book->getPublisher(), "Expected book to have new publisher object associated.");
  269. // Now let's set it back, just to be double sure ...
  270. $con->exec("UPDATE " . BookPeer::TABLE_NAME . " SET "
  271. . " publisher_id = " . $pub1->getId()
  272. . " WHERE id = " . $book->getId());
  273. $book->reload();
  274. $this->assertEquals($pub1->getId(), $book->getPublisherId(), "Expected book to have old publisher id (again).");
  275. $this->assertSame($pub1, $book->getPublisher(), "Expected book to have old publisher object associated (again).");
  276. }
  277. /**
  278. * Test the effect of typecast on primary key values and instance pool retrieval.
  279. */
  280. public function testObjectInstancePoolTypecasting()
  281. {
  282. $reader = new BookReader();
  283. $reader->setName("Tester");
  284. $reader->save();
  285. $readerId = $reader->getId();
  286. $book = new Book();
  287. $book->setTitle("BookTest");
  288. $book->setISBN("TEST");
  289. $book->save();
  290. $bookId = $book->getId();
  291. $opinion = new BookOpinion();
  292. $opinion->setBookId((string)$bookId);
  293. $opinion->setReaderId((string)$readerId);
  294. $opinion->setRating(5);
  295. $opinion->setRecommendToFriend(false);
  296. $opinion->save();
  297. $opinion2 = BookOpinionPeer::retrieveByPK($bookId, $readerId);
  298. $this->assertSame($opinion, $opinion2, "Expected same object to be retrieved from differently type-casted primary key values.");
  299. }
  300. /**
  301. * Test the reload() method.
  302. */
  303. public function testReload()
  304. {
  305. BookstoreDataPopulator::populate();
  306. $a = AuthorPeer::doSelectOne(new Criteria());
  307. $origName = $a->getFirstName();
  308. $a->setFirstName(md5(time()));
  309. $this->assertNotEquals($origName, $a->getFirstName());
  310. $this->assertTrue($a->isModified());
  311. $a->reload();
  312. $this->assertEquals($origName, $a->getFirstName());
  313. $this->assertFalse($a->isModified());
  314. }
  315. /**
  316. * Test reload(deep=true) method.
  317. */
  318. public function testReloadDeep()
  319. {
  320. BookstoreDataPopulator::populate();
  321. // arbitrary book
  322. $b = BookPeer::doSelectOne(new Criteria());
  323. // arbitrary, different author
  324. $c = new Criteria();
  325. $c->add(AuthorPeer::ID, $b->getAuthorId(), Criteria::NOT_EQUAL);
  326. $a = AuthorPeer::doSelectOne($c);
  327. $origAuthor = $b->getAuthor();
  328. $b->setAuthor($a);
  329. $this->assertNotEquals($origAuthor, $b->getAuthor(), "Expected just-set object to be different from obj from DB");
  330. $this->assertTrue($b->isModified());
  331. $b->reload($deep=true);
  332. $this->assertEquals($origAuthor, $b->getAuthor(), "Expected object in DB to be restored");
  333. $this->assertFalse($a->isModified());
  334. }
  335. /**
  336. * Test saving an object and getting correct number of affected rows from save().
  337. * This includes tests of cascading saves to fk-related objects.
  338. */
  339. public function testSaveReturnValues()
  340. {
  341. $author = new Author();
  342. $author->setFirstName("Mark");
  343. $author->setLastName("Kurlansky");
  344. // do not save
  345. $pub = new Publisher();
  346. $pub->setName("Penguin Books");
  347. // do not save
  348. $book = new Book();
  349. $book->setTitle("Salt: A World History");
  350. $book->setISBN("0142001619");
  351. $book->setAuthor($author);
  352. $book->setPublisher($pub);
  353. $affected = $book->save();
  354. $this->assertEquals(3, $affected, "Expected 3 affected rows when saving book + publisher + author.");
  355. // change nothing ...
  356. $affected = $book->save();
  357. $this->assertEquals(0, $affected, "Expected 0 affected rows when saving already-saved book.");
  358. // modify the book (UPDATE)
  359. $book->setTitle("Salt A World History");
  360. $affected = $book->save();
  361. $this->assertEquals(1, $affected, "Expected 1 affected row when saving modified book.");
  362. // modify the related author
  363. $author->setLastName("Kurlanski");
  364. $affected = $book->save();
  365. $this->assertEquals(1, $affected, "Expected 1 affected row when saving book with updated author.");
  366. // modify both the related author and the book
  367. $author->setLastName("Kurlansky");
  368. $book->setTitle("Salt: A World History");
  369. $affected = $book->save();
  370. $this->assertEquals(2, $affected, "Expected 2 affected rows when saving updated book with updated author.");
  371. }
  372. /**
  373. * Test deleting an object using the delete() method.
  374. */
  375. public function testDelete()
  376. {
  377. BookstoreDataPopulator::populate();
  378. // 1) grab an arbitrary object
  379. $book = BookPeer::doSelectOne(new Criteria());
  380. $bookId = $book->getId();
  381. // 2) delete it
  382. $book->delete();
  383. // 3) make sure it can't be save()d now that it's deleted
  384. try {
  385. $book->setTitle("Will Fail");
  386. $book->save();
  387. $this->fail("Expect an exception to be thrown when attempting to save() a deleted object.");
  388. } catch (PropelException $e) {}
  389. // 4) make sure that it doesn't exist in db
  390. $book = BookPeer::retrieveByPK($bookId);
  391. $this->assertNull($book, "Expect NULL from retrieveByPK on deleted Book.");
  392. }
  393. /**
  394. *
  395. */
  396. public function testNoColsModified()
  397. {
  398. $e1 = new BookstoreEmployee();
  399. $e1->setName('Employee 1');
  400. $e2 = new BookstoreEmployee();
  401. $e2->setName('Employee 2');
  402. $super = new BookstoreEmployee();
  403. // we don't know who the supervisor is yet
  404. $super->addSubordinate($e1);
  405. $super->addSubordinate($e2);
  406. $affected = $super->save();
  407. }
  408. /**
  409. * Tests new one-to-one functionality.
  410. */
  411. public function testOneToOne()
  412. {
  413. BookstoreDataPopulator::populate();
  414. $emp = BookstoreEmployeePeer::doSelectOne(new Criteria());
  415. $acct = new BookstoreEmployeeAccount();
  416. $acct->setBookstoreEmployee($emp);
  417. $acct->setLogin("testuser");
  418. $acct->setPassword("testpass");
  419. $this->assertSame($emp->getBookstoreEmployeeAccount(), $acct, "Expected same object instance.");
  420. }
  421. /**
  422. * Test the type sensitivity of the resturning columns.
  423. *
  424. */
  425. public function testTypeSensitive()
  426. {
  427. BookstoreDataPopulator::populate();
  428. $book = BookPeer::doSelectOne(new Criteria());
  429. $r = new Review();
  430. $r->setReviewedBy("testTypeSensitive Tester");
  431. $r->setReviewDate(time());
  432. $r->setBook($book);
  433. $r->setRecommended(true);
  434. $r->save();
  435. $id = $r->getId();
  436. unset($r);
  437. // clear the instance cache to force reload from database.
  438. ReviewPeer::clearInstancePool();
  439. BookPeer::clearInstancePool();
  440. // reload and verify that the types are the same
  441. $r2 = ReviewPeer::retrieveByPK($id);
  442. $this->assertInternalType('integer', $r2->getId(), "Expected getId() to return an integer.");
  443. $this->assertInternalType('string', $r2->getReviewedBy(), "Expected getReviewedBy() to return a string.");
  444. $this->assertInternalType('boolean', $r2->getRecommended(), "Expected getRecommended() to return a boolean.");
  445. $this->assertInstanceOf('Book', $r2->getBook(), "Expected getBook() to return a Book.");
  446. $this->assertInternalType('float', $r2->getBook()->getPrice(), "Expected Book->getPrice() to return a float.");
  447. $this->assertInstanceOf('DateTime', $r2->getReviewDate(null), "Expected Book->getReviewDate() to return a DateTime.");
  448. }
  449. /**
  450. * This is a test for expected exceptions when saving UNIQUE.
  451. * See http://propel.phpdb.org/trac/ticket/2
  452. */
  453. public function testSaveUnique()
  454. {
  455. // The whole test is in a transaction, but this test needs real transactions
  456. $this->con->commit();
  457. $emp = new BookstoreEmployee();
  458. $emp->setName(md5(microtime()));
  459. $acct = new BookstoreEmployeeAccount();
  460. $acct->setBookstoreEmployee($emp);
  461. $acct->setLogin("foo");
  462. $acct->setPassword("bar");
  463. $acct->save();
  464. // now attempt to create a new acct
  465. $acct2 = $acct->copy();
  466. try {
  467. $acct2->save();
  468. $this->fail("Expected PropelException in first attempt to save object with duplicate value for UNIQUE constraint.");
  469. } catch (Exception $x) {
  470. try {
  471. // attempt to save it again
  472. $acct3 = $acct->copy();
  473. $acct3->save();
  474. $this->fail("Expected PropelException in second attempt to save object with duplicate value for UNIQUE constraint.");
  475. } catch (Exception $x) {
  476. // this is expected.
  477. }
  478. // now let's double check that it can succeed if we're not violating the constraint.
  479. $acct3->setLogin("foo2");
  480. $acct3->save();
  481. }
  482. $this->con->beginTransaction();
  483. }
  484. public function testIsModifiedIsFalseForNewObjects()
  485. {
  486. $a = new Author();
  487. $this->assertFalse($a->isModified());
  488. }
  489. public function testIsModifiedIsTrueForNewObjectsWithModifications()
  490. {
  491. $a = new Author();
  492. $a->setFirstName('Foo');
  493. $this->assertTrue($a->isModified());
  494. }
  495. public function testIsModifiedIsFalseForNewObjectsWithNullModifications()
  496. {
  497. $a = new Author();
  498. $a->setFirstName(null);
  499. $this->assertFalse($a->isModified());
  500. }
  501. public function testIsModifiedIsFalseForObjectsAfterResetModified()
  502. {
  503. $a = new Author();
  504. $a->setFirstName('Foo');
  505. $a->resetModified();
  506. $this->assertFalse($a->isModified());
  507. }
  508. public function testIsModifiedIsFalseForSavedObjects()
  509. {
  510. $a = new Author();
  511. $a->setFirstName('Foo');
  512. $a->save();
  513. $this->assertFalse($a->isModified());
  514. }
  515. public function testIsModifiedIsTrueForSavedObjectsWithModifications()
  516. {
  517. $a = new Author();
  518. $a->save();
  519. $a->setFirstName('Foo');
  520. $this->assertTrue($a->isModified());
  521. }
  522. public function testIsModifiedIsFalseAfterSetToDefaultValueOnNewObject()
  523. {
  524. $p = new Publisher();
  525. $p->setName('Penguin'); // default column value
  526. $this->assertFalse($p->isModified());
  527. }
  528. public function testIsModifiedIsTrueAfterModifyingOnNonDefaultValueOnNewObject()
  529. {
  530. $p = new Publisher();
  531. $p->setName('Puffin Books');
  532. $this->assertTrue($p->isModified());
  533. }
  534. public function testIsModifiedIsTrueAfterSetToDefaultValueOnModifiedObject()
  535. {
  536. $p = new Publisher();
  537. $p->setName('Puffin Books');
  538. $p->resetModified();
  539. $p->setName('Penguin'); // default column value
  540. $this->assertTrue($p->isModified());
  541. }
  542. public function testIsModifiedIsFalseAfterChangingColumnTypeButNotValue()
  543. {
  544. $a = new Author();
  545. $a->setFirstName('1');
  546. $a->setAge(25);
  547. $a->resetModified();
  548. $a->setAge('25');
  549. $this->assertFalse($a->isModified());
  550. $a->setFirstName(1);
  551. $this->assertFalse($a->isModified());
  552. }
  553. public function testIsModifiedAndNullValues()
  554. {
  555. $a = new Author();
  556. $a->setFirstName("");
  557. $a->setAge(0);
  558. $a->save();
  559. $a->setFirstName(null);
  560. $this->assertTrue($a->isModified(), "Expected Author to be modified after changing empty string column value to NULL.");
  561. $a->setAge(null);
  562. $this->assertTrue($a->isModified(), "Expected Author to be modified after changing 0-value int column to NULL.");
  563. $a->save();
  564. $a->setFirstName('');
  565. $this->assertTrue($a->isModified(), "Expected Author to be modified after changing NULL column value to empty string.");
  566. $a->setAge(0);
  567. $this->assertTrue($a->isModified(), "Expected Author to be modified after changing NULL column to 0-value int.");
  568. }
  569. /**
  570. * Test the BaseObject#equals().
  571. */
  572. public function testEquals()
  573. {
  574. BookstoreDataPopulator::populate();
  575. $b = BookPeer::doSelectOne(new Criteria());
  576. $c = new Book();
  577. $c->setId($b->getId());
  578. $this->assertTrue($b->equals($c), "Expected Book objects to be equal()");
  579. $a = new Author();
  580. $a->setId($b->getId());
  581. $this->assertFalse($b->equals($a), "Expected Book and Author with same primary key NOT to match.");
  582. }
  583. /**
  584. * Test checking for non-default values.
  585. * @see http://propel.phpdb.org/trac/ticket/331
  586. */
  587. public function testHasOnlyDefaultValues()
  588. {
  589. $emp = new BookstoreEmployee();
  590. $emp->setName(md5(microtime()));
  591. $acct2 = new BookstoreEmployeeAccount();
  592. $acct = new BookstoreEmployeeAccount();
  593. $acct->setBookstoreEmployee($emp);
  594. $acct->setLogin("foo");
  595. $acct->setPassword("bar");
  596. $acct->save();
  597. $this->assertFalse($acct->isModified(), "Expected BookstoreEmployeeAccount NOT to be modified after save().");
  598. $acct->setEnabled(true);
  599. $acct->setPassword($acct2->getPassword());
  600. $this->assertTrue($acct->isModified(), "Expected BookstoreEmployeeAccount to be modified after setting default values.");
  601. $this->assertTrue($acct->hasOnlyDefaultValues(), "Expected BookstoreEmployeeAccount to not have only default values.");
  602. $acct->setPassword("bar");
  603. $this->assertFalse($acct->hasOnlyDefaultValues(), "Expected BookstoreEmployeeAccount to have at one non-default value after setting one value to non-default.");
  604. // Test a default date/time value
  605. $r = new Review();
  606. $r->setReviewDate(new DateTime("now"));
  607. $this->assertFalse($r->hasOnlyDefaultValues());
  608. }
  609. public function testDefaultFkColVal()
  610. {
  611. BookstoreDataPopulator::populate();
  612. $sale = new BookstoreSale();
  613. $this->assertEquals(1, $sale->getBookstoreId(), "Expected BookstoreSale object to have a default bookstore_id of 1.");
  614. $bookstore = BookstorePeer::doSelectOne(new Criteria());
  615. $sale->setBookstore($bookstore);
  616. $this->assertEquals($bookstore->getId(), $sale->getBookstoreId(), "Expected FK id to have changed when assigned a valid FK.");
  617. $sale->setBookstore(null);
  618. $this->assertEquals(1, $sale->getBookstoreId(), "Expected BookstoreSale object to have reset to default ID.");
  619. $sale->setPublisher(null);
  620. $this->assertEquals(null, $sale->getPublisherId(), "Expected BookstoreSale object to have reset to NULL publisher ID.");
  621. }
  622. public function testCountRefFk()
  623. {
  624. $book = new Book();
  625. $book->setTitle("Test Book");
  626. $book->setISBN("TT-EE-SS-TT");
  627. $num = 5;
  628. for ($i=2; $i < $num + 2; $i++) {
  629. $r = new Review();
  630. $r->setReviewedBy('Hans ' . $num);
  631. $dt = new DateTime("now");
  632. $dt->modify("-".$i." weeks");
  633. $r->setReviewDate($dt);
  634. $r->setRecommended(($i % 2) == 0);
  635. $book->addReview($r);
  636. }
  637. $this->assertEquals($num, $book->countReviews(), "Expected countReviews to return $num");
  638. $this->assertEquals($num, count($book->getReviews()), "Expected getReviews to return $num reviews");
  639. $book->save();
  640. BookPeer::clearInstancePool();
  641. ReviewPeer::clearInstancePool();
  642. $book = BookPeer::retrieveByPK($book->getId());
  643. $this->assertEquals($num, $book->countReviews(), "Expected countReviews() to return $num (after save)");
  644. $this->assertEquals($num, count($book->getReviews()), "Expected getReviews() to return $num (after save)");
  645. // Now set different criteria and expect different results
  646. $c = new Criteria();
  647. $c->add(ReviewPeer::RECOMMENDED, false);
  648. $this->assertEquals(floor($num/2), $book->countReviews($c), "Expected " . floor($num/2) . " results from countReviews(recomm=false)");
  649. // Change Criteria, run again -- expect different.
  650. $c = new Criteria();
  651. $c->add(ReviewPeer::RECOMMENDED, true);
  652. $this->assertEquals(ceil($num/2), count($book->getReviews($c)), "Expected " . ceil($num/2) . " results from getReviews(recomm=true)");
  653. $this->assertEquals($num, $book->countReviews(), "Expected countReviews to return $num with new empty Criteria");
  654. }
  655. /**
  656. * Test copyInto method.
  657. */
  658. public function testCopyInto_Deep()
  659. {
  660. BookstoreDataPopulator::populate();
  661. // Test a "normal" object
  662. $c = new Criteria();
  663. $c->add(BookPeer::TITLE, 'Harry%', Criteria::LIKE);
  664. $book = BookPeer::doSelectOne($c);
  665. $reviews = $book->getReviews();
  666. $b2 = $book->copy(true);
  667. $this->assertInstanceOf('Book', $b2);
  668. $this->assertNull($b2->getId());
  669. $r2 = $b2->getReviews();
  670. $this->assertEquals(count($reviews), count($r2));
  671. // Test a one-to-one object
  672. $emp = BookstoreEmployeePeer::doSelectOne(new Criteria());
  673. $e2 = $emp->copy(true);
  674. $this->assertInstanceOf('BookstoreEmployee', $e2);
  675. $this->assertNull($e2->getId());
  676. $this->assertEquals($emp->getBookstoreEmployeeAccount()->getLogin(), $e2->getBookstoreEmployeeAccount()->getLogin());
  677. }
  678. /**
  679. * Test copying when an object has composite primary key.
  680. * @link http://propel.phpdb.org/trac/ticket/618
  681. */
  682. public function testCopy_CompositePK()
  683. {
  684. $br = new BookReader();
  685. $br->setName("TestReader");
  686. $br->save();
  687. $br->copy();
  688. $b = new Book();
  689. $b->setTitle("TestBook");
  690. $b->setISBN("XX-XX-XX-XX");
  691. $b->save();
  692. $op = new BookOpinion();
  693. $op->setBookReader($br);
  694. $op->setBook($b);
  695. $op->setRating(10);
  696. $op->setRecommendToFriend(true);
  697. $op->save();
  698. $br2 = $br->copy(true);
  699. $this->assertNull($br2->getId());
  700. $opinions = $br2->getBookOpinions();
  701. $this->assertEquals(1, count($opinions), "Expected to have a related BookOpinion after copy()");
  702. // We DO expect the reader_id to be null
  703. $this->assertNull($opinions[0]->getReaderId());
  704. // but we DO NOT expect the book_id to be null
  705. $this->assertEquals($op->getBookId(), $opinions[0]->getBookId());
  706. }
  707. public function testToArray()
  708. {
  709. $b = new Book();
  710. $b->setTitle('Don Juan');
  711. $arr1 = $b->toArray();
  712. $expectedKeys = array(
  713. 'Id',
  714. 'Title',
  715. 'ISBN',
  716. 'Price',
  717. 'PublisherId',
  718. 'AuthorId'
  719. );
  720. $this->assertEquals($expectedKeys, array_keys($arr1), 'toArray() returns an associative array with BasePeer::TYPE_PHPNAME keys by default');
  721. $this->assertEquals('Don Juan', $arr1['Title'], 'toArray() returns an associative array representation of the object');
  722. }
  723. public function testToArrayKeyType()
  724. {
  725. $b = new Book();
  726. $b->setTitle('Don Juan');
  727. $arr1 = $b->toArray(BasePeer::TYPE_COLNAME);
  728. $expectedKeys = array(
  729. BookPeer::ID,
  730. BookPeer::TITLE,
  731. BookPeer::ISBN,
  732. BookPeer::PRICE,
  733. BookPeer::PUBLISHER_ID,
  734. BookPeer::AUTHOR_ID
  735. );
  736. $this->assertEquals($expectedKeys, array_keys($arr1), 'toArray() accepts a $keyType parameter to change the result keys');
  737. $this->assertEquals('Don Juan', $arr1[BookPeer::TITLE], 'toArray() returns an associative array representation of the object');
  738. }
  739. /**
  740. * Test the toArray() method with new lazyLoad param.
  741. * @link http://propel.phpdb.org/trac/ticket/527
  742. */
  743. public function testToArrayLazyLoad()
  744. {
  745. BookstoreDataPopulator::populate();
  746. $c = new Criteria();
  747. $c->add(MediaPeer::COVER_IMAGE, null, Criteria::NOT_EQUAL);
  748. $c->add(MediaPeer::EXCERPT, null, Criteria::NOT_EQUAL);
  749. $m = MediaPeer::doSelectOne($c);
  750. if ($m === null) {
  751. $this->fail("Test requires at least one media row w/ cover_image and excerpt NOT NULL");
  752. }
  753. $arr1 = $m->toArray(BasePeer::TYPE_COLNAME);
  754. $this->assertNotNull($arr1[MediaPeer::COVER_IMAGE]);
  755. $this->assertInternalType('resource', $arr1[MediaPeer::COVER_IMAGE]);
  756. $arr2 = $m->toArray(BasePeer::TYPE_COLNAME, false);
  757. $this->assertNull($arr2[MediaPeer::COVER_IMAGE]);
  758. $this->assertNull($arr2[MediaPeer::EXCERPT]);
  759. $diffKeys = array_keys(array_diff($arr1, $arr2));
  760. $expectedDiff = array(MediaPeer::COVER_IMAGE, MediaPeer::EXCERPT);
  761. $this->assertEquals($expectedDiff, $diffKeys);
  762. }
  763. public function testToArrayIncludesForeignObjects()
  764. {
  765. BookstoreDataPopulator::populate();
  766. BookPeer::clearInstancePool();
  767. AuthorPeer::clearInstancePool();
  768. PublisherPeer::clearInstancePool();
  769. $c = new Criteria();
  770. $c->add(BookPeer::TITLE, 'Don Juan');
  771. $books = BookPeer::doSelectJoinAuthor($c);
  772. $book = $books[0];
  773. $arr1 = $book->toArray(BasePeer::TYPE_PHPNAME, null, array(), true);
  774. $expectedKeys = array(
  775. 'Id',
  776. 'Title',
  777. 'ISBN',
  778. 'Price',
  779. 'PublisherId',
  780. 'AuthorId',
  781. 'Author'
  782. );
  783. $this->assertEquals($expectedKeys, array_keys($arr1), 'toArray() can return sub arrays for hydrated related objects');
  784. $this->assertEquals('George', $arr1['Author']['FirstName'], 'toArray() can return sub arrays for hydrated related objects');
  785. $c = new Criteria();
  786. $c->add(BookPeer::TITLE, 'Don Juan');
  787. $books = BookPeer::doSelectJoinAll($c);
  788. $book = $books[0];
  789. $arr2 = $book->toArray(BasePeer::TYPE_PHPNAME, null, array(), true);
  790. $expectedKeys = array(
  791. 'Id',
  792. 'Title',
  793. 'ISBN',
  794. 'Price',
  795. 'PublisherId',
  796. 'AuthorId',
  797. 'Publisher',
  798. 'Author'
  799. );
  800. $this->assertEquals($expectedKeys, array_keys($arr2), 'toArray() can return sub arrays for hydrated related objects');
  801. }
  802. public function testToArrayIncludesForeignReferrers()
  803. {
  804. $a1 = new Author();
  805. $a1->setFirstName('Leo');
  806. $a1->setLastName('Tolstoi');
  807. $arr = $a1->toArray(BasePeer::TYPE_PHPNAME, null, array(), true);
  808. $this->assertFalse(array_key_exists('Books', $arr));
  809. $b1 = new Book();
  810. $b1->setTitle('War and Peace');
  811. $b2 = new Book();
  812. $b2->setTitle('Anna Karenina');
  813. $a1->addBook($b1);
  814. $a1->addBook($b2);
  815. $arr = $a1->toArray(BasePeer::TYPE_PHPNAME, null, array(), true);
  816. $this->assertTrue(array_key_exists('Books', $arr));
  817. $this->assertEquals(2, count($arr['Books']));
  818. $this->assertEquals('War and Peace', $arr['Books']['Book_0']['Title']);
  819. $this->assertEquals('Anna Karenina', $arr['Books']['Book_1']['Title']);
  820. $this->assertEquals('*RECURSION*', $arr['Books']['Book_0']['Author']);
  821. }
  822. /**
  823. * Test regexp validator for ticket:542
  824. * @link http://propel.phpdb.org/trac/ticket/542
  825. */
  826. public function testRegexValidator()
  827. {
  828. $b = new Bookstore();
  829. $b->setWebsite("http://this.is.valid.com/foo.bar");
  830. $res = $b->validate();
  831. $this->assertTrue($res, "Expected URL to validate");
  832. }
  833. /**
  834. * Test that setting the auto-increment primary key will result in exception.
  835. */
  836. public function testSettingAutoIncrementPK()
  837. {
  838. // The whole test is in a transaction, but this test needs real transactions
  839. $this->con->commit();
  840. $b = new Bookstore();
  841. $b->setId(1);
  842. $b->setStoreName("Test");
  843. try {
  844. $b->save();
  845. $this->fail("Expected setting auto-increment primary key to result in Exception");
  846. } catch (Exception $x) {
  847. $this->assertInstanceOf('PropelException', $x);
  848. }
  849. // ... but we should silently ignore NULL values, since these are really
  850. // the same as "not set" in PHP world.
  851. $b = new Bookstore();
  852. $b->setId(null);
  853. $b->setStoreName("Test2");
  854. try {
  855. $b->save();
  856. } catch (Exception $x) {
  857. $this->fail("Expected no exception when setting auto-increment primary key to NULL");
  858. }
  859. // success ...
  860. $this->con->beginTransaction();
  861. }
  862. /**
  863. * Checks wether we are allowed to specify the primary key on a
  864. * table with allowPkInsert=true set
  865. *
  866. * saves the object, gets it from data-source again and then compares
  867. * them for equality (thus the instance pool is also checked)
  868. */
  869. public function testAllowPkInsertOnIdMethodNativeTable()
  870. {
  871. $cu = new Customer;
  872. $cu->setPrimaryKey(100000);
  873. $cu->save();
  874. $this->assertEquals(100000, $cu->getPrimaryKey());
  875. $cu2 = CustomerPeer::retrieveByPk(100000);
  876. $this->assertSame($cu, $cu2);
  877. }
  878. /**
  879. * Checks if it is allowed to save new, empty objects with a auto increment column
  880. */
  881. public function testAllowEmptyWithAutoIncrement()
  882. {
  883. $bookreader = new BookReader();
  884. $bookreader->save();
  885. $this->assertFalse($bookreader->isNew() );
  886. }
  887. /**
  888. * Test foreign key relationships based on references to unique cols but not PK.
  889. * @link http://propel.phpdb.org/trac/ticket/691
  890. */
  891. public function testUniqueFkRel()
  892. {
  893. $employee = new BookstoreEmployee();
  894. $employee->setName("Johnny Walker");
  895. $acct = new BookstoreEmployeeAccount();
  896. $acct->setBookstoreEmployee($employee);
  897. $acct->setLogin("test-login");
  898. $acct->save();
  899. $acctId = $acct->getEmployeeId();
  900. $al = new AcctAuditLog();
  901. $al->setBookstoreEmployeeAccount($acct);
  902. $al->save();
  903. $alId = $al->getId();
  904. BookstoreEmployeePeer::clearInstancePool();
  905. BookstoreEmployeeAccountPeer::clearInstancePool();
  906. AcctAuditLogPeer::clearInstancePool();
  907. $al2 = AcctAuditLogPeer::retrieveByPK($alId);
  908. /* @var $al2 AcctAuditLog */
  909. $mapacct = $al2->getBookstoreEmployeeAccount();
  910. $lookupacct = BookstoreEmployeeAccountPeer::retrieveByPK($acctId);
  911. $logs = $lookupacct->getAcctAuditLogs();
  912. $this->assertTrue(count($logs) == 1, "Expected 1 audit log result.");
  913. $this->assertEquals($logs[0]->getId(), $al->getId(), "Expected returned audit log to match created audit log.");
  914. }
  915. public function testIsPrimaryKeyNull()
  916. {
  917. $b = new Book();
  918. $this->assertTrue($b->isPrimaryKeyNull());
  919. $b->setPrimaryKey(123);
  920. $this->assertFalse($b->isPrimaryKeyNull());
  921. $b->setPrimaryKey(null);
  922. $this->assertTrue($b->isPrimaryKeyNull());
  923. }
  924. public function testIsPrimaryKeyNullCompmosite()
  925. {
  926. $b = new BookOpinion();
  927. $this->assertTrue($b->isPrimaryKeyNull());
  928. $b->setPrimaryKey(array(123, 456));
  929. $this->assertFalse($b->isPrimaryKeyNull());
  930. $b->setPrimaryKey(array(123, null));
  931. $this->assertFalse($b->isPrimaryKeyNull());
  932. $b->setPrimaryKey(array(null, 456));
  933. $this->assertFalse($b->isPrimaryKeyNull());
  934. $b->setPrimaryKey(array(null, null));
  935. $this->assertTrue($b->isPrimaryKeyNull());
  936. }
  937. public function testAddToStringDefault()
  938. {
  939. $this->assertTrue(method_exists('Author', '__toString'), 'addPrimaryString() adds a __toString() method even if no column has the primaryString attribute');
  940. $author = new Author();
  941. $author->setFirstName('Leo');
  942. $author->setLastName('Tolstoi');
  943. $expected = <<<EOF
  944. Id: null
  945. FirstName: Leo
  946. LastName: Tolstoi
  947. Email: null
  948. Age: null
  949. EOF;
  950. $this->assertEquals($expected, (string) $author, 'addPrimaryString() adds a __toString() method returning the YAML representation of the object where no column is defined as primaryString');
  951. }
  952. public function testAddToStringPrimaryString()
  953. {
  954. $this->assertTrue(method_exists('Book', '__toString'), 'addPrimaryString() adds a __toString() method if a column has the primaryString attribute');
  955. $book = new Book();
  956. $book->setTitle('foo');
  957. $this->assertEquals('foo', (string) $book, 'addPrimaryString() adds a __toString() method returning the value of the the first column where primaryString is true');
  958. }
  959. public function testPreInsert()
  960. {
  961. $author = new TestAuthor();
  962. $author->setFirstName("bogus");
  963. $author->setLastName("Lastname");
  964. $author->save();
  965. $this->assertEquals('PreInsertedFirstname', $author->getFirstName());
  966. }
  967. public function testPreUpdate()
  968. {
  969. $author = new TestAuthor();
  970. $author->setFirstName("bogus");
  971. $author->setLastName("Lastname");
  972. $author->save();
  973. $author->setNew(false);
  974. $author->save();
  975. $this->assertEquals('PreUpdatedFirstname', $author->getFirstName());
  976. }
  977. public function testPostInsert()
  978. {
  979. $author = new TestAuthor();
  980. $author->setFirstName("bogus");
  981. $author->setLastName("Lastname");
  982. $author->save();
  983. $this->assertEquals('PostInsertedLastName', $author->getLastName());
  984. }
  985. public function testPostUpdate()
  986. {
  987. $author = new TestAuthor();
  988. $author->setFirstName("bogus");
  989. $author->setLastName("Lastname");
  990. $author->save();
  991. $author->setNew(false);
  992. $author->save();
  993. $this->assertEquals('PostUpdatedLastName', $author->getLastName());
  994. }
  995. public function testPreSave()
  996. {
  997. $author = new TestAuthor();
  998. $author->setFirstName("bogus");
  999. $author->setLastName("Lastname");
  1000. $author->save();
  1001. $this->assertEquals('pre@save.com', $author->getEmail());
  1002. }
  1003. public function testPreSaveFalse()
  1004. {
  1005. $con = Propel::getConnection(AuthorPeer::DATABASE_NAME);
  1006. $author = new TestAuthorSaveFalse();
  1007. $author->setFirstName("bogus");
  1008. $author->setLastName("Lastname");
  1009. $res = $author->save($con);
  1010. $this->assertEquals(0, $res);
  1011. $this->assertEquals('pre@save.com', $author->getEmail());
  1012. $this->assertNotEquals(115, $author->getAge());
  1013. $this->assertTrue($author->isNew());
  1014. $this->assertEquals(1, $con->getNestedTransactionCount());
  1015. }
  1016. public function testPostSave()
  1017. {
  1018. $author = new TestAuthor();
  1019. $author->setFirstName("bogus");
  1020. $author->setLastName("Lastname");
  1021. $author->save();
  1022. $this->assertEquals(115, $author->getAge());
  1023. }
  1024. public function testPreDelete()
  1025. {
  1026. $author = new TestAuthor();
  1027. $author->setFirstName("bogus");
  1028. $author->setLastName("Lastname");
  1029. $author->save();
  1030. $author->delete();
  1031. $this->assertEquals("Pre-Deleted", $author->getFirstName());
  1032. }
  1033. public function testPreDeleteFalse()
  1034. {
  1035. $con = Propel::getConnection(AuthorPeer::DATABASE_NAME);
  1036. $author = new TestAuthorDeleteFalse();
  1037. $author->setFirstName("bogus");
  1038. $author->setLastName("Lastname");
  1039. $author->save($con);
  1040. $author->delete($con);
  1041. $this->assertEquals("Pre-Deleted", $author->getFirstName());
  1042. $this->assertNotEquals("Post-Deleted", $author->getLastName());
  1043. $this->assertFalse($author->isDeleted());
  1044. $this->assertEquals(1, $con->getNestedTransactionCount());
  1045. }
  1046. public function testPostDelete()
  1047. {
  1048. $author = new TestAuthor();
  1049. $author->setFirstName("bogus");
  1050. $author->setLastName("Lastname");
  1051. $author->save();
  1052. $author->delete();
  1053. $this->assertEquals("Post-Deleted", $author->getLastName());
  1054. }
  1055. public function testMagicVirtualColumnGetter()
  1056. {
  1057. $book = new Book();
  1058. $book->setVirtualColumn('Foo', 'bar');
  1059. $this->assertEquals('bar', $book->getFoo(), 'generated __call() catches getters for virtual columns');
  1060. $book = new Book();
  1061. $book->setVirtualColumn('foo', 'bar');
  1062. $this->assertEquals('bar', $book->getFoo(), 'generated __call() catches getters for virtual columns starting with a lowercase character');
  1063. }
  1064. /**
  1065. * @expectedException PropelException
  1066. */
  1067. public function testMagicCallUndefined()
  1068. {
  1069. $book = new Book();
  1070. $book->fooMethodName();
  1071. }
  1072. public static function conditionsForTestReadOnly()
  1073. {
  1074. return array(
  1075. array('reload'),
  1076. array('delete'),
  1077. array('save'),
  1078. array('doSave'),
  1079. );
  1080. }
  1081. /**
  1082. * @dataProvider conditionsForTestReadOnly
  1083. */
  1084. public function testReadOnly($method)
  1085. {
  1086. $cv = new ContestView();
  1087. $this->assertFalse(method_exists($cv, $method), 'readOnly tables end up with no ' . $method . ' method in the generated object class');
  1088. }
  1089. }