ceedling 1.1.3 → 1.1.4

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 (165) hide show
  1. checksums.yaml +4 -4
  2. data/GIT_COMMIT_SHA +1 -1
  3. data/README.md +1 -1
  4. data/assets/fake_crash_test_fixture.rb +14 -0
  5. data/assets/partial_all_module.h +11 -0
  6. data/assets/run_with_ubsan.rb +15 -0
  7. data/assets/same_dir_pairing_module.c +4 -0
  8. data/assets/same_dir_pairing_module.h +8 -0
  9. data/assets/same_dir_pairing_module_func.h +6 -0
  10. data/assets/same_dir_pairing_other.c +4 -0
  11. data/assets/same_dir_pairing_other.h +8 -0
  12. data/assets/test_example_file_ub_shift_overflow.c +22 -0
  13. data/assets/test_partial_all_module.c +16 -0
  14. data/assets/test_same_dir_pairing.c +23 -0
  15. data/docs/Changelog.md +21 -1
  16. data/docs/mkdocs/configuration/reference/index.md +8 -0
  17. data/docs/mkdocs/configuration/reference/partials.md +38 -0
  18. data/examples/wondrous_forest/src/LightSensor.c +21 -4
  19. data/examples/wondrous_forest/src/LightSensor.h +12 -4
  20. data/examples/wondrous_forest/test/TestLightSensor.c +34 -4
  21. data/lib/ceedling/c_extractor/c_extractor.rb +37 -11
  22. data/lib/ceedling/c_extractor/c_extractor_constants.rb +0 -3
  23. data/lib/ceedling/c_extractor/c_extractor_declarations.rb +26 -25
  24. data/lib/ceedling/c_extractor/c_extractor_functions.rb +5 -12
  25. data/lib/ceedling/config/configurator.rb +1 -0
  26. data/lib/ceedling/config/configurator_setup.rb +26 -0
  27. data/lib/ceedling/defaults.rb +8 -0
  28. data/lib/ceedling/file_path_utils.rb +7 -0
  29. data/lib/ceedling/file_wrapper.rb +8 -0
  30. data/lib/ceedling/generators/generator.rb +15 -0
  31. data/lib/ceedling/generators/generator_helper.rb +25 -6
  32. data/lib/ceedling/generators/generator_partials.rb +84 -3
  33. data/lib/ceedling/generators/generator_test_results_backtrace.rb +183 -83
  34. data/lib/ceedling/includes/includes.rb +66 -11
  35. data/lib/ceedling/objects.yml +5 -0
  36. data/lib/ceedling/partials/partializer.rb +18 -3
  37. data/lib/ceedling/partials/partializer_utils.rb +6 -1
  38. data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +43 -16
  39. data/lib/ceedling/test_invoker/test_build_executor.rb +19 -8
  40. data/lib/version.rb +1 -1
  41. data/mkdocs.yml +1 -0
  42. data/site-local/404.html +30 -0
  43. data/site-local/configuration/environment-vars.html +30 -0
  44. data/site-local/configuration/global-collections.html +30 -0
  45. data/site-local/configuration/index.html +30 -0
  46. data/site-local/configuration/loading.html +30 -0
  47. data/site-local/configuration/mixins.html +30 -0
  48. data/site-local/configuration/parallel-builds.html +30 -0
  49. data/site-local/configuration/project-file.html +30 -0
  50. data/site-local/configuration/reference/cexception.html +30 -0
  51. data/site-local/configuration/reference/cmock.html +30 -0
  52. data/site-local/configuration/reference/defines.html +30 -0
  53. data/site-local/configuration/reference/environment.html +30 -0
  54. data/site-local/configuration/reference/extension.html +30 -0
  55. data/site-local/configuration/reference/files.html +30 -0
  56. data/site-local/configuration/reference/flags.html +30 -0
  57. data/site-local/configuration/reference/index.html +36 -0
  58. data/site-local/configuration/reference/libraries.html +30 -0
  59. data/site-local/configuration/reference/mixins.html +30 -0
  60. data/site-local/configuration/reference/partials.html +4257 -0
  61. data/site-local/configuration/reference/paths.html +30 -0
  62. data/site-local/configuration/reference/plugins.html +30 -0
  63. data/site-local/configuration/reference/project.html +30 -0
  64. data/site-local/configuration/reference/release-build.html +31 -1
  65. data/site-local/configuration/reference/test-build.html +31 -1
  66. data/site-local/configuration/reference/test-runner.html +30 -0
  67. data/site-local/configuration/reference/tools.html +30 -0
  68. data/site-local/configuration/reference/unity.html +30 -0
  69. data/site-local/configuration/which-ceedling.html +30 -0
  70. data/site-local/development/index.html +30 -0
  71. data/site-local/development/plugins/configuration.html +30 -0
  72. data/site-local/development/plugins/index.html +30 -0
  73. data/site-local/development/plugins/plugin-subclass.html +30 -0
  74. data/site-local/development/plugins/rake-tasks.html +30 -0
  75. data/site-local/development/workflow.html +30 -0
  76. data/site-local/getting-started/command-line.html +30 -0
  77. data/site-local/getting-started/example-projects/cipher-quest.html +30 -0
  78. data/site-local/getting-started/example-projects/index.html +30 -0
  79. data/site-local/getting-started/example-projects/temp-sensor.html +30 -0
  80. data/site-local/getting-started/example-projects/wondrous-forest.html +30 -0
  81. data/site-local/getting-started/index.html +30 -0
  82. data/site-local/getting-started/installation.html +30 -0
  83. data/site-local/getting-started/quick-start.html +30 -0
  84. data/site-local/help.html +30 -0
  85. data/site-local/index.html +30 -0
  86. data/site-local/overview/build-system.html +30 -0
  87. data/site-local/overview/index.html +30 -0
  88. data/site-local/overview/test-environments.html +30 -0
  89. data/site-local/overview/tools-and-frameworks.html +30 -0
  90. data/site-local/plugins/beep.html +30 -0
  91. data/site-local/plugins/bullseye.html +30 -0
  92. data/site-local/plugins/command-hooks.html +30 -0
  93. data/site-local/plugins/compile-commands-json-db.html +30 -0
  94. data/site-local/plugins/cppcheck.html +30 -0
  95. data/site-local/plugins/dependencies.html +30 -0
  96. data/site-local/plugins/fff.html +30 -0
  97. data/site-local/plugins/gcov/examples.html +30 -0
  98. data/site-local/plugins/gcov/gcovr.html +30 -0
  99. data/site-local/plugins/gcov/index.html +30 -0
  100. data/site-local/plugins/gcov/overview.html +30 -0
  101. data/site-local/plugins/gcov/reportgenerator.html +30 -0
  102. data/site-local/plugins/gcov/reporting.html +30 -0
  103. data/site-local/plugins/gcov/setup.html +30 -0
  104. data/site-local/plugins/gcov/tool-versions.html +30 -0
  105. data/site-local/plugins/gcov/troubleshooting.html +30 -0
  106. data/site-local/plugins/index.html +30 -0
  107. data/site-local/plugins/module-generator.html +30 -0
  108. data/site-local/plugins/report-build-warnings-log.html +30 -0
  109. data/site-local/plugins/report-tests-gtestlike-stdout.html +30 -0
  110. data/site-local/plugins/report-tests-ide-stdout.html +30 -0
  111. data/site-local/plugins/report-tests-log-factory.html +30 -0
  112. data/site-local/plugins/report-tests-pretty-stdout.html +30 -0
  113. data/site-local/plugins/report-tests-raw-output-log.html +30 -0
  114. data/site-local/plugins/report-tests-teamcity-stdout.html +30 -0
  115. data/site-local/plugins/valgrind.html +30 -0
  116. data/site-local/project/release-history.html +30 -0
  117. data/site-local/project/upgrade.html +30 -0
  118. data/site-local/reference/build-directives.html +30 -0
  119. data/site-local/reference/command-line.html +30 -0
  120. data/site-local/reference/environment-vars.html +30 -0
  121. data/site-local/reference/gcov-plugin.html +30 -0
  122. data/site-local/reference/global-collections.html +30 -0
  123. data/site-local/reference/index.html +30 -0
  124. data/site-local/reference/partials-macros.html +30 -0
  125. data/site-local/reference/project-configuration.html +30 -0
  126. data/site-local/sitemap.xml.gz +0 -0
  127. data/site-local/snapshot/examples/cipher_quest/index.html +30 -0
  128. data/site-local/snapshot/examples/temp_sensor/index.html +30 -0
  129. data/site-local/snapshot/examples/wondrous_forest/index.html +30 -0
  130. data/site-local/testing-guide/build-directives.html +30 -0
  131. data/site-local/testing-guide/conventions.html +30 -0
  132. data/site-local/testing-guide/frameworks.html +30 -0
  133. data/site-local/testing-guide/index.html +30 -0
  134. data/site-local/testing-guide/partials/configuration.html +30 -0
  135. data/site-local/testing-guide/partials/conventions.html +30 -0
  136. data/site-local/testing-guide/partials/directives.html +30 -0
  137. data/site-local/testing-guide/partials/example.html +30 -0
  138. data/site-local/testing-guide/partials/index.html +30 -0
  139. data/site-local/testing-guide/partials/overview.html +30 -0
  140. data/site-local/testing-guide/partials/variables.html +30 -0
  141. data/site-local/testing-guide/test-cases.html +30 -0
  142. data/site-local/testing-guide/test-sample.html +30 -0
  143. data/site-local/testing-guide/test-suite-anatomy.html +30 -0
  144. data/spec/support/system/spec_system_helper.rb +25 -0
  145. data/spec/system/deployment_as_gem_spec.rb +12 -0
  146. data/spec/system/deployment_as_vendor_spec.rb +17 -0
  147. data/spec/system/encoding_stress_spec.rb +4 -4
  148. data/spec/system/example_wondrous_forest_spec.rb +2 -2
  149. data/spec/system/support/common_test_cases.rb +137 -0
  150. data/spec/units/c_extractor/c_extractor_declarations_spec.rb +27 -4
  151. data/spec/units/c_extractor/c_extractor_functions_spec.rb +1 -11
  152. data/spec/units/c_extractor/c_extractor_integration_spec.rb +18 -11
  153. data/spec/units/c_extractor/c_extractor_spec.rb +57 -1
  154. data/spec/units/config/configurator_setup_spec.rb +61 -0
  155. data/spec/units/file_path_utils_spec.rb +17 -0
  156. data/spec/units/generators/generator_helper_spec.rb +34 -7
  157. data/spec/units/generators/generator_partials_spec.rb +120 -12
  158. data/spec/units/generators/generator_test_results_backtrace_spec.rb +200 -37
  159. data/spec/units/includes/include_spec.rb +30 -18
  160. data/spec/units/includes/includes_spec.rb +100 -10
  161. data/spec/units/partials/partializer_spec.rb +113 -1
  162. data/spec/units/partials/partializer_utils_spec.rb +11 -0
  163. data/spec/units/preprocess/preprocessinator_includes_handler_spec.rb +96 -7
  164. data/spec/units/system_wrapper_spec.rb +72 -0
  165. metadata +19 -2
