polyrun 2.1.3 → 2.2.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -1
  3. data/CONTRIBUTING.md +22 -0
  4. data/docs/SETUP_PROFILE.md +1 -1
  5. data/ext/polyrun_coverage_merge/coverage_merge.c +492 -0
  6. data/ext/polyrun_coverage_merge/extconf.rb +3 -0
  7. data/lib/polyrun/benchmark/profile.rb +191 -0
  8. data/lib/polyrun/benchmark/report.rb +87 -0
  9. data/lib/polyrun/cli/benchmark_commands.rb +66 -0
  10. data/lib/polyrun/cli/coverage_commands.rb +4 -4
  11. data/lib/polyrun/cli/coverage_merge_io.rb +30 -4
  12. data/lib/polyrun/cli/failure_commands.rb +10 -3
  13. data/lib/polyrun/cli/help.rb +12 -8
  14. data/lib/polyrun/cli/report_commands.rb +25 -11
  15. data/lib/polyrun/cli/run_shards_parallel_children.rb +1 -1
  16. data/lib/polyrun/cli/run_shards_plan_options.rb +1 -1
  17. data/lib/polyrun/cli/spec_quality_commands.rb +16 -7
  18. data/lib/polyrun/cli.rb +8 -1
  19. data/lib/polyrun/coverage/example_diff.rb +127 -60
  20. data/lib/polyrun/coverage/example_diff_snapshot.rb +44 -0
  21. data/lib/polyrun/coverage/example_diff_track_filter.rb +51 -0
  22. data/lib/polyrun/coverage/file_stats_report.rb +36 -0
  23. data/lib/polyrun/coverage/formatter.rb +22 -1
  24. data/lib/polyrun/coverage/merge/formatters.rb +11 -3
  25. data/lib/polyrun/coverage/merge_merge_two.rb +112 -63
  26. data/lib/polyrun/coverage/merge_native.rb +37 -0
  27. data/lib/polyrun/coverage/reporting.rb +1 -1
  28. data/lib/polyrun/export/csv.rb +25 -0
  29. data/lib/polyrun/export/markdown.rb +47 -0
  30. data/lib/polyrun/hooks/shell_runner.rb +33 -0
  31. data/lib/polyrun/hooks.rb +4 -7
  32. data/lib/polyrun/reporting/failure_merge.rb +48 -12
  33. data/lib/polyrun/reporting/junit.rb +8 -7
  34. data/lib/polyrun/reporting/junit_report.rb +87 -0
  35. data/lib/polyrun/rspec/example_debug.rb +1 -1
  36. data/lib/polyrun/rspec/sharded_formatter_compat.rb +30 -7
  37. data/lib/polyrun/spec_quality/profile.rb +24 -12
  38. data/lib/polyrun/spec_quality/report.rb +93 -0
  39. data/lib/polyrun/spec_quality.rb +19 -11
  40. data/lib/polyrun/timing/summary.rb +55 -5
  41. data/lib/polyrun/version.rb +1 -1
  42. data/polyrun.gemspec +8 -1
  43. metadata +58 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a5cd4e5af5195cb25ca3185b3e828556746f21a6911f8a60f1b43b5b6a316d0
4
- data.tar.gz: 67362c68f463339cfd8a66e665b9fb6a5f75cf8ed6276e1a846c68147a27e848
3
+ metadata.gz: 8b7bedc5bda9c9ee341927dab2ba6aedafaebe4c26ad73750d8ed7ad4845f4e3
4
+ data.tar.gz: bac9cd71c5ab3372c0ff5dda891dd354a0ceaac3555f5949870ce8611646debc
5
5
  SHA512:
