blob: 06e8ca186f1c305ea18f6dbfafa01edfb2f3b9b5 [file] [log] [blame]
Marc Kupietz37f96072026-09-03 07:18:11 +02001offlineConnection <- function() {
2 methods::new(
3 "KorAPConnection",
4 apiUrl = "https://example.invalid/",
5 KorAPUrl = "https://example.invalid/",
6 # keeps the unrelated "authorize your application" warning out of the way
7 authorizationSupported = FALSE,
8 verbose = FALSE
9 )
10}
11
12# Returning no candidates lets collocationAnalysis() finish without contacting
13# the server, so that the caching around it can be tested offline.
14mockEmptyAnalysis <- function() {
15 testthat::local_mocked_bindings(
16 collocatesQuery = function(...) tibble::tibble(),
17 .package = "RKorAPClient",
18 .env = parent.frame()
19 )
20}
21
22test_that("cache files record the parameters of the analysis", {
23 mockEmptyAnalysis()
24 cacheFile <- tempfile(fileext = ".rds")
25 on.exit(unlink(cacheFile), add = TRUE)
26
27 collocationAnalysis(offlineConnection(), "Test", minOccur = 3, cacheAs = cacheFile)
28
29 stored <- attr(readRDS(cacheFile), RKorAPClient:::collocationCacheAttribute)
30 expect_false(is.null(stored))
31 expect_equal(stored$parameters$node, "Test")
32 expect_equal(stored$parameters$minOccur, 3)
33 expect_equal(stored$apiUrl, "https://example.invalid/")
34 # every parameter of the analysis is recorded, not just those visible in the
35 # result, so that added parameters are covered automatically
36 expect_true(all(c(
37 "topCollocatesLimit", "searchHitsSampleLimit", "exactFrequencies",
38 "stopwords", "threshold", "collocateFilterRegex", "seed"
39 ) %in% names(stored$parameters)))
40 # kco and cacheAs are not parameters of the analysis
41 expect_false(any(c("kco", "cacheAs") %in% names(stored$parameters)))
42})
43
44test_that("the returned result is the same whether it was cached or not", {
45 mockEmptyAnalysis()
46 cacheFile <- tempfile(fileext = ".rds")
47 on.exit(unlink(cacheFile), add = TRUE)
48 kco <- offlineConnection()
49
50 fresh <- collocationAnalysis(kco, "Test", cacheAs = cacheFile)
51 fromCache <- collocationAnalysis(kco, "Test", cacheAs = cacheFile)
52
53 expect_equal(fromCache, fresh)
54 # the parameters live in the file only, not in the returned value
55 expect_null(attr(fromCache, RKorAPClient:::collocationCacheAttribute))
56})
57
58test_that("an unchanged call is served from the cache without contacting the server", {
59 cacheFile <- tempfile(fileext = ".rds")
60 on.exit(unlink(cacheFile), add = TRUE)
61 kco <- offlineConnection()
62
63 local({
64 mockEmptyAnalysis()
65 collocationAnalysis(kco, "Test", minOccur = 3, cacheAs = cacheFile)
66 })
67
68 testthat::local_mocked_bindings(
69 collocatesQuery = function(...) stop("server must not be contacted"),
70 .package = "RKorAPClient"
71 )
72 expect_no_warning(collocationAnalysis(kco, "Test", minOccur = 3, cacheAs = cacheFile))
73})
74
75test_that("changed parameters make the analysis be recomputed, with a warning", {
76 cacheFile <- tempfile(fileext = ".rds")
77 on.exit(unlink(cacheFile), add = TRUE)
78 kco <- offlineConnection()
79
80 local({
81 mockEmptyAnalysis()
82 collocationAnalysis(kco, "Test", minOccur = 3, cacheAs = cacheFile)
83 })
84
85 testthat::local_mocked_bindings(
86 collocatesQuery = function(...) stop("recomputed"),
87 .package = "RKorAPClient"
88 )
89
90 # the warning names the parameter that differs, and the analysis is rerun
91 expect_warning(
92 expect_error(
93 collocationAnalysis(kco, "Test", minOccur = 5, cacheAs = cacheFile),
94 "recomputed"
95 ),
96 "minOccur"
97 )
98
99 # a changed node is caught as well
100 expect_warning(
101 expect_error(
102 collocationAnalysis(kco, "Other", minOccur = 3, cacheAs = cacheFile),
103 "recomputed"
104 ),
105 "node"
106 )
107})
108
109test_that("a recomputed analysis overwrites the stale cache file", {
110 cacheFile <- tempfile(fileext = ".rds")
111 on.exit(unlink(cacheFile), add = TRUE)
112 kco <- offlineConnection()
113
114 local({
115 mockEmptyAnalysis()
116 collocationAnalysis(kco, "Test", minOccur = 3, cacheAs = cacheFile)
117 })
118
119 local({
120 mockEmptyAnalysis()
121 expect_warning(
122 collocationAnalysis(kco, "Test", minOccur = 5, cacheAs = cacheFile),
123 "minOccur"
124 )
125 })
126
127 stored <- attr(readRDS(cacheFile), RKorAPClient:::collocationCacheAttribute)
128 expect_equal(stored$parameters$minOccur, 5)
129})
130
131test_that("cache files written without parameters are still used", {
132 cacheFile <- tempfile(fileext = ".rds")
133 on.exit(unlink(cacheFile), add = TRUE)
134 kco <- offlineConnection()
135
136 # as written by RKorAPClient 1.3.0
137 legacy <- tibble::tibble(node = "Test", collocate = "c", logDice = 7)
138 saveRDS(legacy, cacheFile)
139
140 testthat::local_mocked_bindings(
141 collocatesQuery = function(...) stop("server must not be contacted"),
142 .package = "RKorAPClient"
143 )
144 expect_equal(collocationAnalysis(kco, "Test", cacheAs = cacheFile), legacy)
145})
146
147test_that("differingCollocationCacheParameters reports what changed", {
148 differing <- RKorAPClient:::differingCollocationCacheParameters
149
150 stored <- list(
151 parameters = list(node = "Test", minOccur = 3, vc = ""),
152 dots = list(),
153 apiUrl = "https://korap.ids-mannheim.de/api/v1.0/"
154 )
155
156 expect_equal(differing(stored, stored), character(0))
157
158 changed <- stored
159 changed$parameters$minOccur <- 5
160 expect_equal(differing(stored, changed), "minOccur")
161
162 changed <- stored
163 changed$parameters$minOccur <- 5
164 changed$parameters$vc <- "textType=/Zeit.*/"
165 expect_setequal(differing(stored, changed), c("minOccur", "vc"))
166
167 changed <- stored
168 changed$dots <- list(smoothingConstant = 1)
169 expect_equal(differing(stored, changed), "...")
170
171 changed <- stored
172 changed$apiUrl <- "https://korap.dnb.de/api/v1.0/"
173 expect_equal(differing(stored, changed), "KorAP instance")
174})