| Marc Kupietz | a3a8cd9 | 2026-09-08 07:59:04 +0200 | [diff] [blame] | 1 | test_that("cacheAsFileName appends .rds where it is missing", { |
| 2 | expect_equal(RKorAPClient:::cacheAsFileName("analysis"), "analysis.rds") |
| 3 | expect_equal(RKorAPClient:::cacheAsFileName("analysis.rds"), "analysis.rds") |
| 4 | expect_equal(RKorAPClient:::cacheAsFileName("analysis.RDS"), "analysis.RDS") |
| 5 | }) |
| 6 | |
| Marc Kupietz | c6e7736 | 2026-09-08 14:07:49 +0200 | [diff] [blame^] | 7 | offlineKco <- function() { |
| 8 | methods::new( |
| 9 | "KorAPConnection", |
| 10 | apiUrl = "https://example.invalid/", |
| 11 | KorAPUrl = "https://example.invalid/", |
| 12 | authorizationSupported = FALSE, |
| 13 | verbose = FALSE |
| 14 | ) |
| 15 | } |
| 16 | |
| 17 | test_that("blessCacheAs makes an old file usable again", { |
| 18 | kco <- offlineKco() |
| 19 | file <- tempfile(fileext = ".rds") |
| 20 | on.exit(unlink(file), add = TRUE) |
| 21 | legacy <- tibble::tibble(node = "Test", collocate = "c", logDice = 7) |
| 22 | saveRDS(legacy, file) |
| 23 | |
| 24 | testthat::local_mocked_bindings( |
| 25 | collocatesQuery = function(...) stop("server must not be contacted"), |
| 26 | .package = "RKorAPClient" |
| 27 | ) |
| 28 | |
| 29 | expect_message(blessCacheAs(file), "records no parameters") |
| 30 | expect_silent(result <- collocationAnalysis(kco, "Test", cacheAs = file)) |
| 31 | expect_equal(result, legacy) |
| 32 | }) |
| 33 | |
| 34 | test_that("blessing records itself without claiming a provenance", { |
| 35 | file <- tempfile(fileext = ".rds") |
| 36 | on.exit(unlink(file), add = TRUE) |
| 37 | saveRDS(tibble::tibble(x = 1), file) |
| 38 | |
| 39 | suppressMessages(blessCacheAs(file)) |
| 40 | info <- cacheAsInfo(file) |
| 41 | |
| 42 | expect_equal(info$scoresConfirmedFor, RKorAPClient:::cacheAsScoreVersion) |
| 43 | expect_s3_class(info$blessedAt, "POSIXct") |
| 44 | # what actually wrote the file is unknown and stays unclaimed |
| 45 | expect_null(info$packageVersion) |
| 46 | }) |
| 47 | |
| 48 | test_that("blessCacheAs refuses a file that is not there", { |
| 49 | expect_error(blessCacheAs(file.path(tempdir(), "no-such-cache.rds")), "does not exist") |
| 50 | }) |
| 51 | |
| Marc Kupietz | afac514 | 2026-09-08 10:37:42 +0200 | [diff] [blame] | 52 | test_that("cacheAsInfo says what produced a file", { |
| 53 | skip_if_offline() |
| 54 | kco <- KorAPConnection(accessToken = NULL, verbose = FALSE) |
| 55 | file <- tempfile(fileext = ".rds") |
| 56 | on.exit(unlink(file), add = TRUE) |
| 57 | |
| 58 | frequencyQuery(kco, "Ameisenplage", cacheAs = file) |
| 59 | info <- cacheAsInfo(file) |
| 60 | |
| 61 | expect_equal(info$packageVersion, as.character(utils::packageVersion("RKorAPClient"))) |
| 62 | expect_equal(info$apiUrl, kco@apiUrl) |
| 63 | expect_equal(info$indexRevision, kco@indexRevision) |
| 64 | expect_equal(info$parameters$query, "Ameisenplage") |
| 65 | # given without its extension, the .rds file is found |
| 66 | expect_equal(cacheAsInfo(sub("\\.rds$", "", file)), info) |
| 67 | }) |
| 68 | |
| 69 | test_that("cacheAsInfo has nothing to report for a file from before 1.4.0", { |
| 70 | file <- tempfile(fileext = ".rds") |
| 71 | on.exit(unlink(file), add = TRUE) |
| 72 | saveRDS(tibble::tibble(x = 1), file) |
| 73 | |
| 74 | expect_null(cacheAsInfo(file)) |
| 75 | }) |
| 76 | |
| 77 | test_that("cacheAsInfo refuses a file that is not there", { |
| 78 | expect_error( |
| 79 | cacheAsInfo(file.path(tempdir(), "no-such-cache.rds")), |
| 80 | "does not exist" |
| 81 | ) |
| 82 | }) |
| 83 | |
| Marc Kupietz | a3a8cd9 | 2026-09-08 07:59:04 +0200 | [diff] [blame] | 84 | test_that("a cache file is written and read back, without contacting the server", { |
| 85 | skip_if_offline() |
| 86 | kco <- KorAPConnection(accessToken = NULL, verbose = FALSE) |
| 87 | dir <- file.path(tempdir(), "cacheAsTest") |
| 88 | dir.create(dir, showWarnings = FALSE) |
| 89 | on.exit(unlink(dir, recursive = TRUE), add = TRUE) |
| 90 | |
| 91 | # every query function that takes cacheAs, so that one added later without a |
| 92 | # cache file of its own does not go unnoticed |
| 93 | queries <- list( |
| 94 | "frequencyQuery" = function(f) frequencyQuery(kco, "Ameisenplage", cacheAs = f), |
| 95 | "corpusStats" = function(f) corpusStats(kco, vc = "pubDate since 2020", as.df = TRUE, cacheAs = f), |
| 96 | "collocationScoreQuery" = function(f) collocationScoreQuery(kco, "Grund", "triftiger", cacheAs = f), |
| 97 | "textMetadata" = function(f) textMetadata(kco, "WPD17/L79/98721", cacheAs = f) |
| 98 | ) |
| 99 | |
| 100 | for (name in names(queries)) { |
| 101 | query <- queries[[name]] |
| 102 | file <- file.path(dir, name) |
| 103 | |
| 104 | fresh <- query(file) |
| 105 | expect_true(file.exists(paste0(file, ".rds")), info = name) |
| 106 | |
| 107 | fromCache <- local({ |
| 108 | testthat::local_mocked_bindings( |
| 109 | apiCall = function(...) stop("server must not be contacted"), |
| 110 | .package = "RKorAPClient" |
| 111 | ) |
| 112 | query(file) |
| 113 | }) |
| 114 | expect_equal(fromCache, fresh, info = name) |
| 115 | |
| 116 | # what produced the result lives in the file only, not in the value |
| 117 | expect_null(attr(fromCache, RKorAPClient:::cacheAsAttribute), info = name) |
| 118 | expect_equal( |
| 119 | attr(readRDS(paste0(file, ".rds")), RKorAPClient:::cacheAsAttribute)$scoreVersion, |
| 120 | RKorAPClient:::cacheAsScoreVersion, |
| 121 | info = name |
| 122 | ) |
| 123 | } |
| 124 | }) |
| 125 | |
| 126 | test_that("a cache file written before the scores were corrected is refused", { |
| 127 | skip_if_offline() |
| 128 | kco <- KorAPConnection(accessToken = NULL, verbose = FALSE) |
| 129 | file <- tempfile(fileext = ".rds") |
| 130 | on.exit(unlink(file), add = TRUE) |
| 131 | |
| 132 | frequencyQuery(kco, "Ameisenplage", cacheAs = file) |
| 133 | aged <- readRDS(file) |
| 134 | record <- attr(aged, RKorAPClient:::cacheAsAttribute) |
| 135 | # as a file from before the corrections has it: an older score generation, and |
| 136 | # an older version to go with it |
| 137 | record$scoreVersion <- "1.3.0" |
| 138 | record$packageVersion <- "1.3.0" |
| 139 | attr(aged, RKorAPClient:::cacheAsAttribute) <- record |
| 140 | saveRDS(aged, file) |
| 141 | |
| 142 | expect_warning(frequencyQuery(kco, "Ameisenplage", cacheAs = file), "1\\.3\\.0") |
| 143 | # and the refused file is replaced by a current one, so the warning comes once |
| 144 | expect_silent(frequencyQuery(kco, "Ameisenplage", cacheAs = file)) |
| 145 | }) |
| 146 | |
| 147 | test_that("a query that differs is recomputed rather than read back", { |
| 148 | skip_if_offline() |
| 149 | kco <- KorAPConnection(accessToken = NULL, verbose = FALSE) |
| 150 | file <- tempfile(fileext = ".rds") |
| 151 | on.exit(unlink(file), add = TRUE) |
| 152 | |
| 153 | frequencyQuery(kco, "Ameisenplage", cacheAs = file) |
| 154 | expect_warning(frequencyQuery(kco, "Heuschreckenplage", cacheAs = file), "query") |
| 155 | }) |
| 156 | |
| 157 | test_that("verbosity is not part of what a cache file records", { |
| 158 | skip_if_offline() |
| 159 | kco <- KorAPConnection(accessToken = NULL, verbose = FALSE) |
| 160 | file <- tempfile(fileext = ".rds") |
| 161 | on.exit(unlink(file), add = TRUE) |
| 162 | |
| 163 | corpusStats(kco, vc = "pubDate since 2020", as.df = TRUE, cacheAs = file) |
| 164 | # how loud a query is does not change what it returns, so it must not make |
| 165 | # the file be thrown away |
| 166 | expect_silent( |
| 167 | corpusStats(kco, vc = "pubDate since 2020", as.df = TRUE, verbose = TRUE, cacheAs = file) |
| 168 | ) |
| 169 | }) |