@@ -522,6 +522,31 @@ describe Partializer do
522
522
  expect(result).not_to include(UserInclude.new('partial1.h'))
523
523
  expect(result).not_to include(UserInclude.new('partial2.h'))
524
524
  end
525
+
526
+ it "appends the shared types header when one was generated for this module" do
527
+ includes = [UserInclude.new('header1.h')]
528
+ partials = {}
529
+ result = @partializer.remap_implementation_header_includes(
530
+ name: 'module',
531
+ includes: includes,
532
+ partials: partials,
533
+ types_header: 'ceedling_partial_module_types.h'
534
+ )
535
+
536
+ expect(result).to include(UserInclude.new('ceedling_partial_module_types.h'))
537
+ end
538
+
539
+ it "does not append a types header when the module has none" do
540
+ includes = [UserInclude.new('header1.h')]
541
+ partials = {}
542
+ result = @partializer.remap_implementation_header_includes(
543
+ name: 'module',
544
+ includes: includes,
545
+ partials: partials
546
+ )
547
+
548
+ expect(result).to match_array([UserInclude.new('header1.h')])
549
+ end
525
550
  end
526
551
 
527
552
  ###
@@ -683,6 +708,31 @@ describe Partializer do
683
708
  expect(result).not_to include(UserInclude.new('partial1.h'))
