summaryrefslogtreecommitdiff
path: root/_test/lib
diff options
context:
space:
mode:
authorhfuecks <hfuecks@gmail.com>2005-11-06 23:14:47 +0100
committerhfuecks <hfuecks@gmail.com>2005-11-06 23:14:47 +0100
commit4add97cbe7c3aae97c8c54fc6a3bd7fae1de29a2 (patch)
treeef7cadf57b2620e057cea128559d8a8789202ed1 /_test/lib
parent6b7b33dca364d6167321792ffb4459a604fbab82 (diff)
downloadrpg-4add97cbe7c3aae97c8c54fc6a3bd7fae1de29a2.tar.gz
rpg-4add97cbe7c3aae97c8c54fc6a3bd7fae1de29a2.tar.bz2
mock_functions_patch
darcs-hash:20051106221447-e96b6-ff3d9d209aa899273b7116a72fbd3d49d4cc0500.gz
Diffstat (limited to '_test/lib')
-rw-r--r--_test/lib/mock_functions.php519
-rw-r--r--_test/lib/testmanager.php1
2 files changed, 520 insertions, 0 deletions
diff --git a/_test/lib/mock_functions.php b/_test/lib/mock_functions.php
new file mode 100644
index 000000000..5ffed24d6
--- /dev/null
+++ b/_test/lib/mock_functions.php
@@ -0,0 +1,519 @@
+<?php
+ /**
+ * base include file for SimpleTest
+ * @package SimpleTest
+ * @subpackage MockFunctions
+ * @version $Id: mock_objects.php,v 1.86 2005/09/10 23:01:56 lastcraft Exp $
+ */
+
+ /**
+ * Generates a mock version of a function.
+ * Note that all public methods in this class should be called
+ * statically
+ * Note that you must call the restore method yourself, to remove
+ * a mock function implementation after associated tests are
+ * complete
+ * @package SimpleTest
+ * @subpackage MockFunctions
+ */
+ class MockFunction {
+
+ /**
+ * Raises an error if you construct MockFunction
+ * @access private
+ */
+ function MockFunction() {
+ trigger_error('MockFunction only provides static methods',
+ E_USER_ERROR);
+ }
+
+ /**
+ * Generates a mock function
+ * @param string $function Function name to mock
+ * @access public
+ * @return SimpleMockFunction
+ * @static
+ */
+ function & generate($function) {
+ $mock = & MockFunction::_instance($function, TRUE);
+ $mock->deploy();
+ return $mock;
+ }
+
+ /**
+ * Removes the mock function implementation and restores
+ * the real implementation (if one existed)
+ * @TODO Would be good to have this called automatically
+ * @param string $function Function name
+ * @access public
+ * @static
+ */
+ function restore($function) {
+ $mock = & MockFunction::_instance($function);
+ $mock->restore();
+ }
+
+ /**
+ * Fetch a singleton instance of SimpleMockFunction
+ * @param string $function Function name
+ * @param boolean $fresh Force a fresh instance
+ * @access private
+ * @static
+ */
+ function &_instance($function, $fresh = FALSE) {
+ static $singleton = array();
+
+ $function = strtolower($function);
+
+ if ( $fresh ) {
+ if ( isset($singleton[$function]) ) {
+ unset($singleton[$function]);
+ }
+ }
+
+ if ( !isset($singleton[$function]) ) {
+ // TODO: case sensitivity issues
+ $class = $function."MockFunction";
+ MockFunction::_generateSubClass($class, $function);
+ $singleton[$function] = new $class($function);
+ }
+
+ return $singleton[$function];
+ }
+
+ /**
+ * Required for strict mode and SimpleMock
+ * @TODO Should perhaps be placed in SimpleFunctionGenerator
+ * @param string $class subclass name
+ * @param string $method method name
+ * @access private
+ * @static
+ */
+ function _generateSubClass($class, $method) {
+ if ( class_exists($class) ) {
+ return;
+ }
+ $code = "class $class extends SimpleMockFunction {\n";
+ $code .= " function $method () {}\n";
+ $code .= "}\n";
+ eval($code);
+ }
+
+ /**
+ * Changes the default wildcard object.
+ * @param string $function Function name wildcard applies to
+ * @param mixed $wildcard Parameter matching wildcard.
+ * @access public
+ * @static
+ */
+ function setWildcard($function, $wildcard) {
+ $mock = & MockFunction::_instance($function);
+ $mock->setWildcard($wildcard);
+ }
+
+ /**
+ * Fetches the call count of a function so far.
+ * @param string $function Function name called.
+ * @return Number of calls so far.
+ * @access public
+ * @static
+ */
+ function getCallCount($function) {
+ $mock = & MockFunction::_instance($function);
+ return $mock->getCallCount($function);
+ }
+
+ /**
+ * Sets a return for a parameter list that will
+ * be passed by value for all calls to this function.
+ * @param string $function Function name.
+ * @param mixed $value Result of call passed by value.
+ * @param array $args List of parameters to match
+ * including wildcards.
+ * @access public
+ * @static
+ */
+ function setReturnValue($function, $value, $args = false) {
+ $mock = & MockFunction::_instance($function);
+ $mock->setReturnValue($function, $value, $args);
+ }
+
+ /**
+ * Sets a return for a parameter list that will
+ * be passed by value only when the required call count
+ * is reached.
+ * @param integer $timing Number of calls in the future
+ * to which the result applies. If
+ * not set then all calls will return
+ * the value.
+ * @param string $function Function name.
+ * @param mixed $value Result of call passed by value.
+ * @param array $args List of parameters to match
+ * including wildcards.
+ * @access public
+ * @static
+ */
+ function setReturnValueAt($timing, $function, $value, $args = false) {
+ $mock = & MockFunction::_instance($function);
+ $mock->setReturnValueAt($timing, $function, $value, $args);
+ }
+
+ /**
+ * Sets a return for a parameter list that will
+ * be passed by reference for all calls.
+ * @param string $function Function name.
+ * @param mixed $reference Result of the call will be this object.
+ * @param array $args List of parameters to match
+ * including wildcards.
+ * @access public
+ * @static
+ */
+ function setReturnReference($function, &$reference, $args = false) {
+ $mock = & MockFunction::_instance($function);
+ $mock->setReturnReference($function, $reference, $args);
+ }
+
+ /**
+ * Sets a return for a parameter list that will
+ * be passed by value only when the required call count
+ * is reached.
+ * @param integer $timing Number of calls in the future
+ * to which the result applies. If
+ * not set then all calls will return
+ * the value.
+ * @param string $function Function name.
+ * @param mixed $reference Result of the call will be this object.
+ * @param array $args List of parameters to match
+ * including wildcards.
+ * @access public
+ * @static
+ */
+ function setReturnReferenceAt($timing, $function, &$reference, $args = false) {
+ $mock = & MockFunction::_instance($function);
+ $mock->setReturnReferenceAt($timing, $function, &$reference, $args);
+ }
+
+ /**
+ * Sets up an expected call with a set of
+ * expected parameters in that call. All
+ * calls will be compared to these expectations
+ * regardless of when the call is made.
+ * @param string $function Function call to test.
+ * @param array $args Expected parameters for the call
+ * including wildcards.
+ * @param string $message Overridden message.
+ * @access public
+ * @static
+ */
+ function expectArguments($function, $args, $message = '%s') {
+ $mock = & MockFunction::_instance($function);
+ $mock->expectArguments($function, $args, $message);
+ }
+
+ /**
+ * Sets up an expected call with a set of
+ * expected parameters in that call. The
+ * expected call count will be adjusted if it
+ * is set too low to reach this call.
+ * @param integer $timing Number of calls in the future at
+ * which to test. Next call is 0.
+ * @param string $function Function call to test.
+ * @param array $args Expected parameters for the call
+ * including wildcards.
+ * @param string $message Overridden message.
+ * @access public
+ * @static
+ */
+ function expectArgumentsAt($timing, $function, $args, $message = '%s') {
+ $mock = & MockFunction::_instance($function);
+ $mock->expectArgumentsAt($timing, $function, $args, $message);
+ }
+
+ /**
+ * Sets an expectation for the number of times
+ * a function will be called.
+ * @param string $function Function call to test.
+ * @param integer $count Number of times it should
+ * have been called at tally.
+ * @param string $message Overridden message.
+ * @access public
+ * @static
+ */
+ function expectCallCount($function, $count, $message = '%s') {
+ $mock = & MockFunction::_instance($function);
+ $mock->expectCallCount($function, $count, $message);
+ }
+
+ /**
+ * Sets the number of times a function may be called
+ * before a test failure is triggered.
+ * @param string $function Function call to test.
+ * @param integer $count Most number of times it should
+ * have been called.
+ * @param string $message Overridden message.
+ * @access public
+ * @static
+ */
+ function expectMaximumCallCount($function, $count, $message = '%s') {
+ $mock = & MockFunction::_instance($function);
+ $mock->expectMaximumCallCount($function, $count, $message);
+ }
+
+ /**
+ * Sets the minimum number of times the function must be called
+ * otherwise a test failure is triggered
+ * @param string $function Function call to test.
+ * @param integer $count Least number of times it should
+ * have been called.
+ * @param string $message Overridden message.
+ * @access public
+ * @static
+ */
+ function expectMinimumCallCount($function, $count, $message = '%s') {
+ $mock = & MockFunction::_instance($function);
+ $mock->expectMinimumCallCount($function, $count, $message);
+ }
+
+ /**
+ * Convenience method for barring a function
+ * call.
+ * @param string $function Function call to ban.
+ * @param string $message Overridden message.
+ * @access public
+ * @static
+ */
+ function expectNever($function, $message = '%s') {
+ $mock = & MockFunction::_instance($function);
+ $mock->expectNever($function, $message);
+ }
+
+ /**
+ * Convenience method for a single function
+ * call.
+ * @param string $function Function call to track.
+ * @param array $args Expected argument list or
+ * false for any arguments.
+ * @param string $message Overridden message.
+ * @access public
+ * @static
+ */
+ function expectOnce($function, $args = false, $message = '%s') {
+ $mock = & MockFunction::_instance($function);
+ $mock->expectOnce($function, $args, $message);
+ }
+
+ /**
+ * Convenience method for requiring a function
+ * call.
+ * @param string $function Function call to track.
+ * @param array $args Expected argument list or
+ * false for any arguments.
+ * @param string $message Overridden message.
+ * @access public
+ * @static
+ */
+ function expectAtLeastOnce($function, $args = false, $message = '%s') {
+ $mock = & MockFunction::_instance($function);
+ $mock->expectAtLeastOnce($function, $args, $message);
+ }
+
+ function atTestEnd($function) {
+ $mock = & MockFunction::_instance($function);
+ $mock->atTestEnd($function);
+ }
+
+ }
+
+ /**
+ * Represents a single, mocked function, tracking calls made to it
+ * @package SimpleTest
+ * @subpackage MockFunctions
+ */
+ class SimpleMockFunction extends SimpleMock {
+
+ var $_is_mocked = FALSE;
+ var $_generator;
+
+ /**
+ * Sets up the mock, creating a generator depending on whether
+ * the function is already declared
+ * @param string $function Name of function being mocked
+ */
+ function SimpleMockFunction($function) {
+
+ SimpleMock :: SimpleMock();
+
+ if ( function_exists($function) ) {
+ $this->_generator = new SimpleDeclaredFunctionGenerator($function);
+ } else {
+ $this->_generator = new SimpleUndeclaredFunctionGenerator($function);
+ }
+
+ }
+
+ /**
+ * Deploys the mock function implementation into PHP's function
+ * table, replacing any existing implementation
+ * @access public
+ */
+ function deploy() {
+
+ if ( !$this->_is_mocked ) {
+
+ $this->_is_mocked = TRUE;
+ $this->_generator->deploy();
+
+ }
+
+ }
+
+ /**
+ * Restores the state of PHP's function table to that before
+ * the mock function was deployed. Removes the mock function
+ * implementation and restores any existing implementation of
+ * that function
+ * @access public
+ */
+ function restore() {
+
+ if ( $this->_is_mocked ) {
+
+ $this->_is_mocked = FALSE;
+ $this->_generator->restore();
+
+ }
+
+ }
+
+ }
+
+ /**
+ * Base class for deploying and restoring from mock functions
+ * @package SimpleTest
+ * @subpackage MockFunctions
+ * @abstract
+ */
+ class SimpleFunctionGenerator {
+
+ var $_function;
+
+ /**
+ * @TODO Validate the function name (as it's being used in eval)
+ * @TODO Add list of illegal functions (ones which must not be mocked
+ * as they will break SimpleTest, which uses them)
+ * @param string $function Name of function being mocked
+ */
+ function SimpleFunctionGenerator($function) {
+ $this->_function = $function;
+ }
+
+ /**
+ * Generates the mock function implementation, using eval
+ * @access private
+ */
+ function _generateMockFunction() {
+ $code = "function " . $this->_function . "() {\n";
+ $code .= " \$args = func_get_args();\n";
+ $code .= " \$mock = & MockFunction::_instance('".$this->_function."');\n";
+ $code .= " \$result = &\$mock->_invoke(\"".$this->_function."\", \$args);\n";
+ $code .= " return \$result;\n";
+ $code .= "}\n";
+ eval($code);
+ }
+ }
+
+ /**
+ * Mock function generator for functions which have already been declared
+ * @package SimpleTest
+ * @subpackage MockFunctions
+ */
+ class SimpleDeclaredFunctionGenerator extends SimpleFunctionGenerator {
+
+ var $_tmp_function = NULL;
+
+ /**
+ * Invokes the _generateTmpFnFname
+ * @param string $function Name of function being mocked
+ */
+ function SimpleDeclaredFunctionGenerator($function) {
+
+ SimpleFunctionGenerator::SimpleFunctionGenerator($function);
+ $this->_generateTmpFnFname();
+
+ }
+
+ /**
+ * Generates a temporary name for the declared function implementation
+ * which is will be renamed to while the mock function is in use
+ * @access private
+ */
+ function _generateTmpFnFname() {
+ static $count = 1;
+ $this->_tmp_function = 'tmp_'.md5(time().$this->_function.$count);
+ $count++;
+ }
+
+ /**
+ * Deploys the mock function implementation
+ * @access public
+ */
+ function deploy() {
+
+ runkit_function_rename(
+ $this->_function,
+ $this->_tmp_function
+ ) or
+ trigger_error('Error archiving real function implementation',
+ E_USER_ERROR);
+
+ $this->_generateMockFunction();
+ }
+
+ /**
+ * Removes the mock function implementation and restores
+ * the previously declared implementation
+ * @access public
+ */
+ function restore() {
+
+ runkit_function_remove($this->_function) or
+ trigger_error('Error removing mock function',
+ E_USER_ERROR);
+
+ runkit_function_rename(
+ $this->_tmp_function,
+ $this->_function
+ ) or
+ trigger_error('Error restoring real function',
+ E_USER_ERROR);
+ }
+ }
+
+ /**
+ * Mock function generator for functions which have not
+ * already been declared
+ * @package SimpleTest
+ * @subpackage MockFunctions
+ */
+ class SimpleUndeclaredFunctionGenerator extends SimpleFunctionGenerator {
+
+ /**
+ * Deploys the mock function implementation
+ * @access public
+ */
+ function deploy() {
+ $this->_generateMockFunction();
+ }
+
+ /**
+ * Removes the mock function implementation
+ * @access public
+ */
+ function restore() {
+ runkit_function_remove($this->_function) or
+ trigger_error('Error removing mock function',
+ E_USER_ERROR);
+ }
+
+ }
+
diff --git a/_test/lib/testmanager.php b/_test/lib/testmanager.php
index c23d18441..ab4851eaf 100644
--- a/_test/lib/testmanager.php
+++ b/_test/lib/testmanager.php
@@ -47,6 +47,7 @@ class TestManager {
require_once SIMPLE_TEST . 'web_tester.php';
require_once SIMPLE_TEST . 'mock_objects.php';
require_once 'web.inc.php';
+ require_once 'mock_functions.php';
}
function runAllTests(&$reporter) {