Skip to content

Commit 0181c53

Browse files
hellofromtonyadanielpunkass
authored andcommitted
Build/Test Tools: Fix null handling and string type casting in WP_UnitTestCase_Base::assertSameIgnoreEOL().
Basically, the whole `assertSameIgnoreEOL()` assertion was fundamentally flawed. The assertion contends that it checks that the expected and actual values are of the same type and value, but the reality was very different. * The function uses `map_deep()` to potentially handle all sorts of inputs. * `map_deep()` handles arrays and objects with special casing, but will call the callback on everything else without further distinction. * The callback used passes the expected/actual value on to the `str_replace()` function to remove potential new line differences. * And the `str_replace()` function will - with a non-array input for the `$subject` - always return a string. * The output of these calls to `map_deep()` will therefore have "normalized" _all properties_ in objects, _all values_ in arrays and _all non-object, non-array values_ to strings. * And a call to `assertSame()` will therefore NEVER do a proper type check as the type of all input has already, unintentionally, been "normalized" to string. Aside from this clear flaw in the design of the assertion, PHP 8.1 now exposes a further issue as a `null` value for an object property, an array value or a plain value, will now yield a ` str_replace(): Passing null to parameter WordPress#3 ($subject) of type array|string is deprecated` notice. To fix both these issues, the fix in this PR ensures that the call to `str_replace()` will now only be made if the input is a text string. All other values passed to the callback are left in their original type. This ensures that a proper value AND type comparison can be done as well as prevents the PHP 8.1 deprecation notices. Ref: * https://developer.wordpress.org/reference/functions/map_deep/ * https://www.php.net/manual/en/function.str-replace.php This commit: - Fixes type-casting of non-string values to `string` (the flawed part of this assertion) by invoking `str_replace()` when the value is of string type. - Fixes the PHP 8.1 `str_replace(): Passing null to parameter WordPress#3 ($subject) of type array|string is deprecated` deprecation notice. - Micro-optimization: skips `map_deep()` when actual and/or expected are `null` (no need to process). - Adjusts the method documentation for both this method and the `assertEqualsIgnoreEOL()` alias method to document that the `$expected` and `$actual` parameters can be of any type. Follow-up to [48937], [51135], [51478]. Props jrf, hellofromTonya. See #53363, #53635. git-svn-id: https://develop.svn.wordpress.org/trunk@51831 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 919e14a commit 0181c53

File tree

1 file changed

+29
-17
lines changed

1 file changed

+29
-17
lines changed

tests/phpunit/includes/abstract-testcase.php

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -724,24 +724,36 @@ public function assertDiscardWhitespace( $expected, $actual, $message = '' ) {
724724
* @since 5.8.0 Added support for nested arrays.
725725
* @since 5.9.0 Added the `$message` parameter.
726726
*
727-
* @param string|array $expected The expected value.
728-
* @param string|array $actual The actual value.
729-
* @param string $message Optional. Message to display when the assertion fails.
727+
* @param mixed $expected The expected value.
728+
* @param mixed $actual The actual value.
729+
* @param string $message Optional. Message to display when the assertion fails.
730730
*/
731731
public function assertSameIgnoreEOL( $expected, $actual, $message = '' ) {
732-
$expected = map_deep(
733-
$expected,
734-
static function ( $value ) {
735-
return str_replace( "\r\n", "\n", $value );
736-
}
737-
);
732+
if ( null !== $expected ) {
733+
$expected = map_deep(
734+
$expected,
735+
static function ( $value ) {
736+
if ( is_string( $value ) ) {
737+
return str_replace( "\r\n", "\n", $value );
738+
}
739+
740+
return $value;
741+
}
742+
);
743+
}
738744

739-
$actual = map_deep(
740-
$actual,
741-
static function ( $value ) {
742-
return str_replace( "\r\n", "\n", $value );
743-
}
744-
);
745+
if ( null !== $actual ) {
746+
$actual = map_deep(
747+
$actual,
748+
static function ( $value ) {
749+
if ( is_string( $value ) ) {
750+
return str_replace( "\r\n", "\n", $value );
751+
}
752+
753+
return $value;
754+
}
755+
);
756+
}
745757

746758
$this->assertSame( $expected, $actual, $message );
747759
}
@@ -753,8 +765,8 @@ static function ( $value ) {
753765
* @since 5.6.0 Turned into an alias for `::assertSameIgnoreEOL()`.
754766
* @since 5.9.0 Added the `$message` parameter.
755767
*
756-
* @param string $expected The expected value.
757-
* @param string $actual The actual value.
768+
* @param mixed $expected The expected value.
769+
* @param mixed $actual The actual value.
758770
* @param string $message Optional. Message to display when the assertion fails.
759771
*/
760772
public function assertEqualsIgnoreEOL( $expected, $actual, $message = '' ) {

0 commit comments

Comments
 (0)