PageRenderTime 70ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/propel_15/vendor/propel/test/testsuite/generator/builder/om/GeneratedObjectTest.php

http://github.com/eventhorizonpl/forked-php-orm-benchmark
PHP | 1364 lines | 875 code | 264 blank | 225 comment | 10 complexity | f60244b6c6d96dffd169b03da852f1c5 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0
  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 '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 '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. * Test the behavior of date/time/values.
  228. * This requires that the model was built with propel.useDateTimeClass=true.
  229. */
  230. public function testTemporalValues_PreEpoch()
  231. {
  232. $r = new Review();
  233. $preEpochDate = new DateTime('1602-02-02');
  234. $r->setReviewDate($preEpochDate);
  235. $this->assertEquals('1602-02-02', $r->getReviewDate(null)->format("Y-m-d"));
  236. $r->setReviewDate('1702-02-02');
  237. $this->assertTrue($r->isModified());
  238. $this->assertEquals('1702-02-02', $r->getReviewDate(null)->format("Y-m-d"));
  239. // Now test for setting null
  240. $r->setReviewDate(null);
  241. $this->assertNull($r->getReviewDate());
  242. }
  243. /**
  244. * Test setting invalid date/time.
  245. */
  246. public function testSetTemporalValue_Invalid()
  247. {
  248. $this->markTestSkipped();
  249. // FIXME - Figure out why this doesn't work (causes a PHP ERROR instead of throwing Exception) in
  250. // the Phing+PHPUnit context
  251. $r = new Review();
  252. try {
  253. $r->setReviewDate("Invalid Date");
  254. $this->fail("Expected PropelException when setting date column w/ invalid date");
  255. } catch (PropelException $x) {
  256. print "Caught expected PropelException: " . $x->__toString();
  257. }
  258. }
  259. /**
  260. * Test setting TIMESTAMP columns w/ unix int timestamp.
  261. */
  262. public function testTemporalValues_Unix()
  263. {
  264. $store = new Bookstore();
  265. $store->setStoreName("test");
  266. $store->setStoreOpenTime(strtotime('12:55'));
  267. $store->save();
  268. $this->assertEquals('12:55', $store->getStoreOpenTime(null)->format('H:i'));
  269. $acct = new BookstoreEmployeeAccount();
  270. $acct->setCreated(time());
  271. $this->assertEquals(date('Y-m-d H:i'), $acct->getCreated('Y-m-d H:i'));
  272. $review = new Review();
  273. $review->setReviewDate(time());
  274. $this->assertEquals(date('Y-m-d'), $review->getReviewDate('Y-m-d'));
  275. }
  276. /**
  277. * Test setting empty temporal values.
  278. * @link http://propel.phpdb.org/trac/ticket/586
  279. */
  280. public function testTemporalValues_Empty()
  281. {
  282. $review = new Review();
  283. $review->setReviewDate('');
  284. $this->assertNull($review->getReviewDate());
  285. }
  286. /**
  287. * Test setting TIME columns.
  288. */
  289. public function testTemporalValues_TimeSetting()
  290. {
  291. $store = new Bookstore();
  292. $store->setStoreName("test");
  293. $store->setStoreOpenTime("12:55");
  294. $store->save();
  295. $store = new Bookstore();
  296. $store->setStoreName("test2");
  297. $store->setStoreOpenTime(new DateTime("12:55"));
  298. $store->save();
  299. }
  300. /**
  301. * Test setting TIME columns.
  302. */
  303. public function testTemporalValues_DateSetting()
  304. {
  305. BookstoreDataPopulator::populate();
  306. $r = new Review();
  307. $r->setBook(BookPeer::doSelectOne(new Criteria()));
  308. $r->setReviewDate(new DateTime('1999-12-20'));
  309. $r->setReviewedBy("Hans");
  310. $r->setRecommended(false);
  311. $r->save();
  312. }
  313. /**
  314. * Testing creating & saving new object & instance pool.
  315. */
  316. public function testObjectInstances_New()
  317. {
  318. $emp = new BookstoreEmployee();
  319. $emp->setName(md5(microtime()));
  320. $emp->save();
  321. $id = $emp->getId();
  322. $retrieved = BookstoreEmployeePeer::retrieveByPK($id);
  323. $this->assertSame($emp, $retrieved, "Expected same object (from instance pool)");
  324. }
  325. /**
  326. *
  327. */
  328. public function testObjectInstances_Fkeys()
  329. {
  330. // Establish a relationship between one employee and account
  331. // and then change the employee_id and ensure that the account
  332. // is not pulling the old employee.
  333. $pub1 = new Publisher();
  334. $pub1->setName('Publisher 1');
  335. $pub1->save();
  336. $pub2 = new Publisher();
  337. $pub2->setName('Publisher 2');
  338. $pub2->save();
  339. $book = new Book();
  340. $book->setTitle("Book Title");
  341. $book->setISBN("1234");
  342. $book->setPublisher($pub1);
  343. $book->save();
  344. $this->assertSame($pub1, $book->getPublisher());
  345. // now change values behind the scenes
  346. $con = Propel::getConnection(BookstoreEmployeeAccountPeer::DATABASE_NAME);
  347. $con->exec("UPDATE " . BookPeer::TABLE_NAME . " SET "
  348. . " publisher_id = " . $pub2->getId()
  349. . " WHERE id = " . $book->getId());
  350. $book2 = BookPeer::retrieveByPK($book->getId());
  351. $this->assertSame($book, $book2, "Expected same book object instance");
  352. $this->assertEquals($pub1->getId(), $book->getPublisherId(), "Expected book to have OLD publisher id before reload()");
  353. $book->reload();
  354. $this->assertEquals($pub2->getId(), $book->getPublisherId(), "Expected book to have new publisher id");
  355. $this->assertSame($pub2, $book->getPublisher(), "Expected book to have new publisher object associated.");
  356. // Now let's set it back, just to be double sure ...
  357. $con->exec("UPDATE " . BookPeer::TABLE_NAME . " SET "
  358. . " publisher_id = " . $pub1->getId()
  359. . " WHERE id = " . $book->getId());
  360. $book->reload();
  361. $this->assertEquals($pub1->getId(), $book->getPublisherId(), "Expected book to have old publisher id (again).");
  362. $this->assertSame($pub1, $book->getPublisher(), "Expected book to have old publisher object associated (again).");
  363. }
  364. /**
  365. * Test the effect of typecast on primary key values and instance pool retrieval.
  366. */
  367. public function testObjectInstancePoolTypecasting()
  368. {
  369. $reader = new BookReader();
  370. $reader->setName("Tester");
  371. $reader->save();
  372. $readerId = $reader->getId();
  373. $book = new Book();
  374. $book->setTitle("BookTest");
  375. $book->setISBN("TEST");
  376. $book->save();
  377. $bookId = $book->getId();
  378. $opinion = new BookOpinion();
  379. $opinion->setBookId((string)$bookId);
  380. $opinion->setReaderId((string)$readerId);
  381. $opinion->setRating(5);
  382. $opinion->setRecommendToFriend(false);
  383. $opinion->save();
  384. $opinion2 = BookOpinionPeer::retrieveByPK($bookId, $readerId);
  385. $this->assertSame($opinion, $opinion2, "Expected same object to be retrieved from differently type-casted primary key values.");
  386. }
  387. /**
  388. * Test the reload() method.
  389. */
  390. public function testReload()
  391. {
  392. BookstoreDataPopulator::populate();
  393. $a = AuthorPeer::doSelectOne(new Criteria());
  394. $origName = $a->getFirstName();
  395. $a->setFirstName(md5(time()));
  396. $this->assertNotEquals($origName, $a->getFirstName());
  397. $this->assertTrue($a->isModified());
  398. $a->reload();
  399. $this->assertEquals($origName, $a->getFirstName());
  400. $this->assertFalse($a->isModified());
  401. }
  402. /**
  403. * Test reload(deep=true) method.
  404. */
  405. public function testReloadDeep()
  406. {
  407. BookstoreDataPopulator::populate();
  408. // arbitrary book
  409. $b = BookPeer::doSelectOne(new Criteria());
  410. // arbitrary, different author
  411. $c = new Criteria();
  412. $c->add(AuthorPeer::ID, $b->getAuthorId(), Criteria::NOT_EQUAL);
  413. $a = AuthorPeer::doSelectOne($c);
  414. $origAuthor = $b->getAuthor();
  415. $b->setAuthor($a);
  416. $this->assertNotEquals($origAuthor, $b->getAuthor(), "Expected just-set object to be different from obj from DB");
  417. $this->assertTrue($b->isModified());
  418. $b->reload($deep=true);
  419. $this->assertEquals($origAuthor, $b->getAuthor(), "Expected object in DB to be restored");
  420. $this->assertFalse($a->isModified());
  421. }
  422. /**
  423. * Test saving an object and getting correct number of affected rows from save().
  424. * This includes tests of cascading saves to fk-related objects.
  425. */
  426. public function testSaveReturnValues()
  427. {
  428. $author = new Author();
  429. $author->setFirstName("Mark");
  430. $author->setLastName("Kurlansky");
  431. // do not save
  432. $pub = new Publisher();
  433. $pub->setName("Penguin Books");
  434. // do not save
  435. $book = new Book();
  436. $book->setTitle("Salt: A World History");
  437. $book->setISBN("0142001619");
  438. $book->setAuthor($author);
  439. $book->setPublisher($pub);
  440. $affected = $book->save();
  441. $this->assertEquals(3, $affected, "Expected 3 affected rows when saving book + publisher + author.");
  442. // change nothing ...
  443. $affected = $book->save();
  444. $this->assertEquals(0, $affected, "Expected 0 affected rows when saving already-saved book.");
  445. // modify the book (UPDATE)
  446. $book->setTitle("Salt A World History");
  447. $affected = $book->save();
  448. $this->assertEquals(1, $affected, "Expected 1 affected row when saving modified book.");
  449. // modify the related author
  450. $author->setLastName("Kurlanski");
  451. $affected = $book->save();
  452. $this->assertEquals(1, $affected, "Expected 1 affected row when saving book with updated author.");
  453. // modify both the related author and the book
  454. $author->setLastName("Kurlansky");
  455. $book->setTitle("Salt: A World History");
  456. $affected = $book->save();
  457. $this->assertEquals(2, $affected, "Expected 2 affected rows when saving updated book with updated author.");
  458. }
  459. /**
  460. * Test deleting an object using the delete() method.
  461. */
  462. public function testDelete()
  463. {
  464. BookstoreDataPopulator::populate();
  465. // 1) grab an arbitrary object
  466. $book = BookPeer::doSelectOne(new Criteria());
  467. $bookId = $book->getId();
  468. // 2) delete it
  469. $book->delete();
  470. // 3) make sure it can't be save()d now that it's deleted
  471. try {
  472. $book->setTitle("Will Fail");
  473. $book->save();
  474. $this->fail("Expect an exception to be thrown when attempting to save() a deleted object.");
  475. } catch (PropelException $e) {}
  476. // 4) make sure that it doesn't exist in db
  477. $book = BookPeer::retrieveByPK($bookId);
  478. $this->assertNull($book, "Expect NULL from retrieveByPK on deleted Book.");
  479. }
  480. /**
  481. *
  482. */
  483. public function testNoColsModified()
  484. {
  485. $e1 = new BookstoreEmployee();
  486. $e1->setName('Employee 1');
  487. $e2 = new BookstoreEmployee();
  488. $e2->setName('Employee 2');
  489. $super = new BookstoreEmployee();
  490. // we don't know who the supervisor is yet
  491. $super->addSubordinate($e1);
  492. $super->addSubordinate($e2);
  493. $affected = $super->save();
  494. }
  495. /**
  496. * Tests new one-to-one functionality.
  497. */
  498. public function testOneToOne()
  499. {
  500. BookstoreDataPopulator::populate();
  501. $emp = BookstoreEmployeePeer::doSelectOne(new Criteria());
  502. $acct = new BookstoreEmployeeAccount();
  503. $acct->setBookstoreEmployee($emp);
  504. $acct->setLogin("testuser");
  505. $acct->setPassword("testpass");
  506. $this->assertSame($emp->getBookstoreEmployeeAccount(), $acct, "Expected same object instance.");
  507. }
  508. /**
  509. * Test the type sensitivity of the resturning columns.
  510. *
  511. */
  512. public function testTypeSensitive()
  513. {
  514. BookstoreDataPopulator::populate();
  515. $book = BookPeer::doSelectOne(new Criteria());
  516. $r = new Review();
  517. $r->setReviewedBy("testTypeSensitive Tester");
  518. $r->setReviewDate(time());
  519. $r->setBook($book);
  520. $r->setRecommended(true);
  521. $r->save();
  522. $id = $r->getId();
  523. unset($r);
  524. // clear the instance cache to force reload from database.
  525. ReviewPeer::clearInstancePool();
  526. BookPeer::clearInstancePool();
  527. // reload and verify that the types are the same
  528. $r2 = ReviewPeer::retrieveByPK($id);
  529. $this->assertType('integer', $r2->getId(), "Expected getId() to return an integer.");
  530. $this->assertType('string', $r2->getReviewedBy(), "Expected getReviewedBy() to return a string.");
  531. $this->assertType('boolean', $r2->getRecommended(), "Expected getRecommended() to return a boolean.");
  532. $this->assertType('Book', $r2->getBook(), "Expected getBook() to return a Book.");
  533. $this->assertType('float', $r2->getBook()->getPrice(), "Expected Book->getPrice() to return a float.");
  534. $this->assertType('DateTime', $r2->getReviewDate(null), "Expected Book->getReviewDate() to return a DateTime.");
  535. }
  536. /**
  537. * This is a test for expected exceptions when saving UNIQUE.
  538. * See http://propel.phpdb.org/trac/ticket/2
  539. */
  540. public function testSaveUnique()
  541. {
  542. // The whole test is in a transaction, but this test needs real transactions
  543. $this->con->commit();
  544. $emp = new BookstoreEmployee();
  545. $emp->setName(md5(microtime()));
  546. $acct = new BookstoreEmployeeAccount();
  547. $acct->setBookstoreEmployee($emp);
  548. $acct->setLogin("foo");
  549. $acct->setPassword("bar");
  550. $acct->save();
  551. // now attempt to create a new acct
  552. $acct2 = $acct->copy();
  553. try {
  554. $acct2->save();
  555. $this->fail("Expected PropelException in first attempt to save object with duplicate value for UNIQUE constraint.");
  556. } catch (Exception $x) {
  557. try {
  558. // attempt to save it again
  559. $acct3 = $acct->copy();
  560. $acct3->save();
  561. $this->fail("Expected PropelException in second attempt to save object with duplicate value for UNIQUE constraint.");
  562. } catch (Exception $x) {
  563. // this is expected.
  564. }
  565. // now let's double check that it can succeed if we're not violating the constraint.
  566. $acct3->setLogin("foo2");
  567. $acct3->save();
  568. }
  569. $this->con->beginTransaction();
  570. }
  571. /**
  572. * Test for correct reporting of isModified().
  573. */
  574. public function testIsModified()
  575. {
  576. // 1) Basic test
  577. $a = new Author();
  578. $a->setFirstName("John");
  579. $a->setLastName("Doe");
  580. $a->setAge(25);
  581. $this->assertTrue($a->isModified(), "Expected Author to be modified after setting values.");
  582. $a->save();
  583. $this->assertFalse($a->isModified(), "Expected Author to be unmodified after saving set values.");
  584. // 2) Test behavior with setting vars of different types
  585. // checking setting int col to string val
  586. $a->setAge('25');
  587. $this->assertFalse($a->isModified(), "Expected Author to be unmodified after setting int column to string-cast of same value.");
  588. $a->setFirstName("John2");
  589. $this->assertTrue($a->isModified(), "Expected Author to be modified after changing string column value.");
  590. // checking setting string col to int val
  591. $a->setFirstName("1");
  592. $a->save();
  593. $this->assertFalse($a->isModified(), "Expected Author to be unmodified after saving set values.");
  594. $a->setFirstName(1);
  595. $this->assertFalse($a->isModified(), "Expected Author to be unmodified after setting string column to int-cast of same value.");
  596. // 3) Test for appropriate behavior of NULL
  597. // checking "" -> NULL
  598. $a->setFirstName("");
  599. $a->save();
  600. $this->assertFalse($a->isModified(), "Expected Author to be unmodified after saving set values.");
  601. $a->setFirstName(null);
  602. $this->assertTrue($a->isModified(), "Expected Author to be modified after changing empty string column value to NULL.");
  603. $a->setFirstName("John");
  604. $a->setAge(0);
  605. $a->save();
  606. $this->assertFalse($a->isModified(), "Expected Author to be unmodified after saving set values.");
  607. $a->setAge(null);
  608. $this->assertTrue($a->isModified(), "Expected Author to be modified after changing 0-value int column to NULL.");
  609. $a->save();
  610. $this->assertFalse($a->isModified(), "Expected Author to be unmodified after saving set values.");
  611. $a->setAge(0);
  612. $this->assertTrue($a->isModified(), "Expected Author to be modified after changing NULL-value int column to 0.");
  613. }
  614. /**
  615. * Test the BaseObject#equals().
  616. */
  617. public function testEquals()
  618. {
  619. BookstoreDataPopulator::populate();
  620. $b = BookPeer::doSelectOne(new Criteria());
  621. $c = new Book();
  622. $c->setId($b->getId());
  623. $this->assertTrue($b->equals($c), "Expected Book objects to be equal()");
  624. $a = new Author();
  625. $a->setId($b->getId());
  626. $this->assertFalse($b->equals($a), "Expected Book and Author with same primary key NOT to match.");
  627. }
  628. /**
  629. * Test checking for non-default values.
  630. * @see http://propel.phpdb.org/trac/ticket/331
  631. */
  632. public function testHasOnlyDefaultValues()
  633. {
  634. $emp = new BookstoreEmployee();
  635. $emp->setName(md5(microtime()));
  636. $acct2 = new BookstoreEmployeeAccount();
  637. $acct = new BookstoreEmployeeAccount();
  638. $acct->setBookstoreEmployee($emp);
  639. $acct->setLogin("foo");
  640. $acct->setPassword("bar");
  641. $acct->save();
  642. $this->assertFalse($acct->isModified(), "Expected BookstoreEmployeeAccount NOT to be modified after save().");
  643. $acct->setEnabled(true);
  644. $acct->setPassword($acct2->getPassword());
  645. $this->assertTrue($acct->isModified(), "Expected BookstoreEmployeeAccount to be modified after setting default values.");
  646. $this->assertTrue($acct->hasOnlyDefaultValues(), "Expected BookstoreEmployeeAccount to not have only default values.");
  647. $acct->setPassword("bar");
  648. $this->assertFalse($acct->hasOnlyDefaultValues(), "Expected BookstoreEmployeeAccount to have at one non-default value after setting one value to non-default.");
  649. // Test a default date/time value
  650. $r = new Review();
  651. $r->setReviewDate(new DateTime("now"));
  652. $this->assertFalse($r->hasOnlyDefaultValues());
  653. }
  654. public function testDefaultFkColVal()
  655. {
  656. BookstoreDataPopulator::populate();
  657. $sale = new BookstoreSale();
  658. $this->assertEquals(1, $sale->getBookstoreId(), "Expected BookstoreSale object to have a default bookstore_id of 1.");
  659. $bookstore = BookstorePeer::doSelectOne(new Criteria());
  660. $sale->setBookstore($bookstore);
  661. $this->assertEquals($bookstore->getId(), $sale->getBookstoreId(), "Expected FK id to have changed when assigned a valid FK.");
  662. $sale->setBookstore(null);
  663. $this->assertEquals(1, $sale->getBookstoreId(), "Expected BookstoreSale object to have reset to default ID.");
  664. $sale->setPublisher(null);
  665. $this->assertEquals(null, $sale->getPublisherId(), "Expected BookstoreSale object to have reset to NULL publisher ID.");
  666. }
  667. public function testCountRefFk()
  668. {
  669. $book = new Book();
  670. $book->setTitle("Test Book");
  671. $book->setISBN("TT-EE-SS-TT");
  672. $num = 5;
  673. for ($i=2; $i < $num + 2; $i++) {
  674. $r = new Review();
  675. $r->setReviewedBy('Hans ' . $num);
  676. $dt = new DateTime("now");
  677. $dt->modify("-".$i." weeks");
  678. $r->setReviewDate($dt);
  679. $r->setRecommended(($i % 2) == 0);
  680. $book->addReview($r);
  681. }
  682. $this->assertEquals($num, $book->countReviews(), "Expected countReviews to return $num");
  683. $this->assertEquals($num, count($book->getReviews()), "Expected getReviews to return $num reviews");
  684. $book->save();
  685. BookPeer::clearInstancePool();
  686. ReviewPeer::clearInstancePool();
  687. $book = BookPeer::retrieveByPK($book->getId());
  688. $this->assertEquals($num, $book->countReviews(), "Expected countReviews() to return $num (after save)");
  689. $this->assertEquals($num, count($book->getReviews()), "Expected getReviews() to return $num (after save)");
  690. // Now set different criteria and expect different results
  691. $c = new Criteria();
  692. $c->add(ReviewPeer::RECOMMENDED, false);
  693. $this->assertEquals(floor($num/2), $book->countReviews($c), "Expected " . floor($num/2) . " results from countReviews(recomm=false)");
  694. // Change Criteria, run again -- expect different.
  695. $c = new Criteria();
  696. $c->add(ReviewPeer::RECOMMENDED, true);
  697. $this->assertEquals(ceil($num/2), count($book->getReviews($c)), "Expected " . ceil($num/2) . " results from getReviews(recomm=true)");
  698. $this->assertEquals($num, $book->countReviews(), "Expected countReviews to return $num with new empty Criteria");
  699. }
  700. /**
  701. * Test copyInto method.
  702. */
  703. public function testCopyInto_Deep()
  704. {
  705. BookstoreDataPopulator::populate();
  706. // Test a "normal" object
  707. $c = new Criteria();
  708. $c->add(BookPeer::TITLE, 'Harry%', Criteria::LIKE);
  709. $book = BookPeer::doSelectOne($c);
  710. $reviews = $book->getReviews();
  711. $b2 = $book->copy(true);
  712. $this->assertType('Book', $b2);
  713. $this->assertNull($b2->getId());
  714. $r2 = $b2->getReviews();
  715. $this->assertEquals(count($reviews), count($r2));
  716. // Test a one-to-one object
  717. $emp = BookstoreEmployeePeer::doSelectOne(new Criteria());
  718. $e2 = $emp->copy(true);
  719. $this->assertType('BookstoreEmployee', $e2);
  720. $this->assertNull($e2->getId());
  721. $this->assertEquals($emp->getBookstoreEmployeeAccount()->getLogin(), $e2->getBookstoreEmployeeAccount()->getLogin());
  722. }
  723. /**
  724. * Test copying when an object has composite primary key.
  725. * @link http://propel.phpdb.org/trac/ticket/618
  726. */
  727. public function testCopy_CompositePK()
  728. {
  729. $br = new BookReader();
  730. $br->setName("TestReader");
  731. $br->save();
  732. $br->copy();
  733. $b = new Book();
  734. $b->setTitle("TestBook");
  735. $b->setISBN("XX-XX-XX-XX");
  736. $b->save();
  737. $op = new BookOpinion();
  738. $op->setBookReader($br);
  739. $op->setBook($b);
  740. $op->setRating(10);
  741. $op->setRecommendToFriend(true);
  742. $op->save();
  743. $br2 = $br->copy(true);
  744. $this->assertNull($br2->getId());
  745. $opinions = $br2->getBookOpinions();
  746. $this->assertEquals(1, count($opinions), "Expected to have a related BookOpinion after copy()");
  747. // We DO expect the reader_id to be null
  748. $this->assertNull($opinions[0]->getReaderId());
  749. // but we DO NOT expect the book_id to be null
  750. $this->assertEquals($op->getBookId(), $opinions[0]->getBookId());
  751. }
  752. public function testToArray()
  753. {
  754. $b = new Book();
  755. $b->setTitle('Don Juan');
  756. $arr1 = $b->toArray();
  757. $expectedKeys = array(
  758. 'Id',
  759. 'Title',
  760. 'ISBN',
  761. 'Price',
  762. 'PublisherId',
  763. 'AuthorId'
  764. );
  765. $this->assertEquals($expectedKeys, array_keys($arr1), 'toArray() returns an associative array with BasePeer::TYPE_PHPNAME keys by default');
  766. $this->assertEquals('Don Juan', $arr1['Title'], 'toArray() returns an associative array representation of the object');
  767. }
  768. public function testToArrayKeyType()
  769. {
  770. $b = new Book();
  771. $b->setTitle('Don Juan');
  772. $arr1 = $b->toArray(BasePeer::TYPE_COLNAME);
  773. $expectedKeys = array(
  774. BookPeer::ID,
  775. BookPeer::TITLE,
  776. BookPeer::ISBN,
  777. BookPeer::PRICE,
  778. BookPeer::PUBLISHER_ID,
  779. BookPeer::AUTHOR_ID
  780. );
  781. $this->assertEquals($expectedKeys, array_keys($arr1), 'toArray() accepts a $keyType parameter to change the result keys');
  782. $this->assertEquals('Don Juan', $arr1[BookPeer::TITLE], 'toArray() returns an associative array representation of the object');
  783. }
  784. /**
  785. * Test the toArray() method with new lazyLoad param.
  786. * @link http://propel.phpdb.org/trac/ticket/527
  787. */
  788. public function testToArrayLazyLoad()
  789. {
  790. BookstoreDataPopulator::populate();
  791. $c = new Criteria();
  792. $c->add(MediaPeer::COVER_IMAGE, null, Criteria::NOT_EQUAL);
  793. $c->add(MediaPeer::EXCERPT, null, Criteria::NOT_EQUAL);
  794. $m = MediaPeer::doSelectOne($c);
  795. if ($m === null) {
  796. $this->fail("Test requires at least one media row w/ cover_image and excerpt NOT NULL");
  797. }
  798. $arr1 = $m->toArray(BasePeer::TYPE_COLNAME);
  799. $this->assertNotNull($arr1[MediaPeer::COVER_IMAGE]);
  800. $this->assertType('resource', $arr1[MediaPeer::COVER_IMAGE]);
  801. $arr2 = $m->toArray(BasePeer::TYPE_COLNAME, false);
  802. $this->assertNull($arr2[MediaPeer::COVER_IMAGE]);
  803. $this->assertNull($arr2[MediaPeer::EXCERPT]);
  804. $diffKeys = array_keys(array_diff($arr1, $arr2));
  805. $expectedDiff = array(MediaPeer::COVER_IMAGE, MediaPeer::EXCERPT);
  806. $this->assertEquals($expectedDiff, $diffKeys);
  807. }
  808. public function testToArrayIncludeForeignObjects()
  809. {
  810. BookstoreDataPopulator::populate();
  811. BookPeer::clearInstancePool();
  812. AuthorPeer::clearInstancePool();
  813. PublisherPeer::clearInstancePool();
  814. $c = new Criteria();
  815. $c->add(BookPeer::TITLE, 'Don Juan');
  816. $books = BookPeer::doSelectJoinAuthor($c);
  817. $book = $books[0];
  818. $arr1 = $book->toArray(BasePeer::TYPE_PHPNAME, null, true);
  819. $expectedKeys = array(
  820. 'Id',
  821. 'Title',
  822. 'ISBN',
  823. 'Price',
  824. 'PublisherId',
  825. 'AuthorId',
  826. 'Author'
  827. );
  828. $this->assertEquals($expectedKeys, array_keys($arr1), 'toArray() can return sub arrays for hydrated related objects');
  829. $this->assertEquals('George', $arr1['Author']['FirstName'], 'toArray() can return sub arrays for hydrated related objects');
  830. $c = new Criteria();
  831. $c->add(BookPeer::TITLE, 'Don Juan');
  832. $books = BookPeer::doSelectJoinAll($c);
  833. $book = $books[0];
  834. $arr2 = $book->toArray(BasePeer::TYPE_PHPNAME, null, true);
  835. $expectedKeys = array(
  836. 'Id',
  837. 'Title',
  838. 'ISBN',
  839. 'Price',
  840. 'PublisherId',
  841. 'AuthorId',
  842. 'Publisher',
  843. 'Author'
  844. );
  845. $this->assertEquals($expectedKeys, array_keys($arr2), 'toArray() can return sub arrays for hydrated related objects');
  846. }
  847. /**
  848. * Test regexp validator for ticket:542
  849. * @link http://propel.phpdb.org/trac/ticket/542
  850. */
  851. public function testRegexValidator()
  852. {
  853. $b = new Bookstore();
  854. $b->setWebsite("http://this.is.valid.com/foo.bar");
  855. $res = $b->validate();
  856. $this->assertTrue($res, "Expected URL to validate");
  857. }
  858. /**
  859. * Test that setting the auto-increment primary key will result in exception.
  860. */
  861. public function testSettingAutoIncrementPK()
  862. {
  863. // The whole test is in a transaction, but this test needs real transactions
  864. $this->con->commit();
  865. $b = new Bookstore();
  866. $b->setId(1);
  867. $b->setStoreName("Test");
  868. try {
  869. $b->save();
  870. $this->fail("Expected setting auto-increment primary key to result in Exception");
  871. } catch (Exception $x) {
  872. $this->assertType('PropelException', $x);
  873. }
  874. // ... but we should silently ignore NULL values, since these are really
  875. // the same as "not set" in PHP world.
  876. $b = new Bookstore();
  877. $b->setId(null);
  878. $b->setStoreName("Test2");
  879. try {
  880. $b->save();
  881. } catch (Exception $x) {
  882. $this->fail("Expected no exception when setting auto-increment primary key to NULL");
  883. }
  884. // success ...
  885. $this->con->beginTransaction();
  886. }
  887. /**
  888. * Checks wether we are allowed to specify the primary key on a
  889. * table with allowPkInsert=true set
  890. *
  891. * saves the object, gets it from data-source again and then compares
  892. * them for equality (thus the instance pool is also checked)
  893. */
  894. public function testAllowPkInsertOnIdMethodNativeTable()
  895. {
  896. $cu = new Customer;
  897. $cu->setPrimaryKey(100000);
  898. $cu->save();
  899. $this->assertEquals(100000, $cu->getPrimaryKey());
  900. $cu2 = CustomerPeer::retrieveByPk(100000);
  901. $this->assertSame($cu, $cu2);
  902. }
  903. /**
  904. * Checks if it is allowed to save new, empty objects with a auto increment column
  905. */
  906. public function testAllowEmptyWithAutoIncrement()
  907. {
  908. $bookreader = new BookReader();
  909. $bookreader->save();
  910. $this->assertFalse($bookreader->isNew() );
  911. }
  912. /**
  913. * Test foreign key relationships based on references to unique cols but not PK.
  914. * @link http://propel.phpdb.org/trac/ticket/691
  915. */
  916. public function testUniqueFkRel()
  917. {
  918. $employee = new BookstoreEmployee();
  919. $employee->setName("Johnny Walker");
  920. $acct = new BookstoreEmployeeAccount();
  921. $acct->setBookstoreEmployee($employee);
  922. $acct->setLogin("test-login");
  923. $acct->save();
  924. $acctId = $acct->getEmployeeId();
  925. $al = new AcctAuditLog();
  926. $al->setBookstoreEmployeeAccount($acct);
  927. $al->save();
  928. $alId = $al->getId();
  929. BookstoreEmployeePeer::clearInstancePool();
  930. BookstoreEmployeeAccountPeer::clearInstancePool();
  931. AcctAuditLogPeer::clearInstancePool();
  932. $al2 = AcctAuditLogPeer::retrieveByPK($alId);
  933. /* @var $al2 AcctAuditLog */
  934. $mapacct = $al2->getBookstoreEmployeeAccount();
  935. $lookupacct = BookstoreEmployeeAccountPeer::retrieveByPK($acctId);
  936. $logs = $lookupacct->getAcctAuditLogs();
  937. $this->assertTrue(count($logs) == 1, "Expected 1 audit log result.");
  938. $this->assertEquals($logs[0]->getId(), $al->getId(), "Expected returned audit log to match created audit log.");
  939. }
  940. public function testIsPrimaryKeyNull()
  941. {
  942. $b = new Book();
  943. $this->assertTrue($b->isPrimaryKeyNull());
  944. $b->setPrimaryKey(123);
  945. $this->assertFalse($b->isPrimaryKeyNull());
  946. $b->setPrimaryKey(null);
  947. $this->assertTrue($b->isPrimaryKeyNull());
  948. }
  949. public function testIsPrimaryKeyNullCompmosite()
  950. {
  951. $b = new BookOpinion();
  952. $this->assertTrue($b->isPrimaryKeyNull());
  953. $b->setPrimaryKey(array(123, 456));
  954. $this->assertFalse($b->isPrimaryKeyNull());
  955. $b->setPrimaryKey(array(123, null));
  956. $this->assertFalse($b->isPrimaryKeyNull());
  957. $b->setPrimaryKey(array(null, 456));
  958. $this->assertFalse($b->isPrimaryKeyNull());
  959. $b->setPrimaryKey(array(null, null));
  960. $this->assertTrue($b->isPrimaryKeyNull());
  961. }
  962. public function testAddPrimaryString()
  963. {
  964. $this->assertFalse(method_exists('Author', '__toString'), 'addPrimaryString() does not add a __toString() method if no column has the primaryString attribute');
  965. $this->assertTrue(method_exists('Book', '__toString'), 'addPrimaryString() adds a __toString() method if a column has the primaryString attribute');
  966. $book = new Book();
  967. $book->setTitle('foo');
  968. $this->assertEquals((string) $book, 'foo', 'addPrimaryString() adds a __toString() method returning the value of the the first column where primaryString is true');
  969. }
  970. public function testPreInsert()
  971. {
  972. $author = new TestAuthor();
  973. $author->setFirstName("bogus");
  974. $author->setLastName("Lastname");
  975. $author->save();
  976. $this->assertEquals('PreInsertedFirstname', $author->getFirstName());
  977. }
  978. public function testPreUpdate()
  979. {
  980. $author = new TestAuthor();
  981. $author->setFirstName("bogus");
  982. $author->setLastName("Lastname");
  983. $author->save();
  984. $author->setNew(false);
  985. $author->save();
  986. $this->assertEquals('PreUpdatedFirstname', $author->getFirstName());
  987. }
  988. public function testPostInsert()
  989. {
  990. $author = new TestAuthor();
  991. $author->setFirstName("bogus");
  992. $author->setLastName("Lastname");
  993. $author->save();
  994. $this->assertEquals('PostInsertedLastName', $author->getLastName());
  995. }
  996. public function testPostUpdate()
  997. {
  998. $author = new TestAuthor();
  999. $author->setFirstName("bogus");
  1000. $author->setLastName("Lastname");
  1001. $author->save();
  1002. $author->setNew(false);
  1003. $author->save();
  1004. $this->assertEquals('PostUpdatedLastName', $author->getLastName());
  1005. }
  1006. public function testPreSave()
  1007. {
  1008. $author = new TestAuthor();
  1009. $author->setFirstName("bogus");
  1010. $author->setLastName("Lastname");
  1011. $author->save();
  1012. $this->assertEquals('pre@save.com', $author->getEmail());
  1013. }
  1014. public function testPreSaveFalse()
  1015. {
  1016. $con = Propel::getConnection(AuthorPeer::DATABASE_NAME);
  1017. $author = new TestAuthorSaveFalse();
  1018. $author->setFirstName("bogus");
  1019. $author->setLastName("Lastname");
  1020. $res = $author->save($con);
  1021. $this->assertEquals(0, $res);
  1022. $this->assertEquals('pre@save.com', $author->getEmail());
  1023. $this->assertNotEquals(115, $author->getAge());
  1024. $this->assertTrue($author->isNew());
  1025. $this->assertEquals(1, $con->getNestedTransactionCount());
  1026. }
  1027. public function testPostSave()
  1028. {
  1029. $author = new TestAuthor();
  1030. $author->setFirstName("bogus");
  1031. $author->setLastName("Lastname");
  1032. $author->save();
  1033. $this->assertEquals(115, $author->getAge());
  1034. }
  1035. public function testPreDelete()
  1036. {
  1037. $author = new TestAuthor();
  1038. $author->setFirstName("bogus");
  1039. $author->setLastName("Lastname");
  1040. $author->save();
  1041. $author->delete();
  1042. $this->assertEquals("Pre-Deleted", $author->getFirstName());
  1043. }
  1044. public function testPreDeleteFalse()
  1045. {
  1046. $con = Propel::getConnection(AuthorPeer::DATABASE_NAME);
  1047. $author = new TestAuthorDeleteFalse();
  1048. $author->setFirstName("bogus");
  1049. $author->setLastName("Lastname");
  1050. $author->save($con);
  1051. $author->delete($con);
  1052. $this->assertEquals("Pre-Deleted", $author->getFirstName());
  1053. $this->assertNotEquals("Post-Deleted", $author->getLastName());
  1054. $this->assertFalse($author->isDeleted());
  1055. $this->assertEquals(1, $con->getNestedTransactionCount());
  1056. }
  1057. public function testPostDelete()
  1058. {
  1059. $author = new TestAuthor();
  1060. $author->setFirstName("bogus");
  1061. $author->setLastName("Lastname");
  1062. $author->save();
  1063. $author->delete();
  1064. $this->assertEquals("Post-Deleted", $author->getLastName());
  1065. }
  1066. public function testMagicVirtualColumnGetter()
  1067. {
  1068. $book = new Book();
  1069. $book->setVirtualColumn('Foo', 'bar');
  1070. $this->assertEquals('bar', $book->getFoo(), 'generated __call() catches getters for virtual columns');
  1071. $book = new Book();
  1072. $book->setVirtualColumn('foo', 'bar');
  1073. $this->assertEquals('bar', $book->getFoo(), 'generated __call() catches getters for virtual columns starting with a lowercase character');
  1074. }
  1075. /**
  1076. * @expectedException PropelException
  1077. */
  1078. public function testMagicCallUndefined()
  1079. {
  1080. $book = new Book();
  1081. $book->fooMethodName();
  1082. }
  1083. public static function conditionsForTestReadOnly()
  1084. {
  1085. return array(
  1086. array('reload'),
  1087. array('delete'),
  1088. array('save'),
  1089. array('doSave'),
  1090. );
  1091. }
  1092. /**
  1093. * @dataProvider conditionsForTestReadOnly
  1094. */
  1095. public function testReadOnly($method)
  1096. {
  1097. $cv = new ContestView();
  1098. $this->assertFalse(method_exists($cv, $method), 'readOnly tables end up with no ' . $method . ' method in the generated object class');
  1099. }
  1100. }