OrmFunctionalTestCase.php 9.1 KB
Newer Older
romanb's avatar
romanb committed
1
<?php
romanb's avatar
romanb committed
2

3
namespace Doctrine\Tests;
romanb's avatar
romanb committed
4

romanb's avatar
romanb committed
5
/**
6
 * Base testcase class for all functional ORM testcases.
romanb's avatar
romanb committed
7
 *
8
 * @since 2.0
romanb's avatar
romanb committed
9
 */
10
class OrmFunctionalTestCase extends OrmTestCase
romanb's avatar
romanb committed
11
{
12 13
    /* The metadata cache shared between all functional tests. */
    private static $_metadataCacheImpl = null;
14 15
    /* The query cache shared between all functional tests. */
    private static $_queryCacheImpl = null;
16

17 18 19
    /* Shared connection when a TestCase is run alone (outside of it's functional suite) */
    private static $_sharedConn;
    
20 21 22
    /**
     * @var \Doctrine\ORM\EntityManager
     */
23 24
    protected $_em;

25 26 27
    /**
     * @var \Doctrine\ORM\Tools\SchemaTool
     */
28
    protected $_schemaTool;
29

30 31 32 33 34
    /**
     * @var \Doctrine\DBAL\Logging\DebugStack
     */
    protected $_sqlLoggerStack;

35 36 37 38 39 40 41 42 43 44 45 46
    /** The names of the model sets used in this testcase. */
    private $_usedModelSets = array();

    /** Whether the database schema has already been created. */
    private static $_tablesCreated = array();

    /** List of model sets and their classes. */
    private static $_modelSets = array(
        'cms' => array(
            'Doctrine\Tests\Models\CMS\CmsUser',
            'Doctrine\Tests\Models\CMS\CmsPhonenumber',
            'Doctrine\Tests\Models\CMS\CmsAddress',
47 48
            'Doctrine\Tests\Models\CMS\CmsGroup',
            'Doctrine\Tests\Models\CMS\CmsArticle'
49 50
        ),
        'forum' => array(),
51 52 53
        'company' => array(
            'Doctrine\Tests\Models\Company\CompanyPerson',
            'Doctrine\Tests\Models\Company\CompanyEmployee',
romanb's avatar
romanb committed
54 55 56 57
            'Doctrine\Tests\Models\Company\CompanyManager',
            'Doctrine\Tests\Models\Company\CompanyOrganization',
            'Doctrine\Tests\Models\Company\CompanyEvent',
            'Doctrine\Tests\Models\Company\CompanyAuction',
58 59
            'Doctrine\Tests\Models\Company\CompanyRaffle',
            'Doctrine\Tests\Models\Company\CompanyCar'
60
        ),
piccoloprincipe's avatar
piccoloprincipe committed
61 62
        'ecommerce' => array(
            'Doctrine\Tests\Models\ECommerce\ECommerceCart',
63 64
            'Doctrine\Tests\Models\ECommerce\ECommerceCustomer',
            'Doctrine\Tests\Models\ECommerce\ECommerceProduct',
65
            'Doctrine\Tests\Models\ECommerce\ECommerceShipping',
66 67
            'Doctrine\Tests\Models\ECommerce\ECommerceFeature',
            'Doctrine\Tests\Models\ECommerce\ECommerceCategory'
piccoloprincipe's avatar
piccoloprincipe committed
68
        ),
69 70 71
        'generic' => array(
            'Doctrine\Tests\Models\Generic\DateTimeModel'
        )
72 73 74
    );

    protected function useModelSet($setName)
romanb's avatar
romanb committed
75
    {
76
        $this->_usedModelSets[$setName] = true;
romanb's avatar
romanb committed
77 78 79
    }
    
    /**
80
     * Sweeps the database tables and clears the EntityManager.
romanb's avatar
romanb committed
81 82 83
     */
    protected function tearDown()
    {
84
        $conn = $this->sharedFixture['conn'];
85 86

        $this->_sqlLoggerStack->enabled = false;
87
        
88
        if (isset($this->_usedModelSets['cms'])) {
89 90 91 92 93 94
            $conn->executeUpdate('DELETE FROM cms_users_groups');
            $conn->executeUpdate('DELETE FROM cms_groups');
            $conn->executeUpdate('DELETE FROM cms_addresses');
            $conn->executeUpdate('DELETE FROM cms_phonenumbers');
            $conn->executeUpdate('DELETE FROM cms_articles');
            $conn->executeUpdate('DELETE FROM cms_users');
romanb's avatar
romanb committed
95
        }
96
        
piccoloprincipe's avatar
piccoloprincipe committed
97
        if (isset($this->_usedModelSets['ecommerce'])) {
98 99 100 101 102 103 104 105
            $conn->executeUpdate('DELETE FROM ecommerce_carts_products');
            $conn->executeUpdate('DELETE FROM ecommerce_products_categories');
            $conn->executeUpdate('DELETE FROM ecommerce_products_related');
            $conn->executeUpdate('DELETE FROM ecommerce_carts');
            $conn->executeUpdate('DELETE FROM ecommerce_customers');
            $conn->executeUpdate('DELETE FROM ecommerce_features');
            $conn->executeUpdate('DELETE FROM ecommerce_products');
            $conn->executeUpdate('DELETE FROM ecommerce_shippings');
106
            $conn->executeUpdate('UPDATE ecommerce_categories SET parent_id = NULL');
107
            $conn->executeUpdate('DELETE FROM ecommerce_categories');
piccoloprincipe's avatar
piccoloprincipe committed
108
        }
109
        
110
        if (isset($this->_usedModelSets['company'])) {
111 112 113
            $conn->executeUpdate('DELETE FROM company_persons_friends');
            $conn->executeUpdate('DELETE FROM company_managers');
            $conn->executeUpdate('DELETE FROM company_employees');
114
            $conn->executeUpdate('UPDATE company_persons SET spouse_id = NULL');
115 116 117
            $conn->executeUpdate('DELETE FROM company_persons');
            $conn->executeUpdate('DELETE FROM company_raffles');
            $conn->executeUpdate('DELETE FROM company_auctions');
118
            $conn->executeUpdate('UPDATE company_organizations SET main_event_id = NULL');
119 120
            $conn->executeUpdate('DELETE FROM company_events');
            $conn->executeUpdate('DELETE FROM company_organizations');
121
        }
122
        
123
        if (isset($this->_usedModelSets['generic'])) {
124
            $conn->executeUpdate('DELETE FROM date_time_model');
125
        }
126
        
127
        $this->_em->clear();
romanb's avatar
romanb committed
128
    }
129

130 131 132 133
    /**
     * Creates a connection to the test database, if there is none yet, and
     * creates the necessary tables.
     */
134 135
    protected function setUp()
    {
136
        $forceCreateTables = false;
137
        
138
        if ( ! isset($this->sharedFixture['conn'])) {
139 140 141
            if ( ! isset(self::$_sharedConn)) {
                self::$_sharedConn = TestUtil::getConnection();
            }
142
            
143
            $this->sharedFixture['conn'] = self::$_sharedConn;
144
            
145 146 147
            if ($this->sharedFixture['conn']->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
                $forceCreateTables = true;
            }
148
        }
149
        
150 151
        if ( ! $this->_em) {
            $this->_em = $this->_getEntityManager();
152 153 154 155
            $this->_schemaTool = new \Doctrine\ORM\Tools\SchemaTool($this->_em);
        }

        $classes = array();
156
        
157
        foreach ($this->_usedModelSets as $setName => $bool) {
romanb's avatar
romanb committed
158
            if ( ! isset(self::$_tablesCreated[$setName])/* || $forceCreateTables*/) {
159 160 161
                foreach (self::$_modelSets[$setName] as $className) {
                    $classes[] = $this->_em->getClassMetadata($className);
                }
162
                
163 164 165
                self::$_tablesCreated[$setName] = true;
            }
        }
166
        
167
        if ($classes) {
romanb's avatar
romanb committed
168
            $this->_schemaTool->createSchema($classes);
169
        }
170 171

        $this->_sqlLoggerStack->enabled = true;
172 173
    }

174 175 176 177 178 179 180
    /**
     * Gets an EntityManager for testing purposes.
     *
     * @param Configuration $config The Configuration to pass to the EntityManager.
     * @param EventManager $eventManager The EventManager to pass to the EntityManager.
     * @return EntityManager
     */
181
    protected function _getEntityManager($config = null, $eventManager = null) {
182 183 184 185
        // NOTE: Functional tests use their own shared metadata cache, because
        // the actual database platform used during execution has effect on some
        // metadata mapping behaviors (like the choice of the ID generation).
        if (is_null(self::$_metadataCacheImpl)) {
186
            self::$_metadataCacheImpl = new \Doctrine\Common\Cache\ArrayCache;
187
        }
188
        
189
        if (is_null(self::$_queryCacheImpl)) {
190
        	self::$_queryCacheImpl = new \Doctrine\Common\Cache\ArrayCache;
191
        }
192 193 194

        $this->_sqlLoggerStack = new \Doctrine\DBAL\Logging\DebugStack();
        $this->_sqlLoggerStack->enabled = false;
195
        
romanb's avatar
romanb committed
196 197
        //FIXME: two different configs! $conn and the created entity manager have
        // different configs.
198
        $config = new \Doctrine\ORM\Configuration();
199
        $config->setMetadataCacheImpl(self::$_metadataCacheImpl);
200
        $config->setQueryCacheImpl(self::$_queryCacheImpl);
201 202
        $config->setProxyDir(__DIR__ . '/Proxies');
        $config->setProxyNamespace('Doctrine\Tests\Proxies');
203
        
204
        $conn = $this->sharedFixture['conn'];
205
        $conn->getConfiguration()->setSqlLogger($this->_sqlLoggerStack);
206
        
207
        return \Doctrine\ORM\EntityManager::create($conn, $config);
208
    }
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

    protected function onNotSuccessfulTest(\Exception $e)
    {
        if($this->_sqlLoggerStack->queries !== null && count($this->_sqlLoggerStack->queries)) {
            $queries = "";
            for($i = 0; $i < count($this->_sqlLoggerStack->queries); $i++) {
                $query = $this->_sqlLoggerStack->queries[$i];
                $params = array_map(function($p) { return "'".$p."'"; }, $query['params']);
                $queries .= ($i+1).". SQL: '".$query['sql']."' Params: ".implode(", ", $params).PHP_EOL;
            }
            
            $trace = $e->getTrace();
            $traceMsg = "";
            foreach($trace AS $part) {
                if(isset($part['file'])) {
                    if(strpos($part['file'], "PHPUnit/") !== false) {
                        // Beginning with PHPUnit files we don't print the trace anymore.
                        break;
                    }

                    $traceMsg .= $part['file'].":".$part['line'].PHP_EOL;
                }
            }

            $message = "[".get_class($e)."] ".$e->getMessage().PHP_EOL.PHP_EOL."With queries:".PHP_EOL.$queries.PHP_EOL."Trace:".PHP_EOL.$traceMsg;

            throw new \Exception($message, (int)$e->getCode(), $e);
        }
        throw $e;
    }
piccoloprincipe's avatar
piccoloprincipe committed
239
}