Increase test coverage
kelunik opened this issue · comments
We're currently at only 36%, that's way too low. This is an issue that should stay open as long as we're not on an acceptable level.
We're now at 64%, progress!
I'd be happy to work on this one!
Just submit a PR. :-)
I'm having trouble while testing the ZlibOutputStream
.
Here are my steps:
-
I create a
IteratorStream
with thefixtures/foobar.txt
contents, like in theZlibInputStreamTest
. -
In the
ZlibOutputStream
instance I don't know what to pass as to the first parameter. What kind ofOutputStream
should I use? I tried to use anew ResourceOutputStream(fopen("php://memory", "wb+"))
. I also tried to create aResourceInputStream
with the same resource stream, but I can't read it back. -
I'm writing the contents of the
IteratorStream
to theZlibOutputStream
. -
Now I need to assert that the contents of the
OutputStream
instance matchfixtures/foobar.txt.gz
. I know I can't read from that interface, but I'm not sure how to proceed. Maybe astream_socket_pair
like in theResourceStreamTest
?
I guess we could add an OutputBuffer
that implements Promise
and OutputStream
and resolves the promise once the stream has ended or fails it if there's an error.
Would you be interested in working on that?
Another solution is to use a stream pair, as you suggested.
Yes absolutely. In my mind this would complement the InMemoryStream
.
I don't have a really good grasp of the Amp framework, so I'm not sure I can make this test pass.
Here's what I've tried so far.
I will try to increase coverage on easier parts.
If you can point me to some direction I will give it another shot, otherwise I can leave that part.
So far I've achieved a 90% coverage!
https://gist.github.com/sebdesign/b2ea5b9dc1bedb3f9614fa8f44031ab8
@sebdesign The issue is your output buffer implementation, it needs to be something like this:
<?php
namespace Amp\ByteStream;
use Amp\ByteStream\ClosedException;
use Amp\Deferred;
use Amp\Promise;
use Amp\Success;
class OutputBuffer implements OutputStream, Promise {
private $deferred;
private $contents;
private $closed = false;
public function __construct() {
$this->deferred = new Deferred;
}
public function write(string $data): Promise {
if ($this->closed) {
throw new ClosedException("The stream has already been closed.");
}
$this->contents .= $data;
return new Success(\strlen($data));
}
public function end(string $finalData = ""): Promise {
if ($this->closed) {
throw new ClosedException("The stream has already been closed.");
}
$this->contents .= $finalData;
$this->closed = true;
$this->deferred->resolve($this->contents);
$this->contents = "";
return new Success(\strlen($finalData));
}
public function onResolve(callable $onResolve) {
$this->deferred->promise()->onResolve($onResolve);
}
}
It needs to collect the contents and resolve the promise (async placeholder) once the stream is complete.
Thanks for your feedback!
But I'm still getting the same failure when comparing the compressed/uncompressed files.
Sorry, didn't have a closer look. The issue is that the stream is written in single byte chunks, so there are other compression blocks generated as when generating the complete file in one chunk. I guess it's best to test the input stream and then test the output stream by writing the output and then reading the contents again and see whether it's the same content (uncompressed).
Oh now I get it. That means we won't do any assertions against the compressed file?
That's probably best. Another option is to compress the full file in one chunk with the same compression level as the pre-generated file.
I got it passing by writing a $fileStream = new ResourceInputStream(fopen($file1, 'r'));
to the OutputBuffer
through the ZlibOutputStream
.
Then I used an InMemoryStream
with the contents of the OutputBuffer
through the ZlibInputStream
to decompress the data and assert against the uncompressed file.
I changed the code in the end
method of the ZlibOutputStream
to call the end
method on the destination
.
Then in the test I'm calling yield $gzStream->end()
otherwise nothing works.
One thing I noticed is that the close()
method on the ZlipOutputStream
is not being called.
Indeed, the if ($error)
looks wrong in the onResolve
call.
We're at 94% now, think I can close this issue. 🎉