mirror of
https://github.com/servo/servo.git
synced 2025-08-19 12:25:33 +01:00
Refactored image cache task - details below.
* Simpler image cache API for clients to use. * Significantly fewer threads. * One thread for image cache task (multiplexes commands, decoder threads and async resource requests). * 4 threads for decoder worker tasks. * Removed ReflowEvent hacks in script and layout tasks. * Image elements pass a Trusted<T> to image cache, which is used to dirty nodes via script task. Previous use of Untrusted addresses was unsafe. * Image requests such as background-image on layout / paint threads trigger repaint only rather than full reflow. * Add reflow batching for when multiple images load quickly. * Reduces the number of paints loading wikipedia from ~95 to ~35. * Reasonably simple to add proper prefetch support in a follow up PR. * Async loaded images always construct Image fragments now, instead of generic. * Image fragments support the image not being present. * Simpler implementation of synchronous image loading for reftests. * Removed image holder. * image.onload support. * image NaturalWidth and NaturalHeight support. * Updated WPT expectations.
This commit is contained in:
parent
e278e5b9a2
commit
d8aef7208e
33 changed files with 2785 additions and 1679 deletions
|
@ -1,574 +0,0 @@
|
|||
/* 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::image_cache_task::*;
|
||||
use net_traits::image_cache_task::ImageResponseMsg::*;
|
||||
use net_traits::image_cache_task::Msg::*;
|
||||
|
||||
use net::resource_task::{start_sending, ProgressSender};
|
||||
use net_traits::{ControlMsg, Metadata, ResourceTask};
|
||||
use net_traits::image_cache_task::{ImageCacheTask, ImageCacheTaskClient, 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: ProgressSender) { }
|
||||
}
|
||||
struct DoesNothing;
|
||||
impl Closure for DoesNothing { }
|
||||
|
||||
struct JustSendOK {
|
||||
url_requested_chan: Sender<()>,
|
||||
}
|
||||
impl Closure for JustSendOK {
|
||||
fn invoke(&self, response: ProgressSender) {
|
||||
self.url_requested_chan.send(()).unwrap();
|
||||
response.send(Done(Ok(()))).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
struct SendTestImage;
|
||||
impl Closure for SendTestImage {
|
||||
fn invoke(&self, response: ProgressSender) {
|
||||
response.send(Payload(test_image_bin())).unwrap();
|
||||
response.send(Done(Ok(()))).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
struct SendBogusImage;
|
||||
impl Closure for SendBogusImage {
|
||||
fn invoke(&self, response: ProgressSender) {
|
||||
response.send(Payload(vec!())).unwrap();
|
||||
response.send(Done(Ok(()))).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
struct SendTestImageErr;
|
||||
impl Closure for SendTestImageErr {
|
||||
fn invoke(&self, response: ProgressSender) {
|
||||
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: ProgressSender) {
|
||||
// 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: ProgressSender) {
|
||||
// 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(_, consumer) => {
|
||||
let chan = start_sending(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(_, consumer) => {
|
||||
let chan = start_sending(consumer, Metadata::default(
|
||||
Url::parse("file:///fake").unwrap()));
|
||||
chan.send(Payload(test_image_bin())).unwrap();
|
||||
chan.send(Done(Ok(()))).unwrap();
|
||||
image_bin_sent_chan.send(()).unwrap();
|
||||
}
|
||||
ControlMsg::Exit => {
|
||||
resource_task_exited_chan.send(()).unwrap();
|
||||
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).unwrap();
|
||||
|
||||
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(_, consumer) => {
|
||||
let chan = start_sending(consumer, Metadata::default(
|
||||
Url::parse("file:///fake").unwrap()));
|
||||
chan.send(Payload(test_image_bin())).unwrap();
|
||||
chan.send(Done(Err("".to_string()))).unwrap();
|
||||
image_bin_sent_chan.send(()).unwrap();
|
||||
}
|
||||
ControlMsg::Exit => {
|
||||
resource_task_exited_chan.send(()).unwrap();
|
||||
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).unwrap();
|
||||
|
||||
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).unwrap();
|
||||
}
|
||||
|
||||
#[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).unwrap();
|
||||
}
|
||||
|
||||
#[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).unwrap();
|
||||
}
|
||||
|
||||
#[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).unwrap();
|
||||
}
|
||||
|
||||
#[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(()).unwrap();
|
||||
|
||||
match response_port.recv().unwrap() {
|
||||
ImageResponseMsg::ImageReady(..) => (),
|
||||
_ => panic!("bleh")
|
||||
}
|
||||
|
||||
image_cache_task.exit();
|
||||
mock_resource_task.send(ControlMsg::Exit).unwrap();
|
||||
}
|
||||
|
||||
#[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(()).unwrap();
|
||||
|
||||
match response_port.recv().unwrap() {
|
||||
ImageResponseMsg::ImageFailed => (),
|
||||
_ => panic!("bleh")
|
||||
}
|
||||
|
||||
image_cache_task.exit();
|
||||
mock_resource_task.send(ControlMsg::Exit).unwrap();
|
||||
}
|
||||
|
||||
#[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).unwrap();
|
||||
}
|
|
@ -12,6 +12,5 @@ extern crate util;
|
|||
|
||||
#[cfg(test)] mod cookie;
|
||||
#[cfg(test)] mod data_loader;
|
||||
#[cfg(test)] mod image_cache_task;
|
||||
#[cfg(test)] mod mime_classifier;
|
||||
#[cfg(test)] mod resource_task;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue