96 lines
3.8 KiB
PHP
96 lines
3.8 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
use Steuerkram\Services\PayPalNvpFetchService;
|
||
|
||
/**
|
||
* Test 91: PayPalNvpFetchService – Erkennung abgeschnittener Antworten (#185).
|
||
*
|
||
* Eine abgeschnittene NVP-Antwort darf nicht still verworfen werden, sondern
|
||
* muss als Hinweis im Abrufprotokoll landen. Deckt die beiden dafür
|
||
* zuständigen Hilfsmethoden isTruncatedTransferError() und isLengthMismatch()
|
||
* ab, die ohne echte PayPal-Verbindung testbar sind.
|
||
*/
|
||
class PayPalNvpAbgeschnitteneAntwortTest extends TestCase
|
||
{
|
||
protected string $testName = 'Test 91: PayPalNvpFetchService – abgeschnittene Antworten';
|
||
|
||
public function run(): void
|
||
{
|
||
$this->testIsTruncatedTransferErrorErkenntBekannteFehlercodes();
|
||
$this->testIsTruncatedTransferErrorErkenntFehlermeldungstext();
|
||
$this->testIsTruncatedTransferErrorIgnoriertNormaleFehler();
|
||
$this->testIsLengthMismatchErkenntKuerzereAntwort();
|
||
$this->testIsLengthMismatchOhneFehlalarm();
|
||
}
|
||
|
||
private function callPrivateStatic(string $method, array $args = []): mixed
|
||
{
|
||
$ref = new \ReflectionMethod(PayPalNvpFetchService::class, $method);
|
||
$ref->setAccessible(true);
|
||
return $ref->invokeArgs(null, $args);
|
||
}
|
||
|
||
private function testIsTruncatedTransferErrorErkenntBekannteFehlercodes(): void
|
||
{
|
||
foreach ([CURLE_PARTIAL_FILE, CURLE_GOT_NOTHING, CURLE_RECV_ERROR] as $errNo) {
|
||
$this->assert(
|
||
$this->callPrivateStatic('isTruncatedTransferError', [$errNo, '']) === true,
|
||
"isTruncatedTransferError() erkennt cURL-Fehlercode {$errNo} als abgeschnittenen Transfer"
|
||
);
|
||
}
|
||
}
|
||
|
||
private function testIsTruncatedTransferErrorErkenntFehlermeldungstext(): void
|
||
{
|
||
$this->assert(
|
||
$this->callPrivateStatic('isTruncatedTransferError', [
|
||
0,
|
||
'transfer closed with 128 bytes remaining to read',
|
||
]) === true,
|
||
'isTruncatedTransferError() erkennt "transfer closed"-Meldungen auch bei unbekanntem Fehlercode'
|
||
);
|
||
$this->assert(
|
||
$this->callPrivateStatic('isTruncatedTransferError', [0, 'Empty reply from server']) === true,
|
||
'isTruncatedTransferError() erkennt "Empty reply from server"'
|
||
);
|
||
}
|
||
|
||
private function testIsTruncatedTransferErrorIgnoriertNormaleFehler(): void
|
||
{
|
||
$this->assert(
|
||
$this->callPrivateStatic('isTruncatedTransferError', [0, '']) === false,
|
||
'isTruncatedTransferError() meldet ohne Fehlercode/-text keinen Abbruch'
|
||
);
|
||
$this->assert(
|
||
$this->callPrivateStatic('isTruncatedTransferError', [CURLE_COULDNT_CONNECT, 'Connection refused']) === false,
|
||
'isTruncatedTransferError() stuft einen Verbindungsfehler nicht als abgeschnittene Antwort ein'
|
||
);
|
||
}
|
||
|
||
private function testIsLengthMismatchErkenntKuerzereAntwort(): void
|
||
{
|
||
$this->assert(
|
||
$this->callPrivateStatic('isLengthMismatch', ['ACK=Success', 100.0]) === true,
|
||
'isLengthMismatch() erkennt eine Antwort, die kürzer als Content-Length ist'
|
||
);
|
||
}
|
||
|
||
private function testIsLengthMismatchOhneFehlalarm(): void
|
||
{
|
||
$vollstaendig = 'ACK=Success';
|
||
$this->assert(
|
||
$this->callPrivateStatic('isLengthMismatch', [$vollstaendig, (float)strlen($vollstaendig)]) === false,
|
||
'isLengthMismatch() schlägt bei übereinstimmender Länge nicht an'
|
||
);
|
||
$this->assert(
|
||
$this->callPrivateStatic('isLengthMismatch', ['ACK=Success', 0.0]) === false,
|
||
'isLengthMismatch() schlägt ohne bekannte Content-Length (0/-1) nicht an'
|
||
);
|
||
$this->assert(
|
||
$this->callPrivateStatic('isLengthMismatch', ['ACK=Success', -1.0]) === false,
|
||
'isLengthMismatch() schlägt bei negativer Content-Length nicht an'
|
||
);
|
||
}
|
||
}
|