crew_test("new queue is valid", {
  x <- crew_queue(step = 2e3L)
  expect_silent(x$validate())
  expect_equal(x$data, character(0L))
  expect_equal(x$head, 1L)
  expect_equal(x$tail, 0L)
  expect_equal(x$step, 2e3L)
})

crew_test("basic set()", {
  x <- crew_queue()
  expect_true(x$empty())
  expect_false(x$nonempty())
  expect_equal(x$list(), character(0L))
  x$set(c("a", "b", "c"))
  expect_equal(x$list(), c("a", "b", "c"))
  expect_false(x$empty())
  expect_true(x$nonempty())
  expect_equal(x$data, c("a", "b", "c"))
  expect_equal(x$head, 1L)
  expect_equal(x$tail, 3L)
  expect_silent(x$validate())
})

crew_test("basic reset()", {
  x <- crew_queue()
  x$set(c("a", "b", "c"))
  expect_false(x$empty())
  expect_true(x$nonempty())
  x$pop()
  expect_false(x$empty())
  expect_true(x$nonempty())
  x$reset()
  expect_true(x$empty())
  expect_false(x$nonempty())
  expect_equal(x$data, character(0L))
  expect_equal(x$head, 1L)
  expect_equal(x$tail, 0L)
  expect_silent(x$validate())
})

crew_test("basic pop()", {
  x <- crew_queue()
  expect_true(x$empty())
  expect_false(x$nonempty())
  expect_null(x$pop())
  x$set(c("a", "b", "c"))
  expect_false(x$empty())
  expect_true(x$nonempty())
  expect_equal(x$pop(), "a")
  expect_silent(x$validate())
  expect_equal(x$data, c("a", "b", "c"))
  expect_equal(x$head, 2L)
  expect_equal(x$tail, 3L)
  expect_equal(x$pop(), "b")
  expect_false(x$empty())
  expect_true(x$nonempty())
  expect_silent(x$validate())
  expect_equal(x$data, c("a", "b", "c"))
  expect_equal(x$head, 3L)
  expect_equal(x$tail, 3L)
  expect_equal(x$pop(), "c")
  expect_true(x$empty())
  expect_false(x$nonempty())
  expect_silent(x$validate())
  expect_equal(x$data, c("a", "b", "c"))
  expect_equal(x$head, 4L)
  expect_equal(x$tail, 3L)
  for (index in seq_len(3L)) {
    expect_null(x$pop())
    expect_true(x$empty())
    expect_false(x$nonempty())
    expect_silent(x$validate())
    expect_equal(x$data, c("a", "b", "c"))
    expect_equal(x$head, 4L)
    expect_equal(x$tail, 3L)
  }
  x$reset()
  expect_silent(x$validate())
  expect_equal(x$data, character(0L))
  expect_equal(x$head, 1L)
  expect_equal(x$tail, 0L)
})

crew_test("queue$pop(n = 1)", {
  q <- crew_queue(letters, step = 100L)
  expect_equal(q$pop(), "a")
  expect_equal(q$pop(), "b")
  expect_equal(q$data[q$head], "c")
  for (index in seq_len(length(letters) - 2L) + 2L) {
    expect_equal(q$pop(), letters[index])
  }
  expect_null(q$pop())
  q$extend(n = 100L)
  expect_null(q$pop())
  q$push(letters)
  for (index in seq_along(letters)) {
    expect_equal(q$pop(), letters[index])
  }
  expect_null(q$pop())
  expect_equal(q$data, c(letters, rep(NA_character_, 74L)))
  expect_equal(q$head, 27L)
  expect_equal(q$tail, 26L)
})

crew_test("queue$pop() with n > 1", {
  q <- crew_queue(letters, step = 100L)
  q$extend(n = 100)
  expect_equal(q$head, 1L)
  expect_equal(q$tail, 26L)
  expect_equal(q$pop(n = 2), c("a", "b"))
  expect_equal(q$head, 3L)
  expect_equal(q$tail, 26L)
  expect_equal(q$pop(n = 2), c("c", "d"))
  expect_equal(q$head, 5L)
  expect_equal(q$tail, 26L)
  expect_equal(q$pop(15L), letters[seq(from = 5L, to = 19L)])
  expect_equal(q$head, 20L)
  expect_equal(q$tail, 26L)
  expect_equal(q$pop(10L), letters[seq(from = 20L, to = 26L)])
  expect_equal(q$head, 27L)
  expect_equal(q$tail, 26L)
  expect_null(q$pop(10L))
  expect_equal(q$head, 27L)
  expect_equal(q$tail, 26L)
  q$push(c("a1", "a2", "a3"))
  expect_equal(q$head, 27L)
  expect_equal(q$tail, 29L)
  expect_equal(q$pop(2), c("a1", "a2"))
  expect_equal(q$head, 29L)
  expect_equal(q$tail, 29L)
  expect_equal(q$pop(2), "a3")
  expect_equal(q$head, 30L)
  expect_equal(q$tail, 29L)
  expect_null(q$pop(2L))
  expect_equal(q$head, 30L)
  expect_equal(q$tail, 29L)
})

