Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QA: stricter type adherence #779

Merged
merged 6 commits into from
Dec 12, 2022
Merged

Conversation

jrfnl
Copy link
Member

@jrfnl jrfnl commented Nov 21, 2022

Introduction

This PR is the outcome of an experiment to turn on strict_types for this code base (which can not happen for real until support for PHP 5.6 has been dropped).

Running the tests over the code base with strict_types turned on, initially yielded 646 tests erroring out and 156 tests failing (and three extra tests being skipped).

The below commits fix the majority of these, save for 6 test errors.

These last 6 test errors are TypeErrors for PHP native functions which expect a string, but are receiving a stringable object, which for all intends and purposes is perfectly valid.

If and when Requests would move to enabling strict_types for real, those last six issues can be solved by adding a (string) cast in 3 places in the code base.


Details of the last siẋ errors (fold out)
1) WpOrg\Requests\Tests\IdnaEncoder\IdnaEncoderTest::testEncoding with data set "stringable object" (WpOrg\Requests\Tests\Fixtures\StringableObject Object (...), 'xn--tba')                                                             
TypeError: explode(): Argument #2 ($string) must be of type string, WpOrg\Requests\Tests\Fixtures\StringableObject given                                                                                                                 
                                                                                                                                                                                                                                         
path/to/Requests/src/IdnaEncoder.php:68
path/to/Requests/tests/IdnaEncoder/IdnaEncoderTest.php:56
                                                                                                                                                                                                                                         
2) WpOrg\Requests\Tests\Requests\RequestsTest::testDefaultTransport                                                                                                                                                                      
TypeError: preg_match(): Argument #2 ($subject) must be of type string, WpOrg\Requests\Iri given                                                                                                                                         
                                                                                                                                                                                                                                         
path/to/Requests/src/Requests.php:660
path/to/Requests/src/Requests.php:456
path/to/Requests/src/Requests.php:307
path/to/Requests/tests/Requests/RequestsTest.php:151
                                                                                                                                                                                                                                         
3) WpOrg\Requests\Tests\Ssl\MatchDomainTest::testMatch with data set "top-level domain (stringable object)" (WpOrg\Requests\Tests\Fixtures\StringableObject Object (...), WpOrg\Requests\Tests\Fixtures\StringableObject Object (...))   
TypeError: preg_match(): Argument #2 ($subject) must be of type string, WpOrg\Requests\Tests\Fixtures\StringableObject given                                                                                                             
                                                                                                                                                                                                                                         
path/to/Requests/src/Ssl.php:109
path/to/Requests/src/Ssl.php:160
path/to/Requests/tests/Ssl/MatchDomainTest.php:51
                                                                                                                                                                                                                                         
4) WpOrg\Requests\Tests\Ssl\VerifyReferenceNameTest::testVerifyReferenceName with data set "three parts, no wildcard" (WpOrg\Requests\Tests\Fixtures\StringableObject Object (...), true)                                                
TypeError: preg_match(): Argument #2 ($subject) must be of type string, WpOrg\Requests\Tests\Fixtures\StringableObject given                                                                                                             
                                                                                                                                                                                                                                         
path/to/Requests/src/Ssl.php:109
path/to/Requests/tests/Ssl/VerifyReferenceNameTest.php:52

5) WpOrg\Requests\Tests\Transport\Curl\CurlTest::testSimpleGET
TypeError: preg_match(): Argument #2 ($subject) must be of type string, WpOrg\Requests\Iri given

path/to/Requests/src/Requests.php:660
path/to/Requests/src/Requests.php:456
path/to/Requests/src/Requests.php:307
path/to/Requests/tests/Transport/BaseTestCase.php:76

6) WpOrg\Requests\Tests\Transport\Fsockopen\FsockopenTest::testSimpleGET
TypeError: preg_match(): Argument #2 ($subject) must be of type string, WpOrg\Requests\Iri given

path/to/Requests/src/Requests.php:660
path/to/Requests/src/Requests.php:456
path/to/Requests/src/Requests.php:307
path/to/Requests/tests/Transport/BaseTestCase.php:76


Note: no tests are added for any of these changes as the existing tests cover them already, but don't show the issue unless strict_types mode is turned on.

Commits

QA | IdnaEncoder::punycode_encode(): pass the correct type

The IdnaEncoder::digit_to_char() method expects an int, not a float, for the $digit parameter. Same goes for the PHP native substr() function called from within the IdnaEncoder::digit_to_char() method to which the $digit parameter.

This ensures that the values passed to IdnaEncoder::digit_to_char(), which due to the use of % and floor are typed as float, will now contain the correct int type.

QA | Iri::remove_dot_segments(): pass the correct type

