Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve test suite by adding PHPUnit to require-dev, support PHPUnit 7 - legacy PHPUnit 4 and test against legacy PHP 5.3 through PHP 7.3 #46

Merged
merged 4 commits into from
Sep 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
language: php

php:
- 5.3
# - 5.3 # requires old distro
- 5.4
- 5.5
- 5.6
- 7
- hhvm
- 7.0
- 7.1
- 7.2
- 7.3

sudo: false
# lock distro so new future defaults will not break the build
dist: trusty

matrix:
include:
- php: 5.3
dist: precise

install:
- composer install --no-interaction

script:
- phpunit --coverage-text
- vendor/bin/phpunit --coverage-text
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ execute arbitrary commands within isolated containers, stop running containers a
* [JSON streaming](#json-streaming)
* [JsonProgressException](#jsonprogressexception)
* [Install](#install)
* [Tests](#tests)
* [License](#license)

## Quickstart example
Expand Down Expand Up @@ -389,6 +390,25 @@ The recommended way to install this library is [through composer](http://getcomp
}
```

This project aims to run on any platform and thus does not require any PHP
extensions and supports running on legacy PHP 5.3 through current PHP 7+.
It's *highly recommended to use PHP 7+* for this project.

## Tests

To run the test suite, you first need to clone this repo and then install all
dependencies [through Composer](https://getcomposer.org):

```bash
$ composer install
```

To run the test suite, go to the project root and run:

```bash
$ php vendor/bin/phpunit
```

## License

MIT
8 changes: 6 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"autoload": {
"psr-4": { "Clue\\React\\Docker\\": "src/" }
},
"autoload-dev": {
"psr-4": { "Clue\\Tests\\React\\Docker\\": "tests/" }
},
"require": {
"php": ">=5.3",
"react/event-loop": "~0.3.0|~0.4.0",
Expand All @@ -23,8 +26,9 @@
"clue/promise-stream-react": "^0.1"
},
"require-dev": {
"clue/tar-react": "~0.1.0",
"clue/block-react": "~0.3.0",
"clue/caret-notation": "~0.2.0",
"clue/block-react": "~0.3.0"
"clue/tar-react": "~0.1.0",
"phpunit/phpunit": "^7.0 || ^6.0 || ^5.0 || ^4.8.35"
}
}
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>

<phpunit bootstrap="tests/bootstrap.php"
<phpunit bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
Expand Down
34 changes: 18 additions & 16 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace Clue\Tests\React\Docker;

use Clue\React\Docker\Client;
use React\Promise\Deferred;
use Clue\React\Buzz\Browser;
Expand All @@ -20,13 +22,13 @@ class ClientTest extends TestCase

public function setUp()
{
$this->loop = $this->getMock('React\EventLoop\LoopInterface');
$this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
$this->sender = $this->getMockBuilder('Clue\React\Buzz\Io\Sender')->disableOriginalConstructor()->getMock();
$this->browser = new Browser($this->loop, $this->sender);
$this->browser = $this->browser->withBase('http://x/');

$this->parser = $this->getMock('Clue\React\Docker\Io\ResponseParser');
$this->streamingParser = $this->getMock('Clue\React\Docker\Io\StreamingParser');
$this->parser = $this->getMockBuilder('Clue\React\Docker\Io\ResponseParser')->getMock();
$this->streamingParser = $this->getMockBuilder('Clue\React\Docker\Io\StreamingParser')->getMock();
$this->client = new Client($this->browser, $this->parser, $this->streamingParser);
}

Expand All @@ -41,7 +43,7 @@ public function testPing()
public function testEvents()
{
$json = array();
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('GET', '/events', $this->createResponseJsonStream($json));
$this->streamingParser->expects($this->once())->method('parseJsonStream')->will($this->returnValue($stream));
Expand All @@ -53,7 +55,7 @@ public function testEvents()
public function testEventsArgs()
{
$json = array();
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('GET', '/events?since=10&until=20&filters=%7B%22image%22%3A%5B%22busybox%22%2C%22ubuntu%22%5D%7D', $this->createResponseJsonStream($json));
$this->streamingParser->expects($this->once())->method('parseJsonStream')->will($this->returnValue($stream));
Expand Down Expand Up @@ -122,7 +124,7 @@ public function testContainerExport()

public function testContainerExportStream()
{
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('get', '/containers/123/export', $this->createResponse(''));
$this->streamingParser->expects($this->once())->method('parsePlainStream')->will($this->returnValue($stream));
Expand Down Expand Up @@ -248,7 +250,7 @@ public function testContainerCopy()

public function testContainerCopyStream()
{
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('post', '/containers/123/copy', $this->createResponse(''));
$this->streamingParser->expects($this->once())->method('parsePlainStream')->will($this->returnValue($stream));
Expand Down Expand Up @@ -276,7 +278,7 @@ public function testImageListAll()
public function testImageCreate()
{
$json = array();
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('post', '/images/create?fromImage=busybox', $this->createResponseJsonStream($json));
$this->streamingParser->expects($this->once())->method('parseJsonStream')->will($this->returnValue($stream));
Expand All @@ -287,7 +289,7 @@ public function testImageCreate()

public function testImageCreateStream()
{
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('post', '/images/create?fromImage=busybox', $this->createResponseJsonStream(array()));
$this->streamingParser->expects($this->once())->method('parseJsonStream')->will($this->returnValue($stream));
Expand All @@ -314,7 +316,7 @@ public function testImageHistory()
public function testImagePush()
{
$json = array();
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('post', '/images/123/push', $this->createResponseJsonStream($json));
$this->streamingParser->expects($this->once())->method('parseJsonStream')->will($this->returnValue($stream));
Expand All @@ -325,7 +327,7 @@ public function testImagePush()

public function testImagePushStream()
{
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('post', '/images/123/push', $this->createResponseJsonStream(array()));
$this->streamingParser->expects($this->once())->method('parseJsonStream')->will($this->returnValue($stream));
Expand All @@ -338,7 +340,7 @@ public function testImagePushCustomRegistry()
// TODO: verify headers
$auth = array();
$json = array();
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('post', '/images/demo.acme.com%3A5000/123/push?tag=test', $this->createResponseJsonStream($json));
$this->streamingParser->expects($this->once())->method('parseJsonStream')->will($this->returnValue($stream));
Expand Down Expand Up @@ -411,7 +413,7 @@ public function testExecStart()
{
$data = 'hello world';
$config = array();
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('POST', '/exec/123/start', $this->createResponse($data));
$this->streamingParser->expects($this->once())->method('parsePlainStream')->will($this->returnValue($stream));
Expand All @@ -424,7 +426,7 @@ public function testExecStart()
public function testExecStartStreamWithoutTtyWillDemultiplex()
{
$config = array();
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('POST', '/exec/123/start', $this->createResponse());
$this->streamingParser->expects($this->once())->method('parsePlainStream')->will($this->returnValue($stream));
Expand All @@ -436,7 +438,7 @@ public function testExecStartStreamWithoutTtyWillDemultiplex()
public function testExecStartStreamWithTtyWillNotDemultiplex()
{
$config = array('Tty' => true);
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('POST', '/exec/123/start', $this->createResponse());
$this->streamingParser->expects($this->once())->method('parsePlainStream')->will($this->returnValue($stream));
Expand All @@ -448,7 +450,7 @@ public function testExecStartStreamWithTtyWillNotDemultiplex()
public function testExecStartStreamWithCustomStderrEvent()
{
$config = array();
$stream = $this->getMock('React\Stream\ReadableStreamInterface');
$stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock();

$this->expectRequest('POST', '/exec/123/start', $this->createResponse());
$this->streamingParser->expects($this->once())->method('parsePlainStream')->will($this->returnValue($stream));
Expand Down
7 changes: 6 additions & 1 deletion tests/FactoryTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace Clue\Tests\React\Docker;

use Clue\React\Docker\Factory;
use React\EventLoop\Factory as LoopFactory;

Expand All @@ -16,9 +18,12 @@ public function setUp()
$this->factory = new Factory($this->loop, $this->browser);
}

/**
* @doesNotPerformAssertions
*/
public function testCtorDefaultBrowser()
{
$factory = new Factory($this->loop);
new Factory($this->loop);
}

public function testCreateClientUsesCustomUnixSender()
Expand Down
49 changes: 41 additions & 8 deletions tests/FunctionalClientTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace Clue\Tests\React\Docker;

use Clue\React\Docker\Client;
use React\EventLoop\Factory as LoopFactory;
use Clue\React\Docker\Factory;
Expand All @@ -22,7 +24,7 @@ public function setUp()

try {
Block\await($promise, $this->loop);
} catch (Exception $e) {
} catch (\Exception $e) {
$this->markTestSkipped('Unable to connect to docker ' . $e->getMessage());
}
}
Expand All @@ -34,6 +36,23 @@ public function testPing()
$this->loop->run();
}

/**
* @doesNotPerformAssertions
*/
public function testImageInspectCheckIfBusyboxExists()
{
$promise = $this->client->imageInspect('busybox:latest');

try {
Block\await($promise, $this->loop);
} catch (\RuntimeException $e) {
$this->markTestSkipped('Image "busybox" not downloaded yet');
}
}

/**
* @depends testImageInspectCheckIfBusyboxExists
*/
public function testCreateStartAndRemoveContainer()
{
$config = array(
Expand Down Expand Up @@ -73,6 +92,9 @@ public function testCreateStartAndRemoveContainer()
$this->assertEquals('destroy', $ret[3]['status']);
}

/**
* @depends testImageInspectCheckIfBusyboxExists
*/
public function testStartRunning()
{
$config = array(
Expand All @@ -87,8 +109,6 @@ public function testStartRunning()
$this->assertNotNull($container['Id']);
$this->assertNull($container['Warnings']);

$start = microtime(true);

$promise = $this->client->containerStart($container['Id']);
$ret = Block\await($promise, $this->loop);

Expand Down Expand Up @@ -177,7 +197,7 @@ public function testExecStringCommandWithOutputWhileRunning($container)
*/
public function testExecStreamOutputInMultipleChunksWhileRunning($container)
{
$promise = $this->client->execCreate($container, 'echo -n hello && sleep 0 && echo -n world');
$promise = $this->client->execCreate($container, 'echo -n hello && sleep 0.2 && echo -n world');
$exec = Block\await($promise, $this->loop);

$this->assertTrue(is_array($exec));
Expand Down Expand Up @@ -339,27 +359,40 @@ public function testImageSearch()
$this->assertGreaterThan(9, count($ret));
}

/**
* @depends testImageInspectCheckIfBusyboxExists
* @doesNotPerformAssertions
*/
public function testImageTag()
{
// create new tag "bb:now" on "busybox:latest"
$promise = $this->client->imageTag('busybox', 'bb', 'now');
$ret = Block\await($promise, $this->loop);
Block\await($promise, $this->loop);

// delete tag "bb:now" again
$promise = $this->client->imageRemove('bb:now');
$ret = Block\await($promise, $this->loop);
Block\await($promise, $this->loop);
}

public function testImageCreateStreamMissingWillEmitJsonError()
{
$promise = $this->client->version();
$version = Block\await($promise, $this->loop);

// old API reports a progress with error message, newer API just returns 404 right away
// https://docs.docker.com/engine/api/version-history/
$old = $version['ApiVersion'] < '1.22';

$stream = $this->client->imageCreateStream('clue/does-not-exist');

// one "progress" event, but no "data" events
$stream->on('progress', $this->expectCallableOnce());
$old && $stream->on('progress', $this->expectCallableOnce());
$old || $stream->on('progress', $this->expectCallableNever());
$stream->on('data', $this->expectCallableNever());

// will emit "error" with JsonProgressException and close
$stream->on('error', $this->expectCallableOnceParameter('Clue\React\Docker\Io\JsonProgressException'));
$old && $stream->on('error', $this->expectCallableOnceParameter('Clue\React\Docker\Io\JsonProgressException'));
$old || $stream->on('error', $this->expectCallableOnceParameter('Clue\React\Buzz\Message\ResponseException'));
$stream->on('close', $this->expectCallableOnce());

$this->loop->run();
Expand Down
Loading