ceedling 1.1.5 → 1.1.6

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/GIT_COMMIT_SHA +1 -1
  3. data/assets/tests_with_conditional_includes/src/feature_config.h +13 -0
  4. data/assets/tests_with_conditional_includes/src/feature_extra.h +13 -0
  5. data/assets/tests_with_conditional_includes/src/local_flag_extra.h +13 -0
  6. data/assets/tests_with_conditional_includes/src/nested_extra.h +13 -0
  7. data/assets/tests_with_conditional_includes/src/nested_wrapper.h +16 -0
  8. data/assets/tests_with_conditional_includes/src/project_flag_extra.h +13 -0
  9. data/assets/tests_with_conditional_includes/src/widget.c +48 -0
  10. data/assets/tests_with_conditional_includes/src/widget.h +15 -0
  11. data/assets/tests_with_conditional_includes/src/widget_feature.c +29 -0
  12. data/assets/tests_with_conditional_includes/src/widget_feature.h +13 -0
  13. data/assets/tests_with_conditional_includes/test/test_widget.c +44 -0
  14. data/assets/tests_with_conditional_includes/test/test_widget_feature.c +31 -0
  15. data/docs/Changelog.md +20 -1
  16. data/examples/wondrous_forest/src/SensorHal.h +13 -0
  17. data/examples/wondrous_forest/src/TemperatureSensor.c +12 -5
  18. data/examples/wondrous_forest/src/TemperatureSensor.h +5 -4
  19. data/examples/wondrous_forest/test/TestTemperatureSensor.c +32 -3
  20. data/lib/ceedling/generators/generator_test_runner.rb +25 -1
  21. data/lib/ceedling/partials/partializer.rb +8 -1
  22. data/lib/ceedling/preprocess/preprocessinator.rb +22 -0
  23. data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +33 -0
  24. data/lib/version.rb +1 -1
  25. data/site-local/sitemap.xml.gz +0 -0
  26. data/spec/support/system/spec_system_helper.rb +11 -0
  27. data/spec/support/system/system_context.rb +18 -9
  28. data/spec/system/conditional_include_macro_visibility_spec.rb +152 -0
  29. data/spec/system/encoding_stress_spec.rb +4 -4
  30. data/spec/system/example_wondrous_forest_spec.rb +2 -2
  31. data/spec/system/support/common_test_cases.rb +5 -1
  32. data/spec/system/test_runner_system_include_spec.rb +90 -0
  33. data/spec/units/generators/generator_test_runner_spec.rb +69 -0
  34. data/spec/units/partials/partializer_spec.rb +69 -0
  35. data/spec/units/preprocess/preprocessinator_includes_handler_spec.rb +61 -0
  36. data/spec/units/preprocess/preprocessinator_spec.rb +136 -0
  37. data/vendor/c_exception/lib/CException.h +1 -1
  38. data/vendor/c_exception/project.yml +2 -2
  39. data/vendor/c_exception/test/TestException.c +1 -1
  40. data/vendor/c_exception/test/support/CExceptionConfig.h +5 -11
  41. data/vendor/cmock/docs/CMockChangeLog.md +23 -22
  42. data/vendor/cmock/scripts/create_makefile.rb +4 -3
  43. data/vendor/cmock/src/cmock.h +1 -1
  44. data/vendor/cmock/vendor/c_exception/lib/CException.h +1 -1
  45. data/vendor/cmock/vendor/c_exception/project.yml +2 -2
  46. data/vendor/cmock/vendor/c_exception/test/TestException.c +1 -1
  47. data/vendor/cmock/vendor/c_exception/test/support/CExceptionConfig.h +5 -11
  48. data/vendor/cmock/vendor/unity/auto/generate_test_runner.rb +85 -29
  49. data/vendor/cmock/vendor/unity/docs/UnityChangeLog.md +1 -0
  50. data/vendor/cmock/vendor/unity/examples/unity_config.h +8 -0
  51. data/vendor/cmock/vendor/unity/src/unity.c +9 -1
  52. data/vendor/cmock/vendor/unity/src/unity.h +1 -1
  53. data/vendor/cmock/vendor/unity/test/rakefile +2 -1
  54. data/vendor/cmock/vendor/unity/test/testdata/testRunnerGeneratorEmpty.c +13 -0
  55. data/vendor/cmock/vendor/unity/test/tests/test_generate_test_runner.rb +31 -0
  56. data/vendor/unity/auto/generate_test_runner.rb +63 -57
  57. data/vendor/unity/docs/UnityChangeLog.md +1 -0
  58. data/vendor/unity/examples/unity_config.h +8 -0
  59. data/vendor/unity/src/unity.c +9 -1
  60. data/vendor/unity/src/unity.h +1 -1
  61. data/vendor/unity/test/rakefile +2 -1
  62. data/vendor/unity/test/tests/test_generate_test_runner.rb +20 -0
  63. metadata +21 -3
  64. data/vendor/cmock/vendor/unity/auto/run_test.erb +0 -37
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a54ad80f099a4117063db064305062de3ef308e0d6a34f5285ad616540c21239
4
- data.tar.gz: aad1cd6bf73dc6710908593a9ec0c493404f13c1ecce8d7f285c2cd537b41b7f
3
+ metadata.gz: d99664eb478b97c839d72985434b355644836056256cd574d9d0868e7ece0f2d
4
+ data.tar.gz: c82999e6fe6a8eb48a3c3f33031453af444c4ef0fc98bb0be554879d6b6e6072
5
5
  SHA512:
