Skip to content

Commit 2c78499

Browse files
committed
test: cover subprocess fallback branches
1 parent 7f2a2f9 commit 2c78499

5 files changed

Lines changed: 221 additions & 3 deletions

File tree

R/internal_utilities.R

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,15 @@ java_subprocess_env <- function(java_home, rjava = FALSE) {
8686
checkmate::assert_logical(rjava, len = 1)
8787

8888
env_vars <- Sys.getenv()
89+
env_get <- function(name) {
90+
if (name %in% names(env_vars)) {
91+
env_vars[[name]]
92+
} else {
93+
NA_character_
94+
}
95+
}
8996
java_bin <- file.path(java_home, "bin")
90-
old_path <- env_vars[["PATH"]]
97+
old_path <- env_get("PATH")
9198

9299
env_vars["JAVA_HOME"] <- java_home
93100
env_vars["PATH"] <- paste(java_bin, old_path, sep = .Platform$path.sep)
@@ -105,7 +112,7 @@ java_subprocess_env <- function(java_home, rjava = FALSE) {
105112
jvm_lib_dir <- dirname(libjvm_path)
106113

107114
if (identical(sysname, "Linux")) {
108-
old_ld <- env_vars[["LD_LIBRARY_PATH"]]
115+
old_ld <- env_get("LD_LIBRARY_PATH")
109116
if (is.na(old_ld)) {
110117
old_ld <- ""
111118
}
@@ -116,7 +123,7 @@ java_subprocess_env <- function(java_home, rjava = FALSE) {
116123
jvm_lib_dir
117124
}
118125
} else if (identical(sysname, "Darwin")) {
119-
old_dyld <- env_vars[["DYLD_LIBRARY_PATH"]]
126+
old_dyld <- env_get("DYLD_LIBRARY_PATH")
120127
if (is.na(old_dyld)) {
121128
old_dyld <- ""
122129
}

tests/testthat/test-internal_utilities_rjava.R

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,11 @@ test_that("java_version_check_rscript handles errors gracefully", {
107107

108108
expect_true(grepl("Error", result))
109109
})
110+
111+
test_that("parse_java_major_version handles valid and invalid inputs", {
112+
expect_equal(rJavaEnv:::parse_java_major_version("21.0.8"), "21")
113+
expect_equal(rJavaEnv:::parse_java_major_version("1.8.0_452"), "8")
114+
expect_null(rJavaEnv:::parse_java_major_version(NULL))
115+
expect_null(rJavaEnv:::parse_java_major_version(""))
116+
expect_null(rJavaEnv:::parse_java_major_version("not-a-version"))
117+
})

tests/testthat/test-java_env_subprocess_regression.R

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,86 @@ test_that("._java_version_check_rjava_impl_original prefers callr", {
3535
expect_equal(state$captured_libpath, .libPaths())
3636
})
3737

38+
test_that("._java_version_check_rjava_impl_original returns FALSE without java_home", {
39+
expect_false(rJavaEnv:::._java_version_check_rjava_impl_original(NULL))
40+
expect_false(rJavaEnv:::._java_version_check_rjava_impl_original(""))
41+
})
42+
43+
test_that("._java_version_check_rjava_impl_original falls back when callr errors", {
44+
skip_if_not_installed("callr")
45+
state <- new.env(parent = emptyenv())
46+
state$captured_env <- NULL
47+
48+
local_mocked_bindings(
49+
r = function(...) stop("callr failed"),
50+
.package = "callr"
51+
)
52+
53+
local_mocked_bindings(
54+
java_subprocess_env = function(java_home, rjava = FALSE) {
55+
state$captured_env <- c(
56+
JAVA_HOME = java_home,
57+
PATH = paste0(java_home, "/bin")
58+
)
59+
state$captured_env
60+
},
61+
.package = "rJavaEnv"
62+
)
63+
64+
local_mocked_bindings(
65+
system2 = function(command, args, stdout, stderr, timeout, env) {
66+
state$captured_env <- env
67+
c(
68+
"rJava and other rJava/Java-based packages will use Java version: \"17.0.9\""
69+
)
70+
},
71+
.package = "base"
72+
)
73+
74+
result <- rJavaEnv:::._java_version_check_rjava_impl_original(
75+
java_home = "/mock/java"
76+
)
77+
78+
expect_equal(result$major_version, "17")
79+
expect_equal(state$captured_env[["JAVA_HOME"]], "/mock/java")
80+
})
81+
82+
test_that("._java_version_check_rjava_impl_original falls back when callr output is unusable", {
83+
skip_if_not_installed("callr")
84+
85+
local_mocked_bindings(
86+
r = function(...) {
87+
list(
88+
java_version = "not-a-version",
89+
output = "rJava and other rJava/Java-based packages will use Java version: \"not-a-version\""
90+
)
91+
},
92+
.package = "callr"
93+
)
94+
95+
local_mocked_bindings(
96+
java_subprocess_env = function(java_home, rjava = FALSE) {
97+
c(JAVA_HOME = java_home, PATH = paste0(java_home, "/bin"))
98+
},
99+
.package = "rJavaEnv"
100+
)
101+
102+
local_mocked_bindings(
103+
system2 = function(...) {
104+
c(
105+
"rJava and other rJava/Java-based packages will use Java version: \"25.0.2\""
106+
)
107+
},
108+
.package = "base"
109+
)
110+
111+
result <- rJavaEnv:::._java_version_check_rjava_impl_original(
112+
java_home = "/mock/java"
113+
)
114+
115+
expect_equal(result$major_version, "25")
116+
})
117+
38118
test_that("._java_version_check_rjava_impl_original falls back to Rscript", {
39119
mock_paths <- c(
40120
"/usr/lib/R/library",
@@ -92,3 +172,49 @@ test_that("._java_version_check_rjava_impl_original falls back to Rscript", {
92172
expect_true(grepl("/home/user/R/x86_64-pc-linux-gnu-library/4.5", script_text))
93173
expect_false(any(grepl("get_libjvm_path <- function", state$captured_script)))
94174
})
175+
176+
test_that("._java_version_check_rjava_impl_original returns FALSE on bad subprocess output", {
177+
local_mocked_bindings(
178+
requireNamespace = function(pkg, quietly = TRUE) FALSE,
179+
.package = "base"
180+
)
181+
182+
local_mocked_bindings(
183+
java_subprocess_env = function(java_home, rjava = FALSE) {
184+
c(JAVA_HOME = java_home, PATH = paste0(java_home, "/bin"))
185+
},
186+
.package = "rJavaEnv"
187+
)
188+
189+
local_mocked_bindings(
190+
system2 = function(...) character(0),
191+
.package = "base"
192+
)
193+
194+
expect_false(
195+
rJavaEnv:::._java_version_check_rjava_impl_original(java_home = "/mock/java")
196+
)
197+
})
198+
199+
test_that("._java_version_check_rjava_impl_original returns FALSE on subprocess error text", {
200+
local_mocked_bindings(
201+
requireNamespace = function(pkg, quietly = TRUE) FALSE,
202+
.package = "base"
203+
)
204+
205+
local_mocked_bindings(
206+
java_subprocess_env = function(java_home, rjava = FALSE) {
207+
c(JAVA_HOME = java_home, PATH = paste0(java_home, "/bin"))
208+
},
209+
.package = "rJavaEnv"
210+
)
211+
212+
local_mocked_bindings(
213+
system2 = function(...) "Error checking Java version: JVM init failed",
214+
.package = "base"
215+
)
216+
217+
expect_false(
218+
rJavaEnv:::._java_version_check_rjava_impl_original(java_home = "/mock/java")
219+
)
220+
})

tests/testthat/test-java_scoped.R

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,46 @@ test_that("java_subprocess_env configures Linux rJava loader variables", {
101101
})
102102
})
103103

104+
test_that("java_subprocess_env only updates JAVA_HOME and PATH when rjava is FALSE", {
105+
withr::with_envvar(c(
106+
PATH = "/usr/bin",
107+
LD_LIBRARY_PATH = "sentinel",
108+
JAVA_LD_LIBRARY_PATH = "sentinel-java-ld"
109+
), {
110+
env_vars <- rJavaEnv:::java_subprocess_env("/mock/java/home", rjava = FALSE)
111+
112+
expect_equal(env_vars[["JAVA_HOME"]], "/mock/java/home")
113+
expect_true(grepl("/mock/java/home/bin", env_vars[["PATH"]]))
114+
expect_equal(env_vars[["LD_LIBRARY_PATH"]], "sentinel")
115+
expect_equal(env_vars[["JAVA_LD_LIBRARY_PATH"]], "sentinel-java-ld")
116+
})
117+
})
118+
119+
test_that("java_subprocess_env returns base env when libjvm cannot be resolved", {
120+
local_mocked_bindings(
121+
Sys.info = function() c(sysname = "Linux"),
122+
.package = "base"
123+
)
124+
125+
local_mocked_bindings(
126+
get_libjvm_path = function(...) NULL,
127+
.package = "rJavaEnv"
128+
)
129+
130+
withr::with_envvar(c(
131+
PATH = "/usr/bin",
132+
LD_LIBRARY_PATH = NA,
133+
JAVA_LD_LIBRARY_PATH = "sentinel-java-ld"
134+
), {
135+
env_vars <- rJavaEnv:::java_subprocess_env("/mock/java/home", rjava = TRUE)
136+
137+
expect_equal(env_vars[["JAVA_HOME"]], "/mock/java/home")
138+
expect_true(grepl("/mock/java/home/bin", env_vars[["PATH"]]))
139+
expect_equal(env_vars[["JAVA_LD_LIBRARY_PATH"]], "sentinel-java-ld")
140+
expect_false("LD_LIBRARY_PATH" %in% names(env_vars))
141+
})
142+
})
143+
104144
test_that("java_subprocess_env configures macOS DYLD_LIBRARY_PATH for rJava", {
105145
local_mocked_bindings(
106146
Sys.info = function() c(sysname = "Darwin"),
@@ -121,6 +161,27 @@ test_that("java_subprocess_env configures macOS DYLD_LIBRARY_PATH for rJava", {
121161
})
122162
})
123163

164+
test_that("java_subprocess_env handles missing loader path variables", {
165+
local_mocked_bindings(
166+
Sys.info = function() c(sysname = "Darwin"),
167+
.package = "base"
168+
)
169+
170+
local_mocked_bindings(
171+
get_libjvm_path = function(...) "/mock/java/home/lib/server/libjvm.dylib",
172+
.package = "rJavaEnv"
173+
)
174+
175+
withr::with_envvar(c(PATH = "/usr/bin", DYLD_LIBRARY_PATH = NA), {
176+
env_vars <- rJavaEnv:::java_subprocess_env("/mock/java/home", rjava = TRUE)
177+
178+
expect_equal(
179+
env_vars[["DYLD_LIBRARY_PATH"]],
180+
"/mock/java/home/lib/server"
181+
)
182+
})
183+
})
184+
124185
test_that("java_subprocess_env leaves Windows at JAVA_HOME and PATH only", {
125186
local_mocked_bindings(
126187
Sys.info = function() c(sysname = "Windows"),

tests/testthat/test-java_valid_versions_extra.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,22 @@ test_that("java_valid_major_versions_temurin uses shipped fallback when probes f
314314
expect_equal(versions, fallback)
315315
})
316316

317+
test_that("java_valid_major_versions_temurin returns empty when probes succeed without assets", {
318+
local_mocked_bindings(
319+
read_json_url = function(url, max_simplify_lvl = "data_frame") {
320+
if (grepl("info/available_releases", url)) {
321+
return(list(available_releases = c(17, 21)))
322+
}
323+
list()
324+
},
325+
.package = "rJavaEnv"
326+
)
327+
328+
versions <- java_valid_major_versions_temurin(platform = "linux", arch = "x64")
329+
330+
expect_identical(versions, character(0))
331+
})
332+
317333
# Test java_valid_major_versions_corretto with explicit platform/arch
318334
test_that("java_valid_major_versions_corretto works with explicit parameters", {
319335
skip_on_cran()

0 commit comments

Comments
 (0)