Browse Source
- Makes use of PHP's internal Web server to deliver expected responses from a real server - Windows batch file can be used to run tests (Linux and Mac test runners to come later) - Added PHPUnit to dev dependenciesmicrosub
J. King
7 years ago
10 changed files with 1273 additions and 61 deletions
File diff suppressed because it is too large
@ -0,0 +1,44 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
namespace JKingWeb\Arsse\Misc; |
|||
|
|||
trait DateFormatter { |
|||
|
|||
protected function dateTransform($date, string $format = "iso8601", bool $local = false) { |
|||
$date = $this->dateNormalize($date); |
|||
$format = strtolower($format); |
|||
if($format=="unix") return $date; |
|||
switch ($format) { |
|||
case 'http': $f = "D, d M Y H:i:s \G\M\T"; break; |
|||
case 'iso8601': $f = \DateTime::ATOM; break; |
|||
case 'sql': $f = "Y-m-d H:i:s"; break; |
|||
case 'date': $f = "Y-m-d"; break; |
|||
case 'time': $f = "H:i:s"; break; |
|||
default: $f = \DateTime::ATOM; break; |
|||
} |
|||
if($local) { |
|||
return date($f, $date); |
|||
} else { |
|||
return gmdate($f, $date); |
|||
} |
|||
} |
|||
|
|||
protected function dateNormalize($date) { |
|||
// convert input to a Unix timestamp |
|||
if($date instanceof \DateTimeInterface) { |
|||
$time = $date->getTimestamp(); |
|||
} else if(is_numeric($date)) { |
|||
$time = (int) $date; |
|||
} else if($date===null) { |
|||
return null; |
|||
} else if(is_string($date)) { |
|||
$time = strtotime($date); |
|||
if($time===false) return null; |
|||
} else if (is_bool($date)) { |
|||
return null; |
|||
} else { |
|||
$time = (int) $date; |
|||
} |
|||
return $time; |
|||
} |
|||
} |
@ -0,0 +1,63 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
namespace JKingWeb\Arsse; |
|||
Use Phake; |
|||
|
|||
|
|||
class TestFeed extends \PHPUnit\Framework\TestCase { |
|||
use Test\Tools; |
|||
|
|||
protected $base = "http://localhost:8000/Feed/"; |
|||
|
|||
function time(string $t): string { |
|||
return gmdate("D, d M Y H:i:s \G\M\T", strtotime($t)); |
|||
} |
|||
|
|||
function setUp() { |
|||
$this->clearData(); |
|||
Data::$conf = new Conf(); |
|||
} |
|||
|
|||
function testComputeNextFetchFrom304() { |
|||
// if less than half an hour, check in 15 minutes |
|||
$exp = strtotime("now + 15 minutes"); |
|||
$t = strtotime("now"); |
|||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", $this->dateTransform($t, "http")); |
|||
$this->assertTime($exp, $f->nextFetch); |
|||
$t = strtotime("now - 29 minutes"); |
|||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", $this->dateTransform($t, "http")); |
|||
$this->assertTime($exp, $f->nextFetch); |
|||
// if less than an hour, check in 30 minutes |
|||
$exp = strtotime("now + 30 minutes"); |
|||
$t = strtotime("now - 30 minutes"); |
|||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", $this->dateTransform($t, "http")); |
|||
$this->assertTime($exp, $f->nextFetch); |
|||
$t = strtotime("now - 59 minutes"); |
|||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", $this->dateTransform($t, "http")); |
|||
$this->assertTime($exp, $f->nextFetch); |
|||
// if less than three hours, check in an hour |
|||
$exp = strtotime("now + 1 hour"); |
|||
$t = strtotime("now - 1 hour"); |
|||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", $this->dateTransform($t, "http")); |
|||
$this->assertTime($exp, $f->nextFetch); |
|||
$t = strtotime("now - 2 hours 59 minutes"); |
|||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", $this->dateTransform($t, "http")); |
|||
$this->assertTime($exp, $f->nextFetch); |
|||
// if more than 36 hours, check in 24 hours |
|||
$exp = strtotime("now + 1 day"); |
|||
$t = strtotime("now - 36 hours"); |
|||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", $this->dateTransform($t, "http")); |
|||
$this->assertTime($exp, $f->nextFetch); |
|||
$t = strtotime("now - 2 years"); |
|||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", $this->dateTransform($t, "http")); |
|||
$this->assertTime($exp, $f->nextFetch); |
|||
// otherwise check in three hours |
|||
$exp = strtotime("now + 3 hours"); |
|||
$t = strtotime("now - 6 hours"); |
|||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", $this->dateTransform($t, "http")); |
|||
$this->assertTime($exp, $f->nextFetch); |
|||
$t = strtotime("now - 35 hours"); |
|||
$f = new Feed(null, $this->base."NextFetch/NotModified?t=$t", $this->dateTransform($t, "http")); |
|||
$this->assertTime($exp, $f->nextFetch); |
|||
} |
|||
} |
@ -0,0 +1,4 @@ |
|||
<?php return [ |
|||
'code' => 304, |
|||
'lastMod' => (int) $_GET['t'], |
|||
]; |
@ -0,0 +1,66 @@ |
|||
<?php |
|||
declare(strict_types=1); |
|||
namespace JKingWeb\Arsse; |
|||
require_once __DIR__."/../bootstrap.php"; |
|||
|
|||
/* |
|||
|
|||
This is a so-called router for the the internal PHP Web server: |
|||
<http://php.net/manual/en/features.commandline.webserver.php> |
|||
|
|||
It is used to test feed parsing in a controlled environment, |
|||
answering specific requests used in tests with the data required |
|||
to pass the test. |
|||
|
|||
The parameters of the responses are kept in separate files, |
|||
which include the following data: |
|||
|
|||
- Response content |
|||
- Response code |
|||
- Content type |
|||
- Whether to send cache headers |
|||
- Last modified |
|||
- Any other headers |
|||
|
|||
*/ |
|||
|
|||
|
|||
$defaults = [ // default values for response |
|||
'code' => 200, |
|||
'content' => "", |
|||
'mime' => "application/octet-stream", |
|||
'lastMod' => time(), |
|||
'cache' => true, |
|||
'fields' => [], |
|||
]; |
|||
|
|||
$url = explode("?",$_SERVER['REQUEST_URI'])[0]; |
|||
$base = BASE."tests".\DIRECTORY_SEPARATOR."docroot"; |
|||
$test = $base.str_replace("/",\DIRECTORY_SEPARATOR,$url).".php"; |
|||
if(!file_exists($test)) { |
|||
$response = [ |
|||
'code' => 499, |
|||
'content' => "Test '$test' missing.", |
|||
'mime' => "application/octet-stream", |
|||
'lastMod' => time(), |
|||
'cache' => true, |
|||
'fields' => [], |
|||
]; |
|||
} else { |
|||
$response = array_merge($defaults, (include $test)); |
|||
} |
|||
// set the response code |
|||
http_response_code((int) $response['code']); |
|||
// if the response has a body, set the content type and (possibly) the ETag. |
|||
if(strlen($response['content'])) { |
|||
header("Content-Type: ".$response['mime']); |
|||
if($response['cache']) header("ETag: ".md5($response['content'])); |
|||
} |
|||
// if caching is enabled, set the last-modified date |
|||
if($response['cache']) header("Last-Modified: ".gmdate("D, d M Y H:i:s \G\M\T", $response['lastMod'])); |
|||
// set any other specified fields verbatim |
|||
foreach($response['fields'] as $h) { |
|||
header($h); |
|||
} |
|||
// send the content |
|||
echo $response['content']; |
@ -0,0 +1,10 @@ |
|||
@echo off |
|||
setlocal |
|||
set base=%~dp0 |
|||
start php -S localhost:8000 "%base%\server.php" |
|||
php "%base%\..\vendor\phpunit\phpunit\phpunit" -c "%base%\phpunit.xml" |
|||
timeout /nobreak /t 1 >nul |
|||
for /f "usebackq tokens=5" %%a in (`netstat -aon ^| find "LISTENING" ^| find ":8000"`) do ( |
|||
taskkill /pid %%a >nul |
|||
goto :eof |
|||
) |
Loading…
Reference in new issue