diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
index cab4934525c42ab1be917f7f54f8c255d53f9b3d..c2b3d6e9517a0b66d9dcd7016c6648ad372f41c2 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
@@ -42,6 +42,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
@@ -55,6 +57,7 @@ import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RErrorHandling;
+import com.oracle.truffle.r.runtime.RErrorHandling.HandlerStacks;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
@@ -912,7 +915,12 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     @Override
     @TruffleBoundary
     public Object R_ToplevelExec() {
-        return RErrorHandling.resetAndGetHandlerStacks();
+        return RErrorHandling.resetAndGetHandlerStacks().handlerStack;
+    }
+
+    @Override
+    public void restoreHandlerStacks(Object savedHandlerStack) {
+        RErrorHandling.restoreHandlerStack(savedHandlerStack);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
index f8a81aab1f9996222b0b2c9522cdedce03a03b1d..cfc4c80acb4c40e4c78fa2b1e01174778b679ab3 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
@@ -275,6 +275,8 @@ public interface StdUpCallsRFFI {
 
     Object R_ToplevelExec();
 
+    void restoreHandlerStacks(Object savedHandlerStack);
+
     int RDEBUG(Object x);
 
     void SET_RDEBUG(Object x, int v);
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
index f7f80924ca61a74e5e53154ff4eab6cb0ddea981..e5f5f5cfdce29cb59143a704c51cfeddb6ba2d74 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
@@ -202,7 +202,8 @@ typedef void (*call_DUPLICATE_ATTRIB)(SEXP to, SEXP from);
 typedef int (*call_IS_S4_OBJECT)(SEXP x);
 typedef void (*call_SET_S4_OBJECT)(SEXP x);
 typedef void (*call_UNSET_S4_OBJECT)(SEXP x);
-typedef Rboolean (*call_R_ToplevelExec)(void (*fun)(void *), void *data);
+typedef SEXP (*call_R_ToplevelExec)();
+typedef void (*call_restoreHandlerStack)(SEXP saved_handler_stack);
 typedef void (*call_R_RestoreHashCount)(SEXP rho);
 typedef Rboolean (*call_R_IsPackageEnv)(SEXP rho);
 typedef SEXP (*call_R_PackageEnvName)(SEXP rho);
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
index 8008fede3e7cc374695fea9e699d25b50020fb22..cc3ddaf77801fcbcf663e28e6f02d1be12094a4f 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
@@ -173,10 +173,11 @@
 #define octsize_x 168
 #define registerCCallable_x 169
 #define registerRoutines_x 170
-#define setDotSymbolValues_x 171
-#define unif_rand_x 172
-#define useDynamicSymbols_x 173
+#define restoreHandlerStacks_x 171
+#define setDotSymbolValues_x 172
+#define unif_rand_x 173
+#define useDynamicSymbols_x 174
 
-#define UPCALLS_TABLE_SIZE 174
+#define UPCALLS_TABLE_SIZE 175
 
 #endif // RFFI_UPCALLSINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
index c69fd861ca3255694cb9b8733dc4947d5be014af..c305453c283d0c934e99e13942a7399d78aabf1d 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
@@ -1253,7 +1253,16 @@ void UNSET_S4_OBJECT(SEXP x) {
 
 Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
     TRACE0();
-    return (Rboolean) unimplemented("R_ToplevelExec");
+
+    // reset handler stack
+    SEXP saved_handler_stack = ((call_R_ToplevelExec) callbacks[R_ToplevelExec_x])();
+    checkExitCall();
+    fun(data);
+    ((call_restoreHandlerStack) callbacks[restoreHandlerStacks_x])(saved_handler_stack);
+    checkExitCall();
+
+    // TODO detect errors
+    return TRUE;
 }
 
 SEXP R_ExecWithCleanup(SEXP (*fun)(void *), void *data,
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index 9e5feb5256930f3cae636754eef8a244ede164eb..abac1ea7b759d8258c9ad9e5b450f782aaa33374 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-46
+47
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index ddddd0287c8f0a66953348b28210defd344e5bba..051060c567f3adb12e2bdc3e72b8be645c7b9778 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -31,6 +31,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.nio.file.CopyOption;
 import java.nio.file.DirectoryStream;
 import java.nio.file.FileAlreadyExistsException;
@@ -677,7 +678,7 @@ public class FileFunctions {
                             files.add(fullNames ? FileSystems.getDefault().getPath(vecPathString, DOTDOT).toString() : DOTDOT);
                         }
                     }
-                } catch (IOException ex) {
+                } catch (IOException | UncheckedIOException ex) {
                     // ignored
                 }
             }
