test_that("on_cancel callback is called", { dx <- NULL cancelled <- FALSE cancel_msg <- NULL do <- async(function() { dx <<- deferred$new( action = function(resolve) { }, on_cancel = function(msg) { cancelled <<- TRUE cancel_msg <<- msg }) dx$cancel("changed my mind") }) err <- tryCatch(synchronise(do()), error = function(e) e) expect_match(conditionMessage(err), "changed my mind") expect_s3_class(err, "async_cancelled") expect_equal(get_private(dx)$state, "rejected") expect_true(cancelled) expect_match(cancel_msg, "changed my mind") }) test_that("then() is also rejected on cancel", { dx <- dx2 <- NULL do <- async(function() { dx <<- deferred$new(action = function(resolve) { }) dx2 <<- dx$then(function() "not this far") dx$cancel("changed my mind") dx2 }) err <- tryCatch(synchronise(do()), error = function(e) e) expect_match(conditionMessage(get_private(dx)$value), "changed my mind") expect_match(conditionMessage(get_private(dx2)$value), "changed my mind") expect_s3_class(get_private(dx)$value, "async_cancelled") expect_s3_class(get_private(dx2)$value, "async_cancelled") expect_equal(get_private(dx2)$state, "rejected") expect_equal(get_private(dx)$state, "rejected") }) test_that("can catch and handle cancellation", { err <- NULL do <- async(function() { dx <- deferred$new(action = function(resolve) { }) dx2 <- dx$catch(error = function(e) err <<- e) dx$cancel("changed my mind") dx2 }) synchronise(do()) expect_s3_class(err, "async_cancelled") expect_match(conditionMessage(err), "changed my mind") }) test_that("cancel delay", { do <- function() { d1 <- delay(60) d1$cancel() } tic <- Sys.time() expect_error(synchronise(do()), "Cancelled", class = "async_cancelled") tac <- Sys.time() expect_true(tac - tic < as.difftime(30, units = "secs")) }) test_that("cancel delay after it has started", { cancelled <- NULL do <- function() { d1 <- delay(5) d1x <- d1$catch(error = identity) d2 <- delay(1/100)$ then(function() { d1$cancel("nope"); "OK" }) when_all(d1x, d2) } tic <- Sys.time() res <- synchronise(do()) tac <- Sys.time() expect_s3_class(res[[1]], "async_cancelled") expect_equal(conditionMessage(res[[1]]), "nope") expect_equal(res[[2]], "OK") expect_true(tac - tic < as.difftime(4, units = "secs")) })