684
709
  expect(result).not_to include(UserInclude.new('partial2.h'))
685
710
  end
711
+
712
+ it "appends the shared types header when one was generated for this module" do
713
+ includes = [UserInclude.new('header1.h')]
714
+ partials = {}
715
+ result = @partializer.remap_interface_header_includes(
716
+ name: 'module',
717
+ includes: includes,
718
+ partials: partials,
719
+ types_header: 'ceedling_partial_module_types.h'
720
+ )
721
+
722
+ expect(result).to include(UserInclude.new('ceedling_partial_module_types.h'))
723
+ end
724
+
725
+ it "does not append a types header when the module has none" do
726
+ includes = [UserInclude.new('header1.h')]
727
+ partials = {}
728
+ result = @partializer.remap_interface_header_includes(
729
+ name: 'module',
730
+ includes: includes,
731
+ partials: partials
732
+ )
733
+
734
+ expect(result).to match_array([UserInclude.new('header1.h')])
735
+ end
686
736
  end
687
737
 
688
738
  ###
@@ -1521,6 +1571,66 @@ describe Partializer do
1521
1571
  expect(result).to eq(filtered)
1522
1572
  end
1523
1573
 
1574
+ it "merges declaration-only functions into the DEDUCT candidate pool" do
1575
+ defn = double('inline_func', name: 'inline_fn')
1576
+ decl = double('proto_func', name: 'proto_fn')
1577
+ defs = [defn]
1578
+ decls = [decl]
1579
+ filtered = [double('iface_inline'), double('iface_proto')]
1580
+ pf = make_pf(type: Partials::DEDUCT)
1581
+
1582
+ expect(@partializer_helper).to receive(:filter_and_transform_funcs)
1583
+ .with([defn, decl], Partials::DEDUCT, :interface).and_return(filtered)
1584
+ allow(@partializer_helper).to receive(:subtract_funcs)
1585
+ .with(funcs: filtered, names: []).and_return(filtered)
1586
+
1587
+ result = @partializer.extract_interface_functions(
1588
+ test: 'test_mod', partial: 'mod',
1589
+ definitions: defs, declarations: decls, config: make_config(mocks: pf)
1590
+ )
1591
+ expect(result).to eq(filtered)
1592
+ end
1593
+
1594
+ it "merges declaration-only functions into the PUBLIC candidate pool too" do
1595
+ defn = double('def_func', name: 'pub_def')
1596
+ decl = double('decl_func', name: 'pub_decl')
1597
+ defs = [defn]
1598
+ decls = [decl]
1599
+ filtered = [double('iface_func')]
1600
+ pf = make_pf(type: Partials::PUBLIC)
1601
+
1602
+ expect(@partializer_helper).to receive(:filter_and_transform_funcs)
1603
+ .with([defn, decl], Partials::PUBLIC, :interface).and_return(filtered)
1604
+ allow(@partializer_helper).to receive(:subtract_funcs)
1605
+ .with(funcs: filtered, names: []).and_return(filtered)
1606
+
1607
+ result = @partializer.extract_interface_functions(
1608
+ test: 'test_mod', partial: 'mod',
1609
+ definitions: defs, declarations: decls, config: make_config(mocks: pf)
1610
+ )
1611
+ expect(result).to eq(filtered)
1612
+ end
1613
+
1614
+ it "excludes a declaration already present as a definition with the same name (dedup)" do
1615
+ defn = double('def_func', name: 'shared')
1616
+ decl = double('decl_func', name: 'shared') # e.g. header prototype for the same function
1617
+ defs = [defn]
1618
+ decls = [decl]
1619
+ filtered = [double('iface_func')]
1620
+ pf = make_pf(type: Partials::DEDUCT)
1621
+
1622
+ expect(@partializer_helper).to receive(:filter_and_transform_funcs)
1623
+ .with([defn], Partials::DEDUCT, :interface).and_return(filtered)
1624
+ allow(@partializer_helper).to receive(:subtract_funcs)
1625
+ .with(funcs: filtered, names: []).and_return(filtered)
1626
+
1627
+ result = @partializer.extract_interface_functions(
1628
+ test: 'test_mod', partial: 'mod',
1629
+ definitions: defs, declarations: decls, config: make_config(mocks: pf)
1630
+ )
1631
+ expect(result).to eq(filtered)
1632
+ end
1633
+
1524
1634
  it "fills list from additions only for ACCUMULATE type" do
