Skip to content

Commit 05b8c2b

Browse files
committed
Added tests
1 parent c7ad47a commit 05b8c2b

17 files changed

+1483
-0
lines changed

test/Callback.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Dazzle\Stream\Test;
4+
5+
class Callback
6+
{
7+
public function __invoke()
8+
{}
9+
}

test/TModule.php

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
<?php
2+
3+
namespace Dazzle\Stream\Test;
4+
5+
use Dazzle\Loop\Model\SelectLoop;
6+
use Dazzle\Loop\Loop;
7+
use Dazzle\Loop\LoopExtendedInterface;
8+
use Dazzle\Loop\LoopInterface;
9+
use Dazzle\Stream\Test\_Simulation\Event;
10+
use Dazzle\Stream\Test\_Simulation\Simulation;
11+
use Exception;
12+
13+
class TModule extends TUnit
14+
{
15+
/**
16+
* @var string
17+
*/
18+
const MSG_EVENT_NAME_ASSERTION_FAILED = 'Expected event name mismatch on %s event.';
19+
20+
/**
21+
* @var string
22+
*/
23+
const MSG_EVENT_DATA_ASSERTION_FAILED = 'Expected event data mismatch on %s event.';
24+
25+
/**
26+
* @var string
27+
*/
28+
const MSG_EVENT_GET_ASSERTION_FAILED = "Expected event count mismatch after %s events.\nExpected event %s, got event %s.";
29+
30+
/**
31+
* @var LoopExtendedInterface
32+
*/
33+
private $loop;
34+
35+
/**
36+
* @var Simulation
37+
*/
38+
private $sim;
39+
40+
/**
41+
*
42+
*/
43+
public function setUp()
44+
{
45+
$this->loop = null;
46+
$this->sim = null;
47+
}
48+
49+
/**
50+
*
51+
*/
52+
public function tearDown()
53+
{
54+
unset($this->sim);
55+
unset($this->loop);
56+
}
57+
58+
/**
59+
* @return LoopInterface|null
60+
*/
61+
public function getLoop()
62+
{
63+
return $this->loop;
64+
}
65+
66+
/**
67+
* Run test scenario as simulation.
68+
*
69+
* @param callable(Simulation) $scenario
70+
* @return TModule
71+
*/
72+
public function simulate(callable $scenario)
73+
{
74+
try
75+
{
76+
$this->loop = new Loop(new SelectLoop);
77+
$this->loop->erase(true);
78+
79+
$this->sim = new Simulation($this->loop);
80+
$this->sim->setScenario($scenario);
81+
$this->sim->begin();
82+
}
83+
catch (Exception $ex)
84+
{
85+
$this->fail($ex->getMessage());
86+
}
87+
88+
return $this;
89+
}
90+
91+
/**
92+
* @param $events
93+
* @param int $flags
94+
* @return TModule
95+
*/
96+
public function expect($events, $flags = Simulation::EVENTS_COMPARE_IN_ORDER)
97+
{
98+
$expectedEvents = [];
99+
100+
foreach ($events as $event)
101+
{
102+
$data = isset($event[1]) ? $event[1] : [];
103+
$expectedEvents[] = new Event($event[0], $data);
104+
}
105+
106+
$this->assertEvents(
107+
$this->sim->getExpectations(),
108+
$expectedEvents,
109+
$flags
110+
);
111+
112+
return $this;
113+
}
114+
115+
/**
116+
* @param Event[] $actualEvents
117+
* @param Event[] $expectedEvents
118+
* @param int $flags
119+
*/
120+
public function assertEvents($actualEvents = [], $expectedEvents = [], $flags = Simulation::EVENTS_COMPARE_IN_ORDER)
121+
{
122+
$count = max(count($actualEvents), count($expectedEvents));
123+
124+
if ($flags === Simulation::EVENTS_COMPARE_RANDOMLY)
125+
{
126+
sort($actualEvents);
127+
sort($expectedEvents);
128+
}
129+
130+
for ($i=0; $i<$count; $i++)
131+
{
132+
if (!isset($actualEvents[$i]))
133+
{
134+
$this->fail(
135+
sprintf(self::MSG_EVENT_GET_ASSERTION_FAILED, $i, $expectedEvents[$i]->name(), 'null')
136+
);
137+
}
138+
else if (!isset($expectedEvents[$i]))
139+
{
140+
$this->fail(
141+
sprintf(self::MSG_EVENT_GET_ASSERTION_FAILED, $i, 'null', $actualEvents[$i]->name())
142+
);
143+
}
144+
145+
$actualEvent = $actualEvents[$i];
146+
$expectedEvent = $expectedEvents[$i];
147+
148+
$this->assertSame(
149+
$expectedEvent->name(),
150+
$actualEvent->name(),
151+
sprintf(self::MSG_EVENT_NAME_ASSERTION_FAILED, $i)
152+
);
153+
$this->assertSame(
154+
$expectedEvent->data(),
155+
$actualEvent->data(),
156+
sprintf(self::MSG_EVENT_DATA_ASSERTION_FAILED, $i)
157+
);
158+
}
159+
}
160+
}

