Skip to content
This repository has been archived by the owner on Aug 1, 2023. It is now read-only.

Commit

Permalink
get rid of call_user_func (#32)
Browse files Browse the repository at this point in the history
`call_user_func_array` is deprecated in the latest nightly builds, changing to `$callable()`.

I added a test to confirm this still works with all *reasonable* ways of providing callables (lambda, fun, class_meth, inst_meth). This likely breaks `'func_name'` and `varray['ClassName', 'methodName']` but those would be broken soon anyway by the HHVM migration to use native function pointers.
  • Loading branch information
jjergus authored Sep 11, 2020
1 parent 1282974 commit dcf1beb
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
16 changes: 9 additions & 7 deletions src/ExpectObj.hack
Original file line number Diff line number Diff line change
Expand Up @@ -525,9 +525,12 @@ class ExpectObj<T> extends Assert {
*
* expect( () ==> invariant_violation('...') )->notToThrow(); // would fail
*/
public function notToThrow(?string $msg = null, mixed ...$args): void {
public function notToThrow(
?string $msg = null,
mixed ...$args
): void where T as (function(): mixed) {
$msg = \vsprintf($msg, $args);
$e = $this->tryCallWithArgsReturnException(varray[], \Exception::class);
$e = $this->tryCallReturnException(\Exception::class);
if ($e !== null) {
$msg = Str\format(
"%s was thrown: %s\n%s",
Expand Down Expand Up @@ -572,7 +575,7 @@ class ExpectObj<T> extends Assert {
mixed ...$args
): TException where T = (function(): TRet) {
$msg = \vsprintf($msg ?? '', $args);
$exception = $this->tryCallWithArgsReturnException(vec[], $exception_class);
$exception = $this->tryCallReturnException($exception_class);

if (!$exception) {
throw new \Exception(
Expand Down Expand Up @@ -652,13 +655,12 @@ class ExpectObj<T> extends Assert {
**** Private implementation details ***
***************************************
***************************************/
private function tryCallWithArgsReturnException<Tclass as \Throwable>(
Container<mixed> $args,
private function tryCallReturnException<Tclass as \Throwable>(
classname<Tclass> $expected_exception_type,
): ?Tclass {
): ?Tclass where T as (function(): mixed) {
try {
$callable = $this->var;
$returned = \call_user_func_array($callable, $args);
$returned = $callable();

if ($returned is Awaitable<_>) {
/* HHAST_IGNORE_ERROR[DontUseAsioJoin] */
Expand Down
21 changes: 21 additions & 0 deletions tests/ExpectObjTest.hack
Original file line number Diff line number Diff line change
Expand Up @@ -536,4 +536,25 @@ final class ExpectObjTest extends HackTest {
\restore_error_handler();
expect($previous)->toEqual('not_a_function', 'Error handler contaminated');
}

/**
* Test that all reasonable ways of providing a (function(): mixed) work.
*/
public function testCallables(): void {
expect(() ==> self::exampleStaticCallable())
->toThrow(\Exception::class, 'Static method called!');
expect(class_meth(self::class, 'exampleStaticCallable'))
->toThrow(\Exception::class, 'Static method called!');
expect(inst_meth($this, 'exampleInstanceCallable'))
->toThrow(\Exception::class, 'Instance method called!');
expect(fun('time'))->notToThrow();
}

public static function exampleStaticCallable(): void {
throw new \Exception('Static method called!');
}

public function exampleInstanceCallable(): void {
throw new \Exception('Instance method called!');
}
}

0 comments on commit dcf1beb

Please sign in to comment.