-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add integration tests starting a web server and performing roundtrips
- Loading branch information
Showing
6 changed files
with
209 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
src/main/php | ||
src/test/php | ||
src/test/php | ||
src/it/php |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<?php namespace web\unittest; | ||
|
||
use unittest\TestCase; | ||
|
||
#[@action(new StartServer('web.unittest.TestingServer', 'connected'))] | ||
class IntegrationTest extends TestCase { | ||
private static $connection; | ||
|
||
/** @param peer.Socket $client */ | ||
public static function connected($client) { | ||
self::$connection= $client; | ||
} | ||
|
||
/** | ||
* Sends a request | ||
* | ||
* @param string $method | ||
* @param string $uri | ||
* @param [:string] $headers | ||
* @param string $body | ||
* @return void | ||
*/ | ||
private function send($method, $uri, $headers= [], $body= '') { | ||
self::$connection->write($method.' '.$uri." HTTP/1.0\r\n"); | ||
foreach ($headers as $name => $value) { | ||
self::$connection->write($name.': '.$value."\r\n"); | ||
} | ||
self::$connection->write("\r\n".$body); | ||
} | ||
|
||
#[@test, @values([ | ||
# [200, '200 OK'], | ||
# [404, '404 Not Found'], | ||
# [420, '420 Enhanced your calm'], | ||
#])] | ||
public function echo_status($code, $expected) { | ||
$this->send('GET', '/status/'.$code); | ||
|
||
$status= self::$connection->readLine(); | ||
$this->assertEquals("HTTP/1.0 $expected", $status); | ||
} | ||
|
||
#[@test] | ||
public function raising_exception_yield_500() { | ||
$this->send('GET', '/raise/exception'); | ||
|
||
$status= self::$connection->readLine(); | ||
$this->assertEquals("HTTP/1.0 500 Internal Server Error", $status); | ||
} | ||
|
||
#[@test] | ||
public function unrouted_uris_yield_404() { | ||
$this->send('GET', '/not-routed'); | ||
|
||
$status= self::$connection->readLine(); | ||
$this->assertEquals("HTTP/1.0 404 Not Found", $status); | ||
} | ||
|
||
#[@test] | ||
public function malformed_protocol() { | ||
self::$connection->write("EHLO example.org\r\n"); | ||
|
||
$status= self::$connection->readLine(); | ||
$this->assertEquals("HTTP/1.1 400 Bad Request", $status); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php namespace web\unittest; | ||
|
||
use lang\{Runtime, XPClass}; | ||
use peer\Socket; | ||
use unittest\{PrerequisitesNotMetError, Test, TestAction, TestClassAction}; | ||
|
||
class StartServer implements TestAction, TestClassAction { | ||
private $server, $connected, $process, $client; | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param string $server Server process main class | ||
* @param string $connected Name of connection callback | ||
*/ | ||
public function __construct($server, $connected) { | ||
$this->server= $server; | ||
$this->connected= $connected; | ||
} | ||
|
||
/** | ||
* Starts server | ||
* | ||
* @param lang.XPClass $c | ||
* @return void | ||
* @throws unittest.PrerequisitesNotMetError | ||
*/ | ||
public function beforeTestClass(XPClass $c) { | ||
$this->process= Runtime::getInstance()->newInstance(null, 'class', $this->server, []); | ||
$this->process->in->close(); | ||
|
||
// Check if startup succeeded | ||
$status= $this->process->out->readLine(); | ||
if (2 !== sscanf($status, '+ Service %[0-9.]:%d', $host, $port)) { | ||
$this->afterTestClass($c); | ||
throw new PrerequisitesNotMetError('Cannot start server: '.$status, null); | ||
} | ||
|
||
$this->client= new Socket($host, $port); | ||
$c->getMethod($this->connected)->invoke(null, [$this->client]); | ||
} | ||
|
||
/** | ||
* This method gets invoked before a test method is invoked, and before | ||
* the setUp() method is called. | ||
* | ||
* @param unittest.Test $t | ||
* @return void | ||
* @throws unittest.PrerequisitesNotMetError | ||
*/ | ||
public function beforeTest(Test $t) { | ||
$this->client->connect(); | ||
} | ||
|
||
/** | ||
* This method gets invoked after the test method is invoked and regard- | ||
* less of its outcome, after the tearDown() call has run. | ||
* | ||
* @param unittest.Test $t | ||
* @return void | ||
*/ | ||
public function afterTest(Test $t) { | ||
$this->client->close(); | ||
} | ||
|
||
/** | ||
* Shuts down server | ||
* | ||
* @param lang.XPClass $c | ||
* @return void | ||
*/ | ||
public function afterTestClass(XPClass $c) { | ||
$this->process->err->close(); | ||
$this->process->out->close(); | ||
$this->process->terminate(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php namespace web\unittest; | ||
|
||
use lang\IllegalAccessException; | ||
use web\Application; | ||
|
||
class TestingApplication extends Application { | ||
|
||
/** @return var */ | ||
public function routes() { | ||
return [ | ||
'/status/420' => function($req, $res) { | ||
$res->answer(420, 'Enhanced your calm'); | ||
$res->send('Answered with status 420', 'text/plain'); | ||
}, | ||
'/status' => function($req, $res) { | ||
$status= basename($req->uri()->path()); | ||
$res->answer($status); | ||
$res->send('Answered with status '.$status, 'text/plain'); | ||
}, | ||
'/raise/exception' => function($req, $res) { | ||
throw new IllegalAccessException('No access!'); | ||
} | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?php namespace web\unittest; | ||
|
||
use lang\Throwable; | ||
use peer\ServerSocket; | ||
use peer\server\Server; | ||
use util\cmd\Console; | ||
use web\{Environment, Logging}; | ||
use xp\web\srv\HttpProtocol; | ||
|
||
/** | ||
* Socket server used by integration tests. | ||
* | ||
* Process interaction is performed by messages this server prints to | ||
* standard out: | ||
* | ||
* - Server listens on a free port @ 127.0.0.1 | ||
* - On startup success, "+ Service (IP):(PORT)" is written | ||
* - On errors, "- " and the exception message are written | ||
*/ | ||
class TestingServer { | ||
|
||
/** Starts the server */ | ||
public static function main(array $args) { | ||
$application= new TestingApplication(new Environment('test', '.', '.', '.', [], null)); | ||
|
||
$s= new Server(); | ||
try { | ||
$s->listen(new ServerSocket('127.0.0.1', 0), new HttpProtocol($application, new Logging(null))); | ||
$s->init(); | ||
Console::writeLinef('+ Service %s:%d', $s->socket->host, $s->socket->port); | ||
$s->service(); | ||
$s->shutdown(); | ||
} catch (Throwable $e) { | ||
Console::writeLine('- ', $e->getMessage()); | ||
} | ||
} | ||
} |