Makefile
  1  ################################################################################
  2  # Makefile -- MCU firmware unit test harness for AERIS-10
  3  #
  4  # Builds and runs host-side (macOS) tests for all discovered firmware bugs.
  5  # Uses mock HAL + spy/recording pattern to test real firmware code without
  6  # hardware.
  7  #
  8  # Usage:
  9  #   make          -- build and run all tests
 10  #   make build    -- build all tests without running
 11  #   make test     -- run all tests
 12  #   make clean    -- remove build artifacts
 13  #   make test_bug1  -- build and run just bug1 test
 14  #
 15  # Requirements: Apple Clang or gcc (any C11-capable compiler)
 16  ################################################################################
 17  
 18  CC       := cc
 19  CFLAGS   := -std=c11 -Wall -Wextra -Wno-unused-parameter -g -O0
 20  # Shim headers come FIRST so they override real headers
 21  INCLUDES := -Ishims -I. -I../9_1_1_C_Cpp_Libraries
 22  
 23  # Real source files compiled against mock headers
 24  REAL_SRC := ../9_1_1_C_Cpp_Libraries/adf4382a_manager.c
 25  
 26  # Mock/stub object files (shared across tests)
 27  MOCK_SRCS := stm32_hal_mock.c ad_driver_mock.c
 28  MOCK_OBJS := $(MOCK_SRCS:.c=.o)
 29  
 30  # Real source compiled as object (for tests that need it)
 31  REAL_OBJ  := adf4382a_manager.o
 32  
 33  # Platform source compiled with shim headers
 34  PLATFORM_SRC := ../9_1_1_C_Cpp_Libraries/platform_noos_stm32.c
 35  PLATFORM_OBJ := platform_noos_stm32.o
 36  
 37  # Tests that link against real adf4382a_manager.c + mocks
 38  TESTS_WITH_REAL := test_bug1_timed_sync_init_ordering \
 39                     test_bug3_timed_sync_noop \
 40                     test_bug4_phase_shift_before_check \
 41                     test_bug5_fine_phase_gpio_only \
 42                     test_bug9_platform_ops_null \
 43                     test_bug10_spi_cs_not_toggled \
 44                     test_bug15_htim3_dangling_extern
 45  
 46  # Tests that only need mocks (extracted patterns / static analysis)
 47  TESTS_MOCK_ONLY := test_bug2_ad9523_double_setup \
 48                     test_bug6_timer_variable_collision \
 49                     test_bug7_gpio_pin_conflict \
 50                     test_bug8_uart_commented_out \
 51                     test_bug14_diag_section_args \
 52                     test_gap3_emergency_stop_rails
 53  
 54  # Tests that are standalone (no mocks needed, pure logic)
 55  TESTS_STANDALONE := test_bug12_pa_cal_loop_inverted \
 56                      test_bug13_dac2_adc_buffer_mismatch \
 57                      test_gap3_iwdg_config \
 58                      test_gap3_temperature_max \
 59                      test_gap3_idq_periodic_reread \
 60                      test_gap3_emergency_state_ordering
 61  
 62  # Tests that need platform_noos_stm32.o + mocks
 63  TESTS_WITH_PLATFORM := test_bug11_platform_spi_transmit_only
 64  
 65  ALL_TESTS := $(TESTS_WITH_REAL) $(TESTS_MOCK_ONLY) $(TESTS_STANDALONE) $(TESTS_WITH_PLATFORM)
 66  
 67  .PHONY: all build test clean \
 68          $(addprefix test_,bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 bug14 bug15) \
 69          test_gap3_estop test_gap3_iwdg test_gap3_temp test_gap3_idq test_gap3_order
 70  
 71  all: build test
 72  
 73  build: $(ALL_TESTS)
 74  
 75  test: build
 76  	@echo "==============================================="
 77  	@echo "  Running all $(words $(ALL_TESTS)) bug tests..."
 78  	@echo "==============================================="
 79  	@pass=0; fail=0; \
 80  	for t in $(ALL_TESTS); do \
 81  		echo "--- Running $$t ---"; \
 82  		./$$t; \
 83  		if [ $$? -eq 0 ]; then \
 84  			pass=$$((pass + 1)); \
 85  		else \
 86  			fail=$$((fail + 1)); \
 87  			echo "*** FAILED: $$t ***"; \
 88  		fi; \
 89  	done; \
 90  	echo "==============================================="; \
 91  	echo "  Results: $$pass passed, $$fail failed (of $(words $(ALL_TESTS)) total)"; \
 92  	echo "==============================================="; \
 93  	[ $$fail -eq 0 ]
 94  
 95  # --- Object file rules ---
 96  
 97  %.o: %.c
 98  	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
 99  
