From 67d6f6bdf9cb47e711792cc3b9f31ebda3d4f660 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 29 Sep 2015 19:19:05 +0200
Subject: [PATCH] tests for .External interface usage

---
 .../packages/testrffi/testrffi/R/testrffi.R   |  4 +
 .../packages/testrffi/testrffi/src/testrffi.c | 36 +++++++++
 .../truffle/r/test/ExpectedTestOutput.test    | 30 +++++++-
 .../r/test/rpackages/TestRFFIPackage.java     | 76 +++++++++++++++++++
 .../r/test/rpackages/TestRPackages.java       | 70 ++++++-----------
 .../r/test/rpackages/TestVanillaPackage.java  | 61 +++++++++++++++
 6 files changed, 227 insertions(+), 50 deletions(-)
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRFFIPackage.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java

diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
index 0355ac9fa9..02f30e9d38 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
@@ -25,3 +25,7 @@ rffi.TYPEOF <- function(x) {
 rffi.error <- function() {
 	.Call("invoke_error", PACKAGE = "testrffi")
 }
+
+rffi.dotExternalAccessArgs <- function(...) {
+	.External("dot_external_access_args", ..., PACKAGE = "testrffi")
+}
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
index 4cadd04e57..cf5d7e5a1a 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
@@ -66,3 +66,39 @@ SEXP invoke_TYPEOF(SEXP x) {
 SEXP invoke_error() {
 	error("invoke_error in testrffi");
 }
+
+SEXP dot_external_access_args(SEXP args) {
+    args = CDR(args);
+    int index = 0;
+    for (; args != R_NilValue; args = CDR(args)) {
+	index++;
+	SEXP tag = TAG(args);
+	const char *name = isNull(tag) ? "" : CHAR(PRINTNAME(tag));
+	SEXP value = CAR(args);
+	if (length(value) == 0) {
+	    Rprintf("%d: '%s' length 0\n", index, name);
+	    continue;
+	}
+	switch (TYPEOF(value)) {
+	case LGLSXP:
+	case INTSXP:
+	    Rprintf("%d: '%s' %d\n", index, name, INTEGER(value)[0]);
+	    break;
+	case REALSXP:
+	    Rprintf("%d: '%s' %f\n", index, name, REAL(value)[0]);
+	    break;
+	case CPLXSXP: {
+	    Rcomplex complexValue = COMPLEX(value)[0];
+	    Rprintf("%d: '%s' %f+%fi\n", index, name, complexValue.r,
+		    complexValue.i);
+	    break;
+	}
+	case STRSXP:
+	    Rprintf("%d: '%s' %s\n", index, name, CHAR(STRING_ELT(value, 0)));
+	    break;
+	default:
+	    Rprintf("%d: %s other\n", index, name);
+	}
+    }
+    return R_NilValue;
+}
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 10c3431b51..5cba5419b0 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
@@ -103134,7 +103134,7 @@ attr(,"foo")
  [1] 0.45336386 0.38848030 0.94576608 0.11726267 0.21542351 0.08672997
  [7] 0.35201276 0.16919220 0.93579263 0.26084486
 
-##com.oracle.truffle.r.test.rpackages.TestRPackages.testLoadTestRFFI
+##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFICall
 #{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.addInt(2L, 3L); r2 <- rffi.addDouble(2, 3); v <- rffi.populateIntVector(5); detach("package:testrffi"); list(r1, r2, v) }
 [[1]]
 [1] 5
@@ -103146,7 +103146,33 @@ attr(,"foo")
 [1] 0 1 2 3 4
 
 
-##com.oracle.truffle.r.test.rpackages.TestRPackages.testLoadVanilla
+##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFIExternal
+#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi"); list(r1) }
+1: '' 1
+2: '' 3.000000
+3: '' 1.000000
+4: '' a
+5: '' b
+6: '' 1
+7:  other
+[[1]]
+NULL
+
+
+##com.oracle.truffle.r.test.rpackages.TestRFFIPackage.testLoadTestRFFIExternalWithNames
+#{ library("testrffi", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r1 <- rffi.dotExternalAccessArgs(x=1L, 3, c(1,2,3), y=c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi"); list(r1) }
+1: 'x' 1
+2: '' 3.000000
+3: '' 1.000000
+4: 'y' a
+5: '' b
+6: '' 1
+7:  other
+[[1]]
+NULL
+
+
+##com.oracle.truffle.r.test.rpackages.TestVanillaPackage.testLoadVanilla
 #{ library("vanilla", lib.loc = "com.oracle.truffle.r.test/rpackages/testrlibs_user"); r <- vanilla(); detach("package:vanilla"); r }
 [1] "A vanilla R package"
 [1] "A vanilla R package"
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
new file mode 100644
index 0000000000..1c51cc1b2c
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRFFIPackage.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, 2015, 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 org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+/**
+ * Tests related to the loading, etc. of R packages.
+ */
+public class TestRFFIPackage extends TestRPackages {
+
+    private static final String[] TEST_PACKAGES = new String[]{"testrffi"};
+
+    @BeforeClass
+    public static void setupInstallTestPackages() {
+        for (String p : TEST_PACKAGES) {
+            if (!packagePaths.installPackage(p)) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    @AfterClass
+    public static void tearDownUninstallTestPackages() {
+        for (String p : TEST_PACKAGES) {
+            if (!packagePaths.uninstallPackage(p)) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    @Test
+    public void testLoadTestRFFICall() {
+        assertEval(TestBase.template(
+                        "{ library(\"testrffi\", lib.loc = \"%0\"); r1 <- rffi.addInt(2L, 3L); r2 <- rffi.addDouble(2, 3); v <- rffi.populateIntVector(5); detach(\"package:testrffi\"); list(r1, r2, v) }",
+                        new String[]{packagePaths.rpackagesLibs.toString()}));
+    }
+
+    @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()}));
+    }
+
+    @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()}));
+    }
+}
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 455976bfe1..3b2cb570bb 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
@@ -22,17 +22,23 @@
  */
 package com.oracle.truffle.r.test.rpackages;
 
