test_that("sample JSON strings can be read", { expect_identical( renv_json_read(text = '[true, false, null]'), list(TRUE, FALSE, NULL) ) expect_identical( renv_json_read(text = '{"{}": "::"}'), list("{}" = "::") ) expect_identical( renv_json_read(text = '[{"a": 1.0}, {"b": -1e5}]'), list(list(a = 1.0), list(b = -1E5)) ) expect_identical( renv_json_read(text = '[{}, [], {}]'), list(named(list()), list(), named(list())) ) expect_identical( renv_json_read(text = '[{"]": "["}]'), list(list("]" = "[")) ) }) test_that("sample R objects can be converted to JSON", { before <- list(alpha = 1, beta = 2) json <- renv_json_convert(before) after <- renv_json_read(text = json) expect_equal(before, after) }) test_that("empty R lists are converted as expected", { data <- list() json <- renv_json_convert(data) expect_equal(json, "[]") names(data) <- character() json <- renv_json_convert(data) expect_equal(json, "{}") }) test_that("we can parse a GitHub remotes specification", { skip_slow() data <- renv_remotes_resolve("rstudio/renv") expect_true(data$Source == "GitHub") expect_true(data$RemoteUsername == "rstudio") expect_true(data$RemoteRepo == "renv") }) test_that("we can parse a GitHub remotes specification with 'wininet'", { skip_on_cran() skip_on_os("windows") skip_if_not(renv_platform_windows()) renv_scope_envvars(RENV_DOWNLOAD_FILE_METHOD = "wininet") data <- renv_remotes_resolve("rstudio/renv") expect_true(data$Source == "GitHub") expect_true(data$RemoteUsername == "rstudio") expect_true(data$RemoteRepo == "renv") }) test_that("we can read json containing escape characters", { actual <- list(data = "\\\"") json <- renv_json_convert(actual) expected <- renv_json_read(text = json) expect_equal(actual, expected) }) test_that("JSON null is read as R NULL", { json <- "{\"NULL\": null}" actual <- renv_json_read(text = json) expected <- list("NULL" = NULL) expect_equal(actual, expected) }) test_that("some common control characters are escaped", { json <- renv_json_convert("\b\f\n\r\t") expect_equal(json, "\"\\b\\f\\n\\r\\t\"") }) test_that("scalar values are boxed if requested", { json <- renv_json_convert( object = list(A = "hello", B = "world"), config = list(box = "B") ) value <- renv_json_read(text = json) expect_equal(value, list(A = "hello", B = list("world"))) }) test_that("the renv + jsonlite JSON readers are compatible", { skip_if_not_installed("jsonlite") renv_tests_scope("breakfast") init() lhs <- renv_json_read_default("renv.lock") rhs <- renv_json_read_jsonlite("renv.lock") expect_equal(lhs, rhs) }) test_that("NA values are properly serialized", { expect_equal(renv_json_write(NA, file = NULL), "null") expect_equal(renv_json_write(NA_character_, file = NULL), "null") expect_equal(renv_json_write(NA_real_, file = NULL), "null") expect_equal(renv_json_write(NA_integer_, file = NULL), "null") expect_equal(renv_json_write(NA_complex_, file = NULL), "null") expect_equal(renv_json_write(NaN, file = NULL), "null") }) test_that("we fall back to the internal JSON reader if jsonlite fails", { skip_if_not_installed("jsonlite") json <- renv_json_read(text = "[key: NA]") expect_equal(json, list(key = NA)) }) test_that("json-read.R can function standalone", { renv_tests_scope() renv <- asNamespace("renv") keys <- ls(envir = renv, pattern = "^renv_json_read", all.names = TRUE) vals <- mget(c("%||%", keys), envir = renv) # put those into a separate environment inheriting only from base, and # re-mark those as inheriting from base (so they only 'see' each-other) envir <- new.env(parent = baseenv()) list2env(vals, envir = envir) # for each function, check that it only uses functions from base ok <- list() for (val in vals) { recurse(body(val), function(node, stack) { if (is.call(node) && is.symbol(node[[1L]])) { lhs <- as.character(node[[1L]]) ok[[lhs]] <<- exists(lhs, envir = envir) } }) } # convert to logical vector ok <- convert(ok, "logical") bad <- names(ok)[!ok] if (length(bad) != 0L) { fmt <- "json-read.R is not standalone: %s" stopf(fmt, paste(bad, collapse = ", ")) } })