tests/testthat/test-toxiproxy.R

context("toxiproxy")

test_that("connect to non-running server fails", {
  expect_false(has_toxiproxy(port = 22222))
  expect_error(
    toxiproxy_connection$new(port = 22222),
    "toxiproxy does not appear to be running at http://127.0.0.1:22222")
  expect_false(has_toxiproxy("nosuchhost.nodomain.foo"))
  expect_error(
    toxiproxy_connection$new("nosuchhost.nodomain.foo"),
    "toxiproxy does not appear to be running at http://nosuchhost")
})

test_that("refuse old toxiproxy version", {
  skip_if_no_toxiproxy_server()
  testthat::with_mock(
    `httr::content` = function(...) "1.2.3",
    expect_error(toxiproxy_connection$new(),
                 "Version 1.2.3 of toxiproxy server is not supported"))
})

test_that("create", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_webserver", UPSTREAM_PORT)
  on.exit(proxy$destroy())
  ## TODO: rename this class type to "toxiproxy"
  expect_is(proxy, "toxic_proxy")
  expect_equal(proxy$name, "test_webserver")
  expect_equal(proxy$upstream, sprintf("127.0.0.1:%d", UPSTREAM_PORT))
  expect_equal(proxy$upstream_host, "127.0.0.1")
  expect_equal(proxy$upstream_port, UPSTREAM_PORT)
  expect_is(proxy$listen_port, "integer")
})

test_that("list empty", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  dat <- toxiproxy_list()
  expect_equal(nrow(dat), 0)
  expect_equal(dat$name, character(0))
  expect_equal(dat$listen, character(0))
  expect_equal(dat$upstream, character(0))
  expect_equal(dat$enabled, logical(0))
  expect_equal(dat$toxics, integer(0))
})

test_that("list non-empty", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_self", UPSTREAM_PORT, 22222)
  on.exit(proxy$destroy())

  dat <- toxiproxy_list()
  expect_equal(nrow(dat), 1)
  expect_equal(dat$name, proxy$name)
  expect_equal(dat$listen, proxy$listen)
  expect_equal(dat$upstream, proxy$upstream)
  expect_equal(dat$enabled, proxy$is_enabled())
  expect_equal(dat$toxics, 0)
})

test_that("clear", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  expect_silent(toxiproxy_clear())
  proxy <- toxiproxy_create("test_self", UPSTREAM_PORT, 22222)
  expect_message(toxiproxy_clear(),
                 "Removed proxy test_self")
  expect_equal(nrow(toxiproxy_list()), 0)
})

test_that("get", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_self", UPSTREAM_PORT, 22222)
  on.exit(proxy$destroy())

  expect_error(toxiproxy_get("foo"),
               "'foo' not known to toxiproxy")

  p <- toxiproxy_get("test_self")
  expect_is(p, "toxic_proxy")
  expect_equal(p$name, proxy$name)
  expect_equal(p$listen, proxy$listen)
  expect_equal(p$upstream, proxy$upstream)
})

test_that("get non existant proxy", {
  skip_if_no_toxiproxy_server()
  expect_error(toxiproxy_get("nosuchproxy"),
               "'nosuchproxy' not known to toxiproxy")
})

test_that("delete", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_self", UPSTREAM_PORT, 22222)
  on.exit(proxy$destroy())

  expect_error(toxiproxy_delete("foo"),
               "Cannot delete proxy 'foo':")

  p <- toxiproxy_get("test_self")
  expect_is(p, "toxic_proxy")
  expect_equal(p$name, proxy$name)
  expect_equal(p$listen, proxy$listen)
  expect_equal(p$upstream, proxy$upstream)
})

test_that("reset", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_self", UPSTREAM_PORT, 22222)
  on.exit(proxy$destroy())
  cl <- test_client(proxy$listen_port)

  expect_true(cl())

  proxy$add(latency(5))
  dat <- toxiproxy_list()
  expect_equal(dat$toxics, 1)
  proxy$disable()
  expect_false(cl())

  toxiproxy_reset()
  dat <- toxiproxy_list()
  expect_equal(dat$toxics, 0)
  expect_true(proxy$is_enabled())
  expect_true(cl())
})

test_that("destroy", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_self", UPSTREAM_PORT, 22222)
  on.exit(try(proxy$destroy(), silent = TRUE))
  cl <- test_client(proxy$listen_port)

  expect_true(cl())
  proxy$destroy()
  expect_false(cl())
})

test_that("populate", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()

  data <- data.frame(name = c("foo", "bar"),
                     upstream = c(8474, UPSTREAM_PORT),
                     stringsAsFactors = FALSE)
  toxiproxy_populate(data)
  on.exit(toxiproxy_clear())
  expect_true(all(data$name %in% toxiproxy_list()$name))

  expect_silent(toxiproxy_populate(data))
  expect_true(all(data$name %in% toxiproxy_list()$name))
})

test_that("exists", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  expect_false(toxiproxy_exists("myproxy"))
  on.exit(toxiproxy_clear())
  proxy <- toxiproxy_create("myproxy", UPSTREAM_PORT)
  expect_true(toxiproxy_exists("myproxy"))
})

test_that("check_listen", {
  skip_if_no_toxiproxy_server()
  expect_equal(check_listen(0), "127.0.0.1:0")
  expect_equal(check_listen("host:1"), "host:1")

  expect_error(check_listen("noport"),
               "Invalid string for listen: noport")
  expect_error(check_listen(c("a", "b", "c")),
               "Invalid string for listen: a, b, c")
})

