From f8c4a3e2115c644c3cb1c597d450a96046d9b7f1 Mon Sep 17 00:00:00 2001 From: Mick Jordan <mick.jordan@oracle.com> Date: Thu, 17 Mar 2016 14:26:43 -0700 Subject: [PATCH] add unit tests for installing/loading GnuR recommended packages --- .../truffle/r/test/ExpectedTestOutput.test | 30 ++++ .../r/test/rpackages/TestRFFIPackage.java | 8 +- .../r/test/rpackages/TestRPackages.java | 150 ++++++++++-------- .../rpackages/TestRecommendedPackages.java | 71 +++++++++ .../r/test/rpackages/TestS4TestPackage.java | 11 +- .../r/test/rpackages/TestVanillaPackage.java | 4 +- 6 files changed, 200 insertions(+), 74 deletions(-) create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 9220e2268c..ca25e1438b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -105089,6 +105089,36 @@ NULL NULL +##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad +#{ library(MASS, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:MASS"); } + +##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad +#{ library(boot, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:boot"); } + +##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad +#{ library(class, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:class"); } + +##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad +#{ library(cluster, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:cluster"); } + +##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad +#{ library(codetools, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:codetools"); } + +##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad +#{ library(foreign, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:foreign"); } + +##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad +#{ library(lattice, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:lattice"); } + +##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad +#{ library(nnet, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:nnet"); } + +##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad +#{ library(spatial, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:spatial"); } + +##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad +#{ library(survival, lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); detach("package:survival"); } + ##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Execute #{ library("tests4", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r<-print(tests4:::inspect.vehicle(new("Car"), new("Inspector"))); detach("package:tests4"); unloadNamespace("tests4"); r } Looking for rust diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRFFIPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRFFIPackage.java index c1677d5856..6a63ecc887 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRFFIPackage.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRFFIPackage.java @@ -48,25 +48,25 @@ public class TestRFFIPackage extends TestRPackages { @Test public void testLoadTestRFFICall() { assertEval(TestBase.template("{ library(\"testrffi\", lib.loc = \"%0\"); r1 <- rffi.addInt(2L, 3L); detach(\"package:testrffi\"); list(r1) }", - new String[]{packagePaths.rpackagesLibs.toString()})); + new String[]{TestRPackages.libLoc()})); assertEval(TestBase.template( "{ library(\"testrffi\", lib.loc = \"%0\"); r1 <- rffi.addInt(2L, 3L); r2 <- rffi.addDouble(2, 3); v <- rffi.populateIntVector(5); v2 <- rffi.dotCModifiedArguments(c(0,1,2,3)); " + "v3<-rffi.isRString(character(0)); detach(\"package:testrffi\"); list(r1, r2, v, v2, v3) }", - new String[]{packagePaths.rpackagesLibs.toString()})); + new String[]{TestRPackages.libLoc()})); } @Test public void testLoadTestRFFIExternal() { assertEval(TestBase.template( "{ library(\"testrffi\", lib.loc = \"%0\"); r1 <- rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12)); detach(\"package:testrffi\"); list(r1) }", - new String[]{packagePaths.rpackagesLibs.toString()})); + new String[]{TestRPackages.libLoc()})); } @Test public void testLoadTestRFFIExternalWithNames() { assertEval(TestBase.template( "{ library(\"testrffi\", lib.loc = \"%0\"); r1 <- rffi.dotExternalAccessArgs(x=1L, 3, c(1,2,3), y=c('a', 'b'), 'b', TRUE, as.raw(12)); detach(\"package:testrffi\"); list(r1) }", - new String[]{packagePaths.rpackagesLibs.toString()})); + new String[]{TestRPackages.libLoc()})); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java index 9d0a1da58e..fdf408e402 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java @@ -27,12 +27,9 @@ import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; +import java.util.HashMap; import java.util.Map; import com.oracle.truffle.r.runtime.FastROptions; @@ -42,63 +39,42 @@ import com.oracle.truffle.r.test.TestBase; /** * Tests related to the loading, etc. of R packages. + * + * THis class should be subclassed by a test that wishes to install one or more packages and + * possibly run additional tests after installation using a pattern of the form + * {@code library(pkg, lib.loc="%0"); sometest()}. Note the use of the {@code %0}, which must be + * satisfied by passing the value of {@code libLoc()}. This is required because the test VM is not + * aware of the test install location so it must be explicitly specified. The use of the {@code %0} + * parameter mechanism also requires the use of {@link TestBase#template} in the test itself. + * + * A subclass must provide {@code @BeforeClass} and {@code @AfterClass}methods that call + * {@link #setupInstallTestPackages} and {@link #tearDownUninstallTestPackages}, respectively, to + * install/remove the specific set of packages relevant to the test. + * + * N.B. The same directory is used when generating expected output with GnuR, and running FastR, to + * keep the {@code lib_loc} argument the same in the test string. So the install is destructive, but + * ok as there is never a clash. + * + * The install directory is cleaned on every call to {@link #setupInstallTestPackages} in case a + * previous install failed to complete {@link #tearDownUninstallTestPackages} successfully. */ -public class TestRPackages extends TestBase { +public abstract class TestRPackages extends TestBase { /** - * Create {@link Path}s to needed folders. N.B. The same directory is used when generating - * expected output with GnuR, and running FastR, to keep the {@code lib_loc} argument the same - * in the test string. So the install is destructive, but ok as there is never a clash. + * Create {@link Path}s to needed folders. * */ protected static final class PackagePaths { /** - * The path containing the package distributions as tar files. These are built in the - * {@code com.oracle.truffle.r.test.native} project in the {@code packages} directory. - */ - private final Path rpackagesDists; - /** - * The path to where the package will be installed (R_LIBS_USER). + * The path containing the package distributions as tar files. */ - protected final Path rpackagesLibs; - - private PackagePaths() { - Path rpackages = Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test", "rpackages"); - rpackagesLibs = TestBase.relativize(rpackages.resolve("testrlibs_user")); - // Empty it in case of failure that didn't clean up - if (rpackagesLibs.toFile().exists()) { - try { - Files.walkFileTree(rpackagesLibs, new SimpleFileVisitor<Path>() { - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } + private final Path packagePath; - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { - if (e == null) { - Files.delete(dir); - return FileVisitResult.CONTINUE; - } else { - // directory iteration failed - throw e; - } - } - - }); - } catch (IOException e) { - assert false; - } - } - - rpackagesLibs.toFile().mkdirs(); - rpackagesDists = Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test.native", "packages"); + private PackagePaths(Path rpackagesDists) { + this.packagePath = rpackagesDists; } - protected boolean installPackage(String packageName) { - Path packagePath = rpackagesDists.resolve(packageName).resolve("lib").resolve(packageName + ".tar"); + protected boolean installPackage() { String[] cmds = new String[4]; if (generatingExpected()) { // use GnuR @@ -112,7 +88,7 @@ public class TestRPackages extends TestBase { cmds[cmds.length - 1] = packagePath.toString(); ProcessBuilder pb = new ProcessBuilder(cmds); Map<String, String> env = pb.environment(); - env.put("R_LIBS_USER", rpackagesLibs.toString()); + env.put("R_LIBS_USER", installDir().toString()); if (!generatingExpected()) { env.put("R_INSTALL_TAR", RContext.getInstance().stateREnvVars.get("TAR")); } @@ -147,25 +123,73 @@ public class TestRPackages extends TestBase { } } - protected boolean uninstallPackage(String packageName) { - Path packageDir = rpackagesLibs.resolve(packageName); - try { - deleteDir(packageDir); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - return true; + } + + /** + * The path to the install directory. This is fixed across all tests. + */ + private static Path installDir; + + /** + * Map from package name to info on its location. + */ + private static final Map<String, PackagePaths> packageMap = new HashMap<>(); + + private static Path installDir() { + if (installDir == null) { + installDir = TestBase.relativize(Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test", "rpackages", "testrlibs_user")); } + return installDir; + } + protected static String libLoc() { + return installDir().toString(); } - protected static final PackagePaths packagePaths = new PackagePaths(); + private static boolean uninstallPackage(String packageName) { + Path packageDir = installDir().resolve(packageName); + try { + deleteDir(packageDir); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + return true; + } + + /** + * Pass a custom subclass of this class to override the actual location of the package tar file. + */ + protected static class Resolver { + Path getPath(String p) { + return testNativePath().resolve(p).resolve("lib").resolve(p + ".tar"); + } + } + + private static Path testNativePath() { + return Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test.native", "packages"); + } + + private static PackagePaths getPackagePaths(String pkg, Path path) { + PackagePaths result = packageMap.get(pkg); + if (result == null) { + result = new PackagePaths(path); + packageMap.put(pkg, result); + } + return result; + } protected static void setupInstallTestPackages(String[] testPackages) { + setupInstallTestPackages(testPackages, new Resolver()); + } + + protected static void setupInstallTestPackages(String[] testPackages, Resolver resolver) { if (!checkOnly()) { + TestBase.deleteDir(installDir()); + installDir().toFile().mkdirs(); for (String p : testPackages) { - if (!packagePaths.installPackage(p)) { + PackagePaths packagePaths = getPackagePaths(p, resolver.getPath(p)); + if (!packagePaths.installPackage()) { throw new AssertionError(); } } @@ -175,7 +199,7 @@ public class TestRPackages extends TestBase { protected static void tearDownUninstallTestPackages(String[] testPackages) { if (!checkOnly()) { for (String p : testPackages) { - if (!packagePaths.uninstallPackage(p)) { + if (!uninstallPackage(p)) { throw new AssertionError(); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java new file mode 100644 index 0000000000..e52b79a15a --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.test.rpackages; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.oracle.truffle.r.runtime.REnvVars; +import com.oracle.truffle.r.runtime.RVersionNumber; +import com.oracle.truffle.r.test.TestBase; + +/** + * Test the installation of the "recommended" packages that come with GnuR. N.B. There are no + * specific tests beyond install/load as that is handled separately in the package testing + * framework. We are primarily concerned with detecting installation regressions. + * + */ +public class TestRecommendedPackages extends TestRPackages { + private static final String[] OK_PACKAGES = new String[]{"MASS", "boot", "class", "cluster", "codetools", "foreign", "lattice", "nnet", "spatial", "survival"}; + @SuppressWarnings("unused") private static final String[] PROBLEM_PACKAGES = new String[]{"KernSmooth", "Matrix", "nlme", "rpart"}; + + private static Path getRecommendedPath() { + return Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.native", "gnur", RVersionNumber.R_HYPHEN_FULL, "src", "library", "Recommended"); + } + + @BeforeClass + public static void setupInstallMyTestPackages() { + setupInstallTestPackages(OK_PACKAGES, new Resolver() { + @Override + Path getPath(String p) { + return getRecommendedPath().resolve(p + ".tgz"); + } + }); + } + + @AfterClass + public static void tearDownUninstallMyTestPackages() { + tearDownUninstallTestPackages(OK_PACKAGES); + } + + @Test + public void testLoad() { + assertEval(TestBase.template("{ library(%1, lib.loc = \"%0\"); detach(\"package:%1\"); }", + new String[]{TestRPackages.libLoc()}, OK_PACKAGES)); + } + +} diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java index 13144ae4d4..6cb8a5c1a3 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java @@ -47,23 +47,24 @@ public class TestS4TestPackage extends TestRPackages { @Test public void testS4Load() { - assertEval(TestBase.template("{ library(\"tests4\", lib.loc = \"%0\"); detach(\"package:tests4\"); unloadNamespace(\"tests4\") }", new String[]{packagePaths.rpackagesLibs.toString()})); + assertEval(TestBase.template("{ library(\"tests4\", lib.loc = \"%0\"); detach(\"package:tests4\"); unloadNamespace(\"tests4\") }", + new String[]{TestRPackages.libLoc()})); } @Test public void testS4Execute() { assertEval(TestBase.template( "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Car\"), new(\"Inspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }", - new String[]{packagePaths.rpackagesLibs.toString()})); + new String[]{TestRPackages.libLoc()})); assertEval(TestBase.template( "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Truck\"), new(\"Inspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }", - new String[]{packagePaths.rpackagesLibs.toString()})); + new String[]{TestRPackages.libLoc()})); assertEval(TestBase.template( "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Car\"), new(\"StateInspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }", - new String[]{packagePaths.rpackagesLibs.toString()})); + new String[]{TestRPackages.libLoc()})); assertEval(TestBase.template( "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Truck\"), new(\"StateInspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }", - new String[]{packagePaths.rpackagesLibs.toString()})); + new String[]{TestRPackages.libLoc()})); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java index 3c94ad8785..8f9d0c5541 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java @@ -47,13 +47,13 @@ public class TestVanillaPackage extends TestRPackages { @Test public void testLoadVanilla() { - assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r <- vanilla(); detach(\"package:vanilla\"); r }", new String[]{packagePaths.rpackagesLibs.toString()})); + assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r <- vanilla(); detach(\"package:vanilla\"); r }", new String[]{TestRPackages.libLoc()})); } @Test public void testSimpleFunction() { assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r <- functionTest(c(1,2,3,4,5,6),8:10); detach(\"package:vanilla\"); r }", - new String[]{packagePaths.rpackagesLibs.toString()})); + new String[]{TestRPackages.libLoc()})); } } -- GitLab