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

Revision 1082, 7.9 kB (checked in by tony, 3 months ago)

Refs #683: Added support for PHP 5.3 namespaces

Line 
1 <?php
2
3 use bookstore::Model as PropelModel;
4 use bookstore::Peer as PropelPeer;
5
6 require_once 'bookstore/BookstoreTestBase.php';
7
8 /* It's only fair to admit that these tests were carefully crafted
9 after studying the current implementation to make it look as bad as
10 possible. I am really sorry. :-( */
11
12 class Ticket520Test extends BookstoreTestBase {
13
14     public function testNewObjectsAvailableWhenSaveNotCalled() {
15         $a = new PropelModel::Author();
16         $a->setFirstName("Douglas");
17         $a->setLastName("Adams");
18
19         $b1 = new PropelModel::Book();
20         $b1->setTitle("The Hitchhikers Guide To The Galaxy");
21         $a->addBook($b1);
22
23         $b2 = new PropelModel::Book();
24         $b2->setTitle("The Restaurant At The End Of The Universe");
25         $a->addBook($b2);
26
27         /* As of revision 851, this passes as new objects (here: the Author)
28         always contain all added FK-related objects (here: the Books) in
29         their internal $colBooks collection. */
30         $books = $a->getBooks();
31         $this->assertContains($b1, $books);
32         $this->assertContains($b2, $books);
33     }
34
35     public function testNewObjectsWithCriteria() {
36
37         $a = new PropelModel::Author();
38         $a->setFirstName("Douglas");
39         $a->setLastName("Adams");
40
41         $b1 = new PropelModel::Book();
42         $b1->setTitle("The Hitchhikers Guide To The Galaxy");
43         $a->addBook($b1);
44
45         $b2 = new PropelModel::Book();
46         $b2->setTitle("The Restaurant At The End Of The Universe");
47         $a->addBook($b2);
48
49         $c = new ::Criteria();
50         $c->add(PropelPeer::BookPeer::TITLE, "%Hitchhiker%", ::Criteria::LIKE);
51
52         /* As of revision 851, this fails because new objects like the Author
53         always contain added objects in their internal collection but are unable
54         to apply any Criteria. */
55
56         $guides = $a->getBooks($c);
57         $this->assertEquals(1, count($guides));
58         foreach ($guides as $book) {
59             $this->assertEquals($b1, $book);
60         }
61     }
62
63     public function testSavedObjectsWithCriteria() {
64         $a = new PropelModel::Author();
65         $a->setFirstName("Douglas");
66         $a->setLastName("Adams");
67
68         $b1 = new PropelModel::Book();
69         $b1->setTitle("The Hitchhikers Guide To The Galaxy");
70         $a->addBook($b1);
71
72         $b2 = new PropelModel::Book();
73         $b2->setTitle("The Restaurant At The End Of The Universe");
74         $a->addBook($b2);
75
76         $c = new ::Criteria();
77         $c->add(PropelPeer::BookPeer::TITLE, "%Hitchhiker%", ::Criteria::LIKE);
78
79         /* This is the same as testNewObjectsWithCriteria EXCEPT we're now going
80         to save(). Now the $author and related objects are no longer new
81         and thus the criteria will be applied in the database.
82
83         Apart from that the fix is for sure not trivial, observable behaviour
84         of the $author should not depend on having called save() or not... */
85
86         $booksBeforeSave = $a->getBooks($c);
87         $a->save();
88         $booksAfterSave = $a->getBooks($c);
89
90         // As of revision 851, this passes...
91         $this->assertEquals(1, count($booksAfterSave));
92         foreach ($booksAfterSave as $book) {
93             $this->assertEquals($b1, $book);
94         }
95
96         /* ... but this would fail. Commented out because it's covered
97         by testNewObjectsWithCriteria(). */
98         //$this->assertEquals($booksBeforeSave, $booksAfterSave);
99     }
100
101     public function testAddNewObjectAfterSave() {
102         /* This is like testNewObjectsAvailableWhenSaveNotCalled(),
103         but this time we save the author before adding the book. */
104
105         $a = new PropelModel::Author();
106         $a->setFirstName("Douglas");
107         $a->setLastName("Adams");
108
109         $a->save();
110
111         $b1 = new PropelModel::Book();
112         $b1->setTitle("The Hitchhikers Guide To The Galaxy");
113         $a->addBook($b1);
114
115         /* As of revision 851, although testNewObjectsAvailableWhenSaveNotCalled()
116         worked, this will fail. Because the author has been saved this time,
117         it will only check the database and not see the new (unsaved) book. */
118         $books = $a->getBooks();
119         $this->assertEquals(1, count($books));
120         $this->assertContains($b1, $books);
121
122         /* Now this is the initial ticket 520: If we have a saved author,
123         add a new book but happen to call getBooks() before we call save() again,
124         the book is lost. As of revision 851, this will fail: */
125         $a->save();
126         $this->assertFalse($b1->isNew());
127
128     }
129
130     public function testAddNewObjectAfterSaveWithPoisonedCache() {
131         /* This is like testAddNewObjectAfterSave(),
132         but this time we "poison" the author's $colBooks cache
133         before adding the book by calling getBooks(). */
134
135         $a = new PropelModel::Author();
136         $a->setFirstName("Douglas");
137         $a->setLastName("Adams");
138
139         $a->save();
140         $a->getBooks();
141
142         $b1 = new PropelModel::Book();
143         $b1->setTitle("The Hitchhikers Guide To The Galaxy");
144         $a->addBook($b1);
145
146         /* As of revision 851, this passes. This is because the following
147         call will not look at the database because the same (nil) criteria
148         is used as in the call to getBooks() above. The book has been added to
149         the cache inside the Author object that now is returned. */
150         $books = $a->getBooks();
151         $this->assertEquals(1, count($books));
152         $this->assertContains($b1, $books);
153     }
154
155     public function testCachePoisoning() {
156         /* Like testAddNewObjectAfterSaveWithPoisonedCache, emphasizing
157         cache poisoning. */
158
159         $a = new PropelModel::Author();
160         $a->setFirstName("Douglas");
161         $a->setLastName("Adams");
162
163         $a->save();
164
165         $c = new ::Criteria();
166         $c->add(PropelPeer::BookPeer::TITLE, "%Restaurant%", ::Criteria::LIKE);
167
168         $this->assertEquals(0, count($a->getBooks($c)));
169
170         $b1 = new PropelModel::Book();
171         $b1->setTitle("The Hitchhikers Guide To The Galaxy");
172         $a->addBook($b1);
173
174         /* Like testAddNewObjectAfterSaveWithPoisonedCache, but this time
175         with a real criteria. As of revision 851, this fails because
176         the $b1 is returned although it should not (does not match the
177         criteria). This is the first comment on the 520 ticket. */
178         $this->assertEquals(0, count($a->getBooks($c)));
179
180         /* If we called $a->getBooks() now, $b1 would be lost although
181         it should be in the result. Already covered by
182         testAddNewObjectAfterSave().
183
184         Instead, this time we call save() again, saving the book. However,
185         although everything is in the DB, the cache is still wrong like
186         in the assertion before. */
187         $a->save();
188         $this->assertFalse($b1->isNew());
189         $this->assertEquals(0, count($a->getBooks($c)));
190     }
191
192     public function testDeletedBookDisappears() {
193         $a = new PropelModel::Author();
194         $a->setFirstName("Douglas");
195         $a->setLastName("Adams");
196
197         $b1 = new PropelModel::Book();
198         $b1->setTitle("The Hitchhikers Guide To The Galaxy");
199         $a->addBook($b1);
200
201         $b2 = new PropelModel::Book();
202         $b2->setTitle("The Restaurant At The End Of The Universe");
203         $a->addBook($b2);
204
205         /* As you cannot write $a->remove($b2), you have to delete $b2
206         directly. */
207
208         /* All objects unsaved. As of revision 851, this circumvents the
209         $colBooks cache. Anyway, fails because getBooks() never checks if
210         a colBooks entry has been deleted. */
211         $this->assertEquals(2, count($a->getBooks()));
212         $b2->delete();
213         $this->assertEquals(1, count($a->getBooks()));
214
215         /* Even if we had saved everything before and the delete() had
216         actually updated the DB, the $b2 would still be a "zombie" in
217         $a's $colBooks field. */
218     }
219
220     public function testNewObjectsGetLostOnJoin() {
221         /* While testNewObjectsAvailableWhenSaveNotCalled passed as of
222         revision 851, in this case we call getBooksJoinPublisher() instead
223         of just getBooks(). get...Join...() does not contain the check whether
224         the current object is new, it will always consult the DB and lose the
225         new objects entirely. Thus the test fails. (At least for Propel 1.2 ?!?) */
226
227         $a = new PropelModel::Author();
228         $a->setFirstName("Douglas");
229         $a->setLastName("Adams");
230
231         $p = new PropelModel::Publisher();
232         $p->setName('Pan Books Ltd.');
233
234         $b1 = new PropelModel::Book();
235         $b1->setTitle("The Hitchhikers Guide To The Galaxy");
236         $b1->setPublisher($p); // uh... did not check that :^)
237         $a->addBook($b1);
238
239         $b2 = new PropelModel::Book();
240         $b2->setTitle("The Restaurant At The End Of The Universe");
241         $b2->setPublisher($p);
242         $a->addBook($b2);
243
244         $books = $a->getBooksJoinPublisher();
245         $this->assertEquals(2, count($books));
246         $this->assertContains($b1, $books);
247         $this->assertContains($b2, $books);
248
249         $a->save();
250         $this->assertFalse($b1->isNew());
251         $this->assertFalse($b2->isNew());
252     }
253
254 }
255
256 ?>
257
Note: See TracBrowser for help on using the browser.