Skip to content

Commit 85e6621

Browse files
author
Martin Dostál
committed
Merge branch 'md-writerMock' into 'v1.7.0'
Add WriterMock See merge request redbitcz/composer/utils!27
2 parents 901ab71 + 145a903 commit 85e6621

File tree

5 files changed

+307
-0
lines changed

5 files changed

+307
-0
lines changed

src/IO/IBufferWriter.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Redbitcz\Utils\IO;
6+
7+
interface IBufferWriter extends IOutStream
8+
{
9+
public function hasOutputContent(): bool;
10+
11+
public function getOutputContent(): string;
12+
13+
public function hasErrorContent(): bool;
14+
15+
public function getErrorContent(): string;
16+
}

src/IO/LazyStreamWriter.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Redbitcz\Utils\IO;
6+
7+
use LogicException;
8+
9+
/**
10+
* Same as `FileWriter`, but is opening file descriptors only on first write them
11+
*/
12+
class LazyStreamWriter implements IOutStream
13+
{
14+
/** @var callable */
15+
private $outputStreamFactory;
16+
/** @var callable */
17+
private $errorStreamFactory;
18+
/** @var resource|null */
19+
private $outputStream;
20+
/** @var resource|null */
21+
private $errorStream;
22+
23+
/**
24+
* @param callable $outputStreamFactory Callback which return writable stream handler resource
25+
* @param callable $errorStreamFactory Callback which return writable stream handler resource
26+
*/
27+
public function __construct(callable $outputStreamFactory, callable $errorStreamFactory)
28+
{
29+
$this->outputStreamFactory = $outputStreamFactory;
30+
$this->errorStreamFactory = $errorStreamFactory;
31+
}
32+
33+
public function write(string $string): void
34+
{
35+
if ($this->outputStream === null) {
36+
$this->outputStream = $this->createStream($this->outputStreamFactory);
37+
}
38+
39+
fwrite($this->outputStream, $string);
40+
}
41+
42+
public function error(string $string): void
43+
{
44+
if ($this->errorStream === null) {
45+
$this->errorStream = $this->createStream($this->errorStreamFactory);
46+
}
47+
48+
fwrite($this->errorStream, $string);
49+
}
50+
51+
/**
52+
* @return resource
53+
*/
54+
private function createStream(callable $factory)
55+
{
56+
$stream = $factory();
57+
58+
if (is_resource($stream) === false) {
59+
$type = is_object($stream) ? get_class($stream) : gettype($stream);
60+
throw new LogicException(
61+
"Stream factory callback must returns valid stream handler resource, {$type} returned"
62+
);
63+
}
64+
65+
return $stream;
66+
}
67+
}

src/IO/MemoryWriter.php

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Redbitcz\Utils\IO;
6+
7+
use Closure;
8+
use RuntimeException;
9+
10+
class MemoryWriter implements IBufferWriter
11+
{
12+
/** @var resource|null */
13+
private $outputStream;
14+
15+
/** @var resource|null */
16+
private $errorStream;
17+
18+
/** @var LazyStreamWriter */
19+
private $writer;
20+
21+
public function __construct()
22+
{
23+
$this->writer = new LazyStreamWriter(
24+
Closure::fromCallable([$this, 'createOutputStream']),
25+
Closure::fromCallable([$this, 'createErrorStream']),
26+
);
27+
}
28+
29+
public function __destruct()
30+
{
31+
if ($this->hasOutputContent()) {
32+
fclose($this->outputStream);
33+
}
34+
35+
if ($this->hasErrorContent()) {
36+
fclose($this->errorStream);
37+
}
38+
}
39+
40+
public function write(string $string): void
41+
{
42+
$this->writer->write($string);
43+
}
44+
45+
public function error(string $string): void
46+
{
47+
$this->writer->error($string);
48+
}
49+
50+
/**
51+
* @return resource
52+
*/
53+
private function createOutputStream()
54+
{
55+
return $this->outputStream = $this->createMemoryStream();
56+
}
57+
58+
/**
59+
* @return resource
60+
*/
61+
private function createErrorStream()
62+
{
63+
return $this->errorStream = $this->createMemoryStream();
64+
}
65+
66+
public function hasOutputContent(): bool
67+
{
68+
return isset($this->outputStream);
69+
}
70+
71+
public function getOutputContent(): string
72+
{
73+
return $this->hasOutputContent() ? $this->getStreamContent($this->outputStream) : '';
74+
}
75+
76+
public function hasErrorContent(): bool
77+
{
78+
return isset($this->errorStream);
79+
}
80+
81+
public function getErrorContent(): string
82+
{
83+
return $this->hasErrorContent() ? $this->getStreamContent($this->errorStream) : '';
84+
}
85+
86+
/**
87+
* @return resource
88+
*/
89+
private function createMemoryStream()
90+
{
91+
$fileHandler = fopen('php://memory', 'wb+');
92+
93+
if ($fileHandler === false) {
94+
throw new RuntimeException("Unable to create Memory stream (php://memory)");
95+
}
96+
97+
return $fileHandler;
98+
}
99+
100+
/**
101+
* @param resource $fileHandler
102+
* @return string
103+
*/
104+
private function getStreamContent($fileHandler): string
105+
{
106+
return stream_get_contents($fileHandler, -1, 0);
107+
}
108+
}

