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).