test_that("single process", { px <- get_tool("px") p <- process$new(px, c("sleep", "1", "outln", "foo", "outln", "bar"), stdout = "|") on.exit(p$kill(), add = TRUE) ## Timeout expect_equal( poll(list(p), 0), list(c(output = "timeout", error = "nopipe", process = "nopipe")) ) p$wait() expect_equal( poll(list(p), -1), list(c(output = "ready", error = "nopipe", process = "nopipe")) ) p$read_output_lines() expect_equal( poll(list(p), -1), list(c(output = "ready", error = "nopipe", process = "nopipe")) ) p$kill(close_connections = FALSE) expect_equal( poll(list(p), -1), list(c(output = "ready", error = "nopipe", process = "nopipe")) ) close(p$get_output_connection()) expect_equal( poll(list(p), -1), list(c(output = "closed", error = "nopipe", process = "nopipe")) ) }) test_that("multiple processes", { px <- get_tool("px") cmd1 <- c("sleep", "1", "outln", "foo", "outln", "bar") cmd2 <- c("sleep", "2", "errln", "foo", "errln", "bar") p1 <- process$new(px, cmd1, stdout = "|") p2 <- process$new(px, cmd2, stderr = "|") ## Timeout res <- poll(list(p1 = p1, p2 = p2), 0) expect_equal( res, list( p1 = c(output = "timeout", error = "nopipe", process = "nopipe"), p2 = c(output = "nopipe", error = "timeout", process = "nopipe") ) ) p1$wait() res <- poll(list(p1 = p1, p2 = p2), -1) expect_equal(res$p1, c(output = "ready", error = "nopipe", process = "nopipe")) expect_equal(res$p2[["output"]], "nopipe") expect_true(res$p2[["error"]] %in% c("silent", "ready")) close(p1$get_output_connection()) p2$wait() res <- poll(list(p1 = p1, p2 = p2), -1) expect_equal( res, list( p1 = c(output = "closed", error = "nopipe", process = "nopipe"), p2 = c(output = "nopipe", error = "ready", process = "nopipe") ) ) close(p2$get_error_connection()) res <- poll(list(p1 = p1, p2 = p2), 0) expect_equal( res, list( p1 = c(output = "closed", error = "nopipe", process = "nopipe"), p2 = c(output = "nopipe", error = "closed", process = "nopipe") ) ) }) test_that("multiple polls", { px <- get_tool("px") cmd <- c("sleep", "1", "outln", "foo", "sleep", "1", "outln", "bar") p <- process$new(px, cmd, stdout = "|", stderr = "|") on.exit(p$kill(), add = TRUE) out <- character() while (p$is_alive()) { poll(list(p), 2000) out <- c(out, p$read_output_lines()) } expect_identical(out, c("foo", "bar")) }) test_that("polling and buffering", { skip_on_os("windows") px <- get_tool("px") for (i in 1:10) { ## We set up two processes, one produces a output, that we do not ## read out from the cache. The other one does not produce output. p1 <- process$new(px, c(rbind("outln", 1:20), "sleep", "3"), stdout = "|", stderr = "|") p2 <- process$new(px, c("sleep", "3"), stdout = "|", stderr = "|") ## We poll until p1 has output. We read out some of the output, ## and leave the rest in the buffer. tick <- Sys.time() p1$poll_io(-1) expect_true(Sys.time() - tick < as.difftime(1, units = "secs")) expect_equal(p1$read_output_lines(n = 1), "1") ## Now poll should return immediately, because there is output ready ## from p1. The status of p2 should be 'silent' (and not 'timeout') tick <- Sys.time() s <- poll(list(p1, p2), 3000) dt <- Sys.time() - tick expect_true(dt < as.difftime(2, units = "secs")) expect_equal( s, list( c(output = "ready", error = "silent", process = "nopipe"), c(output = "silent", error = "silent", process = "nopipe") ) ) p1$kill() p2$kill() if (s[[2]][1] != "silent") break; } }) test_that("polling and buffering #2", { px <- get_tool("px") ## We run this a bunch of times, because it used to fail ## non-deterministically on the CI for (i in 1:10) { ## Two processes, they both produce output. For the first process, ## we make sure that there is something in the buffer. ## For the second process we need to poll, but data should be ## available immediately. p1 <- process$new(px, rbind("outln", 1:20), stdout = "|") p2 <- process$new(px, rbind("outln", 21:30), stdout = "|") ## We poll until p1 has output. We read out some of the output, ## and leave the rest in the buffer. p1$poll_io(-1) expect_equal(p1$read_output_lines(n = 1), "1") ## We also need to poll p2, to make sure that there is ## output from it. But we don't read anything from it. expect_equal(p1$poll_io(-1)[["output"]], "ready") expect_equal(p2$poll_io(-1)[["output"]], "ready") ## Now poll should return ready for both processes, and it should ## return fast. tick <- Sys.time() s <- poll(list(p1, p2), 3000) expect_equal( s, list( c(output = "ready", error = "nopipe", process = "nopipe"), c(output = "ready", error = "nopipe", process = "nopipe") ) ) p1$kill() p2$kill() ## Check that poll has returned immediately expect_true(Sys.time() - tick < as.difftime(2, units = "secs")) } })