ceedling 1.1.1 → 1.1.2
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.
- checksums.yaml +4 -4
- data/GIT_COMMIT_SHA +1 -1
- data/README.md +3 -3
- data/assets/broken_uncovered_file.c +13 -0
- data/assets/test_example_file_2.c +22 -0
- data/assets/tests_with_partials_coverage/src/blanks.c +10 -0
- data/assets/tests_with_partials_coverage/src/blanks.h +1 -0
- data/assets/tests_with_partials_coverage/src/counter.c +12 -0
- data/assets/tests_with_partials_coverage/src/counter.h +1 -0
- data/assets/tests_with_partials_coverage/src/decorators.c +11 -0
- data/assets/tests_with_partials_coverage/src/decorators.h +4 -0
- data/assets/tests_with_partials_coverage/test/test_blanks.c +8 -0
- data/assets/tests_with_partials_coverage/test/test_counter.c +9 -0
- data/assets/tests_with_partials_coverage/test/test_decorators.c +8 -0
- data/docs/Changelog.md +17 -3
- data/lib/ceedling/c_extractor/c_extractor_declarations.rb +3 -1
- data/lib/ceedling/c_extractor/c_extractor_preprocessing.rb +20 -7
- data/lib/ceedling/generators/generator_partials.rb +13 -3
- data/lib/ceedling/objects.yml +1 -0
- data/lib/ceedling/preprocess/preprocessinator_file_assembler.rb +10 -2
- data/lib/ceedling/preprocess/preprocessinator_reconstructor.rb +23 -15
- data/lib/version.rb +1 -1
- data/site-local/sitemap.xml.gz +0 -0
- data/spec/system/gcov_deployment_spec.rb +20 -6
- data/spec/system/support/gcov_common_test_cases.rb +31 -45
- data/spec/system/support/gcov_partials_test_cases.rb +116 -0
- data/spec/units/c_extractor/c_extractor_declarations_spec.rb +128 -0
- data/spec/units/c_extractor/c_extractor_definitions_spec.rb +7 -0
- data/spec/units/c_extractor/c_extractor_integration_spec.rb +17 -0
- data/spec/units/c_extractor/c_extractor_preprocessing_spec.rb +46 -0
- data/spec/units/generators/generator_partials_spec.rb +32 -6
- data/spec/units/preprocess/preprocessinator_file_assembler_spec.rb +96 -2
- data/spec/units/preprocess/preprocessinator_reconstructor_spec.rb +151 -1
- metadata +15 -2
|
@@ -17,7 +17,7 @@ RSpec.describe PreprocessinatorFileAssembler do
|
|
|
17
17
|
# Use real ParsingParcels for _filter_conditionals and collect_file_contents_fallback tests
|
|
18
18
|
let(:real_parsing_parcels) { ParsingParcels.new }
|
|
19
19
|
let(:real_reconstructor) do
|
|
20
|
-
PreprocessinatorReconstructor.new({ parsing_parcels: real_parsing_parcels })
|
|
20
|
+
PreprocessinatorReconstructor.new({ parsing_parcels: real_parsing_parcels, file_wrapper: @file_wrapper })
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
before :each do
|
|
@@ -359,9 +359,12 @@ RSpec.describe PreprocessinatorFileAssembler do
|
|
|
359
359
|
|
|
360
360
|
let(:preprocessed_filepath) { '/build/mocks/test_module/module.h' }
|
|
361
361
|
|
|
362
|
+
# Binary mode ('wb'): `contents` lines assembled into this file come from
|
|
363
|
+
# an upstream preprocessed file and must reach disk with their line
|
|
364
|
+
# endings unaltered, which text mode would not guarantee.
|
|
362
365
|
def stub_file_write(filepath)
|
|
363
366
|
output = StringIO.new
|
|
364
|
-
allow(@file_wrapper).to receive(:open).with(filepath, '
|
|
367
|
+
allow(@file_wrapper).to receive(:open).with(filepath, 'wb').and_yield(output)
|
|
365
368
|
output
|
|
366
369
|
end
|
|
367
370
|
|
|
@@ -413,6 +416,97 @@ RSpec.describe PreprocessinatorFileAssembler do
|
|
|
413
416
|
expect(output.string).to include('void foo(void);')
|
|
414
417
|
end
|
|
415
418
|
|
|
419
|
+
it 'opens its output file in binary mode' do
|
|
420
|
+
stub_file_write(preprocessed_filepath)
|
|
421
|
+
|
|
422
|
+
subject.assemble_preprocessed_header_file(
|
|
423
|
+
filename: 'module.h',
|
|
424
|
+
preprocessed_filepath: preprocessed_filepath,
|
|
425
|
+
contents: [],
|
|
426
|
+
extras: [],
|
|
427
|
+
includes: []
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
expect(@file_wrapper).to have_received(:open).with(preprocessed_filepath, 'wb')
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
it "passes content lines through to the output file unchanged, including embedded CRLF" do
|
|
434
|
+
output = stub_file_write(preprocessed_filepath)
|
|
435
|
+
content_line_with_crlf = "void foo(void) {\r\n return;\r\n}"
|
|
436
|
+
|
|
437
|
+
subject.assemble_preprocessed_header_file(
|
|
438
|
+
filename: 'module.h',
|
|
439
|
+
preprocessed_filepath: preprocessed_filepath,
|
|
440
|
+
contents: [content_line_with_crlf],
|
|
441
|
+
extras: [],
|
|
442
|
+
includes: []
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
expect(output.string).to include(content_line_with_crlf)
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
# ===========================================================================
|
|
452
|
+
describe '#assemble_preprocessed_code_file' do
|
|
453
|
+
# ===========================================================================
|
|
454
|
+
|
|
455
|
+
let(:preprocessed_filepath) { '/build/test/preprocess/module.c' }
|
|
456
|
+
|
|
457
|
+
# Binary mode ('wb'): `contents` lines assembled into this file come from
|
|
458
|
+
# an upstream preprocessed file and must reach disk with their line
|
|
459
|
+
# endings unaltered, which text mode would not guarantee.
|
|
460
|
+
def stub_file_write(filepath)
|
|
461
|
+
output = StringIO.new
|
|
462
|
+
allow(@file_wrapper).to receive(:open).with(filepath, 'wb').and_yield(output)
|
|
463
|
+
output
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
it 'writes provided includes and contents to the output file' do
|
|
467
|
+
output = stub_file_write(preprocessed_filepath)
|
|
468
|
+
|
|
469
|
+
subject.assemble_preprocessed_code_file(
|
|
470
|
+
filename: 'module.c',
|
|
471
|
+
preprocessed_filepath: preprocessed_filepath,
|
|
472
|
+
contents: ['void foo(void) {}'],
|
|
473
|
+
extras: [],
|
|
474
|
+
includes: ['#include "bar.h"']
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
expect(output.string).to include('#include "bar.h"')
|
|
478
|
+
expect(output.string).to include('void foo(void) {}')
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
it 'opens its output file in binary mode' do
|
|
482
|
+
stub_file_write(preprocessed_filepath)
|
|
483
|
+
|
|
484
|
+
subject.assemble_preprocessed_code_file(
|
|
485
|
+
filename: 'module.c',
|
|
486
|
+
preprocessed_filepath: preprocessed_filepath,
|
|
487
|
+
contents: [],
|
|
488
|
+
extras: [],
|
|
489
|
+
includes: []
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
expect(@file_wrapper).to have_received(:open).with(preprocessed_filepath, 'wb')
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
it "passes content lines through to the output file unchanged, including embedded CRLF" do
|
|
496
|
+
output = stub_file_write(preprocessed_filepath)
|
|
497
|
+
content_line_with_crlf = "void foo(void) {\r\n return;\r\n}"
|
|
498
|
+
|
|
499
|
+
subject.assemble_preprocessed_code_file(
|
|
500
|
+
filename: 'module.c',
|
|
501
|
+
preprocessed_filepath: preprocessed_filepath,
|
|
502
|
+
contents: [content_line_with_crlf],
|
|
503
|
+
extras: [],
|
|
504
|
+
includes: []
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
expect(output.string).to include(content_line_with_crlf)
|
|
508
|
+
end
|
|
509
|
+
|
|
416
510
|
end
|
|
417
511
|
|
|
418
512
|
end
|
|
@@ -12,9 +12,11 @@ require 'ceedling/parsing_parcels'
|
|
|
12
12
|
describe PreprocessinatorReconstructor do
|
|
13
13
|
before(:each) do
|
|
14
14
|
@parsing_parcels = ParsingParcels.new()
|
|
15
|
+
@file_wrapper = double( "FileWrapper" )
|
|
15
16
|
@extractor = described_class.new(
|
|
16
17
|
{
|
|
17
|
-
:parsing_parcels => @parsing_parcels
|
|
18
|
+
:parsing_parcels => @parsing_parcels,
|
|
19
|
+
:file_wrapper => @file_wrapper,
|
|
18
20
|
}
|
|
19
21
|
)
|
|
20
22
|
end
|
|
@@ -75,6 +77,105 @@ describe PreprocessinatorReconstructor do
|
|
|
75
77
|
expect( @extractor.extract_file_as_array_from_expansion( input, filepath ) ).to eq expected
|
|
76
78
|
end
|
|
77
79
|
|
|
80
|
+
it "should preserve a run of multiple consecutive blank lines rather than collapsing to one" do
|
|
81
|
+
filepath = "this/path/MY_FILE.C"
|
|
82
|
+
|
|
83
|
+
file_contents = [
|
|
84
|
+
'# 1 "./this/path/MY_FILE.C" 99999',
|
|
85
|
+
'void some_function(void) {',
|
|
86
|
+
'',
|
|
87
|
+
'',
|
|
88
|
+
'',
|
|
89
|
+
' return 0;',
|
|
90
|
+
'}'
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
# All three blank lines must survive -- e.g. a stripped multi-line comment
|
|
94
|
+
# or literal blank lines in the source, either way nothing gets dropped.
|
|
95
|
+
expected = [
|
|
96
|
+
'void some_function(void) {',
|
|
97
|
+
'',
|
|
98
|
+
'',
|
|
99
|
+
'',
|
|
100
|
+
' return 0;',
|
|
101
|
+
'}'
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
input = StringIO.new( file_contents.join( "\n" ) )
|
|
105
|
+
|
|
106
|
+
expect( @extractor.extract_file_as_array_from_expansion( input, filepath ) ).to eq expected
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "should preserve independent runs of differing blank-line counts between separate code lines" do
|
|
110
|
+
filepath = "path/multi.c"
|
|
111
|
+
|
|
112
|
+
file_contents = [
|
|
113
|
+
'# 1 "path/multi.c" 1',
|
|
114
|
+
'int a;',
|
|
115
|
+
'',
|
|
116
|
+
'',
|
|
117
|
+
'int b;',
|
|
118
|
+
'',
|
|
119
|
+
'int c;',
|
|
120
|
+
'',
|
|
121
|
+
'',
|
|
122
|
+
'',
|
|
123
|
+
'int d;'
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
# Each run's count must stay attached to its own gap -- not merged with a
|
|
127
|
+
# neighboring run, not truncated to a shared count.
|
|
128
|
+
expected = [
|
|
129
|
+
'int a;',
|
|
130
|
+
'',
|
|
131
|
+
'',
|
|
132
|
+
'int b;',
|
|
133
|
+
'',
|
|
134
|
+
'int c;',
|
|
135
|
+
'',
|
|
136
|
+
'',
|
|
137
|
+
'',
|
|
138
|
+
'int d;'
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
input = StringIO.new( file_contents.join( "\n" ) )
|
|
142
|
+
|
|
143
|
+
expect( @extractor.extract_file_as_array_from_expansion( input, filepath ) ).to eq expected
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "should preserve a following blank-line run after a marker-continuation (dangling semicolon) fragment" do
|
|
147
|
+
filepath = "sys/types_wrapper.c"
|
|
148
|
+
|
|
149
|
+
file_contents = [
|
|
150
|
+
'# 1 "sys/types_wrapper.c" 1',
|
|
151
|
+
'typedef unsigned long uint32_t', # System typedef expansion, unterminated
|
|
152
|
+
'# 1 "sys/types_wrapper.c" 2', # GCC re-marks the SAME source line...
|
|
153
|
+
';', # ...to attach a dangling ';' as a continuation, not a new line
|
|
154
|
+
'',
|
|
155
|
+
'',
|
|
156
|
+
'void some_function(void) {',
|
|
157
|
+
' return;',
|
|
158
|
+
'}',
|
|
159
|
+
'# 1 "some/useless/file.c"'
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
# The typedef and its dangling ';' must aggregate onto a single output
|
|
163
|
+
# line (existing behavior), and the two blank lines that follow -- e.g.
|
|
164
|
+
# from a stripped comment after the typedef -- must both still survive.
|
|
165
|
+
expected = [
|
|
166
|
+
'typedef unsigned long uint32_t;',
|
|
167
|
+
'',
|
|
168
|
+
'',
|
|
169
|
+
'void some_function(void) {',
|
|
170
|
+
' return;',
|
|
171
|
+
'}'
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
input = StringIO.new( file_contents.join( "\n" ) )
|
|
175
|
+
|
|
176
|
+
expect( @extractor.extract_file_as_array_from_expansion( input, filepath ) ).to eq expected
|
|
177
|
+
end
|
|
178
|
+
|
|
78
179
|
it "should extract text of original file from preprocessed expansion with complex preprocessor line marker sequence" do
|
|
79
180
|
filepath = "dir/our_file.c"
|
|
80
181
|
|
|
@@ -207,6 +308,8 @@ describe PreprocessinatorReconstructor do
|
|
|
207
308
|
'',
|
|
208
309
|
'static _Bool ecs_foo__init_structure(void);',
|
|
209
310
|
'',
|
|
311
|
+
'',
|
|
312
|
+
'',
|
|
210
313
|
'void ecs_foo_init(void) {',
|
|
211
314
|
' var1 = ecs_foo__init_structure();',
|
|
212
315
|
'}',
|
|
@@ -697,4 +800,51 @@ describe PreprocessinatorReconstructor do
|
|
|
697
800
|
|
|
698
801
|
end
|
|
699
802
|
|
|
803
|
+
context "#compact_file_from_expansion" do
|
|
804
|
+
it "should open its input in binary mode and its output in binary mode" do
|
|
805
|
+
# Binary mode on both ends: this content is read again downstream by code
|
|
806
|
+
# that depends on its line count being exact, so nothing here should be
|
|
807
|
+
# subject to platform-specific line ending translation.
|
|
808
|
+
input_handle = StringIO.new( '# 1 "WANT.c" 5' + "\n" + 'text_we_want();' + "\n" )
|
|
809
|
+
output_handle = StringIO.new
|
|
810
|
+
|
|
811
|
+
expect(@file_wrapper).to receive(:open).with( 'input.c', 'rb' ).and_yield( input_handle )
|
|
812
|
+
expect(@file_wrapper).to receive(:open).with( 'output.c', 'wb' ).and_yield( output_handle )
|
|
813
|
+
|
|
814
|
+
@extractor.compact_file_from_expansion(
|
|
815
|
+
input_filepath: 'input.c',
|
|
816
|
+
source_filepath: 'WANT.c',
|
|
817
|
+
output_filepath: 'output.c'
|
|
818
|
+
)
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
it "should extract the same content from CRLF-terminated input as from LF-terminated input" do
|
|
822
|
+
# GCC's preprocessor output on Windows is CRLF-terminated. Extraction must
|
|
823
|
+
# produce identical results regardless of the input's line endings, since
|
|
824
|
+
# the exact line count of what's extracted matters to code downstream.
|
|
825
|
+
lf_input = StringIO.new(
|
|
826
|
+
'# 1 "WANT.c" 5' + "\n" + "line_one();\n" + "\n" + "line_two();\n"
|
|
827
|
+
)
|
|
828
|
+
crlf_input = StringIO.new(
|
|
829
|
+
'# 1 "WANT.c" 5' + "\r\n" + "line_one();\r\n" + "\r\n" + "line_two();\r\n"
|
|
830
|
+
)
|
|
831
|
+
lf_output = StringIO.new
|
|
832
|
+
crlf_output = StringIO.new
|
|
833
|
+
|
|
834
|
+
allow(@file_wrapper).to receive(:open).with( 'lf.c', 'rb' ).and_yield( lf_input )
|
|
835
|
+
allow(@file_wrapper).to receive(:open).with( 'lf_out.c', 'wb' ).and_yield( lf_output )
|
|
836
|
+
allow(@file_wrapper).to receive(:open).with( 'crlf.c', 'rb' ).and_yield( crlf_input )
|
|
837
|
+
allow(@file_wrapper).to receive(:open).with( 'crlf_out.c', 'wb' ).and_yield( crlf_output )
|
|
838
|
+
|
|
839
|
+
@extractor.compact_file_from_expansion(
|
|
840
|
+
input_filepath: 'lf.c', source_filepath: 'WANT.c', output_filepath: 'lf_out.c'
|
|
841
|
+
)
|
|
842
|
+
@extractor.compact_file_from_expansion(
|
|
843
|
+
input_filepath: 'crlf.c', source_filepath: 'WANT.c', output_filepath: 'crlf_out.c'
|
|
844
|
+
)
|
|
845
|
+
|
|
846
|
+
expect( crlf_output.string ).to eq( lf_output.string )
|
|
847
|
+
end
|
|
848
|
+
end
|
|
849
|
+
|
|
700
850
|
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.
|
|
4
|
+
version: 1.1.2
|
|
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-07-
|
|
13
|
+
date: 2026-07-27 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: rake
|
|
@@ -167,6 +167,7 @@ files:
|
|
|
167
167
|
- Gemfile.lock
|
|
168
168
|
- README.md
|
|
169
169
|
- Rakefile
|
|
170
|
+
- assets/broken_uncovered_file.c
|
|
170
171
|
- assets/ceedling
|
|
171
172
|
- assets/ceedling.cmd
|
|
172
173
|
- assets/default_gitignore
|
|
@@ -179,6 +180,7 @@ files:
|
|
|
179
180
|
- assets/example_file_with_stdio.h
|
|
180
181
|
- assets/project.yml
|
|
181
182
|
- assets/test_example_file.c
|
|
183
|
+
- assets/test_example_file_2.c
|
|
182
184
|
- assets/test_example_file_boom.c
|
|
183
185
|
- assets/test_example_file_crash_assert.c
|
|
184
186
|
- assets/test_example_file_crash_sigsegv.c
|
|
@@ -203,6 +205,15 @@ files:
|
|
|
203
205
|
- assets/tests_with_fallback_conditionals/src/conditional_module.h
|
|
204
206
|
- assets/tests_with_fallback_conditionals/src/optional_dep.h
|
|
205
207
|
- assets/tests_with_fallback_conditionals/test/test_conditionals.c
|
|
208
|
+
- assets/tests_with_partials_coverage/src/blanks.c
|
|
209
|
+
- assets/tests_with_partials_coverage/src/blanks.h
|
|
210
|
+
- assets/tests_with_partials_coverage/src/counter.c
|
|
211
|
+
- assets/tests_with_partials_coverage/src/counter.h
|
|
212
|
+
- assets/tests_with_partials_coverage/src/decorators.c
|
|
213
|
+
- assets/tests_with_partials_coverage/src/decorators.h
|
|
214
|
+
- assets/tests_with_partials_coverage/test/test_blanks.c
|
|
215
|
+
- assets/tests_with_partials_coverage/test/test_counter.c
|
|
216
|
+
- assets/tests_with_partials_coverage/test/test_decorators.c
|
|
206
217
|
- assets/tests_with_preprocessing/src/adc_hardwareA.c
|
|
207
218
|
- assets/tests_with_preprocessing/src/adc_hardwareA.h
|
|
208
219
|
- assets/tests_with_preprocessing/src/adc_hardwareB.c
|
|
@@ -917,6 +928,7 @@ files:
|
|
|
917
928
|
- spec/system/support/cppcheck_helpers.rb
|
|
918
929
|
- spec/system/support/gcov_common_test_cases.rb
|
|
919
930
|
- spec/system/support/gcov_helpers.rb
|
|
931
|
+
- spec/system/support/gcov_partials_test_cases.rb
|
|
920
932
|
- spec/system/support/valgrind_common_test_cases.rb
|
|
921
933
|
- spec/system/support/valgrind_helpers.rb
|
|
922
934
|
- spec/system/upgrade_as_vendor_spec.rb
|
|
@@ -1762,6 +1774,7 @@ test_files:
|
|
|
1762
1774
|
- spec/system/support/cppcheck_helpers.rb
|
|
1763
1775
|
- spec/system/support/gcov_common_test_cases.rb
|
|
1764
1776
|
- spec/system/support/gcov_helpers.rb
|
|
1777
|
+
- spec/system/support/gcov_partials_test_cases.rb
|
|
1765
1778
|
- spec/system/support/valgrind_common_test_cases.rb
|
|
1766
1779
|
- spec/system/support/valgrind_helpers.rb
|
|
1767
1780
|
- spec/system/upgrade_as_vendor_spec.rb
|