Skip to content

Commit

Permalink
Let exceptions to bubble (#4)
Browse files Browse the repository at this point in the history
* Let exceptions to bubble

* Test JsonEncodeException

* Modify JsonEncodeException construction

* Rename test methods

* Assert exception data

* Fix variable juggling
  • Loading branch information
nerg4l authored May 23, 2020
1 parent 8b535cb commit a225707
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 42 deletions.
64 changes: 33 additions & 31 deletions src/BroadcasttClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,26 @@
use Broadcastt\Exception\InvalidArgumentException;
use Broadcastt\Exception\InvalidChannelNameException;
use Broadcastt\Exception\InvalidDataException;
use Broadcastt\Exception\InvalidHostException;
use Broadcastt\Exception\InvalidSocketIdException;
use Broadcastt\Exception\JsonEncodeException;
use Broadcastt\Exception\TooManyChannelsException;
use Broadcastt\Exception\InvalidHostException;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use function GuzzleHttp\Psr7\stream_for;
use GuzzleHttp\Psr7\Uri;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\LogLevel;
use function GuzzleHttp\Psr7\stream_for;

/**
* Class BroadcasttClient
*
* @package Broadcastt
*
* @property-read int $appId Id of your application
Expand Down Expand Up @@ -74,7 +76,6 @@ class BroadcasttClient implements LoggerAwareInterface
'timeout' => null,
];


/**
* Initializes a new Broadcastt instance with key, secret and ID of an app.
*
Expand All @@ -101,6 +102,7 @@ public function __construct($appId, $appKey, $appSecret, $appCluster = 'eu')
* Clients can be instantiated from a URI. For example: "http://key:[email protected]/apps/{appId}"
*
* @param string|UriInterface $uri
*
* @return BroadcasttClient
*/
public static function fromUri($uri)
Expand All @@ -126,7 +128,7 @@ public static function fromUri($uri)
throw new InvalidArgumentException('Secret part of user info is missing from URI');
}

list($appKey, $appSecret) = $userInfo;
[$appKey, $appSecret] = $userInfo;