6
- metadata.gz: 0ee2a51402a1ca62a0e42f5c9c0b7cfb47871b4723fd33096ef22d90c0dc5ae7c7eb7944833e354a745c9d1123192ed6b92fb195537a8c9d69bd9c81e0330530
7
- data.tar.gz: 2bfd96e070e2fa703f08e85587296690a930734a5eb409c709fd5bca2cd2875aa0b9eb8cb1dca9484852ab37ffc668f9d387fce1ed0c05fc90cd69507982dbcd
6
+ metadata.gz: 2464ee642f445988fdf76aff593d659f6c41da9c5e8a78431d17c690383fa84d21141fd0335d5737a9827cd04e48a956aa18c44f32348084e1b1d7055a4bdecd
7
+ data.tar.gz: a3251efd857f8314fdcef2f7e743d056d3aca42f76e01455f58b2c1caa7730aae1ca199c7c21bdc812ab2f50cbe4314be7f64c1ea56589ba2fbd4924a29b0e0a
data/GIT_COMMIT_SHA CHANGED
@@ -1 +1 @@
1
- 57b6a98
1
+ 4a45278
@@ -0,0 +1,13 @@
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
+ #ifndef FEATURE_CONFIG_H
9
+ #define FEATURE_CONFIG_H
10
+
11
+ #define FEATURE_LEVEL (2)
12
+
13
+ #endif // FEATURE_CONFIG_H
@@ -0,0 +1,13 @@
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
+ #ifndef FEATURE_EXTRA_H
9
+ #define FEATURE_EXTRA_H
10
+
11
+ #define FEATURE_EXTRA_MACRO (7)
12
+
13
+ #endif // FEATURE_EXTRA_H
@@ -0,0 +1,13 @@
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
+ #ifndef LOCAL_FLAG_EXTRA_H
9
+ #define LOCAL_FLAG_EXTRA_H
10
+
11
+ #define LOCAL_FLAG_MACRO (11)
12
+
13
+ #endif // LOCAL_FLAG_EXTRA_H
@@ -0,0 +1,13 @@
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
+ #ifndef NESTED_EXTRA_H
9
+ #define NESTED_EXTRA_H
10
+
11
+ #define NESTED_MACRO (17)
12
+
13
+ #endif // NESTED_EXTRA_H
@@ -0,0 +1,16 @@
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
+ /* widget.c includes this wrapper directly; nested_extra.h is only ever
9
+ * reached transitively through it, never named directly by widget.c. */
10
+
11
+ #ifndef NESTED_WRAPPER_H
12
+ #define NESTED_WRAPPER_H
13
+
14
+ #include "nested_extra.h"
15
+
16
+ #endif // NESTED_WRAPPER_H
@@ -0,0 +1,13 @@
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
+ #ifndef PROJECT_FLAG_EXTRA_H
9
+ #define PROJECT_FLAG_EXTRA_H
10
+
11
+ #define PROJECT_FLAG_MACRO (13)
12
+
13
+ #endif // PROJECT_FLAG_EXTRA_H
@@ -0,0 +1,48 @@
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
+ #include "widget.h"
9
+
10
+ /* (a) Conditional include gated on a project-level :defines macro. */
11
+ #ifdef PROJECT_FLAG
12
+ #include "project_flag_extra.h"
13
+ #endif
14
+
15
+ #define LOCAL_FLAG (1)
16
+
17
+ /* (b) Conditional include gated on a macro #define'd earlier in this same file. */
18
+ #if LOCAL_FLAG
19
+ #include "local_flag_extra.h"
20
+ #endif
21
+
22
+ /* (c) Reached only transitively, via nested_wrapper.h's own #include -- never
23
+ * itself named directly by this file. Must not appear as a duplicate,
24
+ * spuriously-promoted top-level #include in generated output. */
25
+ #include "nested_wrapper.h"
26
+
27
+ static int Widget__FromProjectFlag(void)
28
+ {
29
+ #ifdef PROJECT_FLAG
30
+ return PROJECT_FLAG_MACRO;
31
+ #else
32
+ return 0;
33
+ #endif
34
+ }
35
+
36
+ static int Widget__FromLocalFlag(void)
37
+ {
38
+ return LOCAL_FLAG_MACRO;
39
+ }
40
+
41
+ static int Widget__FromNested(void)
42
+ {
43
+ return NESTED_MACRO;
44
+ }
45
+
46
+ int Widget_FromProjectFlag(void) { return Widget__FromProjectFlag(); }
47
+ int Widget_FromLocalFlag(void) { return Widget__FromLocalFlag(); }
48
+ int Widget_FromNested(void) { return Widget__FromNested(); }
@@ -0,0 +1,15 @@
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
+ #ifndef WIDGET_H
9
+ #define WIDGET_H
10
+
11
+ int Widget_FromProjectFlag(void);
12
+ int Widget_FromLocalFlag(void);
13
+ int Widget_FromNested(void);
14
+
15
+ #endif // WIDGET_H
@@ -0,0 +1,29 @@
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
+ /* Reproduces issue #1223: a conditional #include guarded by a macro defined
9
+ * in an EARLIER #include in this same file (as opposed to a project :defines
10
+ * macro or a same-file #define, both of which already work correctly -- see
11
+ * widget.c). Ceedling's bare-includes extraction pass runs against an
12
+ * isolated, sibling-free copy of this file and so never actually opens
13
+ * feature_config.h to learn FEATURE_LEVEL's value, evaluating the #if below
14
+ * as false and silently dropping feature_extra.h from the generated Partial
15
+ * even though FEATURE_LEVEL is genuinely > 1. */
16
+
17
+ #include "widget_feature.h"
18
+ #include "feature_config.h" /* defines FEATURE_LEVEL (2) */
19
+
20
+ #if FEATURE_LEVEL > 1
21
+ #include "feature_extra.h" /* defines FEATURE_EXTRA_MACRO */
22
+ #endif
23
+
24
+ static int WidgetFeature__FromFeatureLevel(void)
25
+ {
26
+ return FEATURE_EXTRA_MACRO;
27
+ }
28
+
29
+ int WidgetFeature_FromFeatureLevel(void) { return WidgetFeature__FromFeatureLevel(); }
@@ -0,0 +1,13 @@
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
+ #ifndef WIDGET_FEATURE_H
9
+ #define WIDGET_FEATURE_H
10
+
11
+ int WidgetFeature_FromFeatureLevel(void);
12
+
13
+ #endif // WIDGET_FEATURE_H
@@ -0,0 +1,44 @@
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
+ /* Partials pattern: TEST_PARTIAL_ALL_MODULE
9
+ * Exercises three #include-discovery scenarios that already work correctly
10
+ * without any source fix -- a regression guard locked in before touching
11
+ * the includes-discovery pipeline:
12
+ * (a) conditional include gated on a project :defines macro
13
+ * (b) conditional include gated on a same-file #define
14
+ * (c) a header reached only transitively (never itself directly
15
+ * #include'd by widget.c) correctly not duplicated in as a false
16
+ * top-level entry */
17
+
18
+ #include "unity.h"
19
+ #include "ceedling.h"
20
+
21
+ #include TEST_PARTIAL_ALL_MODULE(widget)
22
+
23
+ void setUp(void)
24
+ {
25
+ }
26
+
27
+ void tearDown(void)
28
+ {
29
+ }
30
+
31
+ void test_FromProjectFlag_ReturnsProjectFlagMacro(void)
32
+ {
33
+ TEST_ASSERT_EQUAL_INT(13, Widget__FromProjectFlag());
34
+ }
35
+
36
+ void test_FromLocalFlag_ReturnsLocalFlagMacro(void)
37
+ {
38
+ TEST_ASSERT_EQUAL_INT(11, Widget__FromLocalFlag());
39
+ }
40
+
41
+ void test_FromNested_ReturnsNestedMacro(void)
42
+ {
43
+ TEST_ASSERT_EQUAL_INT(17, Widget__FromNested());
44
+ }
@@ -0,0 +1,31 @@
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
+ /* Partials pattern: TEST_PARTIAL_ALL_MODULE
9
+ * Regression test for #1223: without the fix, this fails to *compile* --
10
+ * FEATURE_EXTRA_MACRO is undeclared in the generated Partial implementation
11
+ * because feature_extra.h's conditional #include (guarded by a macro from
12
+ * an earlier #include in widget_feature.c) is silently dropped. See
13
+ * widget_feature.c for the full explanation. */
14
+
15
+ #include "unity.h"
16
+ #include "ceedling.h"
17
+
18
+ #include TEST_PARTIAL_ALL_MODULE(widget_feature)
19
+
20
+ void setUp(void)
21
+ {
22
+ }
23
+
24
+ void tearDown(void)
25
+ {
26
+ }
27
+
28
+ void test_FromFeatureLevel_ReturnsFeatureExtraMacro(void)
29
+ {
30
+ TEST_ASSERT_EQUAL_INT(7, WidgetFeature__FromFeatureLevel());
31
+ }
data/docs/Changelog.md CHANGED
@@ -1,4 +1,4 @@
1
- p# 🌱 Ceedling Changelog
1
+ # 🌱 Ceedling Changelog
2
2
 
