1 | <?php |
||||||
2 | |||||||
3 | namespace Doctrine\Tests; |
||||||
4 | |||||||
5 | use Doctrine\Common\Cache\ArrayCache; |
||||||
6 | use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver; |
||||||
7 | use Doctrine\DBAL\Driver\Connection; |
||||||
8 | use Doctrine\DBAL\Driver\PDOSqlite\Driver as SqliteDriver; |
||||||
9 | use Doctrine\DBAL\Logging\DebugStack; |
||||||
10 | use Doctrine\DBAL\Types\Type; |
||||||
11 | use Doctrine\ORM\Cache\CacheConfiguration; |
||||||
12 | use Doctrine\ORM\Cache\DefaultCacheFactory; |
||||||
13 | use Doctrine\ORM\Cache\Logging\StatisticsCacheLogger; |
||||||
14 | use Doctrine\ORM\Configuration; |
||||||
15 | use Doctrine\ORM\EntityManager; |
||||||
16 | use Doctrine\ORM\Tools\DebugUnitOfWorkListener; |
||||||
17 | use Doctrine\ORM\Tools\SchemaTool; |
||||||
18 | use Doctrine\Tests\DbalTypes\Rot13Type; |
||||||
19 | use Doctrine\Tests\EventListener\CacheMetadataListener; |
||||||
20 | use Doctrine\Tests\Models; |
||||||
21 | use PHPUnit\Framework\AssertionFailedError; |
||||||
22 | |||||||
23 | /** |
||||||
24 | * Base testcase class for all functional ORM testcases. |
||||||
25 | * |
||||||
26 | * @since 2.0 |
||||||
27 | */ |
||||||
28 | abstract class OrmFunctionalTestCase extends OrmTestCase |
||||||
29 | { |
||||||
30 | /** |
||||||
31 | * The metadata cache shared between all functional tests. |
||||||
32 | * |
||||||
33 | * @var \Doctrine\Common\Cache\Cache|null |
||||||
34 | */ |
||||||
35 | private static $_metadataCacheImpl = null; |
||||||
36 | |||||||
37 | /** |
||||||
38 | * The query cache shared between all functional tests. |
||||||
39 | * |
||||||
40 | * @var \Doctrine\Common\Cache\Cache|null |
||||||
41 | */ |
||||||
42 | private static $_queryCacheImpl = null; |
||||||
43 | |||||||
44 | /** |
||||||
45 | * Shared connection when a TestCase is run alone (outside of its functional suite). |
||||||
46 | * |
||||||
47 | * @var \Doctrine\DBAL\Connection|null |
||||||
48 | */ |
||||||
49 | protected static $_sharedConn; |
||||||
50 | |||||||
51 | /** |
||||||
52 | * @var \Doctrine\ORM\EntityManager |
||||||
53 | */ |
||||||
54 | protected $_em; |
||||||
55 | |||||||
56 | /** |
||||||
57 | * @var \Doctrine\ORM\Tools\SchemaTool |
||||||
58 | */ |
||||||
59 | protected $_schemaTool; |
||||||
60 | |||||||
61 | /** |
||||||
62 | * @var \Doctrine\DBAL\Logging\DebugStack |
||||||
63 | */ |
||||||
64 | protected $_sqlLoggerStack; |
||||||
65 | |||||||
66 | /** |
||||||
67 | * The names of the model sets used in this testcase. |
||||||
68 | * |
||||||
69 | * @var array |
||||||
70 | */ |
||||||
71 | protected $_usedModelSets = []; |
||||||
72 | |||||||
73 | /** |
||||||
74 | * To be configured by the test that uses result set cache |
||||||
75 | * |
||||||
76 | * @var \Doctrine\Common\Cache\Cache|null |
||||||
77 | */ |
||||||
78 | protected $resultCacheImpl; |
||||||
79 | |||||||
80 | /** |
||||||
81 | * Whether the database schema has already been created. |
||||||
82 | * |
||||||
83 | * @var array |
||||||
84 | */ |
||||||
85 | protected static $_tablesCreated = []; |
||||||
86 | |||||||
87 | /** |
||||||
88 | * Array of entity class name to their tables that were created. |
||||||
89 | * |
||||||
90 | * @var array |
||||||
91 | */ |
||||||
92 | protected static $_entityTablesCreated = []; |
||||||
93 | |||||||
94 | /** |
||||||
95 | * List of model sets and their classes. |
||||||
96 | * |
||||||
97 | * @var array |
||||||
98 | */ |
||||||
99 | protected static $_modelSets = [ |
||||||
100 | 'cms' => [ |
||||||
101 | Models\CMS\CmsUser::class, |
||||||
102 | Models\CMS\CmsPhonenumber::class, |
||||||
103 | Models\CMS\CmsAddress::class, |
||||||
104 | Models\CMS\CmsEmail::class, |
||||||
105 | Models\CMS\CmsGroup::class, |
||||||
106 | Models\CMS\CmsTag::class, |
||||||
107 | Models\CMS\CmsArticle::class, |
||||||
108 | Models\CMS\CmsComment::class, |
||||||
109 | ], |
||||||
110 | 'company' => [ |
||||||
111 | Models\Company\CompanyPerson::class, |
||||||
112 | Models\Company\CompanyEmployee::class, |
||||||
113 | Models\Company\CompanyManager::class, |
||||||
114 | Models\Company\CompanyOrganization::class, |
||||||
115 | Models\Company\CompanyEvent::class, |
||||||
116 | Models\Company\CompanyAuction::class, |
||||||
117 | Models\Company\CompanyRaffle::class, |
||||||
118 | Models\Company\CompanyCar::class, |
||||||
119 | Models\Company\CompanyContract::class, |
||||||
120 | ], |
||||||
121 | 'ecommerce' => [ |
||||||
122 | Models\ECommerce\ECommerceCart::class, |
||||||
123 | Models\ECommerce\ECommerceCustomer::class, |
||||||
124 | Models\ECommerce\ECommerceProduct::class, |
||||||
125 | Models\ECommerce\ECommerceShipping::class, |
||||||
126 | Models\ECommerce\ECommerceFeature::class, |
||||||
127 | Models\ECommerce\ECommerceCategory::class |
||||||
128 | ], |
||||||
129 | 'generic' => [ |
||||||
130 | Models\Generic\BooleanModel::class, |
||||||
131 | Models\Generic\DateTimeModel::class, |
||||||
132 | Models\Generic\DecimalModel::class, |
||||||
133 | Models\Generic\SerializationModel::class, |
||||||
134 | ], |
||||||
135 | 'routing' => [ |
||||||
136 | Models\Routing\RoutingLeg::class, |
||||||
137 | Models\Routing\RoutingLocation::class, |
||||||
138 | Models\Routing\RoutingRoute::class, |
||||||
139 | Models\Routing\RoutingRouteBooking::class, |
||||||
140 | ], |
||||||
141 | 'navigation' => [ |
||||||
142 | Models\Navigation\NavUser::class, |
||||||
143 | Models\Navigation\NavCountry::class, |
||||||
144 | Models\Navigation\NavPhotos::class, |
||||||
145 | Models\Navigation\NavTour::class, |
||||||
146 | Models\Navigation\NavPointOfInterest::class, |
||||||
147 | ], |
||||||
148 | 'directorytree' => [ |
||||||
149 | Models\DirectoryTree\AbstractContentItem::class, |
||||||
150 | Models\DirectoryTree\File::class, |
||||||
151 | Models\DirectoryTree\Directory::class, |
||||||
152 | ], |
||||||
153 | 'ddc117' => [ |
||||||
154 | Models\DDC117\DDC117Article::class, |
||||||
155 | Models\DDC117\DDC117Reference::class, |
||||||
156 | Models\DDC117\DDC117Translation::class, |
||||||
157 | Models\DDC117\DDC117ArticleDetails::class, |
||||||
158 | Models\DDC117\DDC117ApproveChanges::class, |
||||||
159 | Models\DDC117\DDC117Editor::class, |
||||||
160 | Models\DDC117\DDC117Link::class, |
||||||
161 | ], |
||||||
162 | 'ddc3699' => [ |
||||||
163 | Models\DDC3699\DDC3699Parent::class, |
||||||
164 | Models\DDC3699\DDC3699RelationOne::class, |
||||||
165 | Models\DDC3699\DDC3699RelationMany::class, |
||||||
166 | Models\DDC3699\DDC3699Child::class, |
||||||
167 | ], |
||||||
168 | 'stockexchange' => [ |
||||||
169 | Models\StockExchange\Bond::class, |
||||||
170 | Models\StockExchange\Stock::class, |
||||||
171 | Models\StockExchange\Market::class, |
||||||
172 | ], |
||||||
173 | 'legacy' => [ |
||||||
174 | Models\Legacy\LegacyUser::class, |
||||||
175 | Models\Legacy\LegacyUserReference::class, |
||||||
176 | Models\Legacy\LegacyArticle::class, |
||||||
177 | Models\Legacy\LegacyCar::class, |
||||||
178 | ], |
||||||
179 | 'customtype' => [ |
||||||
180 | Models\CustomType\CustomTypeChild::class, |
||||||
181 | Models\CustomType\CustomTypeParent::class, |
||||||
182 | Models\CustomType\CustomTypeUpperCase::class, |
||||||
183 | ], |
||||||
184 | 'compositekeyinheritance' => [ |
||||||
185 | Models\CompositeKeyInheritance\JoinedRootClass::class, |
||||||
186 | Models\CompositeKeyInheritance\JoinedChildClass::class, |
||||||
187 | Models\CompositeKeyInheritance\SingleRootClass::class, |
||||||
188 | Models\CompositeKeyInheritance\SingleChildClass::class, |
||||||
189 | ], |
||||||
190 | 'taxi' => [ |
||||||
191 | Models\Taxi\PaidRide::class, |
||||||
192 | Models\Taxi\Ride::class, |
||||||
193 | Models\Taxi\Car::class, |
||||||
194 | Models\Taxi\Driver::class, |
||||||
195 | ], |
||||||
196 | 'cache' => [ |
||||||
197 | Models\Cache\Country::class, |
||||||
198 | Models\Cache\State::class, |
||||||
199 | Models\Cache\City::class, |
||||||
200 | Models\Cache\Traveler::class, |
||||||
201 | Models\Cache\TravelerProfileInfo::class, |
||||||
202 | Models\Cache\TravelerProfile::class, |
||||||
203 | Models\Cache\Travel::class, |
||||||
204 | Models\Cache\Attraction::class, |
||||||
205 | Models\Cache\Restaurant::class, |
||||||
206 | Models\Cache\Beach::class, |
||||||
207 | Models\Cache\Bar::class, |
||||||
208 | Models\Cache\Flight::class, |
||||||
209 | Models\Cache\Token::class, |
||||||
210 | Models\Cache\Login::class, |
||||||
211 | Models\Cache\Client::class, |
||||||
212 | Models\Cache\Person::class, |
||||||
213 | Models\Cache\Address::class, |
||||||
214 | Models\Cache\Action::class, |
||||||
215 | Models\Cache\ComplexAction::class, |
||||||
216 | Models\Cache\AttractionInfo::class, |
||||||
217 | Models\Cache\AttractionContactInfo::class, |
||||||
218 | Models\Cache\AttractionLocationInfo::class |
||||||
219 | ], |
||||||
220 | 'tweet' => [ |
||||||
221 | Models\Tweet\User::class, |
||||||
222 | Models\Tweet\Tweet::class, |
||||||
223 | Models\Tweet\UserList::class, |
||||||
224 | ], |
||||||
225 | 'ddc2504' => [ |
||||||
226 | Models\DDC2504\DDC2504RootClass::class, |
||||||
227 | Models\DDC2504\DDC2504ChildClass::class, |
||||||
228 | Models\DDC2504\DDC2504OtherClass::class, |
||||||
229 | ], |
||||||
230 | 'ddc3346' => [ |
||||||
231 | Models\DDC3346\DDC3346Author::class, |
||||||
232 | Models\DDC3346\DDC3346Article::class, |
||||||
233 | ], |
||||||
234 | 'quote' => [ |
||||||
235 | Models\Quote\Address::class, |
||||||
236 | Models\Quote\City::class, |
||||||
237 | Models\Quote\FullAddress::class, |
||||||
238 | Models\Quote\Group::class, |
||||||
239 | Models\Quote\NumericEntity::class, |
||||||
240 | Models\Quote\Phone::class, |
||||||
241 | Models\Quote\User::class |
||||||
242 | ], |
||||||
243 | 'vct_onetoone' => [ |
||||||
244 | Models\ValueConversionType\InversedOneToOneEntity::class, |
||||||
245 | Models\ValueConversionType\OwningOneToOneEntity::class |
||||||
246 | ], |
||||||
247 | 'vct_onetoone_compositeid' => [ |
||||||
248 | Models\ValueConversionType\InversedOneToOneCompositeIdEntity::class, |
||||||
249 | Models\ValueConversionType\OwningOneToOneCompositeIdEntity::class |
||||||
250 | ], |
||||||
251 | 'vct_onetoone_compositeid_foreignkey' => [ |
||||||
252 | Models\ValueConversionType\AuxiliaryEntity::class, |
||||||
253 | Models\ValueConversionType\InversedOneToOneCompositeIdForeignKeyEntity::class, |
||||||
254 | Models\ValueConversionType\OwningOneToOneCompositeIdForeignKeyEntity::class |
||||||
255 | ], |
||||||
256 | 'vct_onetomany' => [ |
||||||
257 | Models\ValueConversionType\InversedOneToManyEntity::class, |
||||||
258 | Models\ValueConversionType\OwningManyToOneEntity::class |
||||||
259 | ], |
||||||
260 | 'vct_onetomany_compositeid' => [ |
||||||
261 | Models\ValueConversionType\InversedOneToManyCompositeIdEntity::class, |
||||||
262 | Models\ValueConversionType\OwningManyToOneCompositeIdEntity::class |
||||||
263 | ], |
||||||
264 | 'vct_onetomany_compositeid_foreignkey' => [ |
||||||
265 | Models\ValueConversionType\AuxiliaryEntity::class, |
||||||
266 | Models\ValueConversionType\InversedOneToManyCompositeIdForeignKeyEntity::class, |
||||||
267 | Models\ValueConversionType\OwningManyToOneCompositeIdForeignKeyEntity::class |
||||||
268 | ], |
||||||
269 | 'vct_onetomany_extralazy' => [ |
||||||
270 | Models\ValueConversionType\InversedOneToManyExtraLazyEntity::class, |
||||||
271 | Models\ValueConversionType\OwningManyToOneExtraLazyEntity::class |
||||||
272 | ], |
||||||
273 | 'vct_manytomany' => [ |
||||||
274 | Models\ValueConversionType\InversedManyToManyEntity::class, |
||||||
275 | Models\ValueConversionType\OwningManyToManyEntity::class |
||||||
276 | ], |
||||||
277 | 'vct_manytomany_compositeid' => [ |
||||||
278 | Models\ValueConversionType\InversedManyToManyCompositeIdEntity::class, |
||||||
279 | Models\ValueConversionType\OwningManyToManyCompositeIdEntity::class |
||||||
280 | ], |
||||||
281 | 'vct_manytomany_compositeid_foreignkey' => [ |
||||||
282 | Models\ValueConversionType\AuxiliaryEntity::class, |
||||||
283 | Models\ValueConversionType\InversedManyToManyCompositeIdForeignKeyEntity::class, |
||||||
284 | Models\ValueConversionType\OwningManyToManyCompositeIdForeignKeyEntity::class |
||||||
285 | ], |
||||||
286 | 'vct_manytomany_extralazy' => [ |
||||||
287 | Models\ValueConversionType\InversedManyToManyExtraLazyEntity::class, |
||||||
288 | Models\ValueConversionType\OwningManyToManyExtraLazyEntity::class |
||||||
289 | ], |
||||||
290 | 'geonames' => [ |
||||||
291 | Models\GeoNames\Country::class, |
||||||
292 | Models\GeoNames\Admin1::class, |
||||||
293 | Models\GeoNames\Admin1AlternateName::class, |
||||||
294 | Models\GeoNames\City::class |
||||||
295 | ], |
||||||
296 | 'custom_id_object_type' => [ |
||||||
297 | Models\CustomType\CustomIdObjectTypeParent::class, |
||||||
298 | Models\CustomType\CustomIdObjectTypeChild::class, |
||||||
299 | ], |
||||||
300 | 'pagination' => [ |
||||||
301 | Models\Pagination\Company::class, |
||||||
302 | Models\Pagination\Logo::class, |
||||||
303 | Models\Pagination\Department::class, |
||||||
304 | Models\Pagination\User::class, |
||||||
305 | Models\Pagination\User1::class, |
||||||
306 | ], |
||||||
307 | 'versioned_many_to_one' => [ |
||||||
308 | Models\VersionedManyToOne\Category::class, |
||||||
309 | Models\VersionedManyToOne\Article::class, |
||||||
310 | ], |
||||||
311 | 'issue5989' => [ |
||||||
312 | Models\Issue5989\Issue5989Person::class, |
||||||
313 | Models\Issue5989\Issue5989Employee::class, |
||||||
314 | Models\Issue5989\Issue5989Manager::class, |
||||||
315 | ], |
||||||
316 | ]; |
||||||
317 | |||||||
318 | /** |
||||||
319 | * @param string $setName |
||||||
320 | * |
||||||
321 | * @return void |
||||||
322 | */ |
||||||
323 | protected function useModelSet($setName) |
||||||
324 | { |
||||||
325 | $this->_usedModelSets[$setName] = true; |
||||||
326 | } |
||||||
327 | |||||||
328 | /** |
||||||
329 | * Sweeps the database tables and clears the EntityManager. |
||||||
330 | * |
||||||
331 | * @return void |
||||||
332 | */ |
||||||
333 | protected function tearDown() |
||||||
334 | { |
||||||
335 | $conn = static::$_sharedConn; |
||||||
336 | |||||||
337 | // In case test is skipped, tearDown is called, but no setup may have run |
||||||
338 | if ( ! $conn) { |
||||||
339 | return; |
||||||
340 | } |
||||||
341 | |||||||
342 | $platform = $conn->getDatabasePlatform(); |
||||||
343 | |||||||
344 | $this->_sqlLoggerStack->enabled = false; |
||||||
345 | |||||||
346 | if (isset($this->_usedModelSets['cms'])) { |
||||||
347 | $conn->executeUpdate('DELETE FROM cms_users_groups'); |
||||||
348 | $conn->executeUpdate('DELETE FROM cms_groups'); |
||||||
349 | $conn->executeUpdate('DELETE FROM cms_users_tags'); |
||||||
350 | $conn->executeUpdate('DELETE FROM cms_tags'); |
||||||
351 | $conn->executeUpdate('DELETE FROM cms_addresses'); |
||||||
352 | $conn->executeUpdate('DELETE FROM cms_phonenumbers'); |
||||||
353 | $conn->executeUpdate('DELETE FROM cms_comments'); |
||||||
354 | $conn->executeUpdate('DELETE FROM cms_articles'); |
||||||
355 | $conn->executeUpdate('DELETE FROM cms_users'); |
||||||
356 | $conn->executeUpdate('DELETE FROM cms_emails'); |
||||||
357 | } |
||||||
358 | |||||||
359 | if (isset($this->_usedModelSets['ecommerce'])) { |
||||||
360 | $conn->executeUpdate('DELETE FROM ecommerce_carts_products'); |
||||||
361 | $conn->executeUpdate('DELETE FROM ecommerce_products_categories'); |
||||||
362 | $conn->executeUpdate('DELETE FROM ecommerce_products_related'); |
||||||
363 | $conn->executeUpdate('DELETE FROM ecommerce_carts'); |
||||||
364 | $conn->executeUpdate('DELETE FROM ecommerce_customers'); |
||||||
365 | $conn->executeUpdate('DELETE FROM ecommerce_features'); |
||||||
366 | $conn->executeUpdate('DELETE FROM ecommerce_products'); |
||||||
367 | $conn->executeUpdate('DELETE FROM ecommerce_shippings'); |
||||||
368 | $conn->executeUpdate('UPDATE ecommerce_categories SET parent_id = NULL'); |
||||||
369 | $conn->executeUpdate('DELETE FROM ecommerce_categories'); |
||||||
370 | } |
||||||
371 | |||||||
372 | if (isset($this->_usedModelSets['company'])) { |
||||||
373 | $conn->executeUpdate('DELETE FROM company_contract_employees'); |
||||||
374 | $conn->executeUpdate('DELETE FROM company_contract_managers'); |
||||||
375 | $conn->executeUpdate('DELETE FROM company_contracts'); |
||||||
376 | $conn->executeUpdate('DELETE FROM company_persons_friends'); |
||||||
377 | $conn->executeUpdate('DELETE FROM company_managers'); |
||||||
378 | $conn->executeUpdate('DELETE FROM company_employees'); |
||||||
379 | $conn->executeUpdate('UPDATE company_persons SET spouse_id = NULL'); |
||||||
380 | $conn->executeUpdate('DELETE FROM company_persons'); |
||||||
381 | $conn->executeUpdate('DELETE FROM company_raffles'); |
||||||
382 | $conn->executeUpdate('DELETE FROM company_auctions'); |
||||||
383 | $conn->executeUpdate('UPDATE company_organizations SET main_event_id = NULL'); |
||||||
384 | $conn->executeUpdate('DELETE FROM company_events'); |
||||||
385 | $conn->executeUpdate('DELETE FROM company_organizations'); |
||||||
386 | } |
||||||
387 | |||||||
388 | if (isset($this->_usedModelSets['generic'])) { |
||||||
389 | $conn->executeUpdate('DELETE FROM boolean_model'); |
||||||
390 | $conn->executeUpdate('DELETE FROM date_time_model'); |
||||||
391 | $conn->executeUpdate('DELETE FROM decimal_model'); |
||||||
392 | $conn->executeUpdate('DELETE FROM serialize_model'); |
||||||
393 | } |
||||||
394 | |||||||
395 | if (isset($this->_usedModelSets['routing'])) { |
||||||
396 | $conn->executeUpdate('DELETE FROM RoutingRouteLegs'); |
||||||
397 | $conn->executeUpdate('DELETE FROM RoutingRouteBooking'); |
||||||
398 | $conn->executeUpdate('DELETE FROM RoutingRoute'); |
||||||
399 | $conn->executeUpdate('DELETE FROM RoutingLeg'); |
||||||
400 | $conn->executeUpdate('DELETE FROM RoutingLocation'); |
||||||
401 | } |
||||||
402 | |||||||
403 | if(isset($this->_usedModelSets['navigation'])) { |
||||||
404 | $conn->executeUpdate('DELETE FROM navigation_tour_pois'); |
||||||
405 | $conn->executeUpdate('DELETE FROM navigation_photos'); |
||||||
406 | $conn->executeUpdate('DELETE FROM navigation_pois'); |
||||||
407 | $conn->executeUpdate('DELETE FROM navigation_tours'); |
||||||
408 | $conn->executeUpdate('DELETE FROM navigation_countries'); |
||||||
409 | } |
||||||
410 | if (isset($this->_usedModelSets['directorytree'])) { |
||||||
411 | $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier("file")); |
||||||
412 | // MySQL doesn't know deferred deletions therefore only executing the second query gives errors. |
||||||
413 | $conn->executeUpdate('DELETE FROM Directory WHERE parentDirectory_id IS NOT NULL'); |
||||||
414 | $conn->executeUpdate('DELETE FROM Directory'); |
||||||
415 | } |
||||||
416 | if (isset($this->_usedModelSets['ddc117'])) { |
||||||
417 | $conn->executeUpdate('DELETE FROM ddc117editor_ddc117translation'); |
||||||
418 | $conn->executeUpdate('DELETE FROM DDC117Editor'); |
||||||
419 | $conn->executeUpdate('DELETE FROM DDC117ApproveChanges'); |
||||||
420 | $conn->executeUpdate('DELETE FROM DDC117Link'); |
||||||
421 | $conn->executeUpdate('DELETE FROM DDC117Reference'); |
||||||
422 | $conn->executeUpdate('DELETE FROM DDC117ArticleDetails'); |
||||||
423 | $conn->executeUpdate('DELETE FROM DDC117Translation'); |
||||||
424 | $conn->executeUpdate('DELETE FROM DDC117Article'); |
||||||
425 | } |
||||||
426 | if (isset($this->_usedModelSets['stockexchange'])) { |
||||||
427 | $conn->executeUpdate('DELETE FROM exchange_bonds_stocks'); |
||||||
428 | $conn->executeUpdate('DELETE FROM exchange_bonds'); |
||||||
429 | $conn->executeUpdate('DELETE FROM exchange_stocks'); |
||||||
430 | $conn->executeUpdate('DELETE FROM exchange_markets'); |
||||||
431 | } |
||||||
432 | if (isset($this->_usedModelSets['legacy'])) { |
||||||
433 | $conn->executeUpdate('DELETE FROM legacy_users_cars'); |
||||||
434 | $conn->executeUpdate('DELETE FROM legacy_users_reference'); |
||||||
435 | $conn->executeUpdate('DELETE FROM legacy_articles'); |
||||||
436 | $conn->executeUpdate('DELETE FROM legacy_cars'); |
||||||
437 | $conn->executeUpdate('DELETE FROM legacy_users'); |
||||||
438 | } |
||||||
439 | |||||||
440 | if (isset($this->_usedModelSets['customtype'])) { |
||||||
441 | $conn->executeUpdate('DELETE FROM customtype_parent_friends'); |
||||||
442 | $conn->executeUpdate('DELETE FROM customtype_parents'); |
||||||
443 | $conn->executeUpdate('DELETE FROM customtype_children'); |
||||||
444 | $conn->executeUpdate('DELETE FROM customtype_uppercases'); |
||||||
445 | } |
||||||
446 | |||||||
447 | if (isset($this->_usedModelSets['compositekeyinheritance'])) { |
||||||
448 | $conn->executeUpdate('DELETE FROM JoinedChildClass'); |
||||||
449 | $conn->executeUpdate('DELETE FROM JoinedRootClass'); |
||||||
450 | $conn->executeUpdate('DELETE FROM SingleRootClass'); |
||||||
451 | } |
||||||
452 | |||||||
453 | if (isset($this->_usedModelSets['taxi'])) { |
||||||
454 | $conn->executeUpdate('DELETE FROM taxi_paid_ride'); |
||||||
455 | $conn->executeUpdate('DELETE FROM taxi_ride'); |
||||||
456 | $conn->executeUpdate('DELETE FROM taxi_car'); |
||||||
457 | $conn->executeUpdate('DELETE FROM taxi_driver'); |
||||||
458 | } |
||||||
459 | |||||||
460 | if (isset($this->_usedModelSets['tweet'])) { |
||||||
461 | $conn->executeUpdate('DELETE FROM tweet_tweet'); |
||||||
462 | $conn->executeUpdate('DELETE FROM tweet_user_list'); |
||||||
463 | $conn->executeUpdate('DELETE FROM tweet_user'); |
||||||
464 | } |
||||||
465 | |||||||
466 | if (isset($this->_usedModelSets['cache'])) { |
||||||
467 | $conn->executeUpdate('DELETE FROM cache_attraction_location_info'); |
||||||
468 | $conn->executeUpdate('DELETE FROM cache_attraction_contact_info'); |
||||||
469 | $conn->executeUpdate('DELETE FROM cache_attraction_info'); |
||||||
470 | $conn->executeUpdate('DELETE FROM cache_visited_cities'); |
||||||
471 | $conn->executeUpdate('DELETE FROM cache_flight'); |
||||||
472 | $conn->executeUpdate('DELETE FROM cache_attraction'); |
||||||
473 | $conn->executeUpdate('DELETE FROM cache_travel'); |
||||||
474 | $conn->executeUpdate('DELETE FROM cache_traveler'); |
||||||
475 | $conn->executeUpdate('DELETE FROM cache_traveler_profile_info'); |
||||||
476 | $conn->executeUpdate('DELETE FROM cache_traveler_profile'); |
||||||
477 | $conn->executeUpdate('DELETE FROM cache_city'); |
||||||
478 | $conn->executeUpdate('DELETE FROM cache_state'); |
||||||
479 | $conn->executeUpdate('DELETE FROM cache_country'); |
||||||
480 | $conn->executeUpdate('DELETE FROM cache_login'); |
||||||
481 | $conn->executeUpdate('DELETE FROM cache_token'); |
||||||
482 | $conn->executeUpdate('DELETE FROM cache_complex_action'); |
||||||
483 | $conn->executeUpdate('DELETE FROM cache_action'); |
||||||
484 | $conn->executeUpdate('DELETE FROM cache_client'); |
||||||
485 | } |
||||||
486 | |||||||
487 | if (isset($this->_usedModelSets['ddc3346'])) { |
||||||
488 | $conn->executeUpdate('DELETE FROM ddc3346_articles'); |
||||||
489 | $conn->executeUpdate('DELETE FROM ddc3346_users'); |
||||||
490 | } |
||||||
491 | |||||||
492 | if (isset($this->_usedModelSets['ornemental_orphan_removal'])) { |
||||||
493 | $conn->executeUpdate('DELETE FROM ornemental_orphan_removal_person'); |
||||||
494 | $conn->executeUpdate('DELETE FROM ornemental_orphan_removal_phone_number'); |
||||||
495 | } |
||||||
496 | |||||||
497 | if (isset($this->_usedModelSets['quote'])) { |
||||||
498 | $conn->executeUpdate( |
||||||
499 | sprintf( |
||||||
500 | 'UPDATE %s SET %s = NULL', |
||||||
501 | $platform->quoteIdentifier("quote-address"), |
||||||
502 | $platform->quoteIdentifier('user-id') |
||||||
503 | ) |
||||||
504 | ); |
||||||
505 | |||||||
506 | $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-users-groups')); |
||||||
507 | $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-group')); |
||||||
508 | $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-phone')); |
||||||
509 | $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-user')); |
||||||
510 | $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-address')); |
||||||
511 | $conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier('quote-city')); |
||||||
512 | } |
||||||
513 | |||||||
514 | if (isset($this->_usedModelSets['vct_onetoone'])) { |
||||||
515 | $conn->executeUpdate('DELETE FROM vct_owning_onetoone'); |
||||||
516 | $conn->executeUpdate('DELETE FROM vct_inversed_onetoone'); |
||||||
517 | } |
||||||
518 | |||||||
519 | if (isset($this->_usedModelSets['vct_onetoone_compositeid'])) { |
||||||
520 | $conn->executeUpdate('DELETE FROM vct_owning_onetoone_compositeid'); |
||||||
521 | $conn->executeUpdate('DELETE FROM vct_inversed_onetoone_compositeid'); |
||||||
522 | } |
||||||
523 | |||||||
524 | if (isset($this->_usedModelSets['vct_onetoone_compositeid_foreignkey'])) { |
||||||
525 | $conn->executeUpdate('DELETE FROM vct_owning_onetoone_compositeid_foreignkey'); |
||||||
526 | $conn->executeUpdate('DELETE FROM vct_inversed_onetoone_compositeid_foreignkey'); |
||||||
527 | $conn->executeUpdate('DELETE FROM vct_auxiliary'); |
||||||
528 | } |
||||||
529 | |||||||
530 | if (isset($this->_usedModelSets['vct_onetomany'])) { |
||||||
531 | $conn->executeUpdate('DELETE FROM vct_owning_manytoone'); |
||||||
532 | $conn->executeUpdate('DELETE FROM vct_inversed_onetomany'); |
||||||
533 | } |
||||||
534 | |||||||
535 | if (isset($this->_usedModelSets['vct_onetomany_compositeid'])) { |
||||||
536 | $conn->executeUpdate('DELETE FROM vct_owning_manytoone_compositeid'); |
||||||
537 | $conn->executeUpdate('DELETE FROM vct_inversed_onetomany_compositeid'); |
||||||
538 | } |
||||||
539 | |||||||
540 | if (isset($this->_usedModelSets['vct_onetomany_compositeid_foreignkey'])) { |
||||||
541 | $conn->executeUpdate('DELETE FROM vct_owning_manytoone_compositeid_foreignkey'); |
||||||
542 | $conn->executeUpdate('DELETE FROM vct_inversed_onetomany_compositeid_foreignkey'); |
||||||
543 | $conn->executeUpdate('DELETE FROM vct_auxiliary'); |
||||||
544 | } |
||||||
545 | |||||||
546 | if (isset($this->_usedModelSets['vct_onetomany_extralazy'])) { |
||||||
547 | $conn->executeUpdate('DELETE FROM vct_owning_manytoone_extralazy'); |
||||||
548 | $conn->executeUpdate('DELETE FROM vct_inversed_onetomany_extralazy'); |
||||||
549 | } |
||||||
550 | |||||||
551 | if (isset($this->_usedModelSets['vct_manytomany'])) { |
||||||
552 | $conn->executeUpdate('DELETE FROM vct_xref_manytomany'); |
||||||
553 | $conn->executeUpdate('DELETE FROM vct_owning_manytomany'); |
||||||
554 | $conn->executeUpdate('DELETE FROM vct_inversed_manytomany'); |
||||||
555 | } |
||||||
556 | |||||||
557 | if (isset($this->_usedModelSets['vct_manytomany_compositeid'])) { |
||||||
558 | $conn->executeUpdate('DELETE FROM vct_xref_manytomany_compositeid'); |
||||||
559 | $conn->executeUpdate('DELETE FROM vct_owning_manytomany_compositeid'); |
||||||
560 | $conn->executeUpdate('DELETE FROM vct_inversed_manytomany_compositeid'); |
||||||
561 | } |
||||||
562 | |||||||
563 | if (isset($this->_usedModelSets['vct_manytomany_compositeid_foreignkey'])) { |
||||||
564 | $conn->executeUpdate('DELETE FROM vct_xref_manytomany_compositeid_foreignkey'); |
||||||
565 | $conn->executeUpdate('DELETE FROM vct_owning_manytomany_compositeid_foreignkey'); |
||||||
566 | $conn->executeUpdate('DELETE FROM vct_inversed_manytomany_compositeid_foreignkey'); |
||||||
567 | $conn->executeUpdate('DELETE FROM vct_auxiliary'); |
||||||
568 | } |
||||||
569 | |||||||
570 | if (isset($this->_usedModelSets['vct_manytomany_extralazy'])) { |
||||||
571 | $conn->executeUpdate('DELETE FROM vct_xref_manytomany_extralazy'); |
||||||
572 | $conn->executeUpdate('DELETE FROM vct_owning_manytomany_extralazy'); |
||||||
573 | $conn->executeUpdate('DELETE FROM vct_inversed_manytomany_extralazy'); |
||||||
574 | } |
||||||
575 | if (isset($this->_usedModelSets['geonames'])) { |
||||||
576 | $conn->executeUpdate('DELETE FROM geonames_admin1_alternate_name'); |
||||||
577 | $conn->executeUpdate('DELETE FROM geonames_admin1'); |
||||||
578 | $conn->executeUpdate('DELETE FROM geonames_city'); |
||||||
579 | $conn->executeUpdate('DELETE FROM geonames_country'); |
||||||
580 | } |
||||||
581 | |||||||
582 | if (isset($this->_usedModelSets['custom_id_object_type'])) { |
||||||
583 | $conn->executeUpdate('DELETE FROM custom_id_type_child'); |
||||||
584 | $conn->executeUpdate('DELETE FROM custom_id_type_parent'); |
||||||
585 | } |
||||||
586 | |||||||
587 | if (isset($this->_usedModelSets['pagination'])) { |
||||||
588 | $conn->executeUpdate('DELETE FROM pagination_logo'); |
||||||
589 | $conn->executeUpdate('DELETE FROM pagination_department'); |
||||||
590 | $conn->executeUpdate('DELETE FROM pagination_company'); |
||||||
591 | $conn->executeUpdate('DELETE FROM pagination_user'); |
||||||
592 | } |
||||||
593 | |||||||
594 | if (isset($this->_usedModelSets['versioned_many_to_one'])) { |
||||||
595 | $conn->executeUpdate('DELETE FROM versioned_many_to_one_article'); |
||||||
596 | $conn->executeUpdate('DELETE FROM versioned_many_to_one_category'); |
||||||
597 | } |
||||||
598 | |||||||
599 | if (isset($this->_usedModelSets['issue5989'])) { |
||||||
600 | $conn->executeUpdate('DELETE FROM issue5989_persons'); |
||||||
601 | $conn->executeUpdate('DELETE FROM issue5989_employees'); |
||||||
602 | $conn->executeUpdate('DELETE FROM issue5989_managers'); |
||||||
603 | } |
||||||
604 | |||||||
605 | $this->_em->clear(); |
||||||
606 | } |
||||||
607 | |||||||
608 | /** |
||||||
609 | * @param array $classNames |
||||||
610 | * |
||||||
611 | * @return void |
||||||
612 | * |
||||||
613 | * @throws \RuntimeException |
||||||
614 | */ |
||||||
615 | protected function setUpEntitySchema(array $classNames) |
||||||
616 | { |
||||||
617 | if ($this->_em === null) { |
||||||
618 | throw new \RuntimeException("EntityManager not set, you have to call parent::setUp() before invoking this method."); |
||||||
619 | } |
||||||
620 | |||||||
621 | $classes = []; |
||||||
622 | foreach ($classNames as $className) { |
||||||
623 | if ( ! isset(static::$_entityTablesCreated[$className])) { |
||||||
624 | static::$_entityTablesCreated[$className] = true; |
||||||
625 | $classes[] = $this->_em->getClassMetadata($className); |
||||||
626 | } |
||||||
627 | } |
||||||
628 | |||||||
629 | if ($classes) { |
||||||
630 | $this->_schemaTool->createSchema($classes); |
||||||
631 | } |
||||||
632 | } |
||||||
633 | |||||||
634 | /** |
||||||
635 | * Creates a connection to the test database, if there is none yet, and |
||||||
636 | * creates the necessary tables. |
||||||
637 | * |
||||||
638 | * @return void |
||||||
639 | */ |
||||||
640 | protected function setUp() |
||||||
641 | { |
||||||
642 | $this->setUpDBALTypes(); |
||||||
643 | |||||||
644 | if ( ! isset(static::$_sharedConn)) { |
||||||
645 | static::$_sharedConn = TestUtil::getConnection(); |
||||||
646 | } |
||||||
647 | |||||||
648 | if (isset($GLOBALS['DOCTRINE_MARK_SQL_LOGS'])) { |
||||||
649 | if (in_array(static::$_sharedConn->getDatabasePlatform()->getName(), ["mysql", "postgresql"])) { |
||||||
650 | static::$_sharedConn->executeQuery('SELECT 1 /*' . get_class($this) . '*/'); |
||||||
651 | } else if (static::$_sharedConn->getDatabasePlatform()->getName() == "oracle") { |
||||||
652 | static::$_sharedConn->executeQuery('SELECT 1 /*' . get_class($this) . '*/ FROM dual'); |
||||||
653 | } |
||||||
654 | } |
||||||
655 | |||||||
656 | if ( ! $this->_em) { |
||||||
657 | $this->_em = $this->_getEntityManager(); |
||||||
658 | $this->_schemaTool = new SchemaTool($this->_em); |
||||||
659 | } |
||||||
660 | |||||||
661 | $classes = []; |
||||||
662 | |||||||
663 | foreach ($this->_usedModelSets as $setName => $bool) { |
||||||
664 | if ( ! isset(static::$_tablesCreated[$setName])) { |
||||||
665 | foreach (static::$_modelSets[$setName] as $className) { |
||||||
666 | $classes[] = $this->_em->getClassMetadata($className); |
||||||
667 | } |
||||||
668 | |||||||
669 | static::$_tablesCreated[$setName] = true; |
||||||
670 | } |
||||||
671 | } |
||||||
672 | |||||||
673 | if ($classes) { |
||||||
674 | $this->_schemaTool->createSchema($classes); |
||||||
675 | } |
||||||
676 | |||||||
677 | $this->_sqlLoggerStack->enabled = true; |
||||||
678 | } |
||||||
679 | |||||||
680 | /** |
||||||
681 | * Gets an EntityManager for testing purposes. |
||||||
682 | * |
||||||
683 | * @return EntityManager |
||||||
684 | * |
||||||
685 | * @throws \Doctrine\ORM\ORMException |
||||||
686 | */ |
||||||
687 | protected function _getEntityManager( |
||||||
688 | Connection $connection = null, |
||||||
689 | MappingDriver $mappingDriver = null |
||||||
690 | ) { |
||||||
691 | // NOTE: Functional tests use their own shared metadata cache, because |
||||||
692 | // the actual database platform used during execution has effect on some |
||||||
693 | // metadata mapping behaviors (like the choice of the ID generation). |
||||||
694 | if (is_null(self::$_metadataCacheImpl)) { |
||||||
695 | if (isset($GLOBALS['DOCTRINE_CACHE_IMPL'])) { |
||||||
696 | self::$_metadataCacheImpl = new $GLOBALS['DOCTRINE_CACHE_IMPL']; |
||||||
697 | } else { |
||||||
698 | self::$_metadataCacheImpl = new ArrayCache(); |
||||||
699 | } |
||||||
700 | } |
||||||
701 | |||||||
702 | if (is_null(self::$_queryCacheImpl)) { |
||||||
703 | self::$_queryCacheImpl = new ArrayCache(); |
||||||
704 | } |
||||||
705 | |||||||
706 | $this->_sqlLoggerStack = new DebugStack(); |
||||||
707 | $this->_sqlLoggerStack->enabled = false; |
||||||
708 | |||||||
709 | //FIXME: two different configs! $conn and the created entity manager have |
||||||
710 | // different configs. |
||||||
711 | $config = new Configuration(); |
||||||
712 | $config->setMetadataCacheImpl(self::$_metadataCacheImpl); |
||||||
713 | $config->setQueryCacheImpl(self::$_queryCacheImpl); |
||||||
714 | $config->setProxyDir(__DIR__ . '/Proxies'); |
||||||
715 | $config->setProxyNamespace('Doctrine\Tests\Proxies'); |
||||||
716 | |||||||
717 | if (null !== $this->resultCacheImpl) { |
||||||
718 | $config->setResultCacheImpl($this->resultCacheImpl); |
||||||
719 | } |
||||||
720 | |||||||
721 | $enableSecondLevelCache = getenv('ENABLE_SECOND_LEVEL_CACHE'); |
||||||
722 | |||||||
723 | if ($this->isSecondLevelCacheEnabled || $enableSecondLevelCache) { |
||||||
724 | |||||||
725 | $cacheConfig = new CacheConfiguration(); |
||||||
726 | $cache = $this->getSharedSecondLevelCacheDriverImpl(); |
||||||
727 | $factory = new DefaultCacheFactory($cacheConfig->getRegionsConfiguration(), $cache); |
||||||
728 | |||||||
729 | $this->secondLevelCacheFactory = $factory; |
||||||
730 | |||||||
731 | if ($this->isSecondLevelCacheLogEnabled) { |
||||||
732 | $this->secondLevelCacheLogger = new StatisticsCacheLogger(); |
||||||
733 | $cacheConfig->setCacheLogger($this->secondLevelCacheLogger); |
||||||
734 | } |
||||||
735 | |||||||
736 | $cacheConfig->setCacheFactory($factory); |
||||||
737 | $config->setSecondLevelCacheEnabled(true); |
||||||
738 | $config->setSecondLevelCacheConfiguration($cacheConfig); |
||||||
739 | |||||||
740 | $this->isSecondLevelCacheEnabled = true; |
||||||
741 | } |
||||||
742 | |||||||
743 | $config->setMetadataDriverImpl( |
||||||
744 | $mappingDriver ?? $config->newDefaultAnnotationDriver( |
||||||
745 | [ |
||||||
746 | realpath(__DIR__ . '/Models/Cache'), |
||||||
747 | realpath(__DIR__ . '/Models/GeoNames') |
||||||
748 | ], |
||||||
749 | true |
||||||
750 | ) |
||||||
751 | ); |
||||||
752 | |||||||
753 | $conn = $connection ?: static::$_sharedConn; |
||||||
754 | $conn->getConfiguration()->setSQLLogger($this->_sqlLoggerStack); |
||||||
0 ignored issues
–
show
The method
getConfiguration() does not exist on Doctrine\DBAL\Driver\Connection . It seems like you code against a sub-type of Doctrine\DBAL\Driver\Connection such as Doctrine\DBAL\Connection .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
755 | |||||||
756 | // get rid of more global state |
||||||
757 | $evm = $conn->getEventManager(); |
||||||
758 | foreach ($evm->getListeners() AS $event => $listeners) { |
||||||
759 | foreach ($listeners AS $listener) { |
||||||
760 | $evm->removeEventListener([$event], $listener); |
||||||
761 | } |
||||||
762 | } |
||||||
763 | |||||||
764 | if ($enableSecondLevelCache) { |
||||||
765 | $evm->addEventListener('loadClassMetadata', new CacheMetadataListener()); |
||||||
766 | } |
||||||
767 | |||||||
768 | if (isset($GLOBALS['db_event_subscribers'])) { |
||||||
769 | foreach (explode(",", $GLOBALS['db_event_subscribers']) AS $subscriberClass) { |
||||||
770 | $subscriberInstance = new $subscriberClass(); |
||||||
771 | $evm->addEventSubscriber($subscriberInstance); |
||||||
772 | } |
||||||
773 | } |
||||||
774 | |||||||
775 | if (isset($GLOBALS['debug_uow_listener'])) { |
||||||
776 | $evm->addEventListener(['onFlush'], new DebugUnitOfWorkListener()); |
||||||
777 | } |
||||||
778 | |||||||
779 | return EntityManager::create($conn, $config); |
||||||
780 | } |
||||||
781 | |||||||
782 | /** |
||||||
783 | * @param \Throwable $e |
||||||
784 | * |
||||||
785 | * @return void |
||||||
786 | * |
||||||
787 | * @throws \Throwable |
||||||
788 | */ |
||||||
789 | protected function onNotSuccessfulTest(\Throwable $e) |
||||||
790 | { |
||||||
791 | if ($e instanceof AssertionFailedError) { |
||||||
792 | throw $e; |
||||||
793 | } |
||||||
794 | |||||||
795 | if(isset($this->_sqlLoggerStack->queries) && count($this->_sqlLoggerStack->queries)) { |
||||||
796 | $queries = ""; |
||||||
797 | $last25queries = array_slice(array_reverse($this->_sqlLoggerStack->queries, true), 0, 25, true); |
||||||
798 | foreach ($last25queries as $i => $query) { |
||||||
799 | $params = array_map(function($p) { if (is_object($p)) return get_class($p); else return var_export($p, true); }, $query['params'] ?: [] |
||||||
800 | ); |
||||||
801 | $queries .= $i.". SQL: '".$query['sql']."' Params: ".implode(", ", $params).PHP_EOL; |
||||||
802 | } |
||||||
803 | |||||||
804 | $trace = $e->getTrace(); |
||||||
805 | $traceMsg = ""; |
||||||
806 | foreach($trace AS $part) { |
||||||
807 | if(isset($part['file'])) { |
||||||
808 | if(strpos($part['file'], "PHPUnit/") !== false) { |
||||||
809 | // Beginning with PHPUnit files we don't print the trace anymore. |
||||||
810 | break; |
||||||
811 | } |
||||||
812 | |||||||
813 | $traceMsg .= $part['file'].":".$part['line'].PHP_EOL; |
||||||
814 | } |
||||||
815 | } |
||||||
816 | |||||||
817 | $message = "[".get_class($e)."] ".$e->getMessage().PHP_EOL.PHP_EOL."With queries:".PHP_EOL.$queries.PHP_EOL."Trace:".PHP_EOL.$traceMsg; |
||||||
818 | |||||||
819 | throw new \Exception($message, (int)$e->getCode(), $e); |
||||||
820 | } |
||||||
821 | throw $e; |
||||||
822 | } |
||||||
823 | |||||||
824 | public function assertSQLEquals($expectedSql, $actualSql) |
||||||
825 | { |
||||||
826 | return $this->assertEquals(strtolower($expectedSql), strtolower($actualSql), "Lowercase comparison of SQL statements failed."); |
||||||
827 | } |
||||||
828 | |||||||
829 | /** |
||||||
830 | * Using the SQL Logger Stack this method retrieves the current query count executed in this test. |
||||||
831 | * |
||||||
832 | * @return int |
||||||
833 | */ |
||||||
834 | protected function getCurrentQueryCount() |
||||||
835 | { |
||||||
836 | return count($this->_sqlLoggerStack->queries); |
||||||
837 | } |
||||||
838 | |||||||
839 | /** |
||||||
840 | * Configures DBAL types required in tests |
||||||
841 | */ |
||||||
842 | protected function setUpDBALTypes() |
||||||
843 | { |
||||||
844 | if (Type::hasType('rot13')) { |
||||||
845 | Type::overrideType('rot13', Rot13Type::class); |
||||||
846 | } else { |
||||||
847 | Type::addType('rot13', Rot13Type::class); |
||||||
848 | } |
||||||
849 | } |
||||||
850 | } |
||||||
851 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.