test/TModule/AsyncStreamTest.php

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
namespace Dazzle\Stream\Test\TModule\Stream;
4+
5+
use Dazzle\Stream\AsyncStreamReaderInterface;
6+
use Dazzle\Stream\AsyncStreamWriterInterface;
7+
use Dazzle\Stream\Test\_Simulation\SimulationInterface;
8+
use Dazzle\Stream\Test\TModule;
9+
use ReflectionClass;
10+
11+
/**
12+
* @runTestsInSeparateProcesses
13+
* @preserveGlobalState disabled
14+
*/
15+
class AsyncStreamTest extends TModule
16+
{
17+
public function tearDown()
18+
{
19+
$local = $this->basePath();
20+
unlink("$local/temp");
21+
}
22+
23+
/**
24+
* @dataProvider asyncStreamPairProvider
25+
* @param string $readerClass
26+
* @param string $writerClass
27+
*/
28+
public function testAsyncStream_WritesAndReadsDataCorrectly($readerClass, $writerClass)
29+
{
30+
$this
31+
->simulate(function(SimulationInterface $sim) use($readerClass, $writerClass) {
32+
$loop = $sim->getLoop();
33+
$local = $this->basePath();
34+
$cnt = 0;
35+
36+
$reader = (new ReflectionClass($readerClass))->newInstance(
37+
fopen("file://$local/temp", 'w+'),
38+
$loop
39+
);
40+
$reader->on('data', function(AsyncStreamReaderInterface $conn, $data) use($sim) {
41+
$sim->expect('data', $data);
42+
$conn->close();
43+
});
44+
$reader->on('end', $this->expectCallableOnce());
45+
$reader->on('drain', $this->expectCallableNever());
46+
$reader->on('finish', $this->expectCallableNever());
47+
$reader->on('error', $this->expectCallableNever());
48+
$reader->on('close', function() use($sim, &$cnt) {
49+
$sim->expect('close');
50+
if (++$cnt === 2)
51+
{
52+
$sim->done();
53+
}
54+
});
55+
56+
$writer = (new ReflectionClass($writerClass))->newInstance(
57+
fopen("file://$local/temp", 'r+'),
58+
$loop
59+
);
60+
$writer->on('data', $this->expectCallableNever());
61+
$writer->on('end', $this->expectCallableNever());
62+
$writer->on('drain', function(AsyncStreamWriterInterface $writer) use($sim) {
63+
$sim->expect('drain');
64+
$writer->close();
65+
});
66+
$writer->on('finish', $this->expectCallableOnce());
67+
$writer->on('error', $this->expectCallableNever());
68+
$writer->on('close', function() use($sim, &$cnt) {
69+
$sim->expect('close');
70+
if (++$cnt === 2)
71+
{
72+
$sim->done();
73+
}
74+
});
75+
76+
$writer->write('message!');
77+
$reader->read();
78+
})
79+
->expect([
80+
[ 'drain' ],
81+
[ 'close' ],
82+
[ 'data', 'message!' ],
83+
[ 'close' ]
84+
])
85+
;
86+
}
87+
88+
/**
89+
* Provider classes of AsyncStream.
90+
*
91+
* @return string[][]
92+
*/
93+
public function asyncStreamPairProvider()
94+
{
95+
return [
96+
[
97+
'Dazzle\Stream\AsyncStream',
98+
'Dazzle\Stream\AsyncStream'
99+
],
100+
[
101+
'Dazzle\Stream\AsyncStreamReader',
102+
'Dazzle\Stream\AsyncStreamWriter'
103+
]
104+
];
105+
}
106+
}