6
- metadata.gz: b7f7ff8592774bfb1bd173753f5c3cca77d99a392a9dbabdd0bf11c85b510a3dc4cf0c2a66912cf5d48384445e74039a2cfa296d6aeb40b5d008aa575700ef0b
7
- data.tar.gz: 05aad7cb17b505112548d072895d56c88f885f07b31e3052ab12e5b4ab0979a555bdf9872380107a60211a8bd54dbd176b98a8970eaba7756fa2e87f8a475a15
6
+ metadata.gz: fe09eaccf1eaf3fba5a998d49f2f2df9cfd6a1da6b1eef960e6cbe894f2269b05777be459fe394a67c3038d72750a8401ae8e224726901ac4bd437e3d01a93ed
7
+ data.tar.gz: f8090b77fba080b7ca1996afeec0c2680ca26e0d0a4571453210f421f4921685bd8c5bcfeb79724556e377ff26968a914b52bf24b4a1a433a9500d656aa43f41
data/CHANGELOG.md CHANGED
@@ -1,6 +1,15 @@
1
1
  # CHANGELOG
2
2
 
3
- ## Unreleased
3
+ ## 2.2.0 (2026-07-13)
4
+
5
+ - Fix `install_example_rails_logging!` raising `NameError` when example-debug Rails logging runs under `POLYRUN_EXAMPLE_DEBUG=1`.
6
+ - Improve spec-quality per-example coverage diff: sparse scoped snapshots, track-aware diff without a second full blob copy, and optional lazy profile dimensions.
7
+ - Add CSV and Markdown exports for coverage, timing, spec-quality, and failure merge reports.
8
+ - Add `report-junit --format xml|csv|markdown` (XML remains default for CI).
9
+ - Add `Polyrun::Benchmark::Profile` / `report-benchmark` / `polyrun bench`; benchmark runs write JSON sidecars under `tmp/benchmarks/` with optional `POLYRUN_BENCH_FORMATS`.
10
+ - Add optional native coverage merge acceleration (`ext/polyrun_coverage_merge`: `merge_line_arrays`, `merge_two`, `line_counts`) with Ruby fallbacks.
11
+ - Add RSpec performance benchmarks (`rake bench_performance`, `spec/performance/`) with profile logs under `tmp/benchmarks/`.
12
+ - Include `csv` and `markdown` in default post-merge coverage formats (`POLYRUN_MERGE_FORMATS`).
4
13
 
5
14
  ## 2.1.3 (2026-07-10)
6
15
 
data/CONTRIBUTING.md CHANGED
@@ -17,11 +17,33 @@ bundle exec rake spec
17
17
 
18
18
  Coverage merge performance (large synthetic payloads):
19
19
 
20
+ Native extension (optional; compiles via `bundle install` or `cd ext/polyrun_coverage_merge && ruby extconf.rb && make`):
21
+
22
+ After pulling changes under `ext/**/*.c` or `ext/**/extconf.rb`, rebuild the extension before running specs or benchmarks:
23
+
24
+ ```bash
25
+ make native-extension
26
+ # or: bundle exec rake native_extension
27
+ ```
28
+
29
+ If merge specs segfault or native acceleration behaves oddly after a pull, run `make clean` in `ext/polyrun_coverage_merge` and `make native-extension` again (or `bundle install` to trigger a full compile).
30
+
31
+ CI compiles the extension on Linux and macOS (`.github/workflows/native-extension.yml`).
32
+
20
33
  ```bash
21
34
  bundle exec rake bench_merge
22
35
  # or: ruby benchmark/merge_coverage.rb
23
36
  ```
24
37
 
38
+ RSpec performance benchmarks (coverage merge + spec-quality peek; writes `tmp/benchmarks/profile_<sha>.log`):
39
+
40
+ ```bash
41
+ bundle exec rake bench_performance
42
+ # optional: STACKPROF=1 or BENCHMARK_IPS=1 for spec/performance/profiling_spec.rb
43
+ # optional: BENCH_MEMORY=1 bundle exec rspec spec/performance/benchmark_merge_spec.rb spec/performance/benchmark_spec.rb --tag benchmark
44
+ # optional env: BENCH_LINE_COUNT_REPS, BENCH_MEMORY_REPS
45
+ ```
46
+
25
47
  Run the suite under alternate Ruby constraints (see `Appraisals` and `gemfiles/`):
