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.
Files changed (359) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/LICENSE +0 -0
  4. data/README.md +1360 -636
  5. data/Rakefile +61 -41
  6. data/bin/galaaz-bootstrap +137 -0
  7. data/bin/galaaz-jruby +14 -0
  8. data/bin/galaaz_jruby_env.inc.sh +6 -0
  9. data/bin/gbookdown +64 -0
  10. data/bin/gknit +84 -13
  11. data/bin/gknit-draft.rb +0 -0
  12. data/bin/gstudio +5 -3
  13. data/bin/gstudio_irb.rb +0 -0
  14. data/bin/gstudio_pry.rb +0 -0
  15. data/bin/install-tinytex +6 -0
  16. data/bin/run_all_rspec +43 -0
  17. data/bin/run_example +14 -0
  18. data/bin/run_old_rspec +19 -0
  19. data/bin/run_rspec +23 -0
  20. data/bin/run_rspec_subset +38 -0
  21. data/bin/run_slow_rspec +19 -0
  22. data/blogs/R-on-Rails-Planning-Document.md +940 -0
  23. data/blogs/README.md +100 -0
  24. data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +38 -66
  25. data/blogs/galaaz_ggplot/galaaz_ggplot.log +754 -0
  26. data/blogs/galaaz_ggplot/galaaz_ggplot.md +115 -155
  27. data/blogs/galaaz_ggplot/galaaz_ggplot.tex +607 -0
  28. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/midwest_rb.png +0 -0
  29. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/scatter_plot_rb.png +0 -0
  30. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/midwest_rb.png +0 -0
  31. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/scatter_plot_rb.png +0 -0
  32. data/blogs/galaaz_ggplot/midwest.Rmd +3 -3
  33. data/blogs/galaaz_ggplot/midwest_external_png +0 -0
  34. data/blogs/gknit/gknit.Rmd +47 -52
  35. data/blogs/gknit/gknit.md +1430 -0
  36. data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
  37. data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
  38. data/blogs/gknit/lst.rds +0 -0
  39. data/blogs/gknit/model.rb +1 -1
  40. data/blogs/gknit/stats.bib +0 -0
  41. data/blogs/manual/include_model_local_repro.Rmd +14 -0
  42. data/blogs/manual/include_model_local_repro.md +75 -0
  43. data/blogs/manual/lst.rds +0 -0
  44. data/blogs/manual/manual.Rmd +852 -239
  45. data/blogs/manual/manual.log +1786 -0
  46. data/blogs/manual/manual.md +1360 -636
  47. data/blogs/manual/manual.tex +1883 -1161
  48. data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
  49. data/blogs/manual/manual_files/figure-html/diverging_bar.png +0 -0
  50. data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
  51. data/blogs/manual/model.rb +1 -1
  52. data/blogs/nse_dplyr/nse_dplyr.Rmd +84 -111
  53. data/blogs/nse_dplyr/nse_dplyr.log +928 -0
  54. data/blogs/nse_dplyr/nse_dplyr.md +198 -229
  55. data/blogs/oh_my/not_so.rb +0 -0
  56. data/blogs/oh_my/oh_my.Rmd +1234 -25
  57. data/blogs/oh_my/oh_my.log +804 -0
  58. data/blogs/oh_my/oh_my.md +1663 -86
  59. data/blogs/oh_my/oh_my.tex +821 -0
  60. data/blogs/oh_my/old.Rmd +15 -14
  61. data/blogs/ruby_plot/ruby_plot.Rmd +58 -82
  62. data/blogs/ruby_plot/ruby_plot.log +885 -0
  63. data/blogs/ruby_plot/ruby_plot.md +71 -102
  64. data/blogs/ruby_plot/ruby_plot.tex +940 -0
  65. data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.png +0 -0
  66. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.png +0 -0
  67. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.png +0 -0
  68. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.png +0 -0
  69. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.png +0 -0
  70. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
  71. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
  72. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.png +0 -0
  73. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.png +0 -0
  74. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
  75. data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
  76. data/blogs/ruby_plot/ruby_plot_files/figure-latex/dose_len.png +0 -0
  77. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
  78. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
  79. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
  80. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
  81. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
  82. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
  83. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
  84. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
  85. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
  86. data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
  87. data/blogs/test/test.Rmd +14 -0
  88. data/examples/50Plots_MasterList/Images/midwest-scatterplot.PNG +0 -0
  89. data/examples/50Plots_MasterList/ScatterPlot.rb +0 -0
  90. data/examples/50Plots_MasterList/scatter_plot.rb +0 -0
  91. data/examples/Bibliography/master.bib +0 -0
  92. data/examples/Bibliography/stats.bib +0 -0
  93. data/examples/R/calc.R +0 -0
  94. data/examples/R/java_interop.R +0 -0
  95. data/examples/bioconductor_deseq2_airway/Documentation/DESeq2-airway-walkthrough.md +56 -0
  96. data/examples/bioconductor_deseq2_airway/bench_galaaz_three_same_process.rb +53 -0
  97. data/examples/bioconductor_deseq2_airway/bench_r_three_same_process.R +34 -0
  98. data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb +33 -0
  99. data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz_optimized.rb +34 -0
  100. data/examples/bioconductor_deseq2_airway/deseq2_airway_minimal.R +30 -0
  101. data/examples/bioconductor_deseq2_airway/deseq2_airway_pipeline_for_bench.R +36 -0
  102. data/examples/islr/all.rb +13 -0
  103. data/examples/islr/ch2.spec.rb +37 -7
  104. data/examples/islr/ch3.spec.rb +11 -2
  105. data/examples/islr/ch3_boston.rb +27 -0
  106. data/examples/islr/ch3_multiple_regression.rb +0 -0
  107. data/examples/islr/ch6.spec.rb +24 -1
  108. data/examples/islr/x_y_rnorm.jpg +0 -0
  109. data/examples/latex_templates/Test-acm_article/acm_proc_article-sp.cls +0 -0
  110. data/examples/latex_templates/Test-acm_article/sigproc.bib +0 -0
  111. data/examples/latex_templates/Test-acs_article/acs-Test-acs_article.bib +0 -0
  112. data/examples/latex_templates/Test-acs_article/acs-my_output.bib +0 -0
  113. data/examples/latex_templates/Test-aea_article/BibFile.bib +0 -0
  114. data/examples/latex_templates/Test-aea_article/Test-aea_article.Rmd +0 -0
  115. data/examples/latex_templates/Test-aea_article/references.bib +0 -0
  116. data/examples/latex_templates/Test-amq_article/Test-amq_article.Rmd +0 -0
  117. data/examples/latex_templates/Test-amq_article/Test-amq_article.pdfsync +0 -0
  118. data/examples/latex_templates/Test-ieee_article/IEEEtran.bst +0 -0
  119. data/examples/latex_templates/Test-ieee_article/mybibfile.bib +0 -0
  120. data/examples/latex_templates/Test-rjournal_article/RJournal.sty +0 -0
  121. data/examples/latex_templates/Test-rjournal_article/RJreferences.bib +0 -0
  122. data/examples/latex_templates/Test-rjournal_article/Test-rjournal_article.Rmd +0 -0
  123. data/examples/misc/baseball.csv +0 -0
  124. data/examples/misc/ggplot.rb +3 -2
  125. data/examples/misc/moneyball.rb +0 -0
  126. data/examples/misc/subsetting.rb +0 -0
  127. data/examples/multithread_shards_to_r/shards_to_r.rb +67 -0
  128. data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.Rmd +0 -0
  129. data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.Rmd +0 -0
  130. data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.Rmd +0 -0
  131. data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.Rmd +0 -0
  132. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/attend-grade-relationships.csv +0 -0
  133. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.Rmd +0 -0
  134. data/examples/rmarkdown/svm-xaringan-example/svm-xaringan-example.Rmd +0 -0
  135. data/examples/sthda_ggplot/README.md +0 -0
  136. data/examples/sthda_ggplot/RUN.md +41 -0
  137. data/examples/sthda_ggplot/all.rb +0 -0
  138. data/examples/sthda_ggplot/one_variable_continuous/density_gg.rb +0 -0
  139. data/examples/sthda_ggplot/one_variable_continuous/geom_area.rb +0 -0
  140. data/examples/sthda_ggplot/one_variable_continuous/geom_density.rb +2 -0
  141. data/examples/sthda_ggplot/one_variable_continuous/geom_dotplot.rb +0 -0
  142. data/examples/sthda_ggplot/one_variable_continuous/geom_freqpoly.rb +0 -0
  143. data/examples/sthda_ggplot/one_variable_continuous/geom_histogram.rb +0 -0
  144. data/examples/sthda_ggplot/one_variable_continuous/histogram_density.rb +0 -0
  145. data/examples/sthda_ggplot/one_variable_continuous/stat.rb +0 -0
  146. data/examples/sthda_ggplot/one_variable_discrete/bar.rb +0 -0
  147. data/examples/sthda_ggplot/qplots/box_violin_dot.rb +0 -0
  148. data/examples/sthda_ggplot/qplots/scatter_plots.rb +0 -0
  149. data/examples/sthda_ggplot/scatter_gg.rb +0 -0
  150. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_bin2d.rb +0 -0
  151. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_density2d.rb +0 -0
  152. data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_hex.rb +0 -0
  153. data/examples/sthda_ggplot/two_variables_cont_cont/geom_point.rb +0 -0
  154. data/examples/sthda_ggplot/two_variables_cont_cont/geom_smooth.rb +0 -0
  155. data/examples/sthda_ggplot/two_variables_cont_cont/misc.rb +0 -0
  156. data/examples/sthda_ggplot/two_variables_cont_function/geom_area.rb +4 -3
  157. data/examples/sthda_ggplot/two_variables_disc_cont/geom_bar.rb +0 -0
  158. data/examples/sthda_ggplot/two_variables_disc_cont/geom_boxplot.rb +0 -0
  159. data/examples/sthda_ggplot/two_variables_disc_cont/geom_dotplot.rb +0 -0
  160. data/examples/sthda_ggplot/two_variables_disc_cont/geom_jitter.rb +0 -0
  161. data/examples/sthda_ggplot/two_variables_disc_cont/geom_line.rb +0 -0
  162. data/examples/sthda_ggplot/two_variables_disc_cont/geom_violin.rb +0 -0
  163. data/examples/sthda_ggplot/two_variables_disc_disc/geom_jitter.rb +0 -0
  164. data/examples/sthda_ggplot/two_variables_error/geom_crossbar.rb +0 -0
  165. data/ext/new_bridge/Makefile +46 -0
  166. data/ext/new_bridge/galaaz_gatekeeper_phase0.cpp +12 -0
  167. data/ext/new_bridge/galaaz_gatekeeper_phase1.cpp +1639 -0
  168. data/lib/R_interface/galaaz_device.R +20 -0
  169. data/lib/R_interface/include_engine.R +109 -0
  170. data/lib/R_interface/new_bridge_adapter.rb +824 -0
  171. data/lib/R_interface/r.rb +177 -25
  172. data/lib/R_interface/r_arrow.rb +113 -0
  173. data/lib/R_interface/r_libs.R +3 -3
  174. data/lib/R_interface/r_methods.rb +13 -126
  175. data/lib/R_interface/r_module_s.rb +0 -0
  176. data/lib/R_interface/rbinary_operators.rb +20 -2
  177. data/lib/R_interface/rclosure.rb +5 -1
  178. data/lib/R_interface/rdata_frame.rb +34 -70
  179. data/lib/R_interface/rdevice.rb +125 -0
  180. data/lib/R_interface/rdevices.R +0 -0
  181. data/lib/R_interface/renvironment.rb +10 -4
  182. data/lib/R_interface/rexpression.rb +5 -1
  183. data/lib/R_interface/rindexed_object.rb +41 -13
  184. data/lib/R_interface/rlanguage.rb +20 -62
  185. data/lib/R_interface/rlist.rb +115 -25
  186. data/lib/R_interface/rlogical_operators.rb +0 -0
  187. data/lib/R_interface/rmatrix.rb +2 -11
  188. data/lib/R_interface/rmd_indexed_object.rb +5 -1
  189. data/lib/R_interface/robject.rb +348 -290
  190. data/lib/R_interface/rpkg.rb +0 -0
  191. data/lib/R_interface/rsupport.rb +609 -328
  192. data/lib/R_interface/rsupport_scope.rb +2 -1
  193. data/lib/R_interface/rsymbol.rb +50 -0
  194. data/lib/R_interface/ruby_callback.rb +2 -3
  195. data/lib/R_interface/ruby_extensions.rb +225 -175
  196. data/lib/R_interface/runary_operators.rb +0 -0
  197. data/lib/R_interface/rvector.rb +147 -31
  198. data/lib/galaaz.rb +0 -0
  199. data/lib/galaaz_jruby.rb +22 -0
  200. data/lib/gknit/diagnostics.rb +50 -0
  201. data/lib/gknit/draft.rb +23 -17
  202. data/lib/gknit/include_engine.rb +15 -7
  203. data/lib/gknit/knitr_engine.rb +223 -74
  204. data/lib/gknit/rb_engine.rb +3 -3
  205. data/lib/gknit/ruby_engine.rb +0 -0
  206. data/lib/gknit.rb +1 -0
  207. data/lib/new_bridge/bootstrap/windows_bootstrap.rb +285 -0
  208. data/lib/new_bridge/envelope.rb +51 -0
  209. data/lib/new_bridge/eval_result.rb +26 -0
  210. data/lib/new_bridge/framing.rb +39 -0
  211. data/lib/new_bridge/instance_pool_client.rb +38 -0
  212. data/lib/new_bridge/r_instance_manager.rb +404 -0
  213. data/lib/new_bridge/session_client.rb +530 -0
  214. data/lib/new_bridge/tcp_framed.rb +44 -0
  215. data/lib/new_bridge.rb +9 -0
  216. data/lib/util/exec_ruby.rb +95 -20
  217. data/lib/util/inline_file.rb +35 -30
  218. data/new_bridge_specs/benchmark_phase5_5_unboxing_spec.rb +96 -0
  219. data/new_bridge_specs/eval_r_async_spec.rb +113 -0
  220. data/new_bridge_specs/integration_phase5_1_concurrent_spec.rb +50 -0
  221. data/new_bridge_specs/integration_phase5_1_eval_spec.rb +16 -0
  222. data/new_bridge_specs/integration_phase5_1_r_api_spec.rb +25 -0
  223. data/new_bridge_specs/integration_phase5_1_smoke_spec.rb +31 -0
  224. data/new_bridge_specs/integration_phase5_2_dataframe_unboxing_spec.rb +19 -0
  225. data/new_bridge_specs/integration_phase5_2_handle_eval_unboxing_spec.rb +25 -0
  226. data/new_bridge_specs/integration_phase5_3_callback_args_spec.rb +28 -0
  227. data/new_bridge_specs/integration_phase5_3_callback_error_spec.rb +22 -0
  228. data/new_bridge_specs/integration_phase5_3_callback_timeout_spec.rb +28 -0
  229. data/new_bridge_specs/integration_phase5_3_callbacks_smoke_spec.rb +22 -0
  230. data/new_bridge_specs/integration_phase5_3_edge_cases_spec.rb +52 -0
  231. data/new_bridge_specs/integration_phase5_3_nested_spec.rb +30 -0
  232. data/new_bridge_specs/integration_phase5_4_concurrent_sessions_spec.rb +53 -0
  233. data/new_bridge_specs/integration_phase5_4_nested_session_callbacks_spec.rb +49 -0
  234. data/new_bridge_specs/integration_phase5_4_session_routing_spec.rb +38 -0
  235. data/new_bridge_specs/integration_phase5_5_stress_concurrency_spec.rb +52 -0
  236. data/new_bridge_specs/integration_phase5_5_unbox_walk_spec.rb +46 -0
  237. data/new_bridge_specs/phase0_protocol_spec.rb +96 -0
  238. data/new_bridge_specs/phase1_req_ret_spec.rb +66 -0
  239. data/new_bridge_specs/phase2_multi_instance_spec.rb +67 -0
  240. data/new_bridge_specs/phase3_callbacks_spec.rb +71 -0
  241. data/new_bridge_specs/phase4_2_hardening_spec.rb +252 -0
  242. data/new_bridge_specs/phase4_3_r_instance_manager_spec.rb +85 -0
  243. data/new_bridge_specs/phase4_nested_callbacks_spec.rb +123 -0
  244. data/r_requires/ggplot.rb +0 -0
  245. data/r_requires/knitr.rb +0 -0
  246. data/specs/all.rb +15 -11
  247. data/specs/arrow_from_ruby_batches_spec.rb +50 -0
  248. data/specs/arrow_semantics_spec.rb +64 -0
  249. data/specs/bridge_concurrent_spec.rb +46 -0
  250. data/specs/bridge_nested_spec.rb +25 -0
  251. data/specs/dataframe_semantics_spec.rb +122 -0
  252. data/specs/dataframe_single_index_logical_filter_spec.rb +21 -0
  253. data/specs/dispatch_probe_cache_spec.rb +38 -0
  254. data/specs/dispatch_probe_error_class_fallback_spec.rb +20 -0
  255. data/specs/dispatch_probe_fallback_spec.rb +18 -0
  256. data/specs/environment_semantics_spec.rb +89 -0
  257. data/specs/field_access_spec.rb +31 -0
  258. data/specs/figures/bg.jpeg +0 -0
  259. data/specs/figures/bg.png +0 -0
  260. data/specs/figures/bg.svg +168 -57
  261. data/specs/figures/dose_len.png +0 -0
  262. data/specs/figures/no_args.jpeg +0 -0
  263. data/specs/figures/no_args.png +0 -0
  264. data/specs/figures/no_args.svg +168 -57
  265. data/specs/figures/width_height.jpeg +0 -0
  266. data/specs/figures/width_height.png +0 -0
  267. data/specs/figures/width_height_units1.jpeg +0 -0
  268. data/specs/figures/width_height_units1.png +0 -0
  269. data/specs/figures/width_height_units2.jpeg +0 -0
  270. data/specs/figures/width_height_units2.png +0 -0
  271. data/specs/formula_semantics_spec.rb +81 -0
  272. data/specs/galaaz_util_exec_ruby_spec.rb +85 -0
  273. data/specs/galaaz_util_inline_file_spec.rb +54 -0
  274. data/specs/gknit_cli_option_permutation_spec.rb +24 -0
  275. data/specs/gknit_include_engine_spec.rb +72 -0
  276. data/specs/gknit_install_timeout_report_spec.rb +69 -0
  277. data/specs/gknit_internal_error_report_spec.rb +57 -0
  278. data/specs/gknit_vector_map_output_spec.rb +59 -0
  279. data/specs/globalenv_guardrail_spec.rb +52 -0
  280. data/specs/language_expression_semantics_spec.rb +145 -0
  281. data/specs/list_semantics_spec.rb +111 -0
  282. data/specs/new_bridge_bulk_dataframe_transfer_spec.rb +44 -0
  283. data/specs/new_bridge_bulk_vector_transfer_spec.rb +73 -0
  284. data/specs/new_bridge_callback_timeout_spec.rb +69 -0
  285. data/specs/new_bridge_eval_r_fallback_spec.rb +55 -0
  286. data/specs/nil_null_spec.rb +42 -0
  287. data/specs/object_build_phase2_spec.rb +53 -0
  288. data/specs/phase1_callback_bridge_spec.rb +84 -0
  289. data/specs/phase2_gknit_generic_rendering_guardrail_spec.rb +46 -0
  290. data/specs/phase2_gknit_no_raw_code_leakage_spec.rb +43 -0
  291. data/specs/phase3_gknit_generic_graphics_capture_spec.rb +71 -0
  292. data/specs/plot_device_semantics_spec.rb +28 -0
  293. data/specs/plot_snapshot_semantics_spec.rb +58 -0
  294. data/specs/protocol_result_spec.rb +236 -0
  295. data/specs/r_batch_fail_fast_spec.rb +47 -0
  296. data/specs/r_bridge_bootstrap_spec.rb +11 -0
  297. data/specs/r_devices.spec.rb +1 -1
  298. data/specs/r_eval.spec.rb +16 -18
  299. data/specs/r_function.spec.rb +1 -1
  300. data/specs/r_instance_manager_spec.rb +285 -0
  301. data/specs/r_list_apply.spec.rb +15 -15
  302. data/specs/r_matrix.spec.rb +0 -0
  303. data/specs/r_nse.spec.rb +5 -5
  304. data/specs/r_object_send_dispatch_spec.rb +13 -0
  305. data/specs/r_vector_comparator_spec.rb +8 -0
  306. data/specs/r_vector_creation.spec.rb +0 -0
  307. data/specs/r_vector_functions.spec.rb +0 -0
  308. data/specs/r_vector_object.spec.rb +0 -0
  309. data/specs/r_vector_operators.spec.rb +0 -0
  310. data/specs/r_vector_structured_scalar_reads_spec.rb +35 -0
  311. data/specs/r_vector_subsetting.spec.rb +0 -0
  312. data/specs/range_helper_spec.rb +21 -0
  313. data/specs/rsupport_scope_spec.rb +28 -0
  314. data/specs/rsupport_var_name_thread_safety_spec.rb +24 -0
  315. data/specs/scalar_character_spec.rb +44 -0
  316. data/specs/scoped_symbol_dsl_refinement_spec.rb +40 -0
  317. data/specs/session_env_bridge_spec.rb +25 -0
  318. data/specs/simplecov_bootstrap_spec.rb +10 -0
  319. data/specs/spec_helper.rb +10 -0
  320. data/specs/tmp.rb +0 -0
  321. data/specs/unboxing_recursion_regression_spec.rb +30 -0
  322. data/specs/unboxing_spec.rb +49 -0
  323. data/specs/verify_callbacks.rb +42 -0
  324. data/sty/galaaz.sty +0 -0
  325. data/version.rb +1 -1
  326. metadata +194 -64
  327. data/blogs/galaaz_ggplot/galaaz_ggplot.html +0 -520
  328. data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
  329. data/blogs/galaaz_ggplot/midwest.html +0 -188
  330. data/blogs/gknit/gknit.html +0 -2266
  331. data/blogs/gknit/gknit.pdf +0 -0
  332. data/blogs/manual/manual.html +0 -4638
  333. data/blogs/manual/manual.pdf +0 -0
  334. data/blogs/manual/manual_files/figure-latex/diverging_bar.pdf +0 -0
  335. data/blogs/nse_dplyr/nse_dplyr.html +0 -878
  336. data/blogs/nse_dplyr/nse_dplyr.pdf +0 -0
  337. data/blogs/oh_my/oh_my.html +0 -568
  338. data/blogs/ruby_plot/ruby_plot.html +0 -544
  339. data/blogs/ruby_plot/ruby_plot.pdf +0 -0
  340. data/examples/latex_templates/Test-acs_article/Test-acs_article.pdf +0 -0
  341. data/examples/latex_templates/Test-aea_article/Test-aea_article.pdf +0 -0
  342. data/examples/latex_templates/Test-amq_article/Test-amq_article.pdf +0 -0
  343. data/examples/latex_templates/Test-amq_article/pics/Figure2.pdf +0 -0
  344. data/examples/latex_templates/Test-asa_article/Test-asa_article.pdf +0 -0
  345. data/examples/latex_templates/Test-ieee_article/Test-ieee_article.pdf +0 -0
  346. data/examples/latex_templates/Test-rjournal_article/RJwrapper.pdf +0 -0
  347. data/examples/latex_templates/Test-springer_article/Test-springer_article.pdf +0 -0
  348. data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.pdf +0 -0
  349. data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.pdf +0 -0
  350. data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.pdf +0 -0
  351. data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.pdf +0 -0
  352. data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.pdf +0 -0
  353. data/specs/r_dataframe.spec.rb +0 -379
  354. data/specs/r_environment.spec.rb +0 -140
  355. data/specs/r_formula.spec.rb +0 -232
  356. data/specs/r_language.spec.rb +0 -112
  357. data/specs/r_list.spec.rb +0 -293
  358. data/specs/r_plots.spec.rb +0 -72
  359. 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
+