aboutsummaryrefslogtreecommitdiffstats
path: root/components/net/tests
diff options
context:
space:
mode:
Diffstat (limited to 'components/net/tests')
-rw-r--r--components/net/tests/chrome_loader.rs44
-rw-r--r--components/net/tests/cookie.rs413
-rw-r--r--components/net/tests/cookie_http_state.rs1927
-rw-r--r--components/net/tests/cookie_http_state_utils.py174
-rw-r--r--components/net/tests/data_loader.rs139
-rw-r--r--components/net/tests/fetch.rs982
-rw-r--r--components/net/tests/file_loader.rs17
-rw-r--r--components/net/tests/filemanager_thread.rs110
-rw-r--r--components/net/tests/hsts.rs294
-rw-r--r--components/net/tests/http_loader.rs1186
-rw-r--r--components/net/tests/main.rs112
-rw-r--r--components/net/tests/mime_classifier.rs560
-rwxr-xr-xcomponents/net/tests/parsable_mime/application/font-woff/test.wof1
-rw-r--r--components/net/tests/parsable_mime/application/ogg/small.oggbin0 -> 105243 bytes
-rw-r--r--components/net/tests/parsable_mime/application/pdf/test.pdf157
-rwxr-xr-xcomponents/net/tests/parsable_mime/application/postscript/test.ps1
-rwxr-xr-xcomponents/net/tests/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobjectbin0 -> 36 bytes
-rw-r--r--components/net/tests/parsable_mime/application/x-gzip/test.gzbin0 -> 1239 bytes
-rwxr-xr-xcomponents/net/tests/parsable_mime/application/x-rar-compressed/test.rarbin0 -> 7 bytes
-rwxr-xr-xcomponents/net/tests/parsable_mime/application/zip/test.zip1
-rw-r--r--components/net/tests/parsable_mime/audio/aiff/test.aifbin0 -> 47122 bytes
-rw-r--r--components/net/tests/parsable_mime/audio/basic/test.aubin0 -> 47086 bytes
-rw-r--r--components/net/tests/parsable_mime/audio/midi/test.midbin0 -> 8444 bytes
-rw-r--r--components/net/tests/parsable_mime/audio/mpeg/test.mp3bin0 -> 33621 bytes
-rw-r--r--components/net/tests/parsable_mime/audio/wave/test.wavbin0 -> 47196 bytes
-rw-r--r--components/net/tests/parsable_mime/image/bmp/test.bmpbin0 -> 11914 bytes
-rw-r--r--components/net/tests/parsable_mime/image/gif/test87abin0 -> 1303 bytes
-rw-r--r--components/net/tests/parsable_mime/image/gif/test89a.gifbin0 -> 1303 bytes
-rw-r--r--components/net/tests/parsable_mime/image/jpeg/test.jpgbin0 -> 3744 bytes
-rw-r--r--components/net/tests/parsable_mime/image/png/test.pngbin0 -> 4293 bytes
-rwxr-xr-xcomponents/net/tests/parsable_mime/image/webp/test.webpbin0 -> 14 bytes
-rw-r--r--components/net/tests/parsable_mime/image/x-icon/test.icobin0 -> 12206 bytes
-rw-r--r--components/net/tests/parsable_mime/image/x-icon/test_cursor.icobin0 -> 12206 bytes
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_a_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_a_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_a_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_a_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_b_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_b_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_b_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_b_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_body_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_body_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_body_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_body_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_br_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_br_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_br_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_br_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_comment_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_comment_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_comment_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_comment_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_div_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_div_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_div_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_div_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_doctype_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_doctype_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_doctype_3e.html4
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_doctype_3e_u.html4
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_font_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_font_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_font_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_font_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_h1_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_h1_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_h1_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_h1_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_head_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_head_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_head_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_head_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_iframe_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_iframe_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_iframe_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_iframe_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_p_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_p_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_p_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_p_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_page_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_page_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_page_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_page_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_script_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_script_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_script_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_script_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_style_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_style_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_style_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_style_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_table_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_table_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_table_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_table_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_title_20.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_title_20_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_title_3e.html3
-rw-r--r--components/net/tests/parsable_mime/text/html/text_html_title_3e_u.html3
-rw-r--r--components/net/tests/parsable_mime/text/plain/utf16bebom.txtbin0 -> 42 bytes
-rw-r--r--components/net/tests/parsable_mime/text/plain/utf16lebom.txtbin0 -> 40 bytes
-rw-r--r--components/net/tests/parsable_mime/text/plain/utf8bom.txt1
-rwxr-xr-xcomponents/net/tests/parsable_mime/text/xml/feed.atom1
-rw-r--r--components/net/tests/parsable_mime/text/xml/feed.rss151
-rw-r--r--components/net/tests/parsable_mime/text/xml/rdf_rss.xml7
-rw-r--r--components/net/tests/parsable_mime/text/xml/rdf_rss_ko_1.xml7
-rw-r--r--components/net/tests/parsable_mime/text/xml/rdf_rss_ko_2.xml3
-rw-r--r--components/net/tests/parsable_mime/text/xml/rdf_rss_ko_3.xml6
-rw-r--r--components/net/tests/parsable_mime/text/xml/rdf_rss_ko_4.xml7
-rw-r--r--components/net/tests/parsable_mime/text/xml/test.xml6
-rw-r--r--components/net/tests/parsable_mime/unknown/binary_filebin0 -> 1024 bytes
-rw-r--r--components/net/tests/parsable_mime/unknown/open_type1
-rw-r--r--components/net/tests/parsable_mime/unknown/true_type.ttfbin0 -> 333616 bytes
-rw-r--r--components/net/tests/parsable_mime/unknown/true_type_collection.ttc1
-rw-r--r--components/net/tests/parsable_mime/video/avi/test.avibin0 -> 675840 bytes
-rw-r--r--components/net/tests/parsable_mime/video/mp4/test.mp4bin0 -> 383631 bytes
-rw-r--r--components/net/tests/parsable_mime/video/webm/test.webmbin0 -> 229455 bytes
-rw-r--r--components/net/tests/resource_thread.rs142
-rw-r--r--components/net/tests/subresource_integrity.rs92
-rw-r--r--components/net/tests/test.jpegbin0 -> 62218 bytes
122 files changed, 6749 insertions, 0 deletions
diff --git a/components/net/tests/chrome_loader.rs b/components/net/tests/chrome_loader.rs
new file mode 100644
index 00000000000..c7669d9a0ac
--- /dev/null
+++ b/components/net/tests/chrome_loader.rs
@@ -0,0 +1,44 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use net::test::resolve_chrome_url;
+use servo_url::ServoUrl;
+
+fn c(s: &str) -> Result<ServoUrl, ()> {
+ resolve_chrome_url(&ServoUrl::parse(s).unwrap())
+}
+
+#[test]
+fn test_resolve_chrome_url() {
+ assert_eq!(c("chrome://resources/nonexistent.jpg"), Err(()));
+ assert_eq!(c("chrome://not-resources/badcert.jpg"), Err(()));
+ assert_eq!(c("chrome://resources/badcert.jpg").unwrap().scheme(), "file");
+ assert_eq!(c("chrome://resources/subdir/../badcert.jpg").unwrap().scheme(), "file");
+ assert_eq!(c("chrome://resources/subdir/../../badcert.jpg").unwrap().scheme(), "file");
+ assert_eq!(c("chrome://resources/../badcert.jpg").unwrap().scheme(), "file");
+ assert_eq!(c("chrome://resources/../README.md"), Err(()));
+ assert_eq!(c("chrome://resources/%2e%2e/README.md"), Err(()));
+
+ assert_eq!(c("chrome://resources/etc/passwd"), Err(()));
+ assert_eq!(c("chrome://resources//etc/passwd"), Err(()));
+ assert_eq!(c("chrome://resources/%2Fetc%2Fpasswd"), Err(()));
+
+ assert_eq!(c("chrome://resources/C:/Windows/notepad.exe"), Err(()));
+ assert_eq!(c("chrome://resources/C:\\Windows\\notepad.exe"), Err(()));
+
+ assert_eq!(c("chrome://resources/localhost/C:/Windows/notepad.exe"), Err(()));
+ assert_eq!(c("chrome://resources//localhost/C:/Windows/notepad.exe"), Err(()));
+ assert_eq!(c("chrome://resources///localhost/C:/Windows/notepad.exe"), Err(()));
+ assert_eq!(c("chrome://resources/\\\\localhost\\C:\\Windows\\notepad.exe"), Err(()));
+
+ assert_eq!(c("chrome://resources/%3F/C:/Windows/notepad.exe"), Err(()));
+ assert_eq!(c("chrome://resources//%3F/C:/Windows/notepad.exe"), Err(()));
+ assert_eq!(c("chrome://resources///%3F/C:/Windows/notepad.exe"), Err(()));
+ assert_eq!(c("chrome://resources/\\\\%3F\\C:\\Windows\\notepad.exe"), Err(()));
+
+ assert_eq!(c("chrome://resources/%3F/UNC/localhost/C:/Windows/notepad.exe"), Err(()));
+ assert_eq!(c("chrome://resources//%3F/UNC/localhost/C:/Windows/notepad.exe"), Err(()));
+ assert_eq!(c("chrome://resources///%3F/UNC/localhost/C:/Windows/notepad.exe"), Err(()));
+ assert_eq!(c("chrome://resources/\\\\%3F\\UNC\\localhost\\C:\\Windows\\notepad.exe"), Err(()));
+}
diff --git a/components/net/tests/cookie.rs b/components/net/tests/cookie.rs
new file mode 100644
index 00000000000..0508f5ae4ec
--- /dev/null
+++ b/components/net/tests/cookie.rs
@@ -0,0 +1,413 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use cookie_rs;
+use hyper::header::{Header, SetCookie};
+use net::cookie::Cookie;
+use net::cookie_storage::CookieStorage;
+use net_traits::CookieSource;
+use servo_url::ServoUrl;
+
+#[test]
+fn test_domain_match() {
+ assert!(Cookie::domain_match("foo.com", "foo.com"));
+ assert!(Cookie::domain_match("bar.foo.com", "foo.com"));
+ assert!(Cookie::domain_match("baz.bar.foo.com", "foo.com"));
+
+ assert!(!Cookie::domain_match("bar.foo.com", "bar.com"));
+ assert!(!Cookie::domain_match("bar.com", "baz.bar.com"));
+ assert!(!Cookie::domain_match("foo.com", "bar.com"));
+
+ assert!(!Cookie::domain_match("bar.com", "bbar.com"));
+ assert!(Cookie::domain_match("235.132.2.3", "235.132.2.3"));
+ assert!(!Cookie::domain_match("235.132.2.3", "1.1.1.1"));
+ assert!(!Cookie::domain_match("235.132.2.3", ".2.3"));
+}
+
+#[test]
+fn test_path_match() {
+ assert!(Cookie::path_match("/", "/"));
+ assert!(Cookie::path_match("/index.html", "/"));
+ assert!(Cookie::path_match("/w/index.html", "/"));
+ assert!(Cookie::path_match("/w/index.html", "/w/index.html"));
+ assert!(Cookie::path_match("/w/index.html", "/w/"));
+ assert!(Cookie::path_match("/w/index.html", "/w"));
+
+ assert!(!Cookie::path_match("/", "/w/"));
+ assert!(!Cookie::path_match("/a", "/w/"));
+ assert!(!Cookie::path_match("/", "/w"));
+ assert!(!Cookie::path_match("/w/index.html", "/w/index"));
+ assert!(!Cookie::path_match("/windex.html", "/w/"));
+ assert!(!Cookie::path_match("/windex.html", "/w"));
+}
+
+#[test]
+fn test_default_path() {
+ assert!(&*Cookie::default_path("/foo/bar/baz/") == "/foo/bar/baz");
+ assert!(&*Cookie::default_path("/foo/bar/baz") == "/foo/bar");
+ assert!(&*Cookie::default_path("/foo/") == "/foo");
+ assert!(&*Cookie::default_path("/foo") == "/");
+ assert!(&*Cookie::default_path("/") == "/");
+ assert!(&*Cookie::default_path("") == "/");
+ assert!(&*Cookie::default_path("foo") == "/");
+}
+
+#[test]
+fn fn_cookie_constructor() {
+ use net_traits::CookieSource;
+
+ let url = &ServoUrl::parse("http://example.com/foo").unwrap();
+
+ let gov_url = &ServoUrl::parse("http://gov.ac/foo").unwrap();
+ // cookie name/value test
+ assert!(cookie_rs::Cookie::parse(" baz ").is_err());
+ assert!(cookie_rs::Cookie::parse(" = bar ").is_err());
+ assert!(cookie_rs::Cookie::parse(" baz = ").is_ok());
+
+ // cookie domains test
+ let cookie = cookie_rs::Cookie::parse(" baz = bar; Domain = ").unwrap();
+ assert!(Cookie::new_wrapped(cookie.clone(), url, CookieSource::HTTP).is_some());
+ let cookie = Cookie::new_wrapped(cookie, url, CookieSource::HTTP).unwrap();
+ assert!(&**cookie.cookie.domain().as_ref().unwrap() == "example.com");
+
+ // cookie public domains test
+ let cookie = cookie_rs::Cookie::parse(" baz = bar; Domain = gov.ac").unwrap();
+ assert!(Cookie::new_wrapped(cookie.clone(), url, CookieSource::HTTP).is_none());
+ assert!(Cookie::new_wrapped(cookie, gov_url, CookieSource::HTTP).is_some());
+
+ // cookie domain matching test
+ let cookie = cookie_rs::Cookie::parse(" baz = bar ; Secure; Domain = bazample.com").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let cookie = cookie_rs::Cookie::parse(" baz = bar ; Secure; Path = /foo/bar/").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_some());
+
+ let cookie = cookie_rs::Cookie::parse(" baz = bar ; HttpOnly").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::NonHTTP).is_none());
+
+ let cookie = cookie_rs::Cookie::parse(" baz = bar ; Secure; Path = /foo/bar/").unwrap();
+ let cookie = Cookie::new_wrapped(cookie, url, CookieSource::HTTP).unwrap();
+ assert!(cookie.cookie.value() == "bar");
+ assert!(cookie.cookie.name() == "baz");
+ assert!(cookie.cookie.secure());
+ assert!(&cookie.cookie.path().as_ref().unwrap()[..] == "/foo/bar/");
+ assert!(&cookie.cookie.domain().as_ref().unwrap()[..] == "example.com");
+ assert!(cookie.host_only);
+
+ let u = &ServoUrl::parse("http://example.com/foobar").unwrap();
+ let cookie = cookie_rs::Cookie::parse("foobar=value;path=/").unwrap();
+ assert!(Cookie::new_wrapped(cookie, u, CookieSource::HTTP).is_some());
+}
+
+#[test]
+fn test_cookie_secure_prefix() {
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Secure-SID=12345").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("http://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Secure-SID=12345; Secure").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Secure-SID=12345; Secure").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_some());
+
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Secure-SID=12345; Domain=example.com").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("http://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Secure-SID=12345; Secure; Domain=example.com").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Secure-SID=12345; Secure; Domain=example.com").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_some());
+}
+
+#[test]
+fn test_cookie_host_prefix() {
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Host-SID=12345").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("http://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Host-SID=12345; Secure").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Host-SID=12345; Secure").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Host-SID=12345; Domain=example.com").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Host-SID=12345; Domain=example.com; Path=/").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("http://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Host-SID=12345; Secure; Domain=example.com").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Host-SID=12345; Secure; Domain=example.com").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Host-SID=12345; Secure; Domain=example.com; Path=/").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_none());
+
+ let url = &ServoUrl::parse("https://example.com").unwrap();
+ let cookie = cookie_rs::Cookie::parse("__Host-SID=12345; Secure; Path=/").unwrap();
+ assert!(Cookie::new_wrapped(cookie, url, CookieSource::HTTP).is_some());
+}
+
+#[cfg(target_os = "windows")]
+fn delay_to_ensure_different_timestamp() {
+ use std::thread;
+ use std::time::Duration;
+
+ // time::now()'s resolution on some platforms isn't granular enought to ensure
+ // that two back-to-back calls to Cookie::new_wrapped generate different timestamps .
+ thread::sleep(Duration::from_millis(500));
+}
+
+#[cfg(not(target_os = "windows"))]
+fn delay_to_ensure_different_timestamp() {}
+
+#[test]
+fn test_sort_order() {
+ use std::cmp::Ordering;
+
+ let url = &ServoUrl::parse("http://example.com/foo").unwrap();
+ let a_wrapped = cookie_rs::Cookie::parse("baz=bar; Path=/foo/bar/").unwrap();
+ let a = Cookie::new_wrapped(a_wrapped.clone(), url, CookieSource::HTTP).unwrap();
+ delay_to_ensure_different_timestamp();
+ let a_prime = Cookie::new_wrapped(a_wrapped, url, CookieSource::HTTP).unwrap();
+ let b = cookie_rs::Cookie::parse("baz=bar;Path=/foo/bar/baz/").unwrap();
+ let b = Cookie::new_wrapped(b, url, CookieSource::HTTP).unwrap();
+
+ assert!(b.cookie.path().as_ref().unwrap().len() > a.cookie.path().as_ref().unwrap().len());
+ assert!(CookieStorage::cookie_comparator(&a, &b) == Ordering::Greater);
+ assert!(CookieStorage::cookie_comparator(&b, &a) == Ordering::Less);
+ assert!(CookieStorage::cookie_comparator(&a, &a_prime) == Ordering::Less);
+ assert!(CookieStorage::cookie_comparator(&a_prime, &a) == Ordering::Greater);
+ assert!(CookieStorage::cookie_comparator(&a, &a) == Ordering::Equal);
+}
+
+fn add_cookie_to_storage(storage: &mut CookieStorage, url: &ServoUrl, cookie_str: &str)
+{
+ let source = CookieSource::HTTP;
+ let cookie = cookie_rs::Cookie::parse(cookie_str.to_owned()).unwrap();
+ let cookie = Cookie::new_wrapped(cookie, url, source).unwrap();
+ storage.push(cookie, url, source);
+}
+
+#[test]
+fn test_insecure_cookies_cannot_evict_secure_cookie() {
+ let mut storage = CookieStorage::new(5);
+ let secure_url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap();
+ let source = CookieSource::HTTP;
+ let mut cookies = Vec::new();
+
+ cookies.push(cookie_rs::Cookie::parse("foo=bar; Secure; Domain=home.example.org").unwrap());
+ cookies.push(cookie_rs::Cookie::parse("foo2=bar; Secure; Domain=.example.org").unwrap());
+ cookies.push(cookie_rs::Cookie::parse("foo3=bar; Secure; Path=/foo").unwrap());
+ cookies.push(cookie_rs::Cookie::parse("foo4=bar; Secure; Path=/foo/bar").unwrap());
+
+ for bare_cookie in cookies {
+ let cookie = Cookie::new_wrapped(bare_cookie, &secure_url, source).unwrap();
+ storage.push(cookie, &secure_url, source);
+ }
+
+ let insecure_url = ServoUrl::parse("http://home.example.org:8888/cookie-parser?0001").unwrap();
+
+ add_cookie_to_storage(&mut storage, &insecure_url, "foo=value; Domain=home.example.org");
+ add_cookie_to_storage(&mut storage, &insecure_url, "foo2=value; Domain=.example.org");
+ add_cookie_to_storage(&mut storage, &insecure_url, "foo3=value; Path=/foo/bar");
+ add_cookie_to_storage(&mut storage, &insecure_url, "foo4=value; Path=/foo");
+
+ let source = CookieSource::HTTP;
+ assert_eq!(storage.cookies_for_url(&secure_url, source).unwrap(), "foo=bar; foo2=bar");
+
+ let url = ServoUrl::parse("https://home.example.org:8888/foo/cookie-parser-result?0001").unwrap();
+ let source = CookieSource::HTTP;
+ assert_eq!(storage.cookies_for_url(&url, source).unwrap(), "foo3=bar; foo4=value; foo=bar; foo2=bar");
+
+ let url = ServoUrl::parse("https://home.example.org:8888/foo/bar/cookie-parser-result?0001").unwrap();
+ let source = CookieSource::HTTP;
+ assert_eq!(storage.cookies_for_url(&url, source).unwrap(), "foo4=bar; foo3=bar; foo4=value; foo=bar; foo2=bar");
+}
+
+#[test]
+fn test_secure_cookies_eviction() {
+ let mut storage = CookieStorage::new(5);
+ let url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap();
+ let source = CookieSource::HTTP;
+ let mut cookies = Vec::new();
+
+ cookies.push(cookie_rs::Cookie::parse("foo=bar; Secure; Domain=home.example.org").unwrap());
+ cookies.push(cookie_rs::Cookie::parse("foo2=bar; Secure; Domain=.example.org").unwrap());
+ cookies.push(cookie_rs::Cookie::parse("foo3=bar; Secure; Path=/foo").unwrap());
+ cookies.push(cookie_rs::Cookie::parse("foo4=bar; Secure; Path=/foo/bar").unwrap());
+
+ for bare_cookie in cookies {
+ let cookie = Cookie::new_wrapped(bare_cookie, &url, source).unwrap();
+ storage.push(cookie, &url, source);
+ }
+
+ add_cookie_to_storage(&mut storage, &url, "foo=value; Domain=home.example.org");
+ add_cookie_to_storage(&mut storage, &url, "foo2=value; Domain=.example.org");
+ add_cookie_to_storage(&mut storage, &url, "foo3=value; Path=/foo/bar");
+ add_cookie_to_storage(&mut storage, &url, "foo4=value; Path=/foo");
+
+ let source = CookieSource::HTTP;
+ assert_eq!(storage.cookies_for_url(&url, source).unwrap(), "foo2=value");
+
+ let url = ServoUrl::parse("https://home.example.org:8888/foo/cookie-parser-result?0001").unwrap();
+ let source = CookieSource::HTTP;
+ assert_eq!(storage.cookies_for_url(&url, source).unwrap(), "foo3=bar; foo4=value; foo2=value");
+
+ let url = ServoUrl::parse("https://home.example.org:8888/foo/bar/cookie-parser-result?0001").unwrap();
+ let source = CookieSource::HTTP;
+ assert_eq!(storage.cookies_for_url(&url, source).unwrap(),
+ "foo4=bar; foo3=value; foo3=bar; foo4=value; foo2=value");
+}
+
+#[test]
+fn test_secure_cookies_eviction_non_http_source() {
+ let mut storage = CookieStorage::new(5);
+ let url = ServoUrl::parse("https://home.example.org:8888/cookie-parser?0001").unwrap();
+ let source = CookieSource::NonHTTP;
+ let mut cookies = Vec::new();
+
+ cookies.push(cookie_rs::Cookie::parse("foo=bar; Secure; Domain=home.example.org").unwrap());
+ cookies.push(cookie_rs::Cookie::parse("foo2=bar; Secure; Domain=.example.org").unwrap());
+ cookies.push(cookie_rs::Cookie::parse("foo3=bar; Secure; Path=/foo").unwrap());
+ cookies.push(cookie_rs::Cookie::parse("foo4=bar; Secure; Path=/foo/bar").unwrap());
+
+ for bare_cookie in cookies {
+ let cookie = Cookie::new_wrapped(bare_cookie, &url, source).unwrap();
+ storage.push(cookie, &url, source);
+ }
+
+ add_cookie_to_storage(&mut storage, &url, "foo=value; Domain=home.example.org");
+ add_cookie_to_storage(&mut storage, &url, "foo2=value; Domain=.example.org");
+ add_cookie_to_storage(&mut storage, &url, "foo3=value; Path=/foo/bar");
+ add_cookie_to_storage(&mut storage, &url, "foo4=value; Path=/foo");
+
+ let source = CookieSource::HTTP;
+ assert_eq!(storage.cookies_for_url(&url, source).unwrap(), "foo2=value");
+
+ let url = ServoUrl::parse("https://home.example.org:8888/foo/cookie-parser-result?0001").unwrap();
+ let source = CookieSource::HTTP;
+ assert_eq!(storage.cookies_for_url(&url, source).unwrap(), "foo3=bar; foo4=value; foo2=value");
+
+ let url = ServoUrl::parse("https://home.example.org:8888/foo/bar/cookie-parser-result?0001").unwrap();
+ let source = CookieSource::HTTP;
+ assert_eq!(storage.cookies_for_url(&url, source).unwrap(),
+ "foo4=bar; foo3=value; foo3=bar; foo4=value; foo2=value");
+}
+
+
+fn add_retrieve_cookies(set_location: &str,
+ set_cookies: &[String],
+ final_location: &str)
+ -> String {
+ let mut storage = CookieStorage::new(5);
+ let url = ServoUrl::parse(set_location).unwrap();
+ let source = CookieSource::HTTP;
+
+ // Add all cookies to the store
+ for str_cookie in set_cookies {
+ let bytes = str_cookie.to_string().into_bytes();
+ let header = Header::parse_header(&[bytes]).unwrap();
+ let SetCookie(cookies) = header;
+ for bare_cookie in cookies {
+ let cookie = Cookie::from_cookie_string(bare_cookie, &url, source).unwrap();
+ storage.push(cookie, &url, source);
+ }
+ }
+
+ // Get cookies for the test location
+ let url = ServoUrl::parse(final_location).unwrap();
+ storage.cookies_for_url(&url, source).unwrap_or("".to_string())
+}
+
+
+#[test]
+fn test_cookie_eviction_expired() {
+ let mut vec = Vec::new();
+ for i in 1..6 {
+ let st = format!("extra{}=bar; Secure; expires=Sun, 18-Apr-2000 21:06:29 GMT",
+ i);
+ vec.push(st);
+ }
+ vec.push("foo=bar; Secure; expires=Sun, 18-Apr-2027 21:06:29 GMT".to_owned());
+ let r = add_retrieve_cookies("https://home.example.org:8888/cookie-parser?0001",
+ &vec, "https://home.example.org:8888/cookie-parser-result?0001");
+ assert_eq!(&r, "foo=bar");
+}
+
+
+#[test]
+fn test_cookie_eviction_all_secure_one_nonsecure() {
+ let mut vec = Vec::new();
+ for i in 1..5 {
+ let st = format!("extra{}=bar; Secure; expires=Sun, 18-Apr-2026 21:06:29 GMT",
+ i);
+ vec.push(st);
+ }
+ vec.push("foo=bar; expires=Sun, 18-Apr-2026 21:06:29 GMT".to_owned());
+ vec.push("foo2=bar; Secure; expires=Sun, 18-Apr-2028 21:06:29 GMT".to_owned());
+ let r = add_retrieve_cookies("https://home.example.org:8888/cookie-parser?0001",
+ &vec, "https://home.example.org:8888/cookie-parser-result?0001");
+ assert_eq!(&r, "extra1=bar; extra2=bar; extra3=bar; extra4=bar; foo2=bar");
+}
+
+
+#[test]
+fn test_cookie_eviction_all_secure_new_nonsecure() {
+ let mut vec = Vec::new();
+ for i in 1..6 {
+ let st = format!("extra{}=bar; Secure; expires=Sun, 18-Apr-2026 21:06:29 GMT",
+ i);
+ vec.push(st);
+ }
+ vec.push("foo=bar; expires=Sun, 18-Apr-2077 21:06:29 GMT".to_owned());
+ let r = add_retrieve_cookies("https://home.example.org:8888/cookie-parser?0001",
+ &vec, "https://home.example.org:8888/cookie-parser-result?0001");
+ assert_eq!(&r, "extra1=bar; extra2=bar; extra3=bar; extra4=bar; extra5=bar");
+}
+
+
+#[test]
+fn test_cookie_eviction_all_nonsecure_new_secure() {
+ let mut vec = Vec::new();
+ for i in 1..6 {
+ let st = format!("extra{}=bar; expires=Sun, 18-Apr-2026 21:06:29 GMT", i);
+ vec.push(st);
+ }
+ vec.push("foo=bar; Secure; expires=Sun, 18-Apr-2077 21:06:29 GMT".to_owned());
+ let r = add_retrieve_cookies("https://home.example.org:8888/cookie-parser?0001",
+ &vec, "https://home.example.org:8888/cookie-parser-result?0001");
+ assert_eq!(&r, "extra2=bar; extra3=bar; extra4=bar; extra5=bar; foo=bar");
+}
+
+
+#[test]
+fn test_cookie_eviction_all_nonsecure_new_nonsecure() {
+ let mut vec = Vec::new();
+ for i in 1..6 {
+ let st = format!("extra{}=bar; expires=Sun, 18-Apr-2026 21:06:29 GMT", i);
+ vec.push(st);
+ }
+ vec.push("foo=bar; expires=Sun, 18-Apr-2077 21:06:29 GMT".to_owned());
+ let r = add_retrieve_cookies("https://home.example.org:8888/cookie-parser?0001",
+ &vec, "https://home.example.org:8888/cookie-parser-result?0001");
+ assert_eq!(&r, "extra2=bar; extra3=bar; extra4=bar; extra5=bar; foo=bar");
+}
diff --git a/components/net/tests/cookie_http_state.rs b/components/net/tests/cookie_http_state.rs
new file mode 100644
index 00000000000..30cec8b26b2
--- /dev/null
+++ b/components/net/tests/cookie_http_state.rs
@@ -0,0 +1,1927 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use hyper::header::{Header, SetCookie};
+use net::cookie::Cookie;
+use net::cookie_storage::CookieStorage;
+use net_traits::CookieSource;
+use servo_url::ServoUrl;
+
+
+fn run(set_location: &str, set_cookies: &[&str], final_location: &str) -> String {
+ let mut storage = CookieStorage::new(150);
+ let url = ServoUrl::parse(set_location).unwrap();
+ let source = CookieSource::HTTP;
+
+ // Add all cookies to the store
+ for str_cookie in set_cookies {
+ let bytes = str_cookie.to_string().into_bytes();
+ let header = Header::parse_header(&[bytes]);
+ if let Ok(SetCookie(cookies)) = header {
+ for bare_cookie in cookies {
+ if let Some(cookie) = Cookie::from_cookie_string(bare_cookie, &url, source) {
+ storage.push(cookie, &url, source);
+ }
+ }
+ }
+ }
+
+ // Get cookies for the test location
+ let url = ServoUrl::parse(final_location).unwrap();
+ storage.cookies_for_url(&url, source).unwrap_or("".to_string())
+}
+
+// Following are all tests extracted from https://github.com/abarth/http-state.git
+// They are generated by `./mach update-net-cookies`
+// Test listing
+
+#[test]
+fn test_0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?0001",
+ &["foo=bar"],
+ "http://home.example.org:8888/cookie-parser-result?0001");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_0002() {
+ let r = run("http://home.example.org:8888/cookie-parser?0002",
+ &["foo=bar; Expires=Fri, 07 Aug 2019 08:04:19 GMT"],
+ "http://home.example.org:8888/cookie-parser-result?0002");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+#[should_panic] // Look at cookie_http_state_utils.py if this test fails
+fn test_0003() {
+ let r = run("http://home.example.org:8888/cookie-parser?0003",
+ &["foo=bar; Expires=Fri, 07 Aug 2007 08:04:19 GMT",
+ "foo2=bar2; Expires=Fri, 07 Aug 2017 08:04:19 GMT"],
+ "http://home.example.org:8888/cookie-parser-result?0003");
+ assert_eq!(&r, "foo2=bar2");
+}
+
+#[test]
+fn test_0004() {
+ let r = run("http://home.example.org:8888/cookie-parser?0004",
+ &["foo"],
+ "http://home.example.org:8888/cookie-parser-result?0004");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_0005() {
+ let r = run("http://home.example.org:8888/cookie-parser?0005",
+ &["foo=bar; max-age=10000;"],
+ "http://home.example.org:8888/cookie-parser-result?0005");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+#[should_panic] // Look at cookie_http_state_utils.py if this test fails
+fn test_0006() {
+ let r = run("http://home.example.org:8888/cookie-parser?0006",
+ &["foo=bar; max-age=0;"],
+ "http://home.example.org:8888/cookie-parser-result?0006");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_0007() {
+ let r = run("http://home.example.org:8888/cookie-parser?0007",
+ &["foo=bar; version=1;"],
+ "http://home.example.org:8888/cookie-parser-result?0007");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_0008() {
+ let r = run("http://home.example.org:8888/cookie-parser?0008",
+ &["foo=bar; version=1000;"],
+ "http://home.example.org:8888/cookie-parser-result?0008");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_0009() {
+ let r = run("http://home.example.org:8888/cookie-parser?0009",
+ &["foo=bar; customvalue=1000;"],
+ "http://home.example.org:8888/cookie-parser-result?0009");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_0010() {
+ let r = run("http://home.example.org:8888/cookie-parser?0010",
+ &["foo=bar; secure;"],
+ "http://home.example.org:8888/cookie-parser-result?0010");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_0011() {
+ let r = run("http://home.example.org:8888/cookie-parser?0011",
+ &["foo=bar; customvalue=\"1000 or more\";"],
+ "http://home.example.org:8888/cookie-parser-result?0011");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_0012() {
+ let r = run("http://home.example.org:8888/cookie-parser?0012",
+ &["foo=bar; customvalue=\"no trailing semicolon\""],
+ "http://home.example.org:8888/cookie-parser-result?0012");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_0013() {
+ let r = run("http://home.example.org:8888/cookie-parser?0013",
+ &["foo=bar", "foo=qux"],
+ "http://home.example.org:8888/cookie-parser-result?0013");
+ assert_eq!(&r, "foo=qux");
+}
+
+#[test]
+fn test_0014() {
+ let r = run("http://home.example.org:8888/cookie-parser?0014",
+ &["foo1=bar", "foo2=qux"],
+ "http://home.example.org:8888/cookie-parser-result?0014");
+ assert_eq!(&r, "foo1=bar; foo2=qux");
+}
+
+#[test]
+fn test_0015() {
+ let r = run("http://home.example.org:8888/cookie-parser?0015",
+ &["a=b", "z=y"],
+ "http://home.example.org:8888/cookie-parser-result?0015");
+ assert_eq!(&r, "a=b; z=y");
+}
+
+#[test]
+fn test_0016() {
+ let r = run("http://home.example.org:8888/cookie-parser?0016",
+ &["z=y", "a=b"],
+ "http://home.example.org:8888/cookie-parser-result?0016");
+ assert_eq!(&r, "z=y; a=b");
+}
+
+#[test]
+fn test_0017() {
+ let r = run("http://home.example.org:8888/cookie-parser?0017",
+ &["z=y, a=b"],
+ "http://home.example.org:8888/cookie-parser-result?0017");
+ assert_eq!(&r, "z=y, a=b");
+}
+
+#[test]
+fn test_0018() {
+ let r = run("http://home.example.org:8888/cookie-parser?0018",
+ &["z=y; foo=bar, a=b"],
+ "http://home.example.org:8888/cookie-parser-result?0018");
+ assert_eq!(&r, "z=y");
+}
+
+#[test]
+fn test_0019() {
+ let r = run("http://home.example.org:8888/cookie-parser?0019",
+ &["foo=b;max-age=3600, c=d;path=/"],
+ "http://home.example.org:8888/cookie-parser-result?0019");
+ assert_eq!(&r, "foo=b");
+}
+
+#[test]
+fn test_0020() {
+ let r = run("http://home.example.org:8888/cookie-parser?0020",
+ &["a=b", "=", "c=d"],
+ "http://home.example.org:8888/cookie-parser-result?0020");
+ assert_eq!(&r, "a=b; c=d");
+}
+
+#[test]
+fn test_0021() {
+ let r = run("http://home.example.org:8888/cookie-parser?0021",
+ &["a=b", "=x", "c=d"],
+ "http://home.example.org:8888/cookie-parser-result?0021");
+ assert_eq!(&r, "a=b; c=d");
+}
+
+#[test]
+fn test_0022() {
+ let r = run("http://home.example.org:8888/cookie-parser?0022",
+ &["a=b", "x=", "c=d"],
+ "http://home.example.org:8888/cookie-parser-result?0022");
+ assert_eq!(&r, "a=b; x=; c=d");
+}
+
+#[test]
+fn test_0023() {
+ let r = run("http://home.example.org:8888/cookie-parser?0023",
+ &["foo"],
+ "http://home.example.org:8888/cookie-parser-result?0023");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_0024() {
+ let r = run("http://home.example.org:8888/cookie-parser?0024",
+ &["foo", "="],
+ "http://home.example.org:8888/cookie-parser-result?0024");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_0025() {
+ let r = run("http://home.example.org:8888/cookie-parser?0025",
+ &["foo", "; bar"],
+ "http://home.example.org:8888/cookie-parser-result?0025");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_0026() {
+ let r = run("http://home.example.org:8888/cookie-parser?0026",
+ &["foo"],
+ "http://home.example.org:8888/cookie-parser-result?0026");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_0027() {
+ let r = run("http://home.example.org:8888/cookie-parser?0027",
+ &["foo", "bar"],
+ "http://home.example.org:8888/cookie-parser-result?0027");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_0028() {
+ let r = run("http://home.example.org:8888/cookie-parser?0028",
+ &["foo"],
+ "http://home.example.org:8888/cookie-parser-result?0028");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0001",
+ &["foo=bar; Secure"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0001");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0002() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0002",
+ &["foo=bar; seCURe"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0002");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0003() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0003",
+ &["foo=bar; \"Secure\""],
+ "http://home.example.org:8888/cookie-parser-result?attribute0003");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_attribute0004() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0004",
+ &["foo=bar; Secure="],
+ "http://home.example.org:8888/cookie-parser-result?attribute0004");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0005() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0005",
+ &["foo=bar; Secure=aaaa"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0005");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0006() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0006",
+ &["foo=bar; Secure qux"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0006");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_attribute0007() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0007",
+ &["foo=bar; Secure =aaaaa"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0007");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0008() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0008",
+ &["foo=bar; Secure= aaaaa"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0008");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0009() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0009",
+ &["foo=bar; Secure; qux"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0009");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0010() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0010",
+ &["foo=bar; Secure;qux"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0010");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0011() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0011",
+ &["foo=bar; Secure ; qux"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0011");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0012() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0012",
+ &["foo=bar; Secure"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0012");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0013() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0013",
+ &["foo=bar; Secure ;"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0013");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0014() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0014",
+ &["foo=bar; Path"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0014");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_attribute0015() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0015",
+ &["foo=bar; Path="],
+ "http://home.example.org:8888/cookie-parser-result?attribute0015");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_attribute0016() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0016",
+ &["foo=bar; Path=/"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0016");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_attribute0017() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0017",
+ &["foo=bar; Path=/qux"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0017");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0018() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0018",
+ &["foo=bar; Path =/qux"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0018");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0019() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0019",
+ &["foo=bar; Path= /qux"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0019");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0020() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0020",
+ &["foo=bar; Path=/qux ; taz"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0020");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0021() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0021",
+ &["foo=bar; Path=/qux; Path=/"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0021");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_attribute0022() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0022",
+ &["foo=bar; Path=/; Path=/qux"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0022");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0023() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0023",
+ &["foo=bar; Path=/qux; Path=/cookie-parser-result"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0023");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_attribute0024() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0024",
+ &["foo=bar; Path=/cookie-parser-result; Path=/qux"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0024");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0025() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0025",
+ &["foo=bar; qux; Secure"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0025");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_attribute0026() {
+ let r = run("http://home.example.org:8888/cookie-parser?attribute0026",
+ &["foo=bar; qux=\"aaa;bbb\"; Secure"],
+ "http://home.example.org:8888/cookie-parser-result?attribute0026");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_charset0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?charset0001",
+ &["foo=\u{6625}\u{8282}\u{56de}\u{5bb6}\u{8def}\u{b7}\u{6625}\u{8fd0}\u{5b8c}\
+\u{5168}\u{624b}\u{518c}"],
+ "http://home.example.org:8888/cookie-parser-result?charset0001");
+ assert_eq!(&r, "foo=\u{6625}\u{8282}\u{56de}\u{5bb6}\u{8def}\u{b7}\u{6625}\u{8fd0}\u{5b8c}\
+\u{5168}\u{624b}\u{518c}");
+}
+
+#[test]
+fn test_charset0002() {
+ let r = run("http://home.example.org:8888/cookie-parser?charset0002",
+ &["\u{6625}\u{8282}\u{56de}=\u{5bb6}\u{8def}\u{b7}\u{6625}\u{8fd0}\u{5b8c}\
+\u{5168}\u{624b}\u{518c}"],
+ "http://home.example.org:8888/cookie-parser-result?charset0002");
+ assert_eq!(&r, "\u{6625}\u{8282}\u{56de}=\u{5bb6}\u{8def}\u{b7}\u{6625}\u{8fd0}\u{5b8c}\
+\u{5168}\u{624b}\u{518c}");
+}
+
+#[test]
+fn test_charset0003() {
+ let r = run("http://home.example.org:8888/cookie-parser?charset0003",
+ &["\u{6625}\u{8282}\u{56de}=\u{5bb6}\u{8def}\u{b7}\u{6625}\u{8fd0}; \u{5b8c}\
+\u{5168}\u{624b}\u{518c}"],
+ "http://home.example.org:8888/cookie-parser-result?charset0003");
+ assert_eq!(&r, "\u{6625}\u{8282}\u{56de}=\u{5bb6}\u{8def}\u{b7}\u{6625}\u{8fd0}");
+}
+
+#[test]
+fn test_charset0004() {
+ let r = run("http://home.example.org:8888/cookie-parser?charset0004",
+ &["foo=\"\u{6625}\u{8282}\u{56de}\u{5bb6}\u{8def}\u{b7}\u{6625}\u{8fd0}\u{5b8c}\
+\u{5168}\u{624b}\u{518c}\""],
+ "http://home.example.org:8888/cookie-parser-result?charset0004");
+ assert_eq!(&r, "foo=\"\u{6625}\u{8282}\u{56de}\u{5bb6}\u{8def}\u{b7}\u{6625}\u{8fd0}\u{5b8c}\
+\u{5168}\u{624b}\u{518c}\"");
+}
+
+#[test]
+fn test_chromium0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0001",
+ &["a=b"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0001");
+ assert_eq!(&r, "a=b");
+}
+
+#[test]
+fn test_chromium0002() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0002",
+ &["aBc=\"zzz \" ;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0002");
+ assert_eq!(&r, "aBc=\"zzz \"");
+}
+
+#[test]
+fn test_chromium0003() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0003",
+ &["aBc=\"zzz \" ;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0003");
+ assert_eq!(&r, "aBc=\"zzz \"");
+}
+
+#[test]
+fn test_chromium0004() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0004",
+ &["aBc=\"zz;pp\" ; ;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0004");
+ assert_eq!(&r, "aBc=\"zz");
+}
+
+#[test]
+fn test_chromium0005() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0005",
+ &["aBc=\"zz ;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0005");
+ assert_eq!(&r, "aBc=\"zz");
+}
+
+#[test]
+fn test_chromium0006() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0006",
+ &["aBc=\"zzz \" \"ppp\" ;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0006");
+ assert_eq!(&r, "aBc=\"zzz \" \"ppp\"");
+}
+
+#[test]
+fn test_chromium0007() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0007",
+ &["aBc=\"zzz \" \"ppp\" ;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0007");
+ assert_eq!(&r, "aBc=\"zzz \" \"ppp\"");
+}
+
+#[test]
+fn test_chromium0008() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0008",
+ &["aBc=A\"B ;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0008");
+ assert_eq!(&r, "aBc=A\"B");
+}
+
+#[test]
+fn test_chromium0009() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0009",
+ &["BLAHHH; path=/;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0009");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_chromium0010() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0010",
+ &["\"BLA\\\"HHH\"; path=/;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0010");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_chromium0011() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0011",
+ &["a=\"B"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0011");
+ assert_eq!(&r, "a=\"B");
+}
+
+#[test]
+fn test_chromium0012() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0012",
+ &["=ABC"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0012");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_chromium0013() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0013",
+ &["ABC=; path = /"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0013");
+ assert_eq!(&r, "ABC=");
+}
+
+#[test]
+fn test_chromium0014() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0014",
+ &[" A = BC ;foo;;; bar"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0014");
+ assert_eq!(&r, "A=BC");
+}
+
+#[test]
+fn test_chromium0015() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0015",
+ &[" A=== BC ;foo;;; bar"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0015");
+ assert_eq!(&r, "A=== BC");
+}
+
+#[test]
+fn test_chromium0016() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0016",
+ &["foo=\"zohNumRKgI0oxyhSsV3Z7D\" ; expires=Sun, 18-Apr-2027 21:06:29 GMT\
+ ; path=/ ;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0016");
+ assert_eq!(&r, "foo=\"zohNumRKgI0oxyhSsV3Z7D\"");
+}
+
+#[test]
+fn test_chromium0017() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0017",
+ &["foo=zohNumRKgI0oxyhSsV3Z7D ; expires=Sun, 18-Apr-2027 21:06:29 GMT ; p\
+ath=/ ;"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0017");
+ assert_eq!(&r, "foo=zohNumRKgI0oxyhSsV3Z7D");
+}
+
+#[test]
+fn test_chromium0018() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0018",
+ &[],
+ "http://home.example.org:8888/cookie-parser-result?chromium0018");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_chromium0019() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0019",
+ &["a=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"],
+ "http://home.example.org:8888/cookie-parser-result?chromium0019");
+ assert_eq!(&r, "a=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+}
+
+#[test]
+fn test_chromium0021() {
+ let r = run("http://home.example.org:8888/cookie-parser?chromium0021",
+ &[],
+ "http://home.example.org:8888/cookie-parser-result?chromium0021");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_comma0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?comma0001",
+ &["foo=bar, baz=qux"],
+ "http://home.example.org:8888/cookie-parser-result?comma0001");
+ assert_eq!(&r, "foo=bar, baz=qux");
+}
+
+#[test]
+fn test_comma0002() {
+ let r = run("http://home.example.org:8888/cookie-parser?comma0002",
+ &["foo=\"bar, baz=qux\""],
+ "http://home.example.org:8888/cookie-parser-result?comma0002");
+ assert_eq!(&r, "foo=\"bar, baz=qux\"");
+}
+
+#[test]
+fn test_comma0003() {
+ let r = run("http://home.example.org:8888/cookie-parser?comma0003",
+ &["foo=bar; b,az=qux"],
+ "http://home.example.org:8888/cookie-parser-result?comma0003");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_comma0004() {
+ let r = run("http://home.example.org:8888/cookie-parser?comma0004",
+ &["foo=bar; baz=q,ux"],
+ "http://home.example.org:8888/cookie-parser-result?comma0004");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_comma0005() {
+ let r = run("http://home.example.org:8888/cookie-parser?comma0005",
+ &["foo=bar; Max-Age=50,399"],
+ "http://home.example.org:8888/cookie-parser-result?comma0005");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_comma0006() {
+ let r = run("http://home.example.org:8888/cookie-parser?comma0006",
+ &["foo=bar; Expires=Fri, 07 Aug 2019 08:04:19 GMT"],
+ "http://home.example.org:8888/cookie-parser-result?comma0006");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_comma0007() {
+ let r = run("http://home.example.org:8888/cookie-parser?comma0007",
+ &["foo=bar; Expires=Fri 07 Aug 2019 08:04:19 GMT, baz=qux"],
+ "http://home.example.org:8888/cookie-parser-result?comma0007");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0001",
+ &["foo=bar; domain=home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0001");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0002() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0002",
+ &["foo=bar; domain=home.example.org"],
+ "http://sibling.example.org:8888/cookie-parser-result?domain0002");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0003() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0003",
+ &["foo=bar; domain=.home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0003");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0004() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0004",
+ &["foo=bar; domain=home.example.org"],
+ "http://subdomain.home.example.org:8888/cookie-parser-result?domain0004");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0005() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0005",
+ &["foo=bar; domain=.home.example.org"],
+ "http://subdomain.home.example.org:8888/cookie-parser-result?domain0005");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0006() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0006",
+ &["foo=bar; domain=.home.example.org"],
+ "http://sibling.example.org:8888/cookie-parser-result?domain0006");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0007() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0007",
+ &["foo=bar; domain=sibling.example.org"],
+ "http://sibling.example.org:8888/cookie-parser-result?domain0007");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0008() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0008",
+ &["foo=bar; domain=.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0008");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0009() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0009",
+ &["foo=bar; domain=example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0009");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0010() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0010",
+ &["foo=bar; domain=..home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0010");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0011() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0011",
+ &["foo=bar; domain=home..example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0011");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0012() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0012",
+ &["foo=bar; domain= .home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0012");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0013() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0013",
+ &["foo=bar; domain= . home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0013");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0014() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0014",
+ &["foo=bar; domain=home.example.org."],
+ "http://home.example.org:8888/cookie-parser-result?domain0014");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0015() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0015",
+ &["foo=bar; domain=home.example.org.."],
+ "http://home.example.org:8888/cookie-parser-result?domain0015");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0016() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0016",
+ &["foo=bar; domain=home.example.org ."],
+ "http://home.example.org:8888/cookie-parser-result?domain0016");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0017() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0017",
+ &["foo=bar; domain=.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0017");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0018() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0018",
+ &["foo=bar; domain=.org."],
+ "http://home.example.org:8888/cookie-parser-result?domain0018");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0019() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0019",
+ &["foo=bar; domain=home.example.org", "foo2=bar2; domain=.home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0019");
+ assert_eq!(&r, "foo=bar; foo2=bar2");
+}
+
+#[test]
+fn test_domain0020() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0020",
+ &["foo2=bar2; domain=.home.example.org", "foo=bar; domain=home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0020");
+ assert_eq!(&r, "foo2=bar2; foo=bar");
+}
+
+#[test]
+fn test_domain0021() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0021",
+ &["foo=bar; domain=\"home.example.org\""],
+ "http://home.example.org:8888/cookie-parser-result?domain0021");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0022() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0022",
+ &["foo=bar; domain=home.example.org", "foo2=bar2; domain=.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0022");
+ assert_eq!(&r, "foo=bar; foo2=bar2");
+}
+
+#[test]
+fn test_domain0023() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0023",
+ &["foo2=bar2; domain=.example.org", "foo=bar; domain=home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0023");
+ assert_eq!(&r, "foo2=bar2; foo=bar");
+}
+
+#[test]
+fn test_domain0024() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0024",
+ &["foo=bar; domain=.example.org; domain=home.example.org"],
+ "http://sibling.example.org:8888/cookie-parser-result?domain0024");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0025() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0025",
+ &["foo=bar; domain=home.example.org; domain=.example.org"],
+ "http://sibling.example.org:8888/cookie-parser-result?domain0025");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0026() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0026",
+ &["foo=bar; domain=home.eXaMpLe.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0026");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0027() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0027",
+ &["foo=bar; domain=home.example.org:8888"],
+ "http://home.example.org:8888/cookie-parser-result?domain0027");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0028() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0028",
+ &["foo=bar; domain=subdomain.home.example.org"],
+ "http://subdomain.home.example.org:8888/cookie-parser-result?domain0028");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0029() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0029",
+ &["foo=bar"],
+ "http://subdomain.home.example.org:8888/cookie-parser-result?domain0029");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0031() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0031",
+ &["foo=bar; domain=home.example.org; domain=.example.org"],
+ "http://sibling.example.org:8888/cookie-parser-result?domain0031");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0033() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0033",
+ &["foo=bar; domain=home.example.org"],
+ "http://hoMe.eXaMplE.org:8888/cookie-parser-result?domain0033");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0034() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0034",
+ &["foo=bar; domain=home.example.org; domain=home.example.com"],
+ "http://home.example.org:8888/cookie-parser-result?domain0034");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0035() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0035",
+ &["foo=bar; domain=home.example.com; domain=home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0035");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0036() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0036",
+ &["foo=bar; domain=home.example.org; domain=home.example.com; domain=home.\
+example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0036");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0037() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0037",
+ &["foo=bar; domain=home.example.com; domain=home.example.org; domain=home.\
+example.com"],
+ "http://home.example.org:8888/cookie-parser-result?domain0037");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0038() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0038",
+ &["foo=bar; domain=home.example.org; domain=home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0038");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0039() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0039",
+ &["foo=bar; domain=home.example.org; domain=example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0039");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0040() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0040",
+ &["foo=bar; domain=example.org; domain=home.example.org"],
+ "http://home.example.org:8888/cookie-parser-result?domain0040");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_domain0041() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0041",
+ &["foo=bar; domain=.sibling.example.org"],
+ "http://sibling.example.org:8888/cookie-parser-result?domain0041");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_domain0042() {
+ let r = run("http://home.example.org:8888/cookie-parser?domain0042",
+ &["foo=bar; domain=.sibling.home.example.org"],
+ "http://sibling.home.example.org:8888/cookie-parser-result?domain0042");
+ assert_eq!(&r, "");
+}
+
+#[test]
+#[should_panic] // Look at cookie_http_state_utils.py if this test fails
+fn test_mozilla0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0001",
+ &["foo=bar; max-age=-1"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0001");
+ assert_eq!(&r, "");
+}
+
+#[test]
+#[should_panic] // Look at cookie_http_state_utils.py if this test fails
+fn test_mozilla0002() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0002",
+ &["foo=bar; max-age=0"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0002");
+ assert_eq!(&r, "");
+}
+
+#[test]
+#[should_panic] // Look at cookie_http_state_utils.py if this test fails
+fn test_mozilla0003() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0003",
+ &["foo=bar; expires=Thu, 10 Apr 1980 16:33:12 GMT"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0003");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_mozilla0004() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0004",
+ &["foo=bar; max-age=60"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0004");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+#[should_panic] // Look at cookie_http_state_utils.py if this test fails
+fn test_mozilla0005() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0005",
+ &["foo=bar; max-age=-20"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0005");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_mozilla0006() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0006",
+ &["foo=bar; max-age=60"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0006");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+#[should_panic] // Look at cookie_http_state_utils.py if this test fails
+fn test_mozilla0007() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0007",
+ &["foo=bar; expires=Thu, 10 Apr 1980 16:33:12 GMT"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0007");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_mozilla0008() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0008",
+ &["foo=bar; max-age=60", "foo1=bar; max-age=60"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0008");
+ assert_eq!(&r, "foo=bar; foo1=bar");
+}
+
+#[test]
+#[should_panic] // Look at cookie_http_state_utils.py if this test fails
+fn test_mozilla0009() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0009",
+ &["foo=bar; max-age=60", "foo1=bar; max-age=60", "foo=differentvalue; max-age=0"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0009");
+ assert_eq!(&r, "foo1=bar");
+}
+
+#[test]
+#[should_panic] // Look at cookie_http_state_utils.py if this test fails
+fn test_mozilla0010() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0010",
+ &["foo=bar; max-age=60",
+ "foo1=bar; max-age=60",
+ "foo=differentvalue; max-age=0",
+ "foo2=evendifferentvalue; max-age=0"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0010");
+ assert_eq!(&r, "foo1=bar");
+}
+
+#[test]
+fn test_mozilla0011() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0011",
+ &["test=parser; domain=.parser.test; ;; ;=; ,,, ===,abc,=; abracadabra! ma\
+x-age=20;=;;"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0011");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_mozilla0012() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0012",
+ &["test=\"fubar! = foo;bar\\\";\" parser; max-age=6", "five; max-age=2.63,"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0012");
+ assert_eq!(&r, "test=\"fubar! = foo");
+}
+
+#[test]
+#[should_panic] // Look at cookie_http_state_utils.py if this test fails
+fn test_mozilla0013() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0013",
+ &["test=kill; max-age=0", "five; max-age=0"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0013");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_mozilla0014() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0014",
+ &["six"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0014");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_mozilla0015() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0015",
+ &["six", "seven"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0015");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_mozilla0016() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0016",
+ &["six", "seven", " =eight"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0016");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_mozilla0017() {
+ let r = run("http://home.example.org:8888/cookie-parser?mozilla0017",
+ &["six", "seven", " =eight", "test=six"],
+ "http://home.example.org:8888/cookie-parser-result?mozilla0017");
+ assert_eq!(&r, "test=six");
+}
+
+#[test]
+fn test_name0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0001",
+ &["a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0001");
+ assert_eq!(&r, "a=bar");
+}
+
+#[test]
+fn test_name0002() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0002",
+ &["1=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0002");
+ assert_eq!(&r, "1=bar");
+}
+
+#[test]
+fn test_name0003() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0003",
+ &["$=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0003");
+ assert_eq!(&r, "$=bar");
+}
+
+#[test]
+fn test_name0004() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0004",
+ &["!a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0004");
+ assert_eq!(&r, "!a=bar");
+}
+
+#[test]
+fn test_name0005() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0005",
+ &["@a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0005");
+ assert_eq!(&r, "@a=bar");
+}
+
+#[test]
+fn test_name0006() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0006",
+ &["#a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0006");
+ assert_eq!(&r, "#a=bar");
+}
+
+#[test]
+fn test_name0007() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0007",
+ &["$a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0007");
+ assert_eq!(&r, "$a=bar");
+}
+
+#[test]
+fn test_name0008() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0008",
+ &["%a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0008");
+ assert_eq!(&r, "%a=bar");
+}
+
+#[test]
+fn test_name0009() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0009",
+ &["^a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0009");
+ assert_eq!(&r, "^a=bar");
+}
+
+#[test]
+fn test_name0010() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0010",
+ &["&a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0010");
+ assert_eq!(&r, "&a=bar");
+}
+
+#[test]
+fn test_name0011() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0011",
+ &["*a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0011");
+ assert_eq!(&r, "*a=bar");
+}
+
+#[test]
+fn test_name0012() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0012",
+ &["(a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0012");
+ assert_eq!(&r, "(a=bar");
+}
+
+#[test]
+fn test_name0013() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0013",
+ &[")a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0013");
+ assert_eq!(&r, ")a=bar");
+}
+
+#[test]
+fn test_name0014() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0014",
+ &["-a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0014");
+ assert_eq!(&r, "-a=bar");
+}
+
+#[test]
+fn test_name0015() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0015",
+ &["_a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0015");
+ assert_eq!(&r, "_a=bar");
+}
+
+#[test]
+fn test_name0016() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0016",
+ &["+=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0016");
+ assert_eq!(&r, "+=bar");
+}
+
+#[test]
+fn test_name0017() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0017",
+ &["=a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0017");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_name0018() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0018",
+ &["a =bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0018");
+ assert_eq!(&r, "a=bar");
+}
+
+#[test]
+fn test_name0019() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0019",
+ &["\"a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0019");
+ assert_eq!(&r, "\"a=bar");
+}
+
+#[test]
+fn test_name0020() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0020",
+ &["\"a=b\"=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0020");
+ assert_eq!(&r, "\"a=b\"=bar");
+}
+
+#[test]
+fn test_name0021() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0021",
+ &["\"a=b\"=bar", "\"a=qux"],
+ "http://home.example.org:8888/cookie-parser-result?name0021");
+ assert_eq!(&r, "\"a=qux");
+}
+
+#[test]
+fn test_name0022() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0022",
+ &[" foo=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0022");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_name0023() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0023",
+ &["foo;bar=baz"],
+ "http://home.example.org:8888/cookie-parser-result?name0023");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_name0024() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0024",
+ &["$Version=1; foo=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0024");
+ assert_eq!(&r, "$Version=1");
+}
+
+#[test]
+fn test_name0025() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0025",
+ &["===a=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0025");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_name0026() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0026",
+ &["foo=bar"],
+ "http://home.example.org:8888/cookie-parser-result?name0026");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_name0027() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0027",
+ &["foo=bar ;"],
+ "http://home.example.org:8888/cookie-parser-result?name0027");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_name0028() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0028",
+ &["=a"],
+ "http://home.example.org:8888/cookie-parser-result?name0028");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_name0029() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0029",
+ &["="],
+ "http://home.example.org:8888/cookie-parser-result?name0029");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_name0030() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0030",
+ &["foo bar=baz"],
+ "http://home.example.org:8888/cookie-parser-result?name0030");
+ assert_eq!(&r, "foo bar=baz");
+}
+
+#[test]
+fn test_name0031() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0031",
+ &["\"foo;bar\"=baz"],
+ "http://home.example.org:8888/cookie-parser-result?name0031");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_name0032() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0032",
+ &["\"foo\\\"bar;baz\"=qux"],
+ "http://home.example.org:8888/cookie-parser-result?name0032");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_name0033() {
+ let r = run("http://home.example.org:8888/cookie-parser?name0033",
+ &["=foo=bar", "aaa"],
+ "http://home.example.org:8888/cookie-parser-result?name0033");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_optional_domain0030() {
+ let r = run("http://home.example.org:8888/cookie-parser?optional-domain0030",
+ &["foo=bar; domain="],
+ "http://home.example.org:8888/cookie-parser-result?optional-domain0030");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_optional_domain0041() {
+ let r = run("http://home.example.org:8888/cookie-parser?optional-domain0041",
+ &["foo=bar; domain=example.org; domain="],
+ "http://home.example.org:8888/cookie-parser-result?optional-domain0041");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_optional_domain0042() {
+ let r = run("http://home.example.org:8888/cookie-parser?optional-domain0042",
+ &["foo=bar; domain=foo.example.org; domain="],
+ "http://home.example.org:8888/cookie-parser-result?optional-domain0042");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_optional_domain0043() {
+ let r = run("http://home.example.org:8888/cookie-parser?optional-domain0043",
+ &["foo=bar; domain=foo.example.org; domain="],
+ "http://subdomain.home.example.org:8888/cookie-parser-result?optional-do\
+main0043");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_ordering0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?ordering0001",
+ &["key=val0;",
+ "key=val1; path=/cookie-parser-result",
+ "key=val2; path=/",
+ "key=val3; path=/bar",
+ "key=val4; domain=.example.org",
+ "key=val5; domain=.example.org; path=/cookie-parser-result/foo"],
+ "http://home.example.org:8888/cookie-parser-result/foo/baz?ordering0001");
+ assert_eq!(&r, "key=val5; key=val1; key=val2; key=val4");
+}
+
+#[test]
+fn test_path0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0001",
+ &["a=b; path=/", "x=y; path=/cookie-parser-result"],
+ "http://home.example.org:8888/cookie-parser-result?path0001");
+ assert_eq!(&r, "x=y; a=b");
+}
+
+#[test]
+fn test_path0002() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0002",
+ &["a=b; path=/cookie-parser-result", "x=y; path=/"],
+ "http://home.example.org:8888/cookie-parser-result?path0002");
+ assert_eq!(&r, "a=b; x=y");
+}
+
+#[test]
+fn test_path0003() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0003",
+ &["x=y; path=/", "a=b; path=/cookie-parser-result"],
+ "http://home.example.org:8888/cookie-parser-result?path0003");
+ assert_eq!(&r, "a=b; x=y");
+}
+
+#[test]
+fn test_path0004() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0004",
+ &["x=y; path=/cookie-parser-result", "a=b; path=/"],
+ "http://home.example.org:8888/cookie-parser-result?path0004");
+ assert_eq!(&r, "x=y; a=b");
+}
+
+#[test]
+fn test_path0005() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0005",
+ &["foo=bar; path=/cookie-parser-result/foo"],
+ "http://home.example.org:8888/cookie-parser-result?path0005");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0006() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0006",
+ &["foo=bar", "foo=qux; path=/cookie-parser-result/foo"],
+ "http://home.example.org:8888/cookie-parser-result?path0006");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0007() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0007",
+ &["foo=bar; path=/cookie-parser-result/foo"],
+ "http://home.example.org:8888/cookie-parser-result/foo?path0007");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0008() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0008",
+ &["foo=bar; path=/cookie-parser-result/foo"],
+ "http://home.example.org:8888/cookie-parser-result/bar?path0008");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0009() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0009",
+ &["foo=bar; path=/cookie-parser-result/foo/qux"],
+ "http://home.example.org:8888/cookie-parser-result/foo?path0009");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0010() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0010",
+ &["foo=bar; path=/cookie-parser-result/foo/qux"],
+ "http://home.example.org:8888/cookie-parser-result/foo/qux?path0010");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0011() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0011",
+ &["foo=bar; path=/cookie-parser-result/foo/qux"],
+ "http://home.example.org:8888/cookie-parser-result/bar/qux?path0011");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0012() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0012",
+ &["foo=bar; path=/cookie-parser-result/foo/qux"],
+ "http://home.example.org:8888/cookie-parser-result/foo/baz?path0012");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0013() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0013",
+ &["foo=bar; path=/cookie-parser-result/foo/qux/"],
+ "http://home.example.org:8888/cookie-parser-result/foo/baz?path0013");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0014() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0014",
+ &["foo=bar; path=/cookie-parser-result/foo/qux/"],
+ "http://home.example.org:8888/cookie-parser-result/foo/qux?path0014");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0015() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0015",
+ &["foo=bar; path=/cookie-parser-result/foo/qux/"],
+ "http://home.example.org:8888/cookie-parser-result/foo/qux/?path0015");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0016() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0016",
+ &["foo=bar; path=/cookie-parser-result/foo/"],
+ "http://home.example.org:8888/cookie-parser-result/foo/qux?path0016");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0017() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0017",
+ &["foo=bar; path=/cookie-parser-result/foo/"],
+ "http://home.example.org:8888/cookie-parser-result/foo//qux?path0017");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0018() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0018",
+ &["foo=bar; path=/cookie-parser-result/foo/"],
+ "http://home.example.org:8888/cookie-parser-result/fooqux?path0018");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0019() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0019",
+ &["foo=bar; path"],
+ "http://home.example.org:8888/cookie-parser-result?path0019");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0020() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0020",
+ &["foo=bar; path="],
+ "http://home.example.org:8888/cookie-parser-result?path0020");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0021() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0021",
+ &["foo=bar; path=/"],
+ "http://home.example.org:8888/cookie-parser-result?path0021");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0022() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0022",
+ &["foo=bar; path= /"],
+ "http://home.example.org:8888/cookie-parser-result?path0022");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0023() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0023",
+ &["foo=bar; Path=/cookie-PARSER-result"],
+ "http://home.example.org:8888/cookie-parser-result?path0023");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0024() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0024",
+ &["foo=bar; path=/cookie-parser-result/foo/qux?"],
+ "http://home.example.org:8888/cookie-parser-result/foo/qux?path0024");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0025() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0025",
+ &["foo=bar; path=/cookie-parser-result/foo/qux#"],
+ "http://home.example.org:8888/cookie-parser-result/foo/qux?path0025");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0026() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0026",
+ &["foo=bar; path=/cookie-parser-result/foo/qux;"],
+ "http://home.example.org:8888/cookie-parser-result/foo/qux?path0026");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0027() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0027",
+ &["foo=bar; path=\"/cookie-parser-result/foo/qux;\""],
+ "http://home.example.org:8888/cookie-parser-result/foo/qux?path0027");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0028() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0028",
+ &["foo=bar; path=/cookie-parser-result/f%6Fo/bar"],
+ "http://home.example.org:8888/cookie-parser-result/foo/bar?path0028");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0029() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0029",
+ &["a=b; \tpath\t=\t/cookie-parser-result", "x=y; \tpath\t=\t/book"],
+ "http://home.example.org:8888/cookie-parser-result?path0029");
+ assert_eq!(&r, "a=b");
+}
+
+#[test]
+fn test_path0030() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0030",
+ &["foo=bar; path=/dog; path="],
+ "http://home.example.org:8888/cookie-parser-result?path0030");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_path0031() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0031",
+ &["foo=bar; path=; path=/dog"],
+ "http://home.example.org:8888/cookie-parser-result?path0031");
+ assert_eq!(&r, "");
+}
+
+#[test]
+fn test_path0032() {
+ let r = run("http://home.example.org:8888/cookie-parser?path0032",
+ &["foo=bar; path=/cookie-parser-result", "foo=qux; path=/cookie-parser-result/"],
+ "http://home.example.org:8888/cookie-parser-result/dog?path0032");
+ assert_eq!(&r, "foo=qux; foo=bar");
+}
+
+#[test]
+fn test_value0001() {
+ let r = run("http://home.example.org:8888/cookie-parser?value0001",
+ &["foo= bar"],
+ "http://home.example.org:8888/cookie-parser-result?value0001");
+ assert_eq!(&r, "foo=bar");
+}
+
+#[test]
+fn test_value0002() {
+ let r = run("http://home.example.org:8888/cookie-parser?value0002",
+ &["foo=\"bar\""],
+ "http://home.example.org:8888/cookie-parser-result?value0002");
+ assert_eq!(&r, "foo=\"bar\"");
+}
+
+#[test]
+fn test_value0003() {
+ let r = run("http://home.example.org:8888/cookie-parser?value0003",
+ &["foo=\" bar \""],
+ "http://home.example.org:8888/cookie-parser-result?value0003");
+ assert_eq!(&r, "foo=\" bar \"");
+}
+
+#[test]
+fn test_value0004() {
+ let r = run("http://home.example.org:8888/cookie-parser?value0004",
+ &["foo=\"bar;baz\""],
+ "http://home.example.org:8888/cookie-parser-result?value0004");
+ assert_eq!(&r, "foo=\"bar");
+}
+
+#[test]
+fn test_value0005() {
+ let r = run("http://home.example.org:8888/cookie-parser?value0005",
+ &["foo=\"bar=baz\""],
+ "http://home.example.org:8888/cookie-parser-result?value0005");
+ assert_eq!(&r, "foo=\"bar=baz\"");
+}
+
+#[test]
+fn test_value0006() {
+ let r = run("http://home.example.org:8888/cookie-parser?value0006",
+ &["\tfoo\t=\tbar\t \t;\tttt"],
+ "http://home.example.org:8888/cookie-parser-result?value0006");
+ assert_eq!(&r, "foo=bar");
+}
diff --git a/components/net/tests/cookie_http_state_utils.py b/components/net/tests/cookie_http_state_utils.py
new file mode 100644
index 00000000000..b8820c312da
--- /dev/null
+++ b/components/net/tests/cookie_http_state_utils.py
@@ -0,0 +1,174 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import os
+import subprocess
+import tempfile
+
+REPO = "https://github.com/abarth/http-state.git"
+TEST_FILE = "cookie_http_state.rs"
+DOMAIN = "http://home.example.org:8888"
+RUST_FN = """
+#[test]{should_panic}
+fn test_{name}() {{
+ let r = run("{set_location}",
+ {set_cookies},
+ "{location}");
+ assert_eq!(&r, "{expect}");
+}}
+"""
+SET_COOKIES_INDENT = 18
+SHOULD_PANIC = "\n#[should_panic] // Look at cookie_http_state_utils.py if this test fails"
+
+# Those tests should PASS. But until fixes land in servo, keep them failing
+FAILING_TESTS = [
+ "0003", # Waiting for a way to clean expired cookies
+ "0006", # Waiting for a way to clean expired cookies
+ "mozilla0001", # Waiting for a way to clean expired cookies
+ "mozilla0002", # Waiting for a way to clean expired cookies
+ "mozilla0003", # Waiting for a way to clean expired cookies
+ "mozilla0005", # Waiting for a way to clean expired cookies
+ "mozilla0007", # Waiting for a way to clean expired cookies
+ "mozilla0009", # Waiting for a way to clean expired cookies
+ "mozilla0010", # Waiting for a way to clean expired cookies
+ "mozilla0013", # Waiting for a way to clean expired cookies
+]
+
+
+def list_tests(dir):
+ suffix = "-test"
+
+ def keep(name):
+ return name.endswith(suffix) and not name.startswith("disabled")
+
+ tests = [name[:-len(suffix)] for name in os.listdir(dir) if keep(name)]
+ tests.sort()
+ return tests
+
+
+def escape(s):
+ """ Escape the string `s` so that it can be parsed by rust as a valid
+ UTF-8 string.
+ We can't use only `encode("unicode_escape")` as it produces things that
+ rust does not accept ("\\xbf", "\\u6265" for example). So we manually
+ convert all character whose code point is greater than 128 to
+ \\u{code_point}.
+ All other characters are encoded with "unicode_escape" to get escape
+ sequences ("\\r" for example) except for `"` that we specifically escape
+ because our string will be quoted by double-quotes.
+ Lines are also limited in size, so split the string every 70 characters
+ (gives room for indentation).
+ """
+ res = ""
+ last_split = 0
+ for c in s:
+ if len(res) - last_split > 70:
+ res += "\\\n"
+ last_split = len(res)
+ o = ord(c)
+ if o == 34:
+ res += "\\\""
+ continue
+ if o >= 128:
+ res += "\\u{" + hex(o)[2:] + "}"
+ else:
+ res += c.encode("unicode_escape")
+ return res
+
+
+def format_slice_cookies(cookies):
+ esc_cookies = ['"%s"' % escape(c) for c in cookies]
+ if sum(len(s) for s in esc_cookies) < 80:
+ sep = ", "
+ else:
+ sep = ",\n" + " " * SET_COOKIES_INDENT
+ return "&[" + sep.join(esc_cookies) + "]"
+
+
+def generate_code_for_test(test_dir, name):
+ if name in FAILING_TESTS:
+ should_panic = SHOULD_PANIC
+ else:
+ should_panic = ""
+
+ test_file = os.path.join(test_dir, name + "-test")
+ expect_file = os.path.join(test_dir, name + "-expected")
+
+ set_cookies = []
+ set_location = DOMAIN + "/cookie-parser?" + name
+ expect = ""
+ location = DOMAIN + "/cookie-parser-result?" + name
+
+ with open(test_file) as fo:
+ for line in fo:
+ line = line.decode("utf-8").rstrip()
+ prefix = "Set-Cookie: "
+ if line.startswith(prefix):
+ set_cookies.append(line[len(prefix):])
+ prefix = "Location: "
+ if line.startswith(prefix):
+ location = line[len(prefix):]
+ if location.startswith("/"):
+ location = DOMAIN + location
+
+ with open(expect_file) as fo:
+ for line in fo:
+ line = line.decode("utf-8").rstrip()
+ prefix = "Cookie: "
+ if line.startswith(prefix):
+ expect = line[len(prefix):]
+
+ return RUST_FN.format(name=name.replace('-', '_'),
+ set_location=escape(set_location),
+ set_cookies=format_slice_cookies(set_cookies),
+ should_panic=should_panic,
+ location=escape(location),
+ expect=escape(expect))
+
+
+def update_test_file(cachedir):
+ workdir = os.path.dirname(os.path.realpath(__file__))
+ test_file = os.path.join(workdir, TEST_FILE)
+
+ # Create the cache dir
+ if not os.path.isdir(cachedir):
+ os.makedirs(cachedir)
+
+ # Clone or update the repo
+ repo_dir = os.path.join(cachedir, "http-state")
+ if os.path.isdir(repo_dir):
+ args = ["git", "pull", "-f"]
+ process = subprocess.Popen(args, cwd=repo_dir)
+ if process.wait() != 0:
+ print("failed to update the http-state git repo")
+ return 1
+ else:
+ args = ["git", "clone", REPO, repo_dir]
+ process = subprocess.Popen(args)
+ if process.wait() != 0:
+ print("failed to clone the http-state git repo")
+ return 1
+
+ # Truncate the unit test file to remove all existing tests
+ with open(test_file, "r+") as fo:
+ while True:
+ line = fo.readline()
+ if line.strip() == "// Test listing":
+ fo.truncate()
+ fo.flush()
+ break
+ if line == "":
+ print("Failed to find listing delimiter on unit test file")
+ return 1
+
+ # Append all tests to unit test file
+ tests_dir = os.path.join(repo_dir, "tests", "data", "parser")
+ with open(test_file, "a") as fo:
+ for test in list_tests(tests_dir):
+ fo.write(generate_code_for_test(tests_dir, test).encode("utf-8"))
+
+ return 0
+
+if __name__ == "__main__":
+ update_test_file(tempfile.gettempdir())
diff --git a/components/net/tests/data_loader.rs b/components/net/tests/data_loader.rs
new file mode 100644
index 00000000000..4ad73dee080
--- /dev/null
+++ b/components/net/tests/data_loader.rs
@@ -0,0 +1,139 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use fetch;
+use hyper::header::ContentType;
+use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value};
+use hyper_serde::Serde;
+use net_traits::{FetchMetadata, FilteredMetadata, NetworkError};
+use net_traits::request::{Origin, Request};
+use net_traits::response::ResponseBody;
+use servo_url::ServoUrl;
+use std::ops::Deref;
+
+#[cfg(test)]
+fn assert_parse(url: &'static str,
+ content_type: Option<ContentType>,
+ charset: Option<&str>,
+ data: Option<&[u8]>) {
+ let url = ServoUrl::parse(url).unwrap();
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+
+ let response = fetch(&mut request, None);
+
+ match data {
+ Some(data) => {
+ assert!(!response.is_network_error());
+ assert_eq!(response.headers.len(), 1);
+
+ let header_content_type = response.headers.get::<ContentType>();
+ assert_eq!(header_content_type, content_type.as_ref());
+
+ let metadata = match response.metadata() {
+ Ok(FetchMetadata::Filtered { filtered: FilteredMetadata::Basic(m), .. }) => m,
+ result => panic!(result),
+ };
+ assert_eq!(metadata.content_type.map(Serde::into_inner), content_type);
+ assert_eq!(metadata.charset.as_ref().map(String::deref), charset);
+
+ let resp_body = response.body.lock().unwrap();
+ match *resp_body {
+ ResponseBody::Done(ref val) => {
+ assert_eq!(val, &data);
+ },
+ _ => panic!(),
+ }
+ },
+ None => {
+ assert!(response.is_network_error());
+ assert_eq!(response.metadata().err(), Some(NetworkError::Internal("Decoding data URL failed".to_owned())));
+ },
+ }
+}
+
+#[test]
+fn empty_invalid() {
+ assert_parse("data:", None, None, None);
+}
+
+#[test]
+fn plain() {
+ assert_parse(
+ "data:,hello%20world",
+ Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain,
+ vec!((Attr::Charset, Value::Ext("US-ASCII".to_owned())))))),
+ Some("US-ASCII"),
+ Some(b"hello world"));
+}
+
+#[test]
+fn plain_ct() {
+ assert_parse(
+ "data:text/plain,hello",
+ Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain, vec!()))),
+ None,
+ Some(b"hello"));
+}
+
+#[test]
+fn plain_html() {
+ assert_parse(
+ "data:text/html,<p>Servo</p>",
+ Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec!()))),
+ None,
+ Some(b"<p>Servo</p>"));
+}
+
+#[test]
+fn plain_charset() {
+ assert_parse(
+ "data:text/plain;charset=latin1,hello",
+ Some(ContentType(Mime(TopLevel::Text,
+ SubLevel::Plain,
+ vec!((Attr::Charset, Value::Ext("latin1".to_owned())))))),
+ Some("latin1"),
+ Some(b"hello"));
+}
+
+#[test]
+fn plain_only_charset() {
+ assert_parse(
+ "data:;charset=utf-8,hello",
+ Some(ContentType(Mime(TopLevel::Text,
+ SubLevel::Plain,
+ vec!((Attr::Charset, Value::Utf8))))),
+ Some("utf-8"),
+ Some(b"hello"));
+}
+
+#[test]
+fn base64() {
+ assert_parse(
+ "data:;base64,C62+7w==",
+ Some(ContentType(Mime(TopLevel::Text,
+ SubLevel::Plain,
+ vec!((Attr::Charset, Value::Ext("US-ASCII".to_owned())))))),
+ Some("US-ASCII"),
+ Some(&[0x0B, 0xAD, 0xBE, 0xEF]));
+}
+
+#[test]
+fn base64_ct() {
+ assert_parse(
+ "data:application/octet-stream;base64,C62+7w==",
+ Some(ContentType(Mime(TopLevel::Application, SubLevel::Ext("octet-stream".to_owned()), vec!()))),
+ None,
+ Some(&[0x0B, 0xAD, 0xBE, 0xEF]));
+}
+
+#[test]
+fn base64_charset() {
+ assert_parse(
+ "data:text/plain;charset=koi8-r;base64,8PLl9+XkIO3l5Pfl5A==",
+ Some(ContentType(Mime(TopLevel::Text, SubLevel::Plain,
+ vec!((Attr::Charset, Value::Ext("koi8-r".to_owned())))))),
+ Some("koi8-r"),
+ Some(&[0xF0, 0xF2, 0xE5, 0xF7, 0xE5, 0xE4, 0x20, 0xED, 0xE5, 0xE4, 0xF7, 0xE5, 0xE4]));
+}
diff --git a/components/net/tests/fetch.rs b/components/net/tests/fetch.rs
new file mode 100644
index 00000000000..02ae6d0e6e5
--- /dev/null
+++ b/components/net/tests/fetch.rs
@@ -0,0 +1,982 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use {DEFAULT_USER_AGENT, new_fetch_context, fetch, make_server};
+use devtools_traits::DevtoolsControlMsg;
+use devtools_traits::HttpRequest as DevtoolsHttpRequest;
+use devtools_traits::HttpResponse as DevtoolsHttpResponse;
+use fetch_with_context;
+use fetch_with_cors_cache;
+use http_loader::{expect_devtools_http_request, expect_devtools_http_response};
+use hyper::LanguageTag;
+use hyper::header::{Accept, AccessControlAllowCredentials, AccessControlAllowHeaders, AccessControlAllowOrigin};
+use hyper::header::{AcceptEncoding, AcceptLanguage, AccessControlAllowMethods, AccessControlMaxAge};
+use hyper::header::{AccessControlRequestHeaders, AccessControlRequestMethod, Date, UserAgent};
+use hyper::header::{CacheControl, ContentLanguage, ContentLength, ContentType, Expires, LastModified};
+use hyper::header::{Encoding, Location, Pragma, Quality, QualityItem, SetCookie, qitem};
+use hyper::header::{Headers, Host, HttpDate, Referer as HyperReferer};
+use hyper::method::Method;
+use hyper::mime::{Mime, SubLevel, TopLevel};
+use hyper::server::{Request as HyperRequest, Response as HyperResponse, Server};
+use hyper::status::StatusCode;
+use hyper::uri::RequestUri;
+use hyper_openssl;
+use msg::constellation_msg::TEST_PIPELINE_ID;
+use net::connector::create_ssl_client;
+use net::fetch::cors_cache::CorsCache;
+use net::fetch::methods::{CancellationListener, FetchContext};
+use net::filemanager_thread::FileManager;
+use net::hsts::HstsEntry;
+use net::test::HttpState;
+use net_traits::IncludeSubdomains;
+use net_traits::NetworkError;
+use net_traits::ReferrerPolicy;
+use net_traits::request::{Destination, Origin, RedirectMode, Referrer, Request, RequestMode};
+use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
+use servo_config::resource_files::resources_dir_path;
+use servo_url::{ImmutableOrigin, ServoUrl};
+use std::fs::File;
+use std::io::Read;
+use std::sync::{Arc, Mutex};
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::mpsc::{Sender, channel};
+use time::{self, Duration};
+use unicase::UniCase;
+
+// TODO write a struct that impls Handler for storing test values
+
+#[test]
+fn test_fetch_response_is_not_network_error() {
+ static MESSAGE: &'static [u8] = b"";
+ let handler = move |_: HyperRequest, response: HyperResponse| {
+ response.send(MESSAGE).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ let fetch_response = fetch(&mut request, None);
+ let _ = server.close();
+
+ if fetch_response.is_network_error() {
+ panic!("fetch response shouldn't be a network error");
+ }
+}
+
+#[test]
+fn test_fetch_on_bad_port_is_network_error() {
+ let url = ServoUrl::parse("http://www.example.org:6667").unwrap();
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ let fetch_response = fetch(&mut request, None);
+ assert!(fetch_response.is_network_error());
+ let fetch_error = fetch_response.get_network_error().unwrap();
+ assert!(fetch_error == &NetworkError::Internal("Request attempted on bad port".into()))
+}
+
+#[test]
+fn test_fetch_response_body_matches_const_message() {
+ static MESSAGE: &'static [u8] = b"Hello World!";
+ let handler = move |_: HyperRequest, response: HyperResponse| {
+ response.send(MESSAGE).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ let fetch_response = fetch(&mut request, None);
+ let _ = server.close();
+
+ assert!(!fetch_response.is_network_error());
+ assert_eq!(fetch_response.response_type, ResponseType::Basic);
+
+ match *fetch_response.body.lock().unwrap() {
+ ResponseBody::Done(ref body) => {
+ assert_eq!(&**body, MESSAGE);
+ },
+ _ => panic!()
+ };
+}
+
+#[test]
+fn test_fetch_aboutblank() {
+ let url = ServoUrl::parse("about:blank").unwrap();
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ let fetch_response = fetch(&mut request, None);
+ assert!(!fetch_response.is_network_error());
+ assert!(*fetch_response.body.lock().unwrap() == ResponseBody::Done(vec![]));
+}
+
+#[test]
+fn test_fetch_blob() {
+ use ipc_channel::ipc;
+ use net_traits::blob_url_store::BlobBuf;
+
+ let context = new_fetch_context(None);
+
+ let bytes = b"content";
+ let blob_buf = BlobBuf {
+ filename: Some("test.txt".into()),
+ type_string: "text/plain".into(),
+ size: bytes.len() as u64,
+ bytes: bytes.to_vec(),
+ };
+
+ let origin = ServoUrl::parse("http://www.example.org/").unwrap();
+
+ let (sender, receiver) = ipc::channel().unwrap();
+ context.filemanager.promote_memory(blob_buf, true, sender, "http://www.example.org".into());
+ let id = receiver.recv().unwrap().unwrap();
+ let url = ServoUrl::parse(&format!("blob:{}{}", origin.as_str(), id.simple())).unwrap();
+
+
+ let mut request = Request::new(url, Some(Origin::Origin(origin.origin())), None);
+ let fetch_response = fetch_with_context(&mut request, &context);
+
+ assert!(!fetch_response.is_network_error());
+
+ assert_eq!(fetch_response.headers.len(), 2);
+
+ let content_type: &ContentType = fetch_response.headers.get().unwrap();
+ assert_eq!(**content_type, Mime(TopLevel::Text, SubLevel::Plain, vec![]));
+
+ let content_length: &ContentLength = fetch_response.headers.get().unwrap();
+ assert_eq!(**content_length, bytes.len() as u64);
+
+ assert_eq!(*fetch_response.body.lock().unwrap(),
+ ResponseBody::Done(bytes.to_vec()));
+}
+
+#[test]
+fn test_fetch_file() {
+ let mut path = resources_dir_path().expect("Cannot find resource dir");
+ path.push("servo.css");
+
+ let url = ServoUrl::from_file_path(path.clone()).unwrap();
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+
+ let fetch_response = fetch(&mut request, None);
+ assert!(!fetch_response.is_network_error());
+ assert_eq!(fetch_response.headers.len(), 1);
+ let content_type: &ContentType = fetch_response.headers.get().unwrap();
+ assert!(**content_type == Mime(TopLevel::Text, SubLevel::Css, vec![]));
+
+ let resp_body = fetch_response.body.lock().unwrap();
+ let mut file = File::open(path).unwrap();
+ let mut bytes = vec![];
+ let _ = file.read_to_end(&mut bytes);
+
+ match *resp_body {
+ ResponseBody::Done(ref val) => {
+ assert_eq!(val, &bytes);
+ },
+ _ => panic!()
+ }
+}
+
+#[test]
+fn test_fetch_ftp() {
+ let url = ServoUrl::parse("ftp://not-supported").unwrap();
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ let fetch_response = fetch(&mut request, None);
+ assert!(fetch_response.is_network_error());
+}
+
+#[test]
+fn test_fetch_bogus_scheme() {
+ let url = ServoUrl::parse("bogus://whatever").unwrap();
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ let fetch_response = fetch(&mut request, None);
+ assert!(fetch_response.is_network_error());
+}
+
+#[test]
+fn test_cors_preflight_fetch() {
+ static ACK: &'static [u8] = b"ACK";
+ let state = Arc::new(AtomicUsize::new(0));
+ let handler = move |request: HyperRequest, mut response: HyperResponse| {
+ if request.method == Method::Options && state.clone().fetch_add(1, Ordering::SeqCst) == 0 {
+ assert!(request.headers.has::<AccessControlRequestMethod>());
+ assert!(!request.headers.has::<AccessControlRequestHeaders>());
+ assert!(!request.headers.get::<HyperReferer>().unwrap().contains("a.html"));
+ response.headers_mut().set(AccessControlAllowOrigin::Any);
+ response.headers_mut().set(AccessControlAllowCredentials);
+ response.headers_mut().set(AccessControlAllowMethods(vec![Method::Get]));
+ } else {
+ response.headers_mut().set(AccessControlAllowOrigin::Any);
+ response.send(ACK).unwrap();
+ }
+ };
+ let (mut server, url) = make_server(handler);
+
+ let target_url = url.clone().join("a.html").unwrap();
+
+ let origin = Origin::Origin(ImmutableOrigin::new_opaque());
+ let mut request = Request::new(url.clone(), Some(origin), None);
+ request.referrer = Referrer::ReferrerUrl(target_url);
+ request.referrer_policy = Some(ReferrerPolicy::Origin);
+ request.use_cors_preflight = true;
+ request.mode = RequestMode::CorsMode;
+ let fetch_response = fetch(&mut request, None);
+ let _ = server.close();
+
+ assert!(!fetch_response.is_network_error());
+ match *fetch_response.body.lock().unwrap() {
+ ResponseBody::Done(ref body) => assert_eq!(&**body, ACK),
+ _ => panic!()
+ };
+}
+
+#[test]
+fn test_cors_preflight_cache_fetch() {
+ static ACK: &'static [u8] = b"ACK";
+ let state = Arc::new(AtomicUsize::new(0));
+ let counter = state.clone();
+ let mut cache = CorsCache::new();
+ let handler = move |request: HyperRequest, mut response: HyperResponse| {
+ if request.method == Method::Options && state.clone().fetch_add(1, Ordering::SeqCst) == 0 {
+ assert!(request.headers.has::<AccessControlRequestMethod>());
+ assert!(!request.headers.has::<AccessControlRequestHeaders>());
+ response.headers_mut().set(AccessControlAllowOrigin::Any);
+ response.headers_mut().set(AccessControlAllowCredentials);
+ response.headers_mut().set(AccessControlAllowMethods(vec![Method::Get]));
+ response.headers_mut().set(AccessControlMaxAge(6000));
+ } else {
+ response.headers_mut().set(AccessControlAllowOrigin::Any);
+ response.send(ACK).unwrap();
+ }
+ };
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(ImmutableOrigin::new_opaque());
+ let mut request = Request::new(url.clone(), Some(origin.clone()), None);
+ request.referrer = Referrer::NoReferrer;
+ request.use_cors_preflight = true;
+ request.mode = RequestMode::CorsMode;
+ let mut wrapped_request0 = request.clone();
+ let mut wrapped_request1 = request;
+
+ let fetch_response0 = fetch_with_cors_cache(&mut wrapped_request0, &mut cache);
+ let fetch_response1 = fetch_with_cors_cache(&mut wrapped_request1, &mut cache);
+ let _ = server.close();
+
+ assert!(!fetch_response0.is_network_error() && !fetch_response1.is_network_error());
+
+ // The response from the CORS-preflight cache was used
+ assert_eq!(1, counter.load(Ordering::SeqCst));
+
+ // The entry exists in the CORS-preflight cache
+ assert_eq!(true, cache.match_method(&wrapped_request0, Method::Get));
+ assert_eq!(true, cache.match_method(&wrapped_request1, Method::Get));
+
+ match *fetch_response0.body.lock().unwrap() {
+ ResponseBody::Done(ref body) => assert_eq!(&**body, ACK),
+ _ => panic!()
+ };
+ match *fetch_response1.body.lock().unwrap() {
+ ResponseBody::Done(ref body) => assert_eq!(&**body, ACK),
+ _ => panic!()
+ };
+}
+
+#[test]
+fn test_cors_preflight_fetch_network_error() {
+ static ACK: &'static [u8] = b"ACK";
+ let state = Arc::new(AtomicUsize::new(0));
+ let handler = move |request: HyperRequest, mut response: HyperResponse| {
+ if request.method == Method::Options && state.clone().fetch_add(1, Ordering::SeqCst) == 0 {
+ assert!(request.headers.has::<AccessControlRequestMethod>());
+ assert!(!request.headers.has::<AccessControlRequestHeaders>());
+ response.headers_mut().set(AccessControlAllowOrigin::Any);
+ response.headers_mut().set(AccessControlAllowCredentials);
+ response.headers_mut().set(AccessControlAllowMethods(vec![Method::Get]));
+ } else {
+ response.headers_mut().set(AccessControlAllowOrigin::Any);
+ response.send(ACK).unwrap();
+ }
+ };
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(ImmutableOrigin::new_opaque());
+ let mut request = Request::new(url, Some(origin), None);
+ request.method = Method::Extension("CHICKEN".to_owned());
+ request.referrer = Referrer::NoReferrer;
+ request.use_cors_preflight = true;
+ request.mode = RequestMode::CorsMode;
+ let fetch_response = fetch(&mut request, None);
+ let _ = server.close();
+
+ assert!(fetch_response.is_network_error());
+}
+
+#[test]
+fn test_fetch_response_is_basic_filtered() {
+ static MESSAGE: &'static [u8] = b"";
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ response.headers_mut().set(SetCookie(vec![]));
+ // this header is obsoleted, so hyper doesn't implement it, but it's still covered by the spec
+ response.headers_mut().set_raw("Set-Cookie2", vec![]);
+
+ response.send(MESSAGE).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ let fetch_response = fetch(&mut request, None);
+ let _ = server.close();
+
+ assert!(!fetch_response.is_network_error());
+ assert_eq!(fetch_response.response_type, ResponseType::Basic);
+
+ let headers = fetch_response.headers;
+ assert!(!headers.has::<SetCookie>());
+ assert!(headers.get_raw("Set-Cookie2").is_none());
+}
+
+#[test]
+fn test_fetch_response_is_cors_filtered() {
+ static MESSAGE: &'static [u8] = b"";
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ // this is mandatory for the Cors Check to pass
+ // TODO test using different url encodings with this value ie. punycode
+ response.headers_mut().set(AccessControlAllowOrigin::Any);
+
+ // these are the headers that should be kept after filtering
+ response.headers_mut().set(CacheControl(vec![]));
+ response.headers_mut().set(ContentLanguage(vec![]));
+ response.headers_mut().set(ContentType::html());
+ response.headers_mut().set(Expires(HttpDate(time::now() + Duration::days(1))));
+ response.headers_mut().set(LastModified(HttpDate(time::now())));
+ response.headers_mut().set(Pragma::NoCache);
+
+ // these headers should not be kept after filtering, even though they are given a pass
+ response.headers_mut().set(SetCookie(vec![]));
+ response.headers_mut().set_raw("Set-Cookie2", vec![]);
+ response.headers_mut().set(
+ AccessControlAllowHeaders(vec![
+ UniCase("set-cookie".to_owned()),
+ UniCase("set-cookie2".to_owned())
+ ])
+ );
+
+ response.send(MESSAGE).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ // an origin mis-match will stop it from defaulting to a basic filtered response
+ let origin = Origin::Origin(ImmutableOrigin::new_opaque());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ request.mode = RequestMode::CorsMode;
+ let fetch_response = fetch(&mut request, None);
+ let _ = server.close();
+
+ assert!(!fetch_response.is_network_error());
+ assert_eq!(fetch_response.response_type, ResponseType::Cors);
+
+ let headers = fetch_response.headers;
+ assert!(headers.has::<CacheControl>());
+ assert!(headers.has::<ContentLanguage>());
+ assert!(headers.has::<ContentType>());
+ assert!(headers.has::<Expires>());
+ assert!(headers.has::<LastModified>());
+ assert!(headers.has::<Pragma>());
+
+ assert!(!headers.has::<AccessControlAllowOrigin>());
+ assert!(!headers.has::<SetCookie>());
+ assert!(headers.get_raw("Set-Cookie2").is_none());
+}
+
+#[test]
+fn test_fetch_response_is_opaque_filtered() {
+ static MESSAGE: &'static [u8] = b"";
+ let handler = move |_: HyperRequest, response: HyperResponse| {
+ response.send(MESSAGE).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ // an origin mis-match will fall through to an Opaque filtered response
+ let origin = Origin::Origin(ImmutableOrigin::new_opaque());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ let fetch_response = fetch(&mut request, None);
+ let _ = server.close();
+
+ assert!(!fetch_response.is_network_error());
+ assert_eq!(fetch_response.response_type, ResponseType::Opaque);
+
+ assert!(fetch_response.url().is_none());
+ assert!(fetch_response.url_list.is_empty());
+ // this also asserts that status message is "the empty byte sequence"
+ assert!(fetch_response.status.is_none());
+ assert_eq!(fetch_response.headers, Headers::new());
+ match *fetch_response.body.lock().unwrap() {
+ ResponseBody::Empty => { },
+ _ => panic!()
+ }
+ match fetch_response.cache_state {
+ CacheState::None => { },
+ _ => panic!()
+ }
+}
+
+#[test]
+fn test_fetch_response_is_opaque_redirect_filtered() {
+ static MESSAGE: &'static [u8] = b"";
+ let handler = move |request: HyperRequest, mut response: HyperResponse| {
+ let redirects = match request.uri {
+ RequestUri::AbsolutePath(url) =>
+ url.split("/").collect::<String>().parse::<u32>().unwrap_or(0),
+ RequestUri::AbsoluteUri(url) =>
+ url.path_segments().unwrap().next_back().unwrap().parse::<u32>().unwrap_or(0),
+ _ => panic!()
+ };
+
+ if redirects == 1 {
+ response.send(MESSAGE).unwrap();
+ } else {
+ *response.status_mut() = StatusCode::Found;
+ let url = format!("{}", 1);
+ response.headers_mut().set(Location(url.to_owned()));
+ }
+ };
+
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ request.redirect_mode = RedirectMode::Manual;
+ let fetch_response = fetch(&mut request, None);
+ let _ = server.close();
+
+ assert!(!fetch_response.is_network_error());
+ assert_eq!(fetch_response.response_type, ResponseType::OpaqueRedirect);
+
+ // this also asserts that status message is "the empty byte sequence"
+ assert!(fetch_response.status.is_none());
+ assert_eq!(fetch_response.headers, Headers::new());
+ match *fetch_response.body.lock().unwrap() {
+ ResponseBody::Empty => { },
+ _ => panic!()
+ }
+ match fetch_response.cache_state {
+ CacheState::None => { },
+ _ => panic!()
+ }
+}
+
+#[test]
+fn test_fetch_with_local_urls_only() {
+ // If flag `local_urls_only` is set, fetching a non-local URL must result in network error.
+
+ static MESSAGE: &'static [u8] = b"";
+ let handler = move |_: HyperRequest, response: HyperResponse| {
+ response.send(MESSAGE).unwrap();
+ };
+ let (mut server, server_url) = make_server(handler);
+
+ let do_fetch = |url: ServoUrl| {
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+
+ // Set the flag.
+ request.local_urls_only = true;
+
+ fetch(&mut request, None)
+ };
+
+ let local_url = ServoUrl::parse("about:blank").unwrap();
+ let local_response = do_fetch(local_url);
+ let server_response = do_fetch(server_url);
+
+ let _ = server.close();
+
+ assert!(!local_response.is_network_error());
+ assert!(server_response.is_network_error());
+}
+
+// NOTE(emilio): If this test starts failing:
+//
+// openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
+// -keyout resources/privatekey_for_testing.key \
+// -out resources/self_signed_certificate_for_testing.crt
+//
+// And make sure to specify `localhost` as the server name.
+#[test]
+fn test_fetch_with_hsts() {
+ static MESSAGE: &'static [u8] = b"";
+ let handler = move |_: HyperRequest, response: HyperResponse| {
+ response.send(MESSAGE).unwrap();
+ };
+
+ let path = resources_dir_path().expect("Cannot find resource dir");
+ let mut cert_path = path.clone();
+ cert_path.push("self_signed_certificate_for_testing.crt");
+
+ let mut key_path = path.clone();
+ key_path.push("privatekey_for_testing.key");
+
+ let ssl = hyper_openssl::OpensslServer::from_files(key_path, cert_path)
+ .unwrap();
+
+ //takes an address and something that implements hyper::net::Ssl
+ let mut server = Server::https("0.0.0.0:0", ssl).unwrap().handle_threads(handler, 1).unwrap();
+
+ let ca_file = resources_dir_path().unwrap().join("self_signed_certificate_for_testing.crt");
+ let ssl_client = create_ssl_client(&ca_file);
+
+ let context = FetchContext {
+ state: Arc::new(HttpState::new(ssl_client)),
+ user_agent: DEFAULT_USER_AGENT.into(),
+ devtools_chan: None,
+ filemanager: FileManager::new(),
+ cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
+ };
+
+ {
+ let mut list = context.state.hsts_list.write().unwrap();
+ list.push(HstsEntry::new("localhost".to_owned(), IncludeSubdomains::NotIncluded, None)
+ .unwrap());
+ }
+ let url_string = format!("http://localhost:{}", server.socket.port());
+ let url = ServoUrl::parse(&url_string).unwrap();
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ // Set the flag.
+ request.local_urls_only = false;
+ let response = fetch_with_context(&mut request, &context);
+ let _ = server.close();
+ assert_eq!(response.internal_response.unwrap().url().unwrap().scheme(),
+ "https");
+}
+
+#[test]
+fn test_fetch_with_sri_network_error() {
+ static MESSAGE: &'static [u8] = b"alert('Hello, Network Error');";
+ let handler = move |_: HyperRequest, response: HyperResponse| {
+ response.send(MESSAGE).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ // To calulate hash use :
+ // echo -n "alert('Hello, Network Error');" | openssl dgst -sha384 -binary | openssl base64 -A
+ request.integrity_metadata =
+ "sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO".to_owned();
+ // Set the flag.
+ request.local_urls_only = false;
+
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+ assert!(response.is_network_error());
+}
+
+#[test]
+fn test_fetch_with_sri_sucess() {
+ static MESSAGE: &'static [u8] = b"alert('Hello, world.');";
+ let handler = move |_: HyperRequest, response: HyperResponse| {
+ response.send(MESSAGE).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ // To calulate hash use :
+ // echo -n "alert('Hello, Network Error');" | openssl dgst -sha384 -binary | openssl base64 -A
+ request.integrity_metadata =
+ "sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO".to_owned();
+ // Set the flag.
+ request.local_urls_only = false;
+
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+ assert_eq!(response_is_done(&response), true);
+}
+
+/// `fetch` should return a network error if there is a header `X-Content-Type-Options: nosniff`
+#[test]
+fn test_fetch_blocked_nosniff() {
+ #[inline]
+ fn test_nosniff_request(destination: Destination,
+ mime: Mime,
+ should_error: bool) {
+ const MESSAGE: &'static [u8] = b"";
+ const HEADER: &'static str = "X-Content-Type-Options";
+ const VALUE: &'static [u8] = b"nosniff";
+
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ let mime_header = ContentType(mime.clone());
+ response.headers_mut().set(mime_header);
+ assert!(response.headers().has::<ContentType>());
+ // Add the nosniff header
+ response.headers_mut().set_raw(HEADER, vec![VALUE.to_vec()]);
+
+ response.send(MESSAGE).unwrap();
+ };
+
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.destination = destination;
+ let fetch_response = fetch(&mut request, None);
+ let _ = server.close();
+
+ assert_eq!(fetch_response.is_network_error(), should_error);
+ }
+
+ let tests = vec![
+ (Destination::Script, Mime(TopLevel::Text, SubLevel::Javascript, vec![]), false),
+ (Destination::Script, Mime(TopLevel::Text, SubLevel::Css, vec![]), true),
+ (Destination::Style, Mime(TopLevel::Text, SubLevel::Css, vec![]), false),
+ ];
+
+ for test in tests {
+ let (destination, mime, should_error) = test;
+ test_nosniff_request(destination, mime, should_error);
+ }
+}
+
+fn setup_server_and_fetch(message: &'static [u8], redirect_cap: u32) -> Response {
+ let handler = move |request: HyperRequest, mut response: HyperResponse| {
+ let redirects = match request.uri {
+ RequestUri::AbsolutePath(url) =>
+ url.split("/").collect::<String>().parse::<u32>().unwrap_or(0),
+ RequestUri::AbsoluteUri(url) =>
+ url.path_segments().unwrap().next_back().unwrap().parse::<u32>().unwrap_or(0),
+ _ => panic!()
+ };
+
+ if redirects >= redirect_cap {
+ response.send(message).unwrap();
+ } else {
+ *response.status_mut() = StatusCode::Found;
+ let url = format!("{redirects}", redirects = redirects + 1);
+ response.headers_mut().set(Location(url.to_owned()));
+ }
+ };
+
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ let fetch_response = fetch(&mut request, None);
+ let _ = server.close();
+ fetch_response
+}
+
+#[test]
+fn test_fetch_redirect_count_ceiling() {
+ static MESSAGE: &'static [u8] = b"no more redirects";
+ // how many redirects to cause
+ let redirect_cap = 20;
+
+ let fetch_response = setup_server_and_fetch(MESSAGE, redirect_cap);
+
+ assert!(!fetch_response.is_network_error());
+ assert_eq!(fetch_response.response_type, ResponseType::Basic);
+
+ match *fetch_response.body.lock().unwrap() {
+ ResponseBody::Done(ref body) => {
+ assert_eq!(&**body, MESSAGE);
+ },
+ _ => panic!()
+ };
+}
+
+#[test]
+fn test_fetch_redirect_count_failure() {
+ static MESSAGE: &'static [u8] = b"this message shouldn't be reachable";
+ // how many redirects to cause
+ let redirect_cap = 21;
+
+ let fetch_response = setup_server_and_fetch(MESSAGE, redirect_cap);
+
+ assert!(fetch_response.is_network_error());
+
+ match *fetch_response.body.lock().unwrap() {
+ ResponseBody::Done(_) | ResponseBody::Receiving(_) => panic!(),
+ _ => { }
+ };
+}
+
+fn test_fetch_redirect_updates_method_runner(tx: Sender<bool>, status_code: StatusCode, method: Method) {
+ let handler_method = method.clone();
+ let handler_tx = Arc::new(Mutex::new(tx));
+
+ let handler = move |request: HyperRequest, mut response: HyperResponse| {
+ let redirects = match request.uri {
+ RequestUri::AbsolutePath(url) =>
+ url.split("/").collect::<String>().parse::<u32>().unwrap_or(0),
+ RequestUri::AbsoluteUri(url) =>
+ url.path_segments().unwrap().next_back().unwrap().parse::<u32>().unwrap_or(0),
+ _ => panic!()
+ };
+
+ let mut test_pass = true;
+
+ if redirects == 0 {
+ *response.status_mut() = StatusCode::TemporaryRedirect;
+ response.headers_mut().set(Location("1".to_owned()));
+
+ } else if redirects == 1 {
+ // this makes sure that the request method does't change from the wrong status code
+ if handler_method != Method::Get && request.method == Method::Get {
+ test_pass = false;
+ }
+ *response.status_mut() = status_code;
+ response.headers_mut().set(Location("2".to_owned()));
+
+ } else if request.method != Method::Get {
+ test_pass = false;
+ }
+
+ // the first time this handler is reached, nothing is being tested, so don't send anything
+ if redirects > 0 {
+ handler_tx.lock().unwrap().send(test_pass).unwrap();
+ }
+
+ };
+
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ request.method = method;
+
+ let _ = fetch(&mut request, None);
+ let _ = server.close();
+}
+
+#[test]
+fn test_fetch_redirect_updates_method() {
+ let (tx, rx) = channel();
+
+ test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::MovedPermanently, Method::Post);
+ assert_eq!(rx.recv().unwrap(), true);
+ assert_eq!(rx.recv().unwrap(), true);
+ // make sure the test doesn't send more data than expected
+ assert_eq!(rx.try_recv().is_err(), true);
+
+ test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::Found, Method::Post);
+ assert_eq!(rx.recv().unwrap(), true);
+ assert_eq!(rx.recv().unwrap(), true);
+ assert_eq!(rx.try_recv().is_err(), true);
+
+ test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::SeeOther, Method::Get);
+ assert_eq!(rx.recv().unwrap(), true);
+ assert_eq!(rx.recv().unwrap(), true);
+ assert_eq!(rx.try_recv().is_err(), true);
+
+ let extension = Method::Extension("FOO".to_owned());
+
+ test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::MovedPermanently, extension.clone());
+ assert_eq!(rx.recv().unwrap(), true);
+ // for MovedPermanently and Found, Method should only be changed if it was Post
+ assert_eq!(rx.recv().unwrap(), false);
+ assert_eq!(rx.try_recv().is_err(), true);
+
+ test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::Found, extension.clone());
+ assert_eq!(rx.recv().unwrap(), true);
+ assert_eq!(rx.recv().unwrap(), false);
+ assert_eq!(rx.try_recv().is_err(), true);
+
+ test_fetch_redirect_updates_method_runner(tx.clone(), StatusCode::SeeOther, extension.clone());
+ assert_eq!(rx.recv().unwrap(), true);
+ // for SeeOther, Method should always be changed, so this should be true
+ assert_eq!(rx.recv().unwrap(), true);
+ assert_eq!(rx.try_recv().is_err(), true);
+}
+
+fn response_is_done(response: &Response) -> bool {
+ let response_complete = match response.response_type {
+ ResponseType::Default | ResponseType::Basic | ResponseType::Cors => {
+ (*response.body.lock().unwrap()).is_done()
+ }
+ // if the internal response cannot have a body, it shouldn't block the "done" state
+ ResponseType::Opaque | ResponseType::OpaqueRedirect | ResponseType::Error(..) => true
+ };
+
+ let internal_complete = if let Some(ref res) = response.internal_response {
+ res.body.lock().unwrap().is_done()
+ } else {
+ true
+ };
+
+ response_complete && internal_complete
+}
+
+#[test]
+fn test_fetch_async_returns_complete_response() {
+ static MESSAGE: &'static [u8] = b"this message should be retrieved in full";
+ let handler = move |_: HyperRequest, response: HyperResponse| {
+ response.send(MESSAGE).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+
+ let fetch_response = fetch(&mut request, None);
+
+ let _ = server.close();
+ assert_eq!(response_is_done(&fetch_response), true);
+}
+
+#[test]
+fn test_opaque_filtered_fetch_async_returns_complete_response() {
+ static MESSAGE: &'static [u8] = b"";
+ let handler = move |_: HyperRequest, response: HyperResponse| {
+ response.send(MESSAGE).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ // an origin mis-match will fall through to an Opaque filtered response
+ let origin = Origin::Origin(ImmutableOrigin::new_opaque());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+
+ let fetch_response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ assert_eq!(fetch_response.response_type, ResponseType::Opaque);
+ assert_eq!(response_is_done(&fetch_response), true);
+}
+
+#[test]
+fn test_opaque_redirect_filtered_fetch_async_returns_complete_response() {
+ static MESSAGE: &'static [u8] = b"";
+ let handler = move |request: HyperRequest, mut response: HyperResponse| {
+ let redirects = match request.uri {
+ RequestUri::AbsolutePath(url) =>
+ url.split("/").collect::<String>().parse::<u32>().unwrap_or(0),
+ RequestUri::AbsoluteUri(url) =>
+ url.path_segments().unwrap().last().unwrap().parse::<u32>().unwrap_or(0),
+ _ => panic!()
+ };
+
+ if redirects == 1 {
+ response.send(MESSAGE).unwrap();
+ } else {
+ *response.status_mut() = StatusCode::Found;
+ let url = format!("{}", 1);
+ response.headers_mut().set(Location(url.to_owned()));
+ }
+ };
+
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url, Some(origin), None);
+ request.referrer = Referrer::NoReferrer;
+ request.redirect_mode = RedirectMode::Manual;
+
+ let fetch_response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ assert_eq!(fetch_response.response_type, ResponseType::OpaqueRedirect);
+ assert_eq!(response_is_done(&fetch_response), true);
+}
+
+#[test]
+fn test_fetch_with_devtools() {
+ static MESSAGE: &'static [u8] = b"Yay!";
+ let handler = move |_: HyperRequest, response: HyperResponse| {
+ response.send(MESSAGE).unwrap();
+ };
+
+ let (mut server, url) = make_server(handler);
+
+ let origin = Origin::Origin(url.origin());
+ let mut request = Request::new(url.clone(), Some(origin), Some(TEST_PIPELINE_ID));
+ request.referrer = Referrer::NoReferrer;
+
+ let (devtools_chan, devtools_port) = channel::<DevtoolsControlMsg>();
+
+ let _ = fetch(&mut request, Some(devtools_chan));
+ let _ = server.close();
+
+ // notification received from devtools
+ let devhttprequest = expect_devtools_http_request(&devtools_port);
+ let mut devhttpresponse = expect_devtools_http_response(&devtools_port);
+
+ //Creating default headers for request
+ let mut headers = Headers::new();
+
+ headers.set(AcceptEncoding(vec![
+ qitem(Encoding::Gzip),
+ qitem(Encoding::Deflate),
+ qitem(Encoding::EncodingExt("br".to_owned()))
+ ]));
+
+ headers.set(Host { hostname: url.host_str().unwrap().to_owned() , port: url.port().to_owned() });
+
+ let accept = Accept(vec![qitem(Mime(TopLevel::Star, SubLevel::Star, vec![]))]);
+ headers.set(accept);
+
+ let mut en_us: LanguageTag = Default::default();
+ en_us.language = Some("en".to_owned());
+ en_us.region = Some("US".to_owned());
+ let mut en: LanguageTag = Default::default();
+ en.language = Some("en".to_owned());
+ headers.set(AcceptLanguage(vec![
+ qitem(en_us),
+ QualityItem::new(en, Quality(500)),
+ ]));
+
+ headers.set(UserAgent(DEFAULT_USER_AGENT.to_owned()));
+
+ let httprequest = DevtoolsHttpRequest {
+ url: url,
+ method: Method::Get,
+ headers: headers,
+ body: None,
+ pipeline_id: TEST_PIPELINE_ID,
+ startedDateTime: devhttprequest.startedDateTime,
+ timeStamp: devhttprequest.timeStamp,
+ connect_time: devhttprequest.connect_time,
+ send_time: devhttprequest.send_time,
+ is_xhr: true,
+ };
+
+ let content = "Yay!";
+ let mut response_headers = Headers::new();
+ response_headers.set(ContentLength(content.len() as u64));
+ devhttpresponse.headers.as_mut().unwrap().remove::<Date>();
+
+ let httpresponse = DevtoolsHttpResponse {
+ headers: Some(response_headers),
+ status: Some((200, b"OK".to_vec())),
+ body: None,
+ pipeline_id: TEST_PIPELINE_ID,
+ };
+
+ assert_eq!(devhttprequest, httprequest);
+ assert_eq!(devhttpresponse, httpresponse);
+}
diff --git a/components/net/tests/file_loader.rs b/components/net/tests/file_loader.rs
new file mode 100644
index 00000000000..f7a45691e57
--- /dev/null
+++ b/components/net/tests/file_loader.rs
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use std::env;
+use url::Url;
+
+#[test]
+fn load_htm() {
+ let mut path = env::current_dir().expect("didn't get working dir");
+ path.push("tests/test.jpeg");
+
+ let canon_path = path.canonicalize().expect("file path doesn't exist");
+ let url = Url::from_file_path(canon_path);
+
+ assert!(url.is_ok());
+}
diff --git a/components/net/tests/filemanager_thread.rs b/components/net/tests/filemanager_thread.rs
new file mode 100644
index 00000000000..089e56c43fb
--- /dev/null
+++ b/components/net/tests/filemanager_thread.rs
@@ -0,0 +1,110 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use ipc_channel::ipc;
+use net::filemanager_thread::{FileManager, UIProvider};
+use net_traits::blob_url_store::BlobURLStoreError;
+use net_traits::filemanager_thread::{FilterPattern, FileManagerThreadMsg, FileManagerThreadError, ReadFileProgress};
+use std::fs::File;
+use std::io::Read;
+use std::path::PathBuf;
+
+pub const TEST_PROVIDER: &'static TestProvider = &TestProvider;
+
+pub struct TestProvider;
+
+impl UIProvider for TestProvider {
+ fn open_file_dialog(&self, _path: &str, _patterns: Vec<FilterPattern>) -> Option<String> {
+ Some("tests/test.jpeg".to_string())
+ }
+
+ fn open_file_dialog_multi(&self, _path: &str, _patterns: Vec<FilterPattern>) -> Option<Vec<String>> {
+ Some(vec!["tests/test.jpeg".to_string()])
+ }
+}
+
+#[test]
+fn test_filemanager() {
+ let filemanager = FileManager::new();
+
+ // Try to open a dummy file "components/net/tests/test.jpeg" in tree
+ let mut handler = File::open("tests/test.jpeg").expect("test.jpeg is stolen");
+ let mut test_file_content = vec![];
+
+ handler.read_to_end(&mut test_file_content)
+ .expect("Read components/net/tests/test.jpeg error");
+
+ let patterns = vec![FilterPattern(".txt".to_string())];
+ let origin = "test.com".to_string();
+
+ {
+ // Try to select a dummy file "components/net/tests/test.jpeg"
+ let (tx, rx) = ipc::channel().unwrap();
+ filemanager.handle(FileManagerThreadMsg::SelectFile(patterns.clone(), tx, origin.clone(), None),
+ TEST_PROVIDER);
+ let selected = rx.recv().expect("Broken channel")
+ .expect("The file manager failed to find test.jpeg");
+
+ // Expecting attributes conforming the spec
+ assert_eq!(selected.filename, PathBuf::from("test.jpeg"));
+ assert_eq!(selected.type_string, "image/jpeg".to_string());
+
+ // Test by reading, expecting same content
+ {
+ let (tx2, rx2) = ipc::channel().unwrap();
+ filemanager.handle(FileManagerThreadMsg::ReadFile(tx2, selected.id.clone(), false, origin.clone()),
+ TEST_PROVIDER);
+
+ let msg = rx2.recv().expect("Broken channel");
+
+ if let ReadFileProgress::Meta(blob_buf) = msg.expect("File manager reading failure is unexpected") {
+ let mut bytes = blob_buf.bytes;
+
+ loop {
+ match rx2.recv().expect("Broken channel").expect("File manager reading failure is unexpected") {
+ ReadFileProgress::Meta(_) => {
+ panic!("Invalid FileManager reply");
+ }
+ ReadFileProgress::Partial(mut bytes_in) => {
+ bytes.append(&mut bytes_in);
+ }
+ ReadFileProgress::EOF => {
+ break;
+ }
+ }
+ }
+
+ assert_eq!(test_file_content, bytes, "Read content differs");
+ } else {
+ panic!("Invalid FileManager reply");
+ }
+ }
+
+ // Delete the id
+ {
+ let (tx2, rx2) = ipc::channel().unwrap();
+ filemanager.handle(FileManagerThreadMsg::DecRef(selected.id.clone(), origin.clone(), tx2),
+ TEST_PROVIDER);
+
+ let ret = rx2.recv().expect("Broken channel");
+ assert!(ret.is_ok(), "DecRef is not okay");
+ }
+
+ // Test by reading again, expecting read error because we invalidated the id
+ {
+ let (tx2, rx2) = ipc::channel().unwrap();
+ filemanager.handle(FileManagerThreadMsg::ReadFile(tx2, selected.id.clone(), false, origin.clone()),
+ TEST_PROVIDER);
+
+ let msg = rx2.recv().expect("Broken channel");
+
+ match msg {
+ Err(FileManagerThreadError::BlobURLStoreError(BlobURLStoreError::InvalidFileID)) => {},
+ other => {
+ assert!(false, "Get unexpected response after deleting the id: {:?}", other);
+ }
+ }
+ }
+ }
+}
diff --git a/components/net/tests/hsts.rs b/components/net/tests/hsts.rs
new file mode 100644
index 00000000000..eca9d2a8d27
--- /dev/null
+++ b/components/net/tests/hsts.rs
@@ -0,0 +1,294 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use net::hsts::{HstsEntry, HstsList};
+use net_traits::IncludeSubdomains;
+use std::collections::HashMap;
+use time;
+
+#[test]
+fn test_hsts_entry_is_not_expired_when_it_has_no_timestamp() {
+ let entry = HstsEntry {
+ host: "mozilla.org".to_owned(),
+ include_subdomains: false,
+ max_age: Some(20),
+ timestamp: None
+ };
+
+ assert!(!entry.is_expired());
+}
+
+#[test]
+fn test_hsts_entry_is_not_expired_when_it_has_no_max_age() {
+ let entry = HstsEntry {
+ host: "mozilla.org".to_owned(),
+ include_subdomains: false,
+ max_age: None,
+ timestamp: Some(time::get_time().sec as u64)
+ };
+
+ assert!(!entry.is_expired());
+}
+
+#[test]
+fn test_hsts_entry_is_expired_when_it_has_reached_its_max_age() {
+ let entry = HstsEntry {
+ host: "mozilla.org".to_owned(),
+ include_subdomains: false,
+ max_age: Some(10),
+ timestamp: Some(time::get_time().sec as u64 - 20u64)
+ };
+
+ assert!(entry.is_expired());
+}
+
+#[test]
+fn test_hsts_entry_cant_be_created_with_ipv6_address_as_host() {
+ let entry = HstsEntry::new(
+ "2001:0db8:0000:0000:0000:ff00:0042:8329".to_owned(), IncludeSubdomains::NotIncluded, None
+ );
+
+ assert!(entry.is_none(), "able to create HstsEntry with IPv6 host");
+}
+
+#[test]
+fn test_hsts_entry_cant_be_created_with_ipv4_address_as_host() {
+ let entry = HstsEntry::new(
+ "4.4.4.4".to_owned(), IncludeSubdomains::NotIncluded, None
+ );
+
+ assert!(entry.is_none(), "able to create HstsEntry with IPv4 host");
+}
+
+#[test]
+fn test_base_domain_in_entries_map() {
+ let entries_map = HashMap::new();
+
+ let mut list = HstsList {
+ entries_map: entries_map
+ };
+
+ list.push(HstsEntry::new("servo.mozilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, None).unwrap());
+ list.push(HstsEntry::new("firefox.mozilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, None).unwrap());
+ list.push(HstsEntry::new("bugzilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, None).unwrap());
+
+ assert_eq!(list.entries_map.len(), 2);
+ assert_eq!(list.entries_map.get("mozilla.org").unwrap().len(), 2);
+}
+
+#[test]
+fn test_push_entry_with_0_max_age_evicts_entry_from_list() {
+ let mut entries_map = HashMap::new();
+ entries_map.insert("mozilla.org".to_owned(), vec!(HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, Some(500000u64)).unwrap()));
+ let mut list = HstsList {
+ entries_map: entries_map
+ };
+
+ list.push(HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, Some(0)).unwrap());
+
+ assert!(list.is_host_secure("mozilla.org") == false)
+}
+
+#[test]
+fn test_push_entry_to_hsts_list_should_not_add_subdomains_whose_superdomain_is_already_matched() {
+ let mut entries_map = HashMap::new();
+ entries_map.insert("mozilla.org".to_owned(), vec!(HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::Included, None).unwrap()));
+ let mut list = HstsList {
+ entries_map: entries_map
+ };
+
+ list.push(HstsEntry::new("servo.mozilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, None).unwrap());
+
+ assert!(list.entries_map.get("mozilla.org").unwrap().len() == 1)
+}
+
+#[test]
+fn test_push_entry_to_hsts_list_should_update_existing_domain_entrys_include_subdomains() {
+ let mut entries_map = HashMap::new();
+ entries_map.insert("mozilla.org".to_owned(), vec!(HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::Included, None).unwrap()));
+ let mut list = HstsList {
+ entries_map: entries_map
+ };
+
+ assert!(list.is_host_secure("servo.mozilla.org"));
+
+ list.push(HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, None).unwrap());
+
+ assert!(!list.is_host_secure("servo.mozilla.org"))
+}
+
+#[test]
+fn test_push_entry_to_hsts_list_should_not_create_duplicate_entry() {
+ let mut entries_map = HashMap::new();
+ entries_map.insert("mozilla.org".to_owned(), vec!(HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, None).unwrap()));
+ let mut list = HstsList {
+ entries_map: entries_map
+ };
+
+ list.push(HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, None).unwrap());
+
+ assert!(list.entries_map.get("mozilla.org").unwrap().len() == 1)
+}
+
+#[test]
+fn test_push_multiple_entrie_to_hsts_list_should_add_them_all() {
+ let mut list = HstsList {
+ entries_map: HashMap::new()
+ };
+
+ assert!(!list.is_host_secure("mozilla.org"));
+ assert!(!list.is_host_secure("bugzilla.org"));
+
+ list.push(HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::Included, None).unwrap());
+ list.push(HstsEntry::new("bugzilla.org".to_owned(),
+ IncludeSubdomains::Included, None).unwrap());
+
+ assert!(list.is_host_secure("mozilla.org"));
+ assert!(list.is_host_secure("bugzilla.org"));
+}
+
+#[test]
+fn test_push_entry_to_hsts_list_should_add_an_entry() {
+ let mut list = HstsList {
+ entries_map: HashMap::new()
+ };
+
+ assert!(!list.is_host_secure("mozilla.org"));
+
+ list.push(HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::Included, None).unwrap());
+
+ assert!(list.is_host_secure("mozilla.org"));
+}
+
+#[test]
+fn test_parse_hsts_preload_should_return_none_when_json_invalid() {
+ let mock_preload_content = b"derp";
+ assert!(HstsList::from_preload(mock_preload_content).is_none(), "invalid preload list should not have parsed")
+}
+
+#[test]
+fn test_parse_hsts_preload_should_return_none_when_json_contains_no_entries_map_key() {
+ let mock_preload_content = b"{\"nothing\": \"to see here\"}";
+ assert!(HstsList::from_preload(mock_preload_content).is_none(), "invalid preload list should not have parsed")
+}
+
+#[test]
+fn test_parse_hsts_preload_should_decode_host_and_includes_subdomains() {
+ let mock_preload_content = b"{\
+ \"entries\": [\
+ {\"host\": \"mozilla.org\",\
+ \"include_subdomains\": false}\
+ ]\
+ }";
+ let hsts_list = HstsList::from_preload(mock_preload_content);
+ let entries_map = hsts_list.unwrap().entries_map;
+
+ assert_eq!(entries_map.get("mozilla.org").unwrap()[0].host, "mozilla.org");
+ assert!(!entries_map.get("mozilla.org").unwrap()[0].include_subdomains);
+}
+
+#[test]
+fn test_hsts_list_with_no_entries_map_does_not_is_host_secure() {
+ let hsts_list = HstsList {
+ entries_map: HashMap::new()
+ };
+
+ assert!(!hsts_list.is_host_secure("mozilla.org"));
+}
+
+#[test]
+fn test_hsts_list_with_exact_domain_entry_is_is_host_secure() {
+ let mut entries_map = HashMap::new();
+ entries_map.insert("mozilla.org".to_owned(), vec![HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, None).unwrap()]);
+
+ let hsts_list = HstsList {
+ entries_map: entries_map
+ };
+
+ assert!(hsts_list.is_host_secure("mozilla.org"));
+}
+
+#[test]
+fn test_hsts_list_with_subdomain_when_include_subdomains_is_true_is_is_host_secure() {
+ let mut entries_map = HashMap::new();
+ entries_map.insert("mozilla.org".to_owned(), vec![HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::Included, None).unwrap()]);
+ let hsts_list = HstsList {
+ entries_map: entries_map
+ };
+
+ assert!(hsts_list.is_host_secure("servo.mozilla.org"));
+}
+
+#[test]
+fn test_hsts_list_with_subdomain_when_include_subdomains_is_false_is_not_is_host_secure() {
+ let mut entries_map = HashMap::new();
+ entries_map.insert("mozilla.org".to_owned(), vec![HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::NotIncluded, None).unwrap()]);
+ let hsts_list = HstsList {
+ entries_map: entries_map
+ };
+
+ assert!(!hsts_list.is_host_secure("servo.mozilla.org"));
+}
+
+#[test]
+fn test_hsts_list_with_subdomain_when_host_is_not_a_subdomain_is_not_is_host_secure() {
+ let mut entries_map = HashMap::new();
+ entries_map.insert("mozilla.org".to_owned(), vec![HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::Included, None).unwrap()]);
+ let hsts_list = HstsList {
+ entries_map: entries_map
+ };
+
+ assert!(!hsts_list.is_host_secure("servo-mozilla.org"));
+}
+
+#[test]
+fn test_hsts_list_with_subdomain_when_host_is_exact_match_is_is_host_secure() {
+ let mut entries_map = HashMap::new();
+ entries_map.insert("mozilla.org".to_owned(), vec![HstsEntry::new("mozilla.org".to_owned(),
+ IncludeSubdomains::Included, None).unwrap()]);
+ let hsts_list = HstsList {
+ entries_map: entries_map
+ };
+
+ assert!(hsts_list.is_host_secure("mozilla.org"));
+}
+
+#[test]
+fn test_hsts_list_with_expired_entry_is_not_is_host_secure() {
+ let mut entries_map = HashMap::new();
+ entries_map.insert("mozilla.org".to_owned(), vec![HstsEntry {
+ host: "mozilla.org".to_owned(),
+ include_subdomains: false,
+ max_age: Some(20),
+ timestamp: Some(time::get_time().sec as u64 - 100u64)
+ }]);
+ let hsts_list = HstsList {
+ entries_map: entries_map
+ };
+
+ assert!(!hsts_list.is_host_secure("mozilla.org"));
+}
+
+#[test]
+fn test_preload_hsts_domains_well_formed() {
+ let hsts_list = HstsList::from_servo_preload();
+ assert!(!hsts_list.entries_map.is_empty());
+}
diff --git a/components/net/tests/http_loader.rs b/components/net/tests/http_loader.rs
new file mode 100644
index 00000000000..bff34263a52
--- /dev/null
+++ b/components/net/tests/http_loader.rs
@@ -0,0 +1,1186 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use cookie_rs::Cookie as CookiePair;
+use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, NetworkEvent};
+use devtools_traits::HttpRequest as DevtoolsHttpRequest;
+use devtools_traits::HttpResponse as DevtoolsHttpResponse;
+use fetch;
+use fetch_with_context;
+use flate2::Compression;
+use flate2::write::{DeflateEncoder, GzEncoder};
+use hyper::LanguageTag;
+use hyper::header::{Accept, AcceptEncoding, ContentEncoding, ContentLength, Cookie as CookieHeader};
+use hyper::header::{AcceptLanguage, AccessControlAllowOrigin, Authorization, Basic, Date};
+use hyper::header::{Encoding, Headers, Host, Location, Origin, Quality, QualityItem, SetCookie, qitem};
+use hyper::header::{StrictTransportSecurity, UserAgent};
+use hyper::method::Method;
+use hyper::mime::{Mime, SubLevel, TopLevel};
+use hyper::server::{Request as HyperRequest, Response as HyperResponse};
+use hyper::status::StatusCode;
+use hyper::uri::RequestUri;
+use make_server;
+use msg::constellation_msg::TEST_PIPELINE_ID;
+use net::cookie::Cookie;
+use net::cookie_storage::CookieStorage;
+use net::resource_thread::AuthCacheEntry;
+use net::test::replace_host_table;
+use net_traits::{CookieSource, NetworkError};
+use net_traits::request::{Request, RequestInit, RequestMode, CredentialsMode, Destination};
+use net_traits::response::ResponseBody;
+use new_fetch_context;
+use servo_url::{ServoUrl, ImmutableOrigin};
+use std::collections::HashMap;
+use std::io::{Read, Write};
+use std::str::FromStr;
+use std::sync::{Arc, Mutex, RwLock, mpsc};
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::mpsc::Receiver;
+
+fn mock_origin() -> ImmutableOrigin {
+ ServoUrl::parse("http://servo.org").unwrap().origin()
+}
+
+fn read_response(reader: &mut Read) -> String {
+ let mut buf = vec![0; 1024];
+ match reader.read(&mut buf) {
+ Ok(len) if len > 0 => {
+ unsafe { buf.set_len(len); }
+ String::from_utf8(buf).unwrap()
+ },
+ Ok(_) => "".to_owned(),
+ Err(e) => panic!("problem reading response {}", e)
+ }
+}
+
+fn assert_cookie_for_domain(cookie_jar: &RwLock<CookieStorage>, domain: &str, cookie: Option<&str>) {
+ let mut cookie_jar = cookie_jar.write().unwrap();
+ let url = ServoUrl::parse(&*domain).unwrap();
+ let cookies = cookie_jar.cookies_for_url(&url, CookieSource::HTTP);
+ assert_eq!(cookies.as_ref().map(|c| &**c), cookie);
+}
+
+pub fn expect_devtools_http_request(devtools_port: &Receiver<DevtoolsControlMsg>) -> DevtoolsHttpRequest {
+ match devtools_port.recv().unwrap() {
+ DevtoolsControlMsg::FromChrome(
+ ChromeToDevtoolsControlMsg::NetworkEvent(_, net_event)) => {
+ match net_event {
+ NetworkEvent::HttpRequest(httprequest) => {
+ httprequest
+ },
+
+ _ => panic!("No HttpRequest Received"),
+ }
+ },
+ _ => panic!("No HttpRequest Received"),
+ }
+}
+
+pub fn expect_devtools_http_response(devtools_port: &Receiver<DevtoolsControlMsg>) -> DevtoolsHttpResponse {
+ match devtools_port.recv().unwrap() {
+ DevtoolsControlMsg::FromChrome(
+ ChromeToDevtoolsControlMsg::NetworkEvent(_, net_event_response)) => {
+ match net_event_response {
+ NetworkEvent::HttpResponse(httpresponse) => {
+ httpresponse
+ },
+
+ _ => panic!("No HttpResponse Received"),
+ }
+ },
+ _ => panic!("No HttpResponse Received"),
+ }
+}
+
+#[test]
+fn test_check_default_headers_loaded_in_every_request() {
+ let expected_headers = Arc::new(Mutex::new(None));
+ let expected_headers_clone = expected_headers.clone();
+ let handler = move |request: HyperRequest, _: HyperResponse| {
+ assert_eq!(request.headers, expected_headers_clone.lock().unwrap().take().unwrap());
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut headers = Headers::new();
+
+ headers.set(AcceptEncoding(vec![qitem(Encoding::Gzip),
+ qitem(Encoding::Deflate),
+ qitem(Encoding::EncodingExt("br".to_owned()))]));
+
+ let hostname = match url.host_str() {
+ Some(hostname) => hostname.to_owned(),
+ _ => panic!()
+ };
+
+ headers.set(Host { hostname: hostname, port: url.port() });
+
+ let accept = Accept(vec![
+ qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
+ qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_owned()), vec![])),
+ QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900u16)),
+ QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800u16)),
+ ]);
+ headers.set(accept);
+
+ let mut en_us: LanguageTag = Default::default();
+ en_us.language = Some("en".to_owned());
+ en_us.region = Some("US".to_owned());
+ let mut en: LanguageTag = Default::default();
+ en.language = Some("en".to_owned());
+ headers.set(AcceptLanguage(vec![
+ qitem(en_us),
+ QualityItem::new(en, Quality(500)),
+ ]));
+
+ headers.set(UserAgent(::DEFAULT_USER_AGENT.to_owned()));
+
+ *expected_headers.lock().unwrap() = Some(headers.clone());
+
+ // Testing for method.GET
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ destination: Destination::Document,
+ origin: url.clone().origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ // Testing for method.POST
+ let mut post_headers = headers.clone();
+ post_headers.set(ContentLength(0 as u64));
+ let url_str = url.as_str();
+ // request gets header "Origin: http://example.com" but expected_headers has
+ // "Origin: http://example.com/" which do not match for equality so strip trailing '/'
+ post_headers.set(Origin::from_str(&url_str[..url_str.len()-1]).unwrap());
+ *expected_headers.lock().unwrap() = Some(post_headers);
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Post,
+ destination: Destination::Document,
+ origin: url.clone().origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ let _ = server.close();
+}
+
+#[test]
+fn test_load_when_request_is_not_get_or_head_and_there_is_no_body_content_length_should_be_set_to_0() {
+ let handler = move |request: HyperRequest, _: HyperResponse| {
+ assert_eq!(request.headers.get::<ContentLength>(), Some(&ContentLength(0)));
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Post,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ let _ = server.close();
+}
+
+#[test]
+fn test_request_and_response_data_with_network_messages() {
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ response.headers_mut().set(Host { hostname: "foo.bar".to_owned(), port: None });
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request_headers = Headers::new();
+ request_headers.set(Host { hostname: "bar.foo".to_owned(), port: None });
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ headers: request_headers,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let (devtools_chan, devtools_port) = mpsc::channel();
+ let response = fetch(&mut request, Some(devtools_chan));
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ let _ = server.close();
+
+ // notification received from devtools
+ let devhttprequest = expect_devtools_http_request(&devtools_port);
+ let devhttpresponse = expect_devtools_http_response(&devtools_port);
+
+ //Creating default headers for request
+ let mut headers = Headers::new();
+
+ headers.set(AcceptEncoding(vec![
+ qitem(Encoding::Gzip),
+ qitem(Encoding::Deflate),
+ qitem(Encoding::EncodingExt("br".to_owned()))
+ ]));
+
+ headers.set(Host { hostname: url.host_str().unwrap().to_owned() , port: url.port() });
+
+ let accept = Accept(vec![
+ qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
+ qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_owned()), vec![])),
+ QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900u16)),
+ QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800u16)),
+ ]);
+ headers.set(accept);
+
+ let mut en_us: LanguageTag = Default::default();
+ en_us.language = Some("en".to_owned());
+ en_us.region = Some("US".to_owned());
+ let mut en: LanguageTag = Default::default();
+ en.language = Some("en".to_owned());
+ headers.set(AcceptLanguage(vec![
+ qitem(en_us),
+ QualityItem::new(en, Quality(500)),
+ ]));
+
+ headers.set(UserAgent(::DEFAULT_USER_AGENT.to_owned()));
+
+ let httprequest = DevtoolsHttpRequest {
+ url: url,
+ method: Method::Get,
+ headers: headers,
+ body: None,
+ pipeline_id: TEST_PIPELINE_ID,
+ startedDateTime: devhttprequest.startedDateTime,
+ timeStamp: devhttprequest.timeStamp,
+ connect_time: devhttprequest.connect_time,
+ send_time: devhttprequest.send_time,
+ is_xhr: false,
+ };
+
+ let content = "Yay!";
+ let mut response_headers = Headers::new();
+ response_headers.set(ContentLength(content.len() as u64));
+ response_headers.set(Host { hostname: "foo.bar".to_owned(), port: None });
+ response_headers.set(devhttpresponse.headers.as_ref().unwrap().get::<Date>().unwrap().clone());
+
+ let httpresponse = DevtoolsHttpResponse {
+ headers: Some(response_headers),
+ status: Some((200, b"OK".to_vec())),
+ body: None,
+ pipeline_id: TEST_PIPELINE_ID,
+ };
+
+ assert_eq!(devhttprequest, httprequest);
+ assert_eq!(devhttpresponse, httpresponse);
+}
+
+#[test]
+fn test_request_and_response_message_from_devtool_without_pipeline_id() {
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ response.headers_mut().set(Host { hostname: "foo.bar".to_owned(), port: None });
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: None,
+ .. RequestInit::default()
+ });
+ let (devtools_chan, devtools_port) = mpsc::channel();
+ let response = fetch(&mut request, Some(devtools_chan));
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ let _ = server.close();
+
+ // notification received from devtools
+ assert!(devtools_port.try_recv().is_err());
+}
+
+#[test]
+fn test_redirected_request_to_devtools() {
+ let post_handler = move |request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.method, Method::Get);
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut post_server, post_url) = make_server(post_handler);
+
+ let post_redirect_url = post_url.clone();
+ let pre_handler = move |request: HyperRequest, mut response: HyperResponse| {
+ assert_eq!(request.method, Method::Post);
+ response.headers_mut().set(Location(post_redirect_url.to_string()));
+ *response.status_mut() = StatusCode::MovedPermanently;
+ response.send(b"").unwrap();
+ };
+ let (mut pre_server, pre_url) = make_server(pre_handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: pre_url.clone(),
+ method: Method::Post,
+ destination: Destination::Document,
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let (devtools_chan, devtools_port) = mpsc::channel();
+ fetch(&mut request, Some(devtools_chan));
+
+ let _ = pre_server.close();
+ let _ = post_server.close();
+
+ let devhttprequest = expect_devtools_http_request(&devtools_port);
+ let devhttpresponse = expect_devtools_http_response(&devtools_port);
+
+ assert!(devhttprequest.method == Method::Post);
+ assert!(devhttprequest.url == pre_url);
+ assert!(devhttpresponse.status == Some((301, b"Moved Permanently".to_vec())));
+
+ let devhttprequest = expect_devtools_http_request(&devtools_port);
+ let devhttpresponse = expect_devtools_http_response(&devtools_port);
+
+ assert!(devhttprequest.method == Method::Get);
+ assert!(devhttprequest.url == post_url);
+ assert!(devhttpresponse.status == Some((200, b"OK".to_vec())));
+}
+
+
+
+#[test]
+fn test_load_when_redirecting_from_a_post_should_rewrite_next_request_as_get() {
+ let post_handler = move |request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.method, Method::Get);
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut post_server, post_url) = make_server(post_handler);
+
+ let post_redirect_url = post_url.clone();
+ let pre_handler = move |request: HyperRequest, mut response: HyperResponse| {
+ assert_eq!(request.method, Method::Post);
+ response.headers_mut().set(Location(post_redirect_url.to_string()));
+ *response.status_mut() = StatusCode::MovedPermanently;
+ response.send(b"").unwrap();
+ };
+ let (mut pre_server, pre_url) = make_server(pre_handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: pre_url.clone(),
+ method: Method::Post,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = pre_server.close();
+ let _ = post_server.close();
+
+ assert!(response.to_actual().status.unwrap().is_success());
+}
+
+#[test]
+fn test_load_should_decode_the_response_as_deflate_when_response_headers_have_content_encoding_deflate() {
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ response.headers_mut().set(ContentEncoding(vec![Encoding::Deflate]));
+ let mut e = DeflateEncoder::new(Vec::new(), Compression::Default);
+ e.write(b"Yay!").unwrap();
+ let encoded_content = e.finish().unwrap();
+ response.send(&encoded_content).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ let internal_response = response.internal_response.unwrap();
+ assert!(internal_response.status.unwrap().is_success());
+ assert_eq!(*internal_response.body.lock().unwrap(),
+ ResponseBody::Done(b"Yay!".to_vec()));
+}
+
+#[test]
+fn test_load_should_decode_the_response_as_gzip_when_response_headers_have_content_encoding_gzip() {
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ response.headers_mut().set(ContentEncoding(vec![Encoding::Gzip]));
+ let mut e = GzEncoder::new(Vec::new(), Compression::Default);
+ e.write(b"Yay!").unwrap();
+ let encoded_content = e.finish().unwrap();
+ response.send(&encoded_content).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ let internal_response = response.internal_response.unwrap();
+ assert!(internal_response.status.unwrap().is_success());
+ assert_eq!(*internal_response.body.lock().unwrap(),
+ ResponseBody::Done(b"Yay!".to_vec()));
+}
+
+#[test]
+fn test_load_doesnt_send_request_body_on_any_redirect() {
+ let post_handler = move |mut request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.method, Method::Get);
+ let data = read_response(&mut request);
+ assert_eq!(data, "");
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut post_server, post_url) = make_server(post_handler);
+
+ let post_redirect_url = post_url.clone();
+ let pre_handler = move |mut request: HyperRequest, mut response: HyperResponse| {
+ let data = read_response(&mut request);
+ assert_eq!(data, "Body on POST!");
+ response.headers_mut().set(Location(post_redirect_url.to_string()));
+ *response.status_mut() = StatusCode::MovedPermanently;
+ response.send(b"").unwrap();
+ };
+ let (mut pre_server, pre_url) = make_server(pre_handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: pre_url.clone(),
+ body: Some(b"Body on POST!".to_vec()),
+ method: Method::Post,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = pre_server.close();
+ let _ = post_server.close();
+
+ assert!(response.to_actual().status.unwrap().is_success());
+}
+
+#[test]
+fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_are_present() {
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ response.headers_mut().set(StrictTransportSecurity::excluding_subdomains(31536000));
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let context = new_fetch_context(None);
+ let response = fetch_with_context(&mut request, &context);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+ assert_eq!(context.state.hsts_list.read().unwrap().is_host_secure(url.host_str().unwrap()), false);
+}
+
+#[test]
+fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_in_response() {
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ response.headers_mut().set(SetCookie(vec!["mozillaIs=theBest".to_owned()]));
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let context = new_fetch_context(None);
+
+ assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ credentials_mode: CredentialsMode::Include,
+ .. RequestInit::default()
+ });
+ let response = fetch_with_context(&mut request, &context);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), Some("mozillaIs=theBest"));
+}
+
+#[test]
+fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_resource_manager() {
+ let handler = move |request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.headers.get::<CookieHeader>(),
+ Some(&CookieHeader(vec!["mozillaIs=theBest".to_owned()])));
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let context = new_fetch_context(None);
+
+ {
+ let mut cookie_jar = context.state.cookie_jar.write().unwrap();
+ let cookie = Cookie::new_wrapped(
+ CookiePair::new("mozillaIs".to_owned(), "theBest".to_owned()),
+ &url,
+ CookieSource::HTTP
+ ).unwrap();
+ cookie_jar.push(cookie, &url, CookieSource::HTTP);
+ }
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ credentials_mode: CredentialsMode::Include,
+ .. RequestInit::default()
+ });
+ let response = fetch_with_context(&mut request, &context);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+}
+
+#[test]
+fn test_load_sends_cookie_if_nonhttp() {
+ let handler = move |request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.headers.get::<CookieHeader>(),
+ Some(&CookieHeader(vec!["mozillaIs=theBest".to_owned()])));
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let context = new_fetch_context(None);
+
+ {
+ let mut cookie_jar = context.state.cookie_jar.write().unwrap();
+ let cookie = Cookie::new_wrapped(
+ CookiePair::new("mozillaIs".to_owned(), "theBest".to_owned()),
+ &url,
+ CookieSource::NonHTTP
+ ).unwrap();
+ cookie_jar.push(cookie, &url, CookieSource::HTTP);
+ }
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ credentials_mode: CredentialsMode::Include,
+ .. RequestInit::default()
+ });
+ let response = fetch_with_context(&mut request, &context);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+}
+
+#[test]
+fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl() {
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ let pair = vec!["mozillaIs=theBest; HttpOnly".to_owned()];
+ response.headers_mut().set(SetCookie(pair));
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let context = new_fetch_context(None);
+
+ assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ credentials_mode: CredentialsMode::Include,
+ .. RequestInit::default()
+ });
+ let response = fetch_with_context(&mut request, &context);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), Some("mozillaIs=theBest"));
+ let mut cookie_jar = context.state.cookie_jar.write().unwrap();
+ assert!(cookie_jar.cookies_for_url(&url, CookieSource::NonHTTP).is_none());
+}
+
+#[test]
+fn test_when_cookie_received_marked_secure_is_ignored_for_http() {
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ let pair = vec!["mozillaIs=theBest; Secure".to_owned()];
+ response.headers_mut().set(SetCookie(pair));
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let context = new_fetch_context(None);
+
+ assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ credentials_mode: CredentialsMode::Include,
+ .. RequestInit::default()
+ });
+ let response = fetch_with_context(&mut request, &context);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
+}
+
+#[test]
+fn test_load_sets_content_length_to_length_of_request_body() {
+ let content = b"This is a request body";
+ let content_length = ContentLength(content.len() as u64);
+ let handler = move |request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.headers.get::<ContentLength>(), Some(&content_length));
+ response.send(content).unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Post,
+ body: Some(content.to_vec()),
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+}
+
+#[test]
+fn test_load_uses_explicit_accept_from_headers_in_load_data() {
+ let accept = Accept(vec![qitem(Mime(TopLevel::Text, SubLevel::Html, vec![]))]);
+ let expected_accept = accept.clone();
+ let handler = move |request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.headers.get::<Accept>(), Some(&expected_accept));
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut accept_headers = Headers::new();
+ accept_headers.set(accept);
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ headers: accept_headers,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+}
+
+#[test]
+fn test_load_sets_default_accept_to_html_xhtml_xml_and_then_anything_else() {
+ let handler = move |request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.headers.get::<Accept>(), Some(&Accept(vec![
+ qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
+ qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_owned()), vec![])),
+ QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900)),
+ QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800)),
+ ])));
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+}
+
+#[test]
+fn test_load_uses_explicit_accept_encoding_from_load_data_headers() {
+ let accept_encoding = AcceptEncoding(vec![qitem(Encoding::Chunked)]);
+ let expected_accept_encoding = accept_encoding.clone();
+ let handler = move |request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.headers.get::<AcceptEncoding>(), Some(&expected_accept_encoding));
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut accept_encoding_headers = Headers::new();
+ accept_encoding_headers.set(accept_encoding);
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ headers: accept_encoding_headers,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+}
+
+#[test]
+fn test_load_sets_default_accept_encoding_to_gzip_and_deflate() {
+ let handler = move |request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.headers.get::<AcceptEncoding>(), Some(&AcceptEncoding(vec![
+ qitem(Encoding::Gzip),
+ qitem(Encoding::Deflate),
+ qitem(Encoding::EncodingExt("br".to_owned()))
+ ])));
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+}
+
+#[test]
+fn test_load_errors_when_there_a_redirect_loop() {
+ let url_b_for_a = Arc::new(Mutex::new(None::<ServoUrl>));
+ let url_b_for_a_clone = url_b_for_a.clone();
+ let handler_a = move |_: HyperRequest, mut response: HyperResponse| {
+ response.headers_mut().set(Location(url_b_for_a_clone.lock().unwrap().as_ref().unwrap().to_string()));
+ *response.status_mut() = StatusCode::MovedPermanently;
+ response.send(b"").unwrap();
+ };
+ let (mut server_a, url_a) = make_server(handler_a);
+
+ let url_a_for_b = url_a.clone();
+ let handler_b = move |_: HyperRequest, mut response: HyperResponse| {
+ response.headers_mut().set(Location(url_a_for_b.to_string()));
+ *response.status_mut() = StatusCode::MovedPermanently;
+ response.send(b"").unwrap();
+ };
+ let (mut server_b, url_b) = make_server(handler_b);
+
+ *url_b_for_a.lock().unwrap() = Some(url_b.clone());
+
+ let mut request = Request::from_init(RequestInit {
+ url: url_a.clone(),
+ method: Method::Get,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = server_a.close();
+ let _ = server_b.close();
+
+ assert_eq!(response.get_network_error(),
+ Some(&NetworkError::Internal("Too many redirects".to_owned())));
+}
+
+#[test]
+fn test_load_succeeds_with_a_redirect_loop() {
+ let url_b_for_a = Arc::new(Mutex::new(None::<ServoUrl>));
+ let url_b_for_a_clone = url_b_for_a.clone();
+ let handled_a = AtomicBool::new(false);
+ let handler_a = move |_: HyperRequest, mut response: HyperResponse| {
+ if !handled_a.swap(true, Ordering::SeqCst) {
+ response.headers_mut().set(Location(url_b_for_a_clone.lock().unwrap().as_ref().unwrap().to_string()));
+ *response.status_mut() = StatusCode::MovedPermanently;
+ response.send(b"").unwrap();
+ } else {
+ response.send(b"Success").unwrap();
+ }
+ };
+ let (mut server_a, url_a) = make_server(handler_a);
+
+ let url_a_for_b = url_a.clone();
+ let handler_b = move |_: HyperRequest, mut response: HyperResponse| {
+ response.headers_mut().set(Location(url_a_for_b.to_string()));
+ *response.status_mut() = StatusCode::MovedPermanently;
+ response.send(b"").unwrap();
+ };
+ let (mut server_b, url_b) = make_server(handler_b);
+
+ *url_b_for_a.lock().unwrap() = Some(url_b.clone());
+
+ let mut request = Request::from_init(RequestInit {
+ url: url_a.clone(),
+ method: Method::Get,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = server_a.close();
+ let _ = server_b.close();
+
+ let response = response.to_actual();
+ assert_eq!(response.url_list, [url_a.clone(), url_b, url_a]);
+ assert_eq!(*response.body.lock().unwrap(),
+ ResponseBody::Done(b"Success".to_vec()));
+}
+
+#[test]
+fn test_load_follows_a_redirect() {
+ let post_handler = move |request: HyperRequest, response: HyperResponse| {
+ assert_eq!(request.method, Method::Get);
+ response.send(b"Yay!").unwrap();
+ };
+ let (mut post_server, post_url) = make_server(post_handler);
+
+ let post_redirect_url = post_url.clone();
+ let pre_handler = move |request: HyperRequest, mut response: HyperResponse| {
+ assert_eq!(request.method, Method::Get);
+ response.headers_mut().set(Location(post_redirect_url.to_string()));
+ *response.status_mut() = StatusCode::MovedPermanently;
+ response.send(b"").unwrap();
+ };
+ let (mut pre_server, pre_url) = make_server(pre_handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: pre_url.clone(),
+ method: Method::Get,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = pre_server.close();
+ let _ = post_server.close();
+
+ let internal_response = response.internal_response.unwrap();
+ assert!(internal_response.status.unwrap().is_success());
+ assert_eq!(*internal_response.body.lock().unwrap(),
+ ResponseBody::Done(b"Yay!".to_vec()));
+}
+
+#[test]
+fn test_redirect_from_x_to_y_provides_y_cookies_from_y() {
+ let shared_url_y = Arc::new(Mutex::new(None::<ServoUrl>));
+ let shared_url_y_clone = shared_url_y.clone();
+ let handler = move |request: HyperRequest, mut response: HyperResponse| {
+ let path = match request.uri {
+ RequestUri::AbsolutePath(path) => path,
+ uri => panic!("Unexpected uri: {:?}", uri),
+ };
+ if path == "/com/" {
+ assert_eq!(request.headers.get(),
+ Some(&CookieHeader(vec!["mozillaIsNot=dotOrg".to_owned()])));
+ let location = shared_url_y.lock().unwrap().as_ref().unwrap().to_string();
+ response.headers_mut().set(Location(location));
+ *response.status_mut() = StatusCode::MovedPermanently;
+ response.send(b"").unwrap();
+ } else if path == "/org/" {
+ assert_eq!(request.headers.get(),
+ Some(&CookieHeader(vec!["mozillaIs=theBest".to_owned()])));
+ response.send(b"Yay!").unwrap();
+ } else {
+ panic!("unexpected path {:?}", path)
+ }
+ };
+ let (mut server, url) = make_server(handler);
+ let port = url.port().unwrap();
+
+ assert_eq!(url.host_str(), Some("localhost"));
+ let ip = "127.0.0.1".parse().unwrap();
+ let mut host_table = HashMap::new();
+ host_table.insert("mozilla.com".to_owned(), ip);
+ host_table.insert("mozilla.org".to_owned(), ip);
+
+ replace_host_table(host_table);
+
+ let url_x = ServoUrl::parse(&format!("http://mozilla.com:{}/com/", port)).unwrap();
+ let url_y = ServoUrl::parse(&format!("http://mozilla.org:{}/org/", port)).unwrap();
+ *shared_url_y_clone.lock().unwrap() = Some(url_y.clone());
+
+ let context = new_fetch_context(None);
+ {
+ let mut cookie_jar = context.state.cookie_jar.write().unwrap();
+ let cookie_x = Cookie::new_wrapped(
+ CookiePair::new("mozillaIsNot".to_owned(), "dotOrg".to_owned()),
+ &url_x,
+ CookieSource::HTTP
+ ).unwrap();
+
+ cookie_jar.push(cookie_x, &url_x, CookieSource::HTTP);
+
+ let cookie_y = Cookie::new_wrapped(
+ CookiePair::new("mozillaIs".to_owned(), "theBest".to_owned()),
+ &url_y,
+ CookieSource::HTTP
+ ).unwrap();
+ cookie_jar.push(cookie_y, &url_y, CookieSource::HTTP);
+ }
+
+ let mut request = Request::from_init(RequestInit {
+ url: url_x.clone(),
+ method: Method::Get,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ credentials_mode: CredentialsMode::Include,
+ .. RequestInit::default()
+ });
+ let response = fetch_with_context(&mut request, &context);
+
+ let _ = server.close();
+
+ let internal_response = response.internal_response.unwrap();
+ assert!(internal_response.status.unwrap().is_success());
+ assert_eq!(*internal_response.body.lock().unwrap(),
+ ResponseBody::Done(b"Yay!".to_vec()));
+}
+
+#[test]
+fn test_redirect_from_x_to_x_provides_x_with_cookie_from_first_response() {
+ let handler = move |request: HyperRequest, mut response: HyperResponse| {
+ let path = match request.uri {
+ ::hyper::uri::RequestUri::AbsolutePath(path) => path,
+ uri => panic!("Unexpected uri: {:?}", uri),
+ };
+ if path == "/initial/" {
+ response.headers_mut().set_raw("set-cookie", vec![b"mozillaIs=theBest; path=/;".to_vec()]);
+ let location = "/subsequent/".to_string();
+ response.headers_mut().set(Location(location));
+ *response.status_mut() = StatusCode::MovedPermanently;
+ response.send(b"").unwrap();
+ } else if path == "/subsequent/" {
+ assert_eq!(request.headers.get(),
+ Some(&CookieHeader(vec!["mozillaIs=theBest".to_owned()])));
+ response.send(b"Yay!").unwrap();
+ } else {
+ panic!("unexpected path {:?}", path)
+ }
+ };
+ let (mut server, url) = make_server(handler);
+
+ let url = url.join("/initial/").unwrap();
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ credentials_mode: CredentialsMode::Include,
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ let internal_response = response.internal_response.unwrap();
+ assert!(internal_response.status.unwrap().is_success());
+ assert_eq!(*internal_response.body.lock().unwrap(),
+ ResponseBody::Done(b"Yay!".to_vec()));
+}
+
+#[test]
+fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() {
+ let handler = move |request: HyperRequest, response: HyperResponse| {
+ let expected = Authorization(Basic {
+ username: "username".to_owned(),
+ password: Some("test".to_owned())
+ });
+ assert_eq!(request.headers.get(), Some(&expected));
+ response.send(b"").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ credentials_mode: CredentialsMode::Include,
+ .. RequestInit::default()
+ });
+ let context = new_fetch_context(None);
+
+ let auth_entry = AuthCacheEntry {
+ user_name: "username".to_owned(),
+ password: "test".to_owned(),
+ };
+
+ context.state.auth_cache.write().unwrap().entries.insert(url.origin().clone().ascii_serialization(), auth_entry);
+
+ let response = fetch_with_context(&mut request, &context);
+
+ let _ = server.close();
+
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+}
+
+#[test]
+fn test_auth_ui_needs_www_auth() {
+ let handler = move |_: HyperRequest, mut response: HyperResponse| {
+ *response.status_mut() = StatusCode::Unauthorized;
+ response.send(b"").unwrap();
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ body: None,
+ destination: Destination::Document,
+ origin: mock_origin(),
+ pipeline_id: Some(TEST_PIPELINE_ID),
+ credentials_mode: CredentialsMode::Include,
+ .. RequestInit::default()
+ });
+
+ let response = fetch(&mut request, None);
+
+ let _ = server.close();
+
+ assert_eq!(response.internal_response.unwrap().status.unwrap(), StatusCode::Unauthorized);
+}
+
+#[test]
+fn test_origin_set() {
+ let origin_header = Arc::new(Mutex::new(None));
+ let origin_header_clone = origin_header.clone();
+ let handler = move |request: HyperRequest, mut resp: HyperResponse| {
+ let origin_header_clone = origin_header.clone();
+ resp.headers_mut().set(AccessControlAllowOrigin::Any);
+ match request.headers.get::<Origin>() {
+ None => assert_eq!(origin_header_clone.lock().unwrap().take(), None),
+ Some(h) => assert_eq!(*h, origin_header_clone.lock().unwrap().take().unwrap()),
+ }
+ };
+ let (mut server, url) = make_server(handler);
+
+ let mut origin = Origin::new(url.scheme(), url.host_str().unwrap(), url.port());
+ *origin_header_clone.lock().unwrap() = Some(origin.clone());
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Post,
+ body: None,
+ origin: url.clone().origin(),
+ .. RequestInit::default()
+ });
+ let response = fetch(&mut request, None);
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ let origin_url = ServoUrl::parse("http://example.com").unwrap();
+ origin = Origin::new(origin_url.scheme(), origin_url.host_str().unwrap(), origin_url.port());
+ // Test Origin header is set on Get request with CORS mode
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Get,
+ mode: RequestMode::CorsMode,
+ body: None,
+ origin: origin_url.clone().origin(),
+ .. RequestInit::default()
+ });
+
+ *origin_header_clone.lock().unwrap() = Some(origin.clone());
+ let response = fetch(&mut request, None);
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ // Test Origin header is not set on method Head
+ let mut request = Request::from_init(RequestInit {
+ url: url.clone(),
+ method: Method::Head,
+ body: None,
+ origin: url.clone().origin(),
+ .. RequestInit::default()
+ });
+
+ *origin_header_clone.lock().unwrap() = None;
+ let response = fetch(&mut request, None);
+ assert!(response.internal_response.unwrap().status.unwrap().is_success());
+
+ let _ = server.close();
+}
diff --git a/components/net/tests/main.rs b/components/net/tests/main.rs
new file mode 100644
index 00000000000..773b7f387f8
--- /dev/null
+++ b/components/net/tests/main.rs
@@ -0,0 +1,112 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#![cfg(test)]
+
+extern crate cookie as cookie_rs;
+extern crate devtools_traits;
+extern crate flate2;
+extern crate hyper;
+extern crate hyper_openssl;
+extern crate hyper_serde;
+extern crate ipc_channel;
+extern crate msg;
+extern crate net;
+extern crate net_traits;
+extern crate profile_traits;
+extern crate servo_config;
+extern crate servo_url;
+extern crate time;
+extern crate unicase;
+extern crate url;
+
+mod chrome_loader;
+mod cookie;
+mod cookie_http_state;
+mod data_loader;
+mod fetch;
+mod file_loader;
+mod filemanager_thread;
+mod hsts;
+mod http_loader;
+mod mime_classifier;
+mod resource_thread;
+mod subresource_integrity;
+
+use devtools_traits::DevtoolsControlMsg;
+use hyper::server::{Handler, Listening, Server};
+use net::connector::create_ssl_client;
+use net::fetch::cors_cache::CorsCache;
+use net::fetch::methods::{self, CancellationListener, FetchContext};
+use net::filemanager_thread::FileManager;
+use net::test::HttpState;
+use net_traits::FetchTaskTarget;
+use net_traits::request::Request;
+use net_traits::response::Response;
+use servo_config::resource_files::resources_dir_path;
+use servo_url::ServoUrl;
+use std::sync::{Arc, Mutex};
+use std::sync::mpsc::{Sender, channel};
+
+const DEFAULT_USER_AGENT: &'static str = "Such Browser. Very Layout. Wow.";
+
+struct FetchResponseCollector {
+ sender: Sender<Response>,
+}
+
+fn new_fetch_context(dc: Option<Sender<DevtoolsControlMsg>>) -> FetchContext {
+ let ca_file = resources_dir_path().unwrap().join("certs");
+ let ssl_client = create_ssl_client(&ca_file);
+ FetchContext {
+ state: Arc::new(HttpState::new(ssl_client)),
+ user_agent: DEFAULT_USER_AGENT.into(),
+ devtools_chan: dc,
+ filemanager: FileManager::new(),
+ cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
+ }
+}
+impl FetchTaskTarget for FetchResponseCollector {
+ fn process_request_body(&mut self, _: &Request) {}
+ fn process_request_eof(&mut self, _: &Request) {}
+ fn process_response(&mut self, _: &Response) {}
+ fn process_response_chunk(&mut self, _: Vec<u8>) {}
+ /// Fired when the response is fully fetched
+ fn process_response_eof(&mut self, response: &Response) {
+ let _ = self.sender.send(response.clone());
+ }
+}
+
+fn fetch(request: &mut Request, dc: Option<Sender<DevtoolsControlMsg>>) -> Response {
+ fetch_with_context(request, &new_fetch_context(dc))
+}
+
+fn fetch_with_context(request: &mut Request, context: &FetchContext) -> Response {
+ let (sender, receiver) = channel();
+ let mut target = FetchResponseCollector {
+ sender: sender,
+ };
+
+ methods::fetch(request, &mut target, context);
+
+ receiver.recv().unwrap()
+}
+
+fn fetch_with_cors_cache(request: &mut Request, cache: &mut CorsCache) -> Response {
+ let (sender, receiver) = channel();
+ let mut target = FetchResponseCollector {
+ sender: sender,
+ };
+
+ methods::fetch_with_cors_cache(request, cache, &mut target, &new_fetch_context(None));
+
+ receiver.recv().unwrap()
+}
+
+fn make_server<H: Handler + 'static>(handler: H) -> (Listening, ServoUrl) {
+ // this is a Listening server because of handle_threads()
+ let server = Server::http("0.0.0.0:0").unwrap().handle_threads(handler, 2).unwrap();
+ let url_string = format!("http://localhost:{}", server.socket.port());
+ let url = ServoUrl::parse(&url_string).unwrap();
+ (server, url)
+}
diff --git a/components/net/tests/mime_classifier.rs b/components/net/tests/mime_classifier.rs
new file mode 100644
index 00000000000..1a4757ded5f
--- /dev/null
+++ b/components/net/tests/mime_classifier.rs
@@ -0,0 +1,560 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use net::mime_classifier::{ApacheBugFlag, MimeClassifier, Mp4Matcher, NoSniffFlag};
+use net::mime_classifier::as_string_option;
+use net_traits::LoadContext;
+use std::env;
+use std::fs::File;
+use std::io::{self, Read};
+use std::path::{self, PathBuf};
+
+fn read_file(path: &path::Path) -> io::Result<Vec<u8>> {
+ let mut file = File::open(path)?;
+ let mut buffer = Vec::new();
+
+ file.read_to_end(&mut buffer)?;
+
+ Ok(buffer)
+}
+
+#[test]
+fn test_sniff_mp4_matcher() {
+ let matcher = Mp4Matcher;
+
+ let p = PathBuf::from("tests/parsable_mime/video/mp4/test.mp4");
+ let read_result = read_file(&p);
+
+ match read_result {
+ Ok(data) => {
+ println!("Data Length {:?}", data.len());
+ if !matcher.matches(&data) {
+ panic!("Didn't read mime type")
+ }
+ },
+ Err(e) => panic!("Couldn't read from file with error {}", e)
+ }
+}
+
+#[test]
+fn test_sniff_mp4_matcher_long() {
+ // Check that a multi-byte length is calculated correctly
+ let matcher = Mp4Matcher;
+
+ let mut data: [u8; 260] = [0; 260];
+ &data[.. 11].clone_from_slice(
+ &[0x00, 0x00, 0x01, 0x04, 0x66, 0x74, 0x79, 0x70, 0x6D, 0x70, 0x34]
+ );
+
+ assert!(matcher.matches(&data));
+}
+
+#[test]
+fn test_validate_classifier() {
+ let classifier = MimeClassifier::new();
+ classifier.validate().expect("Validation error")
+}
+
+#[cfg(test)]
+fn test_sniff_with_flags(filename_orig: &path::Path,
+ type_string: &str,
+ subtype_string: &str,
+ supplied_type: Option<(&'static str, &'static str)>,
+ no_sniff_flag: NoSniffFlag,
+ apache_bug_flag: ApacheBugFlag) {
+ let current_working_directory = env::current_dir().unwrap();
+ println!("The current directory is {}", current_working_directory.display());
+
+ let mut filename = PathBuf::from("tests/parsable_mime/");
+ filename.push(filename_orig);
+
+ let classifier = MimeClassifier::new();
+
+ let read_result = read_file(&filename);
+
+ match read_result {
+ Ok(data) => {
+ let supplied_type = supplied_type.map(|(x, y)| (x.parse().unwrap(), y));
+ let (parsed_type, parsed_subtp) = classifier.classify(LoadContext::Browsing,
+ no_sniff_flag,
+ apache_bug_flag,
+ &as_string_option(supplied_type),
+ &data);
+ if (&parsed_type[..] != type_string) ||
+ (&parsed_subtp[..] != subtype_string) {
+ panic!("File {:?} parsed incorrectly should be {}/{}, parsed as {}/{}",
+ filename, type_string, subtype_string,
+ parsed_type, parsed_subtp);
+ }
+ }
+ Err(e) => panic!("Couldn't read from file {:?} with error {}",
+ filename, e),
+ }
+}
+
+#[cfg(test)]
+fn test_sniff_full(filename_orig: &path::Path, type_string: &str, subtype_string: &str,
+ supplied_type: Option<(&'static str, &'static str)>) {
+ test_sniff_with_flags(filename_orig,
+ type_string,
+ subtype_string,
+ supplied_type,
+ NoSniffFlag::Off,
+ ApacheBugFlag::Off)
+}
+
+#[cfg(test)]
+fn test_sniff_classification(file: &str, type_string: &str, subtype_string: &str,
+ supplied_type: Option<(&'static str, &'static str)>) {
+ let mut x = PathBuf::from("./");
+ x.push(type_string);
+ x.push(subtype_string);
+ x.push(file);
+ test_sniff_full(&x, type_string, subtype_string, supplied_type);
+}
+#[cfg(test)]
+fn test_sniff_classification_sup(file: &str, type_string: &'static str, subtype_string: &str) {
+ test_sniff_classification(file, type_string, subtype_string, None);
+ let class_type = Some((type_string, ""));
+ test_sniff_classification(file, type_string, subtype_string, class_type);
+}
+
+#[test]
+fn test_sniff_x_icon() {
+ test_sniff_classification_sup("test.ico", "image", "x-icon");
+}
+
+#[test]
+fn test_sniff_x_icon_cursor() {
+ test_sniff_classification_sup("test_cursor.ico", "image", "x-icon");
+}
+
+#[test]
+fn test_sniff_bmp() {
+ test_sniff_classification_sup("test.bmp", "image", "bmp");
+}
+
+#[test]
+fn test_sniff_gif87a() {
+ test_sniff_classification_sup("test87a", "image", "gif");
+}
+
+#[test]
+fn test_sniff_gif89a() {
+ test_sniff_classification_sup("test89a.gif", "image", "gif");
+}
+
+#[test]
+fn test_sniff_webp() {
+ test_sniff_classification_sup("test.webp", "image", "webp");
+}
+
+#[test]
+fn test_sniff_png() {
+ test_sniff_classification_sup("test.png", "image", "png");
+}
+
+#[test]
+fn test_sniff_jpg() {
+ test_sniff_classification_sup("test.jpg", "image", "jpeg");
+}
+
+#[test]
+fn test_sniff_webm() {
+ test_sniff_classification_sup("test.webm", "video", "webm");
+}
+
+#[test]
+fn test_sniff_mp4() {
+ test_sniff_classification_sup("test.mp4", "video", "mp4");
+}
+
+#[test]
+fn test_sniff_avi() {
+ test_sniff_classification_sup("test.avi", "video", "avi");
+}
+
+#[test]
+fn test_sniff_basic() {
+ test_sniff_classification_sup("test.au", "audio", "basic");
+}
+
+#[test]
+fn test_sniff_aiff() {
+ test_sniff_classification_sup("test.aif", "audio", "aiff");
+}
+
+#[test]
+fn test_sniff_mpeg() {
+ test_sniff_classification_sup("test.mp3", "audio", "mpeg");
+}
+
+#[test]
+fn test_sniff_midi() {
+ test_sniff_classification_sup("test.mid", "audio", "midi");
+}
+
+#[test]
+fn test_sniff_wave() {
+ test_sniff_classification_sup("test.wav", "audio", "wave");
+}
+
+#[test]
+fn test_sniff_ogg() {
+ test_sniff_classification("small.ogg", "application", "ogg", None);
+ test_sniff_classification("small.ogg", "application", "ogg", Some(("audio", "")));
+}
+
+#[test]
+#[should_panic]
+fn test_sniff_vsn_ms_fontobject() {
+ test_sniff_classification_sup("vnd.ms-fontobject", "application", "vnd.ms-fontobject");
+}
+
+#[test]
+#[should_panic]
+fn test_sniff_true_type() {
+ test_sniff_full(&PathBuf::from("unknown/true_type.ttf"), "(TrueType)", "", None);
+}
+
+#[test]
+#[should_panic]
+fn test_sniff_open_type() {
+ test_sniff_full(&PathBuf::from("unknown/open_type"), "(OpenType)", "", None);
+}
+
+#[test]
+#[should_panic]
+fn test_sniff_true_type_collection() {
+ test_sniff_full(&PathBuf::from("unknown/true_type_collection.ttc"), "(TrueType Collection)", "", None);
+}
+
+#[test]
+#[should_panic]
+fn test_sniff_woff() {
+ test_sniff_classification_sup("test.wof", "application", "font-woff");
+}
+
+#[test]
+fn test_sniff_gzip() {
+ test_sniff_classification("test.gz", "application", "x-gzip", None);
+}
+
+#[test]
+fn test_sniff_zip() {
+ test_sniff_classification("test.zip", "application", "zip", None);
+}
+
+#[test]
+fn test_sniff_rar() {
+ test_sniff_classification("test.rar", "application", "x-rar-compressed", None);
+}
+
+#[test]
+fn test_sniff_text_html_doctype_20() {
+ test_sniff_classification("text_html_doctype_20.html", "text", "html", None);
+ test_sniff_classification("text_html_doctype_20_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_doctype_3e() {
+ test_sniff_classification("text_html_doctype_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_doctype_3e_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_page_20() {
+ test_sniff_classification("text_html_page_20.html", "text", "html", None);
+ test_sniff_classification("text_html_page_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_page_3e() {
+ test_sniff_classification("text_html_page_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_page_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_head_20() {
+ test_sniff_classification("text_html_head_20.html", "text", "html", None);
+ test_sniff_classification("text_html_head_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_head_3e() {
+ test_sniff_classification("text_html_head_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_head_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_script_20() {
+ test_sniff_classification("text_html_script_20.html", "text", "html", None);
+ test_sniff_classification("text_html_script_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_script_3e() {
+ test_sniff_classification("text_html_script_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_script_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_iframe_20() {
+ test_sniff_classification("text_html_iframe_20.html", "text", "html", None);
+ test_sniff_classification("text_html_iframe_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_iframe_3e() {
+ test_sniff_classification("text_html_iframe_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_iframe_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_h1_20() {
+ test_sniff_classification("text_html_h1_20.html", "text", "html", None);
+ test_sniff_classification("text_html_h1_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_h1_3e() {
+ test_sniff_classification("text_html_h1_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_h1_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_div_20() {
+ test_sniff_classification("text_html_div_20.html", "text", "html", None);
+ test_sniff_classification("text_html_div_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_div_3e() {
+ test_sniff_classification("text_html_div_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_div_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_font_20() {
+ test_sniff_classification("text_html_font_20.html", "text", "html", None);
+ test_sniff_classification("text_html_font_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_font_3e() {
+ test_sniff_classification("text_html_font_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_font_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_table_20() {
+ test_sniff_classification("text_html_table_20.html", "text", "html", None);
+ test_sniff_classification("text_html_table_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_table_3e() {
+ test_sniff_classification("text_html_table_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_table_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_a_20() {
+ test_sniff_classification("text_html_a_20.html", "text", "html", None);
+ test_sniff_classification("text_html_a_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_a_3e() {
+ test_sniff_classification("text_html_a_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_a_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_style_20() {
+ test_sniff_classification("text_html_style_20.html", "text", "html", None);
+ test_sniff_classification("text_html_style_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_style_3e() {
+ test_sniff_classification("text_html_style_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_style_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_title_20() {
+ test_sniff_classification("text_html_title_20.html", "text", "html", None);
+ test_sniff_classification("text_html_title_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_title_3e() {
+ test_sniff_classification("text_html_title_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_title_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_b_20() {
+ test_sniff_classification("text_html_b_20.html", "text", "html", None);
+ test_sniff_classification("text_html_b_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_b_3e() {
+ test_sniff_classification("text_html_b_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_b_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_body_20() {
+ test_sniff_classification("text_html_body_20.html", "text", "html", None);
+ test_sniff_classification("text_html_body_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_body_3e() {
+ test_sniff_classification("text_html_body_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_body_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_br_20() {
+ test_sniff_classification("text_html_br_20.html", "text", "html", None);
+ test_sniff_classification("text_html_br_20_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_br_3e() {
+ test_sniff_classification("text_html_br_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_br_3e_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_p_20() {
+ test_sniff_classification("text_html_p_20.html", "text", "html", None);
+ test_sniff_classification("text_html_p_20_u.html", "text", "html", None);
+}
+#[test]
+fn test_sniff_text_html_p_3e() {
+ test_sniff_classification("text_html_p_3e.html", "text", "html", None);
+ test_sniff_classification("text_html_p_3e_u.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_comment_20() {
+ test_sniff_classification("text_html_comment_20.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_text_html_comment_3e() {
+ test_sniff_classification("text_html_comment_3e.html", "text", "html", None);
+}
+
+#[test]
+fn test_sniff_xml() {
+ test_sniff_classification("test.xml", "text", "xml", None);
+}
+
+#[test]
+fn test_sniff_pdf() {
+ test_sniff_classification("test.pdf", "application", "pdf", None);
+}
+
+#[test]
+fn test_sniff_postscript() {
+ test_sniff_classification("test.ps", "application", "postscript", None);
+}
+
+#[test]
+fn test_sniff_utf_16be_bom() {
+ test_sniff_classification("utf16bebom.txt", "text", "plain", None);
+}
+
+#[test]
+fn test_sniff_utf_16le_bom() {
+ test_sniff_classification("utf16lebom.txt", "text", "plain", None);
+}
+
+#[test]
+fn test_sniff_utf_8_bom() {
+ test_sniff_classification("utf8bom.txt", "text", "plain", None);
+}
+
+#[test]
+fn test_sniff_rss_feed() {
+ // RSS feeds
+ test_sniff_full(&PathBuf::from("text/xml/feed.rss"), "application", "rss+xml", Some(("text", "html")));
+ test_sniff_full(&PathBuf::from("text/xml/rdf_rss.xml"), "application", "rss+xml", Some(("text", "html")));
+ // Not RSS feeds
+ test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_1.xml"), "text", "html", Some(("text", "html")));
+ test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_2.xml"), "text", "html", Some(("text", "html")));
+ test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_3.xml"), "text", "html", Some(("text", "html")));
+ test_sniff_full(&PathBuf::from("text/xml/rdf_rss_ko_4.xml"), "text", "html", Some(("text", "html")));
+}
+
+#[test]
+fn test_sniff_atom_feed() {
+ test_sniff_full(&PathBuf::from("text/xml/feed.atom"), "application", "atom+xml", Some(("text", "html")));
+}
+
+#[test]
+fn test_sniff_binary_file() {
+ test_sniff_full(&PathBuf::from("unknown/binary_file"), "application", "octet-stream", None);
+}
+
+#[test]
+fn test_sniff_atom_feed_with_no_sniff_flag_on() {
+ test_sniff_with_flags(&PathBuf::from("text/xml/feed.atom"),
+ "text",
+ "html",
+ Some(("text", "html")),
+ NoSniffFlag::On,
+ ApacheBugFlag::Off);
+}
+
+#[test]
+fn test_sniff_with_no_sniff_flag_on_and_apache_flag_on() {
+ test_sniff_with_flags(&PathBuf::from("text/xml/feed.atom"),
+ "text",
+ "html",
+ Some(("text", "html")),
+ NoSniffFlag::On,
+ ApacheBugFlag::On);
+}
+
+#[test]
+fn test_sniff_utf_8_bom_with_apache_flag_on() {
+ test_sniff_with_flags(&PathBuf::from("text/plain/utf8bom.txt"),
+ "text",
+ "plain",
+ Some(("dummy", "text")),
+ NoSniffFlag::Off,
+ ApacheBugFlag::On);
+}
+
+#[test]
+fn test_sniff_utf_16be_bom_with_apache_flag_on() {
+ test_sniff_with_flags(&PathBuf::from("text/plain/utf16bebom.txt"),
+ "text",
+ "plain",
+ Some(("dummy", "text")),
+ NoSniffFlag::Off,
+ ApacheBugFlag::On);
+}
+
+#[test]
+fn test_sniff_utf_16le_bom_with_apache_flag_on() {
+ test_sniff_with_flags(&PathBuf::from("text/plain/utf16lebom.txt"),
+ "text",
+ "plain",
+ Some(("dummy", "text")),
+ NoSniffFlag::Off,
+ ApacheBugFlag::On);
+}
+
+#[test]
+fn test_sniff_octet_stream_apache_flag_on() {
+ test_sniff_with_flags(&PathBuf::from("unknown/binary_file"),
+ "application",
+ "octet-stream",
+ Some(("dummy", "binary")),
+ NoSniffFlag::Off,
+ ApacheBugFlag::On);
+}
+
+#[test]
+fn test_sniff_mp4_video_apache_flag_on() {
+ test_sniff_with_flags(&PathBuf::from("video/mp4/test.mp4"),
+ "application",
+ "octet-stream",
+ Some(("video", "mp4")),
+ NoSniffFlag::Off,
+ ApacheBugFlag::On);
+}
diff --git a/components/net/tests/parsable_mime/application/font-woff/test.wof b/components/net/tests/parsable_mime/application/font-woff/test.wof
new file mode 100755
index 00000000000..a1393ebee1d
--- /dev/null
+++ b/components/net/tests/parsable_mime/application/font-woff/test.wof
@@ -0,0 +1 @@
+wOFF \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/application/ogg/small.ogg b/components/net/tests/parsable_mime/application/ogg/small.ogg
new file mode 100644
index 00000000000..0d7f43eb795
--- /dev/null
+++ b/components/net/tests/parsable_mime/application/ogg/small.ogg
Binary files differ
diff --git a/components/net/tests/parsable_mime/application/pdf/test.pdf b/components/net/tests/parsable_mime/application/pdf/test.pdf
new file mode 100644
index 00000000000..e7c6e62775f
--- /dev/null
+++ b/components/net/tests/parsable_mime/application/pdf/test.pdf
@@ -0,0 +1,157 @@
+%PDF-1.2
+%
+
+9 0 obj
+<<
+/Length 10 0 R
+/Filter /FlateDecode
+>>
+stream
+H͐J0 {f$Mn-[&jeۤ ~$}ɅIjs~X-],$Y)'Nu1!V??
+b1Rbb҉H[TD:#&حXi$qnf]a{أq|JLs]QIj%9`঺Uitez$OeBĒүR@zܗg<
+endstream
+endobj
+10 0 obj
+246
+endobj
+4 0 obj
+<<
+/Type /Page
+/Parent 5 0 R
+/Resources <<
+/Font <<
+/F0 6 0 R
+/F1 7 0 R
+>>
+/ProcSet 2 0 R
+>>
+/Contents 9 0 R
+>>
+endobj
+6 0 obj
+<<
+/Type /Font
+/Subtype /TrueType
+/Name /F0
+/BaseFont /Arial
+/Encoding /WinAnsiEncoding
+>>
+endobj
+7 0 obj
+<<
+/Type /Font
+/Subtype /TrueType
+/Name /F1
+/BaseFont /BookAntiqua,Bold
+/FirstChar 31
+/LastChar 255
+/Widths [ 750 250 278 402 606 500 889 833 227 333 333 444 606 250 333 250
+296 500 500 500 500 500 500 500 500 500 500 250 250 606 606 606
+444 747 778 667 722 833 611 556 833 833 389 389 778 611 1000 833
+833 611 833 722 611 667 778 778 1000 667 667 667 333 606 333 606
+500 333 500 611 444 611 500 389 556 611 333 333 611 333 889 611
+556 611 611 389 444 333 611 556 833 500 556 500 310 606 310 606
+750 500 750 333 500 500 1000 500 500 333 1000 611 389 1000 750 750
+750 750 278 278 500 500 606 500 1000 333 998 444 389 833 750 750
+667 250 278 500 500 606 500 606 500 333 747 438 500 606 333 747
+500 400 549 361 361 333 576 641 250 333 361 488 500 889 890 889
+444 778 778 778 778 778 778 1000 722 611 611 611 611 389 389 389
+389 833 833 833 833 833 833 833 606 833 778 778 778 778 667 611
+611 500 500 500 500 500 500 778 444 500 500 500 500 333 333 333
+333 556 611 556 556 556 556 556 549 556 611 611 611 611 556 611
+556 ]
+/Encoding /WinAnsiEncoding
+/FontDescriptor 8 0 R
+>>
+endobj
+8 0 obj
+<<
+/Type /FontDescriptor
+/FontName /BookAntiqua,Bold
+/Flags 16418
+/FontBBox [ -250 -260 1236 930 ]
+/MissingWidth 750
+/StemV 146
+/StemH 146
+/ItalicAngle 0
+/CapHeight 930
+/XHeight 651
+/Ascent 930
+/Descent 260
+/Leading 210
+/MaxWidth 1030
+/AvgWidth 460
+>>
+endobj
+2 0 obj
+[ /PDF /Text ]
+endobj
+5 0 obj
+<<
+/Kids [4 0 R ]
+/Count 1
+/Type /Pages
+/MediaBox [ 0 0 612 792 ]
+>>
+endobj
+1 0 obj
+<<
+/Creator (1725.fm)
+/CreationDate (1-Jan-3 18:15PM)
+/Title (1725.PDF)
+/Author (Unknown)
+/Producer (Acrobat PDFWriter 3.02 for Windows)
+/Keywords ()
+/Subject ()
+>>
+endobj
+3 0 obj
+<<
+/Pages 5 0 R
+/Type /Catalog
+/DefaultGray 11 0 R
+/DefaultRGB 12 0 R
+>>
+endobj
+11 0 obj
+[/CalGray
+<<
+/WhitePoint [0.9505 1 1.0891 ]
+/Gamma 0.2468
+>>
+]
+endobj
+12 0 obj
+[/CalRGB
+<<
+/WhitePoint [0.9505 1 1.0891 ]
+/Gamma [0.2468 0.2468 0.2468 ]
+/Matrix [0.4361 0.2225 0.0139 0.3851 0.7169 0.0971 0.1431 0.0606 0.7141 ]
+>>
+]
+endobj
+xref
+0 13
+0000000000 65535 f
+0000002172 00000 n
+0000002046 00000 n
+0000002363 00000 n
+0000000375 00000 n
+0000002080 00000 n
+0000000518 00000 n
+0000000633 00000 n
+0000001760 00000 n
+0000000021 00000 n
+0000000352 00000 n
+0000002460 00000 n
+0000002548 00000 n
+trailer
+<<
+/Size 13
+/Root 3 0 R
+/Info 1 0 R
+/ID [<47149510433dd4882f05f8c124223734><47149510433dd4882f05f8c124223734>]
+>>
+startxref
+2726
+%%EOF
diff --git a/components/net/tests/parsable_mime/application/postscript/test.ps b/components/net/tests/parsable_mime/application/postscript/test.ps
new file mode 100755
index 00000000000..c273ffa3f0f
--- /dev/null
+++ b/components/net/tests/parsable_mime/application/postscript/test.ps
@@ -0,0 +1 @@
+%!PS-Adobe- \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobject b/components/net/tests/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobject
new file mode 100755
index 00000000000..1b84f4c37c1
--- /dev/null
+++ b/components/net/tests/parsable_mime/application/vnd.ms-fontobject/vnd.ms-fontobject
Binary files differ
diff --git a/components/net/tests/parsable_mime/application/x-gzip/test.gz b/components/net/tests/parsable_mime/application/x-gzip/test.gz
new file mode 100644
index 00000000000..3b99b73e6f0
--- /dev/null
+++ b/components/net/tests/parsable_mime/application/x-gzip/test.gz
Binary files differ
diff --git a/components/net/tests/parsable_mime/application/x-rar-compressed/test.rar b/components/net/tests/parsable_mime/application/x-rar-compressed/test.rar
new file mode 100755
index 00000000000..920bd4d8a8c
--- /dev/null
+++ b/components/net/tests/parsable_mime/application/x-rar-compressed/test.rar
Binary files differ
diff --git a/components/net/tests/parsable_mime/application/zip/test.zip b/components/net/tests/parsable_mime/application/zip/test.zip
new file mode 100755
index 00000000000..5c74c9658c6
--- /dev/null
+++ b/components/net/tests/parsable_mime/application/zip/test.zip
@@ -0,0 +1 @@
+PK \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/audio/aiff/test.aif b/components/net/tests/parsable_mime/audio/aiff/test.aif
new file mode 100644
index 00000000000..ad2e35df40b
--- /dev/null
+++ b/components/net/tests/parsable_mime/audio/aiff/test.aif
Binary files differ
diff --git a/components/net/tests/parsable_mime/audio/basic/test.au b/components/net/tests/parsable_mime/audio/basic/test.au
new file mode 100644
index 00000000000..d4e53deb74a
--- /dev/null
+++ b/components/net/tests/parsable_mime/audio/basic/test.au
Binary files differ
diff --git a/components/net/tests/parsable_mime/audio/midi/test.mid b/components/net/tests/parsable_mime/audio/midi/test.mid
new file mode 100644
index 00000000000..a52838c62bc
--- /dev/null
+++ b/components/net/tests/parsable_mime/audio/midi/test.mid
Binary files differ
diff --git a/components/net/tests/parsable_mime/audio/mpeg/test.mp3 b/components/net/tests/parsable_mime/audio/mpeg/test.mp3
new file mode 100644
index 00000000000..50786790311
--- /dev/null
+++ b/components/net/tests/parsable_mime/audio/mpeg/test.mp3
Binary files differ
diff --git a/components/net/tests/parsable_mime/audio/wave/test.wav b/components/net/tests/parsable_mime/audio/wave/test.wav
new file mode 100644
index 00000000000..f96276c063c
--- /dev/null
+++ b/components/net/tests/parsable_mime/audio/wave/test.wav
Binary files differ
diff --git a/components/net/tests/parsable_mime/image/bmp/test.bmp b/components/net/tests/parsable_mime/image/bmp/test.bmp
new file mode 100644
index 00000000000..8a1b10bae5e
--- /dev/null
+++ b/components/net/tests/parsable_mime/image/bmp/test.bmp
Binary files differ
diff --git a/components/net/tests/parsable_mime/image/gif/test87a b/components/net/tests/parsable_mime/image/gif/test87a
new file mode 100644
index 00000000000..8d49c776420
--- /dev/null
+++ b/components/net/tests/parsable_mime/image/gif/test87a
Binary files differ
diff --git a/components/net/tests/parsable_mime/image/gif/test89a.gif b/components/net/tests/parsable_mime/image/gif/test89a.gif
new file mode 100644
index 00000000000..0e2995e0821
--- /dev/null
+++ b/components/net/tests/parsable_mime/image/gif/test89a.gif
Binary files differ
diff --git a/components/net/tests/parsable_mime/image/jpeg/test.jpg b/components/net/tests/parsable_mime/image/jpeg/test.jpg
new file mode 100644
index 00000000000..7f758f65d13
--- /dev/null
+++ b/components/net/tests/parsable_mime/image/jpeg/test.jpg
Binary files differ
diff --git a/components/net/tests/parsable_mime/image/png/test.png b/components/net/tests/parsable_mime/image/png/test.png
new file mode 100644
index 00000000000..cc81374d4f5
--- /dev/null
+++ b/components/net/tests/parsable_mime/image/png/test.png
Binary files differ
diff --git a/components/net/tests/parsable_mime/image/webp/test.webp b/components/net/tests/parsable_mime/image/webp/test.webp
new file mode 100755
index 00000000000..ad88e62f94c
--- /dev/null
+++ b/components/net/tests/parsable_mime/image/webp/test.webp
Binary files differ
diff --git a/components/net/tests/parsable_mime/image/x-icon/test.ico b/components/net/tests/parsable_mime/image/x-icon/test.ico
new file mode 100644
index 00000000000..a2d0ee49098
--- /dev/null
+++ b/components/net/tests/parsable_mime/image/x-icon/test.ico
Binary files differ
diff --git a/components/net/tests/parsable_mime/image/x-icon/test_cursor.ico b/components/net/tests/parsable_mime/image/x-icon/test_cursor.ico
new file mode 100644
index 00000000000..6029d6684d5
--- /dev/null
+++ b/components/net/tests/parsable_mime/image/x-icon/test_cursor.ico
Binary files differ
diff --git a/components/net/tests/parsable_mime/text/html/text_html_a_20.html b/components/net/tests/parsable_mime/text/html/text_html_a_20.html
new file mode 100644
index 00000000000..1b9619279a7
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_a_20.html
@@ -0,0 +1,3 @@
+
+
+ <A
diff --git a/components/net/tests/parsable_mime/text/html/text_html_a_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_a_20_u.html
new file mode 100644
index 00000000000..887a1280650
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_a_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <a
diff --git a/components/net/tests/parsable_mime/text/html/text_html_a_3e.html b/components/net/tests/parsable_mime/text/html/text_html_a_3e.html
new file mode 100644
index 00000000000..610cd08fea4
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_a_3e.html
@@ -0,0 +1,3 @@
+
+
+ <A>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_a_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_a_3e_u.html
new file mode 100644
index 00000000000..48528fdf341
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_a_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <a>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_b_20.html b/components/net/tests/parsable_mime/text/html/text_html_b_20.html
new file mode 100644
index 00000000000..5977d2eeaab
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_b_20.html
@@ -0,0 +1,3 @@
+
+
+ <B
diff --git a/components/net/tests/parsable_mime/text/html/text_html_b_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_b_20_u.html
new file mode 100644
index 00000000000..a8a963b95f0
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_b_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <b
diff --git a/components/net/tests/parsable_mime/text/html/text_html_b_3e.html b/components/net/tests/parsable_mime/text/html/text_html_b_3e.html
new file mode 100644
index 00000000000..dc79cd5d568
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_b_3e.html
@@ -0,0 +1,3 @@
+
+
+ <B>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_b_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_b_3e_u.html
new file mode 100644
index 00000000000..0d72d281aec
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_b_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <b>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_body_20.html b/components/net/tests/parsable_mime/text/html/text_html_body_20.html
new file mode 100644
index 00000000000..c72b1ad3bec
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_body_20.html
@@ -0,0 +1,3 @@
+
+
+ <BODY
diff --git a/components/net/tests/parsable_mime/text/html/text_html_body_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_body_20_u.html
new file mode 100644
index 00000000000..1d76ebb0f47
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_body_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <body
diff --git a/components/net/tests/parsable_mime/text/html/text_html_body_3e.html b/components/net/tests/parsable_mime/text/html/text_html_body_3e.html
new file mode 100644
index 00000000000..4a66f59ef95
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_body_3e.html
@@ -0,0 +1,3 @@
+
+
+ <BODY>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_body_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_body_3e_u.html
new file mode 100644
index 00000000000..b431695f3ab
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_body_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <body>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_br_20.html b/components/net/tests/parsable_mime/text/html/text_html_br_20.html
new file mode 100644
index 00000000000..d04df680012
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_br_20.html
@@ -0,0 +1,3 @@
+
+
+ <BR
diff --git a/components/net/tests/parsable_mime/text/html/text_html_br_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_br_20_u.html
new file mode 100644
index 00000000000..1c0f0ce13ba
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_br_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <br
diff --git a/components/net/tests/parsable_mime/text/html/text_html_br_3e.html b/components/net/tests/parsable_mime/text/html/text_html_br_3e.html
new file mode 100644
index 00000000000..1d40ef06566
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_br_3e.html
@@ -0,0 +1,3 @@
+
+
+ <BR>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_br_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_br_3e_u.html
new file mode 100644
index 00000000000..c4eae116f03
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_br_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <br>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_comment_20.html b/components/net/tests/parsable_mime/text/html/text_html_comment_20.html
new file mode 100644
index 00000000000..e9612efc73c
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_comment_20.html
@@ -0,0 +1,3 @@
+
+
+ <!--
diff --git a/components/net/tests/parsable_mime/text/html/text_html_comment_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_comment_20_u.html
new file mode 100644
index 00000000000..e9612efc73c
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_comment_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <!--
diff --git a/components/net/tests/parsable_mime/text/html/text_html_comment_3e.html b/components/net/tests/parsable_mime/text/html/text_html_comment_3e.html
new file mode 100644
index 00000000000..44a94ca5a7a
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_comment_3e.html
@@ -0,0 +1,3 @@
+
+
+ <!-->
diff --git a/components/net/tests/parsable_mime/text/html/text_html_comment_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_comment_3e_u.html
new file mode 100644
index 00000000000..44a94ca5a7a
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_comment_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <!-->
diff --git a/components/net/tests/parsable_mime/text/html/text_html_div_20.html b/components/net/tests/parsable_mime/text/html/text_html_div_20.html
new file mode 100644
index 00000000000..2ed34363b2f
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_div_20.html
@@ -0,0 +1,3 @@
+
+
+ <DIV
diff --git a/components/net/tests/parsable_mime/text/html/text_html_div_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_div_20_u.html
new file mode 100644
index 00000000000..b98886efd83
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_div_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <div
diff --git a/components/net/tests/parsable_mime/text/html/text_html_div_3e.html b/components/net/tests/parsable_mime/text/html/text_html_div_3e.html
new file mode 100644
index 00000000000..ccf4ca8d70a
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_div_3e.html
@@ -0,0 +1,3 @@
+
+
+ <DIV>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_div_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_div_3e_u.html
new file mode 100644
index 00000000000..c117f0f4cdd
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_div_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <div>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_doctype_20.html b/components/net/tests/parsable_mime/text/html/text_html_doctype_20.html
new file mode 100644
index 00000000000..dbeb5a41c2a
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_doctype_20.html
@@ -0,0 +1,3 @@
+
+
+ <!DOCTYPE HTML
diff --git a/components/net/tests/parsable_mime/text/html/text_html_doctype_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_doctype_20_u.html
new file mode 100644
index 00000000000..acede44dffb
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_doctype_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <!doctype html
diff --git a/components/net/tests/parsable_mime/text/html/text_html_doctype_3e.html b/components/net/tests/parsable_mime/text/html/text_html_doctype_3e.html
new file mode 100644
index 00000000000..6a22ea8b978
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_doctype_3e.html
@@ -0,0 +1,4 @@
+
+
+ <!DOCTYPE HTML>
+
diff --git a/components/net/tests/parsable_mime/text/html/text_html_doctype_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_doctype_3e_u.html
new file mode 100644
index 00000000000..8b16e40458e
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_doctype_3e_u.html
@@ -0,0 +1,4 @@
+
+
+ <!doctype html>
+
diff --git a/components/net/tests/parsable_mime/text/html/text_html_font_20.html b/components/net/tests/parsable_mime/text/html/text_html_font_20.html
new file mode 100644
index 00000000000..a18fa850617
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_font_20.html
@@ -0,0 +1,3 @@
+
+
+ <FONT
diff --git a/components/net/tests/parsable_mime/text/html/text_html_font_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_font_20_u.html
new file mode 100644
index 00000000000..6a31d2a8aba
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_font_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <font
diff --git a/components/net/tests/parsable_mime/text/html/text_html_font_3e.html b/components/net/tests/parsable_mime/text/html/text_html_font_3e.html
new file mode 100644
index 00000000000..3605840fc5a
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_font_3e.html
@@ -0,0 +1,3 @@
+
+
+ <FONT>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_font_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_font_3e_u.html
new file mode 100644
index 00000000000..1181517947b
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_font_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <font>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_h1_20.html b/components/net/tests/parsable_mime/text/html/text_html_h1_20.html
new file mode 100644
index 00000000000..3ed0eb125ff
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_h1_20.html
@@ -0,0 +1,3 @@
+
+
+ <H1
diff --git a/components/net/tests/parsable_mime/text/html/text_html_h1_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_h1_20_u.html
new file mode 100644
index 00000000000..f517b61487e
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_h1_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <h1
diff --git a/components/net/tests/parsable_mime/text/html/text_html_h1_3e.html b/components/net/tests/parsable_mime/text/html/text_html_h1_3e.html
new file mode 100644
index 00000000000..af0bf8c56b9
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_h1_3e.html
@@ -0,0 +1,3 @@
+
+
+ <H1>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_h1_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_h1_3e_u.html
new file mode 100644
index 00000000000..bae85229fcf
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_h1_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <h1>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_head_20.html b/components/net/tests/parsable_mime/text/html/text_html_head_20.html
new file mode 100644
index 00000000000..eb322c946e0
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_head_20.html
@@ -0,0 +1,3 @@
+
+
+ <HEAD
diff --git a/components/net/tests/parsable_mime/text/html/text_html_head_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_head_20_u.html
new file mode 100644
index 00000000000..899655a5a2c
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_head_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <head
diff --git a/components/net/tests/parsable_mime/text/html/text_html_head_3e.html b/components/net/tests/parsable_mime/text/html/text_html_head_3e.html
new file mode 100644
index 00000000000..058c7dce4a9
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_head_3e.html
@@ -0,0 +1,3 @@
+
+
+ <HEAD>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_head_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_head_3e_u.html
new file mode 100644
index 00000000000..8a33d623daa
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_head_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <head>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_iframe_20.html b/components/net/tests/parsable_mime/text/html/text_html_iframe_20.html
new file mode 100644
index 00000000000..e632915590a
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_iframe_20.html
@@ -0,0 +1,3 @@
+
+
+ <IFRAME
diff --git a/components/net/tests/parsable_mime/text/html/text_html_iframe_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_iframe_20_u.html
new file mode 100644
index 00000000000..527a06e415c
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_iframe_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <iframe
diff --git a/components/net/tests/parsable_mime/text/html/text_html_iframe_3e.html b/components/net/tests/parsable_mime/text/html/text_html_iframe_3e.html
new file mode 100644
index 00000000000..9db0efd47d4
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_iframe_3e.html
@@ -0,0 +1,3 @@
+
+
+ <IFRAME>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_iframe_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_iframe_3e_u.html
new file mode 100644
index 00000000000..e3512c8a5c2
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_iframe_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <iframe>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_p_20.html b/components/net/tests/parsable_mime/text/html/text_html_p_20.html
new file mode 100644
index 00000000000..a099441be2b
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_p_20.html
@@ -0,0 +1,3 @@
+
+
+ <P
diff --git a/components/net/tests/parsable_mime/text/html/text_html_p_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_p_20_u.html
new file mode 100644
index 00000000000..ff4befbde7b
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_p_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <p
diff --git a/components/net/tests/parsable_mime/text/html/text_html_p_3e.html b/components/net/tests/parsable_mime/text/html/text_html_p_3e.html
new file mode 100644
index 00000000000..98db18913d0
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_p_3e.html
@@ -0,0 +1,3 @@
+
+
+ <P>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_p_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_p_3e_u.html
new file mode 100644
index 00000000000..9d99a59ed08
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_p_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <p>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_page_20.html b/components/net/tests/parsable_mime/text/html/text_html_page_20.html
new file mode 100644
index 00000000000..bb1c4572b25
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_page_20.html
@@ -0,0 +1,3 @@
+
+
+ <HTML
diff --git a/components/net/tests/parsable_mime/text/html/text_html_page_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_page_20_u.html
new file mode 100644
index 00000000000..b3300d9f4e4
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_page_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <html
diff --git a/components/net/tests/parsable_mime/text/html/text_html_page_3e.html b/components/net/tests/parsable_mime/text/html/text_html_page_3e.html
new file mode 100644
index 00000000000..e6a49c51924
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_page_3e.html
@@ -0,0 +1,3 @@
+
+
+ <HTML>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_page_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_page_3e_u.html
new file mode 100644
index 00000000000..2b8ee203d25
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_page_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <html>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_script_20.html b/components/net/tests/parsable_mime/text/html/text_html_script_20.html
new file mode 100644
index 00000000000..620c629266c
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_script_20.html
@@ -0,0 +1,3 @@
+
+
+ <SCRIPT
diff --git a/components/net/tests/parsable_mime/text/html/text_html_script_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_script_20_u.html
new file mode 100644
index 00000000000..bd2c58e676c
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_script_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <script
diff --git a/components/net/tests/parsable_mime/text/html/text_html_script_3e.html b/components/net/tests/parsable_mime/text/html/text_html_script_3e.html
new file mode 100644
index 00000000000..d59535f70cd
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_script_3e.html
@@ -0,0 +1,3 @@
+
+
+ <SCRIPT>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_script_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_script_3e_u.html
new file mode 100644
index 00000000000..625c13820f4
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_script_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <script>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_style_20.html b/components/net/tests/parsable_mime/text/html/text_html_style_20.html
new file mode 100644
index 00000000000..57bc2a1ecd7
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_style_20.html
@@ -0,0 +1,3 @@
+
+
+ <STYLE
diff --git a/components/net/tests/parsable_mime/text/html/text_html_style_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_style_20_u.html
new file mode 100644
index 00000000000..8163eca3c60
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_style_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <style
diff --git a/components/net/tests/parsable_mime/text/html/text_html_style_3e.html b/components/net/tests/parsable_mime/text/html/text_html_style_3e.html
new file mode 100644
index 00000000000..229d5f951bd
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_style_3e.html
@@ -0,0 +1,3 @@
+
+
+ <STYLE>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_style_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_style_3e_u.html
new file mode 100644
index 00000000000..12d686e4953
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_style_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <style>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_table_20.html b/components/net/tests/parsable_mime/text/html/text_html_table_20.html
new file mode 100644
index 00000000000..27cccc6acd6
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_table_20.html
@@ -0,0 +1,3 @@
+
+
+ <TABLE
diff --git a/components/net/tests/parsable_mime/text/html/text_html_table_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_table_20_u.html
new file mode 100644
index 00000000000..556b46e7fc4
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_table_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <table
diff --git a/components/net/tests/parsable_mime/text/html/text_html_table_3e.html b/components/net/tests/parsable_mime/text/html/text_html_table_3e.html
new file mode 100644
index 00000000000..351ee543af8
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_table_3e.html
@@ -0,0 +1,3 @@
+
+
+ <TABLE>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_table_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_table_3e_u.html
new file mode 100644
index 00000000000..6259870bfcf
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_table_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <table>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_title_20.html b/components/net/tests/parsable_mime/text/html/text_html_title_20.html
new file mode 100644
index 00000000000..f7d151658d9
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_title_20.html
@@ -0,0 +1,3 @@
+
+
+ <TITLE
diff --git a/components/net/tests/parsable_mime/text/html/text_html_title_20_u.html b/components/net/tests/parsable_mime/text/html/text_html_title_20_u.html
new file mode 100644
index 00000000000..03a072d8ac0
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_title_20_u.html
@@ -0,0 +1,3 @@
+
+
+ <title
diff --git a/components/net/tests/parsable_mime/text/html/text_html_title_3e.html b/components/net/tests/parsable_mime/text/html/text_html_title_3e.html
new file mode 100644
index 00000000000..fedf57b9e4f
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_title_3e.html
@@ -0,0 +1,3 @@
+
+
+ <TITLE>
diff --git a/components/net/tests/parsable_mime/text/html/text_html_title_3e_u.html b/components/net/tests/parsable_mime/text/html/text_html_title_3e_u.html
new file mode 100644
index 00000000000..5fbf8a75c47
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/html/text_html_title_3e_u.html
@@ -0,0 +1,3 @@
+
+
+ <title>
diff --git a/components/net/tests/parsable_mime/text/plain/utf16bebom.txt b/components/net/tests/parsable_mime/text/plain/utf16bebom.txt
new file mode 100644
index 00000000000..9fb50d49fb8
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/plain/utf16bebom.txt
Binary files differ
diff --git a/components/net/tests/parsable_mime/text/plain/utf16lebom.txt b/components/net/tests/parsable_mime/text/plain/utf16lebom.txt
new file mode 100644
index 00000000000..d79d81725ec
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/plain/utf16lebom.txt
Binary files differ
diff --git a/components/net/tests/parsable_mime/text/plain/utf8bom.txt b/components/net/tests/parsable_mime/text/plain/utf8bom.txt
new file mode 100644
index 00000000000..56ad8a265ef
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/plain/utf8bom.txt
@@ -0,0 +1 @@
+ test_file
diff --git a/components/net/tests/parsable_mime/text/xml/feed.atom b/components/net/tests/parsable_mime/text/xml/feed.atom
new file mode 100755
index 00000000000..893c3f27a8e
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/xml/feed.atom
@@ -0,0 +1 @@
+<feed>
diff --git a/components/net/tests/parsable_mime/text/xml/feed.rss b/components/net/tests/parsable_mime/text/xml/feed.rss
new file mode 100644
index 00000000000..9dc94d32b51
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/xml/feed.rss
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="windows-1252"?>
+<rss version="2.0">
+ <channel>
+ <title>FeedForAll Sample Feed</title>
+ <description>RSS is a fascinating technology. The uses for RSS are expanding daily. Take a closer look at how various industries are using the benefits of RSS in their businesses.</description>
+ <link>http://www.feedforall.com/industry-solutions.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <copyright>Copyright 2004 NotePage, Inc.</copyright>
+ <docs>http://blogs.law.harvard.edu/tech/rss</docs>
+ <language>en-us</language>
+ <lastBuildDate>Tue, 19 Oct 2004 13:39:14 -0400</lastBuildDate>
+ <managingEditor>marketing@feedforall.com</managingEditor>
+ <pubDate>Tue, 19 Oct 2004 13:38:55 -0400</pubDate>
+ <webMaster>webmaster@feedforall.com</webMaster>
+ <generator>FeedForAll Beta1 (0.0.1.8)</generator>
+ <image>
+ <url>http://www.feedforall.com/ffalogo48x48.gif</url>
+ <title>FeedForAll Sample Feed</title>
+ <link>http://www.feedforall.com/industry-solutions.htm</link>
+ <description>FeedForAll Sample Feed</description>
+ <width>48</width>
+ <height>48</height>
+ </image>
+ <item>
+ <title>RSS Solutions for Restaurants</title>
+ <description>&lt;b&gt;FeedForAll &lt;/b&gt;helps Restaurant&apos;s communicate with customers. Let your customers know the latest specials or events.&lt;br&gt;
+&lt;br&gt;
+RSS feed uses include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#FF0000&quot;&gt;Daily Specials &lt;br&gt;
+Entertainment &lt;br&gt;
+Calendar of Events &lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/restaurant.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:11 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Schools and Colleges</title>
+ <description>FeedForAll helps Educational Institutions communicate with students about school wide activities, events, and schedules.&lt;br&gt;
+&lt;br&gt;
+RSS feed uses include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#0000FF&quot;&gt;Homework Assignments &lt;br&gt;
+School Cancellations &lt;br&gt;
+Calendar of Events &lt;br&gt;
+Sports Scores &lt;br&gt;
+Clubs/Organization Meetings &lt;br&gt;
+Lunches Menus &lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/schools.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:09 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Computer Service Companies</title>
+ <description>FeedForAll helps Computer Service Companies communicate with clients about cyber security and related issues. &lt;br&gt;
+&lt;br&gt;
+Uses include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#0000FF&quot;&gt;Cyber Security Alerts &lt;br&gt;
+Specials&lt;br&gt;
+Job Postings &lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/computer-service.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:07 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Governments</title>
+ <description>FeedForAll helps Governments communicate with the general public about positions on various issues, and keep the community aware of changes in important legislative issues. &lt;b&gt;&lt;i&gt;&lt;br&gt;
+&lt;/b&gt;&lt;/i&gt;&lt;br&gt;
+RSS uses Include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#00FF00&quot;&gt;Legislative Calendar&lt;br&gt;
+Votes&lt;br&gt;
+Bulletins&lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/government.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:05 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Politicians</title>
+ <description>FeedForAll helps Politicians communicate with the general public about positions on various issues, and keep the community notified of their schedule. &lt;br&gt;
+&lt;br&gt;
+Uses Include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#FF0000&quot;&gt;Blogs&lt;br&gt;
+Speaking Engagements &lt;br&gt;
+Statements&lt;br&gt;
+ &lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/politics.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:03 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Meteorologists</title>
+ <description>FeedForAll helps Meteorologists communicate with the general public about storm warnings and weather alerts, in specific regions. Using RSS meteorologists are able to quickly disseminate urgent and life threatening weather warnings. &lt;br&gt;
+&lt;br&gt;
+Uses Include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#0000FF&quot;&gt;Weather Alerts&lt;br&gt;
+Plotting Storms&lt;br&gt;
+School Cancellations &lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/weather.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:09:01 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Realtors &amp; Real Estate Firms</title>
+ <description>FeedForAll helps Realtors and Real Estate companies communicate with clients informing them of newly available properties, and open house announcements. RSS helps to reach a targeted audience and spread the word in an inexpensive, professional manner. &lt;font color=&quot;#0000FF&quot;&gt;&lt;br&gt;
+&lt;/font&gt;&lt;br&gt;
+Feeds can be used for:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#FF0000&quot;&gt;Open House Dates&lt;br&gt;
+New Properties For Sale&lt;br&gt;
+Mortgage Rates&lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/real-estate.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:08:59 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Banks / Mortgage Companies</title>
+ <description>FeedForAll helps &lt;b&gt;Banks, Credit Unions and Mortgage companies&lt;/b&gt; communicate with the general public about rate changes in a prompt and professional manner. &lt;br&gt;
+&lt;br&gt;
+Uses include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#0000FF&quot;&gt;Mortgage Rates&lt;br&gt;
+Foreign Exchange Rates &lt;br&gt;
+Bank Rates&lt;br&gt;
+Specials&lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/banks.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:08:57 -0400</pubDate>
+ </item>
+ <item>
+ <title>RSS Solutions for Law Enforcement</title>
+ <description>&lt;b&gt;FeedForAll&lt;/b&gt; helps Law Enforcement Professionals communicate with the general public and other agencies in a prompt and efficient manner. Using RSS police are able to quickly disseminate urgent and life threatening information. &lt;br&gt;
+&lt;br&gt;
+Uses include:&lt;br&gt;
+&lt;i&gt;&lt;font color=&quot;#0000FF&quot;&gt;Amber Alerts&lt;br&gt;
+Sex Offender Community Notification &lt;br&gt;
+Weather Alerts &lt;br&gt;
+Scheduling &lt;br&gt;
+Security Alerts &lt;br&gt;
+Police Report &lt;br&gt;
+Meetings&lt;/i&gt;&lt;/font&gt;</description>
+ <link>http://www.feedforall.com/law-enforcement.htm</link>
+ <category domain="www.dmoz.com">Computers/Software/Internet/Site Management/Content Management</category>
+ <comments>http://www.feedforall.com/forum</comments>
+ <pubDate>Tue, 19 Oct 2004 11:08:56 -0400</pubDate>
+ </item>
+ </channel>
+</rss> \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/text/xml/rdf_rss.xml b/components/net/tests/parsable_mime/text/xml/rdf_rss.xml
new file mode 100644
index 00000000000..4c58f82974e
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/xml/rdf_rss.xml
@@ -0,0 +1,7 @@
+<!-- Good format for a "RDF feed" -->
+<?xml version="1.0"?>
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_1.xml b/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_1.xml
new file mode 100644
index 00000000000..f6e486c5960
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_1.xml
@@ -0,0 +1,7 @@
+<!-- Bad format for a "RDF feed" (space between "rdf:" and "RDF") -->
+<?xml version="1.0"?>
+<rdf: RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_2.xml b/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_2.xml
new file mode 100644
index 00000000000..be8414382e5
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_2.xml
@@ -0,0 +1,3 @@
+<!-- Bad format for a "RDF feed" (2 missing URLs) -->
+<?xml version="1.0"?>
+<rdf:RDF/> \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_3.xml b/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_3.xml
new file mode 100644
index 00000000000..5f0f03f1e2d
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_3.xml
@@ -0,0 +1,6 @@
+<!-- Bad format for a "RDF feed" (one missing URL) -->
+<?xml version="1.0"?>
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_4.xml b/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_4.xml
new file mode 100644
index 00000000000..c06a80cf1f8
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/xml/rdf_rss_ko_4.xml
@@ -0,0 +1,7 @@
+<!-- Bad format for a "RDF feed" (unexpected space in first URL) -->
+<?xml version="1.0"?>
+<rdf:RDF
+ xmlns:rdf="http: //www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://purl.org/rss/1.0/"
+>
+</rdf:RDF> \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/text/xml/test.xml b/components/net/tests/parsable_mime/text/xml/test.xml
new file mode 100644
index 00000000000..8fe8c0e91cf
--- /dev/null
+++ b/components/net/tests/parsable_mime/text/xml/test.xml
@@ -0,0 +1,6 @@
+
+<?xml version="1.0" encoding="UTF-8"?>
+<foo>
+ <bar>
+ </bar>
+</foo>
diff --git a/components/net/tests/parsable_mime/unknown/binary_file b/components/net/tests/parsable_mime/unknown/binary_file
new file mode 100644
index 00000000000..ecf3bbcdf3e
--- /dev/null
+++ b/components/net/tests/parsable_mime/unknown/binary_file
Binary files differ
diff --git a/components/net/tests/parsable_mime/unknown/open_type b/components/net/tests/parsable_mime/unknown/open_type
new file mode 100644
index 00000000000..9117b12600f
--- /dev/null
+++ b/components/net/tests/parsable_mime/unknown/open_type
@@ -0,0 +1 @@
+OTTO \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/unknown/true_type.ttf b/components/net/tests/parsable_mime/unknown/true_type.ttf
new file mode 100644
index 00000000000..c0142fea093
--- /dev/null
+++ b/components/net/tests/parsable_mime/unknown/true_type.ttf
Binary files differ
diff --git a/components/net/tests/parsable_mime/unknown/true_type_collection.ttc b/components/net/tests/parsable_mime/unknown/true_type_collection.ttc
new file mode 100644
index 00000000000..42d3cef1e6d
--- /dev/null
+++ b/components/net/tests/parsable_mime/unknown/true_type_collection.ttc
@@ -0,0 +1 @@
+ttcf \ No newline at end of file
diff --git a/components/net/tests/parsable_mime/video/avi/test.avi b/components/net/tests/parsable_mime/video/avi/test.avi
new file mode 100644
index 00000000000..f6cd837a924
--- /dev/null
+++ b/components/net/tests/parsable_mime/video/avi/test.avi
Binary files differ
diff --git a/components/net/tests/parsable_mime/video/mp4/test.mp4 b/components/net/tests/parsable_mime/video/mp4/test.mp4
new file mode 100644
index 00000000000..1fc478842f5
--- /dev/null
+++ b/components/net/tests/parsable_mime/video/mp4/test.mp4
Binary files differ
diff --git a/components/net/tests/parsable_mime/video/webm/test.webm b/components/net/tests/parsable_mime/video/webm/test.webm
new file mode 100644
index 00000000000..da946da5290
--- /dev/null
+++ b/components/net/tests/parsable_mime/video/webm/test.webm
Binary files differ
diff --git a/components/net/tests/resource_thread.rs b/components/net/tests/resource_thread.rs
new file mode 100644
index 00000000000..8ad3081c224
--- /dev/null
+++ b/components/net/tests/resource_thread.rs
@@ -0,0 +1,142 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use ipc_channel::ipc;
+use net::resource_thread::new_core_resource_thread;
+use net::test::parse_hostsfile;
+use net_traits::CoreResourceMsg;
+use profile_traits::time::ProfilerChan;
+use std::net::IpAddr;
+
+fn ip(s: &str) -> IpAddr {
+ s.parse().unwrap()
+}
+
+#[test]
+fn test_exit() {
+ let (tx, _rx) = ipc::channel().unwrap();
+ let (sender, receiver) = ipc::channel().unwrap();
+ let (resource_thread, _private_resource_thread) = new_core_resource_thread(
+ "".into(), None, ProfilerChan(tx), None);
+ resource_thread.send(CoreResourceMsg::Exit(sender)).unwrap();
+ receiver.recv().unwrap();
+}
+
+#[test]
+fn test_parse_hostsfile() {
+ let mock_hosts_file_content = "127.0.0.1 foo.bar.com\n127.0.0.2 servo.test.server";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(2, hosts_table.len());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("foo.bar.com").unwrap());
+ assert_eq!(ip("127.0.0.2"), *hosts_table.get("servo.test.server").unwrap());
+}
+
+#[test]
+fn test_parse_malformed_hostsfile() {
+ let mock_hosts_file_content = "malformed file\n127.0.0.1 foo.bar.com\nservo.test.server 127.0.0.1";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(1, hosts_table.len());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("foo.bar.com").unwrap());
+}
+
+#[test]
+fn test_parse_hostsfile_with_line_comment() {
+ let mock_hosts_file_content = "# this is a line comment\n127.0.0.1 foo.bar.com\n# anothercomment";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(1, hosts_table.len());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("foo.bar.com").unwrap());
+}
+
+#[test]
+fn test_parse_hostsfile_with_end_of_line_comment() {
+ let mock_hosts_file_content = "127.0.0.1 foo.bar.com # line ending comment\n127.0.0.2 servo.test.server #comment";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(2, hosts_table.len());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("foo.bar.com").unwrap());
+ assert_eq!(ip("127.0.0.2"), *hosts_table.get("servo.test.server").unwrap());
+}
+
+#[test]
+fn test_parse_hostsfile_with_2_hostnames_for_1_address() {
+ let mock_hosts_file_content = "127.0.0.1 foo.bar.com baz.bar.com";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(2, hosts_table.len());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("foo.bar.com").unwrap());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("baz.bar.com").unwrap());
+}
+
+#[test]
+fn test_parse_hostsfile_with_4_hostnames_for_1_address() {
+ let mock_hosts_file_content = "127.0.0.1 moz.foo.com moz.bar.com moz.baz.com moz.moz.com";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(4, hosts_table.len());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("moz.foo.com").unwrap());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("moz.bar.com").unwrap());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("moz.baz.com").unwrap());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("moz.moz.com").unwrap());
+}
+
+#[test]
+fn test_parse_hostsfile_with_tabs_instead_spaces() {
+ let mock_hosts_file_content = "127.0.0.1\tfoo.bar.com\n127.0.0.2\tservo.test.server";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(2, hosts_table.len());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("foo.bar.com").unwrap());
+ assert_eq!(ip("127.0.0.2"), *hosts_table.get("servo.test.server").unwrap());
+}
+
+#[test]
+fn test_parse_hostsfile_with_valid_ipv4_addresses()
+{
+ let mock_hosts_file_content =
+ "255.255.255.255 foo.bar.com\n169.0.1.201 servo.test.server\n192.168.5.0 servo.foo.com";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(3, hosts_table.len());
+}
+
+#[test]
+fn test_parse_hostsfile_with_invalid_ipv4_addresses()
+{
+ let mock_hosts_file_content = "256.255.255.255 foo.bar.com\n169.0.1000.201 servo.test.server \
+ \n192.168.5.500 servo.foo.com\n192.abc.100.2 test.servo.com";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(0, hosts_table.len());
+}
+
+#[test]
+fn test_parse_hostsfile_with_valid_ipv6_addresses()
+{
+ let mock_hosts_file_content = "2001:0db8:0000:0000:0000:ff00:0042:8329 foo.bar.com\n\
+ 2001:db8:0:0:0:ff00:42:8329 moz.foo.com\n\
+ 2001:db8::ff00:42:8329 foo.moz.com moz.moz.com\n\
+ 0000:0000:0000:0000:0000:0000:0000:0001 bar.moz.com\n\
+ ::1 foo.bar.baz baz.foo.com\n\
+ 2001:0DB8:85A3:0042:1000:8A2E:0370:7334 baz.bar.moz\n\
+ :: unspecified.moz.com";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(9, hosts_table.len());
+}
+
+#[test]
+fn test_parse_hostsfile_with_invalid_ipv6_addresses()
+{
+ let mock_hosts_file_content = "12001:0db8:0000:0000:0000:ff00:0042:8329 foo.bar.com\n\
+ 2001:zdb8:0:0:0:gg00:42:t329 moz.foo.com\n\
+ 2002:0DB8:85A3:0042:1000:8A2E:0370:7334/1289 baz3.bar.moz";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(0, hosts_table.len());
+}
+
+#[test]
+fn test_parse_hostsfile_with_end_of_line_whitespace()
+{
+ let mock_hosts_file_content = "127.0.0.1 foo.bar.com \n\
+ 2001:db8:0:0:0:ff00:42:8329 moz.foo.com\n \
+ 127.0.0.2 servo.test.server ";
+ let hosts_table = parse_hostsfile(mock_hosts_file_content);
+ assert_eq!(3, hosts_table.len());
+ assert_eq!(ip("127.0.0.1"), *hosts_table.get("foo.bar.com").unwrap());
+ assert_eq!(ip("2001:db8:0:0:0:ff00:42:8329"), *hosts_table.get("moz.foo.com").unwrap());
+ assert_eq!(ip("127.0.0.2"), *hosts_table.get("servo.test.server").unwrap());
+}
diff --git a/components/net/tests/subresource_integrity.rs b/components/net/tests/subresource_integrity.rs
new file mode 100644
index 00000000000..d67da9c1775
--- /dev/null
+++ b/components/net/tests/subresource_integrity.rs
@@ -0,0 +1,92 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use net::subresource_integrity::{SriEntry, get_prioritized_hash_function, get_strongest_metadata};
+use net::subresource_integrity::{is_response_integrity_valid, parsed_metadata};
+use net_traits::response::{Response, ResponseBody};
+use servo_url::ServoUrl;
+
+#[test]
+fn test_get_prioritized_hash_function() {
+ let mut algorithm = get_prioritized_hash_function("sha256", "sha256");
+ assert_eq!(algorithm, None);
+
+ algorithm = get_prioritized_hash_function("sha256", "sha384");
+ assert_eq!(algorithm.unwrap(), "sha384");
+
+ algorithm = get_prioritized_hash_function("sha384", "sha512");
+ assert_eq!(algorithm.unwrap(), "sha512");
+}
+
+#[test]
+fn test_parsed_metadata_without_options() {
+ let integrity_metadata = "sha384-Hash1";
+ let ref parsed_metadata: SriEntry = parsed_metadata(integrity_metadata)[0];
+
+ assert_eq!(parsed_metadata.alg, "sha384");
+ assert_eq!(parsed_metadata.val, "Hash1");
+ assert!(parsed_metadata.opt.is_none());
+}
+
+#[test]
+fn test_parsed_metadata_with_options() {
+ let integrity_metadata = "sha384-Hash1?opt=23";
+ let ref parsed_metadata: SriEntry = parsed_metadata(integrity_metadata)[0];
+
+ assert_eq!(parsed_metadata.alg, "sha384");
+ assert_eq!(parsed_metadata.val, "Hash1");
+ assert!(parsed_metadata.opt.is_some());
+}
+
+#[test]
+fn test_parsed_metadata_with_malformed_integrity() {
+ let integrity_metadata = "Not a valid integrity";
+ let ref parsed_metadata_list: Vec<SriEntry> = parsed_metadata(integrity_metadata);
+
+ assert!(parsed_metadata_list.is_empty());
+}
+
+#[test]
+fn test_get_strongest_metadata_two_same_algorithm() {
+ let integrity_metadata = "sha512-Hash1 sha512-Hash2?opt=23";
+ let parsed_metadata_list: Vec<SriEntry> = parsed_metadata(integrity_metadata);
+
+ let strong_metadata: Vec<SriEntry> = get_strongest_metadata(parsed_metadata_list);
+ assert_eq!(strong_metadata.len(), 2);
+ assert_eq!(strong_metadata[0].alg, strong_metadata[1].alg);
+}
+
+#[test]
+fn test_get_strongest_metadata_different_algorithm() {
+ let integrity_metadata = "sha256-Hash0 sha384-Hash1 sha512-Hash2?opt=23";
+ let parsed_metadata_list: Vec<SriEntry> = parsed_metadata(integrity_metadata);
+
+ let strong_metadata: Vec<SriEntry> = get_strongest_metadata(parsed_metadata_list);
+ assert_eq!(strong_metadata.len(), 1);
+ assert_eq!(strong_metadata[0].alg, "sha512");
+}
+
+#[test]
+fn test_response_integrity_valid() {
+ let url: ServoUrl = ServoUrl::parse("http://servo.org").unwrap();
+ let response: Response = Response::new(url);
+
+ let integrity_metadata = "sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO";
+ let response_body = "alert('Hello, world.');".to_owned().into_bytes();
+
+ *response.body.lock().unwrap() = ResponseBody::Done(response_body);
+ assert!(is_response_integrity_valid(integrity_metadata, &response));
+}
+
+#[test]
+fn test_response_integrity_invalid() {
+ let url: ServoUrl = ServoUrl::parse("http://servo.org").unwrap();
+ let response: Response = Response::new(url);
+
+ let integrity_metadata = "sha256-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO";
+ let response_body = "alert('Hello, world.');".to_owned().into_bytes();
+
+ *response.body.lock().unwrap() = ResponseBody::Done(response_body);
+ assert!(!is_response_integrity_valid(integrity_metadata, &response));
+}
diff --git a/components/net/tests/test.jpeg b/components/net/tests/test.jpeg
new file mode 100644
index 00000000000..08f084cf549
--- /dev/null
+++ b/components/net/tests/test.jpeg
Binary files differ