Skip to content

Commit

Permalink
Introduced and fixed CachedDoubler behaviour in order to reduce memor…
Browse files Browse the repository at this point in the history
…y usage
  • Loading branch information
DonCallisto committed Nov 3, 2018
1 parent 4ba436b commit aba3a3a
Show file tree
Hide file tree
Showing 9 changed files with 34 additions and 35 deletions.
5 changes: 4 additions & 1 deletion spec/Prophecy/Argument/ArgumentsWildcardSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ function it_wraps_non_token_arguments_into_ExactValueToken(\stdClass $object)
$class = get_class($object->getWrappedObject());
$hash = spl_object_hash($object->getWrappedObject());

$this->__toString()->shouldReturn("exact(42), exact(\"zet\"), exact($class:$hash Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n))");
$objHash = "exact(42), exact(\"zet\"), exact($class:$hash Object (\n 'objectProphecyClosure' => Closure:%s Object (\n 0 => Closure:%s Object\n )\n))";

$hashRegexExpr = '[a-f0-9]{32}';
$this->__toString()->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $hashRegexExpr, $hashRegexExpr)));
}

function it_generates_string_representation_from_all_tokens_imploded(
Expand Down
8 changes: 5 additions & 3 deletions spec/Prophecy/Argument/Token/ExactValueTokenSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,15 @@ function it_generates_proper_string_representation_for_resource()

function it_generates_proper_string_representation_for_object(\stdClass $object)
{
$objHash = sprintf('%s:%s',
$objHash = sprintf('exact(%s:%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
);
) . " Object (\n 'objectProphecyClosure' => Closure:%s Object (\n 0 => Closure:%s Object\n )\n))";

$this->beConstructedWith($object);
$this->__toString()->shouldReturn("exact($objHash Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n))");

$hashRegexExpr = '[a-f0-9]{32}';
$this->__toString()->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $hashRegexExpr, $hashRegexExpr)));
}
}

Expand Down
8 changes: 5 additions & 3 deletions spec/Prophecy/Argument/Token/IdenticalValueTokenSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,14 @@ function it_generates_proper_string_representation_for_resource()

function it_generates_proper_string_representation_for_object($object)
{
$objHash = sprintf('%s:%s',
$objHash = sprintf('identical(%s:%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
);
) . " Object (\n 'objectProphecyClosure' => Closure:%s Object (\n 0 => Closure:%s Object\n )\n))";

$this->beConstructedWith($object);
$this->__toString()->shouldReturn("identical($objHash Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n))");

$hashRegexExpr = '[a-f0-9]{32}';
$this->__toString()->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $hashRegexExpr, $hashRegexExpr)));
}
}
4 changes: 2 additions & 2 deletions spec/Prophecy/Doubler/ClassPatch/ProphecySubjectPatchSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function it_forces_class_to_implement_ProphecySubjectInterface(ClassNode $node)
{
$node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface')->shouldBeCalled();

$node->addProperty('objectProphecy', 'private')->willReturn(null);
$node->addProperty('objectProphecyClosure', 'private')->willReturn(null);
$node->getMethods()->willReturn(array());
$node->hasMethod(Argument::any())->willReturn(false);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'), true)->willReturn(null);
Expand All @@ -45,7 +45,7 @@ function it_forces_all_class_methods_except_constructor_to_proxy_calls_into_prop
MethodNode $method3
) {
$node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface')->willReturn(null);
$node->addProperty('objectProphecy', 'private')->willReturn(null);
$node->addProperty('objectProphecyClosure', 'private')->willReturn(null);
$node->hasMethod(Argument::any())->willReturn(false);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'), true)->willReturn(null);
$node->addMethod(Argument::type('Prophecy\Doubler\Generator\Node\MethodNode'), true)->willReturn(null);
Expand Down
5 changes: 3 additions & 2 deletions spec/Prophecy/Util/StringUtilSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ function it_generates_proper_string_representation_for_object(\stdClass $object)
$objHash = sprintf('%s:%s',
get_class($object->getWrappedObject()),
spl_object_hash($object->getWrappedObject())
) . " Object (\n 'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)\n)";
) . " Object (\n 'objectProphecyClosure' => Closure:%s Object (\n 0 => Closure:%s Object\n )\n)";