crew_test("set() resets the queue with entirely new data", {
  x <- crew_queue()
  expect_null(x$pop())
  x$set(c("a", "b", "c", "d"))
  expect_equal(x$pop(), "a")
  expect_equal(x$pop(), "b")
  expect_silent(x$validate())
  expect_equal(x$data, c("a", "b", "c", "d"))
  expect_equal(x$head, 3L)
  expect_equal(x$tail, 4L)
  x$set(data = c("x", "y", "z"))
  expect_silent(x$validate())
  expect_equal(x$data, c("x", "y", "z"))
  expect_equal(x$head, 1L)
  expect_equal(x$tail, 3L)
  x$reset()
  expect_silent(x$validate())
  expect_equal(x$data, character(0L))
  expect_equal(x$head, 1L)
  expect_equal(x$tail, 0L)
})

crew_test("collect() without previous pop()", {
  x <- crew_queue()
  expect_null(x$collect())
  x$set(c("a", "b", "c", "d"))
  expect_equal(x$collect(), c("a", "b", "c", "d"))
  expect_true(x$empty())
  expect_false(x$nonempty())
  expect_null(x$collect())
  expect_equal(x$data, character(0L))
  expect_equal(x$head, 1L)
  expect_equal(x$tail, 0L)
})

crew_test("collect() with previous pop()", {
  x <- crew_queue()
  x$set(c("a", "b", "c", "d"))
  expect_equal(x$pop(), "a")
  expect_equal(x$pop(), "b")
  expect_equal(x$collect(), c("c", "d"))
  expect_equal(x$data, character(0L))
  expect_equal(x$head, 1L)
  expect_equal(x$tail, 0L)
})

crew_test("queue$clean()", {
  q <- crew_queue(step = 100L)
  for (index in seq_len(2L)) {
    q$clean()
    expect_equal(q$data, character(0L))
    expect_equal(q$head, 1L)
    expect_equal(q$tail, 0L)
  }
  q$push(letters)
  for (index in seq_len(4L)) {
    expect_equal(q$pop(), letters[index])
  }
  expect_equal(q$data, c(letters, rep(NA_character_, 74L)))
  expect_equal(q$head, 5L)
  expect_equal(q$data[q$head], "e")
  expect_equal(q$data[q$tail], "z")
  for (index in seq_len(2L)) {
    q$clean()
    expect_equal(q$head, 1L)
    expect_equal(q$tail, 22L)
    expect_equal(q$data[q$head], "e")
    expect_equal(q$data[q$tail], "z")
    expect_equal(q$data, c(letters[-seq_len(4L)], rep(NA_character_, 74L)))
  }
  while (q$nonempty()) {
    expect_true(nzchar(q$pop()))
  }
  expect_equal(q$data, c(letters[-seq_len(4L)], rep(NA_character_, 74L)))
  expect_equal(q$tail, 22L)
  expect_equal(q$data[q$tail], "z")
  expect_equal(q$head, 23L)
  expect_true(is.na(q$data[q$head]))
  expect_null(q$pop())
  for (index in seq_len(2L)) {
    q$clean()
    expect_equal(q$data, rep(NA_character_, 74L))
    expect_equal(q$head, 1L)
    expect_equal(q$tail, 0L)
  }
})

crew_test("queue$extend()", {
  q <- crew_queue(step = 100L)
  q$extend(n = 50)
  expect_equal(q$data, rep(NA_character_, 100L))
  expect_equal(q$head, 1L)
  expect_equal(q$tail, 0L)
  q <- crew_queue(data = letters, step = 100L)
  expect_equal(q$pop(), "a")
  q$extend(n = 100L)
  expect_equal(q$data, c(letters[-1L], rep(NA_character_, 100L)))
  expect_equal(q$head, 1L)
  expect_equal(q$tail, 25L)
  q$extend(n = 100L)
  expect_equal(q$data, c(letters[-1L], rep(NA_character_, 200L)))
  expect_equal(q$head, 1L)
  expect_equal(q$tail, 25L)
})

crew_test("queue$list()", {
  q <- crew_queue(step = 100L)
  q$extend(n = 50)
  expect_equal(q$data, rep(NA_character_, 100L))
  expect_equal(q$head, 1L)
  expect_equal(q$tail, 0L)
  q <- crew_queue(data = letters, step = 100L)
  expect_equal(q$pop(), "a")
  q$extend(n = 100L)
  expect_equal(q$pop(n = 2L), c("b", "c"))
  expect_equal(q$list(), letters[seq(from = 4L, to = 26L)])
})

crew_test("queue$push()", {
  q <- crew_queue(step = 100L)
  q$push(c("a", "b"))
  q$push(c("x", "y"))
  expect_equal(q$data, c("a", "b", "x", "y", rep(NA_character_, 96L)))
  expect_equal(q$head, 1L)
  expect_equal(q$tail, 4L)
  expect_equal(q$pop(), "a")
  expect_equal(q$data, c("a", "b", "x", "y", rep(NA_character_, 96L)))
  expect_equal(q$head, 2L)
  expect_equal(q$tail, 4L)
  q$push("z")
  expect_equal(q$data, c("a", "b", "x", "y", "z", rep(NA_character_, 95L)))
  expect_equal(q$head, 2L)
  expect_equal(q$tail, 5L)
  expect_equal(q$data[q$head], "b")
  expect_equal(q$data[q$tail], "z")
})
