Skip to content

Commit 4f50fce

Browse files
authored
Merge pull request #41 from donatj/delayedResponse
Delayed Response
2 parents bcec733 + 59daa82 commit 4f50fce

File tree

8 files changed

+275
-1
lines changed

8 files changed

+275
-1
lines changed

README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,66 @@ class ExampleTest extends PHPUnit_Framework_TestCase {
218218
}
219219
```
220220

221+
### Delayed Response Usage
222+
223+
By default responses will happen instantly. If you're looking to test timeouts, the DelayedResponse response wrapper may be useful.
224+
225+
```php
226+
<?php
227+
228+
use donatj\MockWebServer\DelayedResponse;
229+
use donatj\MockWebServer\MockWebServer;
230+
use donatj\MockWebServer\Response;
231+
232+
require __DIR__ . '/../vendor/autoload.php';
233+
234+
$server = new MockWebServer;
235+
$server->start();
236+
237+
$response = new Response(
238+
'This is our http body response',
239+
[ 'Cache-Control' => 'no-cache' ],
240+
200
241+
);
242+
243+
// Wrap the response in a DelayedResponse object, which will delay the response
244+
$delayedResponse = new DelayedResponse(
245+
$response,
246+
100000 // sets a delay of 100000 microseconds (.1 seconds) before returning the response
247+
);
248+
249+
$realtimeUrl = $server->setResponseOfPath('/realtime', $response);
250+
$delayedUrl = $server->setResponseOfPath('/delayed', $delayedResponse);
251+
252+
echo "Requesting: $realtimeUrl\n\n";
253+
254+
// This request will run as quickly as possible
255+
$start = microtime(true);
256+
file_get_contents($realtimeUrl);
257+
echo "Realtime Request took: " . (microtime(true) - $start) . " seconds\n\n";
258+
259+
echo "Requesting: $delayedUrl\n\n";
260+
261+
// The request will take the delayed time + the time it takes to make and transfer the request
262+
$start = microtime(true);
263+
file_get_contents($delayedUrl);
264+
echo "Delayed Request took: " . (microtime(true) - $start) . " seconds\n\n";
265+
266+
```
267+
268+
Outputs:
269+
270+
```
271+
Requesting: http://127.0.0.1:61355/realtime
272+
273+
Realtime Request took: 0.015669107437134 seconds
274+
275+
Requesting: http://127.0.0.1:61355/delayed
276+
277+
Delayed Request took: 0.10729098320007 seconds
278+
279+
```
280+
221281
## Multiple Responses from the Same Endpoint
222282

223283
### Response Stack

docs/docs.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,21 @@ Set the Response for the Given Method
293293
- ***string*** `$method`
294294
- ***\donatj\MockWebServer\ResponseInterface*** `$response`
295295

296+
## Class: \donatj\MockWebServer\DelayedResponse
297+
298+
DelayedResponse wraps a response, causing it when called to be delayed by a specified number of microseconds.
299+
300+
### Method: DelayedResponse->__construct
301+
302+
```php
303+
function __construct(\donatj\MockWebServer\ResponseInterface $response, $delay)
304+
```
305+
306+
#### Parameters:
307+
308+
- ***\donatj\MockWebServer\ResponseInterface*** `$response`
309+
- ***int*** `$delay` - Microseconds to delay the response
310+
296311
## Built-In Responses
297312

298313
### Class: \donatj\MockWebServer\Responses\DefaultResponse

example/delayed.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
use donatj\MockWebServer\DelayedResponse;
4+
use donatj\MockWebServer\MockWebServer;
5+
use donatj\MockWebServer\Response;
6+
7+
require __DIR__ . '/../vendor/autoload.php';
8+
9+
$server = new MockWebServer;
10+
$server->start();
11+
12+
$response = new Response(
13+
'This is our http body response',
14+
[ 'Cache-Control' => 'no-cache' ],
15+
200
16+
);
17+
18+
// Wrap the response in a DelayedResponse object, which will delay the response
19+
$delayedResponse = new DelayedResponse(
20+
$response,
21+
100000 // sets a delay of 100000 microseconds (.1 seconds) before returning the response
22+
);
23+
24+
$realtimeUrl = $server->setResponseOfPath('/realtime', $response);
25+
$delayedUrl = $server->setResponseOfPath('/delayed', $delayedResponse);
26+
27+
echo "Requesting: $realtimeUrl\n\n";
28+
29+
// This request will run as quickly as possible
30+
$start = microtime(true);
31+
file_get_contents($realtimeUrl);
32+
echo "Realtime Request took: " . (microtime(true) - $start) . " seconds\n\n";
33+
34+
echo "Requesting: $delayedUrl\n\n";
35+
36+
// The request will take the delayed time + the time it takes to make and transfer the request
37+
$start = microtime(true);
38+
file_get_contents($delayedUrl);
39+
echo "Delayed Request took: " . (microtime(true) - $start) . " seconds\n\n";

mddoc.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ There has been work [started to implement this](https://github.com/donatj/mock-w
2929
<file name="src/Response.php"/>
3030
<file name="src/ResponseStack.php"/>
3131
<file name="src/ResponseByMethod.php"/>
32+
<file name="src/DelayedResponse.php"/>
3233
<section title="Built-In Responses">
3334
<file name="src/Responses/DefaultResponse.php"/>
3435
<file name="src/Responses/NotFoundResponse.php"/>
@@ -65,6 +66,16 @@ There has been work [started to implement this](https://github.com/donatj/mock-w
6566
<section title="PHPUnit">
6667
<source name="example/phpunit.php" lang="php"/>
6768
</section>
69+
<section title="Delayed Response Usage">
70+
<text><![CDATA[By default responses will happen instantly. If you're looking to test timeouts, the DelayedResponse response wrapper may be useful.]]></text>
71+
<source name="example/delayed.php" lang="php"/>
72+
<text>Outputs:</text>
73+
<replace regex="true" search="%Realtime Request took: 0\.\d+ seconds%" replace="Realtime Request took: 0.015669107437134 seconds">
74+
<replace regex="true" search="%Delayed Request took: 0\.\d+ seconds%" replace="Delayed Request took: 0.10729098320007 seconds">
75+
<exec cmd="php example/delayed.php" format="code-block" />
76+
</replace>
77+
</replace>
78+
</section>
6879
</section>
6980
<section title="Multiple Responses from the Same Endpoint">
7081
<section title="Response Stack">

src/DelayedResponse.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
namespace donatj\MockWebServer;
4+
5+
/**
6+
* DelayedResponse wraps a response, causing it when called to be delayed by a specified number of microseconds.
7+
*/
8+
class DelayedResponse implements InitializingResponseInterface, MultiResponseInterface {
9+
10+
/**
11+
* @var int Microseconds to delay the response by.
12+
*/
13+
protected $delay;
14+
/**
15+
* @var \donatj\MockWebServer\ResponseInterface
16+
*/
17+
protected $response;
18+
19+
/**
20+
* @param \donatj\MockWebServer\ResponseInterface $response
21+
* @param int $delay Microseconds to delay the response
22+
*/
23+
public function __construct(
24+
ResponseInterface $response,
25+
$delay
26+
) {
27+
$this->response = $response;
28+
$this->delay = $delay;
29+
}
30+
31+
/**
32+
* @inheritDoc
33+
*/
34+
public function getRef() {
35+
return md5('delayed-' . $this->response->getRef());
36+
}
37+
38+
/**
39+
* @inheritDoc
40+
*/
41+
public function initialize( RequestInfo $request ) {
42+
usleep($this->delay);
43+
}
44+
45+
/**
46+
* @inheritDoc
47+
*/
48+
public function getBody( RequestInfo $request ) {
49+
return $this->response->getBody($request);
50+
}
51+
52+
/**
53+
* @inheritDoc
54+
*/
55+
public function getHeaders( RequestInfo $request ) {
56+
return $this->response->getHeaders($request);
57+
}
58+
59+
/**
60+
* @inheritDoc
61+
*/
62+
public function getStatus( RequestInfo $request ) {
63+
return $this->response->getStatus($request);
64+
}
65+
66+
/**
67+
* @inheritDoc
68+
*/
69+
public function next() {
70+
if( $this->response instanceof MultiResponseInterface ) {
71+
return $this->response->next();
72+
}
73+
74+
return false;
75+
}
76+
77+
}

src/InitializingResponseInterface.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace donatj\MockWebServer;
4+
5+
interface InitializingResponseInterface extends ResponseInterface {
6+
7+
/**
8+
* @param \donatj\MockWebServer\RequestInfo $request
9+
* @return void
10+
* @internal
11+
*/
12+
public function initialize( RequestInfo $request );
13+
14+
}

src/InternalServer.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ public function __invoke() {
132132
}
133133

134134
protected function sendResponse( ResponseInterface $response ) {
135+
if( $response instanceof InitializingResponseInterface ) {
136+
$response->initialize($this->request);
137+
}
138+
135139
http_response_code($response->getStatus($this->request));
136140

137141
foreach( $response->getHeaders($this->request) as $key => $header ) {

test/MockWebServer_IntegrationTest.php

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use donatj\MockWebServer\DelayedResponse;
34
use donatj\MockWebServer\MockWebServer;
45
use donatj\MockWebServer\Response;
56
use donatj\MockWebServer\ResponseByMethod;
@@ -13,7 +14,6 @@
1314

1415
class MockWebServer_IntegrationTest extends BaseServerTest {
1516

16-
1717
public function testBasic() {
1818
$url = self::$server->getServerRoot() . '/endpoint?get=foobar';
1919
$content = file_get_contents($url);
@@ -147,6 +147,60 @@ public function testHttpMethods() {
147147
$this->assertStringEndsWith('501 Not Implemented', $http_response_header[0]);
148148
}
149149

150+
public function testDelayedResponse() {
151+
152+
$realtimeResponse = new Response(
153+
'This is our http body response',
154+
[ 'X-Foo-Bar' => 'BazBazBaz' ],
155+
200
156+
);
157+
158+
$delayedResponse = new DelayedResponse($realtimeResponse, 1000000);
159+
160+
$this->assertNotSame($realtimeResponse->getRef(), $delayedResponse->getRef(),
161+
'DelayedResponse should change the ref. If they are the same, using both causes issues.');
162+
163+
$realtimeUrl = self::$server->setResponseOfPath('/realtimePath', $realtimeResponse);
164+
$delayedUrl = self::$server->setResponseOfPath('/delayedPath', $delayedResponse);
165+
166+
167+
$realtimeStart = microtime(true);
168+
file_get_contents($realtimeUrl);
169+
170+
$delayedStart = microtime(true);
171+
$delayedContent = file_get_contents($delayedUrl);
172+
173+
$end = microtime(true);
174+
175+
$this->assertGreaterThan(.9, ($end - $delayedStart) - ($delayedStart - $realtimeStart), 'Delayed response should take ~1 seconds longer than realtime response');
176+
177+
$this->assertEquals('This is our http body response', $delayedContent);
178+
$this->assertContains('X-Foo-Bar: BazBazBaz', $http_response_header);
179+
}
180+
181+
public function testDelayedMultiResponse() {
182+
$multi = new ResponseStack(
183+
new Response('Response One', [ 'X-Boop-Bat' => 'Sauce' ], 200),
184+
new Response('Response Two', [ 'X-Slaw-Dawg: FranCran' ], 200)
185+
);
186+
187+
$delayed = new DelayedResponse($multi, 1000000);
188+
189+
$path = self::$server->setResponseOfPath('/delayedMultiPath', $delayed);
190+
191+
$start = microtime(true);
192+
$contentOne = file_get_contents($path);
193+
$this->assertSame($contentOne, 'Response One');
194+
$this->assertContains('X-Boop-Bat: Sauce', $http_response_header);
195+
$this->assertGreaterThan(.9, microtime(true) - $start, 'Delayed response should take ~1 seconds longer than realtime response');
196+
197+
$start = microtime(true);
198+
$contentTwo = file_get_contents($path);
199+
$this->assertSame($contentTwo, 'Response Two');
200+
$this->assertContains('X-Slaw-Dawg: FranCran', $http_response_header);
201+
$this->assertGreaterThan(.9, microtime(true) - $start, 'Delayed response should take ~1 seconds longer than realtime response');
202+
}
203+
150204
/**
151205
* Regression Test - Was a problem in 1.0.0-beta.2
152206
*/

0 commit comments

Comments
 (0)