galaaz 0.5.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/LICENSE +0 -0
- data/README.md +1360 -636
- data/Rakefile +61 -41
- data/bin/galaaz-bootstrap +137 -0
- data/bin/galaaz-jruby +14 -0
- data/bin/galaaz_jruby_env.inc.sh +6 -0
- data/bin/gbookdown +64 -0
- data/bin/gknit +84 -13
- data/bin/gknit-draft.rb +0 -0
- data/bin/gstudio +5 -3
- data/bin/gstudio_irb.rb +0 -0
- data/bin/gstudio_pry.rb +0 -0
- data/bin/install-tinytex +6 -0
- data/bin/run_all_rspec +43 -0
- data/bin/run_example +14 -0
- data/bin/run_old_rspec +19 -0
- data/bin/run_rspec +23 -0
- data/bin/run_rspec_subset +38 -0
- data/bin/run_slow_rspec +19 -0
- data/blogs/R-on-Rails-Planning-Document.md +940 -0
- data/blogs/README.md +100 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +38 -66
- data/blogs/galaaz_ggplot/galaaz_ggplot.log +754 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot.md +115 -155
- data/blogs/galaaz_ggplot/galaaz_ggplot.tex +607 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/midwest_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/scatter_plot_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/midwest_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/scatter_plot_rb.png +0 -0
- data/blogs/galaaz_ggplot/midwest.Rmd +3 -3
- data/blogs/galaaz_ggplot/midwest_external_png +0 -0
- data/blogs/gknit/gknit.Rmd +47 -52
- data/blogs/gknit/gknit.md +1430 -0
- data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
- data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
- data/blogs/gknit/lst.rds +0 -0
- data/blogs/gknit/model.rb +1 -1
- data/blogs/gknit/stats.bib +0 -0
- data/blogs/manual/include_model_local_repro.Rmd +14 -0
- data/blogs/manual/include_model_local_repro.md +75 -0
- data/blogs/manual/lst.rds +0 -0
- data/blogs/manual/manual.Rmd +852 -239
- data/blogs/manual/manual.log +1786 -0
- data/blogs/manual/manual.md +1360 -636
- data/blogs/manual/manual.tex +1883 -1161
- data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
- data/blogs/manual/manual_files/figure-html/diverging_bar.png +0 -0
- data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
- data/blogs/manual/model.rb +1 -1
- data/blogs/nse_dplyr/nse_dplyr.Rmd +84 -111
- data/blogs/nse_dplyr/nse_dplyr.log +928 -0
- data/blogs/nse_dplyr/nse_dplyr.md +198 -229
- data/blogs/oh_my/not_so.rb +0 -0
- data/blogs/oh_my/oh_my.Rmd +1234 -25
- data/blogs/oh_my/oh_my.log +804 -0
- data/blogs/oh_my/oh_my.md +1663 -86
- data/blogs/oh_my/oh_my.tex +821 -0
- data/blogs/oh_my/old.Rmd +15 -14
- data/blogs/ruby_plot/ruby_plot.Rmd +58 -82
- data/blogs/ruby_plot/ruby_plot.log +885 -0
- data/blogs/ruby_plot/ruby_plot.md +71 -102
- data/blogs/ruby_plot/ruby_plot.tex +940 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/dose_len.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
- data/blogs/test/test.Rmd +14 -0
- data/examples/50Plots_MasterList/Images/midwest-scatterplot.PNG +0 -0
- data/examples/50Plots_MasterList/ScatterPlot.rb +0 -0
- data/examples/50Plots_MasterList/scatter_plot.rb +0 -0
- data/examples/Bibliography/master.bib +0 -0
- data/examples/Bibliography/stats.bib +0 -0
- data/examples/R/calc.R +0 -0
- data/examples/R/java_interop.R +0 -0
- data/examples/bioconductor_deseq2_airway/Documentation/DESeq2-airway-walkthrough.md +56 -0
- data/examples/bioconductor_deseq2_airway/bench_galaaz_three_same_process.rb +53 -0
- data/examples/bioconductor_deseq2_airway/bench_r_three_same_process.R +34 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb +33 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz_optimized.rb +34 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_minimal.R +30 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_pipeline_for_bench.R +36 -0
- data/examples/islr/all.rb +13 -0
- data/examples/islr/ch2.spec.rb +37 -7
- data/examples/islr/ch3.spec.rb +11 -2
- data/examples/islr/ch3_boston.rb +27 -0
- data/examples/islr/ch3_multiple_regression.rb +0 -0
- data/examples/islr/ch6.spec.rb +24 -1
- data/examples/islr/x_y_rnorm.jpg +0 -0
- data/examples/latex_templates/Test-acm_article/acm_proc_article-sp.cls +0 -0
- data/examples/latex_templates/Test-acm_article/sigproc.bib +0 -0
- data/examples/latex_templates/Test-acs_article/acs-Test-acs_article.bib +0 -0
- data/examples/latex_templates/Test-acs_article/acs-my_output.bib +0 -0
- data/examples/latex_templates/Test-aea_article/BibFile.bib +0 -0
- data/examples/latex_templates/Test-aea_article/Test-aea_article.Rmd +0 -0
- data/examples/latex_templates/Test-aea_article/references.bib +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.Rmd +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.pdfsync +0 -0
- data/examples/latex_templates/Test-ieee_article/IEEEtran.bst +0 -0
- data/examples/latex_templates/Test-ieee_article/mybibfile.bib +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJournal.sty +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJreferences.bib +0 -0
- data/examples/latex_templates/Test-rjournal_article/Test-rjournal_article.Rmd +0 -0
- data/examples/misc/baseball.csv +0 -0
- data/examples/misc/ggplot.rb +3 -2
- data/examples/misc/moneyball.rb +0 -0
- data/examples/misc/subsetting.rb +0 -0
- data/examples/multithread_shards_to_r/shards_to_r.rb +67 -0
- data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/attend-grade-relationships.csv +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.Rmd +0 -0
- data/examples/rmarkdown/svm-xaringan-example/svm-xaringan-example.Rmd +0 -0
- data/examples/sthda_ggplot/README.md +0 -0
- data/examples/sthda_ggplot/RUN.md +41 -0
- data/examples/sthda_ggplot/all.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/density_gg.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_area.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_density.rb +2 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_dotplot.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_freqpoly.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_histogram.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/histogram_density.rb +0 -0
- data/examples/sthda_ggplot/one_variable_continuous/stat.rb +0 -0
- data/examples/sthda_ggplot/one_variable_discrete/bar.rb +0 -0
- data/examples/sthda_ggplot/qplots/box_violin_dot.rb +0 -0
- data/examples/sthda_ggplot/qplots/scatter_plots.rb +0 -0
- data/examples/sthda_ggplot/scatter_gg.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_bin2d.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_density2d.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_hex.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/geom_point.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/geom_smooth.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/misc.rb +0 -0
- data/examples/sthda_ggplot/two_variables_cont_function/geom_area.rb +4 -3
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_bar.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_boxplot.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_dotplot.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_jitter.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_line.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_violin.rb +0 -0
- data/examples/sthda_ggplot/two_variables_disc_disc/geom_jitter.rb +0 -0
- data/examples/sthda_ggplot/two_variables_error/geom_crossbar.rb +0 -0
- data/ext/new_bridge/Makefile +46 -0
- data/ext/new_bridge/galaaz_gatekeeper_phase0.cpp +12 -0
- data/ext/new_bridge/galaaz_gatekeeper_phase1.cpp +1639 -0
- data/lib/R_interface/galaaz_device.R +20 -0
- data/lib/R_interface/include_engine.R +109 -0
- data/lib/R_interface/new_bridge_adapter.rb +824 -0
- data/lib/R_interface/r.rb +177 -25
- data/lib/R_interface/r_arrow.rb +113 -0
- data/lib/R_interface/r_libs.R +3 -3
- data/lib/R_interface/r_methods.rb +13 -126
- data/lib/R_interface/r_module_s.rb +0 -0
- data/lib/R_interface/rbinary_operators.rb +20 -2
- data/lib/R_interface/rclosure.rb +5 -1
- data/lib/R_interface/rdata_frame.rb +34 -70
- data/lib/R_interface/rdevice.rb +125 -0
- data/lib/R_interface/rdevices.R +0 -0
- data/lib/R_interface/renvironment.rb +10 -4
- data/lib/R_interface/rexpression.rb +5 -1
- data/lib/R_interface/rindexed_object.rb +41 -13
- data/lib/R_interface/rlanguage.rb +20 -62
- data/lib/R_interface/rlist.rb +115 -25
- data/lib/R_interface/rlogical_operators.rb +0 -0
- data/lib/R_interface/rmatrix.rb +2 -11
- data/lib/R_interface/rmd_indexed_object.rb +5 -1
- data/lib/R_interface/robject.rb +348 -290
- data/lib/R_interface/rpkg.rb +0 -0
- data/lib/R_interface/rsupport.rb +609 -328
- data/lib/R_interface/rsupport_scope.rb +2 -1
- data/lib/R_interface/rsymbol.rb +50 -0
- data/lib/R_interface/ruby_callback.rb +2 -3
- data/lib/R_interface/ruby_extensions.rb +225 -175
- data/lib/R_interface/runary_operators.rb +0 -0
- data/lib/R_interface/rvector.rb +147 -31
- data/lib/galaaz.rb +0 -0
- data/lib/galaaz_jruby.rb +22 -0
- data/lib/gknit/diagnostics.rb +50 -0
- data/lib/gknit/draft.rb +23 -17
- data/lib/gknit/include_engine.rb +15 -7
- data/lib/gknit/knitr_engine.rb +223 -74
- data/lib/gknit/rb_engine.rb +3 -3
- data/lib/gknit/ruby_engine.rb +0 -0
- data/lib/gknit.rb +1 -0
- data/lib/new_bridge/bootstrap/windows_bootstrap.rb +285 -0
- data/lib/new_bridge/envelope.rb +51 -0
- data/lib/new_bridge/eval_result.rb +26 -0
- data/lib/new_bridge/framing.rb +39 -0
- data/lib/new_bridge/instance_pool_client.rb +38 -0
- data/lib/new_bridge/r_instance_manager.rb +404 -0
- data/lib/new_bridge/session_client.rb +530 -0
- data/lib/new_bridge/tcp_framed.rb +44 -0
- data/lib/new_bridge.rb +9 -0
- data/lib/util/exec_ruby.rb +95 -20
- data/lib/util/inline_file.rb +35 -30
- data/new_bridge_specs/benchmark_phase5_5_unboxing_spec.rb +96 -0
- data/new_bridge_specs/eval_r_async_spec.rb +113 -0
- data/new_bridge_specs/integration_phase5_1_concurrent_spec.rb +50 -0
- data/new_bridge_specs/integration_phase5_1_eval_spec.rb +16 -0
- data/new_bridge_specs/integration_phase5_1_r_api_spec.rb +25 -0
- data/new_bridge_specs/integration_phase5_1_smoke_spec.rb +31 -0
- data/new_bridge_specs/integration_phase5_2_dataframe_unboxing_spec.rb +19 -0
- data/new_bridge_specs/integration_phase5_2_handle_eval_unboxing_spec.rb +25 -0
- data/new_bridge_specs/integration_phase5_3_callback_args_spec.rb +28 -0
- data/new_bridge_specs/integration_phase5_3_callback_error_spec.rb +22 -0
- data/new_bridge_specs/integration_phase5_3_callback_timeout_spec.rb +28 -0
- data/new_bridge_specs/integration_phase5_3_callbacks_smoke_spec.rb +22 -0
- data/new_bridge_specs/integration_phase5_3_edge_cases_spec.rb +52 -0
- data/new_bridge_specs/integration_phase5_3_nested_spec.rb +30 -0
- data/new_bridge_specs/integration_phase5_4_concurrent_sessions_spec.rb +53 -0
- data/new_bridge_specs/integration_phase5_4_nested_session_callbacks_spec.rb +49 -0
- data/new_bridge_specs/integration_phase5_4_session_routing_spec.rb +38 -0
- data/new_bridge_specs/integration_phase5_5_stress_concurrency_spec.rb +52 -0
- data/new_bridge_specs/integration_phase5_5_unbox_walk_spec.rb +46 -0
- data/new_bridge_specs/phase0_protocol_spec.rb +96 -0
- data/new_bridge_specs/phase1_req_ret_spec.rb +66 -0
- data/new_bridge_specs/phase2_multi_instance_spec.rb +67 -0
- data/new_bridge_specs/phase3_callbacks_spec.rb +71 -0
- data/new_bridge_specs/phase4_2_hardening_spec.rb +252 -0
- data/new_bridge_specs/phase4_3_r_instance_manager_spec.rb +85 -0
- data/new_bridge_specs/phase4_nested_callbacks_spec.rb +123 -0
- data/r_requires/ggplot.rb +0 -0
- data/r_requires/knitr.rb +0 -0
- data/specs/all.rb +15 -11
- data/specs/arrow_from_ruby_batches_spec.rb +50 -0
- data/specs/arrow_semantics_spec.rb +64 -0
- data/specs/bridge_concurrent_spec.rb +46 -0
- data/specs/bridge_nested_spec.rb +25 -0
- data/specs/dataframe_semantics_spec.rb +122 -0
- data/specs/dataframe_single_index_logical_filter_spec.rb +21 -0
- data/specs/dispatch_probe_cache_spec.rb +38 -0
- data/specs/dispatch_probe_error_class_fallback_spec.rb +20 -0
- data/specs/dispatch_probe_fallback_spec.rb +18 -0
- data/specs/environment_semantics_spec.rb +89 -0
- data/specs/field_access_spec.rb +31 -0
- data/specs/figures/bg.jpeg +0 -0
- data/specs/figures/bg.png +0 -0
- data/specs/figures/bg.svg +168 -57
- data/specs/figures/dose_len.png +0 -0
- data/specs/figures/no_args.jpeg +0 -0
- data/specs/figures/no_args.png +0 -0
- data/specs/figures/no_args.svg +168 -57
- data/specs/figures/width_height.jpeg +0 -0
- data/specs/figures/width_height.png +0 -0
- data/specs/figures/width_height_units1.jpeg +0 -0
- data/specs/figures/width_height_units1.png +0 -0
- data/specs/figures/width_height_units2.jpeg +0 -0
- data/specs/figures/width_height_units2.png +0 -0
- data/specs/formula_semantics_spec.rb +81 -0
- data/specs/galaaz_util_exec_ruby_spec.rb +85 -0
- data/specs/galaaz_util_inline_file_spec.rb +54 -0
- data/specs/gknit_cli_option_permutation_spec.rb +24 -0
- data/specs/gknit_include_engine_spec.rb +72 -0
- data/specs/gknit_install_timeout_report_spec.rb +69 -0
- data/specs/gknit_internal_error_report_spec.rb +57 -0
- data/specs/gknit_vector_map_output_spec.rb +59 -0
- data/specs/globalenv_guardrail_spec.rb +52 -0
- data/specs/language_expression_semantics_spec.rb +145 -0
- data/specs/list_semantics_spec.rb +111 -0
- data/specs/new_bridge_bulk_dataframe_transfer_spec.rb +44 -0
- data/specs/new_bridge_bulk_vector_transfer_spec.rb +73 -0
- data/specs/new_bridge_callback_timeout_spec.rb +69 -0
- data/specs/new_bridge_eval_r_fallback_spec.rb +55 -0
- data/specs/nil_null_spec.rb +42 -0
- data/specs/object_build_phase2_spec.rb +53 -0
- data/specs/phase1_callback_bridge_spec.rb +84 -0
- data/specs/phase2_gknit_generic_rendering_guardrail_spec.rb +46 -0
- data/specs/phase2_gknit_no_raw_code_leakage_spec.rb +43 -0
- data/specs/phase3_gknit_generic_graphics_capture_spec.rb +71 -0
- data/specs/plot_device_semantics_spec.rb +28 -0
- data/specs/plot_snapshot_semantics_spec.rb +58 -0
- data/specs/protocol_result_spec.rb +236 -0
- data/specs/r_batch_fail_fast_spec.rb +47 -0
- data/specs/r_bridge_bootstrap_spec.rb +11 -0
- data/specs/r_devices.spec.rb +1 -1
- data/specs/r_eval.spec.rb +16 -18
- data/specs/r_function.spec.rb +1 -1
- data/specs/r_instance_manager_spec.rb +285 -0
- data/specs/r_list_apply.spec.rb +15 -15
- data/specs/r_matrix.spec.rb +0 -0
- data/specs/r_nse.spec.rb +5 -5
- data/specs/r_object_send_dispatch_spec.rb +13 -0
- data/specs/r_vector_comparator_spec.rb +8 -0
- data/specs/r_vector_creation.spec.rb +0 -0
- data/specs/r_vector_functions.spec.rb +0 -0
- data/specs/r_vector_object.spec.rb +0 -0
- data/specs/r_vector_operators.spec.rb +0 -0
- data/specs/r_vector_structured_scalar_reads_spec.rb +35 -0
- data/specs/r_vector_subsetting.spec.rb +0 -0
- data/specs/range_helper_spec.rb +21 -0
- data/specs/rsupport_scope_spec.rb +28 -0
- data/specs/rsupport_var_name_thread_safety_spec.rb +24 -0
- data/specs/scalar_character_spec.rb +44 -0
- data/specs/scoped_symbol_dsl_refinement_spec.rb +40 -0
- data/specs/session_env_bridge_spec.rb +25 -0
- data/specs/simplecov_bootstrap_spec.rb +10 -0
- data/specs/spec_helper.rb +10 -0
- data/specs/tmp.rb +0 -0
- data/specs/unboxing_recursion_regression_spec.rb +30 -0
- data/specs/unboxing_spec.rb +49 -0
- data/specs/verify_callbacks.rb +42 -0
- data/sty/galaaz.sty +0 -0
- data/version.rb +1 -1
- metadata +194 -64
- data/blogs/galaaz_ggplot/galaaz_ggplot.html +0 -520
- data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
- data/blogs/galaaz_ggplot/midwest.html +0 -188
- data/blogs/gknit/gknit.html +0 -2266
- data/blogs/gknit/gknit.pdf +0 -0
- data/blogs/manual/manual.html +0 -4638
- data/blogs/manual/manual.pdf +0 -0
- data/blogs/manual/manual_files/figure-latex/diverging_bar.pdf +0 -0
- data/blogs/nse_dplyr/nse_dplyr.html +0 -878
- data/blogs/nse_dplyr/nse_dplyr.pdf +0 -0
- data/blogs/oh_my/oh_my.html +0 -568
- data/blogs/ruby_plot/ruby_plot.html +0 -544
- data/blogs/ruby_plot/ruby_plot.pdf +0 -0
- data/examples/latex_templates/Test-acs_article/Test-acs_article.pdf +0 -0
- data/examples/latex_templates/Test-aea_article/Test-aea_article.pdf +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.pdf +0 -0
- data/examples/latex_templates/Test-amq_article/pics/Figure2.pdf +0 -0
- data/examples/latex_templates/Test-asa_article/Test-asa_article.pdf +0 -0
- data/examples/latex_templates/Test-ieee_article/Test-ieee_article.pdf +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJwrapper.pdf +0 -0
- data/examples/latex_templates/Test-springer_article/Test-springer_article.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.pdf +0 -0
- data/specs/r_dataframe.spec.rb +0 -379
- data/specs/r_environment.spec.rb +0 -140
- data/specs/r_formula.spec.rb +0 -232
- data/specs/r_language.spec.rb +0 -112
- data/specs/r_list.spec.rb +0 -293
- data/specs/r_plots.spec.rb +0 -72
- data/specs/ruby_expression.spec.rb +0 -316
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.3 callback error propagation on the R.bridge seam.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_3_callback_error_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require_relative '../lib/R_interface/r'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'Phase 5.3 integration callback error (R.bridge seam)' do
|
|
11
|
+
before(:all) do
|
|
12
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
13
|
+
R.bridge.eval_r('call_me <- function(f) { f() }')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'propagates Ruby callback failure through bridge call' do
|
|
17
|
+
expect do
|
|
18
|
+
R.call_me(proc { raise 'p53 callback boom' })
|
|
19
|
+
end.to raise_error(StandardError, /evaluation error|boom/)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.3 callback timeout behavior on the R.bridge seam.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_3_callback_timeout_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require_relative '../lib/R_interface/r'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'Phase 5.3 integration callback timeout (R.bridge seam)' do
|
|
11
|
+
before(:all) do
|
|
12
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
13
|
+
R.bridge.eval_r('call_me <- function(f) { f() }')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'raises when callback execution exceeds callback wait (GALAAZ_CALLBACK_TIMEOUT_MS)' do
|
|
17
|
+
old = ENV['GALAAZ_CALLBACK_TIMEOUT_MS']
|
|
18
|
+
ENV['GALAAZ_CALLBACK_TIMEOUT_MS'] = '2000'
|
|
19
|
+
begin
|
|
20
|
+
expect do
|
|
21
|
+
R.call_me(proc { sleep 5; 999 })
|
|
22
|
+
end.to raise_error(StandardError, /timeout|evaluation error|no RET/i)
|
|
23
|
+
ensure
|
|
24
|
+
ENV['GALAAZ_CALLBACK_TIMEOUT_MS'] = old
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.3 callback/proc stub smoke on the R.bridge seam.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_3_callbacks_smoke_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require_relative '../lib/R_interface/r'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'Phase 5.3 integration callbacks smoke (R.bridge seam)' do
|
|
11
|
+
before(:all) do
|
|
12
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'invokes a Ruby Proc from R and returns a scalar result' do
|
|
16
|
+
R.bridge.eval_r('call_me <- function(f) { f() }')
|
|
17
|
+
result = R.call_me(proc { 42.0 })
|
|
18
|
+
expect(result).to be_a(R::Object)
|
|
19
|
+
expect(result.to_ruby).to eq(42.0)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.3 callback edge cases on the R.bridge seam.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_3_edge_cases_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require_relative '../lib/R_interface/r'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'Phase 5.3 integration callback edge cases (R.bridge seam)' do
|
|
11
|
+
before(:all) do
|
|
12
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
13
|
+
R.bridge.eval_r('call_me <- function(f) { f() }')
|
|
14
|
+
R.bridge.eval_r('call_with_arg <- function(f, x) { f(x) }')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'supports callback proc with arity 2 receiving payload and call_id' do
|
|
18
|
+
result = R.call_with_arg(proc { |payload, call_id|
|
|
19
|
+
payload.to_i + (call_id.to_s.empty? ? 0 : 1)
|
|
20
|
+
}, 41)
|
|
21
|
+
|
|
22
|
+
expect(result).to be_a(R::Object)
|
|
23
|
+
expect(result.to_ruby).to eq(42.0)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'passes logical scalar argument through payload conversion' do
|
|
27
|
+
result = R.call_with_arg(proc { |x| x.to_ruby == true ? 7 : 0 }, true)
|
|
28
|
+
expect(result.to_ruby).to eq(7.0)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'keeps nested eval path available inside callback with arity 2' do
|
|
32
|
+
bridge = R.bridge
|
|
33
|
+
inner = nil
|
|
34
|
+
|
|
35
|
+
out = R.call_me(proc { |_payload, _call_id|
|
|
36
|
+
inner = bridge.eval_r_with_result('g2_v_p53_edge <- 55L')
|
|
37
|
+
9
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
expect(out).to be_a(R::Object)
|
|
41
|
+
expect(out.to_ruby).to eq(9.0)
|
|
42
|
+
expect(inner).not_to be_nil
|
|
43
|
+
expect(inner[:type]).to eq(:scalar_integer)
|
|
44
|
+
expect(inner[:value]).to eq(55)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'passes non-scalar callback arguments as a single R::Object' do
|
|
48
|
+
result = R.call_with_arg(proc { |x| x.to_s.empty? ? 1 : 0 }, R.c(1, 2, 3))
|
|
49
|
+
expect(result.to_ruby).to eq(0.0)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.3 nested callback integration on the R.bridge seam.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_3_nested_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require_relative '../lib/R_interface/r'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'Phase 5.3 integration nested callbacks (R.bridge seam)' do
|
|
11
|
+
before(:all) do
|
|
12
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'supports nested eval_r_with_result from inside callback and returns correct values' do
|
|
16
|
+
bridge = R.bridge
|
|
17
|
+
inner_envelope = nil
|
|
18
|
+
|
|
19
|
+
result = R.lapply(R.c(1), proc do |_x|
|
|
20
|
+
inner_envelope = bridge.eval_r_with_result('g2_v_inner <- 200L')
|
|
21
|
+
33
|
|
22
|
+
end)
|
|
23
|
+
|
|
24
|
+
expect(inner_envelope).not_to be_nil
|
|
25
|
+
expect(inner_envelope[:type]).to eq(:scalar_integer)
|
|
26
|
+
expect(inner_envelope[:value]).to eq(200)
|
|
27
|
+
expect(result).to be_a(R::Object)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.4 concurrent session routing integration on the R.bridge seam.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_4_concurrent_sessions_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require_relative '../lib/R_interface/r'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'Phase 5.4 integration concurrent sessions (R.bridge seam)' do
|
|
11
|
+
before(:all) do
|
|
12
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'isolates writes and reads per session under concurrency' do
|
|
16
|
+
bridge = R.bridge
|
|
17
|
+
expect(bridge).to respond_to(:with_session)
|
|
18
|
+
|
|
19
|
+
n_threads = 6
|
|
20
|
+
rounds = 8
|
|
21
|
+
values = Queue.new
|
|
22
|
+
errors = Queue.new
|
|
23
|
+
|
|
24
|
+
threads = n_threads.times.map do |tid|
|
|
25
|
+
Thread.new do
|
|
26
|
+
session = "sess-#{tid}"
|
|
27
|
+
rounds.times do |r|
|
|
28
|
+
expected = (tid * 100) + r
|
|
29
|
+
begin
|
|
30
|
+
got = bridge.with_session(session) do
|
|
31
|
+
bridge.eval_r_with_result("g2_v_slot <- #{expected}L")
|
|
32
|
+
bridge.eval_r_with_result('g2_v_read <- g2_v_slot')[:value]
|
|
33
|
+
end
|
|
34
|
+
values << [session, r, got, expected]
|
|
35
|
+
rescue => e
|
|
36
|
+
errors << [session, r, e.class.name, e.message]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
threads.each(&:join)
|
|
43
|
+
|
|
44
|
+
expect(errors.size).to eq(0), "errors: #{errors.size}"
|
|
45
|
+
expect(values.size).to eq(n_threads * rounds)
|
|
46
|
+
|
|
47
|
+
until values.empty?
|
|
48
|
+
_session, _r, got, expected = values.pop(true) rescue break
|
|
49
|
+
expect(got).to eq(expected)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.4 nested callback + session scoping integration.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_4_nested_session_callbacks_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require_relative '../lib/R_interface/r'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'Phase 5.4 integration nested callbacks with session scoping' do
|
|
11
|
+
before(:all) do
|
|
12
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'keeps nested callback writes isolated to the active session' do
|
|
16
|
+
bridge = R.bridge
|
|
17
|
+
expect(bridge).to respond_to(:with_session)
|
|
18
|
+
|
|
19
|
+
out_a = bridge.with_session('nested-sess-a') do
|
|
20
|
+
bridge.eval_r('call_me <- function(f) { f() }')
|
|
21
|
+
R.call_me(proc do |_payload, _call_id|
|
|
22
|
+
bridge.eval_r_with_result('g2_v_ns <- 111L')
|
|
23
|
+
bridge.eval_r_with_result('g2_v_read <- g2_v_ns')[:value]
|
|
24
|
+
end)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
out_b = bridge.with_session('nested-sess-b') do
|
|
28
|
+
bridge.eval_r('call_me <- function(f) { f() }')
|
|
29
|
+
R.call_me(proc do |_payload, _call_id|
|
|
30
|
+
bridge.eval_r_with_result('g2_v_ns <- 222L')
|
|
31
|
+
bridge.eval_r_with_result('g2_v_read <- g2_v_ns')[:value]
|
|
32
|
+
end)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
read_a = bridge.with_session('nested-sess-a') do
|
|
36
|
+
bridge.eval_r_with_result('g2_v_read <- g2_v_ns')[:value]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
read_b = bridge.with_session('nested-sess-b') do
|
|
40
|
+
bridge.eval_r_with_result('g2_v_read <- g2_v_ns')[:value]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
expect(out_a).to be_a(R::Object)
|
|
44
|
+
expect(out_b).to be_a(R::Object)
|
|
45
|
+
expect(read_a).to eq(111)
|
|
46
|
+
expect(read_b).to eq(222)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.4 session routing integration on the R.bridge seam.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_4_session_routing_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require_relative '../lib/R_interface/r'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'Phase 5.4 integration session routing (R.bridge seam)' do
|
|
11
|
+
before(:all) do
|
|
12
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'keeps same handle name isolated across sessions' do
|
|
16
|
+
bridge = R.bridge
|
|
17
|
+
expect(bridge).to respond_to(:with_session)
|
|
18
|
+
|
|
19
|
+
a_value = bridge.with_session('sess-a') do
|
|
20
|
+
bridge.eval_r_with_result('g2_v_shared <- 10L')
|
|
21
|
+
bridge.eval_r_with_result('g2_v_read <- g2_v_shared')[:value]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
b_value = bridge.with_session('sess-b') do
|
|
25
|
+
bridge.eval_r_with_result('g2_v_shared <- 20L')
|
|
26
|
+
bridge.eval_r_with_result('g2_v_read <- g2_v_shared')[:value]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
again_a = bridge.with_session('sess-a') do
|
|
30
|
+
bridge.eval_r_with_result('g2_v_read <- g2_v_shared')[:value]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
expect(a_value).to eq(10)
|
|
34
|
+
expect(b_value).to eq(20)
|
|
35
|
+
expect(again_a).to eq(10)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.5 stress-level concurrency integration on the R.bridge seam.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_5_stress_concurrency_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require_relative '../lib/R_interface/r'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'Phase 5.5 integration stress concurrency (R.bridge seam)' do
|
|
11
|
+
before(:all) do
|
|
12
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'maintains session isolation under higher concurrent load' do
|
|
16
|
+
bridge = R.bridge
|
|
17
|
+
expect(bridge).to respond_to(:with_session)
|
|
18
|
+
|
|
19
|
+
n_threads = 12
|
|
20
|
+
rounds = 20
|
|
21
|
+
errors = Queue.new
|
|
22
|
+
ok_count = Queue.new
|
|
23
|
+
|
|
24
|
+
threads = n_threads.times.map do |tid|
|
|
25
|
+
Thread.new do
|
|
26
|
+
session = "stress-sess-#{tid}"
|
|
27
|
+
rounds.times do |r|
|
|
28
|
+
expected = (tid * 10_000) + r
|
|
29
|
+
begin
|
|
30
|
+
got = bridge.with_session(session) do
|
|
31
|
+
bridge.eval_r_with_result("g2_v_stress <- #{expected}L")
|
|
32
|
+
bridge.eval_r_with_result('g2_v_read <- g2_v_stress')[:value]
|
|
33
|
+
end
|
|
34
|
+
if got == expected
|
|
35
|
+
ok_count << true
|
|
36
|
+
else
|
|
37
|
+
errors << [session, r, :mismatch, got, expected]
|
|
38
|
+
end
|
|
39
|
+
rescue => e
|
|
40
|
+
errors << [session, r, e.class.name, e.message]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
threads.each(&:join)
|
|
47
|
+
|
|
48
|
+
expect(errors.size).to eq(0), "errors=#{errors.size}"
|
|
49
|
+
expect(ok_count.size).to eq(n_threads * rounds)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 5.5 specialized unbox_walk traversal semantics.
|
|
4
|
+
# Run:
|
|
5
|
+
# bin/run_rspec specs/new_bridge/integration_phase5_5_unbox_walk_spec.rb
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
require 'timeout'
|
|
9
|
+
require_relative '../lib/R_interface/r'
|
|
10
|
+
|
|
11
|
+
RSpec.describe 'Phase 5.5 integration unbox_walk (R.bridge seam)' do
|
|
12
|
+
before(:all) do
|
|
13
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'reports depth_limit for deeply nested lists in one probe call' do
|
|
17
|
+
bridge = R.bridge
|
|
18
|
+
expect(bridge).to respond_to(:unbox_walk)
|
|
19
|
+
|
|
20
|
+
deep = R.list(1)
|
|
21
|
+
(R::Support::MAX_UNBOX_DEPTH + 10).times { deep = R.list(deep) }
|
|
22
|
+
|
|
23
|
+
result = Timeout.timeout(10) do
|
|
24
|
+
bridge.unbox_walk(deep.r_interop,
|
|
25
|
+
max_depth: R::Support::MAX_UNBOX_DEPTH,
|
|
26
|
+
max_nodes: 300_000)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
expect(result[:status]).to eq(:depth_limit)
|
|
30
|
+
expect(result[:max_depth]).to be > R::Support::MAX_UNBOX_DEPTH
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'materializes nested list/scalar trees in one call when supported' do
|
|
34
|
+
bridge = R.bridge
|
|
35
|
+
expect(bridge).to respond_to(:unbox_materialize)
|
|
36
|
+
|
|
37
|
+
tree = R.list(R.list(1, 2), R.list(3, 4))
|
|
38
|
+
result = bridge.unbox_materialize(tree.r_interop,
|
|
39
|
+
max_depth: R::Support::MAX_UNBOX_DEPTH,
|
|
40
|
+
max_nodes: 300_000)
|
|
41
|
+
|
|
42
|
+
expect(result[:status]).to eq(:ok)
|
|
43
|
+
expect(result[:value]).to eq([[1, 2], [3, 4]])
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 0: envelope (MsgPack), framing, TCP echo, Rcpp load smoke test.
|
|
4
|
+
# Run: bundle exec rspec specs/new_bridge/phase0_protocol_spec.rb
|
|
5
|
+
|
|
6
|
+
require 'open3'
|
|
7
|
+
require 'tempfile'
|
|
8
|
+
|
|
9
|
+
root = File.expand_path('../..', __dir__)
|
|
10
|
+
$LOAD_PATH.unshift(File.join(root, 'lib')) unless $LOAD_PATH.include?(File.join(root, 'lib'))
|
|
11
|
+
|
|
12
|
+
require 'new_bridge'
|
|
13
|
+
|
|
14
|
+
RSpec.describe 'NewBridge Phase 0' do
|
|
15
|
+
describe NewBridge::Envelope do
|
|
16
|
+
let(:sample) do
|
|
17
|
+
{
|
|
18
|
+
'call_id' => '550e8400-e29b-41d4-a716-446655440000',
|
|
19
|
+
'parent_id' => nil,
|
|
20
|
+
'type' => 'REQ',
|
|
21
|
+
'payload' => '1 + 1',
|
|
22
|
+
'status' => nil
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'round-trips encode/decode' do
|
|
27
|
+
bytes = described_class.encode(sample)
|
|
28
|
+
out = described_class.decode(bytes)
|
|
29
|
+
expect(out['call_id']).to eq(sample['call_id'])
|
|
30
|
+
expect(out['type']).to eq('REQ')
|
|
31
|
+
expect(out['payload']).to eq('1 + 1')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'raises on invalid MsgPack' do
|
|
35
|
+
expect { described_class.decode("\xff\xff\xff") }.to raise_error(NewBridge::Envelope::Error, /invalid MsgPack/)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'raises on missing required keys' do
|
|
39
|
+
bad = MessagePack.pack('foo' => 'bar')
|
|
40
|
+
expect { described_class.decode(bad) }.to raise_error(NewBridge::Envelope::InvalidEnvelope, /missing keys/)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe NewBridge::Framing do
|
|
45
|
+
it 'writes and reads one frame' do
|
|
46
|
+
io = StringIO.new(+'', 'r+')
|
|
47
|
+
payload = NewBridge::Envelope.encode(
|
|
48
|
+
'call_id' => 'a',
|
|
49
|
+
'type' => 'REQ',
|
|
50
|
+
'payload' => 'x'
|
|
51
|
+
)
|
|
52
|
+
described_class.write_frame(io, payload)
|
|
53
|
+
io.rewind
|
|
54
|
+
back = described_class.read_frame(io)
|
|
55
|
+
expect(back).to eq(payload)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'raises TruncatedFrame on short length prefix' do
|
|
59
|
+
io = StringIO.new("\x02\x00\x00\x00a", 'r') # length 2, only 1 byte body
|
|
60
|
+
expect { described_class.read_frame(io) }.to raise_error(NewBridge::Framing::TruncatedFrame)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe NewBridge::TcpFramed do
|
|
65
|
+
it 'echoes one framed payload over TCP' do
|
|
66
|
+
payload = NewBridge::Envelope.encode('call_id' => 'b', 'type' => 'REQ', 'payload' => 'ok')
|
|
67
|
+
NewBridge::TcpFramed.with_echo_server do |port|
|
|
68
|
+
back = NewBridge::TcpFramed.send_receive('127.0.0.1', port, payload)
|
|
69
|
+
expect(back).to eq(payload)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe 'Rcpp phase0 skeleton' do
|
|
75
|
+
cpp_path = File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase0.cpp', __dir__)
|
|
76
|
+
|
|
77
|
+
it 'loads via sourceCpp and runs galaaz_poll / galaaz_shutdown without hanging' do
|
|
78
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
79
|
+
|
|
80
|
+
cpp = cpp_path.gsub("'", "\\\\'")
|
|
81
|
+
r_script = <<~R
|
|
82
|
+
stopifnot(requireNamespace("Rcpp", quietly = TRUE))
|
|
83
|
+
library(Rcpp)
|
|
84
|
+
sourceCpp("#{cpp}")
|
|
85
|
+
p <- galaaz_poll()
|
|
86
|
+
stopifnot(length(p) == 0L)
|
|
87
|
+
galaaz_shutdown()
|
|
88
|
+
cat("PHASE0_RCPP_OK\\n")
|
|
89
|
+
R
|
|
90
|
+
|
|
91
|
+
stdout, stderr, status = Open3.capture3('R', '--slave', '--no-save', '-e', r_script)
|
|
92
|
+
expect(status.success?).to eq(true), "R failed:\nSTDOUT:\n#{stdout}\nSTDERR:\n#{stderr}"
|
|
93
|
+
expect(stdout).to include('PHASE0_RCPP_OK')
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 1: REQ/RET, per-session env, concurrency. Run: bundle exec rspec specs/new_bridge/phase1_req_ret_spec.rb
|
|
4
|
+
|
|
5
|
+
root = File.expand_path('../..', __dir__)
|
|
6
|
+
$LOAD_PATH.unshift(File.join(root, 'lib')) unless $LOAD_PATH.include?(File.join(root, 'lib'))
|
|
7
|
+
|
|
8
|
+
require 'new_bridge'
|
|
9
|
+
|
|
10
|
+
RSpec.describe 'NewBridge Phase 1 REQ/RET' do
|
|
11
|
+
let(:phase1_cpp) { File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase1.cpp', __dir__) }
|
|
12
|
+
|
|
13
|
+
before(:all) do
|
|
14
|
+
skip 'R not on PATH' unless system('command -v R >/dev/null 2>&1')
|
|
15
|
+
cpp = File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase1.cpp', __dir__)
|
|
16
|
+
@client = NewBridge::SessionClient.new(source_path: cpp)
|
|
17
|
+
@client.start
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
after(:all) do
|
|
21
|
+
@client&.stop
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def with_client
|
|
25
|
+
yield @client
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'evaluates 1+1 as integer 2' do
|
|
29
|
+
with_client do |c|
|
|
30
|
+
out = c.eval_r('1L + 1L')
|
|
31
|
+
expect(out['kind']).to eq('integer')
|
|
32
|
+
expect(out['value']).to eq(2)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'returns double scalar' do
|
|
37
|
+
with_client do |c|
|
|
38
|
+
out = c.eval_r('1.5 + 1')
|
|
39
|
+
expect(out['kind']).to eq('double')
|
|
40
|
+
expect(out['value']).to be_within(1e-9).of(2.5)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'isolates variables per session_id' do
|
|
45
|
+
with_client do |c|
|
|
46
|
+
c.eval_r('x <- 42L', session_id: 'sess-a')
|
|
47
|
+
c.eval_r('x <- 99L', session_id: 'sess-b')
|
|
48
|
+
expect(c.eval_r('x', session_id: 'sess-a')['value']).to eq(42)
|
|
49
|
+
expect(c.eval_r('x', session_id: 'sess-b')['value']).to eq(99)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'handles 10 concurrent Ruby threads with distinct sessions' do
|
|
54
|
+
with_client do |c|
|
|
55
|
+
threads = 10.times.map do |i|
|
|
56
|
+
Thread.new do
|
|
57
|
+
sid = "thr-#{i}"
|
|
58
|
+
c.eval_r("y <- #{i}L", session_id: sid)
|
|
59
|
+
c.eval_r('y', session_id: sid)['value']
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
values = threads.map(&:value)
|
|
63
|
+
expect(values.sort).to eq((0..9).to_a)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Phase 2: multi-instance correctness and isolation.
|
|
4
|
+
# Run: bundle exec rspec specs/new_bridge/phase2_multi_instance_spec.rb
|
|
5
|
+
|
|
6
|
+
root = File.expand_path('../..', __dir__)
|
|
7
|
+
$LOAD_PATH.unshift(File.join(root, 'lib')) unless $LOAD_PATH.include?(File.join(root, 'lib'))
|
|
8
|
+
|
|
9
|
+
require 'new_bridge'
|
|
10
|
+
|
|
11
|
+
RSpec.describe 'NewBridge Phase 2 (REQ/RET Multi-instance)' do
|
|
12
|
+
before(:all) do
|
|
13
|
+
cpp_path = File.expand_path('../ext/new_bridge/galaaz_gatekeeper_phase1.cpp', __dir__)
|
|
14
|
+
@pool = NewBridge::InstancePoolClient.new(
|
|
15
|
+
source_path: cpp_path,
|
|
16
|
+
instances: ['instance-a', 'instance-b']
|
|
17
|
+
).start
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
after(:all) do
|
|
21
|
+
@pool&.stop
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'multi-instance correctness: same session_id on different instances stays isolated' do
|
|
25
|
+
@pool.eval_r('x <- 11L', session_id: 'shared-session', instance_id: 'instance-a')
|
|
26
|
+
@pool.eval_r('x <- 22L', session_id: 'shared-session', instance_id: 'instance-b')
|
|
27
|
+
|
|
28
|
+
a_val = @pool.eval_r('x', session_id: 'shared-session', instance_id: 'instance-a')
|
|
29
|
+
b_val = @pool.eval_r('x', session_id: 'shared-session', instance_id: 'instance-b')
|
|
30
|
+
|
|
31
|
+
expect(a_val['value']).to eq(11)
|
|
32
|
+
expect(b_val['value']).to eq(22)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'instance isolation under concurrency with distinct session_ids' do
|
|
36
|
+
threads = 20.times.map do |i|
|
|
37
|
+
Thread.new do
|
|
38
|
+
sid = "sess-#{i}"
|
|
39
|
+
inst = (i.even? ? 'instance-a' : 'instance-b')
|
|
40
|
+
@pool.eval_r("y <- #{i}L; y", session_id: sid, instance_id: inst)['value']
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
values = threads.map(&:value)
|
|
45
|
+
expect(values.sort).to eq((0..19).to_a)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'stress (light): many REQ calls across the pool' do
|
|
49
|
+
count = 100
|
|
50
|
+
threads = 10.times.map do |t|
|
|
51
|
+
Thread.new do
|
|
52
|
+
start_i = t * (count / 10)
|
|
53
|
+
end_i = start_i + (count / 10) - 1
|
|
54
|
+
inst = (t.even? ? 'instance-a' : 'instance-b')
|
|
55
|
+
|
|
56
|
+
(start_i..end_i).map do |i|
|
|
57
|
+
sid = "stress-sess-#{t}-#{i}"
|
|
58
|
+
@pool.eval_r("z <- #{i}L; z", session_id: sid, instance_id: inst)['value']
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
values = threads.flat_map(&:value)
|
|
64
|
+
expect(values.sort).to eq((0..(count - 1)).to_a)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|