diff --git a/com.oracle.truffle.r.test.packages/importantPackages b/com.oracle.truffle.r.test.packages/importantPackages
new file mode 100644
index 0000000000000000000000000000000000000000..f285b70cb0ca826994786003efe45fdc6c15ba0f
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages/importantPackages
@@ -0,0 +1,183 @@
+abind,1.4-5,https://cloud.r-project.org/src/contrib/abind_1.4-5.tar.gz,
+acepack,1.4.1,https://cloud.r-project.org/src/contrib/acepack_1.4.1.tar.gz,
+afex,0.18-0,https://cloud.r-project.org/src/contrib/afex_0.18-0.tar.gz,
+anomalyDetection,0.2.4,https://cloud.r-project.org/src/contrib/anomalyDetection_0.2.4.tar.gz,
+assertthat,0.2.0,https://cloud.r-project.org/src/contrib/assertthat_0.2.0.tar.gz,
+backports,1.1.1,https://cloud.r-project.org/src/contrib/backports_1.1.1.tar.gz,
+base64enc,0.1-3,https://cloud.r-project.org/src/contrib/base64enc_0.1-3.tar.gz,
+BH,1.65.0-1,https://cloud.r-project.org/src/contrib/BH_1.65.0-1.tar.gz,
+bindr,0.1,https://cloud.r-project.org/src/contrib/bindr_0.1.tar.gz,
+bindrcpp,0.2,https://cloud.r-project.org/src/contrib/bindrcpp_0.2.tar.gz,
+bitops,1.0-6,https://cloud.r-project.org/src/contrib/bitops_1.0-6.tar.gz,
+broom,0.4.3,https://cloud.r-project.org/src/contrib/broom_0.4.3.tar.gz,
+car,2.1-6,https://cloud.r-project.org/src/contrib/car_2.1-6.tar.gz,
+caret,6.0-78,https://cloud.r-project.org/src/contrib/caret_6.0-78.tar.gz,
+caTools,1.17.1,https://cloud.r-project.org/src/contrib/caTools_1.17.1.tar.gz,
+cellranger,1.1.0,https://cloud.r-project.org/src/contrib/cellranger_1.1.0.tar.gz,
+checkmate,1.8.5,https://cloud.r-project.org/src/contrib/checkmate_1.8.5.tar.gz,
+class,7.3-14,https://cloud.r-project.org/src/contrib/class_7.3-14.tar.gz,
+cluster,2.0.6,https://cloud.r-project.org/src/contrib/cluster_2.0.6.tar.gz,
+coda,0.19-1,https://cloud.r-project.org/src/contrib/coda_0.19-1.tar.gz,
+codetools,0.2-15,https://cloud.r-project.org/src/contrib/codetools_0.2-15.tar.gz,
+coin,1.2-2,https://cloud.r-project.org/src/contrib/coin_1.2-2.tar.gz,
+colorspace,1.3-2,https://cloud.r-project.org/src/contrib/colorspace_1.3-2.tar.gz,
+compare,0.2-6,https://cloud.r-project.org/src/contrib/compare_0.2-6.tar.gz,
+crayon,1.3.4,https://cloud.r-project.org/src/contrib/crayon_1.3.4.tar.gz,
+curl,3.0,https://cloud.r-project.org/src/contrib/curl_3.0.tar.gz,
+CVST,0.2-1,https://cloud.r-project.org/src/contrib/CVST_0.2-1.tar.gz,
+data.table,1.10.4-3,https://cloud.r-project.org/src/contrib/data.table_1.10.4-3.tar.gz,
+DBI,0.7,https://cloud.r-project.org/src/contrib/DBI_0.7.tar.gz,
+ddalpha,1.3.1,https://cloud.r-project.org/src/contrib/ddalpha_1.3.1.tar.gz,
+DEoptimR,1.0-8,https://cloud.r-project.org/src/contrib/DEoptimR_1.0-8.tar.gz,
+devtools,1.13.4,https://cloud.r-project.org/src/contrib/devtools_1.13.4.tar.gz,
+dichromat,2.0-0,https://cloud.r-project.org/src/contrib/dichromat_2.0-0.tar.gz,
+digest,0.6.12,https://cloud.r-project.org/src/contrib/digest_0.6.12.tar.gz,
+dimRed,0.1.0,https://cloud.r-project.org/src/contrib/dimRed_0.1.0.tar.gz,
+doSNOW,1.0.15,https://cloud.r-project.org/src/contrib/doSNOW_1.0.15.tar.gz,
+dplyr,0.7.4,https://cloud.r-project.org/src/contrib/dplyr_0.7.4.tar.gz,
+DRR,0.0.2,https://cloud.r-project.org/src/contrib/DRR_0.0.2.tar.gz,
+DT,0.2,https://cloud.r-project.org/src/contrib/DT_0.2.tar.gz,
+e1071,1.6-8,https://cloud.r-project.org/src/contrib/e1071_1.6-8.tar.gz,
+estimability,1.2,https://cloud.r-project.org/src/contrib/estimability_1.2.tar.gz,
+evaluate,0.10.1,https://cloud.r-project.org/src/contrib/evaluate_0.10.1.tar.gz,
+foreach,1.4.3,https://cloud.r-project.org/src/contrib/foreach_1.4.3.tar.gz,
+forecast,8.2,https://cloud.r-project.org/src/contrib/forecast_8.2.tar.gz,
+foreign,0.8-69,https://cloud.r-project.org/src/contrib/foreign_0.8-69.tar.gz,
+Formula,1.2-2,https://cloud.r-project.org/src/contrib/Formula_1.2-2.tar.gz,
+gbm,2.1.3,https://cloud.r-project.org/src/contrib/gbm_2.1.3.tar.gz,
+gdata,2.18.0,https://cloud.r-project.org/src/contrib/gdata_2.18.0.tar.gz,
+ggnetwork,0.5.1,https://cloud.r-project.org/src/contrib/ggnetwork_0.5.1.tar.gz,
+ggplot2,2.2.1,https://cloud.r-project.org/src/contrib/ggplot2_2.2.1.tar.gz,
+git2r,0.19.0,https://cloud.r-project.org/src/contrib/git2r_0.19.0.tar.gz,
+glmnet,2.0-13,https://cloud.r-project.org/src/contrib/glmnet_2.0-13.tar.gz,
+glue,1.2.0,https://cloud.r-project.org/src/contrib/glue_1.2.0.tar.gz,
+gmp,0.5-13.1,https://cloud.r-project.org/src/contrib/gmp_0.5-13.1.tar.gz,
+gower,0.1.2,https://cloud.r-project.org/src/contrib/gower_0.1.2.tar.gz,
+gridExtra,2.3,https://cloud.r-project.org/src/contrib/gridExtra_2.3.tar.gz,
+gtable,0.2.0,https://cloud.r-project.org/src/contrib/gtable_0.2.0.tar.gz,
+gtools,3.5.0,https://cloud.r-project.org/src/contrib/gtools_3.5.0.tar.gz,
+highr,0.6,https://cloud.r-project.org/src/contrib/highr_0.6.tar.gz,
+Hmisc,4.0-3,https://cloud.r-project.org/src/contrib/Hmisc_4.0-3.tar.gz,
+hms,0.4.0,https://cloud.r-project.org/src/contrib/hms_0.4.0.tar.gz,
+htmlTable,1.11.0,https://cloud.r-project.org/src/contrib/htmlTable_1.11.0.tar.gz,
+htmltools,0.3.6,https://cloud.r-project.org/src/contrib/htmltools_0.3.6.tar.gz,
+htmlwidgets,0.9,https://cloud.r-project.org/src/contrib/htmlwidgets_0.9.tar.gz,
+httpuv,1.3.5,https://cloud.r-project.org/src/contrib/httpuv_1.3.5.tar.gz,
+httr,1.3.1,https://cloud.r-project.org/src/contrib/httr_1.3.1.tar.gz,
+ipred,0.9-6,https://cloud.r-project.org/src/contrib/ipred_0.9-6.tar.gz,
+iterators,1.0.8,https://cloud.r-project.org/src/contrib/iterators_1.0.8.tar.gz,
+jsonlite,1.5,https://cloud.r-project.org/src/contrib/jsonlite_1.5.tar.gz,
+kernlab,0.9-25,https://cloud.r-project.org/src/contrib/kernlab_0.9-25.tar.gz,
+KernSmooth,2.23-15,https://cloud.r-project.org/src/contrib/KernSmooth_2.23-15.tar.gz,
+knitr,1.17,https://cloud.r-project.org/src/contrib/knitr_1.17.tar.gz,
+labeling,0.3,https://cloud.r-project.org/src/contrib/labeling_0.3.tar.gz,
+lattice,0.20-35,https://cloud.r-project.org/src/contrib/lattice_0.20-35.tar.gz,
+latticeExtra,0.6-28,https://cloud.r-project.org/src/contrib/latticeExtra_0.6-28.tar.gz,
+lava,1.5.1,https://cloud.r-project.org/src/contrib/lava_1.5.1.tar.gz,
+lazyeval,0.2.1,https://cloud.r-project.org/src/contrib/lazyeval_0.2.1.tar.gz,
+lme4,1.1-14,https://cloud.r-project.org/src/contrib/lme4_1.1-14.tar.gz,
+lmerTest,2.0-36,https://cloud.r-project.org/src/contrib/lmerTest_2.0-36.tar.gz,
+lmtest,0.9-35,https://cloud.r-project.org/src/contrib/lmtest_0.9-35.tar.gz,
+lsmeans,2.27-61,https://cloud.r-project.org/src/contrib/lsmeans_2.27-61.tar.gz,
+lubridate,1.7.1,https://cloud.r-project.org/src/contrib/lubridate_1.7.1.tar.gz,
+magrittr,1.5,https://cloud.r-project.org/src/contrib/magrittr_1.5.tar.gz,
+markdown,0.8,https://cloud.r-project.org/src/contrib/markdown_0.8.tar.gz,
+MASS,7.3-47,https://cloud.r-project.org/src/contrib/MASS_7.3-47.tar.gz,
+Matrix,1.2-12,https://cloud.r-project.org/src/contrib/Matrix_1.2-12.tar.gz,
+MatrixModels,0.4-1,https://cloud.r-project.org/src/contrib/MatrixModels_0.4-1.tar.gz,
+mboost,2.8-1,https://cloud.r-project.org/src/contrib/mboost_2.8-1.tar.gz,
+memoise,1.1.0,https://cloud.r-project.org/src/contrib/memoise_1.1.0.tar.gz,
+mgcv,1.8-22,https://cloud.r-project.org/src/contrib/mgcv_1.8-22.tar.gz,
+mime,0.5,https://cloud.r-project.org/src/contrib/mime_0.5.tar.gz,
+minerva,1.4.7,https://cloud.r-project.org/src/contrib/minerva_1.4.7.tar.gz,
+miniUI,0.1.1,https://cloud.r-project.org/src/contrib/miniUI_0.1.1.tar.gz,
+minqa,1.2.4,https://cloud.r-project.org/src/contrib/minqa_1.2.4.tar.gz,
+mnormt,1.5-5,https://cloud.r-project.org/src/contrib/mnormt_1.5-5.tar.gz,
+ModelMetrics,1.1.0,https://cloud.r-project.org/src/contrib/ModelMetrics_1.1.0.tar.gz,
+modeltools,0.2-21,https://cloud.r-project.org/src/contrib/modeltools_0.2-21.tar.gz,
+multcomp,1.4-8,https://cloud.r-project.org/src/contrib/multcomp_1.4-8.tar.gz,
+munsell,0.4.3,https://cloud.r-project.org/src/contrib/munsell_0.4.3.tar.gz,
+mvoutlier,2.0.8,https://cloud.r-project.org/src/contrib/mvoutlier_2.0.8.tar.gz,
+mvtnorm,1.0-6,https://cloud.r-project.org/src/contrib/mvtnorm_1.0-6.tar.gz,
+naivebayes,0.9.1,https://cloud.r-project.org/src/contrib/naivebayes_0.9.1.tar.gz,
+nlme,3.1-131,https://cloud.r-project.org/src/contrib/nlme_3.1-131.tar.gz,
+nloptr,1.0.4,https://cloud.r-project.org/src/contrib/nloptr_1.0.4.tar.gz,
+nnet,7.3-12,https://cloud.r-project.org/src/contrib/nnet_7.3-12.tar.gz,
+numDeriv,2016.8-1,https://cloud.r-project.org/src/contrib/numDeriv_2016.8-1.tar.gz,
+openssl,0.9.9,https://cloud.r-project.org/src/contrib/openssl_0.9.9.tar.gz,
+OptimalCutpoints,1.1-3,https://cloud.r-project.org/src/contrib/OptimalCutpoints_1.1-3.tar.gz,
+oro.nifti,0.9.1,https://cloud.r-project.org/src/contrib/oro.nifti_0.9.1.tar.gz,
+party,1.2-3,https://cloud.r-project.org/src/contrib/party_1.2-3.tar.gz,
+pbkrtest,0.4-7,https://cloud.r-project.org/src/contrib/pbkrtest_0.4-7.tar.gz,
+pkgconfig,2.0.1,https://cloud.r-project.org/src/contrib/pkgconfig_2.0.1.tar.gz,
+plogr,0.1-1,https://cloud.r-project.org/src/contrib/plogr_0.1-1.tar.gz,
+plyr,1.8.4,https://cloud.r-project.org/src/contrib/plyr_1.8.4.tar.gz,
+ppcor,1.1,https://cloud.r-project.org/src/contrib/ppcor_1.1.tar.gz,
+pracma,2.1.1,https://cloud.r-project.org/src/contrib/pracma_2.1.1.tar.gz,
+pROC,1.10.0,https://cloud.r-project.org/src/contrib/pROC_1.10.0.tar.gz,
+prodlim,1.6.1,https://cloud.r-project.org/src/contrib/prodlim_1.6.1.tar.gz,
+prophet,0.2.1,https://cloud.r-project.org/src/contrib/prophet_0.2.1.tar.gz,
+psych,1.7.8,https://cloud.r-project.org/src/contrib/psych_1.7.8.tar.gz,
+purrr,0.2.4,https://cloud.r-project.org/src/contrib/purrr_0.2.4.tar.gz,
+quantmod,0.4-12,https://cloud.r-project.org/src/contrib/quantmod_0.4-12.tar.gz,
+quantreg,5.34,https://cloud.r-project.org/src/contrib/quantreg_5.34.tar.gz,
+R6,2.2.2,https://cloud.r-project.org/src/contrib/R6_2.2.2.tar.gz,
+randomForest,4.6-12,https://cloud.r-project.org/src/contrib/randomForest_4.6-12.tar.gz,
+randomForestSRC,2.5.1,https://cloud.r-project.org/src/contrib/randomForestSRC_2.5.1.tar.gz,
+RColorBrewer,1.1-2,https://cloud.r-project.org/src/contrib/RColorBrewer_1.1-2.tar.gz,
+Rcpp,0.12.14,https://cloud.r-project.org/src/contrib/Rcpp_0.12.14.tar.gz,
+RcppArmadillo,0.8.300.1.0,https://cloud.r-project.org/src/contrib/RcppArmadillo_0.8.300.1.0.tar.gz,
+RcppEigen,0.3.3.3.1,https://cloud.r-project.org/src/contrib/RcppEigen_0.3.3.3.1.tar.gz,
+RcppRoll,0.2.2,https://cloud.r-project.org/src/contrib/RcppRoll_0.2.2.tar.gz,
+RCurl,1.95-4.8,https://cloud.r-project.org/src/contrib/RCurl_1.95-4.8.tar.gz,
+readr,1.1.1,https://cloud.r-project.org/src/contrib/readr_1.1.1.tar.gz,
+readxl,1.0.0,https://cloud.r-project.org/src/contrib/readxl_1.0.0.tar.gz,
+recipes,0.1.1,https://cloud.r-project.org/src/contrib/recipes_0.1.1.tar.gz,
+rematch,1.0.1,https://cloud.r-project.org/src/contrib/rematch_1.0.1.tar.gz,
+reshape2,1.4.2,https://cloud.r-project.org/src/contrib/reshape2_1.4.2.tar.gz,
+rJava,0.9-9,https://cloud.r-project.org/src/contrib/rJava_0.9-9.tar.gz,
+RJDBC,0.2-5,https://cloud.r-project.org/src/contrib/RJDBC_0.2-5.tar.gz,
+rjson,0.2.15,https://cloud.r-project.org/src/contrib/rjson_0.2.15.tar.gz,
+rlang,0.1.4,https://cloud.r-project.org/src/contrib/rlang_0.1.4.tar.gz,
+rmarkdown,1.8,https://cloud.r-project.org/src/contrib/rmarkdown_1.8.tar.gz,
+RNifti,0.7.1,https://cloud.r-project.org/src/contrib/RNifti_0.7.1.tar.gz,
+robustbase,0.92-8,https://cloud.r-project.org/src/contrib/robustbase_0.92-8.tar.gz,
+ROCR,1.0-7,https://cloud.r-project.org/src/contrib/ROCR_1.0-7.tar.gz,
+ROracle,1.3-1,https://cloud.r-project.org/src/contrib/ROracle_1.3-1.tar.gz,
+rpart,4.1-11,https://cloud.r-project.org/src/contrib/rpart_4.1-11.tar.gz,
+rprojroot,1.2,https://cloud.r-project.org/src/contrib/rprojroot_1.2.tar.gz,
+RSclient,0.7-3,https://cloud.r-project.org/src/contrib/RSclient_0.7-3.tar.gz,
+Rserve,1.7-3,https://cloud.r-project.org/src/contrib/Rserve_1.7-3.tar.gz,
+rstudioapi,0.7,https://cloud.r-project.org/src/contrib/rstudioapi_0.7.tar.gz,
+sandwich,2.4-0,https://cloud.r-project.org/src/contrib/sandwich_2.4-0.tar.gz,
+scales,0.5.0,https://cloud.r-project.org/src/contrib/scales_0.5.0.tar.gz,
+sfsmisc,1.1-1,https://cloud.r-project.org/src/contrib/sfsmisc_1.1-1.tar.gz,
+shiny,1.0.5,https://cloud.r-project.org/src/contrib/shiny_1.0.5.tar.gz,
+shinyjs,0.9.1,https://cloud.r-project.org/src/contrib/shinyjs_0.9.1.tar.gz,
+shinythemes,1.1.1,https://cloud.r-project.org/src/contrib/shinythemes_1.1.1.tar.gz,
+snow,0.4-2,https://cloud.r-project.org/src/contrib/snow_0.4-2.tar.gz,
+sourcetools,0.1.6,https://cloud.r-project.org/src/contrib/sourcetools_0.1.6.tar.gz,
+sp,1.2-5,https://cloud.r-project.org/src/contrib/sp_1.2-5.tar.gz,
+SparseM,1.77,https://cloud.r-project.org/src/contrib/SparseM_1.77.tar.gz,
+sqldf,0.4-11,https://cloud.r-project.org/src/contrib/sqldf_0.4-11.tar.gz,
+stringi,1.1.6,https://cloud.r-project.org/src/contrib/stringi_1.1.6.tar.gz,
+stringr,1.2.0,https://cloud.r-project.org/src/contrib/stringr_1.2.0.tar.gz,
+survival,2.41-3,https://cloud.r-project.org/src/contrib/survival_2.41-3.tar.gz,
+TH.data,1.0-8,https://cloud.r-project.org/src/contrib/TH.data_1.0-8.tar.gz,
+tibble,1.3.4,https://cloud.r-project.org/src/contrib/tibble_1.3.4.tar.gz,
+tidyr,0.7.2,https://cloud.r-project.org/src/contrib/tidyr_0.7.2.tar.gz,
+tidyselect,0.2.3,https://cloud.r-project.org/src/contrib/tidyselect_0.2.3.tar.gz,
+tidyverse,1.2.1,https://cloud.r-project.org/src/contrib/tidyverse_1.2.1.tar.gz,
+timeDate,3042.101,https://cloud.r-project.org/src/contrib/timeDate_3042.101.tar.gz,
+viridis,0.4.0,https://cloud.r-project.org/src/contrib/viridis_0.4.0.tar.gz,
+viridisLite,0.2.0,https://cloud.r-project.org/src/contrib/viridisLite_0.2.0.tar.gz,
+whisker,0.3-2,https://cloud.r-project.org/src/contrib/whisker_0.3-2.tar.gz,
+withr,2.1.0,https://cloud.r-project.org/src/contrib/withr_2.1.0.tar.gz,
+wordcloud,2.5,https://cloud.r-project.org/src/contrib/wordcloud_2.5.tar.gz,
+xgboost,0.6-4,https://cloud.r-project.org/src/contrib/xgboost_0.6-4.tar.gz,
+XML,3.98-1.9,https://cloud.r-project.org/src/contrib/XML_3.98-1.9.tar.gz,
+xml2,1.1.1,https://cloud.r-project.org/src/contrib/xml2_1.1.1.tar.gz,
+xtable,1.8-2,https://cloud.r-project.org/src/contrib/xtable_1.8-2.tar.gz,
+yaml,2.1.15,https://cloud.r-project.org/src/contrib/yaml_2.1.15.tar.gz,
+zoo,1.8-0,https://cloud.r-project.org/src/contrib/zoo_1.8-0.tar.gz,
+
diff --git a/com.oracle.truffle.r.test.packages/r/install.cache.R b/com.oracle.truffle.r.test.packages/r/install.cache.R
index 17f8f91faf34fd1ff63786889a071add6cbafe5a..d74eb390f13e15fe0f38b5848afc6b89ced2bff5 100644
--- a/com.oracle.truffle.r.test.packages/r/install.cache.R
+++ b/com.oracle.truffle.r.test.packages/r/install.cache.R
@@ -21,6 +21,11 @@
 # questions.
 #
 
