}}\preformatted{VERSION="19.1.5"
# Download the appropriate version
curl -O https://mac.r-project.org/openmp/openmp-$\{VERSION\}-darwin20-Release.tar.gz
diff --git a/man/recipes_binary_install.Rd b/man/recipes_binary_install.Rd
index 4cd1545..10345f8 100644
--- a/man/recipes_binary_install.Rd
+++ b/man/recipes_binary_install.Rd
@@ -56,8 +56,14 @@ repository and the install path are either:\tabular{lll}{
Name \tab Installation Location \tab Target \cr
\href{https://mac.r-project.org/bin/darwin17/x86_64}{darwin17/x86_64} \tab /usr/local \tab macOS 10.13, Intel (x86_64) \cr
\href{https://mac.r-project.org/bin/darwin20/x86_64}{darwin20/x86_64} \tab /opt/R/x86_64 \tab macOS 11, Intel (x86_64) \cr
- \href{https://mac.r-project.org/bin/darwin20/arm64}{darwin20/arm64} \tab /opt/R/arm64 \tab macOS 11, Apple M1 (arm64) \cr
+ \href{https://mac.r-project.org/bin/darwin20/arm64}{darwin20/arm64} \tab /opt/R/arm64 \tab macOS 11, Apple Silicon (arm64) \cr
+ \href{https://mac.r-project.org/bin/darwin23/arm64}{darwin23/arm64} \tab /opt/R/arm64 \tab macOS 14 (Sonoma), Apple Silicon (arm64), used by R 4.6 \cr
}
+
+The correct repository is detected automatically: the highest \code{darwin}
+version less than or equal to your macOS is selected for your architecture.
+R 4.6 on Apple Silicon (macOS 14+) therefore resolves to \code{darwin23/arm64},
+which installs to the same \verb{/opt/R/arm64} prefix as \code{darwin20/arm64}.
}
\section{Differences}{
diff --git a/tests/testthat/test-assertions.R b/tests/testthat/test-assertions.R
index 40abc77..3616bf9 100644
--- a/tests/testthat/test-assertions.R
+++ b/tests/testthat/test-assertions.R
@@ -59,15 +59,14 @@ test_that("assert_x86_64 throws error on non-Intel", {
})
test_that("assert_r_version_supported succeeds on supported R version", {
- # Instead of mocking R.version, mock is_r_version to return the expected values
- mockery::stub(assert_r_version_supported, "is_r_version",
- function(version) version %in% c("4.0", "4.1", "4.2", "4.3", "4.4"))
+ # Mock the supported-window check to report a supported version
+ mockery::stub(assert_r_version_supported, "is_r_version_supported", function(...) TRUE)
expect_no_error(assert_r_version_supported())
})
test_that("assert_r_version_supported throws error on unsupported R version", {
- # Mock is_r_version to return FALSE for any input
- mockery::stub(assert_r_version_supported, "is_r_version", function(...) FALSE)
+ # Report an unsupported version
+ mockery::stub(assert_r_version_supported, "is_r_version_supported", function(...) FALSE)
# Instead of trying to mock R.version, mock paste to return a known version
mockery::stub(assert_r_version_supported, "base::paste", function(...) "3.6.0")
# Mock cli::cli_abort to track error message but not actually throw
diff --git a/tests/testthat/test-gfortran.R b/tests/testthat/test-gfortran.R
index 24e7a1d..2767fe9 100644
--- a/tests/testthat/test-gfortran.R
+++ b/tests/testthat/test-gfortran.R
@@ -51,7 +51,8 @@ test_that("gfortran_install installs correct version for R 4.3+", {
mockery::stub(gfortran_install, "assert_macos_supported", function() NULL)
mockery::stub(gfortran_install, "assert_r_version_supported", function() NULL)
mockery::stub(gfortran_install, "is_gfortran_installed", function() FALSE)
- mockery::stub(gfortran_install, "is_r_version", function(v) v == "4.3")
+ mockery::stub(gfortran_install, "is_r_version_at_least",
+ function(target, ...) utils::compareVersion("4.3", target) >= 0)
mockery::stub(gfortran_install, "gfortran_install_location", function() "/opt")
mockery::stub(gfortran_install, "base::file.path", function(...) "/opt/gfortran/bin")
mockery::stub(gfortran_install, "base::paste0", function(...) "$PATH:/opt/gfortran/bin")
@@ -68,12 +69,41 @@ test_that("gfortran_install installs correct version for R 4.3+", {
expect_true(result)
})
+test_that("gfortran_install uses the 14.2 universal installer for R 4.6", {
+ # Mock dependencies
+ mockery::stub(gfortran_install, "assert_mac", function() NULL)
+ mockery::stub(gfortran_install, "assert_macos_supported", function() NULL)
+ mockery::stub(gfortran_install, "assert_r_version_supported", function() NULL)
+ mockery::stub(gfortran_install, "is_gfortran_installed", function() FALSE)
+ mockery::stub(gfortran_install, "is_r_version_at_least",
+ function(target, ...) utils::compareVersion("4.6", target) >= 0)
+ mockery::stub(gfortran_install, "gfortran_install_location", function() "/opt")
+ mockery::stub(gfortran_install, "base::file.path", function(...) "/opt/gfortran/bin")
+ mockery::stub(gfortran_install, "base::paste0", function(...) "$PATH:/opt/gfortran/bin")
+ mockery::stub(gfortran_install, "force_password", function(pw) "mockpw")
+ mockery::stub(gfortran_install, "create_install_location", function(...) TRUE)
+ # The 14.2 universal installer must be chosen for R 4.6; fail loudly otherwise.
+ mockery::stub(gfortran_install, "install_gfortran_14_2_universal", function(...) TRUE)
+ mockery::stub(gfortran_install, "install_gfortran_12_2_universal",
+ function(...) stop("wrong installer: 12.2 used for R 4.6"))
+ mockery::stub(gfortran_install, "renviron_gfortran_path", function(...) NULL)
+ mockery::stub(gfortran_install, "cli::cli_alert_info", function(...) NULL)
+ mockery::stub(gfortran_install, "cli::cli_bullets", function(...) NULL)
+ mockery::stub(gfortran_install, "cli::cli_text", function(...) NULL)
+ mockery::stub(gfortran_install, "cli::cli_alert_success", function(...) NULL)
+
+ result <- gfortran_install(verbose = TRUE)
+ expect_true(result)
+})
+
test_that("gfortran_install handles Intel Mac with R 4.2", {
# Mock dependencies
mockery::stub(gfortran_install, "assert_mac", function() NULL)
mockery::stub(gfortran_install, "assert_macos_supported", function() NULL)
mockery::stub(gfortran_install, "assert_r_version_supported", function() NULL)
mockery::stub(gfortran_install, "is_gfortran_installed", function() FALSE)
+ mockery::stub(gfortran_install, "is_r_version_at_least",
+ function(target, ...) utils::compareVersion("4.2", target) >= 0)
mockery::stub(gfortran_install, "is_r_version", function(v) v == "4.2")
mockery::stub(gfortran_install, "is_x86_64", function() TRUE)
mockery::stub(gfortran_install, "is_aarch64", function() FALSE)
diff --git a/tests/testthat/test-installers.R b/tests/testthat/test-installers.R
index 3065107..3a4e018 100644
--- a/tests/testthat/test-installers.R
+++ b/tests/testthat/test-installers.R
@@ -97,3 +97,55 @@ test_that("pkg_install handles successful installation", {
result <- pkg_install("/tmp/test.pkg", verbose = TRUE)
expect_true(result)
})
+
+test_that("recipe_binary_install_strip_level follows the toolchain tiers", {
+ # Modern tier (R >= 4.3): strip 3 for every architecture
+ mockery::stub(recipe_binary_install_strip_level, "is_r_version_supported", function(...) TRUE)
+ mockery::stub(recipe_binary_install_strip_level, "is_r_version_at_least", function(...) TRUE)
+ expect_equal(recipe_binary_install_strip_level("arm64"), 3)
+ expect_equal(recipe_binary_install_strip_level("aarch64"), 3)
+ expect_equal(recipe_binary_install_strip_level("x86_64"), 3)
+
+ # Legacy tier (4.0 <= R < 4.3): delegates to install_strip_level()
+ mockery::stub(recipe_binary_install_strip_level, "is_r_version_at_least", function(...) FALSE)
+ mockery::stub(recipe_binary_install_strip_level, "install_strip_level", function(...) 99)
+ expect_equal(recipe_binary_install_strip_level("arm64"), 99)
+
+ # Unsupported R version: abort
+ mockery::stub(recipe_binary_install_strip_level, "is_r_version_supported", function(...) FALSE)
+ expect_error(recipe_binary_install_strip_level("arm64"), regexp = "Unsupported R version")
+})
+
+test_that("recipe_binary_install_location follows the toolchain tiers", {
+ # Modern tier (R >= 4.3): /opt/R/
+ mockery::stub(recipe_binary_install_location, "is_r_version_supported", function(...) TRUE)
+ mockery::stub(recipe_binary_install_location, "is_r_version_at_least", function(...) TRUE)
+ expect_equal(recipe_binary_install_location("arm64"), "/opt/R/arm64")
+ expect_equal(recipe_binary_install_location("aarch64"), "/opt/R/arm64")
+ expect_equal(recipe_binary_install_location("x86_64"), "/opt/R/x86_64")
+
+ # Legacy tier (4.0 <= R < 4.3): delegates to install_location()
+ mockery::stub(recipe_binary_install_location, "is_r_version_at_least", function(...) FALSE)
+ mockery::stub(recipe_binary_install_location, "install_location", function(...) "/legacy/loc")
+ expect_equal(recipe_binary_install_location("x86_64"), "/legacy/loc")
+
+ # Unsupported R version: abort
+ mockery::stub(recipe_binary_install_location, "is_r_version_supported", function(...) FALSE)
+ expect_error(recipe_binary_install_location("arm64"), regexp = "Unsupported R version")
+})
+
+test_that("gfortran_install_location follows the toolchain tiers", {
+ # Modern tier (R >= 4.3): /opt
+ mockery::stub(gfortran_install_location, "is_r_version_supported", function(...) TRUE)
+ mockery::stub(gfortran_install_location, "is_r_version_at_least", function(...) TRUE)
+ expect_equal(gfortran_install_location("arm64"), "/opt")
+
+ # Legacy tier (4.0 <= R < 4.3): delegates to install_location()
+ mockery::stub(gfortran_install_location, "is_r_version_at_least", function(...) FALSE)
+ mockery::stub(gfortran_install_location, "install_location", function(...) "/legacy/loc")
+ expect_equal(gfortran_install_location("x86_64"), "/legacy/loc")
+
+ # Unsupported R version: abort
+ mockery::stub(gfortran_install_location, "is_r_version_supported", function(...) FALSE)
+ expect_error(gfortran_install_location("arm64"), regexp = "Unsupported R version")
+})
diff --git a/tests/testthat/test-system.R b/tests/testthat/test-system.R
index 5a2baa0..5776548 100644
--- a/tests/testthat/test-system.R
+++ b/tests/testthat/test-system.R
@@ -79,3 +79,30 @@ test_that("is_r_version correctly identifies R versions", {
expect_true(simplified_is_r_version_full("4.2.1", compare_major_minor = FALSE))
expect_false(simplified_is_r_version_full("4.2.0", compare_major_minor = FALSE))
})
+
+test_that("is_r_version_at_least compares major.minor versions", {
+ expect_true(is_r_version_at_least("4.3", version = "4.6"))
+ expect_true(is_r_version_at_least("4.3", version = "4.3"))
+ expect_false(is_r_version_at_least("4.5", version = "4.3"))
+ expect_true(is_r_version_at_least("4.0", version = "4.6"))
+ expect_false(is_r_version_at_least("4.0", version = "3.6"))
+ # The running R (>= 4.0) is always at least 4.0
+ expect_true(is_r_version_at_least("4.0"))
+})
+
+test_that("is_r_version_supported honors the supported window", {
+ for (v in c("4.0", "4.1", "4.2", "4.3", "4.4", "4.5", "4.6")) {
+ expect_true(is_r_version_supported(version = v), info = v)
+ }
+ for (v in c("3.6", "4.7", "5.0")) {
+ expect_false(is_r_version_supported(version = v), info = v)
+ }
+})
+
+test_that("supported R version window is the single source of truth", {
+ expect_equal(minimum_supported_r_version(), "4.0")
+ expect_equal(maximum_supported_r_version(), "4.6")
+ # The window endpoints must themselves be supported
+ expect_true(is_r_version_supported(version = minimum_supported_r_version()))
+ expect_true(is_r_version_supported(version = maximum_supported_r_version()))
+})