From dc6193f49a76feab6f42932fa3b95fa4658ebb99 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Thu, 31 Dec 2020 00:43:39 -0800 Subject: [PATCH] Civi\Test\Invasive - Add helper for checking protected/private members --- Civi/Test/Invasive.php | 92 +++++++++++++++++++++ tests/phpunit/Civi/Test/InvasiveExample.php | 60 ++++++++++++++ tests/phpunit/Civi/Test/InvasiveTest.php | 36 ++++++++ 3 files changed, 188 insertions(+) create mode 100644 Civi/Test/Invasive.php create mode 100644 tests/phpunit/Civi/Test/InvasiveExample.php create mode 100644 tests/phpunit/Civi/Test/InvasiveTest.php diff --git a/Civi/Test/Invasive.php b/Civi/Test/Invasive.php new file mode 100644 index 0000000000..fe8f5aed4f --- /dev/null +++ b/Civi/Test/Invasive.php @@ -0,0 +1,92 @@ +setAccessible(TRUE); + return $reflection->invokeArgs($object, $args); + } + + /** + * Get the content of a private/protected method. + * + * This is only intended for unit-testing. + * + * @param array $ref + * A reference to class+property. + * Ex: [$myObject, 'myPrivateField'] + * Ex: ['MyClass', 'myPrivateStaticField'] + * @return mixed + */ + public static function get($ref) { + list ($class, $object, $member) = self::parseRef($ref); + $reflection = new \ReflectionProperty($class, $member); + $reflection->setAccessible(TRUE); + return $reflection->getValue($object); + } + + /** + * Get the content of a private/protected method. + * + * This is only intended for unit-testing. + * + * @param array $ref + * A reference to class+property. + * Ex: [$myObject, 'myPrivateField'] + * Ex: ['MyClass', 'myPrivateStaticField'] + * @param mixed $value + * @return mixed + */ + public static function set($ref, $value) { + list ($class, $object, $member) = self::parseRef($ref); + $reflection = new \ReflectionProperty($class, $member); + $reflection->setAccessible(TRUE); + $reflection->setValue($object, $value); + } + + /** + * @param array $callable + * Ex: [$myObject, 'myPrivateMember'] + * Ex: ['MyClass', 'myPrivateStaticMember'] + * @return array + * Ordered array of [string $class, object? $object, string $memberName]. + */ + private static function parseRef($callable) { + if (is_string($callable)) { + list ($class, $member) = explode('::', $callable); + return [$class, NULL, $member]; + } + elseif (is_string($callable[0])) { + return [$callable[0], NULL, $callable[1]]; + } + elseif (is_object($callable[0])) { + return [get_class($callable[0]), $callable[0], $callable[1]]; + } + else { + throw new \RuntimeException("Cannot parse reference to private member"); + } + } + +} diff --git a/tests/phpunit/Civi/Test/InvasiveExample.php b/tests/phpunit/Civi/Test/InvasiveExample.php new file mode 100644 index 0000000000..15ffcea9da --- /dev/null +++ b/tests/phpunit/Civi/Test/InvasiveExample.php @@ -0,0 +1,60 @@ +privateField; + } + + /** + * @param int $privateField + */ + private function setPrivateField(int $privateField) { + $this->privateField = $privateField; + } + + private function twiddlePrivateField(&$output) { + $output = $this->privateField * 100; + return $this->privateField * 10000; + } + + /** + * @return int + */ + protected static function getProtectedStaticField(): int { + return self::$protectedStaticField; + } + + /** + * @param int $protectedStaticField + */ + protected static function setProtectedStaticField(int $protectedStaticField) { + self::$protectedStaticField = $protectedStaticField; + } + +} diff --git a/tests/phpunit/Civi/Test/InvasiveTest.php b/tests/phpunit/Civi/Test/InvasiveTest.php new file mode 100644 index 0000000000..7b109e3838 --- /dev/null +++ b/tests/phpunit/Civi/Test/InvasiveTest.php @@ -0,0 +1,36 @@ +assertEquals(10, Invasive::get([$tgt, 'privateField'])); + $this->assertEquals(10, Invasive::call([$tgt, 'getPrivateField'])); + Invasive::call([$tgt, 'setPrivateField'], [11]); + $this->assertEquals(11, Invasive::call([$tgt, 'getPrivateField'])); + + $theRef = NULL; + $this->assertEquals(110000, Invasive::call([$tgt, 'twiddlePrivateField'], [&$theRef])); + $this->assertEquals(1100, $theRef); + } + + public function testProtectedStatic() { + $tgt = InvasiveExample::class; + $this->assertEquals(20, Invasive::get([$tgt, 'protectedStaticField'])); + $this->assertEquals(20, Invasive::call([$tgt, 'getProtectedStaticField'])); + Invasive::call([$tgt, 'setProtectedStaticField'], [21]); + $this->assertEquals(21, Invasive::call([$tgt, 'getProtectedStaticField'])); + } + +} -- 2.25.1