+# A simple log function; to be replaced by a used of this file.
+log.message <- function(..., level=0) {
+    cat(..., "\n")
+}
+
 pkg.cache.install <- function(pkg.cache.env, pkgname, lib.install, install.cmd) {
     is.cached <- pkg.cache.get(pkg.cache.env, pkgname, lib.install)
     if (!is.cached) {
@@ -243,10 +248,6 @@ pkg.cache.get.version <- function(cache.dir, cache.version, table.file.name, cac
     })
 }
 
-log.message <- function(..., level=0) {
-    cat(..., "\n")
-}
-
 # list of recommended and base packages
 recommended.base.packages <- c("boot", "class", "cluster", "codetools", "foreign", "KernSmooth", "lattice", "MASS", "Matrix", "mgcv", "nlme", "nnet", "rpart", "spatial", "survival", "base", "compiler", "datasets", "grDevices", "graphics", "grid", "methods", "parallel", "splines", "stats", "stats4", "tools", "utils")
 
@@ -254,12 +255,11 @@ recommended.base.packages <- c("boot", "class", "cluster", "codetools", "foreign
 base.packages <- c("base", "compiler", "datasets", "grDevices", "graphics", "grid", "methods", "parallel", "splines", "stats", "stats4", "tools", "utils")
 
 # the list of packages that will be excluded in the transitive dependecies
-ignored.packages <- base.packages
+ignored.packages <- recommended.base.packages
 
 package.dependencies <- function(pkg, lib, dependencies = c("Depends", "Imports", "LinkingTo"), pl = available.packages()) {
     if (!(pkg %in% rownames(pl))) {
-        # TODO: logging
-        cat("Package", pkg, "not on CRAN\n")
+        log.message("Package", pkg, "not on CRAN\n", level=1)
         return (NULL)
     }
     fields <- pl[pkg, dependencies]
diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py
index 4ecb45a153d5a44aeaae001f41a5a1768f98db1d..abbe70e0d115b1104964fb4ac997ea5454967ceb 100644
--- a/mx.fastr/mx_fastr_pkgs.py
+++ b/mx.fastr/mx_fastr_pkgs.py
@@ -320,6 +320,7 @@ class TestFileStatus:
     def __init__(self, status, abspath):
         self.status = status
         self.abspath = abspath
+        self.report = 0, 1, 0
 
 class TestStatus:
     '''Records the test status of a package. status ends up as either "OK" or "FAILED",
@@ -463,36 +464,97 @@ def _set_test_status(fastr_test_info):
             with open(fastr_testfile_status.abspath) as f:
                 fastr_content = f.readlines()
 
-            result = _fuzzy_compare(gnur_content, fastr_content, gnur_testfile_status.abspath, fastr_testfile_status.abspath)
-            if result == -1:
-                print "{0}: content malformed: {1}".format(pkg, gnur_test_output_relpath)
-                fastr_test_status.status = "INDETERMINATE"
-                break
-            if result != 0:
-                fastr_test_status.status = "FAILED"
-                fastr_testfile_status.status = "FAILED"
-                print "{0}: FastR output mismatch: {1}".format(pkg, gnur_test_output_relpath)
-                break
+            # first, parse file and see if a known test framework has been used
+            ok, skipped, failed = handle_output_file(fastr_content)
+            if ok is not None:
+                fastr_testfile_status.report = ok, skipped, failed
+            else:
+                result, n_tests_passed, n_tests_failed = _fuzzy_compare(gnur_content, fastr_content, gnur_testfile_status.abspath, fastr_testfile_status.abspath)
+                if result == -1:
+                    print "{0}: content malformed: {1}".format(pkg, gnur_test_output_relpath)
+                    fastr_test_status.status = "INDETERMINATE"
+                    # we don't know how many tests are in there, so consider the whole file to be one big skipped test
+                    fastr_testfile_status.report = 0, 1, 0
+                    #break
+                elif result != 0:
+                    fastr_test_status.status = "FAILED"
+                    fastr_testfile_status.status = "FAILED"
+                    fastr_testfile_status.report = n_tests_passed, 0, n_tests_failed
+                    print "{0}: FastR output mismatch: {1}".format(pkg, gnur_test_output_relpath)
+                    #break
+                else:
+                    fastr_testfile_status.status = "OK"
+                    fastr_testfile_status.report = n_tests_passed, 0, n_tests_failed
+
+
         # we started out as UNKNOWN
         if not (fastr_test_status.status == "INDETERMINATE" or fastr_test_status.status == "FAILED"):
             fastr_test_status.status = "OK"
 
         # write out a file with the test status for each output (that exists)
         with open(join(_pkg_testdir('fastr', pkg), 'testfile_status'), 'w') as f:
+            f.write('# <file path> <tests passed> <tests skipped> <tests failed>\n')
             for fastr_relpath, fastr_testfile_status in fastr_outputs.iteritems():
                 if fastr_testfile_status.status == "FAILED":
                     relpath = fastr_relpath + ".fail"
                 else:
                     relpath = fastr_relpath
 
-                if os.path.exists(join(_pkg_testdir('fastr', pkg), relpath)):
-                    f.write(relpath)
-                    f.write(' ')
-                    f.write(fastr_testfile_status.status)
-                    f.write('\n')
+                test_output_file = join(_pkg_testdir('fastr', pkg), relpath)
+                if os.path.exists(test_output_file):
+                    ok, skipped, failed = fastr_testfile_status.report
+                    f.write("{0} {1} {2} {3}\n".format(relpath, ok, skipped, failed))
 
         print 'END checking ' + pkg
 
+
+def handle_output_file(test_output_file_contents):
+    """
+    R package tests are usually distributed over several files. Each file can be interpreted as a test suite.
+    This function parses the output file of all test suites and tries to detect if it used the testthat or RUnit.
+    In this case, it parses the summary (number of passed, skipped, failed tests) of these test frameworks.
+    If none of the frameworks is used, it performs an output diff and tries to determine, how many statements
+    produces different output, i.e., every statement is considered to be a unit test.
+    :param test_output_file_contents: the lines of the output file
+    :return: A 3-tuple with the number of passed, skipped, and failed tests.
+    """
+    for i in range(0, len(test_output_file_contents)):
+        if test_output_file_contents[i].startswith("testthat results"):
+            return _parse_testthat_result(test_output_file_contents, i)
+
+        # TODO parse RUnit test protocol
+
+    # if this test did not use one of the known test frameworks, take the report from the fuzzy compare
+    return None, None, None
+
+
+def _parse_testthat_result(lines, i):
+    '''
+    OK: 2 SKIPPED: 0 FAILED: 0
+    '''
+    if i+1 < len(lines) and lines[i+1].startswith("OK"):
+        result_line = lines[i+1]
+        idx_ok = 0
+        idx_skipped = result_line.find("SKIPPED")
+        idx_failed = result_line.find("FAILED")
+        if idx_ok != -1 and idx_skipped != -1 and idx_failed != -1:
+            ok_part = result_line[idx_ok:idx_skipped]
+            skipped_part = result_line[idx_skipped:idx_failed]
+            failed_part = result_line[idx_failed:]
+            return (_testthat_parse_part(ok_part), _testthat_parse_part(skipped_part), _testthat_parse_part(failed_part))
+        raise Exception("Could not parse testthat status line {0}".format(result_line))
+
+def _testthat_parse_part(part):
+    '''
+    parses a part like "OK: 2"
+    '''
+    parts = part.split(":")
+    if len(parts) == 2:
+        assert parts[0] == "OK" or parts[0] == "SKIPPED" or parts[0] == "FAILED"
+        return int(parts[1])
+    raise Exception("could not parse testthat status part {0}".format(part))
+
+
 def _find_start(content):
     marker = "Type 'q()' to quit R."
     for i in range(len(content)):
@@ -507,14 +569,16 @@ def _find_start(content):
                 j = j + 1
     return None
 
+
 def _find_end(content):
     marker = "Time elapsed:"
     for i in range(len(content)):
         line = content[i]
         if marker in line:
-            return i - 1
+            return i
     # not all files have a Time elapsed:
-    return len(content) - 1
+    return len(content)
+
 
 def _find_line(gnur_line, fastr_content, fastr_i):
     '''
@@ -530,6 +594,7 @@ def _find_line(gnur_line, fastr_content, fastr_i):
         fastr_i = fastr_i + 1
     return -1
 
+
 def _replace_engine_references(output):
     for idx, val in enumerate(output):
         if "RUNIT TEST PROTOCOL -- " in val:
@@ -540,6 +605,14 @@ def _replace_engine_references(output):
             output[idx] = val.replace('fastr', '<engine>').replace('gnur', '<engine>')
 
 def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename):
+    '''
+    Compares the test output of GnuR and FastR by ignoring implementation-specific differences like header, error,
+    and warning messages.
+    It returns a 3-tuple (<status>, <statements passed>, <statements failed>), where status=0 if files are equal,
+    status=1 if the files are different, status=-1 if the files could not be compared. In case of status=1,
+    statements passed and statements failed give the numbers on how many statements produced the same or a different
+    output, respectively.
+    '''
     _replace_engine_references(gnur_content)
     _replace_engine_references(fastr_content)
     gnur_start = _find_start(gnur_content)
@@ -547,17 +620,40 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename):
     fastr_start = _find_start(fastr_content)
     fastr_len = len(fastr_content)
     if not gnur_start or not gnur_end or not fastr_start:
