From e21b29c26410837b516af43d2bc751e1dbba5e4c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Mon, 21 Aug 2017 19:44:38 +0200 Subject: [PATCH] #1521 DDC-2922 simplified test case to a minimum reproducible unit --- tests/Doctrine/Tests/Models/CMS/CmsEmail.php | 2 +- .../ORM/Functional/Ticket/DDC2922Test.php | 129 +++++++++++++++++- 2 files changed, 125 insertions(+), 6 deletions(-) diff --git a/tests/Doctrine/Tests/Models/CMS/CmsEmail.php b/tests/Doctrine/Tests/Models/CMS/CmsEmail.php index 0faf4b876..c79c30036 100644 --- a/tests/Doctrine/Tests/Models/CMS/CmsEmail.php +++ b/tests/Doctrine/Tests/Models/CMS/CmsEmail.php @@ -22,7 +22,7 @@ class CmsEmail public $email; /** - * @OneToOne(targetEntity="CmsUser", mappedBy="email", cascade={"persist"}) + * @OneToOne(targetEntity="CmsUser", mappedBy="email") */ public $user; diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2922Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2922Test.php index 188d68fee..6598be42e 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2922Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2922Test.php @@ -1,21 +1,34 @@ useModelSet('cms'); parent::setUp(); + + try { + $this->_schemaTool->createSchema(array_map( + function (string $className) : ClassMetadata { + return $this->_em->getClassMetadata($className); + }, + [ + DDC2922CascadePersistedEntity::class, + DDC2922EntityWithCascadingAssociation::class, + DDC2922EntityWithNonCascadingAssociation::class, + ] + )); + } catch (ToolsException $ignored) {} } /** @@ -63,7 +76,7 @@ class DDC2922Test extends \Doctrine\Tests\OrmFunctionalTestCase */ public function testNewAssociatedEntityWorksWithJustOnePath() { - + self::markTestSkipped(); /** * First we persist and flush an e-mail with no user. Having the * "cascading path" involve a non-new object seems to be important to @@ -113,4 +126,110 @@ class DDC2922Test extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals($user, $this->_em->find(get_class($user),$user->id)); } -} \ No newline at end of file + + /** + * Unlike next test, this one demonstrates that the problem does + * not necessarily reproduce if all the pieces are being flushed together. + * + * @group DDC-2922 + */ + public function testNewAssociatedEntityWorksWithJustOnePath__() + { + $cascadePersisted = new DDC2922CascadePersistedEntity(); + $cascading = new DDC2922EntityWithCascadingAssociation(); + $nonCascading = new DDC2922EntityWithNonCascadingAssociation(); + + // First we persist and flush a DDC2922EntityWithCascadingAssociation with + // the cascading association not set. Having the "cascading path" involve + // a non-new object is important to show that the ORM should be considering + // cascades across entity changesets in subsequent flushes. + $cascading->cascaded = $cascadePersisted; + $nonCascading->cascaded = $cascadePersisted; + + $this->_em->persist($cascading); + $this->_em->persist($nonCascading); + $this->_em->flush(); + + // @TODO assert persistence on both associations + } + + + /** + * This test exhibits the bug describe in the ticket, where an object that + * ought to be reachable causes errors. + * + * @group DDC-2922 + */ + public function testNewAssociatedEntityWorksWithJustOnePath_() + { + $cascadePersisted = new DDC2922CascadePersistedEntity(); + $cascading = new DDC2922EntityWithCascadingAssociation(); + $nonCascading = new DDC2922EntityWithNonCascadingAssociation(); + + // First we persist and flush a DDC2922EntityWithCascadingAssociation with + // the cascading association not set. Having the "cascading path" involve + // a non-new object is important to show that the ORM should be considering + // cascades across entity changesets in subsequent flushes. + $cascading->cascaded = null; + + $this->_em->persist($cascading); + $this->_em->flush(); + + // Note that we have NOT directly persisted the DDC2922CascadePersistedEntity, + // and DDC2922EntityWithNonCascadingAssociation does NOT have a configured + // cascade-persist. + $nonCascading->nonCascaded = $cascadePersisted; + + // However, DDC2922EntityWithCascadingAssociation *does* have a cascade-persist + // association, which ought to allow us to save the DDC2922CascadePersistedEntity + // anyway through that connection. + $cascading->cascaded = $cascadePersisted; + + $this->_em->persist($nonCascading); + $this->_em->flush(); + + // @TODO assert persistence on both associations + } +} + +/** @Entity */ +class DDC2922CascadePersistedEntity +{ + /** @Id @Column(type="string") @GeneratedValue(strategy="NONE") */ + private $id; + + public function __construct() + { + $this->id = uniqid(self::class, true); + } +} + +/** @Entity */ +class DDC2922EntityWithCascadingAssociation +{ + /** @Id @Column(type="string") @GeneratedValue(strategy="NONE") */ + private $id; + + /** @ManyToOne(targetEntity=DDC2922CascadePersistedEntity::class, cascade={"persist"}) */ + public $cascaded; + + public function __construct() + { + $this->id = uniqid(self::class, true); + } +} + +/** @Entity */ +class DDC2922EntityWithNonCascadingAssociation +{ + /** @Id @Column(type="string") @GeneratedValue(strategy="NONE") */ + private $id; + + /** @ManyToOne(targetEntity=DDC2922CascadePersistedEntity::class) */ + public $nonCascaded; + + public function __construct() + { + $this->id = uniqid(self::class, true); + } +}