Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / orm / tests / Doctrine / Tests / OrmFunctionalTestCase.php
1 <?php
2
3 namespace Doctrine\Tests;
4
5 /**
6  * Base testcase class for all functional ORM testcases.
7  *
8  * @since 2.0
9  */
10 abstract class OrmFunctionalTestCase extends OrmTestCase
11 {
12     /* The metadata cache shared between all functional tests. */
13     private static $_metadataCacheImpl = null;
14     /* The query cache shared between all functional tests. */
15     private static $_queryCacheImpl = null;
16
17     /* Shared connection when a TestCase is run alone (outside of it's functional suite) */
18     protected static $_sharedConn;
19
20     /**
21      * @var \Doctrine\ORM\EntityManager
22      */
23     protected $_em;
24
25     /**
26      * @var \Doctrine\ORM\Tools\SchemaTool
27      */
28     protected $_schemaTool;
29
30     /**
31      * @var \Doctrine\DBAL\Logging\DebugStack
32      */
33     protected $_sqlLoggerStack;
34
35     /** The names of the model sets used in this testcase. */
36     protected $_usedModelSets = array();
37
38     /** Whether the database schema has already been created. */
39     protected static $_tablesCreated = array();
40
41     /**
42      * Array of entity class name to their tables that were created.
43      * @var array
44      */
45     protected static $_entityTablesCreated = array();
46
47     /** List of model sets and their classes. */
48     protected static $_modelSets = array(
49         'cms' => array(
50             'Doctrine\Tests\Models\CMS\CmsUser',
51             'Doctrine\Tests\Models\CMS\CmsPhonenumber',
52             'Doctrine\Tests\Models\CMS\CmsAddress',
53             'Doctrine\Tests\Models\CMS\CmsEmail',
54             'Doctrine\Tests\Models\CMS\CmsGroup',
55             'Doctrine\Tests\Models\CMS\CmsArticle',
56             'Doctrine\Tests\Models\CMS\CmsComment',
57         ),
58         'forum' => array(),
59         'company' => array(
60             'Doctrine\Tests\Models\Company\CompanyPerson',
61             'Doctrine\Tests\Models\Company\CompanyEmployee',
62             'Doctrine\Tests\Models\Company\CompanyManager',
63             'Doctrine\Tests\Models\Company\CompanyOrganization',
64             'Doctrine\Tests\Models\Company\CompanyEvent',
65             'Doctrine\Tests\Models\Company\CompanyAuction',
66             'Doctrine\Tests\Models\Company\CompanyRaffle',
67             'Doctrine\Tests\Models\Company\CompanyCar',
68             'Doctrine\Tests\Models\Company\CompanyContract',
69         ),
70         'ecommerce' => array(
71             'Doctrine\Tests\Models\ECommerce\ECommerceCart',
72             'Doctrine\Tests\Models\ECommerce\ECommerceCustomer',
73             'Doctrine\Tests\Models\ECommerce\ECommerceProduct',
74             'Doctrine\Tests\Models\ECommerce\ECommerceShipping',
75             'Doctrine\Tests\Models\ECommerce\ECommerceFeature',
76             'Doctrine\Tests\Models\ECommerce\ECommerceCategory'
77         ),
78         'generic' => array(
79             'Doctrine\Tests\Models\Generic\BooleanModel',
80             'Doctrine\Tests\Models\Generic\DateTimeModel',
81             'Doctrine\Tests\Models\Generic\DecimalModel',
82             'Doctrine\Tests\Models\Generic\SerializationModel',
83         ),
84         'routing' => array(
85             'Doctrine\Tests\Models\Routing\RoutingLeg',
86             'Doctrine\Tests\Models\Routing\RoutingLocation',
87             'Doctrine\Tests\Models\Routing\RoutingRoute',
88             'Doctrine\Tests\Models\Routing\RoutingRouteBooking',
89         ),
90         'navigation' => array(
91             'Doctrine\Tests\Models\Navigation\NavUser',
92             'Doctrine\Tests\Models\Navigation\NavCountry',
93             'Doctrine\Tests\Models\Navigation\NavPhotos',
94             'Doctrine\Tests\Models\Navigation\NavTour',
95             'Doctrine\Tests\Models\Navigation\NavPointOfInterest',
96         ),
97         'directorytree' => array(
98             'Doctrine\Tests\Models\DirectoryTree\AbstractContentItem',
99             'Doctrine\Tests\Models\DirectoryTree\File',
100             'Doctrine\Tests\Models\DirectoryTree\Directory',
101         ),
102         'ddc117' => array(
103             'Doctrine\Tests\Models\DDC117\DDC117Article',
104             'Doctrine\Tests\Models\DDC117\DDC117Reference',
105             'Doctrine\Tests\Models\DDC117\DDC117Translation',
106             'Doctrine\Tests\Models\DDC117\DDC117ArticleDetails',
107             'Doctrine\Tests\Models\DDC117\DDC117ApproveChanges',
108             'Doctrine\Tests\Models\DDC117\DDC117Editor',
109             'Doctrine\Tests\Models\DDC117\DDC117Link',
110         ),
111         'stockexchange' => array(
112             'Doctrine\Tests\Models\StockExchange\Bond',
113             'Doctrine\Tests\Models\StockExchange\Stock',
114             'Doctrine\Tests\Models\StockExchange\Market',
115         ),
116         'legacy' => array(
117             'Doctrine\Tests\Models\Legacy\LegacyUser',
118             'Doctrine\Tests\Models\Legacy\LegacyUserReference',
119             'Doctrine\Tests\Models\Legacy\LegacyArticle',
120             'Doctrine\Tests\Models\Legacy\LegacyCar',
121         ),
122         'customtype' => array(
123             'Doctrine\Tests\Models\CustomType\CustomTypeChild',
124             'Doctrine\Tests\Models\CustomType\CustomTypeParent',
125             'Doctrine\Tests\Models\CustomType\CustomTypeUpperCase',
126         ),
127     );
128
129     protected function useModelSet($setName)
130     {
131         $this->_usedModelSets[$setName] = true;
132     }
133
134     /**
135      * Sweeps the database tables and clears the EntityManager.
136      */
137     protected function tearDown()
138     {
139         $conn = static::$_sharedConn;
140
141         $this->_sqlLoggerStack->enabled = false;
142
143         if (isset($this->_usedModelSets['cms'])) {
144             $conn->executeUpdate('DELETE FROM cms_users_groups');
145             $conn->executeUpdate('DELETE FROM cms_groups');
146             $conn->executeUpdate('DELETE FROM cms_addresses');
147             $conn->executeUpdate('DELETE FROM cms_phonenumbers');
148             $conn->executeUpdate('DELETE FROM cms_comments');
149             $conn->executeUpdate('DELETE FROM cms_articles');
150             $conn->executeUpdate('DELETE FROM cms_users');
151             $conn->executeUpdate('DELETE FROM cms_emails');
152         }
153
154         if (isset($this->_usedModelSets['ecommerce'])) {
155             $conn->executeUpdate('DELETE FROM ecommerce_carts_products');
156             $conn->executeUpdate('DELETE FROM ecommerce_products_categories');
157             $conn->executeUpdate('DELETE FROM ecommerce_products_related');
158             $conn->executeUpdate('DELETE FROM ecommerce_carts');
159             $conn->executeUpdate('DELETE FROM ecommerce_customers');
160             $conn->executeUpdate('DELETE FROM ecommerce_features');
161             $conn->executeUpdate('DELETE FROM ecommerce_products');
162             $conn->executeUpdate('DELETE FROM ecommerce_shippings');
163             $conn->executeUpdate('UPDATE ecommerce_categories SET parent_id = NULL');
164             $conn->executeUpdate('DELETE FROM ecommerce_categories');
165         }
166
167         if (isset($this->_usedModelSets['company'])) {
168             $conn->executeUpdate('DELETE FROM company_contract_employees');
169             $conn->executeUpdate('DELETE FROM company_contract_managers');
170             $conn->executeUpdate('DELETE FROM company_contracts');
171             $conn->executeUpdate('DELETE FROM company_persons_friends');
172             $conn->executeUpdate('DELETE FROM company_managers');
173             $conn->executeUpdate('DELETE FROM company_employees');
174             $conn->executeUpdate('UPDATE company_persons SET spouse_id = NULL');
175             $conn->executeUpdate('DELETE FROM company_persons');
176             $conn->executeUpdate('DELETE FROM company_raffles');
177             $conn->executeUpdate('DELETE FROM company_auctions');
178             $conn->executeUpdate('UPDATE company_organizations SET main_event_id = NULL');
179             $conn->executeUpdate('DELETE FROM company_events');
180             $conn->executeUpdate('DELETE FROM company_organizations');
181         }
182
183         if (isset($this->_usedModelSets['generic'])) {
184             $conn->executeUpdate('DELETE FROM boolean_model');
185             $conn->executeUpdate('DELETE FROM date_time_model');
186             $conn->executeUpdate('DELETE FROM decimal_model');
187             $conn->executeUpdate('DELETE FROM serialize_model');
188         }
189
190         if (isset($this->_usedModelSets['routing'])) {
191             $conn->executeUpdate('DELETE FROM RoutingRouteLegs');
192             $conn->executeUpdate('DELETE FROM RoutingRouteBooking');
193             $conn->executeUpdate('DELETE FROM RoutingRoute');
194             $conn->executeUpdate('DELETE FROM RoutingLeg');
195             $conn->executeUpdate('DELETE FROM RoutingLocation');
196         }
197
198         if(isset($this->_usedModelSets['navigation'])) {
199             $conn->executeUpdate('DELETE FROM navigation_tour_pois');
200             $conn->executeUpdate('DELETE FROM navigation_photos');
201             $conn->executeUpdate('DELETE FROM navigation_pois');
202             $conn->executeUpdate('DELETE FROM navigation_tours');
203             $conn->executeUpdate('DELETE FROM navigation_countries');
204         }
205         if (isset($this->_usedModelSets['directorytree'])) {
206             $conn->executeUpdate('DELETE FROM ' . $this->_em->getConnection()->getDatabasePlatform()->quoteIdentifier("file"));
207             // MySQL doesnt know deferred deletions therefore only executing the second query gives errors.
208             $conn->executeUpdate('DELETE FROM Directory WHERE parentDirectory_id IS NOT NULL');
209             $conn->executeUpdate('DELETE FROM Directory');
210         }
211         if (isset($this->_usedModelSets['ddc117'])) {
212             $conn->executeUpdate('DELETE FROM ddc117editor_ddc117translation');
213             $conn->executeUpdate('DELETE FROM DDC117Editor');
214             $conn->executeUpdate('DELETE FROM DDC117ApproveChanges');
215             $conn->executeUpdate('DELETE FROM DDC117Link');
216             $conn->executeUpdate('DELETE FROM DDC117Reference');
217             $conn->executeUpdate('DELETE FROM DDC117ArticleDetails');
218             $conn->executeUpdate('DELETE FROM DDC117Translation');
219             $conn->executeUpdate('DELETE FROM DDC117Article');
220         }
221         if (isset($this->_usedModelSets['stockexchange'])) {
222             $conn->executeUpdate('DELETE FROM exchange_bonds_stocks');
223             $conn->executeUpdate('DELETE FROM exchange_bonds');
224             $conn->executeUpdate('DELETE FROM exchange_stocks');
225             $conn->executeUpdate('DELETE FROM exchange_markets');
226         }
227         if (isset($this->_usedModelSets['legacy'])) {
228             $conn->executeUpdate('DELETE FROM legacy_users_cars');
229             $conn->executeUpdate('DELETE FROM legacy_users_reference');
230             $conn->executeUpdate('DELETE FROM legacy_articles');
231             $conn->executeUpdate('DELETE FROM legacy_cars');
232             $conn->executeUpdate('DELETE FROM legacy_users');
233         }
234
235         if (isset($this->_usedModelSets['customtype'])) {
236             $conn->executeUpdate('DELETE FROM customtype_parent_friends');
237             $conn->executeUpdate('DELETE FROM customtype_parents');
238             $conn->executeUpdate('DELETE FROM customtype_children');
239             $conn->executeUpdate('DELETE FROM customtype_uppercases');
240         }
241
242         $this->_em->clear();
243     }
244
245     protected function setUpEntitySchema(array $classNames)
246     {
247         if ($this->_em === null) {
248             throw new \RuntimeException("EntityManager not set, you have to call parent::setUp() before invoking this method.");
249         }
250
251         $classes = array();
252         foreach ($classNames as $className) {
253             if ( ! isset(static::$_entityTablesCreated[$className])) {
254                 static::$_entityTablesCreated[$className] = true;
255                 $classes[] = $this->_em->getClassMetadata($className);
256             }
257         }
258
259         if ($classes) {
260             $this->_schemaTool->createSchema($classes);
261         }
262     }
263
264     /**
265      * Creates a connection to the test database, if there is none yet, and
266      * creates the necessary tables.
267      */
268     protected function setUp()
269     {
270         $forceCreateTables = false;
271
272         if ( ! isset(static::$_sharedConn)) {
273             static::$_sharedConn = TestUtil::getConnection();
274
275             if (static::$_sharedConn->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
276                 $forceCreateTables = true;
277             }
278         }
279
280         if (isset($GLOBALS['DOCTRINE_MARK_SQL_LOGS'])) {
281             if (in_array(static::$_sharedConn->getDatabasePlatform()->getName(), array("mysql", "postgresql"))) {
282                 static::$_sharedConn->executeQuery('SELECT 1 /*' . get_class($this) . '*/');
283             } else if (static::$_sharedConn->getDatabasePlatform()->getName() == "oracle") {
284                 static::$_sharedConn->executeQuery('SELECT 1 /*' . get_class($this) . '*/ FROM dual');
285             }
286         }
287
288         if ( ! $this->_em) {
289             $this->_em = $this->_getEntityManager();
290             $this->_schemaTool = new \Doctrine\ORM\Tools\SchemaTool($this->_em);
291         }
292
293         $classes = array();
294
295         foreach ($this->_usedModelSets as $setName => $bool) {
296             if ( ! isset(static::$_tablesCreated[$setName])/* || $forceCreateTables*/) {
297                 foreach (static::$_modelSets[$setName] as $className) {
298                     $classes[] = $this->_em->getClassMetadata($className);
299                 }
300
301                 static::$_tablesCreated[$setName] = true;
302             }
303         }
304
305         if ($classes) {
306             $this->_schemaTool->createSchema($classes);
307         }
308
309         $this->_sqlLoggerStack->enabled = true;
310     }
311
312     /**
313      * Gets an EntityManager for testing purposes.
314      *
315      * @param Configuration $config The Configuration to pass to the EntityManager.
316      * @param EventManager $eventManager The EventManager to pass to the EntityManager.
317      * @return EntityManager
318      */
319     protected function _getEntityManager($config = null, $eventManager = null) {
320         // NOTE: Functional tests use their own shared metadata cache, because
321         // the actual database platform used during execution has effect on some
322         // metadata mapping behaviors (like the choice of the ID generation).
323         if (is_null(self::$_metadataCacheImpl)) {
324             if (isset($GLOBALS['DOCTRINE_CACHE_IMPL'])) {
325                 self::$_metadataCacheImpl = new $GLOBALS['DOCTRINE_CACHE_IMPL'];
326             } else {
327                 self::$_metadataCacheImpl = new \Doctrine\Common\Cache\ArrayCache;
328             }
329         }
330
331         if (is_null(self::$_queryCacheImpl)) {
332             self::$_queryCacheImpl = new \Doctrine\Common\Cache\ArrayCache;
333         }
334
335         $this->_sqlLoggerStack = new \Doctrine\DBAL\Logging\DebugStack();
336         $this->_sqlLoggerStack->enabled = false;
337
338         //FIXME: two different configs! $conn and the created entity manager have
339         // different configs.
340         $config = new \Doctrine\ORM\Configuration();
341         $config->setMetadataCacheImpl(self::$_metadataCacheImpl);
342         $config->setQueryCacheImpl(self::$_queryCacheImpl);
343         $config->setProxyDir(__DIR__ . '/Proxies');
344         $config->setProxyNamespace('Doctrine\Tests\Proxies');
345
346         $config->setMetadataDriverImpl($config->newDefaultAnnotationDriver(array(), true));
347
348         $conn = static::$_sharedConn;
349         $conn->getConfiguration()->setSQLLogger($this->_sqlLoggerStack);
350
351         // get rid of more global state
352         $evm = $conn->getEventManager();
353         foreach ($evm->getListeners() AS $event => $listeners) {
354             foreach ($listeners AS $listener) {
355                 $evm->removeEventListener(array($event), $listener);
356             }
357         }
358
359         if (isset($GLOBALS['db_event_subscribers'])) {
360             foreach (explode(",", $GLOBALS['db_event_subscribers']) AS $subscriberClass) {
361                 $subscriberInstance = new $subscriberClass();
362                 $evm->addEventSubscriber($subscriberInstance);
363             }
364         }
365
366         if (isset($GLOBALS['debug_uow_listener'])) {
367             $evm->addEventListener(array('onFlush'), new \Doctrine\ORM\Tools\DebugUnitOfWorkListener());
368         }
369
370         return \Doctrine\ORM\EntityManager::create($conn, $config);
371     }
372
373     protected function onNotSuccessfulTest(\Exception $e)
374     {
375         if ($e instanceof \PHPUnit_Framework_AssertionFailedError) {
376             throw $e;
377         }
378
379         if(isset($this->_sqlLoggerStack->queries) && count($this->_sqlLoggerStack->queries)) {
380             $queries = "";
381             for($i = count($this->_sqlLoggerStack->queries)-1; $i > max(count($this->_sqlLoggerStack->queries)-25, 0) && isset($this->_sqlLoggerStack->queries[$i]); $i--) {
382                 $query = $this->_sqlLoggerStack->queries[$i];
383                 $params = array_map(function($p) { if (is_object($p)) return get_class($p); else return "'".$p."'"; }, $query['params'] ?: array());
384                 $queries .= ($i+1).". SQL: '".$query['sql']."' Params: ".implode(", ", $params).PHP_EOL;
385             }
386
387             $trace = $e->getTrace();
388             $traceMsg = "";
389             foreach($trace AS $part) {
390                 if(isset($part['file'])) {
391                     if(strpos($part['file'], "PHPUnit/") !== false) {
392                         // Beginning with PHPUnit files we don't print the trace anymore.
393                         break;
394                     }
395
396                     $traceMsg .= $part['file'].":".$part['line'].PHP_EOL;
397                 }
398             }
399
400             $message = "[".get_class($e)."] ".$e->getMessage().PHP_EOL.PHP_EOL."With queries:".PHP_EOL.$queries.PHP_EOL."Trace:".PHP_EOL.$traceMsg;
401
402             throw new \Exception($message, (int)$e->getCode(), $e);
403         }
404         throw $e;
405     }
406
407     /**
408      * Using the SQL Logger Stack this method retrieves the current query count executed in this test.
409      *
410      * @return int
411      */
412     protected function getCurrentQueryCount()
413     {
414         return count($this->_sqlLoggerStack->queries);
415     }
416 }