1525
1635
  defs = [double('def', name: 'named')]
1526
1636
  decls = []
@@ -1548,8 +1658,10 @@ describe Partializer do
1548
1658
  found = double('iface_func', name: 'decl_only')
1549
1659
  pf = make_pf(type: Partials::ACCUMULATE, additions: ['decl_only'])
1550
1660
 
1661
+ # candidates = definitions + declarations (ACCUMULATE ignores this list regardless --
1662
+ # it always starts empty -- but it's still built before the type check discards it).
1551
1663
  allow(@partializer_helper).to receive(:filter_and_transform_funcs)
1552
- .with(defs, Partials::ACCUMULATE, :interface).and_return([])
1664
+ .with(decls, Partials::ACCUMULATE, :interface).and_return([])
1553
1665
  expect(@partializer_helper).to receive(:find_and_transform_func)
1554
1666
  .with(name: 'decl_only', primary_funcs: defs, secondary_funcs: decls, output_type: :interface)
1555
1667
  .and_return(found)
@@ -166,6 +166,17 @@ describe PartializerUtils do
166
166
  expect(result.signature).to eq(signature)
167
167
  expect(result).not_to respond_to(:code_block)
168
168
  end
169
+
170
+ it "strips a trailing semicolon from a declaration-sourced signature" do
171
+ # CFunctionDeclaration#signature_stripped always carries its own trailing
172
+ # semicolon (it's a bare prototype); CFunctionDefinition#signature_stripped never
173
+ # does. Callers render "#{signature};" uniformly, so this must not double up.
174
+ signature = 'void testFunc(int x);'
175
+
176
+ result = @utils.transform_function(mock_func, signature, :interface)
177
+
178
+ expect(result.signature).to eq('void testFunc(int x)')
179
+ end
169
180
  end
