tests/testthat/test-auth-offline-helpers.R

local_clear_cli_auth <- function() {
  withr::local_envvar(
    c(
      DATABRICKS_CLI_PATH = NA_character_,
      DATABRICKS_CONFIG_FILE = NA_character_,
      DATABRICKS_CONFIG_PROFILE = NA_character_,
      DATABRICKS_CLIENT_ID = NA_character_,
      DATABRICKS_CLIENT_SECRET = NA_character_,
      ARM_CLIENT_ID = NA_character_,
      ARM_CLIENT_SECRET = NA_character_,
      ARM_TENANT_ID = NA_character_
    ),
    .local_envir = parent.frame()
  )
  withr::local_options(
    use_databrickscfg = FALSE,
    db_profile = NULL,
    .local_envir = parent.frame()
  )
  rlang::env_unbind(
    db_cli_token_cache,
    rlang::env_names(db_cli_token_cache)
  )
  withr::defer(
    rlang::env_unbind(
      db_cli_token_cache,
      rlang::env_names(db_cli_token_cache)
    ),
    envir = parent.frame()
  )
}

local_cli_token_json <- function(expires_in = 3600) {
  jsonlite::toJSON(
    list(
      access_token = "cli-access-token",
      token_type = "Bearer",
      expiry = "2026-07-14T12:11:01.79814+10:00",
      expires_in = expires_in
    ),
    auto_unbox = TRUE
  )
}

local_sign_cli_request <- function(req) {
  policy <- req$policies$auth_sign
  do.call(
    policy$fun,
    c(
      list(req = req, cache = policy$cache),
      policy$params
    )
  )
}

test_that("configured auth types are normalized before provider routing", {
  local_clear_cli_auth()

  config_file <- fs::path(withr::local_tempdir(), "databricks.cfg")
  writeLines(
    c(
      "[DEFAULT]",
      "auth_type = oauth_m2m"
    ),
    config_file
  )
  withr::local_envvar(DATABRICKS_CONFIG_FILE = config_file)
  withr::local_options(use_databrickscfg = TRUE)

  expect_identical(db_auth_type(), "oauth-m2m")
})

test_that("OAuth auth resolution rejects non-OAuth providers", {
  local_clear_cli_auth()

  expect_error(
    resolve_oauth_auth_mode(
      auth_type = "databricks-cli",
      has_db_m2m = FALSE,
      has_azure_m2m = FALSE
    ),
    "cannot be used by the OAuth client"
  )
})

test_that("CLI token responses are parsed without exposing refresh credentials", {
  local_clear_cli_auth()
  state <- new.env(parent = emptyenv())
  state$command <- NULL
  state$args <- NULL

  local_mocked_bindings(
    run = function(command, args, ...) {
      state$command <- command
      state$args <- args
      list(
        status = 0L,
        stdout = local_cli_token_json(),
        stderr = ""
      )
    },
    .package = "processx"
  )

  token <- db_cli_token(
    host = "workspace.example.com",
    profile = NULL,
    cli_path = "/mock/databricks"
  )

  expect_identical(state$command, "/mock/databricks")
  expect_identical(
    state$args,
    c(
      "auth",
      "token",
      "--host",
      "https://workspace.example.com/"
    )
  )
  expect_identical(token$access_token, "cli-access-token")
  expect_identical(token$token_type, "Bearer")
  expect_s3_class(token, "httr2_token")
  expect_gt(token$expires_at, as.numeric(Sys.time()))
  expect_null(token$refresh_token)
})

test_that("CLI command failures are actionable", {
  local_clear_cli_auth()

  local_mocked_bindings(
    run = function(command, args, ...) {
      error <- simpleError("Databricks CLI failed")
      error$stderr <- "profile is not logged in"
      stop(error)
    },
    .package = "processx"
  )

  error <- tryCatch(
    db_cli_token(
      host = "workspace.example.com",
      profile = "DEV",
      cli_path = "/mock/databricks"
    ),
    error = identity
  )

  expect_s3_class(error, "error")
  expect_match(conditionMessage(error), "profile is not logged in")
})

