ultra-pro-pkg 0.0.1

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 (117) hide show
  1. checksums.yaml +7 -0
  2. data/simplecov-1.0.0/LICENSE +20 -0
  3. data/simplecov-1.0.0/README.md +1524 -0
  4. data/simplecov-1.0.0/doc/alternate-formatters.md +66 -0
  5. data/simplecov-1.0.0/doc/commercial-services.md +25 -0
  6. data/simplecov-1.0.0/doc/editor-integration.md +18 -0
  7. data/simplecov-1.0.0/exe/simplecov +11 -0
  8. data/simplecov-1.0.0/lib/minitest/simplecov_plugin.rb +171 -0
  9. data/simplecov-1.0.0/lib/simplecov/autostart.rb +11 -0
  10. data/simplecov-1.0.0/lib/simplecov/cli/clean.rb +47 -0
  11. data/simplecov-1.0.0/lib/simplecov/cli/coverage.rb +91 -0
  12. data/simplecov-1.0.0/lib/simplecov/cli/diff.rb +151 -0
  13. data/simplecov-1.0.0/lib/simplecov/cli/dotfile.rb +100 -0
  14. data/simplecov-1.0.0/lib/simplecov/cli/merge.rb +116 -0
  15. data/simplecov-1.0.0/lib/simplecov/cli/open.rb +50 -0
  16. data/simplecov-1.0.0/lib/simplecov/cli/report.rb +84 -0
  17. data/simplecov-1.0.0/lib/simplecov/cli/run.rb +36 -0
  18. data/simplecov-1.0.0/lib/simplecov/cli/serve.rb +139 -0
  19. data/simplecov-1.0.0/lib/simplecov/cli/uncovered.rb +107 -0
  20. data/simplecov-1.0.0/lib/simplecov/cli.rb +150 -0
  21. data/simplecov-1.0.0/lib/simplecov/color.rb +74 -0
  22. data/simplecov-1.0.0/lib/simplecov/combine/branches_combiner.rb +54 -0
  23. data/simplecov-1.0.0/lib/simplecov/combine/files_combiner.rb +30 -0
  24. data/simplecov-1.0.0/lib/simplecov/combine/lines_combiner.rb +45 -0
  25. data/simplecov-1.0.0/lib/simplecov/combine/methods_combiner.rb +26 -0
  26. data/simplecov-1.0.0/lib/simplecov/combine/results_combiner.rb +61 -0
  27. data/simplecov-1.0.0/lib/simplecov/combine.rb +30 -0
  28. data/simplecov-1.0.0/lib/simplecov/command_guesser.rb +78 -0
  29. data/simplecov-1.0.0/lib/simplecov/configuration/coverage.rb +171 -0
  30. data/simplecov-1.0.0/lib/simplecov/configuration/coverage_criteria.rb +156 -0
  31. data/simplecov-1.0.0/lib/simplecov/configuration/filters.rb +197 -0
  32. data/simplecov-1.0.0/lib/simplecov/configuration/formatting.rb +119 -0
  33. data/simplecov-1.0.0/lib/simplecov/configuration/ignored_entries.rb +63 -0
  34. data/simplecov-1.0.0/lib/simplecov/configuration/merging.rb +164 -0
  35. data/simplecov-1.0.0/lib/simplecov/configuration/thresholds.rb +174 -0
  36. data/simplecov-1.0.0/lib/simplecov/configuration.rb +184 -0
  37. data/simplecov-1.0.0/lib/simplecov/coverage_statistics.rb +59 -0
  38. data/simplecov-1.0.0/lib/simplecov/coverage_violations.rb +148 -0
  39. data/simplecov-1.0.0/lib/simplecov/defaults.rb +60 -0
  40. data/simplecov-1.0.0/lib/simplecov/deprecation.rb +45 -0
  41. data/simplecov-1.0.0/lib/simplecov/directive.rb +162 -0
  42. data/simplecov-1.0.0/lib/simplecov/exit_codes/exit_code_handling.rb +35 -0
  43. data/simplecov-1.0.0/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +45 -0
  44. data/simplecov-1.0.0/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +45 -0
  45. data/simplecov-1.0.0/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +44 -0
  46. data/simplecov-1.0.0/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +41 -0
  47. data/simplecov-1.0.0/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +70 -0
  48. data/simplecov-1.0.0/lib/simplecov/exit_codes.rb +18 -0
  49. data/simplecov-1.0.0/lib/simplecov/exit_handling.rb +158 -0
  50. data/simplecov-1.0.0/lib/simplecov/file_list.rb +164 -0
  51. data/simplecov-1.0.0/lib/simplecov/filter.rb +139 -0
  52. data/simplecov-1.0.0/lib/simplecov/formatter/base.rb +101 -0
  53. data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/application.css +1 -0
  54. data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/application.js +18 -0
  55. data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/favicon_green.png +0 -0
  56. data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/favicon_red.png +0 -0
  57. data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/favicon_yellow.png +0 -0
  58. data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/index.html +56 -0
  59. data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter.rb +79 -0
  60. data/simplecov-1.0.0/lib/simplecov/formatter/json_formatter/errors_formatter.rb +84 -0
  61. data/simplecov-1.0.0/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +128 -0
  62. data/simplecov-1.0.0/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +99 -0
  63. data/simplecov-1.0.0/lib/simplecov/formatter/json_formatter.rb +87 -0
  64. data/simplecov-1.0.0/lib/simplecov/formatter/multi_formatter.rb +31 -0
  65. data/simplecov-1.0.0/lib/simplecov/formatter/simple_formatter.rb +23 -0
  66. data/simplecov-1.0.0/lib/simplecov/formatter.rb +14 -0
  67. data/simplecov-1.0.0/lib/simplecov/last_run.rb +35 -0
  68. data/simplecov-1.0.0/lib/simplecov/lines_classifier.rb +60 -0
  69. data/simplecov-1.0.0/lib/simplecov/load_global_config.rb +13 -0
  70. data/simplecov-1.0.0/lib/simplecov/no_defaults.rb +4 -0
  71. data/simplecov-1.0.0/lib/simplecov/parallel_adapters/base.rb +61 -0
  72. data/simplecov-1.0.0/lib/simplecov/parallel_adapters/generic.rb +44 -0
  73. data/simplecov-1.0.0/lib/simplecov/parallel_adapters/parallel_tests.rb +93 -0
  74. data/simplecov-1.0.0/lib/simplecov/parallel_adapters.rb +83 -0
  75. data/simplecov-1.0.0/lib/simplecov/parallel_coordination.rb +129 -0
  76. data/simplecov-1.0.0/lib/simplecov/process.rb +37 -0
  77. data/simplecov-1.0.0/lib/simplecov/profiles/bundler_filter.rb +5 -0
  78. data/simplecov-1.0.0/lib/simplecov/profiles/hidden_filter.rb +5 -0
  79. data/simplecov-1.0.0/lib/simplecov/profiles/rails.rb +32 -0
  80. data/simplecov-1.0.0/lib/simplecov/profiles/root_filter.rb +11 -0
  81. data/simplecov-1.0.0/lib/simplecov/profiles/strict.rb +32 -0
  82. data/simplecov-1.0.0/lib/simplecov/profiles/test_frameworks.rb +5 -0
  83. data/simplecov-1.0.0/lib/simplecov/profiles.rb +64 -0
  84. data/simplecov-1.0.0/lib/simplecov/result/missing_source_files_reporter.rb +49 -0
  85. data/simplecov-1.0.0/lib/simplecov/result/source_file_builder.rb +51 -0
  86. data/simplecov-1.0.0/lib/simplecov/result.rb +183 -0
  87. data/simplecov-1.0.0/lib/simplecov/result_adapter.rb +92 -0
  88. data/simplecov-1.0.0/lib/simplecov/result_merger/legacy_format_adapter.rb +28 -0
  89. data/simplecov-1.0.0/lib/simplecov/result_merger/resultset_file.rb +38 -0
  90. data/simplecov-1.0.0/lib/simplecov/result_merger/resultset_store.rb +50 -0
  91. data/simplecov-1.0.0/lib/simplecov/result_merger.rb +162 -0
  92. data/simplecov-1.0.0/lib/simplecov/result_processing.rb +179 -0
  93. data/simplecov-1.0.0/lib/simplecov/simulate_coverage.rb +75 -0
  94. data/simplecov-1.0.0/lib/simplecov/source_file/branch.rb +82 -0
  95. data/simplecov-1.0.0/lib/simplecov/source_file/branch_builder.rb +114 -0
  96. data/simplecov-1.0.0/lib/simplecov/source_file/builder_context.rb +28 -0
  97. data/simplecov-1.0.0/lib/simplecov/source_file/line.rb +77 -0
  98. data/simplecov-1.0.0/lib/simplecov/source_file/line_builder.rb +43 -0
  99. data/simplecov-1.0.0/lib/simplecov/source_file/method.rb +52 -0
  100. data/simplecov-1.0.0/lib/simplecov/source_file/method_builder.rb +58 -0
  101. data/simplecov-1.0.0/lib/simplecov/source_file/ruby_data_parser.rb +88 -0
  102. data/simplecov-1.0.0/lib/simplecov/source_file/skip_chunks.rb +75 -0
  103. data/simplecov-1.0.0/lib/simplecov/source_file/source_loader.rb +63 -0
  104. data/simplecov-1.0.0/lib/simplecov/source_file/statistics.rb +57 -0
  105. data/simplecov-1.0.0/lib/simplecov/source_file.rb +189 -0
  106. data/simplecov-1.0.0/lib/simplecov/static_coverage_extractor/method_collector.rb +55 -0
  107. data/simplecov-1.0.0/lib/simplecov/static_coverage_extractor/visitor.rb +171 -0
  108. data/simplecov-1.0.0/lib/simplecov/static_coverage_extractor.rb +110 -0
  109. data/simplecov-1.0.0/lib/simplecov/useless_results_remover.rb +27 -0
  110. data/simplecov-1.0.0/lib/simplecov/version.rb +5 -0
  111. data/simplecov-1.0.0/lib/simplecov-html.rb +4 -0
  112. data/simplecov-1.0.0/lib/simplecov.rb +255 -0
  113. data/simplecov-1.0.0/lib/simplecov_json_formatter.rb +4 -0
  114. data/simplecov-1.0.0/schemas/coverage-v1.0.schema.json +306 -0
  115. data/simplecov-1.0.0/schemas/coverage.schema.json +306 -0
  116. data/ultra-pro-pkg.gemspec +12 -0
  117. metadata +156 -0
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "color"
4
+ require_relative "cli/dotfile"
5
+ require_relative "cli/clean"
6
+ require_relative "cli/coverage"
7
+ require_relative "cli/diff"
8
+ require_relative "cli/merge"
9
+ require_relative "cli/open"
10
+ require_relative "cli/report"
11
+ require_relative "cli/run"
12
+ require_relative "cli/serve"
13
+ require_relative "cli/uncovered"
14
+
15
+ module SimpleCov
16
+ # Lightweight command-line front-end. `run` dispatches a subcommand
17
+ # (`coverage`, `report`, `uncovered`, `merge`, `diff`, `open`, etc.) —
18
+ # see the `usage` text below for the full list, or run `simplecov help`.
19
+ #
20
+ # Read-only subcommands consume JSONFormatter output (`coverage.json`),
21
+ # which the bundled HTMLFormatter already drops alongside the HTML, so
22
+ # no runtime hooking is needed for those. Default paths follow the
23
+ # project's `.simplecov` `SimpleCov.coverage_dir` setting when one is
24
+ # present, so a project that writes its report somewhere other than
25
+ # `coverage/` doesn't have to pass `--input` / `--report` every
26
+ # invocation.
27
+ module CLI
28
+ COMMANDS = {
29
+ "coverage" => Coverage,
30
+ "run" => Run,
31
+ "open" => Open,
32
+ "report" => Report,
33
+ "uncovered" => Uncovered,
34
+ "merge" => Merge,
35
+ "diff" => Diff,
36
+ "serve" => Serve,
37
+ "clean" => Clean
38
+ }.freeze
39
+
40
+ module_function
41
+
42
+ # Resolved once per process. Walks up from cwd looking for a
43
+ # `.simplecov`; if present, the file is loaded with
44
+ # `SimpleCov.start` neutered so it can't trigger coverage tracking
45
+ # or an at_exit hook just because we asked it for a config value.
46
+ def coverage_dir
47
+ @coverage_dir ||= Dotfile.coverage_dir
48
+ end
49
+
50
+ def default_input
51
+ File.join(coverage_dir, "coverage.json")
52
+ end
53
+
54
+ # Resolve "should this subcommand colorize?" once per invocation.
55
+ # `--no-color` (opts[:no_color]) is the per-invocation kill-switch;
56
+ # otherwise we defer to `SimpleCov::Color.enabled?`, which honors
57
+ # `NO_COLOR` / `FORCE_COLOR` and falls back to `stream.tty?`.
58
+ def color_enabled?(opts, stream)
59
+ return false if opts[:no_color]
60
+
61
+ SimpleCov::Color.enabled?(stream)
62
+ end
63
+
64
+ def default_report
65
+ File.join(coverage_dir, "index.html")
66
+ end
67
+
68
+ def default_resultset
69
+ File.join(coverage_dir, ".resultset.json")
70
+ end
71
+
72
+ # Returns a process exit status (0 on success, non-zero on error).
73
+ def run(argv, stdout: $stdout, stderr: $stderr)
74
+ command, *rest = argv
75
+ handler = COMMANDS[command]
76
+ return handler.run(rest, stdout: stdout, stderr: stderr) if handler
77
+ return stdout.puts(usage) || 0 if [nil, "help", "--help", "-h"].include?(command)
78
+
79
+ stderr.puts("simplecov: unknown command #{command.inspect}", usage)
80
+ 1
81
+ end
82
+
83
+ def usage
84
+ <<~USAGE
85
+ Usage: simplecov <command> [options]
86
+
87
+ Commands:
88
+ run <command...> Execute <command> with simplecov pre-loaded
89
+ (so a coverage report is generated even
90
+ when the project has no test_helper hook)
91
+ coverage <path> Print coverage stats for the given file
92
+ report Print the overall summary and group totals
93
+ uncovered List the lowest-coverage files
94
+ merge <files...> Merge multiple .resultset.json files
95
+ diff <baseline> Show per-file coverage delta vs baseline
96
+ open Open the HTML report in the default browser
97
+ serve Serve the coverage report over HTTP
98
+ clean Remove the coverage report directory
99
+ help Show this message
100
+
101
+ Default paths follow SimpleCov.coverage_dir from a project's
102
+ `.simplecov` when one is present (#{coverage_dir} for this run).
103
+
104
+ coverage / report / uncovered / diff options:
105
+ --input PATH Read from PATH instead of #{default_input}
106
+ --no-color Disable colorized percentages
107
+ (also honors NO_COLOR / FORCE_COLOR env)
108
+
109
+ coverage options:
110
+ --json Print the file's JSON entry verbatim
111
+
112
+ report options:
113
+ --json Emit totals and group sections as JSON
114
+
115
+ uncovered options:
116
+ --threshold N Only show files below N% coverage
117
+ --top N Show at most N files (default: 10)
118
+ --criterion C line, branch, or method (default: line)
119
+ --json Emit results as a JSON array (for CI)
120
+
121
+ merge options:
122
+ --output PATH Write merged resultset to PATH
123
+ (default: #{default_resultset})
124
+ --honor-timeout Drop entries older than merge_timeout
125
+ --dry-run Print what would be written without
126
+ actually writing
127
+ -q, --quiet Suppress the success status line
128
+
129
+ diff options:
130
+ --fail-on-drop Exit non-zero when any file's coverage
131
+ dropped vs the baseline
132
+ --json Emit results as a JSON array (for CI)
133
+ --threshold N Only show files whose absolute delta
134
+ in any criterion is at least N%
135
+
136
+ open options:
137
+ --report PATH Open PATH instead of #{default_report}
138
+
139
+ serve options:
140
+ --port N Bind to port N (default: random open port)
141
+ --host HOST Bind to HOST (default: 127.0.0.1)
142
+
143
+ clean options:
144
+ --dry-run Print what would be removed without
145
+ deleting anything
146
+ -q, --quiet Suppress status lines
147
+ USAGE
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ # ANSI colorization for stderr diagnostics. Thresholds mirror the
5
+ # HTML formatter (>= 90 green, >= 75 yellow, otherwise red) so a
6
+ # team's mental model of "what's the cutoff" is the same whether
7
+ # they're reading the terminal output or the HTML report.
8
+ #
9
+ # Color precedence, highest first:
10
+ #
11
+ # - `SimpleCov.color = true` / `false` (programmatic override, wins
12
+ # over everything; default is `:auto` which falls through)
13
+ # - `NO_COLOR` env var (any non-empty value) → off (see no-color.org)
14
+ # - `FORCE_COLOR` env var (any non-empty value) → on
15
+ # - `stream.tty?` fallback
16
+ #
17
+ # `NO_COLOR` wins over `FORCE_COLOR` if both env vars are set.
18
+ module Color
19
+ GREEN_THRESHOLD = 90
20
+ YELLOW_THRESHOLD = 75
21
+
22
+ ANSI = {
23
+ red: "\e[31m",
24
+ yellow: "\e[33m",
25
+ green: "\e[32m",
26
+ reset: "\e[0m"
27
+ }.freeze
28
+
29
+ module_function
30
+
31
+ # `stream` is the IO that the colorized text is destined for. The
32
+ # formatter writes to stderr, so that's the default. CLI subcommands
33
+ # that print to stdout should pass `$stdout` so a redirected pipe
34
+ # doesn't get ANSI sequences. See the module-level comment for
35
+ # precedence.
36
+ def enabled?(stream = $stderr)
37
+ config = SimpleCov.color
38
+ return config if [true, false].include?(config)
39
+ return false if env_set?("NO_COLOR")
40
+ return true if env_set?("FORCE_COLOR")
41
+
42
+ stream.tty?
43
+ end
44
+
45
+ def for_percent(percent)
46
+ return :green if percent >= GREEN_THRESHOLD
47
+ return :yellow if percent >= YELLOW_THRESHOLD
48
+
49
+ :red
50
+ end
51
+
52
+ # Wrap `text` in the ANSI sequence for `color` (a key of ANSI).
53
+ # Returns the bare text if color is disabled. The `enabled:`
54
+ # keyword lets callers (e.g., CLI subcommands honoring `--no-color`)
55
+ # override the auto-detection without touching env vars.
56
+ def colorize(text, color, enabled: enabled?)
57
+ return text unless enabled
58
+
59
+ "#{ANSI.fetch(color)}#{text}#{ANSI.fetch(:reset)}"
60
+ end
61
+
62
+ # Render `percent` as a fixed "NN.NN%" string colored by which
63
+ # threshold band it falls into. Callers that want a different
64
+ # rendering of the number can pass the pre-rendered `text`.
65
+ def colorize_percent(percent, text = nil, enabled: enabled?)
66
+ colorize(text || format("%.2f%%", percent), for_percent(percent), enabled: enabled)
67
+ end
68
+
69
+ def env_set?(name)
70
+ value = ENV.fetch(name, nil)
71
+ value && !value.empty?
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../source_file/ruby_data_parser"
4
+
5
+ module SimpleCov
6
+ module Combine
7
+ #
8
+ # Combine different branch coverage results on single file.
9
+ #
10
+ # Should be called through `SimpleCov.combine`.
11
+ module BranchesCombiner
12
+ module_function
13
+
14
+ #
15
+ # Return merged branches or the existed branch if other is missing.
16
+ #
17
+ # Branches inside files are always same if they exist, the difference only in coverage count.
18
+ # Branch coverage report for any conditional case is built from hash, it's key is a condition and
19
+ # it's body is a hash << keys from condition and value is coverage rate >>.
20
+ # ex: branches => { [:if, 3, 8, 6, 8, 36] =>
21
+ # {[:then, 4, 8, 6, 8, 12] => 1, [:else, 5, 8, 6, 8, 36] => 2}, ... }
22
+ # We create copy of result and update it values depending on the combined branches coverage values.
23
+ #
24
+ # @return [Hash]
25
+ #
26
+ def combine(coverage_a, coverage_b)
27
+ combined = [coverage_a, coverage_b].each_with_object({}) do |coverage, memo|
28
+ coverage.each do |condition, branches_inside|
29
+ condition_key = tuple_identity(condition)
30
+ condition_tuple, merged_branches = memo[condition_key] ||= [condition, {}]
31
+ merge_branches(merged_branches, branches_inside)
32
+ memo[condition_key] = [condition_tuple, merged_branches]
33
+ end
34
+ end
35
+
36
+ combined.values.to_h { |condition, branches| [condition, branches.values.to_h] }
37
+ end
38
+
39
+ def merge_branches(target, source)
40
+ source.each do |branch, count|
41
+ branch_key = tuple_identity(branch)
42
+ branch_tuple, existing_count = target[branch_key]
43
+ target[branch_key] = [branch_tuple || branch, existing_count ? existing_count + count : count]
44
+ end
45
+ end
46
+
47
+ def tuple_identity(tuple)
48
+ tuple = SourceFile::RubyDataParser.call(tuple)
49
+ type, _id, start_line, start_column, end_line, end_column = tuple
50
+ [type, start_line, start_column, end_line, end_column]
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ module Combine
5
+ #
6
+ # Handle combining two coverage results for same file
7
+ #
8
+ # Should be called through `SimpleCov.combine`.
9
+ module FilesCombiner
10
+ module_function
11
+
12
+ #
13
+ # Combines the results for 2 coverages of a file.
14
+ #
15
+ # @return [Hash]
16
+ #
17
+ def combine(coverage_a, coverage_b)
18
+ combination = {"lines" => Combine.combine(LinesCombiner, coverage_a["lines"], coverage_b["lines"])}
19
+ if SimpleCov.branch_coverage?
20
+ combined_branches = Combine.combine(BranchesCombiner, coverage_a["branches"], coverage_b["branches"])
21
+ combination["branches"] = combined_branches || {}
22
+ end
23
+ if SimpleCov.method_coverage?
24
+ combination["methods"] = Combine.combine(MethodsCombiner, coverage_a["methods"], coverage_b["methods"])
25
+ end
26
+ combination
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ module Combine
5
+ #
6
+ # Combine two different lines coverage results on same file
7
+ #
8
+ # Should be called through `SimpleCov.combine`.
9
+ module LinesCombiner
10
+ module_function
11
+
12
+ # Build a fresh array sized to the longer input. The previous
13
+ # implementation mutated whichever input was longer in place,
14
+ # which could surprise callers holding a reference to that array
15
+ # (e.g. the parsed `coverage` key of a resultset hash being
16
+ # passed into a second merge).
17
+ def combine(coverage_a, coverage_b)
18
+ size = [coverage_a.size, coverage_b.size].max
19
+ Array.new(size) { |i| merge_line_coverage(coverage_a[i], coverage_b[i]) }
20
+ end
21
+
22
+ # Two runs of the same source file should agree on which lines
23
+ # are coverage-relevant (`nil` for comments / whitespace, `0`+
24
+ # for executable). When they don't, treat "relevant on either
25
+ # side" as relevant rather than masking a real `0` as `nil`,
26
+ # which would silently drop an uncovered line from the
27
+ # denominator and inflate the percentage.
28
+ #
29
+ # Logic:
30
+ #
31
+ # => nil + nil = nil
32
+ # => nil + int = int (preserves a relevant-but-uncovered 0)
33
+ # => int + int = int (sum)
34
+ #
35
+ # @param [Integer || nil] first_val
36
+ # @param [Integer || nil] second_val
37
+ # @return [Integer || nil]
38
+ def merge_line_coverage(first_val, second_val)
39
+ return nil if first_val.nil? && second_val.nil?
40
+
41
+ first_val.to_i + second_val.to_i
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ module Combine
5
+ #
6
+ # Combine different method coverage results on a single file.
7
+ #
8
+ # Should be called through `SimpleCov.combine`.
9
+ module MethodsCombiner
10
+ module_function
11
+
12
+ #
13
+ # Return merged methods or the existing methods if other is missing.
14
+ #
15
+ # Method coverage is a flat hash mapping method identifiers to hit counts.
16
+ # Combining sums the hit counts for matching methods and preserves methods
17
+ # that only appear in one result.
18
+ #
19
+ # @return [Hash]
20
+ #
21
+ def combine(coverage_a, coverage_b)
22
+ coverage_a.merge(coverage_b) { |_key, a_count, b_count| a_count + b_count }
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ module Combine
5
+ # There might be reports from different kinds of tests,
6
+ # e.g. RSpec and Cucumber. We need to combine their results
7
+ # into unified one. This class does that.
8
+ # To unite the results on file basis, it leverages
9
+ # the combine of lines and branches inside each file within given results.
10
+ module ResultsCombiner
11
+ module_function
12
+
13
+ #
14
+ # Combine process explanation
15
+ # => ResultCombiner: define all present files between results and start combine on file level.
16
+ # ==> FileCombiner: collect result of next combine levels lines, branches, and methods.
17
+ # ===> LinesCombiner: combine lines results.
18
+ # ===> BranchesCombiner: combine branches results.
19
+ # ===> MethodsCombiner: combine methods results.
20
+ #
21
+ # @return [Hash]
22
+ #
23
+ def combine(*results)
24
+ results.reduce({}) do |combined_results, next_result|
25
+ combine_result_sets(combined_results, next_result)
26
+ end
27
+ end
28
+
29
+ #
30
+ # Manage combining results on files level
31
+ #
32
+ # @param [Hash] combined_results
33
+ # @param [Hash] result
34
+ #
35
+ # @return [Hash]
36
+ #
37
+ def combine_result_sets(combined_results, result)
38
+ results_files = combined_results.keys | result.keys
39
+
40
+ results_files.to_h do |file_name|
41
+ [file_name, combine_file_coverage(
42
+ combined_results[file_name],
43
+ result[file_name]
44
+ )]
45
+ end
46
+ end
47
+
48
+ #
49
+ # Combine two files coverage results
50
+ #
51
+ # @param [Hash] coverage_a
52
+ # @param [Hash] coverage_b
53
+ #
54
+ # @return [Hash]
55
+ #
56
+ def combine_file_coverage(coverage_a, coverage_b)
57
+ Combine.combine(Combine::FilesCombiner, coverage_a, coverage_b)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ # Functionally for combining coverage results
5
+ #
6
+ module Combine
7
+ module_function
8
+
9
+ #
10
+ # Combine two coverage based on the given combiner_module.
11
+ #
12
+ # Combiners should always be called through this interface,
13
+ # as it takes care of short-circuiting of one of the coverages is nil.
14
+ #
15
+ # @return [Hash]
16
+ def combine(combiner_module, coverage_a, coverage_b)
17
+ return existing_coverage(coverage_a, coverage_b) if empty_coverage?(coverage_a, coverage_b)
18
+
19
+ combiner_module.combine(coverage_a, coverage_b)
20
+ end
21
+
22
+ def empty_coverage?(coverage_a, coverage_b)
23
+ !(coverage_a && coverage_b)
24
+ end
25
+
26
+ def existing_coverage(coverage_a, coverage_b)
27
+ coverage_a || coverage_b
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ #
5
+ # Helper that tries to find out what test suite is running (for SimpleCov.command_name)
6
+ #
7
+ module CommandGuesser
8
+ class << self
9
+ # Storage for the original command line call that invoked the test suite.
10
+ # This has got to be stored as early as possible because i.e. rake and test/unit 2
11
+ # have a habit of tampering with ARGV, which makes i.e. the automatic distinction
12
+ # between rails unit/functional/integration tests impossible without this cached
13
+ # item.
14
+ attr_accessor :original_run_command
15
+
16
+ def guess
17
+ [from_command_line_options || from_defined_constants, parallel_data].compact.join(" ")
18
+ end
19
+
20
+ private
21
+
22
+ # When parallel_tests (or a compatible runner) is driving the suite,
23
+ # tag the command name with this worker's position in the pool.
24
+ def parallel_data
25
+ groups, number = ENV.values_at("PARALLEL_TEST_GROUPS", "TEST_ENV_NUMBER")
26
+ return unless groups && number
27
+
28
+ # parallel_tests sets the first worker's TEST_ENV_NUMBER to "" rather
29
+ # than "1"; restore the position so the rendered label reads cleanly.
30
+ number = "1" if number.empty?
31
+ "(#{number}/#{groups})"
32
+ end
33
+
34
+ COMMAND_LINE_FRAMEWORKS = {
35
+ %r{test/functional/} => "Functional Tests",
36
+ %r{test/\{.*functional.*\}/} => "Functional Tests",
37
+ %r{test/integration/} => "Integration Tests",
38
+ %r{test/} => "Unit Tests",
39
+ /spec/ => "RSpec",
40
+ /cucumber/ => "Cucumber Features",
41
+ /features/ => "Cucumber Features"
42
+ }.freeze
43
+ private_constant :COMMAND_LINE_FRAMEWORKS
44
+
45
+ def from_command_line_options
46
+ COMMAND_LINE_FRAMEWORKS.find { |pattern, _| pattern.match?(original_run_command.to_s) }&.last
47
+ end
48
+
49
+ # Inner array literals after the first are flagged uncovered by Ruby's
50
+ # Coverage module even though the constant evaluates as a whole — known
51
+ # quirk with multi-line array literals.
52
+ DEFINED_CONSTANT_FRAMEWORKS = [
53
+ ["RSpec", -> { defined?(::RSpec) }],
54
+ ["Unit Tests", -> { defined?(Test::Unit) }], # simplecov:disable
55
+ ["Minitest", -> { defined?(::Minitest) }], # simplecov:disable
56
+ ["MiniTest", -> { defined?(MiniTest) }] # simplecov:disable
57
+ ].freeze
58
+ private_constant :DEFINED_CONSTANT_FRAMEWORKS
59
+
60
+ # If the command regexps fail, let's try checking defined constants.
61
+ def from_defined_constants
62
+ # simplecov:disable branch — first iter returns when ::RSpec is defined; later branches unreachable
63
+ DEFINED_CONSTANT_FRAMEWORKS.each { |name, defined_check| return name if defined_check.call }
64
+ # simplecov:enable branch
65
+
66
+ # TODO: Provide link to docs/wiki article
67
+ # simplecov:disable — only fires when no framework is detected, which
68
+ # is impossible while our own specs are running under rspec
69
+ warn(
70
+ "SimpleCov failed to recognize the test framework and/or suite used. " \
71
+ "Please specify manually using SimpleCov.command_name 'Unit Tests'."
72
+ )
73
+ "Unknown Test Framework"
74
+ # simplecov:enable
75
+ end
76
+ end
77
+ end
78
+ end