170
181
 
171
182
  context "when output_type is invalid" do
@@ -19,16 +19,20 @@ RSpec.describe PreprocessinatorIncludesHandler do
19
19
  let(:real_parsing_parcels) { ParsingParcels.new }
20
20
 
21
21
  before :each do
22
- @configurator = double('configurator')
23
- @include_factory = double('include_factory')
24
- @file_wrapper = double('file_wrapper')
25
- @yaml_wrapper = double('yaml_wrapper')
26
- @loginator = double('loginator')
27
- @reportinator = double('reportinator')
22
+ @configurator = double('configurator')
23
+ @include_factory = double('include_factory')
24
+ @file_wrapper = double('file_wrapper')
25
+ @file_path_utils = double('file_path_utils')
26
+ @tool_executor = double('tool_executor')
27
+ @yaml_wrapper = double('yaml_wrapper')
28
+ @loginator = double('loginator')
29
+ @reportinator = double('reportinator')
28
30
  @preprocessinator_line_marker_includes_extractor =
29
31
  double('preprocessinator_line_marker_includes_extractor')
30
32
 
31
33
  allow(@loginator).to receive(:log)
34
+ allow(@loginator).to receive(:lazy)
35
+ allow(@loginator).to receive(:log_list)
32
36
  allow(@reportinator).to receive(:generate_module_progress).and_return('')
33
37
 
34
38
  # Include factory helpers: return typed Include objects based on the path
@@ -50,8 +54,9 @@ RSpec.describe PreprocessinatorIncludesHandler do
50
54
  include_factory: @include_factory,
51
55
  preprocessinator_line_marker_includes_extractor:
52
56
  @preprocessinator_line_marker_includes_extractor,
53
- tool_executor: double('tool_executor'),
57
+ tool_executor: @tool_executor,
54
58
  file_wrapper: @file_wrapper,
59
+ file_path_utils: @file_path_utils,
55
60
  yaml_wrapper: @yaml_wrapper,
56
61
  parsing_parcels: real_parsing_parcels,
57
62
  loginator: @loginator,
@@ -66,6 +71,90 @@ RSpec.describe PreprocessinatorIncludesHandler do
66
71
  end
