blob: 91e62f260c8bf88ceedd061f84627c0f1d156df4 [file] [log] [blame]
Marc Kupietza3a8cd92026-09-08 07:59:04 +02001test_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 Kupietzc6e77362026-09-08 14:07:49 +02007offlineKco <- 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
17test_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
34test_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
48test_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 Kupietzc3de7022026-09-08 14:08:12 +020052test_that("withCachedResults takes a file as it is, and says so", {
53 kco <- offlineKco()
54 file <- tempfile(fileext = ".rds")
55 on.exit(unlink(file), add = TRUE)
56 legacy <- tibble::tibble(node = "Test", collocate = "c", logDice = 7)
57 saveRDS(legacy, file)
58
59 testthat::local_mocked_bindings(
60 collocatesQuery = function(...) stop("server must not be contacted"),
61 .package = "RKorAPClient"
62 )
63
64 expect_warning(
65 result <- withCachedResults(collocationAnalysis(kco, "Test", cacheAs = file)),
66 "used as it is"
67 )
68 expect_equal(result, legacy)
69 # and the mode does not outlive the expression
70 expect_null(getOption("rkorap.cacheAs"))
71})
72
73test_that("the offline mode refuses to compute what is not in a file", {
74 kco <- offlineKco()
75 missing <- file.path(tempdir(), "not-written-yet.rds")
76
77 expect_error(
78 withCachedResults(
79 collocationAnalysis(kco, "Test", cacheAs = missing),
80 mode = "offline"
81 ),
82 "offline"
83 )
84})
85
86test_that("the cacheAs mode comes from the option, then the environment", {
87 mode <- RKorAPClient:::cacheAsMode
88
89 expect_equal(mode(), "check")
90
91 local({
92 old <- Sys.getenv("KORAP_CACHE_AS", unset = NA)
93 on.exit(if (is.na(old)) Sys.unsetenv("KORAP_CACHE_AS") else Sys.setenv(KORAP_CACHE_AS = old))
94 Sys.setenv(KORAP_CACHE_AS = "reuse")
95 expect_equal(mode(), "reuse")
96 # the option wins where both are given
97 previous <- options(rkorap.cacheAs = "offline")
98 on.exit(options(previous), add = TRUE)
99 expect_equal(mode(), "offline")
100 })
101
102 local({
103 old <- options(rkorap.cacheAs = "nonsense")
104 on.exit(options(old))
105 expect_error(mode(), "Unknown cacheAs mode")
106 })
107})
108
Marc Kupietzafac5142026-09-08 10:37:42 +0200109test_that("cacheAsInfo says what produced a file", {
110 skip_if_offline()
111 kco <- KorAPConnection(accessToken = NULL, verbose = FALSE)
112 file <- tempfile(fileext = ".rds")
113 on.exit(unlink(file), add = TRUE)
114
115 frequencyQuery(kco, "Ameisenplage", cacheAs = file)
116 info <- cacheAsInfo(file)
117
118 expect_equal(info$packageVersion, as.character(utils::packageVersion("RKorAPClient")))
119 expect_equal(info$apiUrl, kco@apiUrl)
120 expect_equal(info$indexRevision, kco@indexRevision)
121 expect_equal(info$parameters$query, "Ameisenplage")
122 # given without its extension, the .rds file is found
123 expect_equal(cacheAsInfo(sub("\\.rds$", "", file)), info)
124})
125
126test_that("cacheAsInfo has nothing to report for a file from before 1.4.0", {
127 file <- tempfile(fileext = ".rds")
128 on.exit(unlink(file), add = TRUE)
129 saveRDS(tibble::tibble(x = 1), file)
130
131 expect_null(cacheAsInfo(file))
132})
133
134test_that("cacheAsInfo refuses a file that is not there", {
135 expect_error(
136 cacheAsInfo(file.path(tempdir(), "no-such-cache.rds")),
137 "does not exist"
138 )
139})
140
Marc Kupietza3a8cd92026-09-08 07:59:04 +0200141test_that("a cache file is written and read back, without contacting the server", {
142 skip_if_offline()
143 kco <- KorAPConnection(accessToken = NULL, verbose = FALSE)
144 dir <- file.path(tempdir(), "cacheAsTest")
145 dir.create(dir, showWarnings = FALSE)
146 on.exit(unlink(dir, recursive = TRUE), add = TRUE)
147
148 # every query function that takes cacheAs, so that one added later without a
149 # cache file of its own does not go unnoticed
150 queries <- list(
151 "frequencyQuery" = function(f) frequencyQuery(kco, "Ameisenplage", cacheAs = f),
152 "corpusStats" = function(f) corpusStats(kco, vc = "pubDate since 2020", as.df = TRUE, cacheAs = f),
153 "collocationScoreQuery" = function(f) collocationScoreQuery(kco, "Grund", "triftiger", cacheAs = f),
154 "textMetadata" = function(f) textMetadata(kco, "WPD17/L79/98721", cacheAs = f)
155 )
156
157 for (name in names(queries)) {
158 query <- queries[[name]]
159 file <- file.path(dir, name)
160
161 fresh <- query(file)
162 expect_true(file.exists(paste0(file, ".rds")), info = name)
163
164 fromCache <- local({
165 testthat::local_mocked_bindings(
166 apiCall = function(...) stop("server must not be contacted"),
167 .package = "RKorAPClient"
168 )
169 query(file)
170 })
171 expect_equal(fromCache, fresh, info = name)
172
173 # what produced the result lives in the file only, not in the value
174 expect_null(attr(fromCache, RKorAPClient:::cacheAsAttribute), info = name)
175 expect_equal(
176 attr(readRDS(paste0(file, ".rds")), RKorAPClient:::cacheAsAttribute)$scoreVersion,
177 RKorAPClient:::cacheAsScoreVersion,
178 info = name
179 )
180 }
181})
182
183test_that("a cache file written before the scores were corrected is refused", {
184 skip_if_offline()
185 kco <- KorAPConnection(accessToken = NULL, verbose = FALSE)
186 file <- tempfile(fileext = ".rds")
187 on.exit(unlink(file), add = TRUE)
188
189 frequencyQuery(kco, "Ameisenplage", cacheAs = file)
190 aged <- readRDS(file)
191 record <- attr(aged, RKorAPClient:::cacheAsAttribute)
192 # as a file from before the corrections has it: an older score generation, and
193 # an older version to go with it
194 record$scoreVersion <- "1.3.0"
195 record$packageVersion <- "1.3.0"
196 attr(aged, RKorAPClient:::cacheAsAttribute) <- record
197 saveRDS(aged, file)
198
199 expect_warning(frequencyQuery(kco, "Ameisenplage", cacheAs = file), "1\\.3\\.0")
200 # and the refused file is replaced by a current one, so the warning comes once
201 expect_silent(frequencyQuery(kco, "Ameisenplage", cacheAs = file))
202})
203
204test_that("a query that differs is recomputed rather than read back", {
205 skip_if_offline()
206 kco <- KorAPConnection(accessToken = NULL, verbose = FALSE)
207 file <- tempfile(fileext = ".rds")
208 on.exit(unlink(file), add = TRUE)
209
210 frequencyQuery(kco, "Ameisenplage", cacheAs = file)
211 expect_warning(frequencyQuery(kco, "Heuschreckenplage", cacheAs = file), "query")
212})
213
214test_that("verbosity is not part of what a cache file records", {
215 skip_if_offline()
216 kco <- KorAPConnection(accessToken = NULL, verbose = FALSE)
217 file <- tempfile(fileext = ".rds")
218 on.exit(unlink(file), add = TRUE)
219
220 corpusStats(kco, vc = "pubDate since 2020", as.df = TRUE, cacheAs = file)
221 # how loud a query is does not change what it returns, so it must not make
222 # the file be thrown away
223 expect_silent(
224 corpusStats(kco, vc = "pubDate since 2020", as.df = TRUE, verbose = TRUE, cacheAs = file)
225 )
226})