-        return -1
+        return -1, 0, 0
     gnur_i = gnur_start
     fastr_i = fastr_start
+    # the overall result for comparing the file
+    overall_result = 0
+    # the local result, i.e., for the current statement
     result = 0
+    statements_passed = set()
+    statements_failed = set()
+
+    # the first line must start with the prompt, so capture it
+    gnur_prompt = _capture_prompt(gnur_content, gnur_i)
+    fastr_prompt = _capture_prompt(fastr_content, fastr_i)
+
+    gnur_cur_statement_start = -1
+    fastr_cur_statement_start = -1
     while gnur_i < gnur_end:
         gnur_line = gnur_content[gnur_i]
         if fastr_i >= fastr_len:
-            result = 1
+            overall_result = 1
             break
 
         fastr_line = fastr_content[fastr_i]
+
+        # check if the current line starts a statement
+        if _is_statement_begin(gnur_prompt, gnur_line) and gnur_cur_statement_start != gnur_i:
+            gnur_cur_statement_start = gnur_i
+
+        # if we find a new statement begin
+        if _is_statement_begin(fastr_prompt, fastr_line) and fastr_cur_statement_start != fastr_i:
+            fastr_cur_statement_start = fastr_i
+
+        # flag indicating that we want to synchronize
+        sync = False
         if gnur_line != fastr_line:
             if fastr_line.startswith('Warning') and 'FastR does not support graphics package' in fastr_content[fastr_i + 1]:
                 # ignore warning about FastR not supporting the graphics package
