| 
<?phpnamespace WebPower\gcm\server;
 
 class MockHttpClient implements HttpClient
 {
 public $apiKey;
 public $url;
 public $mimeType;
 public $requestBody;
 
 public $responseList = array();
 
 public function post($apiKey, $url, $mimeType, $requestBody)
 {
 $this->apiKey = $apiKey;
 $this->url = $url;
 $this->mimeType = $mimeType;
 $this->requestBody = $requestBody;
 
 return array_shift($this->responseList);
 }
 }
 
 class SenderTest extends \PHPUnit_Framework_TestCase
 {
 private $regId = "15;16";
 private $collapseKey = "collapseKey";
 private $delayWhileIdle = true;
 private $ttl = 108;
 private $authKey = "4815162342";
 
 /** @var Message */
 private $message;
 
 /** @var MockHttpClient */
 private $mockClient;
 
 /** @var Sender */
 private $sender;
 
 protected function setUp()
 {
 parent::setUp();
 $this->message = Message::builder()
 ->collapseKey($this->collapseKey)
 ->delayWhileIdle($this->delayWhileIdle)
 ->timeToLive($this->ttl)
 ->addData('k1', 'v1')
 ->addData('k2', 'v2')
 ->addData('k3', 'v3')
 ->build();
 
 $this->mockClient = new MockHttpClient();
 $this->sender = new Sender($this->authKey);
 $this->sender->setHttpClient($this->mockClient);
 }
 
 public function setResponseExpectations($statusCode, $content)
 {
 $this->mockClient->responseList[] = new HttpClientResponse($statusCode, $content);
 }
 
 /**
 * @expectedException \InvalidArgumentException
 */
 public function testConstructorNull()
 {
 new Sender(null);
 }
 
 public function testSendNoRetry_ok()
 {
 $this->setResponseExpectations(200, "id=4815162342");
 $result = $this->sender->singleSendNoRetry($this->message, $this->regId);
 $this->assertNotNull($result);
 $this->assertEquals("4815162342", $result->getMessageId());
 $this->assertNull($result->getCanonicalRegistrationId());
 $this->assertNull($result->getErrorCodeName());
 $this->assertRequestBody();
 }
 
 public function testSendNoRetry_ok_canonical()
 {
 $this->setResponseExpectations(
 200,
 "id=4815162342\nregistration_id=108"
 );
 $result = $this->sender->singleSendNoRetry($this->message, $this->regId);
 $this->assertNotNull($result);
 $this->assertEquals("4815162342", $result->getMessageId());
 $this->assertEquals("108", $result->getCanonicalRegistrationId());
 $this->assertNull($result->getErrorCodeName());
 $this->assertRequestBody();
 }
 
 public function testSendNoRetry_unauthorized()
 {
 $this->setResponseExpectations(401, "");
 try {
 $this->sender->singleSendNoRetry($this->message, $this->regId);
 $this->fail("Should have thrown InvalidRequestException");
 } catch (InvalidRequestException $e) {
 $this->assertEquals(401, $e->getHttpStatusCode());
 }
 $this->assertRequestBody();
 }
 
 public function testSendNoRetry_error()
 {
 $this->setResponseExpectations(200, "Error=D'OH!");
 $result = $this->sender->singleSendNoRetry($this->message, $this->regId);
 $this->assertNull($result->getMessageId());
 $this->assertNull($result->getCanonicalRegistrationId());
 $this->assertEquals("D'OH!", $result->getErrorCodeName());
 $this->assertRequestBody();
 }
 
 public function testSendNoRetry_serviceUnavailable()
 {
 $this->setResponseExpectations(503, "");
 $result = $this->sender->singleSendNoRetry($this->message, $this->regId);
 $this->assertNull($result);
 $this->assertRequestBody();
 }
 
 /**
 * @expectedException \RuntimeException
 */
 public function testSendNoRetry_emptyBody()
 {
 $this->setResponseExpectations(200, "");
 $this->sender->singleSendNoRetry($this->message, $this->regId);
 }
 
 /**
 * @expectedException \RuntimeException
 */
 public function testSendNoRetry_noToken()
 {
 $this->setResponseExpectations(200, 'no token');
 $this->sender->singleSendNoRetry($this->message, $this->regId);
 }
 
 /**
 * @expectedException \RuntimeException
 */
 public function testSendNoRetry_invalidToken()
 {
 $this->setResponseExpectations(200, 'bad=token');
 $this->sender->singleSendNoRetry($this->message, $this->regId);
 }
 
 public function testSendNoRetry_invalidHttpStatusCode()
 {
 $this->setResponseExpectations(108, 'id=4815162342');
 try {
 $this->sender->singleSendNoRetry($this->message, $this->regId);
 $this->fail('Should have thrown InvalidRequestException');
 } catch (InvalidRequestException $e) {
 $this->assertEquals(108, $e->getHttpStatusCode());
 }
 }
 
 /**
 * @expectedException \InvalidArgumentException
 */
 public function testSendNoRetry_noRegistrationId()
 {
 $this->sender->singleSendNoRetry(Message::builder()->build(), null);
 }
 
 public function testSendNoRetry_json_badRequest()
 {
 $this->setResponseExpectations(42, "bad json");
 try {
 $this->sender->sendNoRetry($this->message, array("108"));
 } catch (InvalidRequestException $e) {
 $this->assertEquals(42, $e->getHttpStatusCode());
 $this->assertEquals("bad json", $e->getDescription());
 $this->assertRequestJsonBody(array("108"));
 }
 }
 
 public function testSendNoRetry_json_ok()
 {
 $json = json_encode(array(
 "multicast_id" => 108,
 "success" => 2,
 "failure" => 1,
 "canonical_ids" => 1,
 "results" => array(
 array('message_id' => 16),
 array('error' => 'DOH!'),
 array('message_id' => 23, 'registration_id' => 42)
 )
 ));
 
 $this->setResponseExpectations(200, $json);
 $registrationIds = array("4", "8", "15");
 $multicastResponse = $this->sender->sendNoRetry(
 $this->message,
 $registrationIds
 );
 $this->assertNotNull($multicastResponse);
 $this->assertEquals(3, $multicastResponse->getTotal());
 $this->assertEquals(2, $multicastResponse->getSuccess());
 $this->assertEquals(1, $multicastResponse->getFailure());
 $this->assertEquals(1, $multicastResponse->getCanonicalIds());
 $this->assertEquals(108, $multicastResponse->getMulticastId());
 $results = $multicastResponse->getResults();
 $this->assertNotNull($results);
 $this->assertEquals(3, count($results));
 $this->assertResult($results[0], "16", null, null);
 $this->assertResult($results[1], null, 'DOH!', null);
 $this->assertResult($results[2], "23", null, "42");
 $this->assertRequestJsonBody($registrationIds);
 }
 
 private function assertRequestBody()
 {
 $body = $this->mockClient->requestBody;
 $params = array();
 foreach (explode('&', $body) as $param) {
 list($key, $value) = explode('=', $param, 2);
 $params[$key] = $value;
 }
 
 $this->assertEquals(7, count($params), $body);
 $this->assertParameter($params, 'registration_id', $this->regId);
 $this->assertParameter($params, 'collapse_key', $this->collapseKey);
 $this->assertParameter($params, 'delay_while_idle', $this->delayWhileIdle ? "1" : "0");
 $this->assertParameter($params, 'time_to_live', "" . $this->ttl);
 $this->assertParameter($params, 'data.k1', 'v1');
 $this->assertParameter($params, 'data.k2', 'v2');
 $this->assertParameter($params, 'data.k3', 'v3');
 }
 
 private function assertParameter($params, $name, $expectedValue)
 {
 $this->assertEquals(
 $expectedValue,
 $params[$name],
 "invalid value for request parameter parameter " . $name
 );
 }
 
 private function assertRequestJsonBody(array $expectedRegIds)
 {
 $this->assertEquals(
 Constants::GCM_SEND_ENDPOINT,
 $this->mockClient->url
 );
 $this->assertEquals('application/json', $this->mockClient->mimeType);
 $body = $this->mockClient->requestBody;
 $json = json_decode($body, true);
 $this->assertEquals($this->ttl, $json['time_to_live']);
 $this->assertEquals($this->collapseKey, $json['collapse_key']);
 $this->assertEquals($this->delayWhileIdle, $json['delay_while_idle']);
 $payload = $json['data'];
 $this->assertNotNull($payload, 'no payload');
 $this->assertEquals(3, count($payload), 'wrong payload size');
 $this->assertEquals('v1', $payload['k1']);
 $this->assertEquals('v2', $payload['k2']);
 $this->assertEquals('v3', $payload['k3']);
 $actualRegIds = $json['registration_ids'];
 $this->assertEquals(count($expectedRegIds), count($actualRegIds));
 $this->assertEquals($expectedRegIds, $actualRegIds);
 }
 
 private function assertResult(
 Result $result,
 $messageId,
 $error,
 $canonicalRegistrationId
 ) {
 $this->assertEquals($messageId, $result->getMessageId());
 $this->assertEquals($error, $result->getErrorCodeName());
 $this->assertEquals(
 $canonicalRegistrationId,
 $result->getCanonicalRegistrationId()
 );
 }
 }
 |