diff options
Diffstat (limited to 'indra/llcorehttp/tests')
| -rwxr-xr-x | indra/llcorehttp/tests/test_httprequest.hpp | 140 | ||||
| -rwxr-xr-x | indra/llcorehttp/tests/test_llcorehttp_peer.py | 49 | 
2 files changed, 185 insertions, 4 deletions
diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp index 27d65f171e..f1b9c02393 100755 --- a/indra/llcorehttp/tests/test_httprequest.hpp +++ b/indra/llcorehttp/tests/test_httprequest.hpp @@ -1213,7 +1213,7 @@ void HttpRequestTestObjectType::test<12>()  		HttpRequest::createService();  		// Enable tracing -		HttpRequest::setPolicyGlobalOption(LLCore::HttpRequest::GP_TRACE, 2); +		HttpRequest::setStaticPolicyOption(HttpRequest::PO_TRACE, HttpRequest::DEFAULT_POLICY_ID, 2, NULL);  		// Start threading early so that thread memory is invariant  		// over the test. @@ -1331,7 +1331,7 @@ void HttpRequestTestObjectType::test<13>()  		HttpRequest::createService();  		// Enable tracing -		HttpRequest::setPolicyGlobalOption(LLCore::HttpRequest::GP_TRACE, 2); +		HttpRequest::setStaticPolicyOption(HttpRequest::PO_TRACE, HttpRequest::DEFAULT_POLICY_ID, 2, NULL);  		// Start threading early so that thread memory is invariant  		// over the test. @@ -2972,6 +2972,142 @@ void HttpRequestTestObjectType::test<21>()  } +template <> template <> +void HttpRequestTestObjectType::test<22>() +{ +	ScopedCurlInit ready; + +	set_test_name("HttpRequest GET 503s with 'Retry-After'"); + +	// This tests mainly that the code doesn't fall over if +	// various well- and mis-formed Retry-After headers are +	// sent along with the response.  Direct inspection of +	// the parsing result isn't supported. +	 +	// Handler can be stack-allocated *if* there are no dangling +	// references to it after completion of this method. +	// Create before memory record as the string copy will bump numbers. +	TestHandler2 handler(this, "handler"); +	std::string url_base(get_base_url() + "/503/");	// path to 503 generators +		 +	// record the total amount of dynamically allocated memory +	mMemTotal = GetMemTotal(); +	mHandlerCalls = 0; + +	HttpRequest * req = NULL; +	HttpOptions * opts = NULL; +	 +	try +	{ +		// Get singletons created +		HttpRequest::createService(); +		 +		// Start threading early so that thread memory is invariant +		// over the test. +		HttpRequest::startThread(); + +		// create a new ref counted object with an implicit reference +		req = new HttpRequest(); +		ensure("Memory allocated on construction", mMemTotal < GetMemTotal()); + +		opts = new HttpOptions(); +		opts->setRetries(1);			// Retry once only +		opts->setUseRetryAfter(true);	// Try to parse the retry-after header +		 +		// Issue a GET that 503s with valid retry-after +		mStatus = HttpStatus(503); +		int url_limit(6); +		for (int i(0); i < url_limit; ++i) +		{ +			std::ostringstream url; +			url << url_base << i << "/"; +			HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, +														 0U, +														 url.str(), +														 0, +														 0, +														 opts, +														 NULL, +														 &handler); + +			std::ostringstream testtag; +			testtag << "Valid handle returned for 503 request #" << i; +			ensure(testtag.str(), handle != LLCORE_HTTP_HANDLE_INVALID); +		} +		 + +		// Run the notification pump. +		int count(0); +		int limit(300);				// One retry but several seconds needed +		while (count++ < limit && mHandlerCalls < url_limit) +		{ +			req->update(0); +			usleep(100000); +		} +		ensure("Request executed in reasonable time", count < limit); +		ensure("One handler invocation for request", mHandlerCalls == url_limit); + +		// Okay, request a shutdown of the servicing thread +		mStatus = HttpStatus(); +		mHandlerCalls = 0; +		HttpHandle handle = req->requestStopThread(&handler); +		ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID); +	 +		// Run the notification pump again +		count = 0; +		limit = 100; +		while (count++ < limit && mHandlerCalls < 1) +		{ +			req->update(1000000); +			usleep(100000); +		} +		ensure("Second request executed in reasonable time", count < limit); +		ensure("Second handler invocation", mHandlerCalls == 1); + +		// See that we actually shutdown the thread +		count = 0; +		limit = 10; +		while (count++ < limit && ! HttpService::isStopped()) +		{ +			usleep(100000); +		} +		ensure("Thread actually stopped running", HttpService::isStopped()); + +		// release options +		opts->release(); +		opts = NULL; +		 +		// release the request object +		delete req; +		req = NULL; + +		// Shut down service +		HttpRequest::destroyService(); +	 +#if defined(WIN32) +		// Can only do this memory test on Windows.  On other platforms, +		// the LL logging system holds on to memory and produces what looks +		// like memory leaks... +	 +		// printf("Old mem:  %d, New mem:  %d\n", mMemTotal, GetMemTotal()); +		ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal()); +#endif +	} +	catch (...) +	{ +		stop_thread(req); +		if (opts) +		{ +			opts->release(); +			opts = NULL; +		} +		delete req; +		HttpRequest::destroyService(); +		throw; +	} +} + +  }  // end namespace tut  namespace diff --git a/indra/llcorehttp/tests/test_llcorehttp_peer.py b/indra/llcorehttp/tests/test_llcorehttp_peer.py index 75a3c39ef2..f6c4d1a820 100755 --- a/indra/llcorehttp/tests/test_llcorehttp_peer.py +++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py @@ -9,7 +9,7 @@  $LicenseInfo:firstyear=2008&license=viewerlgpl$  Second Life Viewer Source Code -Copyright (C) 2012, Linden Research, Inc. +Copyright (C) 2012-2013, Linden Research, Inc.  This library is free software; you can redistribute it and/or  modify it under the terms of the GNU Lesser General Public @@ -47,6 +47,17 @@ from testrunner import freeport, run, debug, VERBOSE  class TestHTTPRequestHandler(BaseHTTPRequestHandler):      """This subclass of BaseHTTPRequestHandler is to receive and echo      LLSD-flavored messages sent by the C++ LLHTTPClient. + +    [Merge with viewer-cat later] +    - '/503/'           Generate 503 responses with various kinds +                        of 'retry-after' headers +    -- '/503/0/'            "Retry-After: 2"    +    -- '/503/1/'            "Retry-After: Thu, 31 Dec 2043 23:59:59 GMT" +    -- '/503/2/'            "Retry-After: Fri, 31 Dec 1999 23:59:59 GMT" +    -- '/503/3/'            "Retry-After: " +    -- '/503/4/'            "Retry-After: (*#*(@*(@(")" +    -- '/503/5/'            "Retry-After: aklsjflajfaklsfaklfasfklasdfklasdgahsdhgasdiogaioshdgo" +    -- '/503/6/'            "Retry-After: 1 2 3 4 5 6 7 8 9 10"      """      def read(self):          # The following logic is adapted from the library module @@ -107,7 +118,41 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):          if "/sleep/" in self.path:              time.sleep(30) -        if "fail" not in self.path: +        if "/503/" in self.path: +            # Tests for various kinds of 'Retry-After' header parsing +            body = None +            if "/503/0/" in self.path: +                self.send_response(503) +                self.send_header("retry-after", "2") +            elif "/503/1/" in self.path: +                self.send_response(503) +                self.send_header("retry-after", "Thu, 31 Dec 2043 23:59:59 GMT") +            elif "/503/2/" in self.path: +                self.send_response(503) +                self.send_header("retry-after", "Fri, 31 Dec 1999 23:59:59 GMT") +            elif "/503/3/" in self.path: +                self.send_response(503) +                self.send_header("retry-after", "") +            elif "/503/4/" in self.path: +                self.send_response(503) +                self.send_header("retry-after", "(*#*(@*(@(") +            elif "/503/5/" in self.path: +                self.send_response(503) +                self.send_header("retry-after", "aklsjflajfaklsfaklfasfklasdfklasdgahsdhgasdiogaioshdgo") +            elif "/503/6/" in self.path: +                self.send_response(503) +                self.send_header("retry-after", "1 2 3 4 5 6 7 8 9 10") +            else: +                # Unknown request +                self.send_response(400) +                body = "Unknown /503/ path in server" +            if "/reflect/" in self.path: +                self.reflect_headers() +            self.send_header("Content-type", "text/plain") +            self.end_headers() +            if body: +                self.wfile.write(body) +        elif "fail" not in self.path:              data = data.copy()          # we're going to modify              # Ensure there's a "reply" key in data, even if there wasn't before              data["reply"] = data.get("reply", llsd.LLSD("success"))  | 