@@ -576,7 +672,7 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename):
                 fastr_i = fastr_i + 1
                 continue
             # we are fuzzy on Error/Warning as FastR often differs
-            # in the context/format of the error/warniong message AND GnuR is sometimes
+            # in the context/format of the error/warning message AND GnuR is sometimes
             # inconsistent over which error message it uses. Unlike the unit test environment,
             # we cannot tag tests in any way, so we simply check that FastR does report
             # an error. We then scan forward to try to get the files back in sync, as the
@@ -585,43 +681,87 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename):
                 to_match = 'Error' if 'Error' in gnur_line else 'Warning'
                 if to_match not in fastr_line:
                     result = 1
-                    break
+                    # XXX do not break
+                    # break
                 else:
-                    # skip until lines match (or not)
-                    gnur_i = gnur_i + 1
-                    fastr_i = fastr_i + 1
-                    if gnur_i == gnur_end - 1:
-                        # at end (there is always a blank line)
-                        break
-                    ni = -1
-                    while gnur_i < gnur_end:
-                        ni = _find_line(gnur_content[gnur_i], fastr_content, fastr_i)
-                        if ni > 0:
-                            break
-                        gnur_i = gnur_i + 1
-                    if ni > 0:
-                        fastr_i = ni
-                        continue
-                    else:
-                        result = 1
-                        break
+                    # accept differences in the error/warning messages but we need to synchronize
+                    sync = True
+
             else:
                 # genuine difference (modulo whitespace)
                 if not _ignore_whitespace(gnur_line, fastr_line):
                     result = 1