$client = new BroadcasttClient($appId, $appKey, $appSecret);
$client->scheme = $uri->getScheme();
Expand Down Expand Up @@ -233,7 +235,7 @@ private function buildRequest($domain, $path, $requestMethod = 'GET', $queryPara
*
* @param RequestInterface $request
*
* @return Response
* @return ResponseInterface
* @throws GuzzleException
*/
private function sendRequest($request)
Expand Down Expand Up @@ -275,6 +277,7 @@ private function buildUri()
* Check if the status code indicates the request was successful.
*
* @param $status
*
* @return bool
*/
private function isSuccessStatusCode($status)
Expand Down Expand Up @@ -345,7 +348,8 @@ public static function httpBuildQuery($array)
* @param bool $jsonEncoded [optional]
*
* @return bool
* invalid
* @throws GuzzleException
* @throws JsonEncodeException on JSON encode failure.
*/
public function trigger($channels, $name, $data, $socketId = null, $jsonEncoded = false)
{
Expand All @@ -356,33 +360,28 @@ public function trigger($channels, $name, $data, $socketId = null, $jsonEncoded
$this->validateChannels($channels);
$this->validateSocketId($socketId);

$jsonData = $data;
if (!$jsonEncoded) {
$data = json_encode($data);
$jsonData = json_encode($data);

// json_encode might return false on failure
if (!$data) {
$this->log('Failed to perform json_encode on the the provided data: {error}', [
'error' => $data,
], LogLevel::ERROR);
// json_encode returns false on failure
if ($jsonData === false) {
throw new JsonEncodeException($data, json_last_error_msg(), json_last_error());
}
}

$postParams = [];
$postParams['name'] = $name;
$postParams['data'] = $data;
$postParams['data'] = $jsonData;
$postParams['channels'] = $channels;

if ($socketId !== null) {
$postParams['socket_id'] = $socketId;
}

try {
$response = $this->post('/event', [], $postParams);
$response = $this->post('/event', [], $postParams);

return $this->isSuccessStatusCode($response->getStatusCode());
} catch (GuzzleException $e) {
return false;
}
return $this->isSuccessStatusCode($response->getStatusCode());
}

/**
Expand All @@ -392,6 +391,8 @@ public function trigger($channels, $name, $data, $socketId = null, $jsonEncoded
* @param bool $jsonEncoded [optional] Defines if the data is already encoded
*
* @return bool
* @throws GuzzleException
* @throws JsonEncodeException on JSON encode failure.
*/
public function triggerBatch($batch = [], $jsonEncoded = false)
{
Expand All @@ -404,21 +405,23 @@ public function triggerBatch($batch = [], $jsonEncoded = false)
}

if (!$jsonEncoded) {
$batch[$key]['data'] = json_encode($event['data']);
$jsonData = json_encode($event['data']);

// json_encode returns false on failure
if ($jsonData === false) {
throw new JsonEncodeException($event['data'], json_last_error_msg(), json_last_error());
}

$batch[$key]['data'] = $jsonData;
}
}

$postParams = [];
$postParams['batch'] = $batch;

$response = $this->post('/events', [], $postParams);

try {
$response = $this->post('/events', [], $postParams);

return $this->isSuccessStatusCode($response->getStatusCode());
} catch (GuzzleException $e) {
return false;
}
return $this->isSuccessStatusCode($response->getStatusCode());
}

/**
Expand All @@ -429,7 +432,7 @@ public function triggerBatch($batch = [], $jsonEncoded = false)
* @param array $queryParams API query params (see https://broadcastt.xyz/docs/References-‐-Rest-API)
* @param array $postParams API post params (see https://broadcastt.xyz/docs/References-‐-Rest-API)
*
* @return Response
* @return ResponseInterface
* @throws GuzzleException
*/
private function post($path, $queryParams = [], $postParams = [])
Expand All @@ -453,7 +456,7 @@ private function post($path, $queryParams = [], $postParams = [])
* @param string $path Path excluding /apps/{appId}
* @param array $queryParams API query params (see https://broadcastt.xyz/docs/References-‐-Rest-API)
*
* @return Response See Broadcastt API docs
* @return ResponseInterface See Broadcastt API docs
* @throws GuzzleException
*/
public function get($path, $queryParams = [])
Expand Down Expand Up @@ -568,5 +571,4 @@ public function __set($name, $value)
$this->modifiers[$name] = $value;
}
}

}
22 changes: 22 additions & 0 deletions src/Exception/JsonEncodeException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Broadcastt\Exception;

class JsonEncodeException extends \RuntimeException
{
private $data;

public function __construct($data, $message, $code, \Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
$this->data = $data;
}

/**
* @return mixed
*/
public function getData()
{
return $this->data;
}
}
23 changes: 20 additions & 3 deletions tests/Feature/BroadcasttTriggerBatchTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
use Broadcastt\Exception\InvalidDataException;
use Broadcastt\Exception\InvalidHostException;
use Broadcastt\Exception\InvalidSocketIdException;
use Broadcastt\Exception\JsonEncodeException;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
Expand Down Expand Up @@ -180,7 +182,7 @@ public function testCanNotTriggerBatchWithInvalidHost()
$this->client->triggerBatch($batch);
}