The PHP native substr_replace() function expects an integer for the $offset parameter, however, the strrpos() function used to determine the offset will return an integer if the $needle is found, but false when the $needle doesn't exist in the $haystack.

This tweaks the code to allow for that and ensures that the substr_replace() function will always receive an integer.

QA | Iri::set_authority(): pass the correct type

The PHP native strpos() function expects an integer for the $offset parameter, however, the strpos() function used to determine the offset will return an integer if the $needle is found, but false when the $needle doesn't exist in the $haystack.

This tweaks the code to allow for that and ensures that the strpos() function will always receive an integer.

QA | Cookie::normalize(): pass the correct type

A cookie will either be a key/value pair or just a plain value (with an implicit integer key).

The Cookie::normalize_attribute() method normalized the value based on a string based key and otherwise returns the value unchanged, so this function call can be bypassed when the cookie is just a plain value without a key as it won't have any effect anyway.

This prevents a call to the PHP native strtolower() function in the Cookie::normalize_attribute() method from passing an integer where a string is expected.

QA | Headers::getValues(): pass the correct type

An HTTP header will either be a key/value pair or just a plain value (with an implicit integer key).

This minor tweak prevents a call to the PHP native strtolower() function being passed an integer where a string is expected.

QA | Cookie::path_matches(): pass the correct type

The $request_path parameter is expected to be a string, but in effect, all scalars are accepted, as well as stringable objects.

While this is fine for the code in the first half of the function, the second half strongly relies on PHP type juggling as the type is treated as a string as of that point.

To make this explicit and ensure that both the strlen() as well as the substr() functions will always receive the correct type, a type casts is being added.

The `IdnaEncoder::digit_to_char()` method expects an `int`, not a float, for the `$digit` parameter. Same goes for the PHP native `substr()` function called from within the `IdnaEncoder::digit_to_char()` method to which the `$digit` parameter.

This ensures that the values passed to `IdnaEncoder::digit_to_char()`, which due to the use of `%` and `floor` are typed as `float`, will now contain the correct `int` type.

Note: no tests are added for this as the existing tests cover this already, but don't show the issue unless `strict_types` mode is turned on.
The PHP native `substr_replace()` function expects an integer for the `$offset` parameter, however, the `strrpos()` function used to determine the _offset_ will return an integer if the `$needle` is found, but `false` when the `$needle` doesn't exist in the `$haystack`.

This tweaks the code to allow for that and ensures that the `substr_replace()` function will always receive an integer.

Note: no tests are added for this as the existing tests cover this already, but don't show the issue unless `strict_types` mode is turned on.
The PHP native `strpos()` function expects an integer for the `$offset` parameter, however, the `strpos()` function used to determine the _offset_ will return an integer if the `$needle` is found, but `false` when the `$needle` doesn't exist in the `$haystack`.

This tweaks the code to allow for that and ensures that the `strpos()` function will always receive an integer.

Note: no tests are added for this as the existing tests cover this already, but don't show the issue unless `strict_types` mode is turned on.
A cookie will either be a key/value pair or just a plain value (with an implicit integer key).

The `Cookie::normalize_attribute()` method normalized the value based on a string based `key` and otherwise returns the `value` unchanged, so this function call can be bypassed when the cookie is just a plain value without a key as it won't have any effect anyway.

This prevents a call to the PHP native `strtolower()` function in the  `Cookie::normalize_attribute()` method from passing an integer where a string is expected.

Note: no tests are added for this as the existing tests cover this already, but don't show the issue unless `strict_types` mode is turned on.
An HTTP header will either be a key/value pair or just a plain value (with an implicit integer key).

This minor tweak prevents a call to the PHP native `strtolower()` function being passed an integer where a string is expected.

Note: no tests are added for this as the existing tests cover this already, but don't show the issue unless `strict_types` mode is turned on.
The `$request_path` parameter is expected to be a `string`, but in effect, all scalars are accepted, as well as stringable objects.

While this is fine for the code in the first half of the function, the second half strongly relies on PHP type juggling as the type is treated as a string as of that point.

To make this explicit and ensure that both the `strlen()` as well as the `substr()` functions will always receive the correct type, a type casts is being added.

Note: no tests are added for this as the existing tests cover this already, but don't show the issue unless `strict_types` mode is turned on.
@jrfnl jrfnl added this to the 2.1.0 milestone Nov 21, 2022
@jrfnl jrfnl requested a review from schlessera November 21, 2022 01:32
@schlessera schlessera merged commit 6b59c3f into develop Dec 12, 2022
@schlessera schlessera deleted the feature/stricter-type-adherence branch December 12, 2022 14:02
@schlessera schlessera modified the milestones: 2.1.0, 2.0.6 Apr 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants