Refuse cacheAs files written before the scores were corrected
A cacheAs file holds a finished analysis, association scores included,
and 1.4.0 computes those differently. A file written by 1.3.0 would
therefore be handed back with numbers that would not be arrived at again,
and the comparison of parameters added during this cycle cannot notice
it: the parameters did not change, the formula did. The version that
wrote a file is now recorded in it, and one from before 1.4.0 is
recomputed and overwritten, with a warning saying why.
The machinery moves to a file of its own on the way, since it is no
longer about collocation analysis alone, and verbose drops out of what a
file records: how loud a query is does not change what it returns.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I8af9eac21ae53fe5d583578c3689b37d140a4af4
diff --git a/tests/testthat/test-collocation-cache-parameters.R b/tests/testthat/test-collocation-cache-parameters.R
index 06e8ca1..a207a8f 100644
--- a/tests/testthat/test-collocation-cache-parameters.R
+++ b/tests/testthat/test-collocation-cache-parameters.R
@@ -26,8 +26,10 @@
collocationAnalysis(offlineConnection(), "Test", minOccur = 3, cacheAs = cacheFile)
- stored <- attr(readRDS(cacheFile), RKorAPClient:::collocationCacheAttribute)
+ stored <- attr(readRDS(cacheFile), RKorAPClient:::cacheAsAttribute)
expect_false(is.null(stored))
+ expect_equal(stored$scoreVersion, RKorAPClient:::cacheAsScoreVersion)
+ expect_equal(stored$packageVersion, as.character(utils::packageVersion("RKorAPClient")))
expect_equal(stored$parameters$node, "Test")
expect_equal(stored$parameters$minOccur, 3)
expect_equal(stored$apiUrl, "https://example.invalid/")
@@ -52,7 +54,7 @@
expect_equal(fromCache, fresh)
# the parameters live in the file only, not in the returned value
- expect_null(attr(fromCache, RKorAPClient:::collocationCacheAttribute))
+ expect_null(attr(fromCache, RKorAPClient:::cacheAsAttribute))
})
test_that("an unchanged call is served from the cache without contacting the server", {
@@ -124,51 +126,83 @@
)
})
- stored <- attr(readRDS(cacheFile), RKorAPClient:::collocationCacheAttribute)
+ stored <- attr(readRDS(cacheFile), RKorAPClient:::cacheAsAttribute)
expect_equal(stored$parameters$minOccur, 5)
})
-test_that("cache files written without parameters are still used", {
+test_that("cache files written before the scores were corrected are refused", {
+ mockEmptyAnalysis()
cacheFile <- tempfile(fileext = ".rds")
on.exit(unlink(cacheFile), add = TRUE)
kco <- offlineConnection()
- # as written by RKorAPClient 1.3.0
+ # as written by RKorAPClient 1.3.0, whose logDice and ll differ from today's
legacy <- tibble::tibble(node = "Test", collocate = "c", logDice = 7)
saveRDS(legacy, cacheFile)
- testthat::local_mocked_bindings(
- collocatesQuery = function(...) stop("server must not be contacted"),
- .package = "RKorAPClient"
+ expect_warning(
+ result <- collocationAnalysis(kco, "Test", cacheAs = cacheFile),
+ "logDice"
)
- expect_equal(collocationAnalysis(kco, "Test", cacheAs = cacheFile), legacy)
+ expect_false(identical(result, legacy))
+ # and the stale file is replaced by one that records what wrote it
+ expect_false(is.null(attr(readRDS(cacheFile), RKorAPClient:::cacheAsAttribute)))
})
-test_that("differingCollocationCacheParameters reports what changed", {
- differing <- RKorAPClient:::differingCollocationCacheParameters
+test_that("cache files of an older version are refused, naming it", {
+ mockEmptyAnalysis()
+ cacheFile <- tempfile(fileext = ".rds")
+ on.exit(unlink(cacheFile), add = TRUE)
+ kco <- offlineConnection()
+
+ collocationAnalysis(kco, "Test", cacheAs = cacheFile)
+ aged <- readRDS(cacheFile)
+ record <- attr(aged, RKorAPClient:::cacheAsAttribute)
+ record$scoreVersion <- "1.3.0"
+ record$packageVersion <- "1.3.0"
+ attr(aged, RKorAPClient:::cacheAsAttribute) <- record
+ saveRDS(aged, cacheFile)
+
+ expect_warning(collocationAnalysis(kco, "Test", cacheAs = cacheFile), "1\\.3\\.0")
+})
+
+test_that("cacheAsRejectionReason says why a cache file cannot be used", {
+ reason <- RKorAPClient:::cacheAsRejectionReason
stored <- list(
+ scoreVersion = RKorAPClient:::cacheAsScoreVersion,
parameters = list(node = "Test", minOccur = 3, vc = ""),
dots = list(),
apiUrl = "https://korap.ids-mannheim.de/api/v1.0/"
)
- expect_equal(differing(stored, stored), character(0))
+ expect_null(reason(stored, stored))
+ expect_match(reason(NULL, stored), "before RKorAPClient")
+
+ # a file from before the corrections: an older score generation, and the
+ # version that wrote it, which the reason names
+ aged <- stored
+ aged$scoreVersion <- "1.3.0"
+ aged$packageVersion <- "1.3.0"
+ expect_match(reason(aged, stored), "written by RKorAPClient 1\\.3\\.0")
+
+ # one that does not even say what wrote it
+ anonymous <- stored
+ anonymous$scoreVersion <- NULL
+ expect_match(reason(anonymous, stored), "written before RKorAPClient")
changed <- stored
changed$parameters$minOccur <- 5
- expect_equal(differing(stored, changed), "minOccur")
+ expect_match(reason(stored, changed), "minOccur")
- changed <- stored
- changed$parameters$minOccur <- 5
changed$parameters$vc <- "textType=/Zeit.*/"
- expect_setequal(differing(stored, changed), c("minOccur", "vc"))
+ expect_match(reason(stored, changed), "minOccur, vc")
changed <- stored
changed$dots <- list(smoothingConstant = 1)
- expect_equal(differing(stored, changed), "...")
+ expect_match(reason(stored, changed), "\\.\\.\\.")
changed <- stored
changed$apiUrl <- "https://korap.dnb.de/api/v1.0/"
- expect_equal(differing(stored, changed), "KorAP instance")
+ expect_match(reason(stored, changed), "KorAP instance")
})