test/TModule/StreamTest.php

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
namespace Dazzle\Stream\Test\TModule\Stream;
4+
5+
use Dazzle\Stream\Stream;
6+
use Dazzle\Stream\StreamReader;
7+
use Dazzle\Stream\StreamWriter;
8+
use Dazzle\Stream\Test\TModule;
9+
10+
/**
11+
* @runTestsInSeparateProcesses
12+
* @preserveGlobalState disabled
13+
*/
14+
class StreamTest extends TModule
15+
{
16+
public function tearDown()
17+
{
18+
$local = $this->basePath();
19+
unlink("$local/temp");
20+
21+
parent::tearDown();
22+
}
23+
24+
public function testStream_WriteAndReadDataScenario()
25+
{
26+
$local = $this->basePath();
27+
$writer = new Stream(fopen("file://$local/temp", 'w+'));
28+
$reader = new Stream(fopen("file://$local/temp", 'r+'));
29+
30+
$expectedData = "qwertyuiop\n";
31+
$capturedData = null;
32+
$readData = null;
33+
34+
$reader->on('data', function($origin, $data) use(&$capturedData) {
35+
$capturedData = $data;
36+
});
37+
$reader->on('end', $this->expectCallableOnce());
38+
$reader->on('error', $this->expectCallableNever());
39+
$reader->on('close', $this->expectCallableOnce());
40+
41+
$writer->on('drain', $this->expectCallableOnce());
42+
$writer->on('finish', $this->expectCallableOnce());
43+
$writer->on('error', $this->expectCallableNever());
44+
$writer->on('close', $this->expectCallableOnce());
45+
46+
$writer->write($expectedData);
47+
$readData = $reader->read();
48+
49+
$writer->close();
50+
$reader->close();
51+
52+
$this->assertEquals($expectedData, $readData);
53+
$this->assertEquals($expectedData, $capturedData);
54+
}
55+
56+
public function testStreamReader_StreamWriter_WriteAndReadDataScenario()
57+
{
58+
$local = $this->basePath();
59+
$writer = new StreamWriter(fopen("file://$local/temp", 'w+'));
60+
$reader = new StreamReader(fopen("file://$local/temp", 'r+'));
61+
62+
$expectedData = "qwertyuiop\n";
63+
$capturedData = null;
64+
$readData = null;
65+
66+
$reader->on('data', function($origin, $data) use(&$capturedData) {
67+
$capturedData = $data;
68+
});
69+
$reader->on('drain', $this->expectCallableNever());
70+
$reader->on('error', $this->expectCallableNever());
71+
$reader->on('close', $this->expectCallableOnce());
72+
73+
$writer->on('data', $this->expectCallableNever());
74+
$writer->on('drain', $this->expectCallableOnce());
75+
$writer->on('error', $this->expectCallableNever());
76+
$writer->on('close', $this->expectCallableOnce());
77+
78+
$writer->write($expectedData);
79+
$readData = $reader->read();
80+
81+
$writer->close();
82+
$reader->close();
83+
84+
$this->assertEquals($expectedData, $readData);
85+
$this->assertEquals($expectedData, $capturedData);
86+
}
87+
}

0 commit comments

Comments
 (0)