Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Unified Diff: ios/net/protocol_handler_util_unittest.mm

Issue 994823004: [iOS] Upstream //ios/net (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/net/protocol_handler_util_unittest.mm
diff --git a/ios/net/protocol_handler_util_unittest.mm b/ios/net/protocol_handler_util_unittest.mm
new file mode 100644
index 0000000000000000000000000000000000000000..d2bdc72ce4b21d6aa024805bdc50bb2858d0cb5e
--- /dev/null
+++ b/ios/net/protocol_handler_util_unittest.mm
@@ -0,0 +1,274 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/mac/scoped_nsobject.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/strings/sys_string_conversions.h"
+#import "ios/net/protocol_handler_util.h"
+#include "net/base/elements_upload_data_stream.h"
+#import "net/base/mac/url_conversions.h"
+#include "net/base/upload_bytes_element_reader.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/data_protocol_handler.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_job.h"
+#include "net/url_request/url_request_job_factory.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "url/gurl.h"
+
+// When C++ exceptions are disabled, the C++ library defines |try| and
+// |catch| so as to allow exception-expecting C++ code to build properly when
+// language support for exceptions is not present. These macros interfere
+// with the use of |@try| and |@catch| in Objective-C files such as this one.
+// Undefine these macros here, after everything has been #included, since
+// there will be no C++ uses and only Objective-C uses from this point on.
+#undef try
+#undef catch
+
+namespace net {
+namespace {
+
+const int kResponseCode = 200;
+const char* kTextHtml = "text/html";
+const char* kTextPlain = "text/plain";
+const char* kAscii = "US-ASCII";
+
+class HeadersURLRequestJob : public URLRequestJob {
+ public:
+ HeadersURLRequestJob(URLRequest* request)
+ : URLRequestJob(request, nullptr) {}
+
+ void Start() override {
+ // Fills response headers and returns immediately.
+ NotifyHeadersComplete();
+ }
+
+ bool GetMimeType(std::string* mime_type) const override {
+ *mime_type = GetContentTypeValue();
+ return true;
+ }
+
+ void GetResponseInfo(HttpResponseInfo* info) override {
+ // This is called by NotifyHeadersComplete().
+ std::string header_string("HTTP/1.0 200 OK");
+ header_string.push_back('\0');
+ header_string += std::string("Cache-Control: max-age=600");
+ header_string.push_back('\0');
+ if (request()->url().DomainIs("multiplecontenttype")) {
+ header_string += std::string(
+ "coNteNt-tYPe: text/plain; charset=iso-8859-4, image/png");
+ header_string.push_back('\0');
+ }
+ header_string += std::string("Content-Type: ") + GetContentTypeValue();
+ header_string.push_back('\0');
+ header_string += std::string("Foo: A");
+ header_string.push_back('\0');
+ header_string += std::string("Bar: B");
+ header_string.push_back('\0');
+ header_string += std::string("Baz: C");
+ header_string.push_back('\0');
+ header_string += std::string("Foo: D");
+ header_string.push_back('\0');
+ header_string += std::string("Foo: E");
+ header_string.push_back('\0');
+ header_string += std::string("Bar: F");
+ header_string.push_back('\0');
+ info->headers = new HttpResponseHeaders(header_string);
+ }
+
+ int GetResponseCode() const override {
+ return kResponseCode;
+ }
+ protected:
+ ~HeadersURLRequestJob() override {}
+
+ std::string GetContentTypeValue() const {
+ if (request()->url().DomainIs("badcontenttype"))
+ return "\xff";
+ return kTextHtml;
+ }
+};
+
+class NetProtocolHandler : public URLRequestJobFactory::ProtocolHandler {
+ public:
+ URLRequestJob* MaybeCreateJob(
+ URLRequest* request,
+ NetworkDelegate* network_delegate) const override {
+ return new HeadersURLRequestJob(request);
+ }
+};
+
+class ProtocolHandlerUtilTest : public testing::Test,
+ public URLRequest::Delegate {
+ public:
+ ProtocolHandlerUtilTest() : request_context_(new TestURLRequestContext) {
+ // Ownership of the protocol handlers is transferred to the factory.
+ job_factory_.SetProtocolHandler("http", new NetProtocolHandler);
+ job_factory_.SetProtocolHandler("data", new DataProtocolHandler);
+ request_context_->set_job_factory(&job_factory_);
+ }
+
+ NSURLResponse* BuildDataURLResponse(const std::string& mime_type,
+ const std::string& encoding,
+ const std::string& content) {
+ // Build an URL in the form "data:<mime_type>;charset=<encoding>,<content>"
+ // The ';' is removed if mime_type or charset is empty.
+ std::string url_string = std::string("data:") + mime_type;
+ if (!encoding.empty())
+ url_string += ";charset=" + encoding;
+ url_string += ",";
+ GURL url(url_string);
+
+ scoped_ptr<URLRequest> request(
+ request_context_->CreateRequest(url, DEFAULT_PRIORITY, this, nullptr));
+ request->Start();
+ base::RunLoop loop;
+ loop.RunUntilIdle();
+ return GetNSURLResponseForRequest(request.get());
+ }
+
+ void CheckDataResponse(NSURLResponse* response,
+ const std::string& mime_type,
+ const std::string& encoding) {
+ EXPECT_NSEQ(base::SysUTF8ToNSString(mime_type), [response MIMEType]);
+ EXPECT_NSEQ(base::SysUTF8ToNSString(encoding), [response textEncodingName]);
+ // The response class must be NSURLResponse (and not NSHTTPURLResponse) when
+ // the scheme is "data".
+ EXPECT_TRUE([response isMemberOfClass:[NSURLResponse class]]);
+ }
+
+ void OnResponseStarted(URLRequest* request) override {}
+ void OnReadCompleted(URLRequest* request, int bytes_read) override {}
+
+ protected:
+ base::MessageLoop loop_;
+ URLRequestJobFactoryImpl job_factory_;
+ scoped_ptr<URLRequestContext> request_context_;
+};
+
+} // namespace
+
+TEST_F(ProtocolHandlerUtilTest, GetResponseDataSchemeTest) {
+ NSURLResponse* response;
+ // MIME type and charset are correctly carried over.
+ response = BuildDataURLResponse("#mime=type'", "$(charset-*", "content");
+ CheckDataResponse(response, "#mime=type'", "$(charset-*");
+ // Missing values are treated as default values.
+ response = BuildDataURLResponse("", "", "content");
+ CheckDataResponse(response, kTextPlain, kAscii);
+}
+
+TEST_F(ProtocolHandlerUtilTest, GetResponseHttpTest) {
+ // Create a request.
+ GURL url(std::string("http://url"));
+ scoped_ptr<URLRequest> request(
+ request_context_->CreateRequest(url, DEFAULT_PRIORITY, this, nullptr));
+ request->Start();
+ // Create a response from the request.
+ NSURLResponse* response = GetNSURLResponseForRequest(request.get());
+ EXPECT_NSEQ([NSString stringWithUTF8String:kTextHtml], [response MIMEType]);
+ ASSERT_TRUE([response isKindOfClass:[NSHTTPURLResponse class]]);
+ NSHTTPURLResponse* http_response = (NSHTTPURLResponse*)response;
+ NSDictionary* headers = [http_response allHeaderFields];
+ // Check the headers, duplicates must be appended.
+ EXPECT_EQ(5u, [headers count]);
+ NSString* foo_header = [headers objectForKey:@"Foo"];
+ EXPECT_NSEQ(@"A,D,E", foo_header);
+ NSString* bar_header = [headers objectForKey:@"Bar"];
+ EXPECT_NSEQ(@"B,F", bar_header);
+ NSString* baz_header = [headers objectForKey:@"Baz"];
+ EXPECT_NSEQ(@"C", baz_header);
+ NSString* cache_header = [headers objectForKey:@"Cache-Control"];
+ EXPECT_NSEQ(@"no-store", cache_header); // Cache-Control is overridden.
+ // Check the status.
+ EXPECT_EQ(request->GetResponseCode(), [http_response statusCode]);
+}
+
+TEST_F(ProtocolHandlerUtilTest, BadHttpContentType) {
+ // Create a request using the magic domain that triggers a garbage
+ // content-type in the test framework.
+ GURL url(std::string("http://badcontenttype"));
+ scoped_ptr<URLRequest> request(
+ request_context_->CreateRequest(url, DEFAULT_PRIORITY, this, nullptr));
+ request->Start();
+ // Create a response from the request.
+ @try {
+ GetNSURLResponseForRequest(request.get());
+ }
+ @catch (id exception) {
+ FAIL() << "Exception while creating response";
+ }
+}
+
+TEST_F(ProtocolHandlerUtilTest, MultipleHttpContentType) {
+ // Create a request using the magic domain that triggers a garbage
+ // content-type in the test framework.
+ GURL url(std::string("http://multiplecontenttype"));
+ scoped_ptr<URLRequest> request(
+ request_context_->CreateRequest(url, DEFAULT_PRIORITY, this, nullptr));
+ request->Start();
+ // Create a response from the request.
+ NSURLResponse* response = GetNSURLResponseForRequest(request.get());
+ EXPECT_NSEQ(@"text/plain", [response MIMEType]);
+ EXPECT_NSEQ(@"iso-8859-4", [response textEncodingName]);
+ NSHTTPURLResponse* http_response = (NSHTTPURLResponse*)response;
+ NSDictionary* headers = [http_response allHeaderFields];
+ NSString* content_type_header = [headers objectForKey:@"Content-Type"];
+ EXPECT_NSEQ(@"text/plain; charset=iso-8859-4", content_type_header);
+}
+
+TEST_F(ProtocolHandlerUtilTest, CopyHttpHeaders) {
+ GURL url(std::string("http://url"));
+ base::scoped_nsobject<NSMutableURLRequest> in_request(
+ [[NSMutableURLRequest alloc] initWithURL:NSURLWithGURL(url)]);
+ [in_request setAllHTTPHeaderFields:@{
+ @"Referer" : @"referrer",
+ @"User-Agent" : @"secret",
+ @"Accept" : @"money/cash",
+ @"Foo" : @"bar",
+ }];
+ scoped_ptr<URLRequest> out_request(
+ request_context_->CreateRequest(url, DEFAULT_PRIORITY, nullptr, nullptr));
+ CopyHttpHeaders(in_request, out_request.get());
+
+ EXPECT_EQ("referrer", out_request->referrer());
+ const HttpRequestHeaders& headers = out_request->extra_request_headers();
+ EXPECT_FALSE(headers.HasHeader("User-Agent")); // User agent is not copied.
+ EXPECT_FALSE(headers.HasHeader("Content-Type")); // Only in POST requests.
+ std::string header;
+ EXPECT_TRUE(headers.GetHeader("Accept", &header));
+ EXPECT_EQ("money/cash", header);
+ EXPECT_TRUE(headers.GetHeader("Foo", &header));
+ EXPECT_EQ("bar", header);
+}
+
+TEST_F(ProtocolHandlerUtilTest, AddMissingHeaders) {
+ GURL url(std::string("http://url"));
+ base::scoped_nsobject<NSMutableURLRequest> in_request(
+ [[NSMutableURLRequest alloc] initWithURL:NSURLWithGURL(url)]);
+ scoped_ptr<URLRequest> out_request(
+ request_context_->CreateRequest(url, DEFAULT_PRIORITY, nullptr, nullptr));
+ out_request->set_method("POST");
+ scoped_ptr<UploadElementReader> reader(
+ new UploadBytesElementReader(nullptr, 0));
+ out_request->set_upload(
+ ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0));
+ CopyHttpHeaders(in_request, out_request.get());
+
+ // Some headers are added by default if missing.
+ const HttpRequestHeaders& headers = out_request->extra_request_headers();
+ std::string header;
+ EXPECT_TRUE(headers.GetHeader("Accept", &header));
+ EXPECT_EQ("*/*", header);
+ EXPECT_TRUE(headers.GetHeader("Content-Type", &header));
+ EXPECT_EQ("application/x-www-form-urlencoded", header);
+}
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698