Skip to content

Commit

Permalink
Fix complete generation process
Browse files Browse the repository at this point in the history
Fix of a major bug putted in light by the new tests in LoaderIntegrationTest: referencing to a property or a call on a fixture that is not fully generated yet.

Solving this problem slightly complexify the generation of the objects and brings the notion of 1. requiring to fully generate an object in one go and 2. introduce the notion of "complete object". This complexification is entirely justified in the sense that it is necessary to fulfil the promised made in #257 which is that the fixture order will have no importance in 3.x.
  • Loading branch information
theofidry committed Nov 2, 2016
1 parent 3de4c7c commit 9570bf4
Show file tree
Hide file tree
Showing 22 changed files with 1,051 additions and 71 deletions.
60 changes: 60 additions & 0 deletions fixtures/Definition/Object/ImmutableByCloneObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

/*
* This file is part of the Alice package.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types = 1);

namespace Nelmio\Alice\Definition\Object;

use Nelmio\Alice\ObjectInterface;

class ImmutableByCloneObject implements ObjectInterface
{
/**
* @var string
*/
private $id;

/**
* @var object
*/
private $instance;

/**
* @param string $id
* @param object $instance
*/
public function __construct(string $id, $instance)
{
$this->id = $id;
$this->instance = $instance;
}

/**
* @inheritdoc
*/
public function getId(): string
{
return $this->id;
}

/**
* @inheritdoc
*/
public function getInstance()
{
return $this->instance;
}

public function __clone()
{
$this->instance = clone $this->instance;
}
}
55 changes: 55 additions & 0 deletions fixtures/Definition/Object/ImmutableObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

/*
* This file is part of the Alice package.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types = 1);

namespace Nelmio\Alice\Definition\Object;

use Nelmio\Alice\ObjectInterface;

class ImmutableObject implements ObjectInterface
{
/**
* @var string
*/
private $id;

/**
* @var object
*/
private $instance;

/**
* @param string $id
* @param object $instance
*/
public function __construct(string $id, $instance)
{
$this->id = $id;
$this->instance = deep_clone($instance);
}

/**
* @inheritdoc
*/
public function getId(): string
{
return $this->id;
}

/**
* @inheritdoc
*/
public function getInstance()
{
return deep_clone($this->instance);
}
}
7 changes: 6 additions & 1 deletion src/Bridge/Symfony/Resources/config/generator.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@
</service>

<service id="nelmio_alice.generator.object_generator"
alias="nelmio_alice.generator.object_generator.simple" />
alias="nelmio_alice.generator.object_generator.complete" />

<service id="nelmio_alice.generator.object_generator.complete"
class="Nelmio\Alice\Generator\ObjectGenerator\CompleteObjectGenerator">
<argument type="service" id="nelmio_alice.generator.object_generator.simple" />
</service>

<service id="nelmio_alice.generator.object_generator.simple"
class="Nelmio\Alice\Generator\ObjectGenerator\SimpleObjectGenerator">
Expand Down
8 changes: 5 additions & 3 deletions src/Definition/MethodCallBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@

namespace Nelmio\Alice\Definition;

/**
* TODO: review this class (i.e. immutability) after Caller is implemented
*/
final class MethodCallBag
{
/**
Expand Down Expand Up @@ -48,4 +45,9 @@ public function mergeWith(self $methodCallsBag): self

return $clone;
}

public function isEmpty(): bool
{
return [] === $this->methodCalls;
}
}
53 changes: 53 additions & 0 deletions src/Definition/Object/CompleteObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the Alice package.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Nelmio\Alice\Definition\Object;

use Nelmio\Alice\ObjectInterface;

/**
* Representation of a fixture object for which the instance has been completed.
*/
final class CompleteObject implements ObjectInterface
{
/**
* @var ObjectInterface
*/
private $object;

public function __construct(ObjectInterface $object)
{
$this->object = $object;
}

/**
* @inheritdoc
*/
public function getId(): string
{
return $this->object->getId();
}

/**
* @inheritdoc
*/
public function getInstance()
{
return $this->object->getInstance();
}

public function __clone()
{
$this->object = clone $this->object;
}
}
5 changes: 5 additions & 0 deletions src/Definition/PropertyBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ public function mergeWith(self $propertyBag): self
return $clone;
}

