responses = array(); $this->requests = array(); } /** * Adds a response object to an internal queue of responses. * @param RemoteContentRequest $response The response to return. */ public function enqueueResponse(RemoteContentRequest $response) { $this->responses[] = $response; } /** * Returns a request object that was sent to fetchRequest. If multiple * requests have been sent to fetchRequest, they are returned by this * method in the order they were requested. * @return RemoteContentRequest */ public function dequeueRequest() { return array_shift($this->requests); } /** * Fakes a content request to a remote server. * @param RemoteContentRequest $request The external request information. * @return RemoteContentRequest The next response which was enqueued by * calling enqueueResponse. */ public function fetchRequest(RemoteContentRequest $request) { $this->requests[] = $request; return array_shift($this->responses); } /** * Fakes multiple requests to a remote server. Calls fetchRequest for * each request passed to this method. * @param array $requests An array of RemoteContentRequests. * @return An array of RemoteContentRequests corresponging to the responses * returned for each of the request inputs. */ public function multiFetchRequest(Array $requests) { $responses = array(); foreach ($requests as $key => $request) { $responses[$key] = $this->fetchRequest($request); } return $responses; } } /** * Unit tests for the MakeRequest class. */ class MakeRequestTest extends \PHPUnit_Framework_TestCase { private $fetcher; private $makeRequest; private $context; private $response; /** * Prepares the environment before running a test. */ protected function setUp() { parent::setUp(); $this->fetcher = new MockMakeRequestFetcher(); $this->makeRequest = new MakeRequest($this->fetcher); $this->context = new GadgetContext('GADGET'); $this->response = new RemoteContentRequest('http://www.example.com'); $this->response->setHttpCode(200); $this->response->setResponseContent("Basic response"); } /** * Cleans up the environment after running a test. */ protected function tearDown() { parent::tearDown(); } /** * Executes a makeRequest call and returns the request object which would * have been sent externally (as opposed to the response). * * @param MakeRequestOptions $params * @param RemoteContentRequest $response The response to return for this * request. * @return RemoteContentRequest The request object. */ protected function catchRequest(MakeRequestOptions $params, RemoteContentRequest $response) { $this->fetcher->enqueueResponse($response); $result = $this->makeRequest->fetch($this->context, $params); return $this->fetcher->dequeueRequest(); } /** * Tests that makeRequest calls with an invalid url throw an exception. */ public function testInvalidUrl() { try { $params = new MakeRequestOptions('invalidurl'); $this->makeRequest->fetch($params); $this->fail("Calling makeRequest with an invalid url should throw an exception."); } catch (\Exception $ex) { } } /** * Tests that normal requests specify a GET to the supplied URL. */ public function testBasicRequest() { $params = new MakeRequestOptions('http://www.example.com'); $params->setNoCache(true); $request = $this->catchRequest($params, $this->response); $this->assertContains($request->getUrl(), 'http://www.example.com'); $this->assertEquals('GET', $request->getMethod()); } /** * Tests that signed requests generate appropriate oauth_ and opensocial_ * parameters. */ public function testSignedRequest() { $token = BasicSecurityToken::createFromValues('owner', 'viewer', 'app', 'domain', 'appUrl', '1', 'default'); $params = new MakeRequestOptions('http://www.example.com'); $params->setAuthz('SIGNED') ->setNoCache(true) ->setSecurityTokenString(urldecode($token->toSerialForm())); $request = $this->catchRequest($params, $this->response); $this->assertContains('oauth_signature', $request->getUrl()); $this->assertContains('oauth_signature_method=RSA-SHA1', $request->getUrl()); $this->assertContains('opensocial_app_url=appUrl', $request->getUrl()); $this->assertContains('opensocial_viewer_id=viewer', $request->getUrl()); $this->assertContains('opensocial_owner_id=owner', $request->getUrl()); $this->assertEquals('GET', $request->getMethod()); } /** * Tests that setting "sign_viewer" = false does not include viewer * information in the request. */ public function testSignedNoViewerRequest() { $token = BasicSecurityToken::createFromValues('owner', 'viewer', 'app', 'domain', 'appUrl', '1', 'default'); $params = new MakeRequestOptions('http://www.example.com'); $params->setAuthz('SIGNED') ->setNoCache(true) ->setSignViewer(false) ->setSecurityTokenString(urldecode($token->toSerialForm())); $request = $this->catchRequest($params, $this->response); $this->assertContains('oauth_signature', $request->getUrl()); $this->assertNotContains('opensocial_viewer_id=viewer', $request->getUrl()); $this->assertContains('opensocial_owner_id=owner', $request->getUrl()); } /** * Tests that setting "format" = "FEED" parses an atom feed into a JSON * structure. */ public function testFeedRequest() { $params = new MakeRequestOptions('http://www.example.com'); $params->setResponseFormat('FEED') ->setNoCache(true) ->setNumEntries(2); $sampleAtomPath = realpath(dirname(__FILE__) . "/../misc/sampleAtomFeed.xml"); $sampleAtom = file_get_contents($sampleAtomPath); $this->response->setResponseContent($sampleAtom); $this->fetcher->enqueueResponse($this->response); $result = $this->makeRequest->fetch($this->context, $params); $feedJson = json_decode($result->getResponseContent(), true); $this->assertArrayHasKey('Entry', $feedJson); $this->assertEquals(2, count($feedJson['Entry'])); $this->assertArrayHasKey('Title', $feedJson['Entry'][0]); $this->assertEquals("Atom-Powered Robots Run Amok", $feedJson['Entry'][0]['Title']); } /** * Tests that setting request headers are passed in the outgoing request. */ public function testRequestHeaders(){ $params = new MakeRequestOptions('http://www.example.com'); $params->setRequestHeaders(array( "Content-Type" => "application/json", "Accept-Language" => "en-us" )); $params->setNoCache(true); $request = $this->catchRequest($params, $this->response); $this->assertTrue($request->hasHeaders()); $this->assertEquals('application/json', $request->getHeader('Content-Type')); $this->assertEquals('en-us', $request->getHeader('Accept-Language')); } /** * Tests that setting invalid request headers are not passed in the outgoing * request. */ public function testInvalidRequestHeaders(){ $params = new MakeRequestOptions('http://www.example.com'); $params->setRequestHeaders(array( "Content-Type" => "application/json", "Accept-Language" => "en-us", "Host" => "http://www.evil.com", "host" => "http://www.evil.com", "HOST" => "http://www.evil.com", "Accept" => "blah", "Accept-Encoding" => "blah" )); $params->setNoCache(true); $request = $this->catchRequest($params, $this->response); $this->assertTrue($request->hasHeaders()); $this->assertEquals('application/json', $request->getHeader('Content-Type')); $this->assertEquals('en-us', $request->getHeader('Accept-Language')); $this->assertNull($request->getHeader('Host')); $this->assertNull($request->getHeader('Accept')); $this->assertNull($request->getHeader('Accept-Encoding')); } /** * Tests that setting request headers in a form urlencoded way are passed in the outgoing request. */ public function testFormEncodedRequestHeaders(){ $params = new MakeRequestOptions('http://www.example.com'); $params->setFormEncodedRequestHeaders("Content-Type=application%2Fx-www-form-urlencoded&Accept-Language=en-us"); $params->setNoCache(true); $request = $this->catchRequest($params, $this->response); $this->assertTrue($request->hasHeaders()); $this->assertEquals('application/x-www-form-urlencoded', $request->getHeader('Content-Type')); } public function testResponseHeaders() { $params = new MakeRequestOptions('http://www.example.com'); $params->setNoCache(true); $headers = array( 'Content-Type' => 'text/plain' ); $this->response->setResponseHeaders($headers); $this->fetcher->enqueueResponse($this->response); $result = $this->makeRequest->fetch($this->context, $params); $response_headers = $result->getResponseHeaders(); $this->assertArrayHasKey('Content-Type', $response_headers); $this->assertEquals('text/plain', $response_headers['Content-Type']); } public function testCleanResponseHeaders() { $response_headers = array( 'Content-Type' => 'text/plain', 'Set-Cookie' => 'blah', 'set-cookie' => 'blah', 'SET-COOKIE' => 'blah', 'sEt-cOoKiE' => 'blah', 'Accept-Ranges' => 'blah', 'Vary' => 'blah', 'Expires' => 'blah', 'Date' => 'blah', 'Pragma' => 'blah', 'Cache-Control' => 'blah', 'Transfer-Encoding' => 'blah', 'WWW-Authenticate' => 'blah' ); $cleaned_headers = $this->makeRequest->cleanResponseHeaders($response_headers); $this->assertArrayHasKey('Content-Type', $cleaned_headers); $this->assertEquals('text/plain', $cleaned_headers['Content-Type']); $this->assertArrayNotHasKey('Set-Cookie', $cleaned_headers); $this->assertArrayNotHasKey('set-cookie', $cleaned_headers); $this->assertArrayNotHasKey('SET-COOKIE', $cleaned_headers); $this->assertArrayNotHasKey('sEt-cOoKiE', $cleaned_headers); $this->assertArrayNotHasKey('Accept-Ranges', $cleaned_headers); $this->assertArrayNotHasKey('Vary', $cleaned_headers); $this->assertArrayNotHasKey('Expires', $cleaned_headers); $this->assertArrayNotHasKey('Date', $cleaned_headers); $this->assertArrayNotHasKey('Pragma', $cleaned_headers); $this->assertArrayNotHasKey('Cache-Control', $cleaned_headers); $this->assertArrayNotHasKey('Transfer-Encoding', $cleaned_headers); $this->assertArrayNotHasKey('WWW-Authenticate', $cleaned_headers); } }