tests/IO/LazyStreamWriterTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
/** @testCase */
3+
4+
declare(strict_types=1);
5+
6+
namespace Tests\IO;
7+
8+
use LogicException;
9+
use Redbitcz\Utils\IO\LazyStreamWriter;
10+
use Tester\Assert;
11+
use Tester\TestCase;
12+
13+
require __DIR__ . '/../../vendor/autoload.php';
14+
15+
class LazyStreamWriterTest extends TestCase
16+
{
17+
public function testInvalidCallback(): void
18+
{
19+
Assert::exception(static function () {
20+
$writer = new LazyStreamWriter(function() {return null;}, function() {return null;});
21+
$writer->write('foo');
22+
}, LogicException::class);
23+
24+
Assert::exception(static function () {
25+
$writer = new LazyStreamWriter(function() {return null;}, function() {return null;});
26+
$writer->error('foo');
27+
}, LogicException::class);
28+
}
29+
}
30+
31+
(new LazyStreamWriterTest)->run();

tests/IO/MemoryWriterTest.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
/** @testCase */
3+
4+
declare(strict_types=1);
5+
6+
namespace Tests\IO;
7+
8+
use Redbitcz\Utils\IO\MemoryWriter;
9+
use Tester\Assert;
10+
use Tester\TestCase;
11+
12+
require __DIR__ . '/../../vendor/autoload.php';
13+
14+
class MemoryWriterTest extends TestCase
15+
{
16+
/**
17+
* @return string[][]
18+
*/
19+
public function getTestOutputData(): array
20+
{
21+
return [
22+
['Hello'],
23+
['Lorem ipsum'],
24+
["Lorem ipsum\n"],
25+
["Lorem ipsum\ntest"],
26+
[""],
27+
["\n"],
28+
["\n\n"],
29+
];
30+
}
31+
32+
/**
33+
* @dataProvider getTestOutputData
34+
* @param string $testData
35+
*/
36+
public function testOutput(string $testData): void
37+
{
38+
$writer = new MemoryWriter();
39+
40+
$writer->write($testData);
41+
$writer->error('noob');
42+
43+
Assert::equal($testData, $writer->getOutputContent());
44+
Assert::equal('noob', $writer->getErrorContent());
45+
}
46+
47+
/**
48+
* @dataProvider getTestOutputData
49+
* @param string $testData
50+
*/
51+
public function testError(string $testData): void
52+
{
53+
$writer = new MemoryWriter();
54+
55+
$writer->write('noob');
56+
$writer->error($testData);
57+
58+
Assert::equal('noob', $writer->getOutputContent());
59+
Assert::equal($testData, $writer->getErrorContent());
60+
}
61+
62+
public function testEmpty(): void
63+
{
64+
$writer = new MemoryWriter();
65+
66+
Assert::equal('', $writer->getOutputContent());
67+
Assert::equal('', $writer->getErrorContent());
68+
}
69+
70+
public function testHasContent(): void
71+
{
72+
$writer = new MemoryWriter();
73+
74+
Assert::equal(false, $writer->hasOutputContent());
75+
Assert::equal(false, $writer->hasErrorContent());
76+
77+
$writer->write('foo');
78+
$writer->error('bar');
79+
80+
Assert::equal(true, $writer->hasOutputContent());
81+
Assert::equal(true, $writer->hasErrorContent());
82+
}
83+
}
84+
85+
(new MemoryWriterTest)->run();

0 commit comments

Comments
 (0)