diff --git a/tests/Doctrine/Tests/ORM/EntityManagerTest.php b/tests/Doctrine/Tests/ORM/EntityManagerTest.php index 37a444a60..a412bb309 100644 --- a/tests/Doctrine/Tests/ORM/EntityManagerTest.php +++ b/tests/Doctrine/Tests/ORM/EntityManagerTest.php @@ -2,6 +2,15 @@ namespace Doctrine\Tests\ORM; +use Doctrine\DBAL\Logging\DebugStack; +use Doctrine\DBAL\Logging\SQLLogger; +use Doctrine\ORM\Configuration; +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\Tools\SchemaTool; +use Doctrine\ORM\Tools\ToolsException; +use Doctrine\Tests\Models\Generic\DateTimeModel; +use Doctrine\Tests\TestUtil; + class EntityManagerTest extends \Doctrine\Tests\OrmTestCase { private $_em; @@ -195,4 +204,187 @@ class EntityManagerTest extends \Doctrine\Tests\OrmTestCase $this->assertSame($this->_em, $em); return 'callback'; } + + public function testMergeDetachedUnInitializedProxy() + { + $em = $this->createEntityManager(); + + $detachedUninitialized = $em->getReference(DateTimeModel::CLASSNAME, 123); + + $em->clear(); + + $managed = $em->getReference(DateTimeModel::CLASSNAME, 123); + + $this->assertSame($managed, $em->merge($detachedUninitialized)); + + $this->assertFalse($managed->__isInitialized()); + $this->assertFalse($detachedUninitialized->__isInitialized()); + } + + public function testMergeUnserializedUnInitializedProxy() + { + $em = $this->createEntityManager(); + + $detachedUninitialized = $em->getReference(DateTimeModel::CLASSNAME, 123); + + $em->clear(); + + $managed = $em->getReference(DateTimeModel::CLASSNAME, 123); + + $this->assertSame( + $managed, + $em->merge(unserialize(serialize($em->merge($detachedUninitialized)))) + ); + + $this->assertFalse($managed->__isInitialized()); + $this->assertFalse($detachedUninitialized->__isInitialized()); + } + + public function testMergeManagedProxy() + { + $em = $this->createEntityManager(); + + $managed = $em->getReference(DateTimeModel::CLASSNAME, 123); + + $this->assertSame($managed, $em->merge($managed)); + + $this->assertFalse($managed->__isInitialized()); + } + + public function testMergingProxyFromDifferentEntityManagerWithExistingManagedInstanceDoesNotReplaceInitializer() + { + $em1 = $this->createEntityManager($logger1 = new DebugStack()); + $em2 = $this->createEntityManager($logger2 = new DebugStack()); + + $entity1 = new DateTimeModel(); + $entity2 = new DateTimeModel(); + + $em1->persist($entity1); + $em2->persist($entity2); + $em1->flush(); + $em2->flush(); + $em1->clear(); + $em2->clear(); + + $queryCount1 = count($logger1->queries); + $queryCount2 = count($logger2->queries); + + $proxy1 = $em1->getReference(DateTimeModel::CLASSNAME, $entity1->id); + $proxy2 = $em2->getReference(DateTimeModel::CLASSNAME, $entity1->id); + $merged2 = $em2->merge($proxy1); + + $this->assertNotSame($proxy1, $merged2); + $this->assertSame($proxy2, $merged2); + + $this->assertFalse($proxy1->__isInitialized()); + $this->assertFalse($proxy2->__isInitialized()); + + $proxy1->__load(); + + $this->assertCount( + $queryCount1 + 1, + $logger1->queries, + 'Loading the first proxy was done through the first entity manager' + ); + $this->assertCount( + $queryCount2, + $logger2->queries, + 'No queries were executed on the second entity manager, as it is unrelated with the first proxy' + ); + + $proxy2->__load(); + + $this->assertCount( + $queryCount1 + 1, + $logger1->queries, + 'Loading the second proxy does not affect the first entity manager' + ); + $this->assertCount( + $queryCount2 + 1, + $logger2->queries, + 'Loading of the second proxy instance was done through the second entity manager' + ); + } + + public function testMergingUnInitializedProxyDoesNotInitializeIt() + { + $em1 = $this->createEntityManager($logger1 = new DebugStack()); + $em2 = $this->createEntityManager($logger2 = new DebugStack()); + + $entity1 = new DateTimeModel(); + $entity2 = new DateTimeModel(); + + $em1->persist($entity1); + $em2->persist($entity2); + $em1->flush(); + $em2->flush(); + $em1->clear(); + $em2->clear(); + + $queryCount1 = count($logger1->queries); + $queryCount2 = count($logger1->queries); + + $unManagedProxy = $em1->getReference(DateTimeModel::CLASSNAME, $entity1->id); + $mergedInstance = $em2->merge($unManagedProxy); + + $this->assertNotInstanceOf('Doctrine\Common\Proxy\Proxy', $mergedInstance); + $this->assertNotSame($unManagedProxy, $mergedInstance); + $this->assertFalse($unManagedProxy->__isInitialized()); + + $this->assertCount( + $queryCount1, + $logger1->queries, + 'Loading the merged instance affected only the first entity manager' + ); + $this->assertCount( + $queryCount1 + 1, + $logger2->queries, + 'Loading the merged instance was done via the second entity manager' + ); + + $unManagedProxy->__load(); + + $this->assertCount( + $queryCount1 + 1, + $logger1->queries, + 'Loading the first proxy was done through the first entity manager' + ); + $this->assertCount( + $queryCount2 + 1, + $logger2->queries, + 'No queries were executed on the second entity manager, as it is unrelated with the first proxy' + ); + } + + /** + * @param SQLLogger $logger + * + * @return \Doctrine\ORM\EntityManager + */ + private function createEntityManager(SQLLogger $logger = null) + { + $config = new Configuration(); + + $config->setProxyDir(realpath(__DIR__ . '/../Proxies/../..')); + $config->setProxyNamespace('Doctrine\Tests\Proxies'); + $config->setMetadataDriverImpl($config->newDefaultAnnotationDriver( + array(realpath(__DIR__ . '/../Models/Cache')), + true + )); + + $connection = TestUtil::getConnection(); + + $connection->getConfiguration()->setSQLLogger($logger); + + $entityManager = EntityManager::create($connection, $config); + + try { + (new SchemaTool($entityManager)) + ->createSchema([$entityManager->getClassMetadata(DateTimeModel::CLASSNAME)]); + } catch (ToolsException $ignored) { + // tables were already created + } + + return $entityManager; + } }