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,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ # Coverage-entry filters scoped to branch / method criteria. See
5
+ # `ignore_branches` and `ignore_methods`, and #1033 /
6
+ # #1046 for the synthetic-entry detection rationale.
7
+ module Configuration
8
+ # Branch types accepted by `ignore_branches`.
9
+ IGNORABLE_BRANCH_TYPES = %i[implicit_else eval_generated].freeze
10
+ # Method types accepted by `ignore_methods`.
11
+ IGNORABLE_METHOD_TYPES = %i[eval_generated].freeze
12
+
13
+ # Variadic; multiple calls union. Setting is recorded regardless
14
+ # of whether branch coverage is enabled at call time. See #1033, #1046.
15
+ def ignore_branches(*types)
16
+ types.each { |type| raise_if_branch_type_unsupported(type) }
17
+ ignored_branches.concat(types).uniq!
18
+ ignored_branches
19
+ end
20
+
21
+ def ignored_branches
22
+ @ignored_branches ||= []
23
+ end
24
+
25
+ def ignored_branch?(type)
26
+ ignored_branches.include?(type)
27
+ end
28
+
29
+ # See `ignore_branches`. The only supported method-type token today
30
+ # is `:eval_generated`; see #1046 for the rationale.
31
+ def ignore_methods(*types)
32
+ types.each { |type| raise_if_method_type_unsupported(type) }
33
+ ignored_methods.concat(types).uniq!
34
+ ignored_methods
35
+ end
36
+
37
+ def ignored_methods
38
+ @ignored_methods ||= []
39
+ end
40
+
41
+ def ignored_method?(type)
42
+ ignored_methods.include?(type)
43
+ end
44
+
45
+ private
46
+
47
+ def raise_if_branch_type_unsupported(type)
48
+ return if IGNORABLE_BRANCH_TYPES.member?(type)
49
+
50
+ raise SimpleCov::ConfigurationError,
51
+ "Unsupported branch type #{type.inspect} for `ignore_branches`. " \
52
+ "Supported values are #{IGNORABLE_BRANCH_TYPES.inspect}"
53
+ end
54
+
55
+ def raise_if_method_type_unsupported(type)
56
+ return if IGNORABLE_METHOD_TYPES.member?(type)
57
+
58
+ raise SimpleCov::ConfigurationError,
59
+ "Unsupported method type #{type.inspect} for `ignore_methods`. " \
60
+ "Supported values are #{IGNORABLE_METHOD_TYPES.inspect}"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ # Result merging and subprocess / parallel-test coordination:
5
+ # `merging`, `merge_subprocesses`, `merge_timeout`, `parallel_tests`.
6
+ module Configuration
7
+ #
8
+ # Get or set whether SimpleCov should hook `Process._fork` to
9
+ # attach itself to subprocesses. Required when the suite uses
10
+ # parallel test workers (e.g. Rails' `parallelize(workers:)`).
11
+ # Defaults to false.
12
+ #
13
+ def merge_subprocesses(value = nil)
14
+ return @enable_for_subprocesses if defined?(@enable_for_subprocesses) && value.nil?
15
+
16
+ @enable_for_subprocesses = value || false
17
+ end
18
+
19
+ # @api private — predicate used by `start_tracking` to decide
20
+ # whether to install the fork hook.
21
+ def enabled_for_subprocesses?
22
+ defined?(@enable_for_subprocesses) ? @enable_for_subprocesses : false
23
+ end
24
+
25
+ #
26
+ # Get or set whether SimpleCov should auto-require the
27
+ # `parallel_tests` gem when it sees `TEST_ENV_NUMBER` /
28
+ # `PARALLEL_TEST_GROUPS` in the environment. Defaults to auto-detect
29
+ # (nil). See #1018.
30
+ #
31
+ def parallel_tests(value = :__no_arg__)
32
+ return defined?(@parallel_tests) ? @parallel_tests : nil if value == :__no_arg__
33
+
34
+ @parallel_tests = value
35
+ end
36
+
37
+ # DEPRECATED: alias for `merge_subprocesses`. Same value/behavior.
38
+ def enable_for_subprocesses(value = nil)
39
+ SimpleCov::Deprecation.warn("`SimpleCov.enable_for_subprocesses` is deprecated. " \
40
+ "Replace with `SimpleCov.merge_subprocesses` (same value, same behavior).")
41
+ return @enable_for_subprocesses if defined?(@enable_for_subprocesses) && value.nil?
42
+
43
+ @enable_for_subprocesses = value || false
44
+ end
45
+
46
+ #
47
+ # Get or set whether to merge results from multiple test suites
48
+ # (test:units, test:functionals, cucumber, ...) into a single
49
+ # coverage report. Defaults to true.
50
+ #
51
+ def merging(use = nil)
52
+ @use_merging = use unless use.nil?
53
+ @use_merging = true unless defined?(@use_merging) && @use_merging == false
54
+ @use_merging
55
+ end
56
+
57
+ #
58
+ # Get or set whether this process owns final merge processing:
59
+ # waiting for sibling workers, building the merged result, formatting,
60
+ # enforcing thresholds, and writing `.last_run.json`.
61
+ #
62
+ # Defaults to true, except for recognized multi-worker parallel runs
63
+ # that explicitly write to a custom coverage destination while merging
64
+ # is enabled. Those runs are likely using an external `SimpleCov.collate`
65
+ # step to finalize the merge.
66
+ #
67
+ def finalize_merge(value = :__no_arg__)
68
+ unless value == :__no_arg__
69
+ @finalize_merge = value
70
+ @finalize_merge_explicit = true
71
+ end
72
+
73
+ return @finalize_merge if defined?(@finalize_merge_explicit) && @finalize_merge_explicit
74
+
75
+ inferred = inferred_finalize_merge?
76
+ warn_about_inferred_finalize_merge unless inferred
77
+ inferred
78
+ end
79
+
80
+ def finalize_merge?
81
+ finalize_merge
82
+ end
83
+
84
+ # @api private
85
+ def merge_finalization_owner?
86
+ collating_result? || finalize_merge?
87
+ end
88
+
89
+ # DEPRECATED: alias for `merging`. Same value, same behavior.
90
+ def use_merging(use = nil)
91
+ SimpleCov::Deprecation.warn("`SimpleCov.use_merging` is deprecated. " \
92
+ "Replace with `SimpleCov.merging` (same value, same behavior).")
93
+ @use_merging = use unless use.nil?
94
+ @use_merging = true unless defined?(@use_merging) && @use_merging == false
95
+ end
96
+
97
+ #
98
+ # Defines the maximum age (in seconds) of a resultset to still be
99
+ # included in merged results. Default is 600 seconds (10 minutes).
100
+ #
101
+ def merge_timeout(seconds = nil)
102
+ @merge_timeout = seconds if seconds.is_a?(Integer)
103
+ @merge_timeout ||= 600
104
+ end
105
+
106
+ #
107
+ # Defines how long (in seconds) the reporting process waits for the
108
+ # remaining parallel-test workers to write their resultsets before it
109
+ # proceeds with a partial merge. Default is 60 seconds. Raise it when a
110
+ # slow worker routinely finishes well after the others, so its coverage
111
+ # is still included and the minimum / maximum coverage checks aren't
112
+ # skipped against a partial total.
113
+ #
114
+ def parallel_wait_timeout(seconds = nil)
115
+ @parallel_wait_timeout = seconds if seconds.is_a?(Integer)
116
+ @parallel_wait_timeout ||= 60
117
+ end
118
+
119
+ private
120
+
121
+ def inferred_finalize_merge?
122
+ return true unless merging
123
+
124
+ adapter = SimpleCov::ParallelAdapters.current
125
+ return true unless adapter
126
+ return true unless adapter.expected_worker_count > 1
127
+ return true unless parallel_worker_environment?
128
+ return true unless explicit_custom_coverage_destination?
129
+
130
+ false
131
+ end
132
+
133
+ def parallel_worker_environment?
134
+ ENV.key?("TEST_ENV_NUMBER") || ENV.key?("PARALLEL_TEST_GROUPS")
135
+ end
136
+
137
+ def explicit_custom_coverage_destination?
138
+ return false unless explicit_coverage_destination?
139
+
140
+ coverage_path != File.expand_path("coverage", root)
141
+ end
142
+
143
+ def explicit_coverage_destination?
144
+ (defined?(@coverage_path_explicit) && @coverage_path_explicit) ||
145
+ (defined?(@coverage_dir_explicit) && @coverage_dir_explicit)
146
+ end
147
+
148
+ def warn_about_inferred_finalize_merge
149
+ return if defined?(@finalize_merge_inference_warned) && @finalize_merge_inference_warned
150
+ return unless print_errors
151
+
152
+ @finalize_merge_inference_warned = true
153
+ warn SimpleCov::Color.colorize(inferred_finalize_merge_warning, :yellow)
154
+ end
155
+
156
+ def inferred_finalize_merge_warning
157
+ "SimpleCov inferred `finalize_merge false` because this parallel worker is merging " \
158
+ "into a custom coverage destination. Set `SimpleCov.finalize_merge false` to keep " \
159
+ "external collation ownership, or `SimpleCov.finalize_merge true` if this worker " \
160
+ "should wait, merge, format, enforce thresholds, and write `.last_run.json`. " \
161
+ "See https://github.com/simplecov-ruby/simplecov#merge-finalization-ownership."
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ # Coverage threshold configuration: `minimum_coverage`,
5
+ # `maximum_coverage`, `expected_coverage`, `maximum_coverage_drop`,
6
+ # `minimum_coverage_by_file`, `minimum_coverage_by_group`,
7
+ # `refuse_coverage_drop`, and friends.
8
+ module Configuration
9
+ #
10
+ # Defines the minimum overall coverage required for the testsuite to pass.
11
+ # Returns non-zero if the current coverage is below this threshold.
12
+ # Default is 0% (disabled).
13
+ #
14
+ def minimum_coverage(coverage = nil)
15
+ return @minimum_coverage ||= {} unless coverage
16
+
17
+ coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
18
+ raise_on_invalid_coverage(coverage, "minimum_coverage")
19
+ @minimum_coverage = coverage
20
+ end
21
+
22
+ def raise_on_invalid_coverage(coverage, coverage_setting)
23
+ coverage.each_key { |criterion| raise_if_criterion_disabled(criterion) }
24
+ coverage.each_value do |percent|
25
+ minimum_possible_coverage_exceeded(coverage_setting) if percent && percent > 100
26
+ end
27
+ end
28
+
29
+ #
30
+ # Defines the maximum overall coverage allowed for the testsuite to
31
+ # pass. Useful paired with `minimum_coverage` (or via
32
+ # `expected_coverage`) to pin coverage to an exact value, so an
33
+ # unexpected jump up fails the build. See #187.
34
+ #
35
+ def maximum_coverage(coverage = nil)
36
+ return @maximum_coverage ||= {} unless coverage
37
+
38
+ coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
39
+ raise_on_invalid_coverage(coverage, "maximum_coverage")
40
+ @maximum_coverage = coverage
41
+ end
42
+
43
+ #
44
+ # Pins the suite to an exact coverage figure by setting both
45
+ # `minimum_coverage` and `maximum_coverage`. See #187.
46
+ #
47
+ def expected_coverage(coverage = nil)
48
+ return minimum_coverage if coverage.nil?
49
+
50
+ minimum_coverage(coverage)
51
+ maximum_coverage(coverage)
52
+ end
53
+
54
+ #
55
+ # Defines the maximum coverage drop at once allowed for the
56
+ # testsuite to pass. Default is 100% (disabled).
57
+ #
58
+ def maximum_coverage_drop(coverage_drop = nil)
59
+ return @maximum_coverage_drop ||= {} unless coverage_drop
60
+
61
+ coverage_drop = {primary_coverage => coverage_drop} if coverage_drop.is_a?(Numeric)
62
+ raise_on_invalid_coverage(coverage_drop, "maximum_coverage_drop")
63
+ @maximum_coverage_drop = coverage_drop
64
+ end
65
+
66
+ #
67
+ # Defines the minimum coverage per file required for the testsuite
68
+ # to pass. Accepts a Numeric (global threshold on the primary
69
+ # criterion), a Symbol-keyed Hash (per-criterion globals), or a
70
+ # Hash mixing Symbol keys with String / Regexp keys to declare
71
+ # per-path overrides. See README and #575.
72
+ #
73
+ def minimum_coverage_by_file(coverage = nil)
74
+ return @minimum_coverage_by_file ||= {} unless coverage
75
+
76
+ coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
77
+ defaults, overrides = partition_per_file_thresholds(coverage)
78
+
79
+ SimpleCov::Deprecation.warn("`SimpleCov.minimum_coverage_by_file` is deprecated. " \
80
+ "Replace it with:\n#{per_file_coverage_replacement(defaults, overrides)}")
81
+
82
+ raise_on_invalid_coverage(defaults, "minimum_coverage_by_file")
83
+ overrides.each_value { |criteria| raise_on_invalid_coverage(criteria, "minimum_coverage_by_file") }
84
+
85
+ @minimum_coverage_by_file = defaults
86
+ @minimum_coverage_by_file_overrides = overrides
87
+ end
88
+
89
+ # Returns the per-path overrides set via `minimum_coverage_by_file`.
90
+ def minimum_coverage_by_file_overrides
91
+ @minimum_coverage_by_file_overrides ||= {}
92
+ end
93
+
94
+ #
95
+ # Defines the minimum coverage per group required for the testsuite
96
+ # to pass. Default is 0% (disabled).
97
+ #
98
+ def minimum_coverage_by_group(coverage = nil)
99
+ return @minimum_coverage_by_group ||= {} unless coverage
100
+
101
+ SimpleCov::Deprecation.warn("`SimpleCov.minimum_coverage_by_group` is deprecated. " \
102
+ "Replace it with:\n#{per_group_coverage_replacement(coverage)}")
103
+ @minimum_coverage_by_group = coverage.dup.transform_values do |group_coverage|
104
+ group_coverage = {primary_coverage => group_coverage} if group_coverage.is_a?(Numeric)
105
+ raise_on_invalid_coverage(group_coverage, "minimum_coverage_by_group")
106
+ group_coverage
107
+ end
108
+ end
109
+
110
+ #
111
+ # Refuses any coverage drop. Coverage is only allowed to increase.
112
+ #
113
+ def refuse_coverage_drop(*criteria)
114
+ criteria = coverage_criteria if criteria.empty?
115
+ maximum_coverage_drop(criteria.to_h { |c| [c, 0] })
116
+ end
117
+
118
+ private
119
+
120
+ # Split a `minimum_coverage_by_file` argument into Symbol-keyed
121
+ # criterion defaults and String/Regexp-keyed per-path overrides;
122
+ # normalize Numeric override values to `{primary_coverage => N}`
123
+ # so downstream code only has one shape to handle.
124
+ def partition_per_file_thresholds(coverage)
125
+ coverage.each_key { |key| validate_per_file_key(key) }
126
+ defaults, raw = coverage.partition { |key, _| key.is_a?(Symbol) }.map(&:to_h)
127
+ overrides = raw.transform_values { |value| value.is_a?(Numeric) ? {primary_coverage => value} : value }
128
+ [defaults, overrides]
129
+ end
130
+
131
+ def validate_per_file_key(key)
132
+ return if key.is_a?(Symbol) || key.is_a?(String) || key.is_a?(Regexp)
133
+
134
+ raise SimpleCov::ConfigurationError,
135
+ "minimum_coverage_by_file keys must be Symbol (criterion), String, or Regexp; got #{key.inspect}"
136
+ end
137
+
138
+ def minimum_possible_coverage_exceeded(coverage_option)
139
+ warn "The coverage you set for #{coverage_option} is greater than 100%"
140
+ end
141
+
142
+ # Render the `coverage` configuration equivalent to a (deprecated)
143
+ # `minimum_coverage_by_file` argument so the deprecation warning can be
144
+ # copy-pasted verbatim into the user's config.
145
+ def per_file_coverage_replacement(defaults, overrides)
146
+ by_criterion = Hash.new { |hash, criterion| hash[criterion] = [] }
147
+ defaults.each { |criterion, percent| by_criterion[criterion] << "minimum_per_file #{percent}" }
148
+ overrides.each do |target, criteria|
149
+ criteria.each do |criterion, percent|
150
+ by_criterion[criterion] << "minimum_per_file #{percent}, only: #{target.inspect}"
151
+ end
152
+ end
153
+ render_coverage_blocks(by_criterion)
154
+ end
155
+
156
+ # Same, for a (deprecated) `minimum_coverage_by_group` argument.
157
+ def per_group_coverage_replacement(coverage)
158
+ by_criterion = Hash.new { |hash, criterion| hash[criterion] = [] }
159
+ coverage.each do |group_name, group_coverage|
160
+ group_coverage = {primary_coverage => group_coverage} if group_coverage.is_a?(Numeric)
161
+ group_coverage.each do |criterion, percent|
162
+ by_criterion[criterion] << "minimum_per_group #{percent}, only: #{group_name.inspect}"
163
+ end
164
+ end
165
+ render_coverage_blocks(by_criterion)
166
+ end
167
+
168
+ def render_coverage_blocks(by_criterion)
169
+ by_criterion.map do |criterion, statements|
170
+ " coverage(#{criterion.inspect}) { #{statements.join('; ')} }"
171
+ end.join("\n")
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+
5
+ module SimpleCov
6
+ #
7
+ # Bundles the configuration options used for SimpleCov. All methods
8
+ # defined here are usable from SimpleCov directly. Please check out
9
+ # SimpleCov documentation for further info.
10
+ #
11
+ module Configuration
12
+ #
13
+ # The root for the project. This defaults to the
14
+ # current working directory.
15
+ #
16
+ # Configure with SimpleCov.root('/my/project/path')
17
+ #
18
+ def root(root = nil)
19
+ return @root if defined?(@root) && root.nil?
20
+
21
+ @coverage_path = nil unless @coverage_path_explicit # invalidate cache
22
+ @root = File.expand_path(root || Dir.getwd)
23
+ end
24
+
25
+ #
26
+ # The name of the output and cache directory. Defaults to 'coverage'
27
+ #
28
+ # Configure with SimpleCov.coverage_dir('cov')
29
+ #
30
+ def coverage_dir(dir = nil)
31
+ return @coverage_dir if defined?(@coverage_dir) && dir.nil?
32
+
33
+ @coverage_path = nil unless @coverage_path_explicit # invalidate cache
34
+ @coverage_dir_explicit = true unless dir.nil?
35
+ @coverage_dir = dir || "coverage"
36
+ end
37
+
38
+ #
39
+ # Returns the full path to the output directory. By default
40
+ # constructed from `SimpleCov.root` + `SimpleCov.coverage_dir`, but
41
+ # callers can override with an arbitrary absolute path — handy for
42
+ # out-of-tree build directories. See #716.
43
+ #
44
+ # Reading is pure: the directory is only created when a path is
45
+ # explicitly assigned (the user has signaled they intend to write
46
+ # there). The codepaths that actually write into the directory
47
+ # (formatters, `LastRun`, `ResultsetStore`) ensure existence
48
+ # themselves, so read-only CLI subcommands that interpolate the
49
+ # path into status text don't materialize a stray `coverage/`
50
+ # directory.
51
+ #
52
+ def coverage_path(path = nil)
53
+ if path
54
+ @coverage_path = File.expand_path(path)
55
+ @coverage_path_explicit = true
56
+ FileUtils.mkdir_p @coverage_path
57
+ end
58
+
59
+ @coverage_path ||= File.expand_path(coverage_dir, root)
60
+ end
61
+
62
+ #
63
+ # The name of the command (a.k.a. Test Suite) currently running.
64
+ # Used for result merging and caching. Auto-detected; set explicitly
65
+ # with SimpleCov.command_name("test:units").
66
+ #
67
+ def command_name(name = nil)
68
+ @name = name unless name.nil?
69
+ @name ||= SimpleCov::CommandGuesser.guess
70
+ @name
71
+ end
72
+
73
+ # Returns the hash of available profiles
74
+ def profiles
75
+ @profiles ||= SimpleCov::Profiles.new
76
+ end
77
+
78
+ #
79
+ # Allows you to configure simplecov in a block instead of
80
+ # prepending SimpleCov to each config method.
81
+ #
82
+ def configure(&block)
83
+ block_context = block.binding.receiver
84
+
85
+ # If the block was defined in our own context, instance_exec is sufficient
86
+ return instance_exec(&block) if equal?(block_context)
87
+
88
+ # Copy the caller's instance variables in so that references like @filter
89
+ # inside the block resolve to the caller's values, not ours.
90
+ saved = swap_ivars_from(block_context)
91
+ instance_exec(&block)
92
+ ensure
93
+ restore_ivars(block_context, saved) if defined?(saved) && saved
94
+ end
95
+
96
+ #
97
+ # Gets or sets the behavior to process coverage results.
98
+ # By default, it stores/merges the current result and formats only
99
+ # from the final reporting process.
100
+ #
101
+ def at_exit(&block)
102
+ @at_exit = block if block
103
+ return @at_exit if @at_exit
104
+ return proc {} unless active_session?
105
+
106
+ @at_exit = proc do
107
+ result = SimpleCov.result
108
+ result.format! if result && SimpleCov.merge_finalization_owner? && SimpleCov.final_result_process?
109
+ end
110
+ end
111
+
112
+ # Whether SimpleCov has anything to do at exit: the Coverage module
113
+ # is actively tracking, or a `@result` has already been assembled
114
+ # (e.g. by `SimpleCov.collate`, which never starts Coverage).
115
+ def active_session?
116
+ SimpleCov.result? || (defined?(Coverage) && Coverage.running?)
117
+ end
118
+
119
+ #
120
+ # Gets or sets the behavior to start a new forked Process.
121
+ # Defaults to adding " (subprocess: #{serial})" to command_name and
122
+ # starting SimpleCov in quiet mode.
123
+ #
124
+ def at_fork(&block)
125
+ @at_fork = block if block
126
+ @at_fork ||= lambda { |_pid|
127
+ # Needs a name that's unique per worker within a run yet identical
128
+ # across runs. Build it from SimpleCov's stable fork serial rather
129
+ # than the OS pid: with the pid, every run produced uniquely-named
130
+ # results that never overwrote the previous run's, so they piled up
131
+ # in .resultset.json until merge_timeout and the merged report's
132
+ # file set drifted from run to run. See issue #1171.
133
+ SimpleCov.command_name "#{SimpleCov.command_name} (subprocess: #{SimpleCov.subprocess_serial})"
134
+ # be quiet, the parent process will use the regular formatter
135
+ SimpleCov.print_errors false
136
+ SimpleCov.formatter SimpleCov::Formatter::SimpleFormatter
137
+ SimpleCov.minimum_coverage 0
138
+ SimpleCov.start
139
+ }
140
+ end
141
+
142
+ #
143
+ # Returns the project name — defaults to the last dirname in
144
+ # SimpleCov.root, capitalized with underscores → spaces.
145
+ #
146
+ def project_name(new_name = nil)
147
+ return @project_name if defined?(@project_name) && @project_name && new_name.nil?
148
+
149
+ @project_name = new_name if new_name.is_a?(String)
150
+ @project_name ||= File.basename(root).capitalize.tr("_", " ")
151
+ end
152
+
153
+ private
154
+
155
+ # Copy instance variables from block_context into self, saving any
156
+ # of ours that would be clobbered. Returns the saved values for
157
+ # later restoration.
158
+ def swap_ivars_from(block_context)
159
+ saved = {}
160
+ our_ivars = instance_variables
161
+ block_context.instance_variables.each do |ivar|
162
+ saved[ivar] = instance_variable_get(ivar) if our_ivars.include?(ivar)
163
+ instance_variable_set(ivar, block_context.instance_variable_get(ivar))
164
+ end
165
+ saved
166
+ end
167
+
168
+ # Copy instance variables back to block_context and restore our saved values.
169
+ def restore_ivars(block_context, saved)
170
+ block_context.instance_variables.each do |ivar|
171
+ block_context.instance_variable_set(ivar, instance_variable_get(ivar))
172
+ end
173
+ saved.each { |ivar, value| instance_variable_set(ivar, value) }
174
+ end
175
+ end
176
+ end
177
+
178
+ require_relative "configuration/coverage"
179
+ require_relative "configuration/coverage_criteria"
180
+ require_relative "configuration/filters"
181
+ require_relative "configuration/formatting"
182
+ require_relative "configuration/ignored_entries"
183
+ require_relative "configuration/merging"
184
+ require_relative "configuration/thresholds"
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ # Holds the individual data of a coverage result.
5
+ #
6
+ # This is uniform across coverage criteria as they all have:
7
+ #
8
+ # * total - how many things to cover there are (total relevant loc/branches)
9
+ # * covered - how many of the coverables are hit
10
+ # * missed - how many of the coverables are missed
11
+ # * omitted - how many lines cannot be covered (blank lines/comments); only meaningful for line coverage
12
+ # * percent - percentage as covered/missed
13
+ # * strength - average hits per/coverable (will not exist for one shot lines format)
14
+ class CoverageStatistics
15
+ attr_reader :total, :covered, :missed, :omitted, :strength, :percent
16
+
17
+ def self.from(coverage_statistics)
18
+ sum_covered, sum_missed, sum_omitted, sum_total_strength =
19
+ coverage_statistics.reduce([0, 0, 0, 0.0]) do |(covered, missed, omitted, total_strength), stats|
20
+ [
21
+ covered + stats.covered,
22
+ missed + stats.missed,
23
+ omitted + stats.omitted,
24
+ # gotta remultiply with loc because files have different strength and loc
25
+ # giving them a different "weight" in total
26
+ total_strength + (stats.strength * stats.total)
27
+ ]
28
+ end
29
+
30
+ new(covered: sum_covered, missed: sum_missed, omitted: sum_omitted, total_strength: sum_total_strength)
31
+ end
32
+
33
+ # Requires only covered, missed and strength to be initialized.
34
+ #
35
+ # Other values are computed by this class.
36
+ def initialize(covered:, missed:, omitted: 0, total_strength: 0.0, percent: nil)
37
+ @covered = covered
38
+ @missed = missed
39
+ @omitted = omitted
40
+ @total = covered + missed
41
+ @percent = percent || compute_percent(covered, missed, total)
42
+ @strength = compute_strength(total_strength, total)
43
+ end
44
+
45
+ private
46
+
47
+ def compute_percent(covered, missed, total)
48
+ return 100.0 if missed.zero?
49
+
50
+ covered * 100.0 / total
51
+ end
52
+
53
+ def compute_strength(total_strength, total)
54
+ return 0.0 if total.zero?
55
+
56
+ total_strength.to_f / total
57
+ end
58
+ end
59
+ end