67
72
 
68
73
 
74
+ # ===========================================================================
75
+ describe '#extract_bare_includes' do
76
+ # ===========================================================================
77
+ # Extraction stages an isolated, sibling-free copy of the file being scanned before running
78
+ # GCC's bare-includes preprocessor pass, so that GCC's own directory-relative #include
79
+ # resolution has no real sibling header available to find and recurse into.
80
+
81
+ let(:test_name) { 'test_other' }
82
+ let(:filepath) { '/project/test/test_other.c' }
83
+ let(:isolation_parent) { '/project/build/test/preprocess/files/test_other' }
84
+ let(:isolation_dir) { "#{isolation_parent}/tmp1234" }
85
+ let(:isolated_filepath) { "#{isolation_dir}/test_other.c" }
86
+ let(:make_rules) do
87
+ "test_other.o: #{isolated_filepath} unity.h mock_foo_func.h other.h\n\n" \
88
+ "unity.h:\n\nmock_foo_func.h:\n\nother.h:\n"
89
+ end
90
+
91
+ before :each do
92
+ allow(@file_path_utils).to receive(:form_test_preprocess_files_path)
93
+ .with(test_name).and_return(isolation_parent)
94
+ allow(@file_wrapper).to receive(:mkdir_tmp)
95
+ .with(nil, isolation_parent).and_return(isolation_dir)
96
+ allow(@file_wrapper).to receive(:cp).with(filepath, isolated_filepath)
97
+ allow(@file_wrapper).to receive(:rm_rf).with(isolation_dir)
98
+
99
+ allow(@configurator).to receive(:tools_test_bare_includes_preprocessor).and_return(:bare_tool)
100
+
101
+ allow(@tool_executor).to receive(:build_command_line) do |tool, extra_args, fp, defs, flgs, paths|
102
+ { options: {}, tool: tool, filepath: fp, defines: defs, flags: flgs, search_paths: paths }
103
+ end
104
+
105
+ allow(@tool_executor).to receive(:exec).and_return(output: make_rules)
106
+ end
107
+
108
+ def call_it
109
+ subject.extract_bare_includes(
110
+ test: test_name, filepath: filepath, search_paths: [], flags: [], defines: []
111
+ )
112
+ end
113
+
114
+ it 'stages a copy of the file into an isolated, sibling-free directory before extraction' do
115
+ call_it()
116
+
117
+ expect(@file_wrapper).to have_received(:mkdir_tmp).with(nil, isolation_parent)
118
+ expect(@file_wrapper).to have_received(:cp).with(filepath, isolated_filepath)
119
+ end
120
+
121
+ it 'builds the bare-includes command against the isolated staged path, not the original' do
122
+ call_it()
123
+
124
+ expect(@tool_executor).to have_received(:build_command_line)
125
+ .with(:bare_tool, [], isolated_filepath, [], [], [])
126
+ end
127
+
128
+ it 'returns the includes parsed from the staged file make-rule output' do
129
+ result = call_it()
130
+ expect(result.map(&:filename)).to contain_exactly('unity.h', 'mock_foo_func.h', 'other.h')
131
+ end
132
+
133
+ it 'cleans up the isolation directory after a successful run' do
134
+ call_it()
135
+ expect(@file_wrapper).to have_received(:rm_rf).with(isolation_dir)
136
+ end
137
+
138
+ it 'cleans up the isolation directory even when the tool executor raises' do
139
+ allow(@tool_executor).to receive(:exec).and_raise(StandardError.new('boom'))
140
+
141
+ expect { call_it() }.to raise_error(StandardError, 'boom')
142
+
143
+ expect(@file_wrapper).to have_received(:rm_rf).with(isolation_dir)
144
+ end
145
+
146
+ it 'still cleans self-reference against the original filepath identity, not the staged copy' do
147
+ self_ref_rules =
148
+ "test_other.o: #{isolated_filepath} #{filepath} other.h\n\n#{filepath}:\n\nother.h:\n"
149
+ allow(@tool_executor).to receive(:exec).and_return(output: self_ref_rules)
150
+
151
+ result = call_it()
152
+ expect(result.map(&:filename)).to contain_exactly('other.h')
153
+ end
154
+
155
+ end
156
+
157
+
69
158
  # ===========================================================================
