Skip to content

Commit

Permalink
Merge pull request #46 from clue-labs/tests
Browse files Browse the repository at this point in the history
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
  • Loading branch information
clue authored Sep 5, 2019
2 parents f356761 + 9891a7e commit 41d92f6
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 68 deletions.
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

0 comments on commit 41d92f6

Please sign in to comment.