ceedling 1.1.0 → 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 +10 -7
- 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 +80 -38
- data/docs/KnownIssues.md +9 -0
- data/docs/ReleaseNotes.md +5 -1
- data/docs/mkdocs/getting-started/installation.md +8 -1
- data/docs/mkdocs/getting-started/quick-start.md +20 -2
- data/docs/mkdocs/help.md +2 -2
- data/docs/mkdocs/index.md +13 -6
- data/docs/mkdocs/overview/build-system.md +4 -4
- data/docs/mkdocs/plugins/bullseye.md +6 -0
- data/docs/mkdocs/plugins/command-hooks.md +20 -15
- data/docs/mkdocs/plugins/gcov/gcovr.md +130 -109
- data/docs/mkdocs/plugins/gcov/index.md +6 -0
- data/docs/mkdocs/plugins/index.md +40 -0
- data/docs/mkdocs/plugins/valgrind.md +6 -0
- data/docs/mkdocs/testing-guide/partials/index.md +22 -13
- 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/config/configurator.rb +2 -1
- data/lib/ceedling/generators/generator_partials.rb +13 -3
- data/lib/ceedling/objects.yml +1 -0
- data/lib/ceedling/preprocess/preprocessinator.rb +3 -2
- data/lib/ceedling/preprocess/preprocessinator_file_assembler.rb +37 -15
- data/lib/ceedling/preprocess/preprocessinator_reconstructor.rb +23 -15
- data/lib/ceedling/test_invoker/test_build_executor.rb +3 -4
- data/lib/ceedling/test_invoker/test_build_planner.rb +0 -2
- data/lib/ceedling/test_invoker/test_invoker_types.rb +1 -1
- data/lib/ceedling/tool_executor.rb +5 -0
- data/lib/version.rb +1 -1
- data/plugins/command_hooks/lib/command_hooks.rb +4 -0
- data/plugins/gcov/lib/console_reportinator.rb +3 -1
- data/plugins/gcov/lib/gcov.rb +3 -3
- data/plugins/gcov/lib/gcov_reportinator.rb +4 -0
- data/plugins/gcov/lib/gcovr_reportinator.rb +61 -14
- data/plugins/gcov/lib/reportgenerator_reportinator.rb +3 -1
- data/site-local/404.html +3 -3
- data/site-local/assets/javascripts/{bundle.79ae519e.min.js → bundle.d7400e89.min.js} +2 -2
- data/site-local/assets/javascripts/{bundle.79ae519e.min.js.map → bundle.d7400e89.min.js.map} +2 -2
- data/site-local/assets/stylesheets/main.ec1eaa64.min.css +1 -0
- data/site-local/assets/stylesheets/{main.484c7ddc.min.css.map → main.ec1eaa64.min.css.map} +1 -1
- data/site-local/configuration/environment-vars.html +3 -3
- data/site-local/configuration/global-collections.html +3 -3
- data/site-local/configuration/index.html +3 -3
- data/site-local/configuration/loading.html +3 -3
- data/site-local/configuration/mixins.html +3 -3
- data/site-local/configuration/parallel-builds.html +3 -3
- data/site-local/configuration/project-file.html +3 -3
- data/site-local/configuration/reference/cexception.html +3 -3
- data/site-local/configuration/reference/cmock.html +3 -3
- data/site-local/configuration/reference/defines.html +3 -3
- data/site-local/configuration/reference/environment.html +3 -3
- data/site-local/configuration/reference/extension.html +3 -3
- data/site-local/configuration/reference/files.html +3 -3
- data/site-local/configuration/reference/flags.html +3 -3
- data/site-local/configuration/reference/index.html +3 -3
- data/site-local/configuration/reference/libraries.html +3 -3
- data/site-local/configuration/reference/mixins.html +3 -3
- data/site-local/configuration/reference/paths.html +3 -3
- data/site-local/configuration/reference/plugins.html +3 -3
- data/site-local/configuration/reference/project.html +3 -3
- data/site-local/configuration/reference/release-build.html +3 -3
- data/site-local/configuration/reference/test-build.html +3 -3
- data/site-local/configuration/reference/test-runner.html +3 -3
- data/site-local/configuration/reference/tools.html +3 -3
- data/site-local/configuration/reference/unity.html +3 -3
- data/site-local/configuration/which-ceedling.html +3 -3
- data/site-local/development/index.html +3 -3
- data/site-local/development/plugins/configuration.html +3 -3
- data/site-local/development/plugins/index.html +3 -3
- data/site-local/development/plugins/plugin-subclass.html +3 -3
- data/site-local/development/plugins/rake-tasks.html +3 -3
- data/site-local/development/workflow.html +3 -3
- data/site-local/getting-started/command-line.html +3 -3
- data/site-local/getting-started/example-projects/cipher-quest.html +3 -3
- data/site-local/getting-started/example-projects/index.html +3 -3
- data/site-local/getting-started/example-projects/temp-sensor.html +3 -3
- data/site-local/getting-started/example-projects/wondrous-forest.html +3 -3
- data/site-local/getting-started/index.html +3 -3
- data/site-local/getting-started/installation.html +12 -4
- data/site-local/getting-started/quick-start.html +18 -4
- data/site-local/help.html +4 -4
- data/site-local/index.html +13 -8
- data/site-local/overview/build-system.html +6 -6
- data/site-local/overview/index.html +3 -3
- data/site-local/overview/test-environments.html +3 -3
- data/site-local/overview/tools-and-frameworks.html +3 -3
- data/site-local/plugins/beep.html +3 -3
- data/site-local/plugins/bullseye.html +9 -3
- data/site-local/plugins/command-hooks.html +42 -38
- data/site-local/plugins/compile-commands-json-db.html +3 -3
- data/site-local/plugins/cppcheck.html +3 -3
- data/site-local/plugins/dependencies.html +3 -3
- data/site-local/plugins/fff.html +3 -3
- data/site-local/plugins/gcov/examples.html +3 -3
- data/site-local/plugins/gcov/gcovr.html +325 -227
- data/site-local/plugins/gcov/index.html +9 -3
- data/site-local/plugins/gcov/overview.html +3 -3
- data/site-local/plugins/gcov/reportgenerator.html +3 -3
- data/site-local/plugins/gcov/reporting.html +3 -3
- data/site-local/plugins/gcov/setup.html +3 -3
- data/site-local/plugins/gcov/tool-versions.html +3 -3
- data/site-local/plugins/gcov/troubleshooting.html +3 -3
- data/site-local/plugins/index.html +79 -15
- data/site-local/plugins/module-generator.html +3 -3
- data/site-local/plugins/report-build-warnings-log.html +3 -3
- data/site-local/plugins/report-tests-gtestlike-stdout.html +3 -3
- data/site-local/plugins/report-tests-ide-stdout.html +3 -3
- data/site-local/plugins/report-tests-log-factory.html +3 -3
- data/site-local/plugins/report-tests-pretty-stdout.html +3 -3
- data/site-local/plugins/report-tests-raw-output-log.html +3 -3
- data/site-local/plugins/report-tests-teamcity-stdout.html +3 -3
- data/site-local/plugins/valgrind.html +9 -3
- data/site-local/project/release-history.html +3 -3
- data/site-local/project/upgrade.html +3 -3
- data/site-local/reference/build-directives.html +3 -3
- data/site-local/reference/command-line.html +3 -3
- data/site-local/reference/environment-vars.html +3 -3
- data/site-local/reference/gcov-plugin.html +3 -3
- data/site-local/reference/global-collections.html +3 -3
- data/site-local/reference/index.html +3 -3
- data/site-local/reference/partials-macros.html +3 -3
- data/site-local/reference/project-configuration.html +3 -3
- data/site-local/sitemap.xml.gz +0 -0
- data/site-local/snapshot/examples/cipher_quest/index.html +3 -3
- data/site-local/snapshot/examples/temp_sensor/index.html +3 -3
- data/site-local/snapshot/examples/wondrous_forest/index.html +3 -3
- data/site-local/testing-guide/build-directives.html +3 -3
- data/site-local/testing-guide/conventions.html +3 -3
- data/site-local/testing-guide/frameworks.html +3 -3
- data/site-local/testing-guide/index.html +3 -3
- data/site-local/testing-guide/partials/configuration.html +3 -3
- data/site-local/testing-guide/partials/conventions.html +3 -3
- data/site-local/testing-guide/partials/directives.html +3 -3
- data/site-local/testing-guide/partials/example.html +3 -3
- data/site-local/testing-guide/partials/index.html +25 -16
- data/site-local/testing-guide/partials/overview.html +3 -3
- data/site-local/testing-guide/partials/variables.html +3 -3
- data/site-local/testing-guide/test-cases.html +3 -3
- data/site-local/testing-guide/test-sample.html +3 -3
- data/site-local/testing-guide/test-suite-anatomy.html +3 -3
- data/spec/support/system/system_context.rb +3 -1
- data/spec/system/gcov_deployment_spec.rb +20 -6
- data/spec/system/support/gcov_common_test_cases.rb +34 -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 +250 -1
- data/spec/units/preprocess/preprocessinator_reconstructor_spec.rb +151 -1
- data/spec/units/test_build_executor_spec.rb +114 -0
- data/vendor/unity/auto/generate_test_runner.rb +55 -5
- data/vendor/unity/src/unity.h +1 -1
- data/vendor/unity/test/testdata/testRunnerGeneratorEmpty.c +13 -0
- data/vendor/unity/test/tests/test_generate_test_runner.rb +11 -0
- metadata +22 -7
- data/site-local/assets/stylesheets/main.484c7ddc.min.css +0 -1
- data/vendor/unity/auto/run_test.erb +0 -37
|
@@ -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
|
|
@@ -260,4 +260,253 @@ RSpec.describe PreprocessinatorFileAssembler do
|
|
|
260
260
|
|
|
261
261
|
end
|
|
262
262
|
|
|
263
|
+
|
|
264
|
+
# ===========================================================================
|
|
265
|
+
describe '#collect_mockable_header_file_contents' do
|
|
266
|
+
# ===========================================================================
|
|
267
|
+
|
|
268
|
+
let(:test) { 'test_module' }
|
|
269
|
+
let(:filepath) { '/src/module.h' }
|
|
270
|
+
let(:directives_only_filepath) { '/build/directives/module.h' }
|
|
271
|
+
let(:preprocessed_filepath) { '/build/full_expansion/module.h' }
|
|
272
|
+
let(:flags) { [] }
|
|
273
|
+
let(:defines) { [] }
|
|
274
|
+
let(:include_paths) { [] }
|
|
275
|
+
|
|
276
|
+
before :each do
|
|
277
|
+
allow(@file_path_utils).to receive(:form_preprocessed_file_full_expansion_filepath)
|
|
278
|
+
.with(filepath, test).and_return(preprocessed_filepath)
|
|
279
|
+
allow(@configurator).to receive(:tools_test_file_full_preprocessor).and_return(:full_preprocessor)
|
|
280
|
+
allow(@tool_executor).to receive(:build_command_line).and_return('gcc -E ...')
|
|
281
|
+
allow(@tool_executor).to receive(:exec)
|
|
282
|
+
stub_file_open(preprocessed_filepath, "# 1 \"#{filepath}\"\nint x;\n", 'r')
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def call_collect_mockable(fallback:, extras:)
|
|
286
|
+
subject.collect_mockable_header_file_contents(
|
|
287
|
+
test: test,
|
|
288
|
+
filepath: filepath,
|
|
289
|
+
directives_only_filepath: directives_only_filepath,
|
|
290
|
+
fallback: fallback,
|
|
291
|
+
flags: flags,
|
|
292
|
+
defines: defines,
|
|
293
|
+
include_paths: include_paths,
|
|
294
|
+
extras: extras
|
|
295
|
+
)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
context 'when extras are not requested' do
|
|
299
|
+
|
|
300
|
+
it 'returns an empty extras list and a nil include guard' do
|
|
301
|
+
_contents, extras, include_guard = call_collect_mockable(fallback: true, extras: false)
|
|
302
|
+
expect(extras).to eq([])
|
|
303
|
+
expect(include_guard).to be_nil
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
it 'does not read the original file to look for an include guard' do
|
|
307
|
+
expect(@file_wrapper).not_to receive(:read)
|
|
308
|
+
call_collect_mockable(fallback: true, extras: false)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
context 'when extras are requested' do
|
|
314
|
+
|
|
315
|
+
let(:header_with_guard) do
|
|
316
|
+
<<~C
|
|
317
|
+
#ifndef FOO_H
|
|
318
|
+
#define FOO_H
|
|
319
|
+
|
|
320
|
+
void foo(void);
|
|
321
|
+
|
|
322
|
+
#endif
|
|
323
|
+
C
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
it 'extracts the include guard from the original file in fallback mode' do
|
|
327
|
+
allow(@file_wrapper).to receive(:read).with(filepath, 2048).and_return(header_with_guard)
|
|
328
|
+
stub_file_open(filepath, header_with_guard, 'rb')
|
|
329
|
+
|
|
330
|
+
_contents, _extras, include_guard = call_collect_mockable(fallback: true, extras: true)
|
|
331
|
+
expect(include_guard).to eq('FOO_H')
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
it 'extracts the include guard from the original file in directives-only mode' do
|
|
335
|
+
allow(@file_wrapper).to receive(:read).with(filepath, 2048).and_return(header_with_guard)
|
|
336
|
+
stub_file_open(directives_only_filepath, header_with_guard, 'r')
|
|
337
|
+
|
|
338
|
+
_contents, _extras, include_guard = call_collect_mockable(fallback: false, extras: true)
|
|
339
|
+
expect(include_guard).to eq('FOO_H')
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
it 'returns a nil include guard when the original file has no #ifndef/#define guard pair' do
|
|
343
|
+
header_without_guard = "#pragma once\n\nvoid foo(void);\n"
|
|
344
|
+
allow(@file_wrapper).to receive(:read).with(filepath, 2048).and_return(header_without_guard)
|
|
345
|
+
stub_file_open(filepath, header_without_guard, 'rb')
|
|
346
|
+
|
|
347
|
+
_contents, _extras, include_guard = call_collect_mockable(fallback: true, extras: true)
|
|
348
|
+
expect(include_guard).to be_nil
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
# ===========================================================================
|
|
357
|
+
describe '#assemble_preprocessed_header_file' do
|
|
358
|
+
# ===========================================================================
|
|
359
|
+
|
|
360
|
+
let(:preprocessed_filepath) { '/build/mocks/test_module/module.h' }
|
|
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.
|
|
365
|
+
def stub_file_write(filepath)
|
|
366
|
+
output = StringIO.new
|
|
367
|
+
allow(@file_wrapper).to receive(:open).with(filepath, 'wb').and_yield(output)
|
|
368
|
+
output
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
it 'writes the given include guard name as the #ifndef/#define/#endif guard' do
|
|
372
|
+
output = stub_file_write(preprocessed_filepath)
|
|
373
|
+
|
|
374
|
+
subject.assemble_preprocessed_header_file(
|
|
375
|
+
filename: 'module.h',
|
|
376
|
+
preprocessed_filepath: preprocessed_filepath,
|
|
377
|
+
contents: ['void foo(void);'],
|
|
378
|
+
extras: [],
|
|
379
|
+
includes: [],
|
|
380
|
+
include_guard: 'FOO_H'
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
expect(output.string).to include("#ifndef FOO_H\n")
|
|
384
|
+
expect(output.string).to include("#define FOO_H\n")
|
|
385
|
+
expect(output.string).to include('#endif // FOO_H')
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
it 'derives a synthetic include guard from the filename when none is given' do
|
|
389
|
+
output = stub_file_write(preprocessed_filepath)
|
|
390
|
+
|
|
391
|
+
subject.assemble_preprocessed_header_file(
|
|
392
|
+
filename: 'module.h',
|
|
393
|
+
preprocessed_filepath: preprocessed_filepath,
|
|
394
|
+
contents: ['void foo(void);'],
|
|
395
|
+
extras: [],
|
|
396
|
+
includes: []
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
expect(output.string).to include("#ifndef __CEEDLING_GENERATED_MODULE_H__\n")
|
|
400
|
+
expect(output.string).to include("#define __CEEDLING_GENERATED_MODULE_H__\n")
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
it 'writes provided includes and contents between the guard lines' do
|
|
404
|
+
output = stub_file_write(preprocessed_filepath)
|
|
405
|
+
|
|
406
|
+
subject.assemble_preprocessed_header_file(
|
|
407
|
+
filename: 'module.h',
|
|
408
|
+
preprocessed_filepath: preprocessed_filepath,
|
|
409
|
+
contents: ['void foo(void);'],
|
|
410
|
+
extras: [],
|
|
411
|
+
includes: ['#include "bar.h"'],
|
|
412
|
+
include_guard: 'FOO_H'
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
expect(output.string).to include('#include "bar.h"')
|
|
416
|
+
expect(output.string).to include('void foo(void);')
|
|
417
|
+
end
|
|
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
|
+
|
|
510
|
+
end
|
|
511
|
+
|
|
263
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
|
|
@@ -0,0 +1,114 @@
|
|
|
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/test_invoker/test_build_executor'
|
|
10
|
+
require 'ceedling/test_invoker/test_invoker_types'
|
|
11
|
+
|
|
12
|
+
PROJECT_BUILD_VENDOR_UNITY_PATH = 'build/vendor/unity' unless defined?(PROJECT_BUILD_VENDOR_UNITY_PATH)
|
|
13
|
+
UNITY_C_FILE = 'unity.c' unless defined?(UNITY_C_FILE)
|
|
14
|
+
|
|
15
|
+
describe TestBuildExecutor do
|
|
16
|
+
before(:each) do
|
|
17
|
+
@configurator = double( "Configurator" )
|
|
18
|
+
@loginator = double( "Loginator" )
|
|
19
|
+
@reportinator = double( "Reportinator" )
|
|
20
|
+
@batchinator = double( "Batchinator" )
|
|
21
|
+
@preprocessinator = double( "Preprocessinator" )
|
|
22
|
+
@partializer = double( "Partializer" )
|
|
23
|
+
@generator = double( "Generator" )
|
|
24
|
+
@test_context_extractor = double( "TestContextExtractor" )
|
|
25
|
+
@plugin_manager = double( "PluginManager" )
|
|
26
|
+
@file_path_utils = double( "FilePathUtils" )
|
|
27
|
+
@file_finder = double( "FileFinder" )
|
|
28
|
+
@file_wrapper = double( "FileWrapper" )
|
|
29
|
+
|
|
30
|
+
@tools_test_compiler = { name: 'fake compiler' }
|
|
31
|
+
@tools_test_assembler = { name: 'fake assembler' }
|
|
32
|
+
|
|
33
|
+
allow(@configurator).to receive(:extension_assembly).and_return( '.asm' )
|
|
34
|
+
allow(@configurator).to receive(:tools_test_compiler).and_return( @tools_test_compiler )
|
|
35
|
+
allow(@configurator).to receive(:tools_test_assembler).and_return( @tools_test_assembler )
|
|
36
|
+
allow(@configurator).to receive(:project_use_mocks).and_return( false )
|
|
37
|
+
allow(@configurator).to receive(:project_use_exceptions).and_return( false )
|
|
38
|
+
allow(@configurator).to receive(:collection_all_support).and_return( [] )
|
|
39
|
+
|
|
40
|
+
allow(@file_path_utils).to receive(:form_test_build_list_filepath).and_return( 'build/list' )
|
|
41
|
+
allow(@file_path_utils).to receive(:form_test_dependencies_filepath).and_return( 'build/deps' )
|
|
42
|
+
|
|
43
|
+
@executor = described_class.new(
|
|
44
|
+
{
|
|
45
|
+
:configurator => @configurator,
|
|
46
|
+
:loginator => @loginator,
|
|
47
|
+
:reportinator => @reportinator,
|
|
48
|
+
:batchinator => @batchinator,
|
|
49
|
+
:preprocessinator => @preprocessinator,
|
|
50
|
+
:partializer => @partializer,
|
|
51
|
+
:generator => @generator,
|
|
52
|
+
:test_context_extractor => @test_context_extractor,
|
|
53
|
+
:plugin_manager => @plugin_manager,
|
|
54
|
+
:file_path_utils => @file_path_utils,
|
|
55
|
+
:file_finder => @file_finder,
|
|
56
|
+
:file_wrapper => @file_wrapper
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
testable = TestInvokerTypes::Testable.new(
|
|
61
|
+
:compile_defines => [],
|
|
62
|
+
:search_paths => [],
|
|
63
|
+
:compile_flags => [],
|
|
64
|
+
:assembler_flags => []
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@state = TestInvokerTypes::PipelineState.new( :testables => { :a_test => testable } )
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context "#compile_test_component" do
|
|
71
|
+
it "compiles a C source file with the configured test compiler tool" do
|
|
72
|
+
allow(@file_wrapper).to receive(:extname).with( 'src/foo.c' ).and_return( '.c' )
|
|
73
|
+
allow(@configurator).to receive(:test_build_use_assembly).and_return( false )
|
|
74
|
+
|
|
75
|
+
expect(@generator).to receive(:generate_object_file_c) do |**args|
|
|
76
|
+
expect( args[:tool] ).to eq( @tools_test_compiler )
|
|
77
|
+
end
|
|
78
|
+
expect(@generator).to_not receive(:generate_object_file_asm)
|
|
79
|
+
|
|
80
|
+
@executor.send(
|
|
81
|
+
:compile_test_component,
|
|
82
|
+
:context => :test, :test => :a_test, :source => 'src/foo.c', :object => 'build/foo.o', :state => @state
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "assembles an assembly source file with the configured test assembler tool when assembly support is enabled" do
|
|
87
|
+
allow(@file_wrapper).to receive(:extname).with( 'src/foo.asm' ).and_return( '.asm' )
|
|
88
|
+
allow(@configurator).to receive(:test_build_use_assembly).and_return( true )
|
|
89
|
+
|
|
90
|
+
expect(@generator).to receive(:generate_object_file_asm) do |**args|
|
|
91
|
+
expect( args[:tool] ).to eq( @tools_test_assembler )
|
|
92
|
+
end
|
|
93
|
+
expect(@generator).to_not receive(:generate_object_file_c)
|
|
94
|
+
|
|
95
|
+
@executor.send(
|
|
96
|
+
:compile_test_component,
|
|
97
|
+
:context => :test, :test => :a_test, :source => 'src/foo.asm', :object => 'build/foo.o', :state => @state
|
|
98
|
+
)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "does not compile an assembly source file when assembly support is disabled" do
|
|
102
|
+
allow(@file_wrapper).to receive(:extname).with( 'src/foo.asm' ).and_return( '.asm' )
|
|
103
|
+
allow(@configurator).to receive(:test_build_use_assembly).and_return( false )
|
|
104
|
+
|
|
105
|
+
expect(@generator).to_not receive(:generate_object_file_c)
|
|
106
|
+
expect(@generator).to_not receive(:generate_object_file_asm)
|
|
107
|
+
|
|
108
|
+
@executor.send(
|
|
109
|
+
:compile_test_component,
|
|
110
|
+
:context => :test, :test => :a_test, :source => 'src/foo.asm', :object => 'build/foo.o', :state => @state
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -100,9 +100,10 @@ class UnityTestRunnerGenerator
|
|
|
100
100
|
create_suite_setup(output)
|
|
101
101
|
create_suite_teardown(output)
|
|
102
102
|
create_reset(output)
|
|
103
|
-
create_run_test(output)
|
|
103
|
+
create_run_test(output)
|
|
104
104
|
create_args_wrappers(output, tests)
|
|
105
105
|
create_shuffle_tests(output) if @options[:shuffle_tests]
|
|
106
|
+
tests = create_warning_test(output, input_file, tests)
|
|
106
107
|
create_main(output, input_file, tests, used_mocks)
|
|
107
108
|
end
|
|
108
109
|
|
|
@@ -406,10 +407,43 @@ class UnityTestRunnerGenerator
|
|
|
406
407
|
end
|
|
407
408
|
|
|
408
409
|
def create_run_test(output)
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
output.puts("
|
|
410
|
+
output.puts("/*=======Test Runner Used To Run Each Test=====*/")
|
|
411
|
+
output.puts("static void run_test(UnityTestFunction func, const char* name, UNITY_LINE_TYPE line_num)")
|
|
412
|
+
output.puts("{")
|
|
413
|
+
output.puts(" Unity.CurrentTestName = name;")
|
|
414
|
+
output.puts(" Unity.CurrentTestLineNumber = (UNITY_UINT) line_num;")
|
|
415
|
+
output.puts("#ifdef UNITY_USE_COMMAND_LINE_ARGS")
|
|
416
|
+
output.puts(" if (!UnityTestMatches())")
|
|
417
|
+
output.puts(" return;")
|
|
418
|
+
output.puts("#endif")
|
|
419
|
+
output.puts(" Unity.NumberOfTests++;")
|
|
420
|
+
output.puts(" UNITY_CLR_DETAILS();")
|
|
421
|
+
output.puts(" UNITY_EXEC_TIME_START();")
|
|
422
|
+
output.puts(" CMock_Init();")
|
|
423
|
+
output.puts(" if (TEST_PROTECT())")
|
|
424
|
+
output.puts(" {")
|
|
425
|
+
if @options[:plugins].include?(:cexception)
|
|
426
|
+
output.puts(" volatile CEXCEPTION_T e;")
|
|
427
|
+
output.puts(" Try {")
|
|
428
|
+
output.puts(" #{@options[:setup_name]}();")
|
|
429
|
+
output.puts(" func();")
|
|
430
|
+
output.puts(" } Catch(e) {")
|
|
431
|
+
output.puts(" TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, \"Unhandled Exception!\");")
|
|
432
|
+
output.puts(" }")
|
|
433
|
+
else
|
|
434
|
+
output.puts(" #{@options[:setup_name]}();")
|
|
435
|
+
output.puts(" func();")
|
|
436
|
+
end
|
|
437
|
+
output.puts(" }")
|
|
438
|
+
output.puts(" if (TEST_PROTECT())")
|
|
439
|
+
output.puts(" {")
|
|
440
|
+
output.puts(" #{@options[:teardown_name]}();")
|
|
441
|
+
output.puts(" CMock_Verify();")
|
|
442
|
+
output.puts(" }")
|
|
443
|
+
output.puts(" CMock_Destroy();")
|
|
444
|
+
output.puts(" UNITY_EXEC_TIME_STOP();")
|
|
445
|
+
output.puts(" UnityConcludeTest();")
|
|
446
|
+
output.puts("}")
|
|
413
447
|
end
|
|
414
448
|
|
|
415
449
|
def create_args_wrappers(output, tests)
|
|
@@ -428,6 +462,22 @@ class UnityTestRunnerGenerator
|
|
|
428
462
|
end
|
|
429
463
|
end
|
|
430
464
|
|
|
465
|
+
def create_warning_test(output, filename, tests)
|
|
466
|
+
if count_tests(tests) == 0
|
|
467
|
+
warning_test = {
|
|
468
|
+
:test => "test_empty_warning",
|
|
469
|
+
:line_number => 0
|
|
470
|
+
}
|
|
471
|
+
output.puts("\n/*=======Warning Test=====*/")
|
|
472
|
+
output.puts("static void #{warning_test[:test]}(void)")
|
|
473
|
+
output.puts('{')
|
|
474
|
+
output.puts(" TEST_IGNORE_MESSAGE(\"Test file '#{filename.gsub(/\\/, '\\\\\\')}' contains no tests.\");")
|
|
475
|
+
output.puts("}\n")
|
|
476
|
+
tests = [warning_test]
|
|
477
|
+
end
|
|
478
|
+
return tests
|
|
479
|
+
end
|
|
480
|
+
|
|
431
481
|
def create_shuffle_tests(output)
|
|
432
482
|
output.puts("\n/*=======Shuffle Test Order=====*/")
|
|
433
483
|
output.puts('static void shuffleTests(struct UnityRunTestParameters run_test_params_arr[], int num_of_tests)')
|
data/vendor/unity/src/unity.h
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
#define UNITY_VERSION_MAJOR 2
|
|
13
13
|
#define UNITY_VERSION_MINOR 7
|
|
14
|
-
#define UNITY_VERSION_BUILD
|
|
14
|
+
#define UNITY_VERSION_BUILD 1
|
|
15
15
|
#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD)
|
|
16
16
|
|
|
17
17
|
#ifdef __cplusplus
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/* =========================================================================
|
|
2
|
+
Unity - A Test Framework for C
|
|
3
|
+
ThrowTheSwitch.org
|
|
4
|
+
Copyright (c) 2007-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
|
|
5
|
+
SPDX-License-Identifier: MIT
|
|
6
|
+
========================================================================= */
|
|
7
|
+
|
|
8
|
+
/* This Test File Is Used To Verify The Warning When No Tests Are Found */
|
|
9
|
+
|
|
10
|
+
#include "unity.h"
|
|
11
|
+
|
|
12
|
+
void setUp(void) {}
|
|
13
|
+
void tearDown(void) {}
|
|
@@ -336,6 +336,17 @@ RUNNER_TESTS = [
|
|
|
336
336
|
},
|
|
337
337
|
|
|
338
338
|
|
|
339
|
+
{ :name => 'EmptyFileWarning',
|
|
340
|
+
:testfile => 'testdata/testRunnerGeneratorEmpty.c',
|
|
341
|
+
:testdefines => ['TEST'],
|
|
342
|
+
:options => nil, #defaults
|
|
343
|
+
:expected => {
|
|
344
|
+
:to_pass => [ ],
|
|
345
|
+
:to_fail => [ ],
|
|
346
|
+
:to_ignore => [ 'test_empty_warning' ],
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
|
|
339
350
|
#### WITH MOCKS ##########################################
|
|
340
351
|
|
|
341
352
|
{ :name => 'DefaultsThroughOptions',
|