From 1de359f3e6b095bcf7d577933bb2823b30da2f58 Mon Sep 17 00:00:00 2001 From: Greg Lin Date: Wed, 10 Aug 2022 17:17:01 -0500 Subject: [PATCH 1/5] Add tests for R builds --- test/docker-compose.yml | 75 ++++++++++++++++++++ test/test-centos.sh | 25 +++++++ test/test-deb.sh | 25 +++++++ test/test-opensuse.sh | 23 +++++++ test/test-r.sh | 18 +++++ test/test-rhel.sh | 26 +++++++ test/test.R | 103 ++++++++++++++++++++++++++++ test/testpkg/.Rbuildignore | 2 + test/testpkg/.gitignore | 2 + test/testpkg/DESCRIPTION | 12 ++++ test/testpkg/NAMESPACE | 6 ++ test/testpkg/R/testpkg.R | 32 +++++++++ test/testpkg/README.md | 3 + test/testpkg/man/add_it.Rd | 19 +++++ test/testpkg/man/square_it.Rd | 17 +++++ test/testpkg/man/subtract_it.Rd | 19 +++++ test/testpkg/man/testpkg-package.Rd | 14 ++++ test/testpkg/src/Makevars | 2 + test/testpkg/src/add.c | 10 +++ test/testpkg/src/init.c | 33 +++++++++ test/testpkg/src/square.f | 5 ++ test/testpkg/src/subtract.cpp | 10 +++ test/testpkg/testpkg.Rproj | 19 +++++ test/testpkg/tests/test.R | 5 ++ 24 files changed, 505 insertions(+) create mode 100644 test/docker-compose.yml create mode 100755 test/test-centos.sh create mode 100755 test/test-deb.sh create mode 100755 test/test-opensuse.sh create mode 100755 test/test-r.sh create mode 100755 test/test-rhel.sh create mode 100644 test/test.R create mode 100644 test/testpkg/.Rbuildignore create mode 100644 test/testpkg/.gitignore create mode 100644 test/testpkg/DESCRIPTION create mode 100644 test/testpkg/NAMESPACE create mode 100644 test/testpkg/R/testpkg.R create mode 100644 test/testpkg/README.md create mode 100644 test/testpkg/man/add_it.Rd create mode 100644 test/testpkg/man/square_it.Rd create mode 100644 test/testpkg/man/subtract_it.Rd create mode 100644 test/testpkg/man/testpkg-package.Rd create mode 100644 test/testpkg/src/Makevars create mode 100644 test/testpkg/src/add.c create mode 100644 test/testpkg/src/init.c create mode 100644 test/testpkg/src/square.f create mode 100644 test/testpkg/src/subtract.cpp create mode 100644 test/testpkg/testpkg.Rproj create mode 100644 test/testpkg/tests/test.R diff --git a/test/docker-compose.yml b/test/docker-compose.yml new file mode 100644 index 0000000..91ea366 --- /dev/null +++ b/test/docker-compose.yml @@ -0,0 +1,75 @@ +version: '2.0' + +services: + ubuntu-1804: + image: ubuntu:bionic + command: /test/test-deb.sh + environment: + - OS_IDENTIFIER=ubuntu-1804 + - R_VERSION=${R_VERSION} + volumes: + - ./:/test + - ../builder/integration/tmp:/packages + ubuntu-2004: + image: ubuntu:focal + command: /test/test-deb.sh + environment: + - OS_IDENTIFIER=ubuntu-2004 + - R_VERSION=${R_VERSION} + volumes: + - ./:/test + - ../builder/integration/tmp:/packages + ubuntu-2204: + image: ubuntu:jammy + command: /test/test-deb.sh + environment: + - OS_IDENTIFIER=ubuntu-2204 + - R_VERSION=${R_VERSION} + volumes: + - ./:/test + - ../builder/integration/tmp:/packages + debian-11: + image: debian:bullseye + command: /test/test-deb.sh + environment: + - OS_IDENTIFIER=debian-11 + - R_VERSION=${R_VERSION} + volumes: + - ./:/test + - ../builder/integration/tmp:/packages + debian-10: + image: debian:buster + command: /test/test-deb.sh + environment: + - OS_IDENTIFIER=debian-10 + - R_VERSION=${R_VERSION} + volumes: + - ./:/test + - ../builder/integration/tmp:/packages + centos-7: + image: centos:centos7 + command: /test/test-centos.sh + environment: + - OS_IDENTIFIER=centos-7 + - R_VERSION=${R_VERSION} + volumes: + - ./:/test + - ../builder/integration/tmp:/packages + centos-8: + image: rockylinux:8 + command: /test/test-centos.sh + environment: + - OS_IDENTIFIER=centos-8 + - R_VERSION=${R_VERSION} + volumes: + - ./:/test + - ../builder/integration/tmp:/packages + opensuse-153: + image: opensuse/leap:15.3 + command: /test/test-opensuse.sh + environment: + - OS_IDENTIFIER=opensuse-153 + - R_VERSION=${R_VERSION} + volumes: + - ./:/test + - ../builder/integration/tmp:/packages diff --git a/test/test-centos.sh b/test/test-centos.sh new file mode 100755 index 0000000..3cee256 --- /dev/null +++ b/test/test-centos.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -ex + +PKG_FILE=/packages/${OS_IDENTIFIER}/R-${R_VERSION}-1-1.x86_64.rpm + +if [ ! -f ${PKG_FILE} ]; then + echo "No package found, skipping tests" + exit 0 +fi + +yum -y -q update +yum -y install epel-release +yum -y install ${PKG_FILE} + +# Show rpm info +rpm -qi R-${R_VERSION} + +/test/test-r.sh + +yum -y remove R-${R_VERSION} + +if [ -d /opt/R/${R_VERSION} ]; then + echo "Failed to uninstall completely" + exit 1 +fi diff --git a/test/test-deb.sh b/test/test-deb.sh new file mode 100755 index 0000000..b4ee24b --- /dev/null +++ b/test/test-deb.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -ex + +PKG_FILE=/packages/${OS_IDENTIFIER}/r-${R_VERSION}_1_amd64.deb + +if [ ! -f ${PKG_FILE} ]; then + echo "No package found, skipping tests" + exit 0 +fi + +export DEBIAN_FRONTEND=noninteractive +apt-get update -qq +apt-get install -f -y ${PKG_FILE} + +# Show deb info +apt-cache show r-${R_VERSION} + +/test/test-r.sh + +apt-get remove -y r-${R_VERSION} + +if [ -d /opt/R/${R_VERSION} ]; then + echo "Failed to uninstall completely" + exit 1 +fi diff --git a/test/test-opensuse.sh b/test/test-opensuse.sh new file mode 100755 index 0000000..174b9c5 --- /dev/null +++ b/test/test-opensuse.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -ex + +PKG_FILE=/packages/${OS_IDENTIFIER}/R-${R_VERSION}-1-1.x86_64.rpm + +if [ ! -f ${PKG_FILE} ]; then + echo "No package found, skipping tests" + exit 0 +fi + +zypper --non-interactive --no-gpg-checks install ${PKG_FILE} + +# Show rpm info +rpm -qi R-${R_VERSION} + +/test/test-r.sh + +zypper --non-interactive remove R-${R_VERSION} + +if [ -d /opt/R/${R_VERSION} ]; then + echo "Failed to uninstall completely" + exit 1 +fi diff --git a/test/test-r.sh b/test/test-r.sh new file mode 100755 index 0000000..628acce --- /dev/null +++ b/test/test-r.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -ex + +DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" + +R_HOME=/opt/R/${R_VERSION}/lib/R +"${R_HOME}/bin/R" --version +"${R_HOME}/bin/Rscript" -e 'sessionInfo()' + +# List R devel dependencies +gcc --version +g++ --version +gfortran --version + +# List shared library dependencies (e.g. BLAS/LAPACK) +LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${R_HOME}/lib ldd "${R_HOME}/lib/libR.so" + +DIR=${DIR} "${R_HOME}/bin/Rscript" /test/test.R diff --git a/test/test-rhel.sh b/test/test-rhel.sh new file mode 100755 index 0000000..c2c7918 --- /dev/null +++ b/test/test-rhel.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +set -ex + +PKG_FILE=/packages/${OS_IDENTIFIER}/R-${R_VERSION}-1-1.x86_64.rpm + +if [ ! -f ${PKG_FILE} ]; then + echo "No package found, skipping tests" + exit 0 +fi + +dnf -y install dnf-plugins-core +dnf config-manager --set-enabled crb +dnf -y install epel-release +dnf -y install ${PKG_FILE} + +# Show rpm info +rpm -qi R-${R_VERSION} + +/test/test-r.sh + +dnf -y remove R-${R_VERSION} + +if [ -d /opt/R/${R_VERSION} ]; then + echo "Failed to uninstall completely" + exit 1 +fi diff --git a/test/test.R b/test/test.R new file mode 100644 index 0000000..360c9b1 --- /dev/null +++ b/test/test.R @@ -0,0 +1,103 @@ +# HTTP mirror to support R 3.1 +options(repos = c("https://cloud.r-project.org", "http://cloud.r-project.org")) + +# Create a temp lib to avoid installing into the system library +temp_lib <- tempdir() +.libPaths(temp_lib) + +# Install a package from CRAN +install.packages("R6") +library(R6) + +# Install a package with C/C++ and Fortran code, which links against libR, BLAS, LAPACK +curr_dir <- Sys.getenv("DIR", ".") +install.packages(file.path(curr_dir, "testpkg"), repos = NULL, clean = TRUE) +source(file.path(curr_dir, "testpkg/tests/test.R")) + +# Check iconv support +if (!capabilities("iconv") || !all(c("ASCII", "LATIN1", "UTF-8") %in% iconvlist())) { + stop("missing iconv support") +} + +# Check that built-in packages can be loaded +for (pkg in rownames(installed.packages(priority = c("base", "recommended")))) { + if (!require(pkg, character.only = TRUE)) { + stop(sprintf("failed to load built-in package %s", pkg)) + } +} + +# Show capabilities. Warnings are returned on missing libraries. +tryCatch(capabilities(), warning = function(w) { + print(capabilities()) + stop(sprintf("missing libraries: %s", w$message)) +}) + +# Check graphics devices +# https://stat.ethz.ch/R-manual/R-devel/library/grDevices/html/Devices.html +for (dev_name in c("png", "jpeg", "tiff", "svg", "bmp", "pdf", "postscript", + "xfig", "pictex", "cairo_pdf", "cairo_ps")) { + # Skip unsupported graphics devices (e.g. tiff in R >= 3.3 on CentOS 6) + if (dev_name %in% names(capabilities()) && capabilities(dev_name) == FALSE) { + next + } + dev <- getFromNamespace(dev_name, "grDevices") + tryCatch({ + file <- tempfile() + on.exit(unlink(file)) + if (dev_name == "xfig") { + # Suppress warning from xfig when onefile = FALSE (the default) + dev(file, onefile = TRUE) + } else { + dev(file) + } + plot(1) + dev.off() + }, warning = function(w) { + # Catch errors which manifest as warnings (e.g. "failed to load cairo DLL") + stop(sprintf("graphics device %s failed: %s", dev_name, w$message)) + }) +} + +# Check for unexpected output from graphics/text rendering. +# Run externally to capture output from external processes. +# For example, "Pango-WARNING **: failed to choose a font, expect ugly output" +# messages when rendering text without any system fonts installed. +output <- system2(R.home("bin/Rscript"), "-e 'png(tempfile()); plot(1)'", stdout = TRUE, stderr = TRUE) +if (length(output) > 0) { + stop(sprintf("unexpected output returned from plotting:\n%s", paste(output, collapse = "\n"))) +} + +# Check download methods: libcurl (supported in R >= 3.2) and internal (based on libxml) +if ("libcurl" %in% names(capabilities())) { + download.file("https://cloud.r-project.org", tempfile(), "libcurl") +} +tmpfile <- tempfile() +write.csv("test", tmpfile) +download.file(sprintf("file://%s", tmpfile), tempfile(), "internal") + +# Check that a pager is configured and help pages work +# https://stat.ethz.ch/R-manual/R-devel/library/base/html/file.show.html +output <- system2(R.home("bin/Rscript"), "-e 'help(stats)'", stdout = TRUE) +if (length(output) == 0) { + stop("failed to display help pages; check that a pager is configured properly") +} + +# Smoke test BLAS/LAPACK functionality. R may start just fine with an incompatible +# BLAS/LAPACK library, and only fail when calling a BLAS or LAPACK routine. +stopifnot(identical(crossprod(matrix(1)), matrix(1))) +stopifnot(identical(chol(matrix(1)), matrix(1))) + +# Check that R 3.x depends on PCRE1, and R 4.x depends on PCRE2. +# R 3.5 and 3.6 will link against PCRE2 if present, and take on an unnecessary dependency. +# Some distros do always require PCRE2, however, such as Debian 11. +ld_flags <- system2(R.home("bin/R"), c("CMD", "config", "--ldflags"), stdout = TRUE) +has_pcre1 <- grepl("-lpcre\\b", ld_flags) +has_pcre2 <- grepl("-lpcre2-8\\b", ld_flags) +if (getRversion() >= "3.5.0" && getRversion() < "4.0.0") { + stopifnot(has_pcre1) + if (has_pcre2) { + message(sprintf("Info: %s is linked against PCRE2, which may be unnecessary", R.version.string)) + } +} else if (getRversion() >= "4.0.0") { + stopifnot(has_pcre2 && !has_pcre1) +} diff --git a/test/testpkg/.Rbuildignore b/test/testpkg/.Rbuildignore new file mode 100644 index 0000000..91114bf --- /dev/null +++ b/test/testpkg/.Rbuildignore @@ -0,0 +1,2 @@ +^.*\.Rproj$ +^\.Rproj\.user$ diff --git a/test/testpkg/.gitignore b/test/testpkg/.gitignore new file mode 100644 index 0000000..508df78 --- /dev/null +++ b/test/testpkg/.gitignore @@ -0,0 +1,2 @@ +.Rproj.user +.Rhistory diff --git a/test/testpkg/DESCRIPTION b/test/testpkg/DESCRIPTION new file mode 100644 index 0000000..8ab34d8 --- /dev/null +++ b/test/testpkg/DESCRIPTION @@ -0,0 +1,12 @@ +Package: testpkg +Type: Package +Title: A Test Package +Version: 0.1.0 +Authors@R: person("Test", "Pkg", email = "test@test", role = c("aut", "cre")) +Description: A test package. +License: MIT +Depends: + R (>= 3.1) +SystemRequirements: C++11 +RoxygenNote: 6.1.1 +Encoding: UTF-8 diff --git a/test/testpkg/NAMESPACE b/test/testpkg/NAMESPACE new file mode 100644 index 0000000..20b3781 --- /dev/null +++ b/test/testpkg/NAMESPACE @@ -0,0 +1,6 @@ +# Generated by roxygen2: do not edit by hand + +export(add_it) +export(square_it) +export(subtract_it) +useDynLib(testpkg, .registration = TRUE) diff --git a/test/testpkg/R/testpkg.R b/test/testpkg/R/testpkg.R new file mode 100644 index 0000000..462e518 --- /dev/null +++ b/test/testpkg/R/testpkg.R @@ -0,0 +1,32 @@ +#' @useDynLib testpkg, .registration = TRUE +"_PACKAGE" + +#' Add it together +#' +#' @param a Number +#' @param b Number +#' @return Sum of numbers +#' @export +add_it <- function(a, b) { + .Call("add", a, b) +} + +#' Subtract it +#' +#' @param a Number +#' @param b Number +#' @return Difference of numbers +#' @export +subtract_it <- function(a, b) { + .Call("subtract", a, b) +} + +#' Square it up +#' +#' @param n Integer +#' @return Square +#' @export +square_it <- function(n) { + result <- .Fortran("square", n = as.integer(n), answer = as.integer(1)) + result$answer +} diff --git a/test/testpkg/README.md b/test/testpkg/README.md new file mode 100644 index 0000000..edbda2f --- /dev/null +++ b/test/testpkg/README.md @@ -0,0 +1,3 @@ +# testpkg + +Test package with C/C++ and Fortran code, which links against libR, BLAS, LAPACK (see [Makevars](src/Makevars)). diff --git a/test/testpkg/man/add_it.Rd b/test/testpkg/man/add_it.Rd new file mode 100644 index 0000000..7f00cf5 --- /dev/null +++ b/test/testpkg/man/add_it.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/testpkg.R +\name{add_it} +\alias{add_it} +\title{Add it together} +\usage{ +add_it(a, b) +} +\arguments{ +\item{a}{Number} + +\item{b}{Number} +} +\value{ +Sum of numbers +} +\description{ +Add it together +} diff --git a/test/testpkg/man/square_it.Rd b/test/testpkg/man/square_it.Rd new file mode 100644 index 0000000..e19a4b4 --- /dev/null +++ b/test/testpkg/man/square_it.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/testpkg.R +\name{square_it} +\alias{square_it} +\title{Square it up} +\usage{ +square_it(n) +} +\arguments{ +\item{n}{Integer} +} +\value{ +Square +} +\description{ +Square it up +} diff --git a/test/testpkg/man/subtract_it.Rd b/test/testpkg/man/subtract_it.Rd new file mode 100644 index 0000000..1b7bb2d --- /dev/null +++ b/test/testpkg/man/subtract_it.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/testpkg.R +\name{subtract_it} +\alias{subtract_it} +\title{Subtract it} +\usage{ +subtract_it(a, b) +} +\arguments{ +\item{a}{Number} + +\item{b}{Number} +} +\value{ +Difference of numbers +} +\description{ +Subtract it +} diff --git a/test/testpkg/man/testpkg-package.Rd b/test/testpkg/man/testpkg-package.Rd new file mode 100644 index 0000000..529cf99 --- /dev/null +++ b/test/testpkg/man/testpkg-package.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/testpkg.R +\docType{package} +\name{testpkg-package} +\alias{testpkg} +\alias{testpkg-package} +\title{testpkg: A Test Package} +\description{ +A test package. +} +\author{ +\strong{Maintainer}: Test Pkg \email{test@test} + +} diff --git a/test/testpkg/src/Makevars b/test/testpkg/src/Makevars new file mode 100644 index 0000000..03c539f --- /dev/null +++ b/test/testpkg/src/Makevars @@ -0,0 +1,2 @@ +CXX_STD=CXX11 +PKG_LIBS=$(MAIN_LDFLAGS) $(LDFLAGS) $(LIBR) $(LIBS) $(LAPACK_LIBS) $(BLAS_LIBS) $(SHLIB_OPENMP_CFLAGS) diff --git a/test/testpkg/src/add.c b/test/testpkg/src/add.c new file mode 100644 index 0000000..77cd5f3 --- /dev/null +++ b/test/testpkg/src/add.c @@ -0,0 +1,10 @@ +#include +#include + +SEXP add(SEXP a, SEXP b) +{ + SEXP result = PROTECT(allocVector(REALSXP, 1)); + REAL(result)[0] = asReal(a) + asReal(b); + UNPROTECT(1); + return result; +} diff --git a/test/testpkg/src/init.c b/test/testpkg/src/init.c new file mode 100644 index 0000000..7d40e5b --- /dev/null +++ b/test/testpkg/src/init.c @@ -0,0 +1,33 @@ +#include +#include +#include + +#define CALLDEF(name, n) {#name, (DL_FUNC) &name, n} +#define FDEF(name) {#name, (DL_FUNC) &F77_SUB(name), sizeof(name ## _t)/sizeof(name ## _t[0]), name ##_t} + +extern SEXP add(SEXP, SEXP); +extern SEXP subtract(SEXP, SEXP); + +void F77_SUB(square)(int *n, int *answer); + +static R_NativePrimitiveArgType square_t[] = { + INTSXP, + INTSXP +}; + +static const R_CallMethodDef CallEntries[] = { + CALLDEF(add, 2), + CALLDEF(subtract, 2), + {NULL, NULL, 0} +}; + +static const R_FortranMethodDef fMethods[] = { + FDEF(square), + {NULL, NULL, 0} +}; + +void R_init_testpkg(DllInfo *dll) +{ + R_registerRoutines(dll, NULL, CallEntries, fMethods, NULL); + R_useDynamicSymbols(dll, FALSE); +} diff --git a/test/testpkg/src/square.f b/test/testpkg/src/square.f new file mode 100644 index 0000000..77971e9 --- /dev/null +++ b/test/testpkg/src/square.f @@ -0,0 +1,5 @@ + subroutine square(x,answer) + integer, intent(in) :: x + integer, intent(out) :: answer + answer = x * x + end diff --git a/test/testpkg/src/subtract.cpp b/test/testpkg/src/subtract.cpp new file mode 100644 index 0000000..c9ef0a1 --- /dev/null +++ b/test/testpkg/src/subtract.cpp @@ -0,0 +1,10 @@ +#include +#include + +extern "C" SEXP subtract(SEXP a, SEXP b) +{ + SEXP result = PROTECT(allocVector(REALSXP, 1)); + REAL(result)[0] = asReal(a) - asReal(b); + UNPROTECT(1); + return result; +} diff --git a/test/testpkg/testpkg.Rproj b/test/testpkg/testpkg.Rproj new file mode 100644 index 0000000..cb6ae55 --- /dev/null +++ b/test/testpkg/testpkg.Rproj @@ -0,0 +1,19 @@ +Version: 1.0 + +RestoreWorkspace: No +SaveWorkspace: No +AlwaysSaveHistory: No + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: knitr +LaTeX: pdfLaTeX + +AutoAppendNewline: Yes +StripTrailingWhitespace: Yes + +BuildType: Package +PackageRoxygenize: rd,collate,namespace diff --git a/test/testpkg/tests/test.R b/test/testpkg/tests/test.R new file mode 100644 index 0000000..7bf3ce7 --- /dev/null +++ b/test/testpkg/tests/test.R @@ -0,0 +1,5 @@ +library(testpkg) + +stopifnot(add_it(1, 2) == 3) +stopifnot(subtract_it(1, 2) == -1) +stopifnot(square_it(3) == 9) From 974cefff66d9c5a3757e2eaccb5d86ff04481f40 Mon Sep 17 00:00:00 2001 From: Greg Lin Date: Wed, 10 Aug 2022 18:39:17 -0500 Subject: [PATCH 2/5] Add Make targets for easier development/testing; update README --- Makefile | 20 ++++++++++++++++++++ README.md | 35 ++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 2e28140..f0f7492 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,26 @@ rebuild-all: deps fetch-serverless-custom-file serverless-deploy.%: deps fetch-serverless-custom-file $(SLS_BINARY) deploy --stage $* +define GEN_TARGETS +docker-build-$(platform): + @cd builder && docker-compose build $(platform) + +build-r-$(platform): + @cd builder && R_VERSION=$(R_VERSION) docker-compose up $(platform) + +test-r-$(platform): + @cd test && R_VERSION=$(R_VERSION) docker-compose up $(platform) + +bash-$(platform): + docker run -it --rm --entrypoint /bin/bash -v $(CURDIR):/r-builds r-builds:$(platform) + +.PHONY: docker-build-$(platform) build-r-$(platform) test-r-$(platform) bash-$(platform) +endef + +$(foreach platform,$(PLATFORMS), \ + $(eval $(GEN_TARGETS)) \ +) + # Helper for launching a bash session on a docker image of your choice. Defaults # to "ubuntu:xenial". TARGET_IMAGE?=ubuntu:xenial diff --git a/README.md b/README.md index d6bf989..2ee37c2 100644 --- a/README.md +++ b/README.md @@ -244,33 +244,34 @@ serverless invoke stepf -n rBuilds -d '{"force": true, "versions": ["3.6.3", "4. ## Testing -To test the R builds locally, you can build the images: +To test the R builds locally, you can use the `build-r-$PLATFORM` and `test-r-$PLATFORM` +targets to build R and run the tests. The tests use the quick install script to install R, +using a locally built R if present, or otherwise a build from the CDN. ```bash -# Build images for all platforms -make docker-build +# Build R 4.1.3 for Ubuntu 22 +R_VERSION=4.1.3 make build-r-ubuntu-2204 -# Or build the image for a single platform -(cd builder && docker-compose build ubuntu-2004) +# Test R 4.1.3 for Ubuntu 22 +R_VERSION=4.1.3 make test-r-ubuntu-2204 ``` -Then run the build script: +Alternatively, you can build an image using the `docker-build-$PLATFORM` +target, launch a bash session within a container using the `bash-$PLATFORM` target, +and interactively run the build script: ```bash -# Build R for all platforms -R_VERSION=4.0.5 make docker-build-r +# Build the image for Ubuntu 22 +make docker-build-ubuntu-2204 -# Build R for a single platform -(cd builder && R_VERSION=4.0.5 docker-compose up ubuntu-2004) +# Launch a bash session for Ubuntu 22 +make bash-ubuntu-2204 -# Alternatively, run the build script from within a container -docker run -it --rm --entrypoint "/bin/bash" r-builds:ubuntu-2004 +# Build R 4.1.3 +R_VERSION=4.1.3 ./build.sh -# Build R 4.0.5 -R_VERSION=4.0.5 ./build.sh - -# Build R devel -R_VERSION=devel ./build.sh +# Build R devel with parallel execution to speed up the build +MAKEFLAGS=-j4 R_VERSION=devel ./build.sh # Build a prerelease version of R (e.g., alpha or beta) R_VERSION=rc R_TARBALL_URL=https://cran.r-project.org/src/base-prerelease/R-latest.tar.gz ./build.sh From 79bd3a378fb122c25a105e60df14eba12f4ff368 Mon Sep 17 00:00:00 2001 From: Greg Lin Date: Wed, 10 Aug 2022 18:39:57 -0500 Subject: [PATCH 3/5] Fix quick install script not detecting Debian version correctly --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 3ba156d..42adb1d 100755 --- a/install.sh +++ b/install.sh @@ -110,7 +110,7 @@ detect_os_version () { cat /etc/os-release | grep -e "^VERSION_ID\=*" | cut -f 2 -d '=' | sed -e 's/"//g' fi fi - if [[ "${os}" == "Ubuntu" ]]; then + if [[ "${os}" == "Ubuntu" ]] || [[ "${os}" == "Debian" ]]; then cat /etc/os-release | grep -e "^VERSION_ID\=*" | cut -f 2 -d '=' | sed -e 's/[".]//g' fi if [[ "${os}" == "SLES15" ]] || [[ "${os}" == "LEAP15" ]]; then From df380906fb83438d2b76c64a188a04d5aa439d09 Mon Sep 17 00:00:00 2001 From: Greg Lin Date: Wed, 10 Aug 2022 18:53:09 -0500 Subject: [PATCH 4/5] Fix unattended quick install hanging on tzdata for Ubuntu 18 --- install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/install.sh b/install.sh index 42adb1d..43321dc 100755 --- a/install.sh +++ b/install.sh @@ -277,6 +277,7 @@ install_deb () { if [[ "${RUN_UNATTENDED}" -ne "0" ]]; then yes="--n" yesapt="-y" + export DEBIAN_FRONTEND=noninteractive fi echo "Updating package indexes..." ${SUDO} apt-get update From 83dfc554f24e019766408566fda09959446cba2e Mon Sep 17 00:00:00 2001 From: Greg Lin Date: Wed, 10 Aug 2022 18:53:42 -0500 Subject: [PATCH 5/5] Use quick install script to test R builds --- test/docker-compose.yml | 40 ++++++++++++++++------------------------ test/test-apt.sh | 27 +++++++++++++++++++++++++++ test/test-centos.sh | 25 ------------------------- test/test-deb.sh | 25 ------------------------- test/test-opensuse.sh | 23 ----------------------- test/test-r.sh | 4 ++-- test/test-rhel.sh | 26 -------------------------- test/test-yum.sh | 32 ++++++++++++++++++++++++++++++++ test/test-zypper.sh | 26 ++++++++++++++++++++++++++ 9 files changed, 103 insertions(+), 125 deletions(-) create mode 100755 test/test-apt.sh delete mode 100755 test/test-centos.sh delete mode 100755 test/test-deb.sh delete mode 100755 test/test-opensuse.sh delete mode 100755 test/test-rhel.sh create mode 100755 test/test-yum.sh create mode 100755 test/test-zypper.sh diff --git a/test/docker-compose.yml b/test/docker-compose.yml index 91ea366..57215bd 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -3,73 +3,65 @@ version: '2.0' services: ubuntu-1804: image: ubuntu:bionic - command: /test/test-deb.sh + command: /r-builds/test/test-apt.sh environment: - OS_IDENTIFIER=ubuntu-1804 - R_VERSION=${R_VERSION} volumes: - - ./:/test - - ../builder/integration/tmp:/packages + - ../:/r-builds ubuntu-2004: image: ubuntu:focal - command: /test/test-deb.sh + command: /r-builds/test/test-apt.sh environment: - OS_IDENTIFIER=ubuntu-2004 - R_VERSION=${R_VERSION} volumes: - - ./:/test - - ../builder/integration/tmp:/packages + - ../:/r-builds ubuntu-2204: image: ubuntu:jammy - command: /test/test-deb.sh + command: /r-builds/test/test-apt.sh environment: - OS_IDENTIFIER=ubuntu-2204 - R_VERSION=${R_VERSION} volumes: - - ./:/test - - ../builder/integration/tmp:/packages + - ../:/r-builds debian-11: image: debian:bullseye - command: /test/test-deb.sh + command: /r-builds/test/test-apt.sh environment: - OS_IDENTIFIER=debian-11 - R_VERSION=${R_VERSION} volumes: - - ./:/test - - ../builder/integration/tmp:/packages + - ../:/r-builds debian-10: image: debian:buster - command: /test/test-deb.sh + command: /r-builds/test/test-apt.sh environment: - OS_IDENTIFIER=debian-10 - R_VERSION=${R_VERSION} volumes: - - ./:/test - - ../builder/integration/tmp:/packages + - ../:/r-builds centos-7: image: centos:centos7 - command: /test/test-centos.sh + command: /r-builds/test/test-yum.sh environment: - OS_IDENTIFIER=centos-7 - R_VERSION=${R_VERSION} volumes: - - ./:/test - - ../builder/integration/tmp:/packages + - ../:/r-builds centos-8: image: rockylinux:8 - command: /test/test-centos.sh + command: /r-builds/test/test-yum.sh environment: - OS_IDENTIFIER=centos-8 - R_VERSION=${R_VERSION} volumes: - - ./:/test - - ../builder/integration/tmp:/packages + - ../:/r-builds opensuse-153: image: opensuse/leap:15.3 - command: /test/test-opensuse.sh + command: /r-builds/test/test-zypper.sh environment: - OS_IDENTIFIER=opensuse-153 - R_VERSION=${R_VERSION} volumes: - - ./:/test - - ../builder/integration/tmp:/packages + - ../:/r-builds diff --git a/test/test-apt.sh b/test/test-apt.sh new file mode 100755 index 0000000..56a8012 --- /dev/null +++ b/test/test-apt.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -ex + +SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" + +# Install quick install script prerequisites +if ! command -v curl > /dev/null 2>&1; then + apt update -qq + apt install -y curl +fi + +# Run the quick install script. Use a locally built file if present, otherwise from the CDN. +tmpdir=$(mktemp -d) +cp -r "${SCRIPT_DIR}/../builder/integration/tmp/${OS_IDENTIFIER}/." "$tmpdir" > /dev/null 2>&1 || true +(cd "$tmpdir" && SCRIPT_ACTION=install R_VERSION="${R_VERSION}" RUN_UNATTENDED=1 "${SCRIPT_DIR}/../install.sh") + +# Show DEB info +apt show "r-${R_VERSION}" + +"${SCRIPT_DIR}/test-r.sh" + +apt remove -y "r-${R_VERSION}" + +if [ -d "/opt/R/${R_VERSION}" ]; then + echo "Failed to uninstall completely" + exit 1 +fi diff --git a/test/test-centos.sh b/test/test-centos.sh deleted file mode 100755 index 3cee256..0000000 --- a/test/test-centos.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -set -ex - -PKG_FILE=/packages/${OS_IDENTIFIER}/R-${R_VERSION}-1-1.x86_64.rpm - -if [ ! -f ${PKG_FILE} ]; then - echo "No package found, skipping tests" - exit 0 -fi - -yum -y -q update -yum -y install epel-release -yum -y install ${PKG_FILE} - -# Show rpm info -rpm -qi R-${R_VERSION} - -/test/test-r.sh - -yum -y remove R-${R_VERSION} - -if [ -d /opt/R/${R_VERSION} ]; then - echo "Failed to uninstall completely" - exit 1 -fi diff --git a/test/test-deb.sh b/test/test-deb.sh deleted file mode 100755 index b4ee24b..0000000 --- a/test/test-deb.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -set -ex - -PKG_FILE=/packages/${OS_IDENTIFIER}/r-${R_VERSION}_1_amd64.deb - -if [ ! -f ${PKG_FILE} ]; then - echo "No package found, skipping tests" - exit 0 -fi - -export DEBIAN_FRONTEND=noninteractive -apt-get update -qq -apt-get install -f -y ${PKG_FILE} - -# Show deb info -apt-cache show r-${R_VERSION} - -/test/test-r.sh - -apt-get remove -y r-${R_VERSION} - -if [ -d /opt/R/${R_VERSION} ]; then - echo "Failed to uninstall completely" - exit 1 -fi diff --git a/test/test-opensuse.sh b/test/test-opensuse.sh deleted file mode 100755 index 174b9c5..0000000 --- a/test/test-opensuse.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -set -ex - -PKG_FILE=/packages/${OS_IDENTIFIER}/R-${R_VERSION}-1-1.x86_64.rpm - -if [ ! -f ${PKG_FILE} ]; then - echo "No package found, skipping tests" - exit 0 -fi - -zypper --non-interactive --no-gpg-checks install ${PKG_FILE} - -# Show rpm info -rpm -qi R-${R_VERSION} - -/test/test-r.sh - -zypper --non-interactive remove R-${R_VERSION} - -if [ -d /opt/R/${R_VERSION} ]; then - echo "Failed to uninstall completely" - exit 1 -fi diff --git a/test/test-r.sh b/test/test-r.sh index 628acce..8783716 100755 --- a/test/test-r.sh +++ b/test/test-r.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -ex -DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" +SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" R_HOME=/opt/R/${R_VERSION}/lib/R "${R_HOME}/bin/R" --version @@ -15,4 +15,4 @@ gfortran --version # List shared library dependencies (e.g. BLAS/LAPACK) LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${R_HOME}/lib ldd "${R_HOME}/lib/libR.so" -DIR=${DIR} "${R_HOME}/bin/Rscript" /test/test.R +DIR=$SCRIPT_DIR "${R_HOME}/bin/Rscript" "${SCRIPT_DIR}/test.R" diff --git a/test/test-rhel.sh b/test/test-rhel.sh deleted file mode 100755 index c2c7918..0000000 --- a/test/test-rhel.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -set -ex - -PKG_FILE=/packages/${OS_IDENTIFIER}/R-${R_VERSION}-1-1.x86_64.rpm - -if [ ! -f ${PKG_FILE} ]; then - echo "No package found, skipping tests" - exit 0 -fi - -dnf -y install dnf-plugins-core -dnf config-manager --set-enabled crb -dnf -y install epel-release -dnf -y install ${PKG_FILE} - -# Show rpm info -rpm -qi R-${R_VERSION} - -/test/test-r.sh - -dnf -y remove R-${R_VERSION} - -if [ -d /opt/R/${R_VERSION} ]; then - echo "Failed to uninstall completely" - exit 1 -fi diff --git a/test/test-yum.sh b/test/test-yum.sh new file mode 100755 index 0000000..93a0e13 --- /dev/null +++ b/test/test-yum.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +set -ex + +SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" + +if command -v dnf > /dev/null 2>&1; then + YUM=dnf +else + YUM=yum +fi + +# Install quick install script prerequisites +if ! command -v curl > /dev/null 2>&1; then + $YUM install -y curl +fi + +# Run the quick install script. Use a locally built file if present, otherwise from the CDN. +tmpdir=$(mktemp -d) +cp -r "${SCRIPT_DIR}/../builder/integration/tmp/${OS_IDENTIFIER}/." "$tmpdir" > /dev/null 2>&1 || true +(cd "$tmpdir" && SCRIPT_ACTION=install R_VERSION="${R_VERSION}" RUN_UNATTENDED=1 "${SCRIPT_DIR}/../install.sh") + +# Show rpm info +rpm -qi "R-${R_VERSION}" + +"${SCRIPT_DIR}/test-r.sh" + +$YUM -y remove "R-${R_VERSION}" + +if [ -d "/opt/R/${R_VERSION}" ]; then + echo "Failed to uninstall completely" + exit 1 +fi diff --git a/test/test-zypper.sh b/test/test-zypper.sh new file mode 100755 index 0000000..7b15c18 --- /dev/null +++ b/test/test-zypper.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +set -ex + +SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" + +# Install quick install script prerequisites +if ! command -v curl > /dev/null 2>&1; then + zypper --non-interactive install curl +fi + +# Run the quick install script. Use a locally built file if present, otherwise from the CDN. +tmpdir=$(mktemp -d) +cp -r "${SCRIPT_DIR}/../builder/integration/tmp/${OS_IDENTIFIER}/." "$tmpdir" > /dev/null 2>&1 || true +(cd "$tmpdir" && SCRIPT_ACTION=install R_VERSION="${R_VERSION}" RUN_UNATTENDED=1 "${SCRIPT_DIR}/../install.sh") + +# Show RPM info +rpm -qi "R-${R_VERSION}" + +"${SCRIPT_DIR}/test-r.sh" + +zypper --non-interactive remove "R-${R_VERSION}" + +if [ -d "/opt/R/${R_VERSION}" ]; then + echo "Failed to uninstall completely" + exit 1 +fi