_SERVER = $_SERVER; } public function tearDown() { $_SERVER = $this->_SERVER; parent::tearDown(); } private static function buildBulkAddRequest() { $req = new TaskQueueBulkAddRequest(); $task = $req->addAddRequest(); $task->setQueueName('default'); $task->setTaskName(''); $task->setUrl('/someUrl'); global $mockTime; $task->setEtaUsec($mockTime * 1e6); $task->setMethod(RequestMethod::POST); return $req; } public function testConstructorUrlWrongType() { $this->setExpectedException('\InvalidArgumentException', 'url_path must be a string. Actual type: integer'); $task = new PushTask(999, ['key' => 'some value']); } public function testConstructorUrlEmpty() { $this->setExpectedException('\InvalidArgumentException', "url_path must begin with '/'."); $task = new PushTask('', ['key' => 'some value']); } public function testConstructorUrlWithoutLeadingSlash() { $this->setExpectedException('\InvalidArgumentException', "url_path must begin with '/'."); $task = new PushTask('wrong', ['key' => 'some value']); } public function testConstructorUrlMustNotContainQueryString() { $this->setExpectedException('\InvalidArgumentException', 'query strings not allowed in url_path.'); $task = new PushTask('/someurl?'); } public function testConstructorQueryDataWrongType() { $this->setExpectedException('\InvalidArgumentException', 'query_data must be an array. Actual type: string'); $task = new PushTask('/myUrl', 'abc'); } public function testConstructorOptionsWrongType() { $this->setExpectedException('\InvalidArgumentException', 'options must be an array. Actual type: integer'); $task = new PushTask('/someUrl', ['key' => 'some value'], 123); } public function testConstructorUnknownOptions() { $this->setExpectedException('\InvalidArgumentException', 'Invalid options supplied: nonsense'); $task = new PushTask('/someUrl', ['key' => 'some value'], ['nonsense' => 123]); } public function testConstructorInvalidMethod() { $this->setExpectedException('\InvalidArgumentException', 'Invalid method: POSTIT'); $task = new PushTask('/someUrl', ['key' => 'some value'], ['method' => 'POSTIT']); } public function testConstructorInvalidName() { $this->setExpectedException('\InvalidArgumentException', 'name must be a string. Actual type: integer'); $task = new PushTask('/someUrl', ['key' => 'some value'], ['name' => 55]); } public function testConstructorNameTooLong() { $name = str_repeat('a', 501); $this->setExpectedException('\InvalidArgumentException', 'name exceeds maximum length of 500. First 1000 ' . 'characters of name: ' . $name); $task = new PushTask('/someUrl', ['key' => 'some value'], ['name' => $name]); } public function testConstructorNameMaxLength() { // Just tests that this doesn't throw an exception. $task = new PushTask('/someUrl', ['key' => 'some value'], ['name' => str_repeat('a', 500)]); } public function testConstructorNameBadCharacters() { $this->setExpectedException('\InvalidArgumentException', 'name must match pattern: ' . PushTask::NAME_PATTERN . '. name: @'); $task = new PushTask('/someUrl', ['key' => 'some value'], ['name' => '@']); } public function testConstructorInvalidDelaySeconds() { $this->setExpectedException('\InvalidArgumentException', 'delay_seconds must be a numeric type.'); $task = new PushTask('/someUrl', ['key' => 'some value'], ['delay_seconds' => 'a few']); } public function testConstructorNegativeDelaySeconds() { $this->setExpectedException('\InvalidArgumentException', 'delay_seconds must be between 0 and ' . PushTask::MAX_DELAY_SECONDS . ' (30 days). delay_seconds: -1'); $task = new PushTask('/someUrl', ['key' => 'some value'], ['delay_seconds' => -1]); } public function testConstructorDelaySecondsTooBig() { $delay = 1 + 30 * 86400; $this->setExpectedException('\InvalidArgumentException', 'delay_seconds must be between 0 and ' . PushTask::MAX_DELAY_SECONDS . ' (30 days). delay_seconds: ' . $delay); $task = new PushTask('/someUrl', ['key' => 'some value'], ['delay_seconds' => $delay]); } public function testConstructorMaxDelaySecond() { // Just tests that a 30 day delay_seconds doesn't throw an exception. $task = new PushTask('/someUrl', ['key' => 'some value'], ['delay_seconds' => 30 * 86400]); } public function testAddInvalidQueue() { $this->setExpectedException('\InvalidArgumentException'); (new PushTask('/someUrl'))->add(999); } public function testAddTaskTooBig() { $this->setExpectedException( '\google\appengine\api\taskqueue\TaskQueueException', 'Task greater than maximum size of ' . PushTask::MAX_TASK_SIZE_BYTES); // Althought 102400 is the max size, it's for the serialized proto which // includes the URL etc. (new PushTask('/someUrl', ['field' => str_repeat('a', 102395)]))->add(); } public function testAddUrlTooBig() { $url = '/' . str_repeat('b', 2083); $this->setExpectedException( '\google\appengine\api\taskqueue\TaskQueueException', 'URL length greater than maximum of ' . PushTask::MAX_URL_LENGTH) . '. URL: ' . $url; (new PushTask($url))->add(); } public function testPushTaskSimplestAdd() { $req = self::buildBulkAddRequest(); $resp = new TaskQueueBulkAddResponse(); $task_result = $resp->addTaskResult(); $task_result->setResult(ErrorCode::OK); $task_result->setChosenTaskName('fred'); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $resp); $task_name = (new PushTask('/someUrl'))->add(); $this->assertEquals('fred', $task_name); $this->apiProxyMock->verify(); } public function testPushTaskSimpleAddWithQueryData() { $query_data = ['key' => 'some value']; $req = self::buildBulkAddRequest(); $req->getAddRequest(0)->setBody(http_build_query($query_data)); $header = $req->getAddRequest(0)->addHeader(); $header->setKey('content-type'); $header->setValue('application/x-www-form-urlencoded'); $resp = new TaskQueueBulkAddResponse(); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $resp); (new PushTask('/someUrl', $query_data))->add(); $this->apiProxyMock->verify(); } public function testPushTaskAddToNonDefaultQueue() { $req = self::buildBulkAddRequest(); $req->getAddRequest(0)->setQueueName('myqueue'); $resp = new TaskQueueBulkAddResponse(); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $resp); (new PushTask('/someUrl'))->add('myqueue'); $this->apiProxyMock->verify(); } public function testPushTaskAddBasicGetRequest() { $req = self::buildBulkAddRequest(); $req->getAddRequest(0)->setMethod(RequestMethod::GET); $resp = new TaskQueueBulkAddResponse(); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $resp); (new PushTask('/someUrl', [], ['method' => 'GET']))->add(); $this->apiProxyMock->verify(); } public function testPushTaskAddGetRequestWithQueryData() { $req = self::buildBulkAddRequest(); $req->getAddRequest(0)->setMethod(RequestMethod::GET); $req->getAddRequest(0)->setUrl('/someUrl?aKey=aValue'); $resp = new TaskQueueBulkAddResponse(); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $resp); $task = new PushTask('/someUrl', ['aKey' => 'aValue'], ['method' => 'GET']); $task->add(); $this->apiProxyMock->verify(); } public function testPushTaskWithNameAndETA() { $req = self::buildBulkAddRequest(); $add_req = $req->getAddRequest(0); $add_req->setTaskName('customTaskName'); $add_req->setEtaUsec($add_req->getEtaUsec() + 5 * 1e6); $resp = new TaskQueueBulkAddResponse(); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $resp); $task = new PushTask('/someUrl', [], ['delay_seconds' => 5, 'name' => 'customTaskName']); $task_name = $task->add(); $this->assertEquals('customTaskName', $task_name); $this->apiProxyMock->verify(); } public function testUnknownQueueError() { $req = self::buildBulkAddRequest(); $exception = new \google\appengine\runtime\ApplicationError( ErrorCode::UNKNOWN_QUEUE, 'message'); $this->setExpectedException( '\google\appengine\api\taskqueue\TaskQueueException', 'Unknown queue'); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $exception); (new PushTask('/someUrl'))->add(); } public function testTransientError() { $req = self::buildBulkAddRequest(); $exception = new \google\appengine\runtime\ApplicationError( ErrorCode::TRANSIENT_ERROR, 'message'); $this->setExpectedException( '\google\appengine\api\taskqueue\TransientTaskQueueException'); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $exception); (new PushTask('/someUrl'))->add(); } public function testPermissionDeniedError() { $req = self::buildBulkAddRequest(); $exception = new \google\appengine\runtime\ApplicationError( ErrorCode::PERMISSION_DENIED, 'message'); $this->setExpectedException( '\google\appengine\api\taskqueue\TaskQueueException', 'Permission Denied'); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $exception); (new PushTask('/someUrl'))->add(); } public function testTombstonedTaskError() { $req = self::buildBulkAddRequest(); $exception = new \google\appengine\runtime\ApplicationError( ErrorCode::TOMBSTONED_TASK, 'message'); $this->setExpectedException( '\google\appengine\api\taskqueue\TaskAlreadyExistsException'); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $exception); (new PushTask('/someUrl'))->add(); } public function testTaskAlreadyExistsError() { $req = self::buildBulkAddRequest(); $exception = new \google\appengine\runtime\ApplicationError( ErrorCode::TASK_ALREADY_EXISTS, 'message'); $this->setExpectedException( '\google\appengine\api\taskqueue\TaskAlreadyExistsException'); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $exception); (new PushTask('/someUrl'))->add(); } public function testTaskInvalidQueueModeError() { $req = self::buildBulkAddRequest(); $exception = new \google\appengine\runtime\ApplicationError( ErrorCode::INVALID_QUEUE_MODE, 'message'); $this->setExpectedException( '\google\appengine\api\taskqueue\TaskQueueException', 'Cannot add a PushTask to a pull queue.'); $this->apiProxyMock->expectCall('taskqueue', 'BulkAdd', $req, $exception); (new PushTask('/someUrl'))->add(); } }