70
159
  describe '#extract_user_includes_from_text' do
71
160
  # ===========================================================================
@@ -0,0 +1,72 @@
1
+ # =========================================================================
2
+ # Ceedling - Test-Centered Build System for C
3
+ # ThrowTheSwitch.org
4
+ # Copyright (c) 2010-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
5
+ # SPDX-License-Identifier: MIT
6
+ # =========================================================================
7
+
8
+ require 'spec_helper'
9
+ require 'ceedling/system_wrapper'
10
+
11
+ describe SystemWrapper do
12
+ before(:each) do
13
+ @sys_wrapper = described_class.new
14
+ end
15
+
16
+ # Portable, real subprocess invocations -- no shell scripting, no signals (those are
17
+ # covered where they're actually consumed, via doubles, in generator_helper_spec.rb).
18
+ # This spec exists to characterize shell_capture3's own contract: it is the sole place
19
+ # a subprocess's real Process::Status is captured, and the one thing downstream crash
20
+ # detection depends on entirely.
21
+ def ruby_command(code)
22
+ "#{RbConfig.ruby} -e #{code.inspect}"
23
+ end
24
+
25
+ describe '#shell_capture3' do
26
+ context 'boom: false (the default, and how test-fixture execution always runs)' do
27
+ it 'forces exit_code to 0 even though the real subprocess exited nonzero' do
28
+ result = @sys_wrapper.shell_capture3( command: ruby_command('exit 3'), boom: false )
29
+ expect(result[:exit_code]).to eq(0)
30
+ end
31
+
32
+ it 'still relays the real, un-neutered Process::Status' do
33
+ result = @sys_wrapper.shell_capture3( command: ruby_command('exit 3'), boom: false )
34
+ expect(result[:status]).not_to be_nil
35
+ expect(result[:status].exitstatus).to eq(3)
36
+ expect(result[:status].success?).to be false
37
+ end
38
+
39
+ it 'forces exit_code to 0 for a genuinely successful subprocess too' do
40
+ result = @sys_wrapper.shell_capture3( command: ruby_command('exit 0'), boom: false )
41
+ expect(result[:exit_code]).to eq(0)
42
+ expect(result[:status].success?).to be true
43
+ end
44
+ end
45
+
46
+ context 'boom: true' do
47
+ it 'surfaces the real nonzero exit code' do
48
+ result = @sys_wrapper.shell_capture3( command: ruby_command('exit 3'), boom: true )
49
+ expect(result[:exit_code]).to eq(3)
50
+ end
51
+
52
+ it 'reports 0 for a genuinely successful subprocess' do
53
+ result = @sys_wrapper.shell_capture3( command: ruby_command('exit 0'), boom: true )
54
+ expect(result[:exit_code]).to eq(0)
55
+ end
56
+
57
+ it 'still relays the same real Process::Status as boom: false does' do
58
+ result = @sys_wrapper.shell_capture3( command: ruby_command('exit 3'), boom: true )
59
+ expect(result[:status].exitstatus).to eq(3)
60
+ end
61
+ end
62
+
63
+ it 'combines stdout and stderr into :output while keeping each stream separately available' do
64
+ result = @sys_wrapper.shell_capture3(
65
+ command: ruby_command('STDOUT.print "out"; STDERR.print "err"'), boom: false
66
+ )
67
+ expect(result[:stdout]).to eq('out')
68
+ expect(result[:stderr]).to eq('err')
69
+ expect(result[:output]).to eq('outerr')
70
+ end
71
+ end
72
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ceedling
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark VanderVoord
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2026-08-06 00:00:00.000000000 Z
13
+ date: 2026-08-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -178,7 +178,15 @@ files:
178
178
  - assets/example_file_with_statics.c
179
179
  - assets/example_file_with_stdio.c
180
180
  - assets/example_file_with_stdio.h
181
+ - assets/fake_crash_test_fixture.rb
182
+ - assets/partial_all_module.h
181
183
  - assets/project.yml
184
+ - assets/run_with_ubsan.rb
185
+ - assets/same_dir_pairing_module.c
186
+ - assets/same_dir_pairing_module.h
187
+ - assets/same_dir_pairing_module_func.h
188
+ - assets/same_dir_pairing_other.c
189
+ - assets/same_dir_pairing_other.h
182
190
  - assets/test_example_file.c