3
3
  This format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
@@ -10,6 +10,24 @@ This changelog is complemented by three other documents:
10
10
 
11
11
  ---
12
12
 
13
+ # [1.1.6] — 2026-08-25
14
+
15
+ ## 🌟 Added
16
+
17
+ - Latest patch releases of Unity, CMock, and CException.
18
+
19
+ ## 💪 Fixed
20
+
21
+ - [#1223](https://github.com/ThrowTheSwitch/Ceedling/issues/1223) Fixed a conditional `#include` silently dropping out of generated code derived from preprocessed code, breaking compilation with an undeclared identifier error. The specific case involves a macro defined by another header included earlier in the same file.
22
+ - [#1216](https://github.com/ThrowTheSwitch/Ceedling/issues/1216) Fixed self-test issue that caused docs-related failures when the local documentation was unavailable (generated in CI but not necessarily present during self tests).
23
+ - [#1236](https://github.com/ThrowTheSwitch/Ceedling/issues/1236) Fixed an issue that converted system includes extracted from a test C file into user includes when generating a test runner (e.g. `#include <sys/stat.h>` became `#include "stat.h"`) and also stripped relative paths from all includes injected into a test runner.
24
+
25
+ ### Partials
26
+
27
+ - [#1215](https://github.com/ThrowTheSwitch/Ceedling/issues/1215) Fixed `MOCK_PARTIAL_ALL_MODULE()`/`MOCK_PARTIAL_MODULE()` silently failing to partialize `inline` functions in some circumstances leading to duplicated symbols breaking compilation.
28
+
29
+ ---
30
+
13
31
  # [1.1.5] — 2026-08-19
14
32
 
15
33
  ## 💪 Fixed
@@ -254,6 +272,7 @@ When test preprocessing is enabled, Ceedling discovers whether your toolchain su
254
272
 
255
273
  ## 👋 Removed
256
274
 
275
+ - `:use_deep_preprocessor` was a short-lived workaround option added after 1.0.0 for certain preprpocessing limitations. Those limitations are fully resolved, and test preprocessor options are now only `:use_test_preprocessor` and `:preprocess_force_fallback`. The latter should rarely be needed, leaving only the former as the only preprocessing feature toggle in Ceedling.
257
276
  - _CeedlingPacket.md_ user manual (superseded by [new documentation site](https://throwtheswitch.github.io/Ceedling/) and local bundle).
258
277
  - _PluginDevelopmentGuide.md_ (superseded by [new documentation site](https://throwtheswitch.github.io/Ceedling/) and local bundle).
259
278
 
@@ -16,4 +16,17 @@ bool SensorHal_IsChannelReady(SensorChannel_t channel);
16
16
  void SensorHal_StartConversion(SensorChannel_t channel);
17
17
  uint32 SensorHal_GetTimestampMs(void);
18
18
 
19
+ /* Vendor-header-style static inline register accessor -- the same pattern that
20
+ * makes a real hardware header need Partial mocking instead of ordinary mocking,
21
+ * since there is no separate .c file to exclude from a test build and swap for a
22
+ * mock's .o at link time. The real body here stands in for what would otherwise
23
+ * be a direct, unsafe-off-target memory-mapped register read: it always returns
24
+ * the same obviously-wrong sentinel, so a test can tell whether this real body
25
+ * ran (Partial mocking failed to intercept the call) instead of its mock. */
26
+ static inline uint16 SensorHal_RawStatusRegister(SensorChannel_t channel)
27
+ {
28
+ (void)channel;
29
+ return 0xDEADu;
30
+ }
31
+
19
32
  #endif /* SENSOR_HAL_H */
@@ -9,9 +9,10 @@
9
9
  #include "TemperatureSensor.h"
10
10
  #include "SensorHal.h"
11
11
 
12
- static float s_calibration_offset;
13
- static int32 s_last_milli_celsius;
14
- static bool s_reading_valid;
12
+ static float s_calibration_offset;
13
+ static int32 s_last_milli_celsius;
14
+ static bool s_reading_valid;
15
+ static uint16 s_last_status_register;
15
16
 
16
17
  /* Linearized approximation: full-scale 4095 counts maps 0 C to 85 C. */
17
18
  static int32 TemperatureSensor__RawToMilliCelsius(uint16 raw_counts)
@@ -45,8 +46,9 @@ bool TemperatureSensor_Sample(void)
45
46
 
46
47
  if (!SensorHal_IsChannelReady(SENSOR_CHANNEL_TEMP)) { return false; }
47
48
 
48
- raw = SensorHal_ReadChannel(SENSOR_CHANNEL_TEMP);
49
- milli_c = TemperatureSensor__RawToMilliCelsius(raw);
49
+ raw = SensorHal_ReadChannel(SENSOR_CHANNEL_TEMP);
50
+ s_last_status_register = SensorHal_RawStatusRegister(SENSOR_CHANNEL_TEMP);
51
+ milli_c = TemperatureSensor__RawToMilliCelsius(raw);
50
52
  milli_c += (int32)(s_calibration_offset * 1000.0f);
51
53
 
52
54
  s_reading_valid = TemperatureSensor__IsInRange(milli_c);
@@ -65,3 +67,8 @@ bool TemperatureSensor_IsValid(void)
65
67
  {
66
68
  return s_reading_valid;
67
69
  }
70
+
71
+ uint16 TemperatureSensor_GetStatusRegister(void)
72
+ {
73
+ return s_last_status_register;
74
+ }
@@ -10,9 +10,10 @@
10
10
 
11
11
  #include "Types.h"
12
12
 
13
- void TemperatureSensor_Init(float calibration_offset_celsius);
14
- bool TemperatureSensor_Sample(void);
15
- int32 TemperatureSensor_GetMilliCelsius(void);
16
- bool TemperatureSensor_IsValid(void);
13
+ void TemperatureSensor_Init(float calibration_offset_celsius);
14
+ bool TemperatureSensor_Sample(void);
15
+ int32 TemperatureSensor_GetMilliCelsius(void);
16
+ bool TemperatureSensor_IsValid(void);
17
+ uint16 TemperatureSensor_GetStatusRegister(void);
17
18
 
18
19
  #endif /* TEMPERATURE_SENSOR_H */
@@ -5,17 +5,25 @@
5
5
  SPDX-License-Identifier: MIT
6
6
  ========================================================================= */
7
7
 
8
- /* Partials pattern: TEST_PARTIAL_ALL_MODULE
8
+ /* Partials pattern: TEST_PARTIAL_ALL_MODULE + MOCK_PARTIAL_ALL_MODULE
9
9
  * Tests both public functions AND the private static helpers
10
10
  * TemperatureSensor__RawToMilliCelsius() and TemperatureSensor__IsInRange().
11
11
  * Also accesses the file-scoped static s_calibration_offset directly.
12
- * SensorHal is mocked traditionally since it has no private statics. */
12
+ * SensorHal is mocked via Partials (MOCK_PARTIAL_ALL_MODULE) rather than
13
+ * traditionally: SensorHal_RawStatusRegister() is a static inline function,
14
+ * which only Partial mocking (not ordinary CMock header mocking) can
15
+ * intercept -- there is no separate SensorHal.c definition for a static
16
+ * inline function to exclude from this test build and replace with a mock
17
+ * .o at link time, so the call must be redirected to the mock before that,
18
+ * at the #include level. Every existing SensorHal_*_Expect* call below
19
+ * keeps working unchanged either way, since Partial-mocked functions use
20
+ * the identical CMock expectation API as a traditionally mocked module. */
13
21
 
14
22
  #include "unity.h"
15
23
  #include "ceedling.h"
16
- #include "MockSensorHal.h"
17
24
 
18
25
  #include TEST_PARTIAL_ALL_MODULE(TemperatureSensor)
26
+ #include MOCK_PARTIAL_ALL_MODULE(SensorHal)
19
27
 
20
28
  #include "Types.h"
21
29
 
@@ -78,6 +86,7 @@ void test_Sample_ReturnsTrueAndStoresReadingWhenReady(void)
78
86
  /* 1638 counts: (1638 * 85000) / 4095 ~= 34000 milli-C (34 C), in range */
79
87
  SensorHal_IsChannelReady_ExpectAndReturn(SENSOR_CHANNEL_TEMP, true);
80
88
  SensorHal_ReadChannel_ExpectAndReturn(SENSOR_CHANNEL_TEMP, 1638u);
89
+ SensorHal_RawStatusRegister_ExpectAndReturn(SENSOR_CHANNEL_TEMP, 0x1234u);
81
90
  SensorHal_StartConversion_Expect(SENSOR_CHANNEL_TEMP);
82
91
 
83
92
  TEST_ASSERT_TRUE(TemperatureSensor_Sample());
@@ -93,8 +102,28 @@ void test_CalibrationOffsetShiftsReading(void)
93
102
  /* 2048 counts ~= 42502 milli-C; with +1.0 C offset -> ~= 43502 */
94
103
  SensorHal_IsChannelReady_ExpectAndReturn(SENSOR_CHANNEL_TEMP, true);
95
104
  SensorHal_ReadChannel_ExpectAndReturn(SENSOR_CHANNEL_TEMP, 2048u);
105
+ SensorHal_RawStatusRegister_ExpectAndReturn(SENSOR_CHANNEL_TEMP, 0x1234u);
96
106
  SensorHal_StartConversion_Expect(SENSOR_CHANNEL_TEMP);
97
107
 
98
108
  TemperatureSensor_Sample();
99
109
  TEST_ASSERT_INT32_WITHIN(200, 43502, TemperatureSensor_GetMilliCelsius());
100
110
  }
111
+
112
+ /* Regression test for #1215: a module partial-mocked via MOCK_PARTIAL_ALL_MODULE
113
+ * (as SensorHal is above) must have its calling module's real #include swapped for
114
+ * the generated mock interface header. Without that swap, SensorHal_RawStatusRegister()'s
115
+ * real static inline body -- unreachable through ordinary link-time mock substitution,
116
+ * since a static inline function has no separate object file to exclude -- compiles
117
+ * straight into this test build and always returns its 0xDEAD sentinel regardless of
118
+ * what's expected here, no matter what the mock is told to return. */
119
+ void test_StatusRegisterReflectsMockedValueNotRealSentinel(void)
120
+ {
121
+ SensorHal_IsChannelReady_ExpectAndReturn(SENSOR_CHANNEL_TEMP, true);
122
+ SensorHal_ReadChannel_ExpectAndReturn(SENSOR_CHANNEL_TEMP, 1638u);
123
+ SensorHal_RawStatusRegister_ExpectAndReturn(SENSOR_CHANNEL_TEMP, 0x1234u);
124
+ SensorHal_StartConversion_Expect(SENSOR_CHANNEL_TEMP);
125
+
126
+ TemperatureSensor_Sample();
127
+
128
+ TEST_ASSERT_EQUAL_HEX16(0x1234u, TemperatureSensor_GetStatusRegister());
129
+ }
@@ -7,6 +7,7 @@
7
7
 
8
8
  require 'generate_test_runner' # Unity's test runner generator
9
9
  require 'ceedling/parsing_parcels'
10
+ require 'ceedling/includes/includes'
10
11
 
11
12
  class GeneratorTestRunner
12
13
 
@@ -38,7 +39,30 @@ class GeneratorTestRunner
38
39
  @test_cases_internal,
39
40
  # Small hack for mock subdirectory support until include paths fully supported
40
41
  mocks.map{ |include| include.filepath },
41
- includes.map{ |include| include.filename }
42
+ # Unity's own generator emits a string verbatim if it contains '<' and otherwise
43
+ # wraps it in double quotes -- each entry here must therefore already be in its
44
+ # final, exact form.
45
+ #
46
+ # System includes only: use the full, bracketed spelling (include_path, a
47
+ # reconciled SystemInclude's original as-written directive text -- e.g.
48
+ # "sys/stat.h" -- when set, else the directory-preserving filepath). A bare
49
+ # filename here drops both the directory component and the '<>' delimiters a
50
+ # system header's own search path depends on (issue #1236).
51
+ #
52
+ # User includes: bare filename, same as always. Unlike mocks (whose subdirectory
53
+ # is a real, dedicated build/test/mocks/<test>/ path -- hence their own
54
+ # directory-preserving filepath usage above) or a system header (whose directory
55
+ # is meaningful to the system include search path), a project's own directories
56
+ # are exposed to the compiler as a flat list of -I search paths, not nested to
57
+ # match whatever directory component a captured UserInclude's filepath happens to
58
+ # carry -- rendering the full path here breaks resolution instead of fixing it.
59
+ includes.map do |include|
60
+ if include.is_a?(SystemInclude)
61
+ "<#{include.include_path || include.filepath}>"
62
+ else
63
+ include.filename
64
+ end
65
+ end
42
66
  )
43
67
  end
44
68
 
@@ -125,8 +125,15 @@ class Partializer
125
125
 
126
126
  partials.each do |_module, config|
127
127
  # Remap mockable interface headers that will be injected into generated partial implementation
128
+ #
129
+ # Any real (non-nil) mock mode means this module has a generated mock interface header
130
+ # to redirect to -- PUBLIC/PRIVATE alone once covered every mode that existed, but DEDUCT
131
+ # (MOCK_PARTIAL_ALL_MODULE) and ACCUMULATE (MOCK_PARTIAL_MODULE) were added later without
132
+ # updating this check, so a module mocked via either of those was silently never
133
+ # redirected: its real header (and any static inline/static function bodies in it) stayed
134
+ # #include'd verbatim, compiling straight past the mock instead of being replaced by it.
128
135
  if includes.any? { |include| include.filename.ext().downcase() == _module.downcase() }
129
- if [PUBLIC, PRIVATE].include?( config.mocks.type )
136
+ if !config.mocks.type.nil?
130
137
  # Insert mockable interface header from remapping of module name
131
138
  _includes << UserInclude.new(
132
139
  @file_path_utils.form_partial_interface_header_filename(_module)
@@ -567,6 +567,28 @@ class Preprocessinator
567
567
  defines: defines
568
568
  )
569
569
 
570
+ # Supplement with a literal text scan of the original file's own #include
571
+ # lines -- the gcc-based bare pass above runs against an isolated copy that
572
+ # can never open another header, so a conditional #include whose guard
573
+ # depends on a macro defined by an *earlier #include in this same file*
574
+ # evaluates false there and silently drops out. Unioning in this text-based
575
+ # pass's result only ever adds candidates for Includes.reconcile below to
576
+ # match against the accurate directives-only pass -- it can't introduce a
577
+ # spurious entry on its own, since reconcile still requires the accurate
578
+ # pass to also report it.
579
+ #
580
+ # This supplements the gcc-based pass rather than replacing it: gcc can
581
+ # resolve an #include whose target is itself a macro (e.g. the
582
+ # MOCK_PARTIAL_ALL_MODULE()-style directives this project's own generated
583
+ # test files use), since a command-line -D define is visible even to the
584
+ # isolated copy -- a literal text scan has no filename there to find at
585
+ # all, since none exists until a real preprocessor expands the macro. The
586
+ # two passes catch different, non-overlapping failure modes; keeping both
587
+ # covers both.
588
+ bare_includes = (
589
+ bare_includes + @includes_handler.extract_bare_includes_from_text( filepath: filepath )
590
+ ).uniq( &:filename )
591
+
570
592
  # Extract user includes
571
593
  user_includes = preprocess_user_includes(
572
594
  name: test,
@@ -115,6 +115,39 @@ class PreprocessinatorIncludesHandler
115
115
  return includes
116
116
  end
117
117
 
118
+ # Scan the original file's own text for every #include line, unconditionally --
119
+ # no #if/#ifdef tracking at all, just literal presence. Supplements the gcc-based
120
+ # bare pass (`extract_bare_includes`), which runs against an isolated, sibling-free
121
+ # copy of the file and so can never open another header to resolve a conditional
122
+ # that depends on a macro that header defines (e.g. `#if SOME_MACRO_FROM_ANOTHER_HEADER`)
123
+ # -- GCC treats the macro as undefined there and silently drops the #include line
124
+ # from that pass's output even though it's a perfectly ordinary, real, top-level
125
+ # #include once actually evaluated with the real file in place. This method's result
126
+ # is meant to be unioned with the gcc-based bare pass's own result (see
127
+ # Preprocessinator#preprocess_file_includes_common), not used on its own -- an
128
+ # `Includes.reconcile` call downstream still only keeps an entry here if the
129
+ # accurate directives-only pass also reports it, so unconditionally capturing every
130
+ # literal #include line (regardless of whether its own guard is really true) is
131
+ # safe: it can only ever let back in an entry the accurate pass already confirmed,
132
+ # never introduce a spurious one on its own. A supplement, not a replacement --
133
+ # the gcc pass can still do something this literal scan structurally can't: resolve
134
+ # an #include whose own target is a macro rather than a literal filename.
135
+ def extract_bare_includes_from_text(filepath:)
136
+ includes = []
137
+
138
+ # Open in binary mode: code_lines applies clean_encoding per-line, but each_line
139
+ # itself can raise on invalid byte sequences before clean_encoding is reached.
140
+ @file_wrapper.open(filepath, 'rb') do |input|
141
+ @parsing_parcels.code_lines( input ) do |line|
142
+ _include = @include_factory.user_include_from_directive( line ) ||
143
+ @include_factory.system_include_from_directive( line )
144
+ includes << Include.new( _include.filepath ) if !_include.nil?
145
+ end
146
+ end
147
+
148
+ return clean_self_reference( filepath, includes )
149
+ end
150
+
118
151
  def extract_user_includes_preprocess(name:, filepath:, preprocessed_filepath:)
119
152
  includes = []
120
153
 
data/lib/version.rb CHANGED
@@ -15,7 +15,7 @@
15
15
  module Ceedling
16
16
  module Version
17
17
  # Convenience constants for gem building, etc.
18
- GEM = '1.1.5'
18
+ GEM = '1.1.6'
19
19
  TAG = GEM
20
20
 
21
21
  # If run as a script print Ceedling's version to $stdout
Binary file
@@ -150,6 +150,17 @@ def test_asset_path(asset_file_name)
150
150
  File.join(File.dirname(__FILE__), '..', '..', '..', 'assets', asset_file_name)
151
151
  end
152
152
 
153
+ # `ceedling new`/`upgrade` only populates a project's docs/ceedling/ by copying this
154
+ # repo's own site-local/ -- the local mkdocs HTML bundle, built only by `rake
155
+ # docs:build:local` (see bin/cli_helper.rb's own identical check). That's a step CI
156
+ # runs in a dedicated job before the test suite, but a plain local `bundle install &&
157
+ # rspec` never runs at all, so docs/ceedling/ is legitimately absent there. Tests
158
+ # asserting a deployed project's doc contents check this first rather than hardcoding
159
+ # an assumption that only ever holds in CI's own environment (issue #1216).
160
+ def html_docs_bundle_available?
161
+ Dir.exist?(File.join(File.dirname(__FILE__), '..', '..', '..', 'site-local'))
162
+ end
163
+
153
164
  def unique_proj_name(prefix)
154
165
  safe = RSpec.current_example.description
155
166
  .downcase