test_that("CLI execution failures retain their cause", {
  local_clear_cli_auth()

  local_mocked_bindings(
    run = function(command, args, ...) {
      stop("process timed out")
    },
    .package = "processx"
  )

  expect_error(
    db_cli_token(
      host = "workspace.example.com",
      profile = "DEV",
      cli_path = "/mock/databricks"
    ),
    regexp = "process timed out"
  )
})

test_that("malformed CLI responses do not expose stdout", {
  local_clear_cli_auth()

  local_mocked_bindings(
    run = function(command, args, ...) {
      list(
        status = 0L,
        stdout = "malformed-must-not-leak",
        stderr = ""
      )
    },
    .package = "processx"
  )

  error <- tryCatch(
    db_cli_token(
      host = "workspace.example.com",
      profile = "DEV",
      cli_path = "/mock/databricks"
    ),
    error = identity
  )

  expect_s3_class(error, "error")
  expect_match(conditionMessage(error), "malformed")
  expect_false(grepl(
    "malformed-must-not-leak",
    conditionMessage(error),
    fixed = TRUE
  ))
})

test_that("invalid CLI expires_in metadata is rejected", {
  local_clear_cli_auth()

  local_mocked_bindings(
    run = function(command, args, ...) {
      list(
        status = 0L,
        stdout = jsonlite::toJSON(
          list(
            access_token = "cli-access-token",
            token_type = "Bearer",
            expiry = "2026-07-14T12:11:01.79814+10:00",
            expires_in = "not-a-number"
          ),
          auto_unbox = TRUE
        ),
        stderr = ""
      )
    },
    .package = "processx"
  )

  expect_error(
    db_cli_token(
      host = "workspace.example.com",
      profile = "DEV",
      cli_path = "/mock/databricks"
    ),
    "malformed"
  )
})

test_that("Databricks CLI auth is deferred and cached until expiry", {
  local_clear_cli_auth()
  state <- new.env(parent = emptyenv())
  state$calls <- 0L
  state$args <- NULL

  config_dir <- withr::local_tempdir()
  config_file <- fs::path(config_dir, "databricks.cfg")
  writeLines(
    c(
      "[WORKSPACE]",
      "host = https://workspace.example.com",
      "auth_type = databricks-cli",
      "[__settings__]",
      "auth_storage = secure",
      "default_profile = WORKSPACE"
    ),
    config_file
  )
  withr::local_envvar(DATABRICKS_CONFIG_FILE = config_file)
  withr::local_options(use_databrickscfg = TRUE)
  expect_identical(default_config_profile(), "WORKSPACE")

  local_mocked_bindings(
    run = function(command, args, ...) {
      state$calls <- state$calls + 1L
      state$args <- args
      list(
        status = 0L,
        stdout = local_cli_token_json(),
        stderr = ""
      )
    },
    .package = "processx"
  )

  req <- db_request(
    endpoint = "clusters/list",
    method = "GET",
    version = "2.0",
    host = "workspace.example.com",
    token = NULL
  )

  expect_s3_class(req, "httr2_request")
  expect_identical(req$policies$auth_sign$params$expiry_margin, 40)
  expect_identical(state$calls, 0L)
  expect_s3_class(local_sign_cli_request(req), "httr2_request")
  expect_identical(state$calls, 1L)
  expect_identical(
    state$args,
    c(
      "auth",
      "token",
      "--profile",
      "WORKSPACE"
    )
  )

  req_two <- db_request(
    endpoint = "warehouses/list",
    method = "GET",
    version = "2.0",
    host = "workspace.example.com",
    token = NULL
  )
  expect_s3_class(local_sign_cli_request(req_two), "httr2_request")
  expect_identical(state$calls, 1L)

  req_two$policies$auth_sign$cache$set(httr2::oauth_token(
    access_token = "expiring",
    expires_in = 35
  ))
  expect_s3_class(local_sign_cli_request(req_two), "httr2_request")
  expect_identical(state$calls, 2L)

  req_other <- db_request(
    endpoint = "warehouses/list",
    method = "GET",
    version = "2.0",
    host = "other-workspace.example.com",
    token = NULL
  )
  expect_s3_class(local_sign_cli_request(req_other), "httr2_request")
  expect_identical(state$calls, 3L)
})

Try the brickster package in your browser

Any scripts or data that you put into this service are public.

brickster documentation built on July 24, 2026, 9:08 a.m.