-import java.io.*;
-import java.nio.charset.*;
-import java.nio.file.*;
-import java.nio.file.attribute.*;
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.context.*;
-import com.oracle.truffle.r.test.*;
+import java.io.BufferedReader;
+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.Map;
+
+import com.oracle.truffle.r.runtime.FastROptions;
+import com.oracle.truffle.r.runtime.REnvVars;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.test.TestBase;
 
 /**
  * Tests related to the loading, etc. of R packages.
@@ -45,7 +51,7 @@ public class TestRPackages extends TestBase {
      * in the test string. So the install is destructive, but ok as there is never a clash.
      *
      */
-    private static final class PackagePaths {
+    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.
@@ -54,7 +60,7 @@ public class TestRPackages extends TestBase {
         /**
          * The path to where the package will be installed (R_LIBS_USER).
          */
-        private final Path rpackagesLibs;
+        protected final Path rpackagesLibs;
 
         private PackagePaths() {
             Path rpackages = Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test", "rpackages");
@@ -91,7 +97,7 @@ public class TestRPackages extends TestBase {
             rpackagesDists = Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.test.native", "packages");
         }
 
-        private boolean installPackage(String packageName) {
+        protected boolean installPackage(String packageName) {
             Path packagePath = rpackagesDists.resolve(packageName).resolve("lib").resolve(packageName + ".tar");
             String[] cmds = new String[4];
             if (generatingExpected()) {
@@ -141,7 +147,7 @@ public class TestRPackages extends TestBase {
             }
         }
 
-        private boolean uninstallPackage(String packageName) {
+        protected boolean uninstallPackage(String packageName) {
             Path packageDir = rpackagesLibs.resolve(packageName);
             try {
                 deleteDir(packageDir);
@@ -154,38 +160,6 @@ public class TestRPackages extends TestBase {
 
     }
 
-    private static final PackagePaths packagePaths = new PackagePaths();
-
-    private static final String[] TEST_PACKAGES = new String[]{"vanilla", "testrffi"};
-
-    @BeforeClass
-    public static void setupInstallTestPackages() {
-        for (String p : TEST_PACKAGES) {
-            if (!packagePaths.installPackage(p)) {
-                throw new AssertionError();
-            }
-        }
-    }
-
-    @AfterClass
-    public static void tearDownUninstallTestPackages() {
-        for (String p : TEST_PACKAGES) {
-            if (!packagePaths.uninstallPackage(p)) {
-                throw new AssertionError();
-            }
-        }
-    }
-
-    @Test
-    public void testLoadVanilla() {
-        assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r <- vanilla(); detach(\"package:vanilla\"); r }", new String[]{packagePaths.rpackagesLibs.toString()}));
-    }
-
-    @Test
-    public void testLoadTestRFFI() {
-        assertEval(TestBase.template(
-                        "{ library(\"testrffi\", lib.loc = \"%0\"); r1 <- rffi.addInt(2L, 3L); r2 <- rffi.addDouble(2, 3); v <- rffi.populateIntVector(5); detach(\"package:testrffi\"); list(r1, r2, v) }",
-                        new String[]{packagePaths.rpackagesLibs.toString()}));
-    }
+    protected static final PackagePaths packagePaths = new PackagePaths();
 
 }
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
new file mode 100644
index 0000000000..0cac5d339a
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2015, 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 org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+/**
+ * Tests related to the loading, etc. of R packages.
+ */
+public class TestVanillaPackage extends TestRPackages {
+
+    private static final String[] TEST_PACKAGES = new String[]{"vanilla"};
+
+    @BeforeClass
+    public static void setupInstallTestPackages() {
+        for (String p : TEST_PACKAGES) {
+            if (!packagePaths.installPackage(p)) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    @AfterClass
+    public static void tearDownUninstallTestPackages() {
+        for (String p : TEST_PACKAGES) {
+            if (!packagePaths.uninstallPackage(p)) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    @Test
+    public void testLoadVanilla() {
+        assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r <- vanilla(); detach(\"package:vanilla\"); r }", new String[]{packagePaths.rpackagesLibs.toString()}));
+    }
+
+}
-- 
GitLab