100  # Real source compiled with shim headers
101  $(REAL_OBJ): $(REAL_SRC) $(MOCK_OBJS)
102  	$(CC) $(CFLAGS) $(INCLUDES) -c $(REAL_SRC) -o $@
103  
104  # Platform source compiled with shim headers
105  $(PLATFORM_OBJ): $(PLATFORM_SRC) $(MOCK_OBJS)
106  	$(CC) $(CFLAGS) $(INCLUDES) -c $(PLATFORM_SRC) -o $@
107  
108  # --- Test binary rules ---
109  
110  # Tests that need real adf4382a_manager.o + mocks
111  $(TESTS_WITH_REAL): %: %.c $(MOCK_OBJS) $(REAL_OBJ)
112  	$(CC) $(CFLAGS) $(INCLUDES) $< $(MOCK_OBJS) $(REAL_OBJ) -o $@
113  
114  # Tests that only need mocks
115  test_bug2_ad9523_double_setup: test_bug2_ad9523_double_setup.c $(MOCK_OBJS)
116  	$(CC) $(CFLAGS) $(INCLUDES) $< $(MOCK_OBJS) -o $@
117  
118  test_bug6_timer_variable_collision: test_bug6_timer_variable_collision.c $(MOCK_OBJS)
119  	$(CC) $(CFLAGS) $(INCLUDES) $< $(MOCK_OBJS) -o $@
120  
121  # Bug 7 needs shim headers + mock objects (post-fix test includes shim adf4382a_manager.h)
122  test_bug7_gpio_pin_conflict: test_bug7_gpio_pin_conflict.c $(MOCK_OBJS)
123  	$(CC) $(CFLAGS) $(INCLUDES) $< $(MOCK_OBJS) -o $@
124  
125  test_bug8_uart_commented_out: test_bug8_uart_commented_out.c
126  	$(CC) $(CFLAGS) -I. $< -o $@
127  
128  test_bug14_diag_section_args: test_bug14_diag_section_args.c $(MOCK_OBJS)
129  	$(CC) $(CFLAGS) $(INCLUDES) $< $(MOCK_OBJS) -o $@
130  
131  # Standalone tests (pure logic, no mocks)
132  test_bug12_pa_cal_loop_inverted: test_bug12_pa_cal_loop_inverted.c
133  	$(CC) $(CFLAGS) $< -lm -o $@
134  
135  test_bug13_dac2_adc_buffer_mismatch: test_bug13_dac2_adc_buffer_mismatch.c
136  	$(CC) $(CFLAGS) $< -lm -o $@
137  
138  # Gap-3 safety tests -- mock-only (needs spy log for GPIO sequence)
139  test_gap3_emergency_stop_rails: test_gap3_emergency_stop_rails.c $(MOCK_OBJS)
140  	$(CC) $(CFLAGS) $(INCLUDES) $< $(MOCK_OBJS) -o $@
141  
142  # Gap-3 safety tests -- standalone (pure logic)
143  test_gap3_iwdg_config: test_gap3_iwdg_config.c
144  	$(CC) $(CFLAGS) $< -lm -o $@
145  
146  test_gap3_temperature_max: test_gap3_temperature_max.c
147  	$(CC) $(CFLAGS) $< -lm -o $@
148  
149  test_gap3_idq_periodic_reread: test_gap3_idq_periodic_reread.c
150  	$(CC) $(CFLAGS) $< -lm -o $@
151  
152  test_gap3_emergency_state_ordering: test_gap3_emergency_state_ordering.c
153  	$(CC) $(CFLAGS) $< -o $@
154  
155  # Tests that need platform_noos_stm32.o + mocks
156  $(TESTS_WITH_PLATFORM): %: %.c $(MOCK_OBJS) $(PLATFORM_OBJ)
157  	$(CC) $(CFLAGS) $(INCLUDES) $< $(MOCK_OBJS) $(PLATFORM_OBJ) -o $@
158  
159  # --- Individual test targets ---
160  
161  test_bug1: test_bug1_timed_sync_init_ordering
162  	./test_bug1_timed_sync_init_ordering
163  
164  test_bug2: test_bug2_ad9523_double_setup
165  	./test_bug2_ad9523_double_setup
166  
167  test_bug3: test_bug3_timed_sync_noop
168  	./test_bug3_timed_sync_noop
169  
170  test_bug4: test_bug4_phase_shift_before_check
171  	./test_bug4_phase_shift_before_check
172  
173  test_bug5: test_bug5_fine_phase_gpio_only
174  	./test_bug5_fine_phase_gpio_only
175  
176  test_bug6: test_bug6_timer_variable_collision
177  	./test_bug6_timer_variable_collision
178  
179  test_bug7: test_bug7_gpio_pin_conflict
180  	./test_bug7_gpio_pin_conflict
181  
182  test_bug8: test_bug8_uart_commented_out
183  	./test_bug8_uart_commented_out
184  
185  test_bug9: test_bug9_platform_ops_null
186  	./test_bug9_platform_ops_null
187  
188  test_bug10: test_bug10_spi_cs_not_toggled
189  	./test_bug10_spi_cs_not_toggled
190  
191  test_bug11: test_bug11_platform_spi_transmit_only
192  	./test_bug11_platform_spi_transmit_only
193  
194  test_bug12: test_bug12_pa_cal_loop_inverted
195  	./test_bug12_pa_cal_loop_inverted
196  
197  test_bug13: test_bug13_dac2_adc_buffer_mismatch
198  	./test_bug13_dac2_adc_buffer_mismatch
199  
200  test_bug14: test_bug14_diag_section_args
201  	./test_bug14_diag_section_args
202  
203  test_bug15: test_bug15_htim3_dangling_extern
204  	./test_bug15_htim3_dangling_extern
205  
206  test_gap3_estop: test_gap3_emergency_stop_rails
207  	./test_gap3_emergency_stop_rails
208  
209  test_gap3_iwdg: test_gap3_iwdg_config
210  	./test_gap3_iwdg_config
211  
212  test_gap3_temp: test_gap3_temperature_max
213  	./test_gap3_temperature_max
214  
215  test_gap3_idq: test_gap3_idq_periodic_reread
216  	./test_gap3_idq_periodic_reread
217  
218  test_gap3_order: test_gap3_emergency_state_ordering
219  	./test_gap3_emergency_state_ordering
220  
221  # --- Clean ---
222  
223  clean:
224  	rm -f *.o $(ALL_TESTS)
225  	@echo "Clean complete"