$this->stringify($object)->shouldReturn("$objHash");
$hashRegexExpr = '[a-f0-9]{32}';
$this->stringify($object)->shouldMatch(sprintf('/^%s$/', sprintf(preg_quote("$objHash"), $hashRegexExpr, $hashRegexExpr)));
}

function it_generates_proper_string_representation_for_object_without_exporting(\stdClass $object)
Expand Down
18 changes: 4 additions & 14 deletions src/Prophecy/Doubler/CachedDoubler.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,19 @@
*/
class CachedDoubler extends Doubler
{
private $classes = array();

/**
* {@inheritdoc}
*/
public function registerClassPatch(ClassPatch\ClassPatchInterface $patch)
{
$this->classes[] = array();

parent::registerClassPatch($patch);
}
private static $classes = array();

/**
* {@inheritdoc}
*/
protected function createDoubleClass(ReflectionClass $class = null, array $interfaces)
{
$classId = $this->generateClassId($class, $interfaces);
if (isset($this->classes[$classId])) {
return $this->classes[$classId];
if (isset(self::$classes[$classId])) {
return self::$classes[$classId];
}

return $this->classes[$classId] = parent::createDoubleClass($class, $interfaces);
return self::$classes[$classId] = parent::createDoubleClass($class, $interfaces);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/Prophecy/Doubler/ClassPatch/ProphecySubjectPatch.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function supports(ClassNode $node)
public function apply(ClassNode $node)
{
$node->addInterface('Prophecy\Prophecy\ProphecySubjectInterface');
$node->addProperty('objectProphecy', 'private');
$node->addProperty('objectProphecyClosure', 'private');

foreach ($node->getMethods() as $name => $method) {
if ('__construct' === strtolower($name)) {
Expand All @@ -65,10 +65,10 @@ public function apply(ClassNode $node)
$prophecyArgument = new ArgumentNode('prophecy');
$prophecyArgument->setTypeHint('Prophecy\Prophecy\ProphecyInterface');
$prophecySetter->addArgument($prophecyArgument);
$prophecySetter->setCode('$this->objectProphecy = $prophecy;');
$prophecySetter->setCode('$this->objectProphecyClosure = function () use ($prophecy) { return $prophecy; };');

$prophecyGetter = new MethodNode('getProphecy');
$prophecyGetter->setCode('return $this->objectProphecy;');
$prophecyGetter->setCode('return call_user_func($this->objectProphecyClosure);');

if ($node->hasMethod('__call')) {
$__call = $node->getMethod('__call');
Expand Down
11 changes: 7 additions & 4 deletions src/Prophecy/Prophet.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Prophecy;

use Prophecy\Doubler\CachedDoubler;
use Prophecy\Doubler\Doubler;
use Prophecy\Doubler\LazyDouble;
use Prophecy\Doubler\ClassPatch;
Expand Down Expand Up @@ -45,11 +46,13 @@ class Prophet
* @param null|RevealerInterface $revealer
* @param null|StringUtil $util
*/
public function __construct(Doubler $doubler = null, RevealerInterface $revealer = null,
StringUtil $util = null)
{
public function __construct(
Doubler $doubler = null,
RevealerInterface $revealer = null,
StringUtil $util = null
) {
if (null === $doubler) {
$doubler = new Doubler;
$doubler = new CachedDoubler();
$doubler->registerClassPatch(new ClassPatch\SplFileInfoPatch);
$doubler->registerClassPatch(new ClassPatch\TraversablePatch);
$doubler->registerClassPatch(new ClassPatch\ThrowablePatch);
Expand Down
4 changes: 1 addition & 3 deletions src/Prophecy/Util/ExportUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,7 @@ protected static function recursiveExport(&$value, $indentation, $processed = nu
if (is_object($value)) {
$class = get_class($value);

if ($value instanceof ProphecyInterface) {
return sprintf('%s Object (*Prophecy*)', $class);
} elseif ($hash = $processed->contains($value)) {
if ($hash = $processed->contains($value)) {
return sprintf('%s:%s Object', $class, $hash);
}

Expand Down

0 comments on commit aba3a3a

Please sign in to comment.