-                    break
-        gnur_i = gnur_i + 1
-        fastr_i = fastr_i + 1
-    if result == 1:
+                    # XXX do not break, but we might need to synchronize indices
+                    # break
+
+
+        # report a mismatch or success
+        if result == 1:
+            # we need to synchronize the indices such that we can continue
+            sync = True
+            # report the last statement to produce different output
+            assert fastr_cur_statement_start != -1
+            if fastr_cur_statement_start in statements_passed:
+                statements_passed.remove(fastr_cur_statement_start)
+            statements_failed.add(fastr_cur_statement_start)
+        else:
+            assert result == 0
+            if fastr_cur_statement_start not in statements_failed:
+                statements_passed.add(fastr_cur_statement_start)
+
+        # synchronize: skip until lines match (or file end reached)
+        if sync:
+            gnur_i = gnur_i + 1
+            fastr_i = fastr_i + 1
+            if gnur_i == gnur_end - 1:
+                # at end (there is always a blank line)
+                break
+            ni = -1
+            # find next statement line (i.e. starting with a prompt)
+
+
+            while gnur_i < gnur_end:
+                if _is_statement_begin(gnur_prompt, gnur_content[gnur_i]):
+                    ni = _find_line(gnur_content[gnur_i], fastr_content, fastr_i)
+                    if ni > 0:
+                        break
+                gnur_i = gnur_i + 1
+            if ni > 0:
+                fastr_i = ni
+
+            overall_result = 1
+            result = 0
+        else:
+            # just advance by one line in FastR and GnuR
+            gnur_i = gnur_i + 1
+            fastr_i = fastr_i + 1
+
+    if overall_result == 1:
         print gnur_filename + ':%d' % gnur_i + ' vs. ' + fastr_filename + ':%d' % fastr_i
         print gnur_line.strip()
         print "vs."
         print fastr_line.strip()