26
48
 
27
49
  ```bash
@@ -76,7 +76,7 @@ Orchestration tracing stays on `DEBUG=1` / `POLYRUN_DEBUG=1`. Per-example toolin
76
76
  | `DEBUG_LOG_LEVEL` | Rails / ActiveRecord logger severity: `debug`, `info`, `warn`, `error`, `fatal`, or Ruby Logger integers (`0` debug … `4` fatal); default `debug` |
77
77
  | `RSPEC_EXAMPLE_TIMEOUT_SEC` | Per-example timeout (disabled while example debug is on) |
78
78
 
79
- In `spec_helper` / `spec/support`: `require "polyrun/rspec"` then `Polyrun::RSpec.install_example_debug!`, `install_example_rails_logging!`, `install_example_timeout!`, and `install_sharded_formatter_compat!` when using Fuubar under `POLYRUN_SHARD_*`. Pair with `install_worker_ping!` for idle timeouts.
79
+ In `spec_helper` / `spec/support`: `require "polyrun/rspec"` then `Polyrun::RSpec.install_sharded_formatter_compat!` (silences per-worker seed/summary/pending under `POLYRUN_SHARD_*`), `install_example_debug!`, `install_example_rails_logging!`, `install_example_timeout!`. Pair with `install_worker_ping!` for idle timeouts.
80
80
 
81
81
  ## 6. Coverage and CI reports
82
82
 
@@ -0,0 +1,492 @@
1
+ #include <ruby.h>
2
+ #include <string.h>
3
+
4
+ static VALUE str_lines;
5
+ static VALUE str_branches;
6
+ static VALUE str_type;
7
+ static VALUE str_start_line;
8
+ static VALUE str_end_line;
9
+ static VALUE str_coverage;
10
+ static ID id_lines;
11
+ static ID id_branches;
12
+ static ID id_type;
13
+ static ID id_start_line;
14
+ static ID id_end_line;
15
+ static ID id_coverage;
16
+ static ID id_relevant;
17
+ static ID id_covered;
18
+ static ID id_sort_branches_for_native;
19
+
20
+ static VALUE
21
+ ignored_string(void)
22
+ {
23
+ return rb_str_new_cstr("ignored");
24
+ }
25
+
26
+ static int
27
+ ignored_hit_p(VALUE value)
28
+ {
29
+ if (!RB_TYPE_P(value, T_STRING)) {
30
+ return 0;
31
+ }
32
+
33
+ return strcmp(StringValueCStr(value), "ignored") == 0;
34
+ }
35
+
36
+ static VALUE
37
+ line_hit_to_i(VALUE value)
38
+ {
39
+ if (NIL_P(value)) {
40
+ return Qnil;
41
+ }
42
+ if (RB_TYPE_P(value, T_FIXNUM) || RB_TYPE_P(value, T_BIGNUM)) {
43
+ return value;
44
+ }
45
+ if (RB_TYPE_P(value, T_STRING)) {
46
+ const char *text = StringValueCStr(value);
47
+ char *end = NULL;
48
+ long number = strtol(text, &end, 10);
49
+ if (end != text && *end == '\0') {
50
+ return LONG2FIX(number);
51
+ }
52
+ return Qnil;
53
+ }
54
+ if (RB_TYPE_P(value, T_SYMBOL)) {
55
+ VALUE as_string = rb_sym2str(value);
56
+ return line_hit_to_i(as_string);
57
+ }
58
+
59
+ return Qnil;
60
+ }
61
+
62
+ static int
63
+ line_hit_positive_p(VALUE value)
64
+ {
65
+ VALUE as_int = line_hit_to_i(value);
66
+ if (NIL_P(as_int)) {
67
+ return 0;
68
+ }
69
+
70
+ VALUE comparison = rb_funcall(as_int, rb_intern(">"), 1, LONG2FIX(0));
71
+ return RTEST(comparison);
72
+ }
73
+
74
+ static VALUE
75
+ coerce_line_array(VALUE value)
76
+ {
77
+ if (NIL_P(value)) {
78
+ return rb_ary_new();
79
+ }
80
+ if (!RB_TYPE_P(value, T_ARRAY)) {
81
+ rb_raise(rb_eTypeError, "lines must be an Array");
82
+ }
83
+
84
+ return value;
85
+ }
86
+
87
+ static VALUE
88
+ line_array_for_count(VALUE value)
89
+ {
90
+ if (NIL_P(value) || !RB_TYPE_P(value, T_ARRAY)) {
91
+ return rb_ary_new();
92
+ }
93
+
94
+ return value;
95
+ }
96
+
97
+ static VALUE
98
+ merge_line_hits(VALUE left, VALUE right)
99
+ {
100
+ if (NIL_P(left)) {
101
+ return right;
102
+ }
103
+ if (NIL_P(right)) {
104
+ return left;
105
+ }
106
+ if (ignored_hit_p(left) || ignored_hit_p(right)) {
107
+ return ignored_string();
108
+ }
109
+
110
+ VALUE left_i = line_hit_to_i(left);
111
+ VALUE right_i = line_hit_to_i(right);
112
+
113
+ if (!NIL_P(left_i) && !NIL_P(right_i)) {
114
+ return rb_funcall(left_i, rb_intern("+"), 1, right_i);
115
+ }
116
+ if (NIL_P(left_i) && !NIL_P(right_i)) {
117
+ return right_i;
118
+ }
119
+ if (!NIL_P(left_i) && NIL_P(right_i)) {
120
+ return left_i;
121
+ }
122
+
123
+ return left;
124
+ }
125
+
126
+ static VALUE
127
+ merge_line_arrays(VALUE left, VALUE right)
128
+ {
129
+ left = coerce_line_array(left);
130
+ right = coerce_line_array(right);
131
+
132
+ long left_len = RARRAY_LEN(left);
133
+ long right_len = RARRAY_LEN(right);
134
+ long max_len = left_len > right_len ? left_len : right_len;
135
+ VALUE out = rb_ary_new2(max_len);
136
+
137
+ for (long index = 0; index < max_len; index++) {
138
+ VALUE left_hit = index < left_len ? rb_ary_entry(left, index) : Qnil;
139
+ VALUE right_hit = index < right_len ? rb_ary_entry(right, index) : Qnil;
140
+ rb_ary_store(out, index, merge_line_hits(left_hit, right_hit));
141
+ }
142
+
143
+ return out;
144
+ }
145
+
146
+ static VALUE
147
+ hash_field(VALUE hash, VALUE string_key, ID symbol_key)
148
+ {
149
+ VALUE value = rb_hash_aref(hash, string_key);
150
+ if (NIL_P(value)) {
151
+ value = rb_hash_aref(hash, ID2SYM(symbol_key));
152
+ }
153
+
154
+ return value;
155
+ }
156
+
157
+ static VALUE
158
+ branch_key(VALUE branch)
159
+ {
160
+ if (!RB_TYPE_P(branch, T_HASH)) {
161
+ branch = rb_hash_new();
162
+ }
163
+
164
+ return rb_ary_new3(
165
+ 3,
166
+ hash_field(branch, str_type, id_type),
167
+ hash_field(branch, str_start_line, id_start_line),
168
+ hash_field(branch, str_end_line, id_end_line)
169
+ );
170
+ }
171
+
172
+ static VALUE
173
+ coverage_count(VALUE branch)
174
+ {
175
+ VALUE coverage = hash_field(branch, str_coverage, id_coverage);
176
+ VALUE as_int = line_hit_to_i(coverage);
177
+ if (NIL_P(as_int)) {
178
+ return LONG2FIX(0);
179
+ }
180
+
181
+ return as_int;
182
+ }
183
+
184
+ static VALUE
185
+ merge_branch_entries(VALUE left, VALUE right)
186
+ {
187
+ VALUE out = rb_hash_dup(left);
188
+ VALUE sum = rb_funcall(coverage_count(left), rb_intern("+"), 1, coverage_count(right));
189
+ rb_hash_aset(out, str_coverage, sum);
190
+
191
+ return out;
192
+ }
193
+
194
+ static VALUE
195
+ merge_module_value(void)
196
+ {
197
+ VALUE polyrun = rb_const_get(rb_cObject, rb_intern("Polyrun"));
198
+ VALUE coverage = rb_const_get(polyrun, rb_intern("Coverage"));
199
+ return rb_const_get(coverage, rb_intern("Merge"));
200
+ }
201
+
202
+ static VALUE
203
+ hash_keys(VALUE hash)
204
+ {
205
+ return rb_funcall(hash, rb_intern("keys"), 0);
206
+ }
207
+
208
+ static VALUE
209
+ sort_branches(VALUE branches)
210
+ {
211
+ if (!RB_TYPE_P(branches, T_ARRAY)) {
212
+ return rb_ary_new();
213
+ }
214
+ if (RARRAY_LEN(branches) < 2) {
215
+ return branches;
216
+ }
217
+
218
+ return rb_funcall(merge_module_value(), id_sort_branches_for_native, 1, branches);
219
+ }
220
+
221
+ static VALUE
222
+ duplicate_branch_side(VALUE value)
223
+ {
224
+ if (NIL_P(value)) {
225
+ return Qnil;
226
+ }
227
+
228
+ return rb_obj_dup(value);
229
+ }
230
+
231
+ static VALUE
232
+ coerce_branch_array(VALUE value)
233
+ {
234
+ if (NIL_P(value)) {
235
+ return Qnil;
236
+ }
237
+ if (!RB_TYPE_P(value, T_ARRAY)) {
238
+ rb_raise(rb_eTypeError, "branches must be an Array");
239
+ }
240
+
241
+ return value;
242
+ }
243
+
244
+ static VALUE
245
+ merge_branch_arrays(VALUE left, VALUE right)
246
+ {
247
+ if (NIL_P(left) && NIL_P(right)) {
248
+ return Qnil;
249
+ }
250
+ if (NIL_P(left)) {
251
+ return duplicate_branch_side(right);
252
+ }
253
+ if (NIL_P(right)) {
254
+ return duplicate_branch_side(left);
255
+ }
256
+
257
+ left = coerce_branch_array(left);
258
+ right = coerce_branch_array(right);
259
+
260
+ VALUE index = rb_hash_new();
261
+ VALUE sides[2] = {left, right};
262
+
263
+ for (int side_index = 0; side_index < 2; side_index++) {
264
+ VALUE array = sides[side_index];
265
+ long length = RARRAY_LEN(array);
266
+
267
+ for (long branch_index = 0; branch_index < length; branch_index++) {
268
+ VALUE branch = rb_ary_entry(array, branch_index);
269
+ if (!RB_TYPE_P(branch, T_HASH)) {
270
+ continue;
271
+ }
272
+
273
+ VALUE key = branch_key(branch);
274
+ VALUE existing = rb_hash_aref(index, key);
275
+ VALUE merged = NIL_P(existing) ? rb_hash_dup(branch) : merge_branch_entries(existing, branch);
276
+ rb_hash_aset(index, key, merged);
277
+ }
278
+ }
279
+
280
+ VALUE values = rb_ary_new();
281
+ VALUE branch_keys = hash_keys(index);
282
+ long branch_count = RARRAY_LEN(branch_keys);
283
+ for (long branch_index = 0; branch_index < branch_count; branch_index++) {
284
+ VALUE key = rb_ary_entry(branch_keys, branch_index);
285
+ rb_ary_push(values, rb_hash_aref(index, key));
286
+ }
287
+
288
+ return sort_branches(values);
289
+ }
290
+
291
+ static VALUE
292
+ normalize_file_entry(VALUE value)
293
+ {
294
+ if (NIL_P(value)) {
295
+ return Qnil;
296
+ }
297
+ if (RB_TYPE_P(value, T_ARRAY)) {
298
+ VALUE entry = rb_hash_new();
299
+ rb_hash_aset(entry, str_lines, value);
300
+ return entry;
301
+ }
302
+ if (RB_TYPE_P(value, T_HASH)) {
303
+ return value;
304
+ }
305
+
306
+ return Qnil;
307
+ }
308
+
309
+ static VALUE
310
+ entry_lines(VALUE entry)
311
+ {
312
+ VALUE lines = rb_hash_aref(entry, str_lines);
313
+ if (NIL_P(lines)) {
314
+ lines = rb_hash_aref(entry, ID2SYM(id_lines));
315
+ }
316
+
317
+ return coerce_line_array(lines);
318
+ }
319
+
320
+ static VALUE
321
+ entry_lines_for_count(VALUE entry)
322
+ {
323
+ VALUE lines = rb_hash_aref(entry, str_lines);
324
+ if (NIL_P(lines)) {
325
+ lines = rb_hash_aref(entry, ID2SYM(id_lines));
326
+ }
327
+
328
+ return line_array_for_count(lines);
329
+ }
330
+
331
+ static VALUE
332
+ entry_branches(VALUE entry)
333
+ {
334
+ VALUE branches = rb_hash_aref(entry, str_branches);
335
+ if (NIL_P(branches)) {
336
+ branches = rb_hash_aref(entry, ID2SYM(id_branches));
337
+ }
338
+
339
+ return branches;
340
+ }
341
+
342
+ static VALUE
343
+ merge_file_entry(VALUE left, VALUE right)
344
+ {
345
+ left = normalize_file_entry(left);
346
+ right = normalize_file_entry(right);
347
+ if (NIL_P(left)) {
348
+ return right;
349
+ }
350
+ if (NIL_P(right)) {
351
+ return left;
352
+ }
353
+
354
+ VALUE merged_lines = merge_line_arrays(entry_lines(left), entry_lines(right));
355
+ VALUE entry = rb_hash_new();
356
+ rb_hash_aset(entry, str_lines, merged_lines);
357
+
358
+ VALUE left_branches = entry_branches(left);
359
+ VALUE right_branches = entry_branches(right);
360
+ if (!NIL_P(left_branches) || !NIL_P(right_branches)) {
361
+ VALUE branches = merge_branch_arrays(left_branches, right_branches);
362
+ if (!NIL_P(branches)) {
363
+ rb_hash_aset(entry, str_branches, branches);
364
+ }
365
+ }
366
+
367
+ return entry;
368
+ }
369
+
370
+ static VALUE
371
+ ensure_hash(VALUE value, const char *name)
372
+ {
373
+ if (NIL_P(value)) {
374
+ return rb_hash_new();
375
+ }
376
+ if (!RB_TYPE_P(value, T_HASH)) {
377
+ rb_raise(rb_eTypeError, "%s must be a Hash", name);
378
+ }
379
+
380
+ return value;
381
+ }
382
+
383
+ static VALUE
384
+ merge_two(VALUE module, VALUE left, VALUE right)
385
+ {
386
+ (void)module;
387
+
388
+ left = ensure_hash(left, "left");
389
+ right = ensure_hash(right, "right");
390
+
391
+ VALUE primary = left;
392
+ VALUE secondary = right;
393
+ if (RHASH_SIZE(right) > RHASH_SIZE(left)) {
394
+ primary = right;
395
+ secondary = left;
396
+ }
397
+
398
+ VALUE out = rb_hash_new();
399
+ VALUE primary_keys = hash_keys(primary);
400
+ long primary_length = RARRAY_LEN(primary_keys);
401
+
402
+ for (long index = 0; index < primary_length; index++) {
403
+ VALUE key = rb_ary_entry(primary_keys, index);
404
+ VALUE value = rb_hash_aref(primary, key);
405
+ VALUE right_entry = rb_hash_aref(secondary, key);
406
+ rb_hash_aset(out, key, merge_file_entry(value, right_entry));
407
+ }
408
+
409
+ VALUE secondary_keys = hash_keys(secondary);
410
+ long secondary_length = RARRAY_LEN(secondary_keys);
411
+
412
+ for (long index = 0; index < secondary_length; index++) {
413
+ VALUE key = rb_ary_entry(secondary_keys, index);
414
+ if (NIL_P(rb_hash_aref(out, key))) {
415
+ rb_hash_aset(out, key, rb_hash_aref(secondary, key));
416
+ }
417
+ }
418
+
419
+ return out;
420
+ }
421
+
422
+ static VALUE
423
+ line_counts(VALUE module, VALUE file_entry)
424
+ {
425
+ (void)module;
426
+
427
+ file_entry = normalize_file_entry(file_entry);
428
+ long relevant = 0;
429
+ long covered = 0;
430
+
431
+ if (!NIL_P(file_entry)) {
432
+ VALUE lines = entry_lines_for_count(file_entry);
433
+ long length = RARRAY_LEN(lines);
434
+
435
+ for (long index = 0; index < length; index++) {
436
+ VALUE hit = rb_ary_entry(lines, index);
437
+ if (NIL_P(hit) || ignored_hit_p(hit)) {
438
+ continue;
439
+ }
440
+
441
+ relevant += 1;
442
+ if (line_hit_positive_p(hit)) {
443
+ covered += 1;
444
+ }
445
+ }
446
+ }
447
+
448
+ VALUE counts = rb_hash_new();
449
+ rb_hash_aset(counts, ID2SYM(id_relevant), LONG2FIX(relevant));
450
+ rb_hash_aset(counts, ID2SYM(id_covered), LONG2FIX(covered));
451
+
452
+ return counts;
453
+ }
454
+
455
+ static VALUE
456
+ merge_line_arrays_method(VALUE module, VALUE left, VALUE right)
457
+ {
458
+ (void)module;
459
+
460
+ return merge_line_arrays(left, right);
461
+ }
462
+
463
+ void
464
+ Init_polyrun_coverage_merge(void)
465
+ {
466
+ id_lines = rb_intern("lines");
467
+ id_branches = rb_intern("branches");
468
+ id_type = rb_intern("type");
469
+ id_start_line = rb_intern("start_line");
470
+ id_end_line = rb_intern("end_line");
471
+ id_coverage = rb_intern("coverage");
472
+ id_relevant = rb_intern("relevant");
473
+ id_covered = rb_intern("covered");
474
+ id_sort_branches_for_native = rb_intern("sort_branches_for_native");
475
+ str_lines = rb_obj_freeze(rb_str_new_cstr("lines"));
476
+ str_branches = rb_obj_freeze(rb_str_new_cstr("branches"));
477
+ str_type = rb_obj_freeze(rb_str_new_cstr("type"));
478
+ str_start_line = rb_obj_freeze(rb_str_new_cstr("start_line"));
479
+ str_end_line = rb_obj_freeze(rb_str_new_cstr("end_line"));
480
+ str_coverage = rb_obj_freeze(rb_str_new_cstr("coverage"));
481
+ rb_global_variable(&str_lines);
482
+ rb_global_variable(&str_branches);
483
+ rb_global_variable(&str_type);
484
+ rb_global_variable(&str_start_line);
485
+ rb_global_variable(&str_end_line);
486
+ rb_global_variable(&str_coverage);
487
+
488
+ VALUE module = rb_define_module("PolyrunCoverageMerge");
489
+ rb_define_singleton_method(module, "merge_line_arrays", merge_line_arrays_method, 2);
490
+ rb_define_singleton_method(module, "merge_two", merge_two, 2);
491
+ rb_define_singleton_method(module, "line_counts", line_counts, 1);
492
+ }
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile("polyrun_coverage_merge")