From 00ec4404992d73e154876fd2fe3a61db7aa3609f Mon Sep 17 00:00:00 2001 From: Walter Dal Mut Date: Sun, 21 Jun 2015 10:35:59 +0200 Subject: [PATCH 1/5] Cover more invalid mark procedures Expose multiple error conditions with invalid hostnames and missing servers in order to catch PHP errors and suppress those. --- tests/ClientTest.php | 56 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/ClientTest.php b/tests/ClientTest.php index f44a2b1a0..e6ca25fd9 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -436,4 +436,60 @@ class ClientTest extends \PHPUnit_Framework_TestCase return $object; } + + /** + * @group udp + */ + public function testWriteUDPPackagesToNoOne() + { + $rawOptions = $this->rawOptions; + $options = new Options(); + $options->setHost("127.0.0.1"); + $options->setUsername("nothing"); + $options->setPassword("nothing"); + $options->setPort(64071); //This is a wrong port + + $adapter = new UdpAdapter($options); + $object = new Client($adapter); + + $object->mark("udp.test", ["mark" => "element"]); + } + + /** + * @group udp + */ + public function testReplicateIssue27() + { + $options = new \InfluxDB\Options(); + + // Configure options + $options->setHost('172.16.1.182'); + $options->setPort(4444); + $options->setDatabase('...'); + $options->setUsername('root'); + $options->setPassword('root'); + + $udpAdapter = new \InfluxDB\Adapter\UdpAdapter($options); + $client = new \InfluxDB\Client($udpAdapter); + + $client->mark("udp.test", ["mark" => "element"]); + } + + /** + * @group udp + */ + public function testWriteUDPPackagesToInvalidHostname() + { + $rawOptions = $this->rawOptions; + $options = new Options(); + $options->setHost("www.test-invalid.this-is-not-a-tld"); + $options->setUsername("nothing"); + $options->setPassword("nothing"); + $options->setPort(15984); + + $adapter = new UdpAdapter($options); + $object = new Client($adapter); + + $object->mark("udp.test", ["mark" => "element"]); + } } From 662f4c978aea0eea844c7db96092bf12bcff2b4b Mon Sep 17 00:00:00 2001 From: Walter Dal Mut Date: Sun, 21 Jun 2015 10:56:16 +0200 Subject: [PATCH 2/5] Removed duplicated testcase on issue #27 --- tests/ClientTest.php | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/tests/ClientTest.php b/tests/ClientTest.php index e6ca25fd9..cd682e617 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -455,26 +455,6 @@ class ClientTest extends \PHPUnit_Framework_TestCase $object->mark("udp.test", ["mark" => "element"]); } - /** - * @group udp - */ - public function testReplicateIssue27() - { - $options = new \InfluxDB\Options(); - - // Configure options - $options->setHost('172.16.1.182'); - $options->setPort(4444); - $options->setDatabase('...'); - $options->setUsername('root'); - $options->setPassword('root'); - - $udpAdapter = new \InfluxDB\Adapter\UdpAdapter($options); - $client = new \InfluxDB\Client($udpAdapter); - - $client->mark("udp.test", ["mark" => "element"]); - } - /** * @group udp */ From 20a64e724bdd73a22ceb2f8b417229e36790811a Mon Sep 17 00:00:00 2001 From: Walter Dal Mut Date: Tue, 23 Jun 2015 07:18:41 +0200 Subject: [PATCH 3/5] Test suite completely rewritten Our test suite mixing integration and few unit tests, is difficult to understand and expand with new features. This commit rewrite completely the test suite in order to separate both: integration and unit tests in different suites in a more maintainable and useful way. --- composer.json | 3 +- composer.lock | 92 ++-- phpunit.xml.dist | 19 +- src/Adapter/UdpAdapter.php | 11 +- tests/ClientTest.php | 475 ------------------ tests/bootstrap.php | 18 - .../integration/Adapter/GuzzleAdapterTest.php | 72 +++ tests/integration/ClientTest.php | 166 ++++++ tests/integration/Framework/TestCase.php | 91 ++++ tests/unit/Adapter/GuzzleAdapterTest.php | 180 +++++++ tests/{ => unit}/Adapter/UdpAdapterTest.php | 78 +++ tests/{ => unit}/ClientFactoryTest.php | 0 tests/unit/ClientTest.php | 65 +++ 13 files changed, 710 insertions(+), 560 deletions(-) delete mode 100644 tests/ClientTest.php delete mode 100644 tests/bootstrap.php create mode 100644 tests/integration/Adapter/GuzzleAdapterTest.php create mode 100644 tests/integration/ClientTest.php create mode 100644 tests/integration/Framework/TestCase.php create mode 100644 tests/unit/Adapter/GuzzleAdapterTest.php rename tests/{ => unit}/Adapter/UdpAdapterTest.php (58%) rename tests/{ => unit}/ClientFactoryTest.php (100%) create mode 100644 tests/unit/ClientTest.php diff --git a/composer.json b/composer.json index 7c0fce5de..298b3aaf0 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,8 @@ }, "autoload-dev": { "psr-4": { - "InfluxDB\\": ["./tests/"] + "InfluxDB\\": ["./tests/unit"], + "InfluxDB\\Integration\\": ["./tests/integration"] } }, "suggest": { diff --git a/composer.lock b/composer.lock index 40b847c1f..882bc4fe7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "61a6988d1b757bb9d3a074d156d73f9d", + "hash": "4a2caee24e54a12ad907d21ddda10e87", "packages": [ { "name": "guzzlehttp/guzzle", @@ -429,16 +429,16 @@ }, { "name": "doctrine/instantiator", - "version": "1.0.4", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", - "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { @@ -449,7 +449,7 @@ "ext-pdo": "*", "ext-phar": "*", "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "2.0.*@ALPHA" + "squizlabs/php_codesniffer": "~2.0" }, "type": "library", "extra": { @@ -458,8 +458,8 @@ } }, "autoload": { - "psr-0": { - "Doctrine\\Instantiator\\": "src" + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -479,7 +479,7 @@ "constructor", "instantiate" ], - "time": "2014-10-13 12:58:55" + "time": "2015-06-14 21:17:01" }, { "name": "kevinlebrun/colors.php", @@ -685,16 +685,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "2.1.5", + "version": "2.1.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "be2286cb8c7e1773eded49d9719219e6f74f9e3e" + "reference": "631e365cf26bb2c078683e8d9bcf8bc631ac4d44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be2286cb8c7e1773eded49d9719219e6f74f9e3e", - "reference": "be2286cb8c7e1773eded49d9719219e6f74f9e3e", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/631e365cf26bb2c078683e8d9bcf8bc631ac4d44", + "reference": "631e365cf26bb2c078683e8d9bcf8bc631ac4d44", "shasum": "" }, "require": { @@ -743,7 +743,7 @@ "testing", "xunit" ], - "time": "2015-06-09 13:05:42" + "time": "2015-06-19 07:11:55" }, { "name": "phpunit/php-file-iterator", @@ -794,16 +794,16 @@ }, { "name": "phpunit/php-text-template", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { @@ -812,20 +812,17 @@ "type": "library", "autoload": { "classmap": [ - "Text/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -834,20 +831,20 @@ "keywords": [ "template" ], - "time": "2014-01-30 17:20:04" + "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", - "version": "1.0.5", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + "reference": "83fe1bdc5d47658b727595c14da140da92b3d66d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/83fe1bdc5d47658b727595c14da140da92b3d66d", + "reference": "83fe1bdc5d47658b727595c14da140da92b3d66d", "shasum": "" }, "require": { @@ -856,13 +853,10 @@ "type": "library", "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -878,20 +872,20 @@ "keywords": [ "timer" ], - "time": "2013-08-02 07:42:54" + "time": "2015-06-13 07:35:30" }, { "name": "phpunit/php-token-stream", - "version": "1.4.1", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "eab81d02569310739373308137284e0158424330" + "reference": "7a9b0969488c3c54fd62b4d504b3ec758fd005d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", - "reference": "eab81d02569310739373308137284e0158424330", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/7a9b0969488c3c54fd62b4d504b3ec758fd005d9", + "reference": "7a9b0969488c3c54fd62b4d504b3ec758fd005d9", "shasum": "" }, "require": { @@ -927,20 +921,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-04-08 04:46:07" + "time": "2015-06-19 03:43:16" }, { "name": "phpunit/phpunit", - "version": "4.7.3", + "version": "4.7.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "41fea1e84ed84d373f5ac099a1276c4358c90708" + "reference": "f6701ef3faea759acd1910a7751d8d102a7fd5bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/41fea1e84ed84d373f5ac099a1276c4358c90708", - "reference": "41fea1e84ed84d373f5ac099a1276c4358c90708", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f6701ef3faea759acd1910a7751d8d102a7fd5bc", + "reference": "f6701ef3faea759acd1910a7751d8d102a7fd5bc", "shasum": "" }, "require": { @@ -954,7 +948,7 @@ "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0", + "phpunit/php-timer": ">=1.0.6", "phpunit/phpunit-mock-objects": "~2.3", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", @@ -999,7 +993,7 @@ "testing", "xunit" ], - "time": "2015-06-11 16:20:25" + "time": "2015-06-21 07:23:36" }, { "name": "phpunit/phpunit-mock-objects", @@ -1440,16 +1434,16 @@ }, { "name": "sebastian/version", - "version": "1.0.5", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "shasum": "" }, "type": "library", @@ -1471,7 +1465,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-02-24 06:35:25" + "time": "2015-06-21 13:59:46" }, { "name": "symfony/yaml", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 64303a46a..36a9debbe 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -5,24 +5,15 @@ convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" - verbose="false"> + verbose="true"> - tests + tests/integration + + + tests/unit - - - - - - - - - - - - src diff --git a/src/Adapter/UdpAdapter.php b/src/Adapter/UdpAdapter.php index 2f9930087..b4c17a1e4 100644 --- a/src/Adapter/UdpAdapter.php +++ b/src/Adapter/UdpAdapter.php @@ -3,7 +3,7 @@ namespace InfluxDB\Adapter; use DateTime; -final class UdpAdapter extends AdapterAbstract +class UdpAdapter extends AdapterAbstract { public function send(array $message) { @@ -37,7 +37,7 @@ final class UdpAdapter extends AdapterAbstract $tags = array_replace_recursive($tags, $message["tags"]); } - $unixepoch = (int)(microtime(true) * 1e9); + $unixepoch = $this->generateTimeInNanoSeconds(); if (array_key_exists("time", $message)) { $dt = new DateTime($message["time"]); $unixepoch = (int)($dt->format("U") * 1e9); @@ -68,7 +68,12 @@ final class UdpAdapter extends AdapterAbstract return implode("\n", $lines); } - private function toKeyValue(array $elems, $escape=false) + protected function generateTimeInNanoSeconds() + { + return (int)(microtime(true) * 1e9); + } + + protected function toKeyValue(array $elems, $escape=false) { $list = []; foreach ($elems as $key => $value) { diff --git a/tests/ClientTest.php b/tests/ClientTest.php deleted file mode 100644 index cd682e617..000000000 --- a/tests/ClientTest.php +++ /dev/null @@ -1,475 +0,0 @@ -rawOptions = $options; - - $tcpOptions = $options["tcp"]; - - $options = new Options(); - $options->setHost($tcpOptions["host"]); - $options->setPort($tcpOptions["port"]); - $options->setUsername($tcpOptions["username"]); - $options->setPassword($tcpOptions["password"]); - $options->setDatabase($tcpOptions["database"]); - - $this->options = $options; - - $guzzleHttp = new GuzzleHttpClient(); - $adapter = new InfluxHttpAdapter($guzzleHttp, $options); - - $influx = new Client($adapter); - $this->object = $influx; - - $databases = $this->object->getDatabases(); - if (array_key_exists("values", $databases["results"][0]["series"][0])) { - foreach ($databases["results"][0]["series"][0]["values"] as $database) { - $this->object->deleteDatabase($database[0]); - } - } - - $this->object->createDatabase($this->rawOptions["udp"]["database"]); - $this->object->createDatabase($this->rawOptions["tcp"]["database"]); - } - - /** - * @group tcp - */ - public function testGuzzleHttpApiWorksCorrectly() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - - sleep(1); - - $body = $this->object->query("select * from \"tcp.test\""); - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("mark", $body["results"][0]["series"][0]["columns"][1]); - $this->assertEquals("element", $body["results"][0]["series"][0]["values"][0][1]); - } - - /** - * @group tcp - * @group proxy - */ - public function testGuzzleHttpApiWorksCorrectlyWithProxies() - { - $this->options->setHost("localhost"); - $this->options->setPort(9000); - $this->options->setPrefix("/influxdb"); - $this->object->mark("tcp.test", ["mark" => "element"]); - - sleep(2); - - $body = $this->object->query("select * from \"tcp.test\""); - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("mark", $body["results"][0]["series"][0]["columns"][1]); - $this->assertEquals("element", $body["results"][0]["series"][0]["values"][0][1]); - } - - /** - * @group tcp - */ - public function testGuzzleHttpQueryApiWorksCorrectly() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - - sleep(1); - - $body = $this->object->query("select * from \"tcp.test\""); - - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("mark", $body["results"][0]["series"][0]["columns"][1]); - $this->assertEquals("element", $body["results"][0]["series"][0]["values"][0][1]); - } - - /** - * @group tcp - */ - public function testGuzzleHttpQueryApiWithMultipleData() - { - $this->object->mark("tcp.test", ["mark" => "element"]); - $this->object->mark("tcp.test", ["mark" => "element2"]); - $this->object->mark("tcp.test", ["mark" => "element3"]); - - sleep(1); - - $body = $this->object->query("select mark from \"tcp.test\"", "s"); - - $this->assertCount(3, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("mark", $body["results"][0]["series"][0]["columns"][1]); - $this->assertEquals("element", $body["results"][0]["series"][0]["values"][0][1]); - } - - /** - * @group tcp - */ - public function testWriteDirectMessages() - { - $this->object->mark([ - "tags" => [ - "dc" => "eu-west-1", - ], - "points" => [ - [ - "measurement" => "vm-serie", - "fields" => [ - "cpu" => 18.12, - "free" => 712423, - ], - ], - ] - ]); - - sleep(1); - - $body = $this->object->query("select * from \"vm-serie\""); - - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("cpu", $body["results"][0]["series"][0]["columns"][1]); - $this->assertEquals(18.12, $body["results"][0]["series"][0]["values"][0][1]); - } - - /** - * @group tcp - */ - public function testOverrideDatabaseNameViaMessage() - { - $this->options->setDatabase("a-wrong-database"); - - $this->object->mark([ - "database" => "tcp.test", - "points" => [ - [ - "measurement" => "vm-serie", - "fields" => [ - "cpu" => 18.12, - "free" => 712423, - ], - ], - ] - ]); - - sleep(1); - - $this->options->setDatabase("tcp.test"); - $body = $this->object->query("select * from \"vm-serie\""); - - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("cpu", $body["results"][0]["series"][0]["columns"][1]); - $this->assertEquals(18.12, $body["results"][0]["series"][0]["values"][0][1]); - $this->assertEquals(712423, $body["results"][0]["series"][0]["values"][0][2]); - } - - /** - * @group udp - */ - public function testUdpIpWriteData() - { - $object = $this->createClientWithUdpAdapter(); - - $object->mark("udp.test", ["mark" => "element"]); - $object->mark("udp.test", ["mark" => "element1"]); - $object->mark("udp.test", ["mark" => "element2"]); - $object->mark("udp.test", ["mark" => "element3"]); - - // Wait UDP/IP message arrives - sleep(2); - - $this->options->setDatabase("udp.test"); - $body = $this->object->query("select * from \"udp.test\""); - - $this->assertCount(4, $body["results"][0]["series"][0]["values"]); - } - - /** - * @group udp - */ - public function testSendMultipleMeasurementWithUdpIp() - { - $object = $this->createClientWithUdpAdapter(); - - $object->mark([ - "points" => [ - [ - "measurement" => "mem", - "fields" => [ - "free" => 712423, - ], - ], - [ - "measurement" => "cpu", - "fields" => [ - "cpu" => 18.12, - ], - ], - ] - ]); - - sleep(2); - - $this->options->setDatabase("udp.test"); - $body = $this->object->query("select * from \"cpu\""); - - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("cpu", $body["results"][0]["series"][0]["columns"][1]); - $this->assertEquals(18.12, $body["results"][0]["series"][0]["values"][0][1]); - - $body = $this->object->query("select * from \"mem\""); - - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("free", $body["results"][0]["series"][0]["columns"][1]); - $this->assertEquals(712423, $body["results"][0]["series"][0]["values"][0][1]); - } - - /** - * @group udp - */ - public function testWriteDirectMessageWithUdpIp() - { - $object = $this->createClientWithUdpAdapter(); - - $object->mark([ - "points" => [ - [ - "measurement" => "vm-serie", - "fields" => [ - "cpu" => 18.12, - "free" => 712423, - ], - ], - ] - ]); - - sleep(2); - - $this->options->setDatabase("udp.test"); - $body = $this->object->query("select * from \"vm-serie\""); - - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("cpu", $body["results"][0]["series"][0]["columns"][1]); - $this->assertEquals(18.12, $body["results"][0]["series"][0]["values"][0][1]); - $this->assertEquals(712423, $body["results"][0]["series"][0]["values"][0][2]); - } - - /** - * @group udp - * @group date - */ - public function testWriteDirectMessageWillPreserveActualTime() - { - $object = $this->createClientWithUdpAdapter(); - - $object->mark([ - "points" => [ - [ - "measurement" => "vm-serie", - "fields" => [ - "cpu" => 18.12, - "free" => 712423, - ], - ], - ] - ]); - - sleep(2); - - $this->options->setDatabase("udp.test"); - $body = $this->object->query("select * from \"vm-serie\""); - - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("time", $body["results"][0]["series"][0]["columns"][0]); - $saved = $body["results"][0]["series"][0]["values"][0][0]; - $this->assertRegExp("/".date("Y-m-d")."/i", $saved); - } - - /** - * @group udp - * @group date - */ - public function testWriteDirectMessageWillPreserveDatetime() - { - $object = $this->createClientWithUdpAdapter(); - - $object->mark([ - "time" => "2009-11-10T23:00:00Z", - "points" => [ - [ - "measurement" => "vm-serie", - "fields" => [ - "cpu" => 18.12, - "free" => 712423, - ], - ], - ] - ]); - - sleep(2); - - $this->options->setDatabase("udp.test"); - $body = $this->object->query("select * from \"vm-serie\""); - - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("time", $body["results"][0]["series"][0]["columns"][0]); - $this->assertEquals("2009-11-10T23:00:00Z", $body["results"][0]["series"][0]["values"][0][0]); - } - - /** - * @group udp - * @group tags - */ - public function testTagsAreWrittenCorrectly() - { - $object = $this->createClientWithUdpAdapter(); - - $object->mark([ - "tags" => [ - "region" => "eu", - ], - "points" => [ - [ - "measurement" => "vm-serie", - "tags" => [ - "dc" => "eu-west-1", - "one" => "two", - ], - "fields" => [ - "cpu" => 18.12, - "free" => 712423, - ], - ], - [ - "measurement" => "vm-serie", - "tags" => [ - "dc" => "us-east-1", - ], - "fields" => [ - "cpu" => 28.12, - "free" => 412923, - ], - ], - ] - ]); - - sleep(2); - - $this->options->setDatabase("udp.test"); - $body = $this->object->query("select * from \"vm-serie\" where dc='eu-west-1'"); - - $this->assertCount(1, $body["results"][0]["series"][0]["values"]); - $this->assertEquals("cpu", $body["results"][0]["series"][0]["columns"][1]); - $this->assertEquals(18.12, $body["results"][0]["series"][0]["values"][0][1]); - $this->assertEquals(712423, $body["results"][0]["series"][0]["values"][0][2]); - } - - /** - * Test that we handle socket problems correctly in the UDP - * adapter, and that they don't inturrupt the user's application. - * - * @group udp - */ - public function testReplicateIssue27() - { - $options = new \InfluxDB\Options(); - - // Configure options - $options->setHost('172.16.1.182'); - $options->setPort(4444); - $options->setDatabase('...'); - $options->setUsername('root'); - $options->setPassword('root'); - - $httpAdapter = new \InfluxDB\Adapter\UdpAdapter($options); - - $client = new \InfluxDB\Client($httpAdapter); - $client->mark("udp.test", ["mark" => "element"]); - } - - public function testListActiveDatabses() - { - $databases = $this->object->getDatabases(); - - $this->assertCount(2, $databases["results"][0]["series"][0]["values"]); - } - - public function testCreateANewDatabase() - { - $this->object->createDatabase("walter"); - - sleep(1); - - $databases = $this->object->getDatabases(); - - $this->assertCount(3, $databases["results"][0]["series"][0]["values"]); - - $this->object->deleteDatabase("walter"); - } - - private function createClientWithUdpAdapter() - { - $rawOptions = $this->rawOptions; - $options = new Options(); - $options->setHost($rawOptions["udp"]["host"]); - $options->setUsername($rawOptions["udp"]["username"]); - $options->setPassword($rawOptions["udp"]["password"]); - $options->setPort($rawOptions["udp"]["port"]); - $options->setDatabase($rawOptions["udp"]["database"]); - - $adapter = new UdpAdapter($options); - $object = new Client($adapter); - - return $object; - } - - /** - * @group udp - */ - public function testWriteUDPPackagesToNoOne() - { - $rawOptions = $this->rawOptions; - $options = new Options(); - $options->setHost("127.0.0.1"); - $options->setUsername("nothing"); - $options->setPassword("nothing"); - $options->setPort(64071); //This is a wrong port - - $adapter = new UdpAdapter($options); - $object = new Client($adapter); - - $object->mark("udp.test", ["mark" => "element"]); - } - - /** - * @group udp - */ - public function testWriteUDPPackagesToInvalidHostname() - { - $rawOptions = $this->rawOptions; - $options = new Options(); - $options->setHost("www.test-invalid.this-is-not-a-tld"); - $options->setUsername("nothing"); - $options->setPassword("nothing"); - $options->setPort(15984); - - $adapter = new UdpAdapter($options); - $object = new Client($adapter); - - $object->mark("udp.test", ["mark" => "element"]); - } -} diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index 4f2e9ae33..000000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,18 +0,0 @@ - [ - "host" => getenv('HOST'), - "port" => getenv('TCP_PORT'), - "protocol" => getenv('TCP_PROTOCOL'), - "database" => getenv('TCP_DB'), - "username" => getenv('USERNAME'), - "password" => getenv('PASSWORD'), - ], - "udp" => [ - "host" => getenv('HOST'), - "port" => getenv('UDP_PORT'), - "database" => getenv('UDP_DB'), - "username" => getenv('USERNAME'), - "password" => getenv('PASSWORD'), - ], -]; diff --git a/tests/integration/Adapter/GuzzleAdapterTest.php b/tests/integration/Adapter/GuzzleAdapterTest.php new file mode 100644 index 000000000..eed5132c1 --- /dev/null +++ b/tests/integration/Adapter/GuzzleAdapterTest.php @@ -0,0 +1,72 @@ +getClient()->createDatabase("tcp.test"); + + $options = new Options(); + $options->setPort(8086); + $options->setDatabase("tcp.test"); + + $http = new GuzzleHttpClient(); + $adapter = new GuzzleAdapter($http, $options); + + $adapter->send([ + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ]); + + $this->assertSerieExists("tcp.test", "vm-serie"); + $this->assertSerieCount("tcp.test", "vm-serie", 1); + $this->assertValueExistsInSerie("tcp.test", "vm-serie", "cpu", 18.12); + $this->assertValueExistsInSerie("tcp.test", "vm-serie", "free", 712423); + } + + public function testWorksWithProxies() + { + $this->getClient()->createDatabase("proxy.test"); + + $options = new Options(); + $options->setPort(9000); + $options->setDatabase("proxy.test"); + $options->setPrefix("/influxdb"); + + $http = new GuzzleHttpClient(); + $adapter = new GuzzleAdapter($http, $options); + + $adapter->send([ + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ]); + + $this->assertSerieExists("proxy.test", "vm-serie"); + $this->assertSerieCount("proxy.test", "vm-serie", 1); + $this->assertValueExistsInSerie("proxy.test", "vm-serie", "cpu", 18.12); + $this->assertValueExistsInSerie("proxy.test", "vm-serie", "free", 712423); + } +} diff --git a/tests/integration/ClientTest.php b/tests/integration/ClientTest.php new file mode 100644 index 000000000..1b56232e6 --- /dev/null +++ b/tests/integration/ClientTest.php @@ -0,0 +1,166 @@ +getClient()->createDatabase("tcp.test"); + $this->getClient()->createDatabase("udp.test"); + } + + public function testSimpleMarkPublicSignature() + { + $options = new Options(); + $options->setDatabase("tcp.test"); + + $guzzleHttp = new GuzzleHttpClient(); + $adapter = new InfluxHttpAdapter($guzzleHttp, $options); + $client = new Client($adapter); + + $client->mark("vm", ["mark" => "element"]); + + $this->assertSerieExists("tcp.test", "vm"); + $this->assertSerieCount("tcp.test", "vm", 1); + $this->assertValueExistsInSerie("tcp.test", "vm", "mark", "element"); + } + + public function testDirectMessagesMarkPublicSignature() + { + $options = new Options(); + $options->setDatabase("tcp.test"); + + $guzzleHttp = new GuzzleHttpClient(); + $adapter = new InfluxHttpAdapter($guzzleHttp, $options); + $client = new Client($adapter); + + $client->mark([ + "database" => "tcp.test", + "retentionPolicy" => "default", + "points" => [ + [ + "measurement" => "tt", + "fields" => [ + "cpu" => 1, + "mem" => 2, + ], + ] + ], + ]); + + $this->assertSerieExists("tcp.test", "tt"); + $this->assertSerieCount("tcp.test", "tt", 1); + $this->assertValueExistsInSerie("tcp.test", "tt", "cpu", 1); + $this->assertValueExistsInSerie("tcp.test", "tt", "mem", 2); + } + + public function testListActiveDatabases() + { + $options = new Options(); + $guzzleHttp = new GuzzleHttpClient(); + $adapter = new InfluxHttpAdapter($guzzleHttp, $options); + $client = new Client($adapter); + + $databases = $client->getDatabases(); + + $this->assertCount(2, $databases["results"][0]["series"][0]["values"]); + } + + public function testCreateANewDatabase() + { + $options = new Options(); + $guzzleHttp = new GuzzleHttpClient(); + $adapter = new InfluxHttpAdapter($guzzleHttp, $options); + + $client = new Client($adapter); + + $client->createDatabase("walter"); + + $databases = $client->getDatabases(); + + $this->assertCount(3, $databases["results"][0]["series"][0]["values"]); + } + + public function testDropExistingDatabase() + { + $options = new Options(); + $guzzleHttp = new GuzzleHttpClient(); + $adapter = new InfluxHttpAdapter($guzzleHttp, $options); + + $client = new Client($adapter); + + $client->createDatabase("walter"); + $this->assertDatabasesCount(3); + + $client->deleteDatabase("walter"); + $this->assertDatabasesCount(2); + } + + /** + * Test that we handle socket problems correctly in the UDP + * adapter, and that they don't inturrupt the user's application. + * + * @group udp + */ + public function testReplicateIssue27() + { + $options = new \InfluxDB\Options(); + + // Configure options + $options->setHost('172.16.1.182'); + $options->setPort(4444); + $options->setDatabase('...'); + $options->setUsername('root'); + $options->setPassword('root'); + + $httpAdapter = new \InfluxDB\Adapter\UdpAdapter($options); + + $client = new \InfluxDB\Client($httpAdapter); + $client->mark("udp.test", ["mark" => "element"]); + } + + /** + * @group udp + */ + public function testWriteUDPPackagesToNoOne() + { + $options = new Options(); + $options->setHost("127.0.0.1"); + $options->setUsername("nothing"); + $options->setPassword("nothing"); + $options->setPort(64071); //This is a wrong port + + $adapter = new UdpAdapter($options); + $object = new Client($adapter); + + $object->mark("udp.test", ["mark" => "element"]); + } + + /** + * @group udp + */ + public function testWriteUDPPackagesToInvalidHostname() + { + $options = new Options(); + $options->setHost("www.test-invalid.this-is-not-a-tld"); + $options->setUsername("nothing"); + $options->setPassword("nothing"); + $options->setPort(15984); + + $adapter = new UdpAdapter($options); + $object = new Client($adapter); + + $object->mark("udp.test", ["mark" => "element"]); + } +} diff --git a/tests/integration/Framework/TestCase.php b/tests/integration/Framework/TestCase.php new file mode 100644 index 000000000..6f6d15107 --- /dev/null +++ b/tests/integration/Framework/TestCase.php @@ -0,0 +1,91 @@ +options = new Options(); + $guzzleHttp = new GuzzleHttpClient(); + $adapter = new InfluxHttpAdapter($guzzleHttp, $options); + + $client = $this->client = new Client($adapter); + + $this->dropAll(); + } + + public function tearDown() + { + $this->dropAll(); + } + + private function dropAll() + { + $databases = $this->getClient()->getDatabases(); + if (array_key_exists("values", $databases["results"][0]["series"][0])) { + foreach ($databases["results"][0]["series"][0]["values"] as $database) { + $this->getClient()->deleteDatabase($database[0]); + } + } + } + + public function assertValueExistsInSerie($database, $serieName, $column, $value) + { + $this->getOptions()->setDatabase($database); + $body = $this->getClient()->query("select {$column} from \"{$serieName}\""); + + foreach ($body["results"][0]["series"][0]["values"] as $result) { + if ($result[1] == $value) { + return $this->assertTrue(true); + } + } + + return $this->fail("Missing value '{$value}'"); + } + + public function assertSerieCount($database, $serieName, $count) + { + $this->getOptions()->setDatabase($database); + $body = $this->getClient()->query("select * from \"{$serieName}\""); + + $this->assertCount(1, $body["results"][0]["series"][0]["values"]); + } + + public function assertSerieExists($database, $serieName) + { + $this->getOptions()->setDatabase($database); + $body = $this->getClient()->query("show measurements"); + + foreach ($body["results"][0]["series"][0]["values"] as $result) { + if ($result[0] == $serieName) { + return $this->assertTrue(true); + } + } + + return $this->fail("Missing serie with name '{$serieName}' in database '{$database}'"); + } + + public function assertDatabasesCount($count) + { + $databases = $this->client->getDatabases(); + $this->assertCount($count, $databases["results"][0]["series"][0]["values"]); + } + + public function getOptions() + { + return $this->options; + } + + public function getClient() + { + return $this->client; + } +} diff --git a/tests/unit/Adapter/GuzzleAdapterTest.php b/tests/unit/Adapter/GuzzleAdapterTest.php new file mode 100644 index 000000000..3cc77da21 --- /dev/null +++ b/tests/unit/Adapter/GuzzleAdapterTest.php @@ -0,0 +1,180 @@ +getMethod("getHttpSeriesEndpoint"); + $method->setAccessible(true); + + $endpoint = $method->invokeArgs($adapter, []); + $this->assertEquals($final, $endpoint); + } + + public function getWriteEndpoints() + { + return [ + ["http://localhost:9000/write", (new Options())->setHost("localhost")->setPort(9000)], + ["https://localhost:9000/write", (new Options())->setHost("localhost")->setPort(9000)->setProtocol("https")], + ["http://localhost:9000/influxdb/write", (new Options())->setHost("localhost")->setPort(9000)->setPrefix("/influxdb")], + ]; + } + + /** + * @group tcp + * @group proxy + * @dataProvider getQueryEndpoints + */ + public function testQueryEndpointGeneration($final, $options) + { + $guzzleHttp = new GuzzleHttpClient(); + $adapter = new InfluxHttpAdapter($guzzleHttp, $options); + + $reflection = new \ReflectionClass(get_class($adapter)); + $method = $reflection->getMethod("getHttpQueryEndpoint"); + $method->setAccessible(true); + + $endpoint = $method->invokeArgs($adapter, []); + $this->assertEquals($final, $endpoint); + } + + public function getQueryEndpoints() + { + return [ + ["http://localhost:9000/query", (new Options())->setHost("localhost")->setPort(9000)], + ["https://localhost:9000/query", (new Options())->setHost("localhost")->setPort(9000)->setProtocol("https")], + ["http://localhost:9000/influxdb/query", (new Options())->setHost("localhost")->setPort(9000)->setPrefix("/influxdb")], + ]; + } + + public function testMergeWithDefaultOptions() + { + $options = new Options(); + $options->setDatabase("db"); + $httpClient = $this->prophesize("GuzzleHttp\\Client"); + $httpClient->post(Argument::Any(), [ + "auth" => ["root", "root"], + "body" => '{"database":"db","retentionPolicy":"default"}', + ])->shouldBeCalledTimes(1); + + $adapter = new InfluxHttpAdapter($httpClient->reveal(), $options); + $adapter->send([]); + } + + public function testAdapterPrepareJsonDataCorrectly() + { + $guzzleHttp = $this->prophesize("GuzzleHttp\Client"); + $guzzleHttp->post("http://localhost:8086/write", [ + "auth" => ["root", "root"], + "body" => '{"database":"db","retentionPolicy":"default","points":[{"measurement":"tcp.test","fields":{"mark":"element"}}]}', + ])->shouldBeCalledTimes(1); + $options = (new Options())->setDatabase("db"); + $adapter = new InfluxHttpAdapter($guzzleHttp->reveal(), $options); + + $adapter->send([ + "points" => [ + [ + "measurement" => "tcp.test", + "fields" => [ + "mark" => "element" + ] + ] + ] + ]); + } + + public function testDefaultOptionOverwrite() + { + $options = new Options(); + $options->setDatabase("db"); + $httpClient = $this->prophesize("GuzzleHttp\\Client"); + $httpClient->post(Argument::Any(), [ + "auth" => ["root", "root"], + "body" => '{"database":"mydb","retentionPolicy":"myPolicy"}', + ])->shouldBeCalledTimes(1); + + $adapter = new InfluxHttpAdapter($httpClient->reveal(), $options); + $adapter->send([ + "database" => "mydb", + "retentionPolicy" => "myPolicy" + ]); + } + + public function testEmptyTagsFieldIsRemoved() + { + $options = new Options(); + $options->setDatabase("db"); + $httpClient = $this->prophesize("GuzzleHttp\\Client"); + $httpClient->post(Argument::Any(), [ + "auth" => ["root", "root"], + "body" => '{"database":"mydb","retentionPolicy":"myPolicy"}', + ])->shouldBeCalledTimes(1); + + $adapter = new InfluxHttpAdapter($httpClient->reveal(), $options); + $adapter->send([ + "database" => "mydb", + "retentionPolicy" => "myPolicy", + "tags" => [], + ]); + } + + public function testGlobalTagsAreInPlace() + { + $options = new Options(); + $options->setDatabase("db"); + $options->setTags([ + "dc" => "us-west", + ]); + $httpClient = $this->prophesize("GuzzleHttp\\Client"); + $httpClient->post(Argument::Any(), [ + "auth" => ["root", "root"], + "body" => '{"database":"mydb","retentionPolicy":"myPolicy","tags":{"dc":"us-west"}}', + ])->shouldBeCalledTimes(1); + + $adapter = new InfluxHttpAdapter($httpClient->reveal(), $options); + $adapter->send([ + "database" => "mydb", + "retentionPolicy" => "myPolicy", + ]); + } + + public function testTagsFieldIsMergedWithGlobalTags() + { + $options = new Options(); + $options->setDatabase("db"); + $options->setTags([ + "dc" => "us-west", + ]); + $httpClient = $this->prophesize("GuzzleHttp\\Client"); + $httpClient->post(Argument::Any(), [ + "auth" => ["root", "root"], + "body" => '{"database":"mydb","retentionPolicy":"myPolicy","tags":{"dc":"us-west","region":"us"}}', + ])->shouldBeCalledTimes(1); + + $adapter = new InfluxHttpAdapter($httpClient->reveal(), $options); + $adapter->send([ + "database" => "mydb", + "retentionPolicy" => "myPolicy", + "tags" => ["region" => "us"], + ]); + } +} diff --git a/tests/Adapter/UdpAdapterTest.php b/tests/unit/Adapter/UdpAdapterTest.php similarity index 58% rename from tests/Adapter/UdpAdapterTest.php rename to tests/unit/Adapter/UdpAdapterTest.php index fa5908086..7ff6b42f2 100644 --- a/tests/Adapter/UdpAdapterTest.php +++ b/tests/unit/Adapter/UdpAdapterTest.php @@ -1,7 +1,13 @@ setDatabase("test"); + $adapter = $this->getMockBuilder("InfluxDB\\Adapter\\UdpAdapter") + ->setConstructorArgs([$options]) + ->setMethods(["write", "generateTimeInNanoSeconds"]) + ->getMock(); + + $adapter->expects($this->any()) + ->method("generateTimeInNanoSeconds") + ->will($this->returnValue(1245)); + + $adapter->expects($this->once()) + ->method("write") + ->with("udp.test mark=\"element\" 1245"); + + $adapter->send([ + "points" => [ + [ + "measurement" => "udp.test", + "fields" => [ + "mark" => "element" + ] + ] + ] + ]); + } + + /** + * @group udp + */ + public function testSendMultipleMeasurementWithUdpIp() + { + $options = (new Options())->setDatabase("test"); + $adapter = $this->getMockBuilder("InfluxDB\\Adapter\\UdpAdapter") + ->setConstructorArgs([$options]) + ->setMethods(["write", "generateTimeInNanoSeconds"]) + ->getMock(); + + $adapter->expects($this->any()) + ->method("generateTimeInNanoSeconds") + ->will($this->onConsecutiveCalls(1245, 1246)); + + $adapter->expects($this->once()) + ->method("write") + ->with(<<send([ + "points" => [ + [ + "measurement" => "mem", + "fields" => [ + "free" => 712423, + ], + ], + [ + "measurement" => "cpu", + "fields" => [ + "cpu" => 18.12, + ], + ], + ] + ]); + } } diff --git a/tests/ClientFactoryTest.php b/tests/unit/ClientFactoryTest.php similarity index 100% rename from tests/ClientFactoryTest.php rename to tests/unit/ClientFactoryTest.php diff --git a/tests/unit/ClientTest.php b/tests/unit/ClientTest.php new file mode 100644 index 000000000..4cc843af1 --- /dev/null +++ b/tests/unit/ClientTest.php @@ -0,0 +1,65 @@ +prophesize("InfluxDB\\Adapter\\WritableInterface"); + $mock->send([ + "points" => [ + [ + "measurement" => "tcp.test", + "fields" => [ + "mark" => "element" + ] + ] + ] + ])->shouldBeCalledTimes(1); + + $object = new Client($mock->reveal()); + $object->mark("tcp.test", ["mark" => "element"]); + } + + public function testWriteDirectMessages() + { + $mock = $this->prophesize("InfluxDB\\Adapter\\WritableInterface"); + $mock->send([ + "tags" => [ + "dc" => "eu-west-1", + ], + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ] + ] + ] + ])->shouldBeCalledTimes(1); + $object = new Client($mock->reveal()); + + $object->mark([ + "tags" => [ + "dc" => "eu-west-1", + ], + "points" => [ + [ + "measurement" => "vm-serie", + "fields" => [ + "cpu" => 18.12, + "free" => 712423, + ], + ], + ] + ]); + } +} From 03ade4c6005dbc7348af422bae9dc1b57ac8ad89 Mon Sep 17 00:00:00 2001 From: Walter Dal Mut Date: Tue, 23 Jun 2015 19:28:14 +0200 Subject: [PATCH 4/5] Added UDP/IP integration tests --- tests/integration/Adapter/UdpAdapterTest.php | 53 ++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/integration/Adapter/UdpAdapterTest.php diff --git a/tests/integration/Adapter/UdpAdapterTest.php b/tests/integration/Adapter/UdpAdapterTest.php new file mode 100644 index 000000000..f04c629ad --- /dev/null +++ b/tests/integration/Adapter/UdpAdapterTest.php @@ -0,0 +1,53 @@ +setPort(4444); + $adapter = new UdpAdapter($options); + + $this->getClient()->createDatabase("udp.test"); + + $adapter->write("cpu value=12.33 " . (int)(microtime(true)*1e9)); + + sleep(2); + + $this->assertSerieExists("udp.test", "cpu"); + $this->assertSerieCount("udp.test", "cpu", 1); + $this->assertValueExistsInSerie("udp.test", "cpu", "value", 12.33); + } + + public function testWriteSimplePointsUsingSendMethod() + { + $options = (new Options()) + ->setPort(4444); + $adapter = new UdpAdapter($options); + + $this->getClient()->createDatabase("udp.test"); + + $adapter->send([ + "retentionPolicy" => "default", + "points" => [ + [ + "measurement" => "mem", + "fields" => [ + "value" => 1233, + ], + ], + ], + ]); + + sleep(2); + + $this->assertSerieExists("udp.test", "mem"); + $this->assertSerieCount("udp.test", "mem", 1); + $this->assertValueExistsInSerie("udp.test", "mem", "value", 1233); + } +} From d9dbd9ba931dd2e207e163ae2f8c41eeabc65413 Mon Sep 17 00:00:00 2001 From: Walter Dal Mut Date: Tue, 23 Jun 2015 19:35:04 +0200 Subject: [PATCH 5/5] Change contributing guidelines --- CONTRIBUTING.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7af948a1a..778ffc64c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,4 @@ We are always thrilled to receive pull requests. We do our best to process them quickly. If your pull request is not accepted on the first try, don't get discouraged! -We follows the *vincent driessen's branching model* -[http://nvie.com/posts/a-successful-git-branching-model/](http://nvie.com/posts/a-successful-git-branching-model/) - +Just branch on master and prepare your PR.