public function isEmpty(): bool
{
return [] === $this->properties;
}

/**
* @inheritdoc
*/
Expand Down
20 changes: 20 additions & 0 deletions src/Generator/GenerationContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ final class GenerationContext
*/
private $resolving;

/**
* @var bool
*/
private $needsCompleteResolution = false;

public function __construct()
{
$this->isFirstPass = true;
Expand All @@ -54,4 +59,19 @@ public function markIsResolvingFixture(string $id)
$this->resolving->add($id);
$this->resolving->checkForCircularReference($id);
}

public function markAsNeedsCompleteGeneration()
{
$this->needsCompleteResolution = true;
}

public function unmarkAsNeedsCompleteGeneration()
{
$this->needsCompleteResolution = false;
}

public function needsCompleteGeneration(): bool
{
return $this->needsCompleteResolution;
}
}
77 changes: 77 additions & 0 deletions src/Generator/ObjectGenerator/CompleteObjectGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

/*
* This file is part of the Alice package.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Nelmio\Alice\Generator\ObjectGenerator;

use Nelmio\Alice\Definition\Object\CompleteObject;
use Nelmio\Alice\FixtureInterface;
use Nelmio\Alice\Generator\GenerationContext;
use Nelmio\Alice\Generator\ObjectGeneratorInterface;
use Nelmio\Alice\Generator\ResolvedFixtureSet;
use Nelmio\Alice\NotClonableTrait;
use Nelmio\Alice\ObjectBag;
use Nelmio\Alice\ObjectInterface;

final class CompleteObjectGenerator implements ObjectGeneratorInterface
{
use NotClonableTrait;

/**
* @var ObjectGeneratorInterface
*/
private $objectGenerator;

public function __construct(ObjectGeneratorInterface $objectGenerator)
{
$this->objectGenerator = $objectGenerator;
}

/**
* @inheritdoc
*/
public function generate(
FixtureInterface $fixture,
ResolvedFixtureSet $fixtureSet,
GenerationContext $context
): ObjectBag
{
if ($fixtureSet->getObjects()->has($fixture)
&& $fixtureSet->getObjects()->get($fixture) instanceof CompleteObject
) {
return $fixtureSet->getObjects();
}

$objects = $this->objectGenerator->generate($fixture, $fixtureSet, $context);
$generatedObject = $objects->get($fixture);

if (false === $this->isObjectComplete($fixture, $generatedObject, $context)) {
return $objects;
}

return $objects->with(new CompleteObject($generatedObject));
}

private function isObjectComplete(FixtureInterface $fixture, ObjectInterface $object, GenerationContext $context): bool
{
return (
$object instanceof CompleteObject
|| $context->needsCompleteGeneration()
|| false === $context->isFirstPass()
|| (
false === $context->needsCompleteGeneration()
&& $fixture->getSpecs()->getProperties()->isEmpty()
&& $fixture->getSpecs()->getMethodCalls()->isEmpty()
)
);
}
}
5 changes: 4 additions & 1 deletion src/Generator/ObjectGenerator/SimpleObjectGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ public function generate(
): ObjectBag
{
if ($context->isFirstPass()) {
return $this->instantiator->instantiate($fixture, $fixtureSet, $context)->getObjects();
$fixtureSet = $this->instantiator->instantiate($fixture, $fixtureSet, $context)->getObjects();
if (false === $context->needsCompleteGeneration()) {
return $fixtureSet;
}
}
$fixtureSet = $this->completeObject($fixture, $fixtureSet, $context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ public function resolve(
throw ResolverNotFoundException::createUnexpectedCall(__METHOD__);
}

$context->markAsNeedsCompleteGeneration();
$fixtureReferenceResult = $this->resolver->resolve($value->getReference(), $fixture, $fixtureSet, $scope, $context);
$context->unmarkAsNeedsCompleteGeneration();

/** @var ResolvedFixtureSet $fixtureSet */
list($instance, $fixtureSet) = [$fixtureReferenceResult->getValue(), $fixtureReferenceResult->getSet()];

Expand Down
Loading

0 comments on commit 9570bf4

Please sign in to comment.