root/trunk/generator/test/classes/propel/GeneratedObjectTest.php

Revision 1024, 25.7 kB (checked in by hans, 4 months ago)

Updating license to version 3 of the LGPL.

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id Rev Date Author HeadURL Revision
Line 
1 <?php
2 /*
3  *  $Id$
4  *
5  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16  *
17  * This software consists of voluntary contributions made by many individuals
18  * and is licensed under version 3 of the LGPL. For more information please see
19  * <http://propel.phpdb.org>.
20  */
21
22 require_once 'bookstore/BookstoreTestBase.php';
23
24 /**
25  * Tests the generated Object classes.
26  *
27  * This test uses generated Bookstore classes to test the behavior of various
28  * object operations.  The _idea_ here is to test every possible generated method
29  * from Object.tpl; if necessary, bookstore will be expanded to accommodate this.
30  *
31  * The database is relaoded before every test and flushed after every test.  This
32  * means that you can always rely on the contents of the databases being the same
33  * for each test method in this class.  See the BookstoreDataPopulator::populate()
34  * method for the exact contents of the database.
35  *
36  * @see        BookstoreDataPopulator
37  * @author     Hans Lellelid <hans@xmpl.org>
38  */
39 class GeneratedObjectTest extends BookstoreTestBase {
40
41     /**
42      * Test saving an object after setting default values for it.
43      */
44     public function testSaveWithDefaultValues()
45     {
46         // From the schema.xml, I am relying on the following:
47         //  - that 'Penguin' is the default Name for a Publisher
48         //  - that 2001-01-01 is the default ReviewDate for a Review
49
50         // 1) check regular values (VARCHAR)
51         $pub = new Publisher();
52         $pub->setName('Penguin');
53         $pub->save();
54         $this->assertTrue($pub->getId() !== null, "Expect Publisher to have been saved when default value set.");
55
56         // 2) check date/time values
57         $review = new Review();
58         // note that this is different from how it's represented in schema, but should resolve to same unix timestamp
59         $review->setReviewDate('2001-01-01');
60         $this->assertTrue($review->isModified(), "Expect Review to have been marked 'modified' after default date/time value set.");
61
62     }
63
64     /**
65      * Test default return values.
66      */
67     public function testDefaultValues()
68     {
69         $r = new Review();
70         $this->assertEquals('2001-01-01', $r->getReviewDate('Y-m-d'));
71
72         $this->assertFalse($r->isModified(), "expected isModified() to be falseb");
73
74         $acct = new BookstoreEmployeeAccount();
75         $this->assertEquals(true, $acct->getEnabled());
76         $this->assertFalse($acct->isModified());
77
78         $acct->setLogin("testuser");
79         $acct->setPassword("testpass");
80         $this->assertTrue($acct->isModified());
81     }
82
83     /**
84      * Tests the use of default expressions.
85      * (Also indirectly tests the reload() method.)
86      */
87     public function testDefaultExpresions()
88     {
89         if (Propel::getDb(BookstoreEmployeePeer::DATABASE_NAME) instanceof DBSqlite) {
90             $this->markTestSkipped("Cannot test default expressions with SQLite");
91         }
92
93         $employee = new BookstoreEmployee();
94         $employee->setName("Johnny Walker");
95
96         $acct = new BookstoreEmployeeAccount();
97         $acct->setBookstoreEmployee($employee);
98         $acct->setLogin("test-login");
99
100         $this->assertNull($acct->getCreated());
101
102         $acct->save();
103
104         // BookstoreEmployeeAccountPeer::removeInstanceFromPool($acct);
105
106         $acct = BookstoreEmployeeAccountPeer::retrieveByPK($acct->getEmployeeId());
107         $this->assertNotNull($acct->getCreated(), "Expected a valid date after retrieving saved object.");
108
109         $now = new DateTime("now");
110         $this->assertEquals($now->format("Y-m-d"), $acct->getCreated("Y-m-d"));
111
112         $acct->setCreated($now);
113         $this->assertEquals($now->format("Y-m-d"), $acct->getCreated("Y-m-d"));
114
115     }
116
117     /**
118      * Test the behavior of date/time/values.
119      * This requires that the model was built with propel.useDateTimeClass=true.
120      */
121     public function testTemporalValues_PreEpoch()
122     {
123         $r = new Review();
124
125         $preEpochDate = new DateTime('1602-02-02');
126
127         $r->setReviewDate($preEpochDate);
128
129         $this->assertEquals('1602-02-02', $r->getReviewDate(null)->format("Y-m-d"));
130
131         $r->setReviewDate('1702-02-02');
132
133         $this->assertTrue($r->isModified());
134
135         $this->assertEquals('1702-02-02', $r->getReviewDate(null)->format("Y-m-d"));
136
137         // Now test for setting null
138         $r->setReviewDate(null);
139         $this->assertNull($r->getReviewDate());
140
141     }
142
143     /**
144      * Test setting invalid date/time.
145      */
146     public function _disabled_testSetTemporalValue_Invalid()
147     {
148         // FIXME - Figure out why this doesn't work (doesn't throw Exception) in the Phing+PHPUnit context
149         $r = new Review();
150         try {
151             $r->setReviewDate("Invalid Date");
152             $this->fail("Expected PropelException when setting date column w/ invalid date");
153         } catch (PropelException $x) {
154             print "Caught expected PropelException: " . $x->__toString();
155         }
156     }
157
158     /**
159      * Test setting TIMESTAMP columns w/ unix int timestamp.
160      */
161     public function testTemporalValues_Unix()
162     {
163         $store = new Bookstore();
164         $store->setStoreName("test");
165         $store->setStoreOpenTime(strtotime('12:55'));
166         $store->save();
167         $this->assertEquals('12:55', $store->getStoreOpenTime(null)->format('H:i'));
168     }
169
170     /**
171      * Test setting TIME columns.
172      */
173     public function testTemporalValues_TimeSetting()
174     {
175         $store = new Bookstore();
176         $store->setStoreName("test");
177         $store->setStoreOpenTime("12:55");
178         $store->save();
179
180         $store = new Bookstore();
181         $store->setStoreName("test2");
182         $store->setStoreOpenTime(new DateTime("12:55"));
183         $store->save();
184     }
185
186     /**
187      * Test setting TIME columns.
188      */
189     public function testTemporalValues_DateSetting()
190     {
191         $r = new Review();
192         $r->setBook(BookPeer::doSelectOne(new Criteria()));
193         $r->setReviewDate(new DateTime('1999-12-20'));
194         $r->setReviewedBy("Hans");
195         $r->setRecommended(false);
196         $r->save();
197     }
198
199     /**
200      * Testing creating & saving new object & instance pool.
201      */
202     public function testObjectInstances_New()
203     {
204         $emp = new BookstoreEmployee();
205         $emp->setName(md5(microtime()));
206         $emp->save();
207         $id = $emp->getId();
208
209         $retrieved = BookstoreEmployeePeer::retrieveByPK($id);
210         $this->assertSame($emp, $retrieved, "Expected same object (from instance pool)");
211     }
212
213     /**
214      *
215      */
216     public function testObjectInstances_Fkeys()
217     {
218         // Establish a relationship between one employee and account
219         // and then change the employee_id and ensure that the account
220         // is not pulling the old employee.
221
222         $pub1 = new Publisher();
223         $pub1->setName('Publisher 1');
224         $pub1->save();
225
226         $pub2 = new Publisher();
227         $pub2->setName('Publisher 2');
228         $pub2->save();
229
230         $book = new Book();
231         $book->setTitle("Book Title");
232         $book->setISBN("1234");
233         $book->setPublisher($pub1);
234         $book->save();
235
236         $this->assertSame($pub1, $book->getPublisher());
237
238         // now change values behind the scenes
239         $con = Propel::getConnection(BookstoreEmployeeAccountPeer::DATABASE_NAME);
240         $con->exec("UPDATE " . BookPeer::TABLE_NAME . " SET "
241         . " publisher_id = " . $pub2->getId()
242         . " WHERE id = " . $book->getId());
243
244
245         $book2 = BookPeer::retrieveByPK($book->getId());
246         $this->assertSame($book, $book2, "Expected same book object instance");
247
248         $this->assertEquals($pub2->getId(), $book->getPublisherId(), "Expected book to have new publisher id");
249         $this->assertSame($pub2, $book->getPublisher(), "Expected book to have new publisher object associated.");
250
251         // Now let's set it back and also verify that reload() works ...
252
253         $con->exec("UPDATE " . BookPeer::TABLE_NAME . " SET "
254         . " publisher_id = " . $pub1->getId()
255         . " WHERE id = " . $book->getId());
256
257         $book->reload();
258
259         $this->assertEquals($pub1->getId(), $book->getPublisherId(), "Expected book to have old publisher id (again).");
260         $this->assertSame($pub1, $book->getPublisher(), "Expected book to have old publisher object associated (again).");
261
262     }
263
264     /**
265      * Test the reload() method.
266      */
267     public function testReload()
268     {
269         $a = AuthorPeer::doSelectOne(new Criteria());
270
271         $origName = $a->getFirstName();
272
273         $a->setFirstName(md5(time()));
274
275         $this->assertNotEquals($origName, $a->getFirstName());
276         $this->assertTrue($a->isModified());
277
278         $a->reload();
279
280         $this->assertEquals($origName, $a->getFirstName());
281         $this->assertFalse($a->isModified());
282
283     }
284
285     /**
286      * Test reload(deep=true) method.
287      */
288     public function testReloadDeep()
289     {
290         // arbitrary book
291         $b = BookPeer::doSelectOne(new Criteria());
292
293         // arbitrary, different author
294         $c = new Criteria();
295         $c->add(AuthorPeer::ID, $b->getAuthorId(), Criteria::NOT_EQUAL);
296         $a = AuthorPeer::doSelectOne($c);
297
298         $origAuthor = $b->getAuthor();
299
300         $b->setAuthor($a);
301
302         $this->assertNotEquals($origAuthor, $b->getAuthor(), "Expected just-set object to be different from obj from DB");
303         $this->assertTrue($b->isModified());
304
305         $b->reload($deep=true);
306
307         $this->assertEquals($origAuthor, $b->getAuthor(), "Expected object in DB to be restored");
308         $this->assertFalse($a->isModified());
309     }
310
311     /**
312      * Test saving an object and getting correct number of affected rows from save().
313      * This includes tests of cascading saves to fk-related objects.
314      */
315     public function testSaveReturnValues()
316     {
317
318         $author = new Author();
319         $author->setFirstName("Mark");
320         $author->setLastName("Kurlansky");
321         // do not save
322
323         $pub = new Publisher();
324         $pub->setName("Penguin Books");
325         // do not save
326
327         $book = new Book();
328         $book->setTitle("Salt: A World History");
329         $book->setISBN("0142001619");
330         $book->setAuthor($author);
331         $book->setPublisher($pub);
332
333         $affected = $book->save();
334         $this->assertEquals(3, $affected, "Expected 3 affected rows when saving book + publisher + author.");
335
336         // change nothing ...
337         $affected = $book->save();
338         $this->assertEquals(0, $affected, "Expected 0 affected rows when saving already-saved book.");
339
340         // modify the book (UPDATE)
341         $book->setTitle("Salt A World History");
342         $affected = $book->save();
343         $this->assertEquals(1, $affected, "Expected 1 affected row when saving modified book.");
344
345         // modify the related author
346         $author->setLastName("Kurlanski");
347         $affected = $book->save();
348         $this->assertEquals(1, $affected, "Expected 1 affected row when saving book with updated author.");
349
350         // modify both the related author and the book
351         $author->setLastName("Kurlansky");
352         $book->setTitle("Salt: A World History");
353         $affected = $book->save();
354         $this->assertEquals(2, $affected, "Expected 2 affected rows when saving updated book with updated author.");
355
356     }
357
358     /**
359      * Test deleting an object using the delete() method.
360      */
361     public function testDelete() {
362
363         // 1) grab an arbitrary object
364         $book = BookPeer::doSelectOne(new Criteria());
365         $bookId = $book->getId();
366
367         // 2) delete it
368         $book->delete();
369
370         // 3) make sure it can't be save()d now that it's deleted
371         try {
372             $book->setTitle("Will Fail");
373             $book->save();
374             $this->fail("Expect an exception to be thrown when attempting to save() a deleted object.");
375         } catch (PropelException $e) {}
376
377         // 4) make sure that it doesn't exist in db
378         $book = BookPeer::retrieveByPK($bookId);
379         $this->assertNull($book, "Expect NULL from retrieveByPK on deleted Book.");
380
381     }
382
383     /**
384      *
385      */
386     public function testNoColsModified()
387     {
388         $e1 = new BookstoreEmployee();
389         $e1->setName('Employee 1');
390
391         $e2 = new BookstoreEmployee();
392         $e2->setName('Employee 2');
393
394         $super = new BookstoreEmployee();
395         // we don't know who the supervisor is yet
396         $super->addSubordinate($e1);
397         $super->addSubordinate($e2);
398
399         $affected = $super->save();
400
401     }
402
403     /**
404      * Tests new one-to-one functionality.
405      *
406      * @todo       -cGeneratedObjectTest Add a test for one-to-one when implemented.
407      */
408     public function testOneToOne()
409     {
410         $emp = BookstoreEmployeePeer::doSelectOne(new Criteria());
411
412         $acct = new BookstoreEmployeeAccount();
413         $acct->setBookstoreEmployee($emp);
414         $acct->setLogin("testuser");
415         $acct->setPassword("testpass");
416
417         $this->assertSame($emp->getBookstoreEmployeeAccount(), $acct, "Expected same object instance.");
418     }
419
420     /**
421      * Test the type sensitivity of the resturning columns.
422      *
423      */
424     public function testTypeSensitive()
425     {
426         $book = BookPeer::doSelectOne(new Criteria());
427
428         $r = new Review();
429         $r->setReviewedBy("testTypeSensitive Tester");
430         $r->setReviewDate(time());
431         $r->setBook($book);
432         $r->setRecommended(true);
433         $r->save();
434
435         $id = $r->getId();
436         unset($r);
437
438         // clear the instance cache to force reload from database.
439         ReviewPeer::clearInstancePool();
440         BookPeer::clearInstancePool();
441
442         // reload and verify that the types are the same
443         $r2 = ReviewPeer::retrieveByPK($id);
444
445         $this->assertType('integer', $r2->getId(), "Expected getId() to return an integer.");
446         $this->assertType('string', $r2->getReviewedBy(), "Expected getReviewedBy() to return a string.");
447         $this->assertType('boolean', $r2->getRecommended(), "Expected getRecommended() to return a boolean.");
448         $this->assertType('Book', $r2->getBook(), "Expected getBook() to return a Book.");
449         $this->assertType('float', $r2->getBook()->getPrice(), "Expected Book->getPrice() to return a float.");
450         $this->assertType('DateTime', $r2->getReviewDate(null), "Expected Book->getReviewDate() to return a DateTime.");
451
452     }
453
454     /**
455      * This is a test for expected exceptions when saving UNIQUE.
456      * See http://propel.phpdb.org/trac/ticket/2
457      */
458     public function testSaveUnique()
459     {
460         $emp = new BookstoreEmployee();
461         $emp->setName(md5(microtime()));
462
463         $acct = new BookstoreEmployeeAccount();
464         $acct->setBookstoreEmployee($emp);
465         $acct->setLogin("foo");
466         $acct->setPassword("bar");
467         $acct->save();
468
469         // now attempt to create a new acct
470         $acct2 = $acct->copy();
471
472         try {
473             $acct2->save();
474             $this->fail("Expected PropelException in first attempt to save object with duplicate value for UNIQUE constraint.");
475         } catch (Exception $x) {
476             try {
477                 // attempt to save it again
478                 $acct3 = $acct->copy();
479                 $acct3->save();
480                 $this->fail("Expected PropelException in second attempt to save object with duplicate value for UNIQUE constraint.");
481             } catch (Exception $x) {
482                 // this is expected.
483             }
484             // now let's double check that it can succeed if we're not violating the constraint.
485             $acct3->setLogin("foo2");
486             $acct3->save();
487         }
488     }
489
490     /**
491      * Test for correct reporting of isModified().
492      */
493     public function testIsModified()
494     {
495         // 1) Basic test
496
497         $a = new Author();
498         $a->setFirstName("John");
499         $a->setLastName("Doe");
500         $a->setAge(25);
501
502         $this->assertTrue($a->isModified(), "Expected Author to be modified after setting values.");
503
504         $a->save();
505
506         $this->assertFalse($a->isModified(), "Expected Author to be unmodified after saving set values.");
507
508         // 2) Test behavior with setting vars of different types
509
510         // checking setting int col to string val
511         $a->setAge('25');
512         $this->assertFalse($a->isModified(), "Expected Author to be unmodified after setting int column to string-cast of same value.");
513
514         $a->setFirstName("John2");
515         $this->assertTrue($a->isModified(), "Expected Author to be modified after changing string column value.");
516
517         // checking setting string col to int val