## This is a nasty function with too many branches because it
## validates user input
test_that("check_populate_data", {
  skip_if_no_toxiproxy_server()
  dat <- data.frame(name = "foo", upstream = 1, listen = 0,
                    stringsAsFactors = FALSE)
  cmp <- data.frame(name = "foo",
                    upstream = "127.0.0.1:1",
                    listen = "127.0.0.1:0",
                    stringsAsFactors = FALSE)
  expect_equal(check_populate_data(dat), cmp)
  expect_equal(check_populate_data(cmp), cmp)
  dat$listen <- NULL
  expect_equal(check_populate_data(dat), cmp)

  expect_error(check_populate_data(NULL),
               "Expected a data.frame")
  expect_error(check_populate_data(data.frame(listen = 0)),
               "Expected column 'name'")
  expect_error(check_populate_data(data.frame(name = 0)),
               "Column 'name' must be a character vector")
  expect_error(
    check_populate_data(data.frame(name = "a", stringsAsFactors = FALSE)),
    "Expected column 'upstream'")

  expect_error(check_populate_data(cbind(cmp, extra = 1)),
               "Unknown columns in populate data: extra")
})

test_that("clear proxy", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("myproxy", UPSTREAM_PORT)
  on.exit(proxy$destroy())
  expect_equal(length(proxy$list()), 0)

  proxy$add(latency(10))
  expect_equal(length(proxy$list()), 1)
  proxy$clear()
  expect_equal(length(proxy$list()), 0)
})

test_that("add dots", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("myproxy", UPSTREAM_PORT)
  on.exit(proxy$destroy())
  expect_equal(length(proxy$list()), 0)

  proxy$add(latency(10), bandwidth(10))
  expect_equal(length(proxy$list()), 2)
  proxy$clear()

  proxy$add(toxic_set(latency(10)))
  expect_equal(length(proxy$list()), 1)
  proxy$clear()
})

test_that("print", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("myproxy", UPSTREAM_PORT)
  str <- capture.output(print(proxy))
  expect_match(str, "<toxic_proxy>", fixed = TRUE, all = FALSE)
  expect_match(str, "(no toxics)", fixed = TRUE, all = FALSE)
  expect_match(str,
               "with_down\\(expr\\)\\s+=> evaluate expr with proxy down",
               all = FALSE)

  proxy$add(latency(1))
  str <- capture.output(print(proxy))
  expect_match(str, "<toxic_proxy>", fixed = TRUE, all = FALSE)
  expect_match(str, "'latency' toxic <latency_downstream>",
               fixed = TRUE, all = FALSE)
  expect_match(str,
               "with_down\\(expr\\)\\s+=> evaluate expr with proxy down",
               all = FALSE)
})

test_that("traffic over proxy", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  tox <- toxiproxy_create("test_webserver", upstream = UPSTREAM_PORT)
  on.exit(tox$destroy())
  cl <- test_client(tox$listen_port)
  expect_true(cl())
  t <- 300
  safety <- 0.95
  expect_true(tox$with(latency(t), cl()))
  len <- tox$with(latency(t), time_roundtrip(cl))
  expect_gt(len, safety * t / 1000)
})

test_that("with_down", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  tox <- toxiproxy_create("test_webserver", upstream = UPSTREAM_PORT)
  on.exit(tox$destroy())
  cl <- test_client(tox$listen_port)

  expect_true(tox$is_enabled())
  expect_false(tox$with_down(cl()))
  expect_true(tox$is_enabled())
  tox$disable()
  expect_false(tox$with_down(cl()))
  expect_false(tox$is_enabled())
})

test_that("create conflicting toxics", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_self", upstream = UPSTREAM_PORT)
  on.exit(proxy$destroy())
  tox <- latency(10)
  proxy$add(tox)
  expect_error(proxy$add(tox), "Error creating toxic")
})

test_that("get toxic", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_self", upstream = UPSTREAM_PORT)
  on.exit(proxy$destroy())
  proxy$add(latency(5, name = "foo"))
  tox <- proxy$get("foo")
  expect_is(tox, "toxic")
  expect_equal(tox$name, "foo")
  expect_equal(tox$type, "latency")
})

test_that("get non-existant toxic", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_self", upstream = UPSTREAM_PORT)
  on.exit(proxy$destroy())
  expect_error(proxy$get("foo"), "Can't get toxic 'foo':", fixed = TRUE)
})

test_that("delete toxic", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_self", upstream = UPSTREAM_PORT)
  on.exit(proxy$destroy())
  proxy$add(latency(5, name = "foo"))
  proxy$add(bandwidth(1, name = "bar"))
  expect_true(proxy$delete("foo"))
  expect_false(proxy$delete("foo"))
  expect_equal(proxy$delete(c("foo", "bar")), c(FALSE, TRUE))
  expect_equal(proxy$delete(c("foo", "bar")), c(FALSE, FALSE))
  expect_equal(proxy$delete(character(0)), logical(0))
})

test_that("Failed add is atomic (ish)", {
  skip_if_no_toxiproxy_server()
  toxiproxy_clear()
  proxy <- toxiproxy_create("test_self", upstream = UPSTREAM_PORT)
  a <- latency(10, name = "a")
  set <- toxic_set(bandwidth(10, "upstream", name = "b"),
                   slicer(20, name = "a"), # name conflict here
                   bandwidth(10, "downstream", name = "c"))
  proxy$clear()
  proxy$add(a)
  expect_equal(names(proxy$list()), "a")
  expect_error(proxy$add(set),
               "toxic already exists")
  expect_equal(names(proxy$list()), "a")
})
richfitz/toxiproxyr documentation built on May 25, 2017, 3:10 a.m.