-    return result
+    return overall_result, len(statements_passed), len(statements_failed)
+
 
 def _ignore_whitespace(gnur_line, fastr_line):
     return gnur_line.translate(None, ' \t') == fastr_line.translate(None, ' \t')
 
+
+def _capture_prompt(lines, idx):
+    # The prompt can be anything, so it is hard to determine it in general.
+    # We will therefore just consider the default prompt.
+    default_prompt = "> "
+    if idx < len(lines) and lines[idx].startswith(default_prompt):
+        return default_prompt
+    return None
+
+
+def _is_statement_begin(captured_prompt, line):
+    line_wo_prompt = line.replace(captured_prompt, "").strip()
+    return line.startswith(captured_prompt) and line_wo_prompt is not "" and not line_wo_prompt.startswith("#")
+
+
 def pkgtest_cmp(args):
     with open(args[0]) as f:
         gnur_content = f.readlines()
@@ -629,6 +769,7 @@ def pkgtest_cmp(args):
         fastr_content = f.readlines()
     return _fuzzy_compare(gnur_content, fastr_content, args[0], args[1])
 
+
 def find_top100(args):
     libinstall = join(_fastr_suite_dir(), "top100.tmp")
     if not os.path.exists(libinstall):
@@ -636,6 +777,7 @@ def find_top100(args):
     os.environ['R_LIBS_USER'] = libinstall
     _installpkgs(['--find-top100', '--use-installed-pkgs'])
 
+
 def remove_dup_pkgs(args):
     pkgs = args[0].split(",")
     x = dict()
@@ -646,6 +788,7 @@ def remove_dup_pkgs(args):
         result += p
     return result
 
+
 def computeApiChecksum(includeDir):
     '''
     Computes a checksum of the header files found in the provided directory (recursively).