# Package build setup ----------------------------------------------------

test_that("with*_latex context fixtures force has_latex result", {
  expect_true(with_latex(has_latex()))
  expect_false(without_latex(has_latex()))

  # one of them should be different from default
  expect_true({
    with_latex(has_latex()) != has_latex() ||
      without_latex(has_latex()) != has_latex()
  })
})

# expect `manual=TRUE` & empty `args` not to add build --no-manual flag
test_that("source build setup accept args and/or parameterized helpers", {
  expect_silent(
    res <- with_latex({
      build_setup_source(
        file.path(testthat::test_path(), "testDummy"),
        file.path(tempdir(), "testDummyBuild"),
        vignettes = FALSE,
        manual = TRUE,
        clean_doc = FALSE,
        args = c(),
        needs_compilation = FALSE
      )
    })
  )
  expect_true(!"--no-manual" %in% res$args)

  # expect `manual=FALSE` to affect build --no-manual flag
  expect_silent(
    res <- with_latex({
      build_setup_source(
        file.path(testthat::test_path(), "testDummy"),
        file.path(tempdir(), "testDummyBuild"),
        vignettes = FALSE,
        manual = FALSE,
        clean_doc = FALSE,
        args = c(),
        needs_compilation = FALSE
      )
    })
  )
  expect_true("--no-manual" %in% res$args)

  # expect `args` "--no-manual" to affect build --no-manual flag
  expect_silent(
    res <- with_latex({
      build_setup_source(
        file.path(testthat::test_path(), "testDummy"),
        file.path(tempdir(), "testDummyBuild"),
        vignettes = FALSE,
        manual = TRUE,
        clean_doc = FALSE,
        args = c("--no-manual"),
        needs_compilation = FALSE
      )
    })
  )
  expect_true("--no-manual" %in% res$args)

  expect_silent(
    res <- build_setup_source(
      file.path(testthat::test_path(), "testDummy"),
      file.path(tempdir(), "testDummyBuild"),
      vignettes = TRUE,
      manual = FALSE,
      clean_doc = FALSE,
      args = c(),
      needs_compilation = FALSE
    )
  )
  expect_true(!"--no-build-vignettes" %in% res$args)

  # expect `vignettes=FALSE` to affect build --no-build-vignettes flag
  expect_silent(
    res <- build_setup_source(
      file.path(testthat::test_path(), "testDummy"),
      file.path(tempdir(), "testDummyBuild"),
      vignettes = FALSE,
      manual = FALSE,
      clean_doc = FALSE,
      args = c(),
      needs_compilation = FALSE
    )
  )
  expect_true("--no-build-vignettes" %in% res$args)

  # expect `arg` `--no-build-vignettes` to produce --no-build-vignettes flag
  expect_silent(
    res <- build_setup_source(
      file.path(testthat::test_path(), "testDummy"),
      file.path(tempdir(), "testDummyBuild"),
      vignettes = TRUE,
      manual = FALSE,
      clean_doc = FALSE,
      args = c("--no-build-vignettes"),
      needs_compilation = FALSE
    )
  )
  expect_true("--no-build-vignettes" %in% res$args)
})

# Package without source code --------------------------------------------

test_that("source builds return correct filenames", {
  path <- build("testDummy", dest_path = tempdir(), quiet = TRUE)
  on.exit(unlink(path))

  expect_true(file.exists(path))
  expect_false(is.na(desc::desc(path)$get("Packaged")))
  expect_true(is.na(desc::desc(path)$get("Built")))
})

test_that("binary builds return correct filenames", {
  path <- build("testDummy", binary = TRUE, dest_path = tempdir(), quiet = TRUE)
  on.exit(unlink(path))

  expect_true(file.exists(path))
})

test_that("can build package without src without compiler", {
  without_compiler({
    path <- build(
      "testDummy",
      binary = TRUE,
      dest_path = tempdir(),
      quiet = TRUE
    )
    on.exit(unlink(path))

    expect_true(file.exists(path))
  })
})


# Package with src code ---------------------------------------------------

test_that("source builds return correct filenames", {
  path <- build(
    "testWithSrc",
    dest_path = tempdir(),
    quiet = TRUE,
    register_routines = FALSE
  )
  on.exit(unlink(path))

  expect_true(file.exists(path))
})

test_that("build package with src requires compiler", {
  without_compiler({
    expect_snapshot(
      error = TRUE,
      suppressMessages(
        build("testWithSrc", dest_path = tempdir(), quiet = TRUE)
      )
    )
  })
})

# Package files -----------------------------------------------------------

test_that("package tarball binary build", {
  path <- build("testDummy", dest_path = tempdir(), quiet = TRUE)
  on.exit(unlink(path), add = TRUE)

  path2 <- build(
    path,
    dest_path = tempdir(),
    quiet = TRUE,
    binary = TRUE,
    needs_compilation = FALSE,
    compile_attributes = FALSE
  )
  on.exit(unlink(path2), add = TRUE)
  expect_true(file.exists(path2))
  expect_false(is.na(desc::desc(path2)$get("Packaged")))
  expect_false(is.na(desc::desc(path2)$get("Built")))
})

test_that("package tarball binary build errors", {
  path <- build("testDummy", dest_path = tempdir(), quiet = TRUE)
  on.exit(unlink(path), add = TRUE)

  expect_snapshot(
    error = TRUE,
    build(path, dest_path = tempdir(), quiet = TRUE)
  )
  expect_snapshot(
    error = TRUE,
    build(
      path,
      dest_path = tempdir(),
      quiet = TRUE,
      binary = TRUE,
      needs_compilation = FALSE,
      compile_attributes = TRUE
    )
  )
})

