Skip to content

Commit

Permalink
Merge pull request #729 from WordPress/feature/648-split-test-class-u…
Browse files Browse the repository at this point in the history
…tility-filterediteratortest
  • Loading branch information
schlessera committed May 9, 2022
2 parents 436ff8b + c8676b9 commit 05689de
Show file tree
Hide file tree
Showing 5 changed files with 282 additions and 217 deletions.
23 changes: 8 additions & 15 deletions src/Utility/FilteredIterator.php
Expand Up @@ -48,6 +48,8 @@ public function __construct($data, $callback) {
/**
* Prevent unserialization of the object for security reasons.
*
* This method is used on PHP 7.4+.
*
* @phpcs:disable PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound
*
* @param array $data Restored array of data originally serialized.
Expand All @@ -59,15 +61,16 @@ public function __unserialize($data) {}
// phpcs:enable

/**
* Perform reinitialization tasks.
* Prevent creating a PHP value from a stored representation of the object for security reasons.
*
* Prevents a callback from being injected during unserialization of an object.
* This method is used on PHP < 7.4.
*
* @param string $data The serialized string.
*
* @return void
*/
public function __wakeup() {
unset($this->callback);
}
#[ReturnTypeWillChange]
public function unserialize($data) {}

/**
* Get the current item's value after filtering
Expand All @@ -84,14 +87,4 @@ public function current() {

return $value;
}

/**
* Prevent creating a PHP value from a stored representation of the object for security reasons.
*
* @param string $data The serialized string.
*
* @return void
*/
#[ReturnTypeWillChange]
public function unserialize($data) {}
}
137 changes: 137 additions & 0 deletions tests/Utility/FilteredIterator/ConstructorTest.php
@@ -0,0 +1,137 @@
<?php

namespace WpOrg\Requests\Tests\Utility\FilteredIterator;

use ReflectionObject;
use stdClass;
use WpOrg\Requests\Exception\InvalidArgument;
use WpOrg\Requests\Tests\TestCase;
use WpOrg\Requests\Tests\TypeProviderHelper;
use WpOrg\Requests\Utility\FilteredIterator;

/**
* @covers \WpOrg\Requests\Utility\FilteredIterator::__construct
*/
final class ConstructorTest extends TestCase {

/**
* Tests that valid $data is accepted by the constructor.
*
* @dataProvider dataValidData
*
* @param mixed $input Valid input.
*
* @return void
*/
public function testValidData($input) {
$this->assertInstanceOf(FilteredIterator::class, new FilteredIterator($input, 'ltrim'));
}

/**
* Data Provider.
*
* @return array
*/
public function dataValidData() {
return TypeProviderHelper::getSelection(TypeProviderHelper::GROUP_ITERABLE);
}

/**
* Tests receiving an exception when an invalid input type is passed as `$data` to the constructor.
*
* @dataProvider dataInvalidData
*
* @param mixed $input Invalid input.
*
* @return void
*/
public function testInvalidData($input) {
$this->expectException(InvalidArgument::class);
$this->expectExceptionMessage('Argument #1 ($data) must be of type iterable');

new FilteredIterator($input, 'ltrim');
}

/**
* Data Provider.
*
* @return array
*/
public function dataInvalidData() {
return TypeProviderHelper::getAllExcept(TypeProviderHelper::GROUP_ITERABLE);
}

/**
* Tests that valid $callback is accepted by the constructor.
*
* @dataProvider dataValidCallback
*
* @param mixed $input Valid input.
*
* @return void
*/
public function testValidCallback($input) {
$obj = new FilteredIterator([], $input);

$reflection = new ReflectionObject($obj);
$property = $reflection->getProperty('callback');
$property->setAccessible(true);
$callback_value = $property->getValue($obj);
$property->setAccessible(false);

$this->assertSame($input, $callback_value, 'Callback property has not been set');
}

/**
* Data Provider.
*
* @return array
*/
public function dataValidCallback() {
return [
'existing PHP native function' => ['strtolower'],
'dummy callback method' => [[$this, 'dummyCallback']],
];
}

/**
* Verify that invalid callbacks are not accepted by the constructor.
*
* @dataProvider dataInvalidCallback
*
* @param mixed $input Invalid callback.
*
* @return void
*/
public function testInvalidCallback($input) {
$obj = new FilteredIterator([], $input);

$reflection = new ReflectionObject($obj);
$property = $reflection->getProperty('callback');
$property->setAccessible(true);
$callback_value = $property->getValue($obj);
$property->setAccessible(false);

$this->assertNull($callback_value, 'Callback property has been set to invalid callback');
}

/**
* Data Provider.
*
* @return array
*/
public function dataInvalidCallback() {
return [
'null' => [null],
'non-existent function' => ['functionname'],
'plain object' => [new stdClass(), 'method'],
];
}

/**
* Dummy callback method.
*
* @return void
*/
public function dummyCallback() {}
}
71 changes: 71 additions & 0 deletions tests/Utility/FilteredIterator/CurrentTest.php
@@ -0,0 +1,71 @@
<?php

namespace WpOrg\Requests\Tests\Utility\FilteredIterator;

use WpOrg\Requests\Tests\TestCase;
use WpOrg\Requests\Utility\FilteredIterator;

/**
* @covers \WpOrg\Requests\Utility\FilteredIterator::current
*/
final class CurrentTest extends TestCase {

/**
* Tests that when there is a valid callback, the current value is always filtered.
*
* @dataProvider dataCallbackIsAppliedIfValid
*
* @param iterable $data The array or object to be iterated on.
* @param callable $callback Callback to be called on each value.
* @param array $expected The values expected to be seen during iteration.
*
* @return void
*/
public function testCallbackIsAppliedIfValid($data, $callback, $expected) {
$iterator = new FilteredIterator($data, $callback);

$actual = [];
foreach ($iterator as $key => $value) {
$actual[$key] = $value;
}

$this->assertSame($expected, $actual);
}

/**
* Data Provider.
*
* @return array
*/
public function dataCallbackIsAppliedIfValid() {
$original = [
'key1' => 'lowercase',
'key2' => 'UPPER CASE',
'key3' => 'Sentence case',
'key4' => 'Title Case',
];

return [
'invalid callback: null' => [
'data' => $original,
'callback' => null,
'expected' => $original,
],
'invalid callback: function does not exist' => [
'data' => $original,
'callback' => 'i_am_not_callable',
'expected' => $original,
],
'valid callback' => [
'data' => $original,
'callback' => 'strtolower',
'expected' => [
'key1' => 'lowercase',
'key2' => 'upper case',
'key3' => 'sentence case',
'key4' => 'title case',
],
],
];
}
}

0 comments on commit 05689de

Please sign in to comment.