diff options
author | Simon Sapin <simon.sapin@exyr.org> | 2015-04-07 17:32:39 +0200 |
---|---|---|
committer | Simon Sapin <simon.sapin@exyr.org> | 2015-04-08 01:07:50 +0200 |
commit | d88770e09f76e89e51f69dd6a6b541600405b7bf (patch) | |
tree | 2b23a566d2a740753de1882d73b771fa1bdef18e | |
parent | 691222696ede82ab7bed219e1c4203200ad2a752 (diff) | |
download | servo-d88770e09f76e89e51f69dd6a6b541600405b7bf.tar.gz servo-d88770e09f76e89e51f69dd6a6b541600405b7bf.zip |
Move net::{data_loader,image_cache_task} unit tests into the unit_tests crate.
-rw-r--r-- | components/net/data_loader.rs | 70 | ||||
-rw-r--r-- | components/net/image_cache_task.rs | 575 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 1 | ||||
-rw-r--r-- | tests/unit/Cargo.toml | 3 | ||||
-rw-r--r-- | tests/unit/lib.rs | 2 | ||||
-rw-r--r-- | tests/unit/net/cookie.rs | 3 | ||||
-rw-r--r-- | tests/unit/net/data_loader.rs | 71 | ||||
-rw-r--r-- | tests/unit/net/image_cache_task.rs | 570 | ||||
-rw-r--r-- | tests/unit/net/mod.rs | 2 | ||||
-rw-r--r-- | tests/unit/net/test.jpeg (renamed from components/net/test.jpeg) | bin | 4962 -> 4962 bytes |
10 files changed, 651 insertions, 646 deletions
diff --git a/components/net/data_loader.rs b/components/net/data_loader.rs index dc1b4356390..03ec60be3a8 100644 --- a/components/net/data_loader.rs +++ b/components/net/data_loader.rs @@ -21,7 +21,7 @@ pub fn factory(load_data: LoadData, _classifier: Arc<MIMEClassifier>) { load(load_data) } -fn load(load_data: LoadData) { +pub fn load(load_data: LoadData) { let start_chan = load_data.consumer; let url = load_data.url; assert!(&*url.scheme == "data"); @@ -81,71 +81,3 @@ fn load(load_data: LoadData) { progress_chan.send(Done(Ok(()))).unwrap(); } } - -#[cfg(test)] -fn assert_parse(url: &'static str, - content_type: Option<(String, String)>, - charset: Option<String>, - data: Option<Vec<u8>>) { - use std::sync::mpsc::channel; - use url::Url; - - let (start_chan, start_port) = channel(); - load(LoadData::new(Url::parse(url).unwrap(), start_chan)); - - let response = start_port.recv().unwrap(); - assert_eq!(&response.metadata.content_type, &content_type); - assert_eq!(&response.metadata.charset, &charset); - - let progress = response.progress_port.recv().unwrap(); - - match data { - None => { - assert_eq!(progress, Done(Err("invalid data uri".to_string()))); - } - Some(dat) => { - assert_eq!(progress, Payload(dat)); - assert_eq!(response.progress_port.recv().unwrap(), Done(Ok(()))); - } - } -} - -#[test] -fn empty_invalid() { - assert_parse("data:", None, None, None); -} - -#[test] -fn plain() { - assert_parse("data:,hello%20world", None, None, Some(b"hello world".iter().map(|&x| x).collect())); -} - -#[test] -fn plain_ct() { - assert_parse("data:text/plain,hello", - Some(("text".to_string(), "plain".to_string())), None, Some(b"hello".iter().map(|&x| x).collect())); -} - -#[test] -fn plain_charset() { - assert_parse("data:text/plain;charset=latin1,hello", - Some(("text".to_string(), "plain".to_string())), Some("latin1".to_string()), Some(b"hello".iter().map(|&x| x).collect())); -} - -#[test] -fn base64() { - assert_parse("data:;base64,C62+7w==", None, None, Some(vec!(0x0B, 0xAD, 0xBE, 0xEF))); -} - -#[test] -fn base64_ct() { - assert_parse("data:application/octet-stream;base64,C62+7w==", - Some(("application".to_string(), "octet-stream".to_string())), None, Some(vec!(0x0B, 0xAD, 0xBE, 0xEF))); -} - -#[test] -fn base64_charset() { - assert_parse("data:text/plain;charset=koi8-r;base64,8PLl9+XkIO3l5Pfl5A==", - Some(("text".to_string(), "plain".to_string())), Some("koi8-r".to_string()), - Some(vec!(0xF0, 0xF2, 0xE5, 0xF7, 0xE5, 0xE4, 0x20, 0xED, 0xE5, 0xE4, 0xF7, 0xE5, 0xE4))); -} diff --git a/components/net/image_cache_task.rs b/components/net/image_cache_task.rs index df38f9d7c31..5897ee50fb2 100644 --- a/components/net/image_cache_task.rs +++ b/components/net/image_cache_task.rs @@ -420,578 +420,3 @@ pub fn spawn_listener<F, A>(f: F) -> Sender<A> }); setup_port.recv().unwrap() } - - -#[cfg(test)] -mod tests { - use super::*; - use net_traits::image_cache_task::ImageResponseMsg::*; - use net_traits::image_cache_task::Msg::*; - - use resource_task::start_sending; - use net_traits::{ControlMsg, Metadata, ProgressMsg, ResourceTask}; - use net_traits::image_cache_task::{ImageCacheTask, ImageResponseMsg, Msg}; - use net_traits::ProgressMsg::{Payload, Done}; - use profile::time; - use std::sync::mpsc::{Sender, channel, Receiver}; - use url::Url; - use util::taskpool::TaskPool; - - static TEST_IMAGE: &'static [u8] = include_bytes!("test.jpeg"); - - pub fn test_image_bin() -> Vec<u8> { - TEST_IMAGE.iter().map(|&x| x).collect() - } - - trait ImageCacheTaskHelper { - fn wait_for_store(&self) -> Receiver<()>; - fn wait_for_store_prefetched(&self) -> Receiver<()>; - } - - impl ImageCacheTaskHelper for ImageCacheTask { - fn wait_for_store(&self) -> Receiver<()> { - let (chan, port) = channel(); - self.send(Msg::WaitForStore(chan)); - port - } - - fn wait_for_store_prefetched(&self) -> Receiver<()> { - let (chan, port) = channel(); - self.send(Msg::WaitForStorePrefetched(chan)); - port - } - } - - trait Closure { - fn invoke(&self, _response: Sender<ProgressMsg>) { } - } - struct DoesNothing; - impl Closure for DoesNothing { } - - struct JustSendOK { - url_requested_chan: Sender<()>, - } - impl Closure for JustSendOK { - fn invoke(&self, response: Sender<ProgressMsg>) { - self.url_requested_chan.send(()); - response.send(Done(Ok(()))); - } - } - - struct SendTestImage; - impl Closure for SendTestImage { - fn invoke(&self, response: Sender<ProgressMsg>) { - response.send(Payload(test_image_bin())); - response.send(Done(Ok(()))); - } - } - - struct SendBogusImage; - impl Closure for SendBogusImage { - fn invoke(&self, response: Sender<ProgressMsg>) { - response.send(Payload(vec!())); - response.send(Done(Ok(()))); - } - } - - struct SendTestImageErr; - impl Closure for SendTestImageErr { - fn invoke(&self, response: Sender<ProgressMsg>) { - response.send(Payload(test_image_bin())); - response.send(Done(Err("".to_string()))); - } - } - - struct WaitSendTestImage { - wait_port: Receiver<()>, - } - impl Closure for WaitSendTestImage { - fn invoke(&self, response: Sender<ProgressMsg>) { - // Don't send the data until after the client requests - // the image - self.wait_port.recv().unwrap(); - response.send(Payload(test_image_bin())); - response.send(Done(Ok(()))); - } - } - - struct WaitSendTestImageErr { - wait_port: Receiver<()>, - } - impl Closure for WaitSendTestImageErr { - fn invoke(&self, response: Sender<ProgressMsg>) { - // Don't send the data until after the client requests - // the image - self.wait_port.recv().unwrap(); - response.send(Payload(test_image_bin())); - response.send(Done(Err("".to_string()))); - } - } - - fn mock_resource_task<T: Closure + Send + 'static>(on_load: Box<T>) -> ResourceTask { - spawn_listener(move |port: Receiver<ControlMsg>| { - loop { - match port.recv().unwrap() { - ControlMsg::Load(response) => { - let chan = start_sending(response.consumer, Metadata::default( - Url::parse("file:///fake").unwrap())); - on_load.invoke(chan); - } - ControlMsg::Exit => break, - _ => {} - } - } - }) - } - - fn profiler() -> time::ProfilerChan { - time::Profiler::create(None) - } - - #[test] - fn should_exit_on_request() { - let mock_resource_task = mock_resource_task(box DoesNothing); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Ignore); - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - #[should_panic] - fn should_panic_if_unprefetched_image_is_requested() { - let mock_resource_task = mock_resource_task(box DoesNothing); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Preload); - let url = Url::parse("file:///").unwrap(); - - let (chan, port) = channel(); - image_cache_task.send(Msg::GetImage(url, chan)); - port.recv().unwrap(); - } - - #[test] - fn should_request_url_from_resource_task_on_prefetch() { - let (url_requested_chan, url_requested) = channel(); - - let mock_resource_task = mock_resource_task(box JustSendOK { url_requested_chan: url_requested_chan}); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Preload); - let url = Url::parse("file:///").unwrap(); - - image_cache_task.send(Prefetch(url)); - url_requested.recv().unwrap(); - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - fn should_not_request_url_from_resource_task_on_multiple_prefetches() { - let (url_requested_chan, url_requested) = channel(); - - let mock_resource_task = mock_resource_task(box JustSendOK { url_requested_chan: url_requested_chan}); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Ignore); - let url = Url::parse("file:///").unwrap(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Prefetch(url)); - url_requested.recv().unwrap(); - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - match url_requested.try_recv() { - Err(_) => (), - Ok(_) => panic!(), - }; - } - - #[test] - fn should_return_image_not_ready_if_data_has_not_arrived() { - let (wait_chan, wait_port) = channel(); - - let mock_resource_task = mock_resource_task(box WaitSendTestImage{wait_port: wait_port}); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Ignore); - let url = Url::parse("file:///").unwrap(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::GetImage(url, response_chan)); - assert!(response_port.recv().unwrap() == ImageResponseMsg::ImageNotReady); - wait_chan.send(()); - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - fn should_return_decoded_image_data_if_data_has_arrived() { - let mock_resource_task = mock_resource_task(box SendTestImage); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Preload); - let url = Url::parse("file:///").unwrap(); - - let join_port = image_cache_task.wait_for_store(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - // Wait until our mock resource task has sent the image to the image cache - join_port.recv().unwrap(); - - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::GetImage(url, response_chan)); - match response_port.recv().unwrap() { - ImageResponseMsg::ImageReady(_) => (), - _ => panic!("bleh") - } - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - fn should_return_decoded_image_data_for_multiple_requests() { - let mock_resource_task = mock_resource_task(box SendTestImage); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Preload); - let url = Url::parse("file:///").unwrap(); - - let join_port = image_cache_task.wait_for_store(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - // Wait until our mock resource task has sent the image to the image cache - join_port.recv().unwrap(); - - for _ in range(0u32, 2u32) { - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::GetImage(url.clone(), response_chan)); - match response_port.recv().unwrap() { - ImageResponseMsg::ImageReady(_) => (), - _ => panic!("bleh") - } - } - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - fn should_not_request_image_from_resource_task_if_image_is_already_available() { - let (image_bin_sent_chan, image_bin_sent) = channel(); - - let (resource_task_exited_chan, resource_task_exited) = channel(); - - let mock_resource_task = spawn_listener(move |port: Receiver<ControlMsg>| { - loop { - match port.recv().unwrap() { - ControlMsg::Load(response) => { - let chan = start_sending(response.consumer, Metadata::default( - Url::parse("file:///fake").unwrap())); - chan.send(Payload(test_image_bin())); - chan.send(Done(Ok(()))); - image_bin_sent_chan.send(()); - } - ControlMsg::Exit => { - resource_task_exited_chan.send(()); - break - } - _ => {} - } - } - }); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Ignore); - let url = Url::parse("file:///").unwrap(); - - image_cache_task.send(Prefetch(url.clone())); - - // Wait until our mock resource task has sent the image to the image cache - image_bin_sent.recv().unwrap(); - - image_cache_task.send(Prefetch(url.clone())); - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - - resource_task_exited.recv().unwrap(); - - // Our resource task should not have received another request for the image - // because it's already cached - match image_bin_sent.try_recv() { - Err(_) => (), - Ok(_) => panic!(), - } - } - - #[test] - fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() { - let (image_bin_sent_chan, image_bin_sent) = channel(); - - let (resource_task_exited_chan, resource_task_exited) = channel(); - let mock_resource_task = spawn_listener(move |port: Receiver<ControlMsg>| { - loop { - match port.recv().unwrap() { - ControlMsg::Load(response) => { - let chan = start_sending(response.consumer, Metadata::default( - Url::parse("file:///fake").unwrap())); - chan.send(Payload(test_image_bin())); - chan.send(Done(Err("".to_string()))); - image_bin_sent_chan.send(()); - } - ControlMsg::Exit => { - resource_task_exited_chan.send(()); - break - } - _ => {} - } - } - }); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Ignore); - let url = Url::parse("file:///").unwrap(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - // Wait until our mock resource task has sent the image to the image cache - image_bin_sent.recv().unwrap(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - - resource_task_exited.recv().unwrap(); - - // Our resource task should not have received another request for the image - // because it's already cached - match image_bin_sent.try_recv() { - Err(_) => (), - Ok(_) => panic!(), - } - } - - #[test] - fn should_return_failed_if_image_bin_cannot_be_fetched() { - let mock_resource_task = mock_resource_task(box SendTestImageErr); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Preload); - let url = Url::parse("file:///").unwrap(); - - let join_port = image_cache_task.wait_for_store_prefetched(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - // Wait until our mock resource task has sent the image to the image cache - join_port.recv().unwrap(); - - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::GetImage(url, response_chan)); - match response_port.recv().unwrap() { - ImageResponseMsg::ImageFailed => (), - _ => panic!("bleh") - } - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_fetched() { - let mock_resource_task = mock_resource_task(box SendTestImageErr); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Preload); - let url = Url::parse("file:///").unwrap(); - - let join_port = image_cache_task.wait_for_store_prefetched(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - // Wait until our mock resource task has sent the image to the image cache - join_port.recv().unwrap(); - - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::GetImage(url.clone(), response_chan)); - match response_port.recv().unwrap() { - ImageResponseMsg::ImageFailed => (), - _ => panic!("bleh") - } - - // And ask again, we should get the same response - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::GetImage(url, response_chan)); - match response_port.recv().unwrap() { - ImageResponseMsg::ImageFailed => (), - _ => panic!("bleh") - } - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - fn should_return_failed_if_image_decode_fails() { - let mock_resource_task = mock_resource_task(box SendBogusImage); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Preload); - let url = Url::parse("file:///").unwrap(); - - let join_port = image_cache_task.wait_for_store(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - // Wait until our mock resource task has sent the image to the image cache - join_port.recv().unwrap(); - - // Make the request - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::GetImage(url, response_chan)); - - match response_port.recv().unwrap() { - ImageResponseMsg::ImageFailed => (), - _ => panic!("bleh") - } - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - fn should_return_image_on_wait_if_image_is_already_loaded() { - let mock_resource_task = mock_resource_task(box SendTestImage); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Preload); - let url = Url::parse("file:///").unwrap(); - - let join_port = image_cache_task.wait_for_store(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - // Wait until our mock resource task has sent the image to the image cache - join_port.recv().unwrap(); - - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::WaitForImage(url, response_chan)); - match response_port.recv().unwrap() { - ImageResponseMsg::ImageReady(..) => (), - _ => panic!("bleh") - } - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - fn should_return_image_on_wait_if_image_is_not_yet_loaded() { - let (wait_chan, wait_port) = channel(); - - let mock_resource_task = mock_resource_task(box WaitSendTestImage {wait_port: wait_port}); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Ignore); - let url = Url::parse("file:///").unwrap(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::WaitForImage(url, response_chan)); - - wait_chan.send(()); - - match response_port.recv().unwrap() { - ImageResponseMsg::ImageReady(..) => (), - _ => panic!("bleh") - } - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - fn should_return_image_failed_on_wait_if_image_fails_to_load() { - let (wait_chan, wait_port) = channel(); - - let mock_resource_task = mock_resource_task(box WaitSendTestImageErr{wait_port: wait_port}); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Ignore); - let url = Url::parse("file:///").unwrap(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::WaitForImage(url, response_chan)); - - wait_chan.send(()); - - match response_port.recv().unwrap() { - ImageResponseMsg::ImageFailed => (), - _ => panic!("bleh") - } - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } - - #[test] - fn sync_cache_should_wait_for_images() { - let mock_resource_task = mock_resource_task(box SendTestImage); - - let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new_sync(mock_resource_task.clone(), - TaskPool::new(4), profiler(), - LoadPlaceholder::Preload); - let url = Url::parse("file:///").unwrap(); - - image_cache_task.send(Prefetch(url.clone())); - image_cache_task.send(Decode(url.clone())); - - let (response_chan, response_port) = channel(); - image_cache_task.send(Msg::GetImage(url, response_chan)); - match response_port.recv().unwrap() { - ImageResponseMsg::ImageReady(_) => (), - _ => panic!("bleh") - } - - image_cache_task.exit(); - mock_resource_task.send(ControlMsg::Exit); - } -} diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 59afb2dcf66..c9071be89cd 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -930,6 +930,7 @@ dependencies = [ "gfx 0.0.1", "net 0.0.1", "net_traits 0.0.1", + "profile 0.0.1", "url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", ] diff --git a/tests/unit/Cargo.toml b/tests/unit/Cargo.toml index 7b995ce669a..3e8520bbcc2 100644 --- a/tests/unit/Cargo.toml +++ b/tests/unit/Cargo.toml @@ -20,6 +20,9 @@ path = "../../components/net" [dependencies.net_traits] path = "../../components/net_traits" +[dependencies.profile] +path = "../../components/profile" + [dependencies.geom] git = "https://github.com/servo/rust-geom" diff --git a/tests/unit/lib.rs b/tests/unit/lib.rs index de3799ef1e6..22e2d349bb6 100644 --- a/tests/unit/lib.rs +++ b/tests/unit/lib.rs @@ -2,7 +2,9 @@ extern crate geom; extern crate gfx; extern crate net; extern crate net_traits; +extern crate profile; extern crate util; +extern crate url; #[cfg(test)] #[path="gfx/mod.rs"] mod gfx_tests; #[cfg(test)] #[path="net/mod.rs"] mod net_tests; diff --git a/tests/unit/net/cookie.rs b/tests/unit/net/cookie.rs index d76a0cda253..6b4ee8fb565 100644 --- a/tests/unit/net/cookie.rs +++ b/tests/unit/net/cookie.rs @@ -1,10 +1,9 @@ extern crate "cookie" as cookie_rs; -extern crate url; use net::cookie::Cookie; use net::cookie_storage::CookieStorage; use net_traits::CookieSource; -use self::url::Url; +use url::Url; #[test] diff --git a/tests/unit/net/data_loader.rs b/tests/unit/net/data_loader.rs new file mode 100644 index 00000000000..ef793f2982a --- /dev/null +++ b/tests/unit/net/data_loader.rs @@ -0,0 +1,71 @@ +use net_traits::LoadData; +use net_traits::ProgressMsg::{Payload, Done}; + +#[cfg(test)] +fn assert_parse(url: &'static str, + content_type: Option<(String, String)>, + charset: Option<String>, + data: Option<Vec<u8>>) { + use std::sync::mpsc::channel; + use url::Url; + use net::data_loader::load; + + let (start_chan, start_port) = channel(); + load(LoadData::new(Url::parse(url).unwrap(), start_chan)); + + let response = start_port.recv().unwrap(); + assert_eq!(&response.metadata.content_type, &content_type); + assert_eq!(&response.metadata.charset, &charset); + + let progress = response.progress_port.recv().unwrap(); + + match data { + None => { + assert_eq!(progress, Done(Err("invalid data uri".to_string()))); + } + Some(dat) => { + assert_eq!(progress, Payload(dat)); + assert_eq!(response.progress_port.recv().unwrap(), Done(Ok(()))); + } + } +} + +#[test] +fn empty_invalid() { + assert_parse("data:", None, None, None); +} + +#[test] +fn plain() { + assert_parse("data:,hello%20world", None, None, Some(b"hello world".iter().map(|&x| x).collect())); +} + +#[test] +fn plain_ct() { + assert_parse("data:text/plain,hello", + Some(("text".to_string(), "plain".to_string())), None, Some(b"hello".iter().map(|&x| x).collect())); +} + +#[test] +fn plain_charset() { + assert_parse("data:text/plain;charset=latin1,hello", + Some(("text".to_string(), "plain".to_string())), Some("latin1".to_string()), Some(b"hello".iter().map(|&x| x).collect())); +} + +#[test] +fn base64() { + assert_parse("data:;base64,C62+7w==", None, None, Some(vec!(0x0B, 0xAD, 0xBE, 0xEF))); +} + +#[test] +fn base64_ct() { + assert_parse("data:application/octet-stream;base64,C62+7w==", + Some(("application".to_string(), "octet-stream".to_string())), None, Some(vec!(0x0B, 0xAD, 0xBE, 0xEF))); +} + +#[test] +fn base64_charset() { + assert_parse("data:text/plain;charset=koi8-r;base64,8PLl9+XkIO3l5Pfl5A==", + Some(("text".to_string(), "plain".to_string())), Some("koi8-r".to_string()), + Some(vec!(0xF0, 0xF2, 0xE5, 0xF7, 0xE5, 0xE4, 0x20, 0xED, 0xE5, 0xE4, 0xF7, 0xE5, 0xE4))); +} diff --git a/tests/unit/net/image_cache_task.rs b/tests/unit/net/image_cache_task.rs new file mode 100644 index 00000000000..22b0920e8ae --- /dev/null +++ b/tests/unit/net/image_cache_task.rs @@ -0,0 +1,570 @@ +use net::image_cache_task::*; +use net_traits::image_cache_task::ImageResponseMsg::*; +use net_traits::image_cache_task::Msg::*; + +use net::resource_task::start_sending; +use net_traits::{ControlMsg, Metadata, ProgressMsg, ResourceTask}; +use net_traits::image_cache_task::{ImageCacheTask, ImageResponseMsg, Msg}; +use net_traits::ProgressMsg::{Payload, Done}; +use profile::time; +use std::sync::mpsc::{Sender, channel, Receiver}; +use url::Url; +use util::taskpool::TaskPool; + +static TEST_IMAGE: &'static [u8] = include_bytes!("test.jpeg"); + +pub fn test_image_bin() -> Vec<u8> { + TEST_IMAGE.iter().map(|&x| x).collect() +} + +trait ImageCacheTaskHelper { + fn wait_for_store(&self) -> Receiver<()>; + fn wait_for_store_prefetched(&self) -> Receiver<()>; +} + +impl ImageCacheTaskHelper for ImageCacheTask { + fn wait_for_store(&self) -> Receiver<()> { + let (chan, port) = channel(); + self.send(Msg::WaitForStore(chan)); + port + } + + fn wait_for_store_prefetched(&self) -> Receiver<()> { + let (chan, port) = channel(); + self.send(Msg::WaitForStorePrefetched(chan)); + port + } +} + +trait Closure { + fn invoke(&self, _response: Sender<ProgressMsg>) { } +} +struct DoesNothing; +impl Closure for DoesNothing { } + +struct JustSendOK { + url_requested_chan: Sender<()>, +} +impl Closure for JustSendOK { + fn invoke(&self, response: Sender<ProgressMsg>) { + self.url_requested_chan.send(()).unwrap(); + response.send(Done(Ok(()))).unwrap(); + } +} + +struct SendTestImage; +impl Closure for SendTestImage { + fn invoke(&self, response: Sender<ProgressMsg>) { + response.send(Payload(test_image_bin())).unwrap(); + response.send(Done(Ok(()))).unwrap(); + } +} + +struct SendBogusImage; +impl Closure for SendBogusImage { + fn invoke(&self, response: Sender<ProgressMsg>) { + response.send(Payload(vec!())).unwrap(); + response.send(Done(Ok(()))).unwrap(); + } +} + +struct SendTestImageErr; +impl Closure for SendTestImageErr { + fn invoke(&self, response: Sender<ProgressMsg>) { + response.send(Payload(test_image_bin())).unwrap(); + response.send(Done(Err("".to_string()))).unwrap(); + } +} + +struct WaitSendTestImage { + wait_port: Receiver<()>, +} +impl Closure for WaitSendTestImage { + fn invoke(&self, response: Sender<ProgressMsg>) { + // Don't send the data until after the client requests + // the image + self.wait_port.recv().unwrap(); + response.send(Payload(test_image_bin())).unwrap(); + response.send(Done(Ok(()))).unwrap(); + } +} + +struct WaitSendTestImageErr { + wait_port: Receiver<()>, +} +impl Closure for WaitSendTestImageErr { + fn invoke(&self, response: Sender<ProgressMsg>) { + // Don't send the data until after the client requests + // the image + self.wait_port.recv().unwrap(); + response.send(Payload(test_image_bin())).unwrap(); + response.send(Done(Err("".to_string()))).unwrap(); + } +} + +fn mock_resource_task<T: Closure + Send + 'static>(on_load: Box<T>) -> ResourceTask { + spawn_listener(move |port: Receiver<ControlMsg>| { + loop { + match port.recv().unwrap() { + ControlMsg::Load(response) => { + let chan = start_sending(response.consumer, Metadata::default( + Url::parse("file:///fake").unwrap())); + on_load.invoke(chan); + } + ControlMsg::Exit => break, + _ => {} + } + } + }) +} + +fn profiler() -> time::ProfilerChan { + time::Profiler::create(None) +} + +#[test] +fn should_exit_on_request() { + let mock_resource_task = mock_resource_task(Box::new(DoesNothing)); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Ignore); + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit).unwrap(); +} + +#[test] +#[should_panic] +fn should_panic_if_unprefetched_image_is_requested() { + let mock_resource_task = mock_resource_task(Box::new(DoesNothing)); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Preload); + let url = Url::parse("file:///").unwrap(); + + let (chan, port) = channel(); + image_cache_task.send(Msg::GetImage(url, chan)); + port.recv().unwrap(); +} + +#[test] +fn should_request_url_from_resource_task_on_prefetch() { + let (url_requested_chan, url_requested) = channel(); + + let mock_resource_task = mock_resource_task(Box::new(JustSendOK { url_requested_chan: url_requested_chan})); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Preload); + let url = Url::parse("file:///").unwrap(); + + image_cache_task.send(Prefetch(url)); + url_requested.recv().unwrap(); + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit).unwrap(); +} + +#[test] +fn should_not_request_url_from_resource_task_on_multiple_prefetches() { + let (url_requested_chan, url_requested) = channel(); + + let mock_resource_task = mock_resource_task(Box::new(JustSendOK { url_requested_chan: url_requested_chan})); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Ignore); + let url = Url::parse("file:///").unwrap(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Prefetch(url)); + url_requested.recv().unwrap(); + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit).unwrap(); + match url_requested.try_recv() { + Err(_) => (), + Ok(_) => panic!(), + }; +} + +#[test] +fn should_return_image_not_ready_if_data_has_not_arrived() { + let (wait_chan, wait_port) = channel(); + + let mock_resource_task = mock_resource_task(Box::new(WaitSendTestImage{wait_port: wait_port})); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Ignore); + let url = Url::parse("file:///").unwrap(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::GetImage(url, response_chan)); + assert!(response_port.recv().unwrap() == ImageResponseMsg::ImageNotReady); + wait_chan.send(()).unwrap(); + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit).unwrap(); +} + +#[test] +fn should_return_decoded_image_data_if_data_has_arrived() { + let mock_resource_task = mock_resource_task(Box::new(SendTestImage)); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Preload); + let url = Url::parse("file:///").unwrap(); + + let join_port = image_cache_task.wait_for_store(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + // Wait until our mock resource task has sent the image to the image cache + join_port.recv().unwrap(); + + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::GetImage(url, response_chan)); + match response_port.recv().unwrap() { + ImageResponseMsg::ImageReady(_) => (), + _ => panic!("bleh") + } + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit).unwrap(); +} + +#[test] +fn should_return_decoded_image_data_for_multiple_requests() { + let mock_resource_task = mock_resource_task(Box::new(SendTestImage)); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Preload); + let url = Url::parse("file:///").unwrap(); + + let join_port = image_cache_task.wait_for_store(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + // Wait until our mock resource task has sent the image to the image cache + join_port.recv().unwrap(); + + for _ in 0..2 { + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::GetImage(url.clone(), response_chan)); + match response_port.recv().unwrap() { + ImageResponseMsg::ImageReady(_) => (), + _ => panic!("bleh") + } + } + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit).unwrap(); +} + +#[test] +fn should_not_request_image_from_resource_task_if_image_is_already_available() { + let (image_bin_sent_chan, image_bin_sent) = channel(); + + let (resource_task_exited_chan, resource_task_exited) = channel(); + + let mock_resource_task = spawn_listener(move |port: Receiver<ControlMsg>| { + loop { + match port.recv().unwrap() { + ControlMsg::Load(response) => { + let chan = start_sending(response.consumer, Metadata::default( + Url::parse("file:///fake").unwrap())); + chan.send(Payload(test_image_bin())); + chan.send(Done(Ok(()))); + image_bin_sent_chan.send(()); + } + ControlMsg::Exit => { + resource_task_exited_chan.send(()); + break + } + _ => {} + } + } + }); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Ignore); + let url = Url::parse("file:///").unwrap(); + + image_cache_task.send(Prefetch(url.clone())); + + // Wait until our mock resource task has sent the image to the image cache + image_bin_sent.recv().unwrap(); + + image_cache_task.send(Prefetch(url.clone())); + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit); + + resource_task_exited.recv().unwrap(); + + // Our resource task should not have received another request for the image + // because it's already cached + match image_bin_sent.try_recv() { + Err(_) => (), + Ok(_) => panic!(), + } +} + +#[test] +fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() { + let (image_bin_sent_chan, image_bin_sent) = channel(); + + let (resource_task_exited_chan, resource_task_exited) = channel(); + let mock_resource_task = spawn_listener(move |port: Receiver<ControlMsg>| { + loop { + match port.recv().unwrap() { + ControlMsg::Load(response) => { + let chan = start_sending(response.consumer, Metadata::default( + Url::parse("file:///fake").unwrap())); + chan.send(Payload(test_image_bin())); + chan.send(Done(Err("".to_string()))); + image_bin_sent_chan.send(()); + } + ControlMsg::Exit => { + resource_task_exited_chan.send(()); + break + } + _ => {} + } + } + }); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Ignore); + let url = Url::parse("file:///").unwrap(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + // Wait until our mock resource task has sent the image to the image cache + image_bin_sent.recv().unwrap(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit); + + resource_task_exited.recv().unwrap(); + + // Our resource task should not have received another request for the image + // because it's already cached + match image_bin_sent.try_recv() { + Err(_) => (), + Ok(_) => panic!(), + } +} + +#[test] +fn should_return_failed_if_image_bin_cannot_be_fetched() { + let mock_resource_task = mock_resource_task(Box::new(SendTestImageErr)); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Preload); + let url = Url::parse("file:///").unwrap(); + + let join_port = image_cache_task.wait_for_store_prefetched(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + // Wait until our mock resource task has sent the image to the image cache + join_port.recv().unwrap(); + + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::GetImage(url, response_chan)); + match response_port.recv().unwrap() { + ImageResponseMsg::ImageFailed => (), + _ => panic!("bleh") + } + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit); +} + +#[test] +fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_fetched() { + let mock_resource_task = mock_resource_task(Box::new(SendTestImageErr)); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Preload); + let url = Url::parse("file:///").unwrap(); + + let join_port = image_cache_task.wait_for_store_prefetched(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + // Wait until our mock resource task has sent the image to the image cache + join_port.recv().unwrap(); + + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::GetImage(url.clone(), response_chan)); + match response_port.recv().unwrap() { + ImageResponseMsg::ImageFailed => (), + _ => panic!("bleh") + } + + // And ask again, we should get the same response + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::GetImage(url, response_chan)); + match response_port.recv().unwrap() { + ImageResponseMsg::ImageFailed => (), + _ => panic!("bleh") + } + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit); +} + +#[test] +fn should_return_failed_if_image_decode_fails() { + let mock_resource_task = mock_resource_task(Box::new(SendBogusImage)); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Preload); + let url = Url::parse("file:///").unwrap(); + + let join_port = image_cache_task.wait_for_store(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + // Wait until our mock resource task has sent the image to the image cache + join_port.recv().unwrap(); + + // Make the request + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::GetImage(url, response_chan)); + + match response_port.recv().unwrap() { + ImageResponseMsg::ImageFailed => (), + _ => panic!("bleh") + } + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit); +} + +#[test] +fn should_return_image_on_wait_if_image_is_already_loaded() { + let mock_resource_task = mock_resource_task(Box::new(SendTestImage)); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Preload); + let url = Url::parse("file:///").unwrap(); + + let join_port = image_cache_task.wait_for_store(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + // Wait until our mock resource task has sent the image to the image cache + join_port.recv().unwrap(); + + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::WaitForImage(url, response_chan)); + match response_port.recv().unwrap() { + ImageResponseMsg::ImageReady(..) => (), + _ => panic!("bleh") + } + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit); +} + +#[test] +fn should_return_image_on_wait_if_image_is_not_yet_loaded() { + let (wait_chan, wait_port) = channel(); + + let mock_resource_task = mock_resource_task(Box::new(WaitSendTestImage {wait_port: wait_port})); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Ignore); + let url = Url::parse("file:///").unwrap(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::WaitForImage(url, response_chan)); + + wait_chan.send(()); + + match response_port.recv().unwrap() { + ImageResponseMsg::ImageReady(..) => (), + _ => panic!("bleh") + } + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit); +} + +#[test] +fn should_return_image_failed_on_wait_if_image_fails_to_load() { + let (wait_chan, wait_port) = channel(); + + let mock_resource_task = mock_resource_task(Box::new(WaitSendTestImageErr{wait_port: wait_port})); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Ignore); + let url = Url::parse("file:///").unwrap(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::WaitForImage(url, response_chan)); + + wait_chan.send(()); + + match response_port.recv().unwrap() { + ImageResponseMsg::ImageFailed => (), + _ => panic!("bleh") + } + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit); +} + +#[test] +fn sync_cache_should_wait_for_images() { + let mock_resource_task = mock_resource_task(Box::new(SendTestImage)); + + let image_cache_task: ImageCacheTask = ImageCacheTaskFactory::new_sync(mock_resource_task.clone(), + TaskPool::new(4), profiler(), + LoadPlaceholder::Preload); + let url = Url::parse("file:///").unwrap(); + + image_cache_task.send(Prefetch(url.clone())); + image_cache_task.send(Decode(url.clone())); + + let (response_chan, response_port) = channel(); + image_cache_task.send(Msg::GetImage(url, response_chan)); + match response_port.recv().unwrap() { + ImageResponseMsg::ImageReady(_) => (), + _ => panic!("bleh") + } + + image_cache_task.exit(); + mock_resource_task.send(ControlMsg::Exit); +} diff --git a/tests/unit/net/mod.rs b/tests/unit/net/mod.rs index 72388d19f18..42505027427 100644 --- a/tests/unit/net/mod.rs +++ b/tests/unit/net/mod.rs @@ -1 +1,3 @@ mod cookie; +mod data_loader; +mod image_cache_task; diff --git a/components/net/test.jpeg b/tests/unit/net/test.jpeg Binary files differindex 1a0bdb7acd1..1a0bdb7acd1 100644 --- a/components/net/test.jpeg +++ b/tests/unit/net/test.jpeg |