test_that("warnings can be turned into errors", {
  src <- withr::local_tempdir()
  dest <- withr::local_tempdir()
  file.copy(test_path("testDummy"), src, recursive = TRUE, copy.mode = FALSE)

  withr::local_options(pkg.build_stop_for_warnings = TRUE)
  expect_silent(
    build(file.path(src, "testDummy"), dest_path = dest, quiet = TRUE)
  )

  dir.create(
    file.path(src, "testDummy", "inst"),
    recursive = TRUE,
    showWarnings = FALSE
  )
  saveRDS(1:10, file.path(src, "testDummy", "inst", "testthat-problems.rds"))

  # No warning/error on R <= 3.5
  if (getRversion() <= "3.6") skip("Needs R 3.5.0")

  # Warning looks different on older R
  expect_snapshot(
    error = TRUE,
    {
      if (getRversion() >= "4.1") {
        build(file.path(src, "testDummy"), dest_path = dest, quiet = TRUE)
      } else {
        suppressMessages(build(
          file.path(src, "testDummy"),
          dest_path = dest,
          quiet = TRUE
        ))
      }
    },
    transform = function(x) {
      x <- sub("\u2018", "'", x, fixed = TRUE)
      x <- sub("\u2019", "'", x, fixed = TRUE)
      x <- sub("checking for file '.*'", "checking for file '<file>'", x)
      x
    },
    variant = if (getRversion() >= "4.1") "new" else "old"
  )
})

test_that("Config/build/clean-inst-doc FALSE", {
  if (Sys.which("pandoc") == "") skip("No pandoc")
  dest <- withr::local_tempdir()
  expect_silent(
    build(
      test_path("testInstDoc"),
      dest_path = dest,
      quiet = TRUE,
      vignettes = TRUE,
      clean_doc = NULL
    )
  )

  pkg <- file.path(dest, dir(dest))
  expect_true(length(pkg) == 1)
  expect_true(file.exists(pkg))
  pkg_files <- untar(pkg, list = TRUE)
  expect_true("testInstDoc/inst/doc/keep.me" %in% pkg_files)
  expect_true("testInstDoc/inst/doc/test.html" %in% pkg_files)
})

test_that("Config/build/clean-inst-doc TRUE", {
  if (Sys.which("pandoc") == "") skip("No pandoc")
  src <- withr::local_tempdir()
  dest <- withr::local_tempdir()
  file.copy(test_path("testInstDoc"), src, recursive = TRUE, copy.mode = FALSE)

  desc::desc_set(
    "Config/build/clean-inst-doc" = "TRUE",
    file = file.path(src, "testInstDoc")
  )

  expect_silent(
    build(
      file.path(src, "testInstDoc"),
      dest_path = dest,
      quiet = TRUE,
      vignettes = TRUE,
      clean_doc = NULL
    )
  )
  pkg <- file.path(dest, dir(dest))
  expect_true(length(pkg) == 1)
  expect_true(file.exists(pkg))
  pkg_files <- untar(pkg, list = TRUE)
  expect_false("testInstDoc/inst/doc/keep.me" %in% pkg_files)
  expect_true("testInstDoc/inst/doc/test.html" %in% pkg_files)
})

test_that("bootstrap.R runs on build if present", {
  src <- withr::local_tempdir()
  dest <- withr::local_tempdir()
  file.copy(test_path("testDummy"), src, recursive = TRUE, copy.mode = FALSE)

  writeLines(
    c(
      'dir.create("inst")',
      'file.create("inst/file-created-by-bootstrap.txt")'
    ),
    file.path(src, "testDummy", "bootstrap.R")
  )

  desc::desc_set(
    "Config/build/bootstrap" = "TRUE",
    file = file.path(src, "testDummy")
  )

  expect_silent(
    build(
      file.path(src, "testDummy"),
      dest_path = dest,
      quiet = TRUE
    )
  )

  pkg <- file.path(dest, dir(dest))
  expect_true(length(pkg) == 1)
  expect_true(file.exists(pkg))
  pkg_files <- untar(pkg, list = TRUE)
  expect_true("testDummy/inst/file-created-by-bootstrap.txt" %in% pkg_files)
})

test_that("bootstrap.R does not run if Config/build/bootstrap is not TRUE", {
  src <- withr::local_tempdir()
  dest <- withr::local_tempdir()
  file.copy(test_path("testDummy"), src, recursive = TRUE, copy.mode = FALSE)

  writeLines(
    c(
      'dir.create("inst")',
      'file.create("inst/file-created-by-bootstrap.txt")'
    ),
    file.path(src, "testDummy", "bootstrap.R")
  )

  expect_silent(
    build(
      file.path(src, "testDummy"),
      dest_path = dest,
      quiet = TRUE
    )
  )

  pkg <- file.path(dest, dir(dest))
  expect_true(length(pkg) == 1)
  expect_true(file.exists(pkg))
  pkg_files <- untar(pkg, list = TRUE)
  expect_false("testDummy/inst/file-created-by-bootstrap.txt" %in% pkg_files)
})

test_that("bootstrap.R can output stdout, stderr, and warnings when run", {
  src <- withr::local_tempdir()
  dest <- withr::local_tempdir()
  file.copy(test_path("testDummy"), src, recursive = TRUE, copy.mode = FALSE)

  writeLines(
    c(
      'message("output on stderr")',
      'cat("output on stdout\\n")',
      'warning("this is a warning")'
    ),
    file.path(src, "testDummy", "bootstrap.R")
  )

  desc::desc_set(
    "Config/build/bootstrap" = "TRUE",
    file = file.path(src, "testDummy")
  )

  expect_output(
    expect_message(
      build(
        file.path(src, "testDummy"),
        dest_path = dest
      ),
      "Running bootstrap.R"
    ),
    "output on stderr.*?output on stdout.*?this is a warning"
  )
})
