Skip to content

Commit

Permalink
Merge pull request #30 from mehamasum/fix/infinite-loop-on-restub-invoke
Browse files Browse the repository at this point in the history
Fix/infinite loop on restub invoke
  • Loading branch information
sirbrillig authored Feb 10, 2022
2 parents 8158560 + ea9ea39 commit 2b19c09
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 4 deletions.
15 changes: 11 additions & 4 deletions src/Spies/GlobalSpies.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ class GlobalSpies {
// A record of all the existing functions that have been redefined
public static $redefined_functions = [];

// A record of all functions that did not have a definition and we generated one.
public static $generated_functions = [];

public static function create_global_spy( $function_name ) {
$spy = new Spy( $function_name );
self::create_global_function( $function_name );
Expand Down Expand Up @@ -84,6 +87,7 @@ private static function create_global_function( $function_name ) {
} else {
$function_eval = self::generate_function_with( $function_name );
eval( $function_eval );
self::$generated_functions[ $function_name ] = true;
}
// Save the name of this function so we know that we already defined it.
self::$global_functions[ $function_name ] = true;
Expand All @@ -105,6 +109,12 @@ public static function call_original_global_function( $function_name, $args ) {
if ( ! isset( self::$redefined_functions[ $function_name ] ) ) {
return;
}

// skip if the function did not exist before (i.e. had no "original" function)
if ( isset( self::$generated_functions[ $function_name ] ) ) {
return;
}

if ( ! function_exists( 'Patchwork\restore' ) ) {
return;
}
Expand All @@ -121,10 +131,7 @@ private static function replace_global_function( $function_name ) {
}
self::$redefined_functions[ $function_name ] = \Patchwork\redefine( $function_name, function() use ( $function_name ) {
$value = \Spies\GlobalSpies::handle_call_for( $function_name, func_get_args(), [ 'return_falsey_objects' => true ] );
if ( isset( $value ) ) {
return self::filter_return_for( $value );
}
return \Patchwork\relay();
return self::filter_return_for( $value );
} );
}

Expand Down
68 changes: 68 additions & 0 deletions tests/ConsecutiveExecutionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php


function global_function_bar() {
return - 1;
}

class ConsecutiveExecutionTest extends \Spies\TestCase {
function tearDown() {
\Spies\finish_spying();
}

public function test__undefined_function___can_be_stubbed() {
$foo_spy = \Spies\get_spy_for( 'undefined_function' )->and_return( 4 );
$ret = undefined_function();
$this->assertEquals( 1, $foo_spy->get_times_called() );
$this->assertEquals( 4, $ret );
}

public function test__undefined_function___can_be_restubbed() {
$foo_spy = \Spies\get_spy_for( 'undefined_function' );
$ret = undefined_function();
$this->assertEquals( 1, $foo_spy->get_times_called() );
$this->assertEquals( null, $ret );
}

public function test__undefined_function___can_be_restubbed_again() {
$foo_spy = \Spies\get_spy_for( 'undefined_function' );
$ret = undefined_function();
$this->assertEquals( 1, $foo_spy->get_times_called() );
$this->assertEquals( null, $ret );
}

public function test__undefined_function___can_be_restubbed_again_with_new_return() {
$foo_spy = \Spies\get_spy_for( 'undefined_function' )->and_return( 3 );
$ret = undefined_function();
$this->assertEquals( 1, $foo_spy->get_times_called() );
$this->assertEquals( 3, $ret );
}

public function test__global_function__can_be_stubbed() {
$bar_spy = \Spies\get_spy_for( 'global_function_bar' )->and_return( 0 );
$ret = global_function_bar();
$this->assertEquals( 1, $bar_spy->get_times_called() );
$this->assertEquals( 0, $ret );
}

public function test__global_function__can_be_restubbed() {
$bar_spy = \Spies\get_spy_for( 'global_function_bar' );
$ret = global_function_bar();
$this->assertEquals( 1, $bar_spy->get_times_called() );
$this->assertEquals( - 1, $ret );
}

public function test__global_function__can_be_restubbed_again() {
$bar_spy = \Spies\get_spy_for( 'global_function_bar' );
$ret = global_function_bar();
$this->assertEquals( 1, $bar_spy->get_times_called() );
$this->assertEquals( - 1, $ret );
}

public function test__global_function__can_be_restubbed_again_with_new_return() {
$bar_spy = \Spies\get_spy_for( 'global_function_bar' )->and_return( 3 );
$ret = global_function_bar();
$this->assertEquals( 1, $bar_spy->get_times_called() );
$this->assertEquals( 3, $ret );
}
}

0 comments on commit 2b19c09

Please sign in to comment.