Add error reporting to image_cache_task

This commit is contained in:
Brian Anderson 2012-08-17 12:48:28 -07:00
parent 311657b56b
commit e297a9abf4
2 changed files with 95 additions and 29 deletions

View file

@ -117,7 +117,8 @@ class ImageHolder {
self.image_cache_task.send(image_cache_task::GetImage(copy url, response_port.chan())); self.image_cache_task.send(image_cache_task::GetImage(copy url, response_port.chan()));
self.image = match response_port.recv() { self.image = match response_port.recv() {
image_cache_task::ImageReady(image) => some(clone(&image)), image_cache_task::ImageReady(image) => some(clone(&image)),
image_cache_task::ImageNotReady => { image_cache_task::ImageNotReady
| image_cache_task::ImageFailed => {
#info("image was not ready for %s", url.to_str()); #info("image was not ready for %s", url.to_str());
// FIXME: Need to schedule another layout when the image is ready // FIXME: Need to schedule another layout when the image is ready
none none

View file

@ -1,5 +1,5 @@
export Msg, Prefetch, Decode, GetImage, Exit; export Msg, Prefetch, Decode, GetImage, Exit;
export ImageResponseMsg, ImageReady, ImageNotReady; export ImageResponseMsg, ImageReady, ImageNotReady, ImageFailed;
export ImageCacheTask; export ImageCacheTask;
export image_cache_task; export image_cache_task;
export ImageCacheTaskClient; export ImageCacheTaskClient;
@ -29,7 +29,7 @@ enum Msg {
Decode(url), Decode(url),
/// Used by the decoder tasks to post decoded images back to the cache /// Used by the decoder tasks to post decoded images back to the cache
/*priv*/ StoreImage(url, arc<~Image>), /*priv*/ StoreImage(url, option<arc<~Image>>),
/// Request an Image object for a URL /// Request an Image object for a URL
GetImage(url, Chan<ImageResponseMsg>), GetImage(url, Chan<ImageResponseMsg>),
@ -43,7 +43,8 @@ enum Msg {
enum ImageResponseMsg { enum ImageResponseMsg {
ImageReady(arc<~Image>), ImageReady(arc<~Image>),
ImageNotReady ImageNotReady,
ImageFailed
} }
type ImageCacheTask = Chan<Msg>; type ImageCacheTask = Chan<Msg>;
@ -251,8 +252,12 @@ impl ImageCache {
let url = url_cell.take(); let url = url_cell.take();
#debug("image_cache_task: started image decode for %s", url.to_str()); #debug("image_cache_task: started image decode for %s", url.to_str());
let image = decode(data); let image = decode(data);
let image = arc(~option::unwrap(image)); let image = if image.is_some() {
to_cache.send(StoreImage(copy url, clone_arc(&image))); some(arc(~option::unwrap(image)))
} else {
none
};
to_cache.send(StoreImage(copy url, move image));
#debug("image_cache_task: ended image decode for %s", url.to_str()); #debug("image_cache_task: ended image decode for %s", url.to_str());
} }
@ -267,6 +272,31 @@ impl ImageCache {
} }
} }
/*priv*/ fn store_image(+url: url, image: &option<arc<~Image>>) {
match self.get_state(copy url) {
Decoding => {
match *image {
some(image) => {
self.set_state(url, Decoded(@clone_arc(&image)));
}
none => {
self.set_state(url, Failed);
}
}
}
Init
| Prefetching(*)
| Prefetched(*)
| Decoded(*)
| Failed => {
fail ~"incorrect state in store_image"
}
}
}
/*priv*/ fn get_image(+url: url, response: Chan<ImageResponseMsg>) { /*priv*/ fn get_image(+url: url, response: Chan<ImageResponseMsg>) {
match self.get_state(copy url) { match self.get_state(copy url) {
@ -288,28 +318,11 @@ impl ImageCache {
} }
Failed => { Failed => {
response.send(ImageNotReady); response.send(ImageFailed);
} }
} }
} }
/*priv*/ fn store_image(+url: url, image: &arc<~Image>) {
match self.get_state(copy url) {
Decoding => {
self.set_state(url, Decoded(@clone_arc(image)));
}
Init
| Prefetching(*)
| Prefetched(*)
| Decoded(*)
| Failed => {
fail ~"incorrect state in store_image"
}
}
}
} }
@ -768,7 +781,7 @@ fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() {
} }
#[test] #[test]
fn should_return_not_ready_if_image_bin_cannot_be_fetched() { fn should_return_failed_if_image_bin_cannot_be_fetched() {
let mock_resource_task = do spawn_listener |from_client| { let mock_resource_task = do spawn_listener |from_client| {
@ -809,7 +822,7 @@ fn should_return_not_ready_if_image_bin_cannot_be_fetched() {
let response_port = port(); let response_port = port();
image_cache_task.send(GetImage(url, response_port.chan())); image_cache_task.send(GetImage(url, response_port.chan()));
match response_port.recv() { match response_port.recv() {
ImageNotReady => (), ImageFailed => (),
_ => fail _ => fail
} }
@ -818,7 +831,7 @@ fn should_return_not_ready_if_image_bin_cannot_be_fetched() {
} }
#[test] #[test]
fn should_return_not_ready_for_multiple_get_image_requests_if_image_bin_cannot_be_fetched() { fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_fetched() {
let mock_resource_task = do spawn_listener |from_client| { let mock_resource_task = do spawn_listener |from_client| {
@ -859,7 +872,7 @@ fn should_return_not_ready_for_multiple_get_image_requests_if_image_bin_cannot_b
let response_port = port(); let response_port = port();
image_cache_task.send(GetImage(copy url, response_port.chan())); image_cache_task.send(GetImage(copy url, response_port.chan()));
match response_port.recv() { match response_port.recv() {
ImageNotReady => (), ImageFailed => (),
_ => fail _ => fail
} }
@ -867,7 +880,7 @@ fn should_return_not_ready_for_multiple_get_image_requests_if_image_bin_cannot_b
let response_port = port(); let response_port = port();
image_cache_task.send(GetImage(url, response_port.chan())); image_cache_task.send(GetImage(url, response_port.chan()));
match response_port.recv() { match response_port.recv() {
ImageNotReady => (), ImageFailed => (),
_ => fail _ => fail
} }
@ -940,3 +953,55 @@ fn should_return_not_ready_if_image_is_still_decoding() {
image_cache_task.exit(); image_cache_task.exit();
mock_resource_task.send(resource_task::Exit); mock_resource_task.send(resource_task::Exit);
} }
#[test]
fn should_return_failed_if_image_decode_fails() {
let mock_resource_task = do spawn_listener |from_client| {
// infer me
let from_client: Port<resource_task::ControlMsg> = from_client;
loop {
match from_client.recv() {
resource_task::Load(_, response) => {
// Bogus data
response.send(resource_task::Payload(~[]));
response.send(resource_task::Done(result::ok(())));
}
resource_task::Exit => break
}
}
};
let image_cache_task = image_cache_task(mock_resource_task);
let url = make_url(~"file", none);
let wait_for_decode = port();
let wait_for_decode_chan = wait_for_decode.chan();
image_cache_task.send(OnMsg(|msg| {
match *msg {
StoreImage(*) => wait_for_decode_chan.send(()),
_ => ()
}
}));
image_cache_task.send(Prefetch(copy url));
image_cache_task.send(Decode(copy url));
// Wait until our mock resource task has sent the image to the image cache
wait_for_decode.recv();
// Make the request
let response_port = port();
image_cache_task.send(GetImage(url, response_port.chan()));
match response_port.recv() {
ImageFailed => (),
_ => fail
}
image_cache_task.exit();
mock_resource_task.send(resource_task::Exit);
}