public function testCanTriggerBatchHandlePayloadTooLargeResponse()
public function testCanTriggerBatchThrowExceptionOnPayloadTooLargeResponse()
{
$mockHandler = new MockHandler([
new Response(413, [], '{}'),
Expand All @@ -202,8 +204,8 @@ public function testCanTriggerBatchHandlePayloadTooLargeResponse()
$batch = [];
$batch[] = ['channel' => 'test-channel', 'name' => 'test-event', 'data' => ['test-key' => 'test-val']];
$batch[] = ['channel' => 'test-channel2', 'name' => 'test-event2', 'data' => ['test-key' => 'test-val2']];
$response = $this->client->triggerBatch($batch);
$this->assertFalse($response);
$this->expectException(GuzzleException::class);
$this->client->triggerBatch($batch);
}

public function testCanTriggerBatchHandlePayloadTooLargeResponseWhenGuzzleExceptionsAreDisabled()
Expand Down Expand Up @@ -233,4 +235,19 @@ public function testCanTriggerBatchHandlePayloadTooLargeResponseWhenGuzzleExcept
$this->assertFalse($response);
}

public function testCanTriggerBatchThrowExceptionOnJsonEncodeFailure()
{
// data from https://www.php.net/manual/en/function.json-last-error.php
$data = "\xB1\x31";

$batch = [];
$batch[] = ['channel' => 'test-channel', 'name' => 'test-event', 'data' => $data];
$this->expectException(JsonEncodeException::class);
try {
$this->client->triggerBatch($batch);
} catch (JsonEncodeException $e) {
$this->assertEquals($e->getData(), $data);
throw $e;
}
}
}
27 changes: 19 additions & 8 deletions tests/Feature/BroadcasttTriggerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

use Broadcastt\BroadcasttClient;
use Broadcastt\Exception\InvalidSocketIdException;
use Broadcastt\Exception\JsonEncodeException;
use Broadcastt\Exception\TooManyChannelsException;
use Broadcastt\Exception\InvalidHostException;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
Expand Down Expand Up @@ -165,7 +167,6 @@ public function testCanNotTriggerWithInvalidChannel($invalidChannel)
$this->client->setGuzzleClient($guzzleClient);

$this->expectException(InvalidArgumentException::class);

$this->client->trigger($invalidChannel, 'test-event', '');
}

Expand All @@ -181,12 +182,11 @@ public function testCanNotTriggerWithMoreThanHundredChannel()

$this->client->setGuzzleClient($guzzleClient);

$this->expectException(TooManyChannelsException::class);

$channels = [];
for ($i = 0; $i < 101; $i++) {
$channels[] = 'test-channel' . $i;
}
$this->expectException(TooManyChannelsException::class);
$this->client->trigger($channels, 'test-event', '');
}

Expand All @@ -207,7 +207,6 @@ public function testCanNotTriggerWithInvalidSocketId($invalidSocketId)
$this->client->setGuzzleClient($guzzleClient);

$this->expectException(InvalidSocketIdException::class);

$this->client->trigger('test-channel', 'test-event', '', $invalidSocketId);
}

Expand All @@ -225,11 +224,10 @@ public function testCanNotTriggerWithInvalidHost()
$this->client->host = 'http://test.xyz';

$this->expectException(InvalidHostException::class);

$this->client->trigger('test-channel', 'test-event', '');
}

public function testCanTriggerHandlePayloadTooLargeResponse()
public function testCanTriggerThrowExceptionOnPayloadTooLargeResponse()
{
$mockHandler = new MockHandler([
new Response(413, [], '{}'),
Expand All @@ -248,8 +246,8 @@ public function testCanTriggerHandlePayloadTooLargeResponse()

$this->client->setGuzzleClient($guzzleClient);

$response = $this->client->trigger('test-channel', 'test-event', '');
$this->assertFalse($response);
$this->expectException(GuzzleException::class);
$this->client->trigger('test-channel', 'test-event', '');
}

public function testCanTriggerHandlePayloadTooLargeResponseWhenGuzzleExceptionsAreDisabled()
Expand All @@ -276,4 +274,17 @@ public function testCanTriggerHandlePayloadTooLargeResponseWhenGuzzleExceptionsA
$this->assertFalse($response);
}

public function testCanTriggerThrowExceptionOnJsonEncodeFailure()
{
// data from https://www.php.net/manual/en/function.json-last-error.php
$data = "\xB1\x31";

$this->expectException(JsonEncodeException::class);
try {
$this->client->trigger('test-channel', 'test-event', $data);
} catch (JsonEncodeException $e) {
$this->assertEquals($e->getData(), $data);
throw $e;
}
}
}

0 comments on commit a225707

Please sign in to comment.