183
191
  - assets/test_example_file_2.c
184
192
  - assets/test_example_file_boom.c
@@ -187,11 +195,14 @@ files:
187
195
  - assets/test_example_file_crash_sigsegv_with_param.c
188
196
  - assets/test_example_file_source_include.c
189
197
  - assets/test_example_file_success.c
198
+ - assets/test_example_file_ub_shift_overflow.c
190
199
  - assets/test_example_file_unity_printf.c
191
200
  - assets/test_example_file_verbose.c
192
201
  - assets/test_example_file_with_mock.c
193
202
  - assets/test_example_file_with_stdio.c
194
203
  - assets/test_example_with_parameterized_tests.c
204
+ - assets/test_partial_all_module.c
205
+ - assets/test_same_dir_pairing.c
195
206
  - assets/tests_with_defines/src/adc_hardware.c
196
207
  - assets/tests_with_defines/src/adc_hardware.h
197
208
  - assets/tests_with_defines/src/adc_hardware_configurator.c
@@ -282,6 +293,7 @@ files:
282
293
  - docs/mkdocs/configuration/reference/index.md
283
294
  - docs/mkdocs/configuration/reference/libraries.md
284
295
  - docs/mkdocs/configuration/reference/mixins.md
296
+ - docs/mkdocs/configuration/reference/partials.md
285
297
  - docs/mkdocs/configuration/reference/paths.md
286
298
  - docs/mkdocs/configuration/reference/plugins.md
287
299
  - docs/mkdocs/configuration/reference/project.md
@@ -808,6 +820,7 @@ files:
808
820
  - site-local/configuration/reference/index.html
809
821
  - site-local/configuration/reference/libraries.html
810
822
  - site-local/configuration/reference/mixins.html
823
+ - site-local/configuration/reference/partials.html
811
824
  - site-local/configuration/reference/paths.html
812
825
  - site-local/configuration/reference/plugins.html
813
826
  - site-local/configuration/reference/project.html
@@ -947,6 +960,7 @@ files:
947
960
  - spec/units/c_extractor/c_extractor_integration_spec.rb
948
961
  - spec/units/c_extractor/c_extractor_preprocessing_spec.rb
949
962
  - spec/units/c_extractor/c_extractor_spec.rb
963
+ - spec/units/config/configurator_setup_spec.rb
950
964
  - spec/units/config_matchinator_spec.rb
951
965
  - spec/units/config_walkinator_spec.rb
952
966
  - spec/units/configurator_builder_spec.rb
@@ -979,6 +993,7 @@ files:
979
993
  - spec/units/reportinator_spec.rb
980
994
  - spec/units/ruby_expandinator_spec.rb
981
995
  - spec/units/system_utils_spec.rb
996
+ - spec/units/system_wrapper_spec.rb
982
997
  - spec/units/test_build_executor_spec.rb
983
998
  - spec/units/test_context_extractor_spec.rb
984
999
  - spec/units/tool_executor_helper_spec.rb
@@ -1793,6 +1808,7 @@ test_files:
1793
1808
  - spec/units/c_extractor/c_extractor_integration_spec.rb
1794
1809
  - spec/units/c_extractor/c_extractor_preprocessing_spec.rb
1795
1810
  - spec/units/c_extractor/c_extractor_spec.rb
1811
+ - spec/units/config/configurator_setup_spec.rb
1796
1812
  - spec/units/config_matchinator_spec.rb
1797
1813
  - spec/units/config_walkinator_spec.rb
1798
1814
  - spec/units/configurator_builder_spec.rb
@@ -1825,6 +1841,7 @@ test_files:
1825
1841
  - spec/units/reportinator_spec.rb
1826
1842
  - spec/units/ruby_expandinator_spec.rb
1827
1843
  - spec/units/system_utils_spec.rb
1844
+ - spec/units/system_wrapper_spec.rb
1828
1845
  - spec/units/test_build_executor_spec.rb
1829
1846
  - spec/units/test_context_extractor_spec.rb
1830
1847
  - spec/units/tool_executor_helper_spec.rb