Skip to content

Commit

Permalink
Improvements to the mocking system
Browse files Browse the repository at this point in the history
  • Loading branch information
spencer-mortensen committed Jun 26, 2017
1 parent 8e93234 commit 1578603
Show file tree
Hide file tree
Showing 18 changed files with 1,575 additions and 501 deletions.
674 changes: 674 additions & 0 deletions COPYING

Large diffs are not rendered by default.

159 changes: 38 additions & 121 deletions src/Agent.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,154 +25,63 @@

namespace TestPhp;

use TestPhp\Packager\Packager;

abstract class Agent
{
/** @var array */
private static $actual;

/** @var array */
private static $calls;
private static $isRecording = true;

/** @var array */
private static $classes;
private static $calls = array();

/** @var array */
private static $objects;
private static $script = array();

/** @var array */
private static $map;
/** @var Mapper */
private static $mapper;

public static function setExpected($expectedJson)
public static function call(array $callable, array $arguments, array $result = null)
{
$expected = json_decode($expectedJson, true);
self::$calls[] = array($callable, $arguments);

foreach ($expected as $callArchive) {
list($callableArchive, $argumentsArchive, $result) = current($callArchive);
$arguments = current($argumentsArchive);
list($objectArchive, $method) = current($callableArchive);
list($objectId, $objectClass) = current($objectArchive);

self::$calls[$objectId][] = array($method, $arguments, $result);
self::$classes[$objectId] = $objectClass;
if (self::$isRecording) {
return self::record($callable, $arguments, $result);
}
}

public static function replay(array $callable, array $arguments)
{
$result = self::getResult($callable);

self::record($callable, $arguments, $result);

return self::perform($result);
return self::play($callable, $arguments);
}

private static function getResult(array $callable)
private static function record(array $callable, array $arguments, array $result = null)
{
$object = $callable[0];
list($actualObjectId, $class) = self::getObjectProperties($object);

$expectedObjectId = &self::$map[$actualObjectId];

if ($expectedObjectId === null) {
$expectedObjectId = self::getExpectedObjectId($object, $class);
}

if ($expectedObjectId === null) {
return array(0, null);
if ($result === null) {
$result = array(0, null);
}

$call = array_shift(self::$calls[$expectedObjectId]);

if ($call === null) {
return array(0, null);
}

$result = array_pop($call);

return self::unpack($result);
}

private static function getObjectProperties($object)
{
$value = Archivist::archive($object);
return current($value);
}

private static function getExpectedObjectId($object, $targetClass)
{
if (!is_array(self::$classes)) {
return null;
}

foreach (self::$classes as $id => $class) {
if ($class !== $targetClass) {
continue;
}

unset(self::$classes[$id]);
self::$objects[$id] = $object;
return $id;
}
self::$script[] = Packager::package(array($callable, $arguments, $result));

return null;
}

private static function unpack($token)
private static function play(array $unpackedCallable, array $unpackedArguments)
{
if (!is_array($token)) {
return $token;
}

list($type, $value) = each($token);

switch ($type) {
default: return $value;
case Archivist::TYPE_ARRAY: return self::unpackArray($value);
case Archivist::TYPE_OBJECT: return self::unpackObject($value);
case Archivist::TYPE_RESOURCE: return self::unpackResource($value);
}
}

private static function unpackArray(array $array)
{
$output = array();
$call = array_shift(self::$script);

foreach ($array as $key => $token) {
$output[$key] = self::unpack($token);
if ($call === null) {
return null;
}

return $output;
}

private static function unpackObject(array $object)
{
$id = $object['id'];

$output = &self::$objects[$id];
list($packedCallable, $packedArguments, $packedResult) = $call;

return $output;
}

private static function unpackResource(array $resource)
{
// TODO:
return null;
}

public static function record(array $callable, array $arguments, array $result)
{
self::$actual[] = array($callable, $arguments, $result);
self::$mapper->associate($packedCallable, $unpackedCallable);
self::$mapper->associate($packedArguments, $unpackedArguments);
$unpackedResult = self::$mapper->unpack($packedResult);

return $result;
return self::perform($unpackedResult);
}

private static function perform(array $result)
private static function perform($result)
{
list($action, $value) = $result;

if ($action === 1) {
echo json_encode($value);
exit;
throw $value;
}

Expand All @@ -181,10 +90,18 @@ private static function perform(array $result)

public static function getCalls()
{
if (!is_array(self::$actual)) {
return array();
}
return self::$calls;
}

public static function getScript()
{
return self::$script;
}

return self::$actual;
public static function setScript($scriptSerialized)
{
self::$script = unserialize($scriptSerialized);
self::$isRecording = false;
self::$mapper = new Mapper();
}
}
119 changes: 0 additions & 119 deletions src/Archivist.php

This file was deleted.

45 changes: 45 additions & 0 deletions src/Archivist/Archives/Archive.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/**
* Copyright (C) 2017 Spencer Mortensen
*
* This file is part of testphp.
*
* Testphp is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Testphp is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with testphp. If not, see <http://www.gnu.org/licenses/>.
*
* @author Spencer Mortensen <spencer@testphp.org>
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL-3.0
* @copyright 2017 Spencer Mortensen
*/

namespace TestPhp\Archivist\Archives;

abstract class Archive
{
const TYPE_OBJECT = 1;
const TYPE_RESOURCE = 2;

/** @var integer */
private $archiveType;

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

public function getArchiveType()
{
return $this->archiveType;
}
}
Loading

0 comments on commit 1578603

Please sign in to comment.