summaryrefslogtreecommitdiff
path: root/deps/fff/examples
diff options
context:
space:
mode:
authorOmniscient <17525998+omnisci3nce@users.noreply.github.com>2024-02-24 22:47:46 +1100
committerOmniscient <17525998+omnisci3nce@users.noreply.github.com>2024-02-24 22:47:46 +1100
commit7b3afcaf77f96e7d62f6cd1623ead7f17512d79f (patch)
treeb5f82c64e9c06a84e4d095ab4ac48712e860b673 /deps/fff/examples
parentb047be5252aeb981faea077409c1768fda0301d9 (diff)
repo init. partial port of existing code
Diffstat (limited to 'deps/fff/examples')
-rw-r--r--deps/fff/examples/CMakeLists.txt6
-rw-r--r--deps/fff/examples/driver_testing/CMakeLists.txt31
-rw-r--r--deps/fff/examples/driver_testing/include/driver.h11
-rw-r--r--deps/fff/examples/driver_testing/include/hardware_abstraction.h15
-rw-r--r--deps/fff/examples/driver_testing/include/registers.h13
-rw-r--r--deps/fff/examples/driver_testing/src/driver.c24
-rw-r--r--deps/fff/examples/driver_testing/src/driver.test.cpp50
-rw-r--r--deps/fff/examples/driver_testing/src/driver.test.fff.cpp63
-rw-r--r--deps/fff/examples/embedded_ui/CMakeLists.txt23
-rw-r--r--deps/fff/examples/embedded_ui/Kata.txt25
-rw-r--r--deps/fff/examples/embedded_ui/include/DISPLAY.h17
-rw-r--r--deps/fff/examples/embedded_ui/include/SYSTEM.h21
-rw-r--r--deps/fff/examples/embedded_ui/include/UI.h12
-rw-r--r--deps/fff/examples/embedded_ui/src/UI.c48
-rw-r--r--deps/fff/examples/embedded_ui/src/UI_test_ansic.c183
-rw-r--r--deps/fff/examples/embedded_ui/src/UI_test_cpp.cpp136
-rw-r--r--deps/fff/examples/weak_linking/CMakeLists.txt54
-rw-r--r--deps/fff/examples/weak_linking/config/config.h.in5
-rw-r--r--deps/fff/examples/weak_linking/include/bus.h6
-rw-r--r--deps/fff/examples/weak_linking/include/display.h5
-rw-r--r--deps/fff/examples/weak_linking/include/error.h7
-rw-r--r--deps/fff/examples/weak_linking/include/sensor.h6
-rw-r--r--deps/fff/examples/weak_linking/src/bus.c30
-rw-r--r--deps/fff/examples/weak_linking/src/display.c29
-rw-r--r--deps/fff/examples/weak_linking/src/error.c10
-rw-r--r--deps/fff/examples/weak_linking/src/main.c27
-rw-r--r--deps/fff/examples/weak_linking/src/sensor.c29
-rw-r--r--deps/fff/examples/weak_linking/test/include/bus.fake.h10
-rw-r--r--deps/fff/examples/weak_linking/test/include/display.fake.h10
-rw-r--r--deps/fff/examples/weak_linking/test/include/error.fake.h10
-rw-r--r--deps/fff/examples/weak_linking/test/include/sensor.fake.h13
-rw-r--r--deps/fff/examples/weak_linking/test/include/test_common.h13
-rw-r--r--deps/fff/examples/weak_linking/test/src/bus.fake.c4
-rw-r--r--deps/fff/examples/weak_linking/test/src/display.fake.c4
-rw-r--r--deps/fff/examples/weak_linking/test/src/display.test.c24
-rw-r--r--deps/fff/examples/weak_linking/test/src/error.fake.c4
-rw-r--r--deps/fff/examples/weak_linking/test/src/main.test.c26
-rw-r--r--deps/fff/examples/weak_linking/test/src/sensor.fake.c11
-rw-r--r--deps/fff/examples/weak_linking/test/src/sensor.test.c23
-rw-r--r--deps/fff/examples/weak_linking/test/src/test_common.c33
40 files changed, 1071 insertions, 0 deletions
diff --git a/deps/fff/examples/CMakeLists.txt b/deps/fff/examples/CMakeLists.txt
new file mode 100644
index 0000000..58a3d09
--- /dev/null
+++ b/deps/fff/examples/CMakeLists.txt
@@ -0,0 +1,6 @@
+# Copyright 2022 Google LLC
+# SPDX-License-Identifier: Apache-2.0
+
+add_subdirectory(driver_testing)
+add_subdirectory(embedded_ui)
+add_subdirectory(weak_linking)
diff --git a/deps/fff/examples/driver_testing/CMakeLists.txt b/deps/fff/examples/driver_testing/CMakeLists.txt
new file mode 100644
index 0000000..3580349
--- /dev/null
+++ b/deps/fff/examples/driver_testing/CMakeLists.txt
@@ -0,0 +1,31 @@
+# Copyright 2022 Google LLC
+# SPDX-License-Identifier: Apache-2.0
+
+# Create the driver test binary
+add_executable(driver_test
+ src/driver.c
+ src/driver.test.cpp
+)
+target_include_directories(driver_test PRIVATE include)
+target_link_libraries(driver_test PRIVATE GTest::gtest_main fff)
+target_compile_definitions(driver_test PUBLIC TEST_USER_OWN_TR1_TUPLE=1 TESTING)
+
+# Create the driver fff test binary
+add_executable(driver_fff_test
+ src/driver.c
+ src/driver.test.fff.cpp
+)
+target_include_directories(driver_fff_test PRIVATE include)
+target_link_libraries(driver_fff_test PRIVATE GTest::gtest_main fff)
+target_compile_definitions(driver_fff_test PUBLIC TEST_USER_OWN_TR1_TUPLE=1 TESTING)
+
+# Add tests to ctest
+add_test(
+ NAME driver_test
+ COMMAND $<TARGET_FILE:driver_test>
+)
+
+add_test(
+ NAME driver_fff_test
+ COMMAND $<TARGET_FILE:driver_fff_test>
+)
diff --git a/deps/fff/examples/driver_testing/include/driver.h b/deps/fff/examples/driver_testing/include/driver.h
new file mode 100644
index 0000000..b7406d4
--- /dev/null
+++ b/deps/fff/examples/driver_testing/include/driver.h
@@ -0,0 +1,11 @@
+
+#ifndef DRIVER
+#define DRIVER
+
+#include <stdint.h>
+
+void driver_write(uint8_t val);
+uint8_t driver_read();
+void driver_init_device();
+
+#endif /*include guard*/
diff --git a/deps/fff/examples/driver_testing/include/hardware_abstraction.h b/deps/fff/examples/driver_testing/include/hardware_abstraction.h
new file mode 100644
index 0000000..affa92e
--- /dev/null
+++ b/deps/fff/examples/driver_testing/include/hardware_abstraction.h
@@ -0,0 +1,15 @@
+#ifndef HARDWARE_ABSTRACTION
+#define HARDWARE_ABSTRACTION
+
+#include <stdint.h>
+
+#ifndef TESTING
+#define IO_MEM_RD8(ADDR) (*((volatile uint8_t *)(ADDR)))
+#define IO_MEM_WR8(ADDR, VAL_8) (*((volatile uint8_t *)(ADDR)) = (VAL_8))
+#else
+/* In testing use fake functions to record calls to IO memory */
+uint8_t IO_MEM_RD8(uint32_t reg);
+void IO_MEM_WR8(uint32_t reg, uint8_t val);
+#endif
+
+#endif /* Include guard */
diff --git a/deps/fff/examples/driver_testing/include/registers.h b/deps/fff/examples/driver_testing/include/registers.h
new file mode 100644
index 0000000..5c9e5a9
--- /dev/null
+++ b/deps/fff/examples/driver_testing/include/registers.h
@@ -0,0 +1,13 @@
+#ifndef REGISTERS_H_
+#define REGISTERS_H_
+
+#define DRIVER_OUTPUT_REGISTER 0xFFAAu
+#define DRIVER_INPUT_REGISTER 0XFFABu
+#define DRIVER_PERIPHERAL_ENABLE_REG 0xFFACu
+#define DRIVER_PERIPHERAL_INITIALIZE_REG 0xFFACu
+
+#define HARDWARE_VERSION_REGISTER 0xFF00u
+#define HARDWARE_REV_A 0x00u
+#define HARDWARE_REV_B 0x01u
+
+#endif /* REGISTERS_H_ */
diff --git a/deps/fff/examples/driver_testing/src/driver.c b/deps/fff/examples/driver_testing/src/driver.c
new file mode 100644
index 0000000..9454ba6
--- /dev/null
+++ b/deps/fff/examples/driver_testing/src/driver.c
@@ -0,0 +1,24 @@
+
+
+#include "hardware_abstraction.h"
+#include "registers.h"
+
+void driver_write(uint8_t val)
+{
+ IO_MEM_WR8(DRIVER_OUTPUT_REGISTER, val);
+}
+
+uint8_t driver_read()
+{
+ return IO_MEM_RD8(DRIVER_INPUT_REGISTER);
+}
+
+void driver_init_device()
+{
+ uint8_t hw_version = IO_MEM_RD8(HARDWARE_VERSION_REGISTER);
+ if(HARDWARE_REV_B == hw_version)
+ {
+ IO_MEM_WR8(DRIVER_PERIPHERAL_ENABLE_REG, 1);
+ }
+ IO_MEM_WR8(DRIVER_PERIPHERAL_INITIALIZE_REG, 1);
+}
diff --git a/deps/fff/examples/driver_testing/src/driver.test.cpp b/deps/fff/examples/driver_testing/src/driver.test.cpp
new file mode 100644
index 0000000..cd80bb3
--- /dev/null
+++ b/deps/fff/examples/driver_testing/src/driver.test.cpp
@@ -0,0 +1,50 @@
+extern "C"
+{
+#include "driver.h"
+#include "registers.h"
+}
+#include "../../../fff.h"
+#include <gtest/gtest.h>
+
+
+extern "C"
+{
+ static uint8_t readVal;
+ static int readCalled;
+ static uint32_t readRegister;
+ uint8_t IO_MEM_RD8(uint32_t reg)
+ {
+ readRegister = reg;
+ readCalled++;
+ return readVal;
+ }
+
+ static uint32_t writeRegister;
+ static uint8_t writeVal;
+ static int writeCalled;
+ void IO_MEM_WR8(uint32_t reg, uint8_t val)
+ {
+ writeRegister = reg;
+ writeVal = val;
+ writeCalled++;
+ }
+}
+
+TEST(Driver, When_writing_Then_writes_data_to_DRIVER_OUTPUT_REGISTER)
+{
+ driver_write(0x34);
+ ASSERT_EQ(1u, writeCalled);
+ ASSERT_EQ(0x34u, writeVal);
+ ASSERT_EQ(DRIVER_OUTPUT_REGISTER, writeRegister);
+}
+
+
+TEST(Driver, When_reading_data_Then_reads_from_DRIVER_INPUT_REGISTER)
+{
+ readVal = 0x55;
+ uint8_t returnedValue = driver_read();
+ ASSERT_EQ(1u, readCalled);
+ ASSERT_EQ(0x55u, returnedValue);
+ ASSERT_EQ(readRegister, DRIVER_INPUT_REGISTER);
+}
+
diff --git a/deps/fff/examples/driver_testing/src/driver.test.fff.cpp b/deps/fff/examples/driver_testing/src/driver.test.fff.cpp
new file mode 100644
index 0000000..56f6192
--- /dev/null
+++ b/deps/fff/examples/driver_testing/src/driver.test.fff.cpp
@@ -0,0 +1,63 @@
+extern "C"{
+ #include "driver.h"
+ #include "registers.h"
+ #include "hardware_abstraction.h"
+}
+#include "fff.h"
+#include <gtest/gtest.h>
+
+DEFINE_FFF_GLOBALS;
+
+FAKE_VOID_FUNC(IO_MEM_WR8, uint32_t, uint8_t);
+FAKE_VALUE_FUNC(uint8_t, IO_MEM_RD8, uint32_t);
+
+class DriverTestFFF : public testing::Test
+{
+public:
+ void SetUp()
+ {
+ RESET_FAKE(IO_MEM_WR8);
+ RESET_FAKE(IO_MEM_RD8);
+ FFF_RESET_HISTORY();
+ }
+
+};
+
+TEST_F(DriverTestFFF, When_writing_Then_writes_data_to_DRIVER_OUTPUT_REGISTER)
+{
+ driver_write(0x34);
+ ASSERT_EQ(1u, IO_MEM_WR8_fake.call_count);
+ ASSERT_EQ(0x34u, IO_MEM_WR8_fake.arg1_val);
+ ASSERT_EQ(DRIVER_OUTPUT_REGISTER, IO_MEM_WR8_fake.arg0_val);
+}
+
+
+TEST_F(DriverTestFFF, When_reading_data_Then_reads_from_DRIVER_INPUT_REGISTER)
+{
+ IO_MEM_RD8_fake.return_val = 0x55;
+ uint8_t returnedValue = driver_read();
+ ASSERT_EQ(1u, IO_MEM_RD8_fake.call_count);
+ ASSERT_EQ(0x55u, returnedValue);
+ ASSERT_EQ(IO_MEM_RD8_fake.arg0_val, DRIVER_INPUT_REGISTER);
+}
+
+TEST_F(DriverTestFFF, Given_revisionB_device_When_initialize_Then_enable_peripheral_before_initializing_it)
+{
+ // Given
+ IO_MEM_RD8_fake.return_val = HARDWARE_REV_B;
+ // When
+ driver_init_device();
+
+ //Then
+ // Gets the hardware revision
+ ASSERT_EQ((void*) IO_MEM_RD8, fff.call_history[0]);
+ ASSERT_EQ(HARDWARE_VERSION_REGISTER, IO_MEM_RD8_fake.arg0_history[0]);
+ // Enables Peripheral
+ ASSERT_EQ((void*) IO_MEM_WR8, fff.call_history[1]);
+ ASSERT_EQ(DRIVER_PERIPHERAL_ENABLE_REG, IO_MEM_WR8_fake.arg0_history[0]);
+ ASSERT_EQ(1, IO_MEM_WR8_fake.arg1_history[0]);
+ // Initializes Peripheral
+ ASSERT_EQ((void*) IO_MEM_WR8, fff.call_history[2]);
+ ASSERT_EQ(DRIVER_PERIPHERAL_INITIALIZE_REG,IO_MEM_WR8_fake.arg0_history[1]);
+ ASSERT_EQ(1, IO_MEM_WR8_fake.arg1_history[1]);
+}
diff --git a/deps/fff/examples/embedded_ui/CMakeLists.txt b/deps/fff/examples/embedded_ui/CMakeLists.txt
new file mode 100644
index 0000000..d2f3015
--- /dev/null
+++ b/deps/fff/examples/embedded_ui/CMakeLists.txt
@@ -0,0 +1,23 @@
+# Copyright 2022 Google LLC
+# SPDX-License-Identifier: Apache-2.0
+
+# Create the ui_test_ansic test binary
+add_executable(ui_test_ansic src/UI_test_ansic.c src/UI.c)
+target_include_directories(ui_test_ansic PRIVATE include)
+target_link_libraries(ui_test_ansic PRIVATE fff)
+
+# Create the ui_test_cpp test binary
+add_executable(ui_test_cpp src/UI_test_cpp.cpp src/UI.c)
+target_include_directories(ui_test_cpp PRIVATE include)
+target_link_libraries(ui_test_cpp PRIVATE GTest::gtest_main fff)
+
+# Add tests to ctest
+add_test(
+ NAME ui_test_ansic
+ COMMAND $<TARGET_FILE:ui_test_ansic>
+)
+
+add_test(
+ NAME ui_test_cpp
+ COMMAND $<TARGET_FILE:ui_test_cpp>
+)
diff --git a/deps/fff/examples/embedded_ui/Kata.txt b/deps/fff/examples/embedded_ui/Kata.txt
new file mode 100644
index 0000000..b466c36
--- /dev/null
+++ b/deps/fff/examples/embedded_ui/Kata.txt
@@ -0,0 +1,25 @@
+
+Problem Definition
+------------------
+The task is to write a user interface module for an embedded device.
+
+Interrupts:
+ * The user interface is responsible for initializing the display.
+ * The user interface will register an interrupt handler for GPIO input 2 (a
+ push button).
+ * It will be possible to register a callback function for button presses.
+ * When there is no callback function set the irq handler will increment a
+ missed irq counter.
+ * When the interrupt occurs the handler will schedule or execute the button
+ press callback if there is one registered.
+Output:
+ * Tasks can write messages to the user interface to be output on the display.
+ * The display is line oriented; when the last line of the display is written
+ the user interface is responsible for clearing the display.
+ * The display is 26 characters wide. Any string longer than that must be
+ truncated before being sent to the display. The string must be null
+ terminated and thus maximum 27 bytes long.
+
+ * BONUS: Have the display be scrolling, i.e. when the display is full, the
+ previous lines must be shifted up one and the new line written in the bottom
+ line.
diff --git a/deps/fff/examples/embedded_ui/include/DISPLAY.h b/deps/fff/examples/embedded_ui/include/DISPLAY.h
new file mode 100644
index 0000000..45ca62e
--- /dev/null
+++ b/deps/fff/examples/embedded_ui/include/DISPLAY.h
@@ -0,0 +1,17 @@
+/*
+ * DISPLAY.h
+ *
+ * Created on: Dec 17, 2010
+ * Author: mlong
+ */
+
+#ifndef DISPLAY_H_
+#define DISPLAY_H_
+
+void DISPLAY_init();
+void DISPLAY_clear();
+unsigned int DISPLAY_get_line_capacity();
+unsigned int DISPLAY_get_line_insert_index();
+void DISPLAY_output(char * message);
+
+#endif /* DISPLAY_H_ */
diff --git a/deps/fff/examples/embedded_ui/include/SYSTEM.h b/deps/fff/examples/embedded_ui/include/SYSTEM.h
new file mode 100644
index 0000000..080144f
--- /dev/null
+++ b/deps/fff/examples/embedded_ui/include/SYSTEM.h
@@ -0,0 +1,21 @@
+/*
+ * DISPLAY.h
+ *
+ * Created on: Dec 17, 2010
+ * Author: mlong
+ */
+
+#ifndef SYSTEM_H_
+#define SYSTEM_H_
+
+typedef void (*irq_func_t)(void);
+
+#define IRQ_GPIO_0 0x70
+#define IRQ_GPIO_1 0x71
+#define IRQ_GPIO_2 0x72
+#define IRQ_GPIO_3 0x73
+
+
+void SYSTEM_register_irq(irq_func_t, unsigned int irq);
+
+#endif /* SYSTEM_H_ */
diff --git a/deps/fff/examples/embedded_ui/include/UI.h b/deps/fff/examples/embedded_ui/include/UI.h
new file mode 100644
index 0000000..8a3fb5c
--- /dev/null
+++ b/deps/fff/examples/embedded_ui/include/UI.h
@@ -0,0 +1,12 @@
+#ifndef UI_H_
+#define UI_H_
+
+typedef void (*button_cbk_t)(void);
+
+void UI_init();
+unsigned int UI_get_missed_irqs();
+void UI_button_irq_handler();
+void UI_register_button_cbk(button_cbk_t cbk);
+void UI_write_line(char *line);
+
+#endif /* UI_H_ */
diff --git a/deps/fff/examples/embedded_ui/src/UI.c b/deps/fff/examples/embedded_ui/src/UI.c
new file mode 100644
index 0000000..8ce996e
--- /dev/null
+++ b/deps/fff/examples/embedded_ui/src/UI.c
@@ -0,0 +1,48 @@
+#include "UI.h"
+#include "DISPLAY.h"
+#include "SYSTEM.h"
+#include <string.h>
+
+static unsigned int missed_irq_counter;
+button_cbk_t button_cbk;
+
+
+void UI_init()
+{
+ DISPLAY_init();
+ SYSTEM_register_irq(UI_button_irq_handler, IRQ_GPIO_2);
+ button_cbk = 0;
+ missed_irq_counter = 0;
+}
+
+unsigned int UI_get_missed_irqs()
+{
+ return missed_irq_counter;
+}
+
+void UI_button_irq_handler()
+{
+ if(button_cbk)
+ {
+ button_cbk();
+ }
+ else
+ {
+ missed_irq_counter++;
+ }
+}
+
+void UI_register_button_cbk(button_cbk_t cbk)
+{
+ button_cbk = cbk;
+}
+
+void UI_write_line(char *line)
+{
+ static char out[27];
+ strncpy(out, line, 26);
+ out[26] = '\0';
+ if(DISPLAY_get_line_capacity() == DISPLAY_get_line_insert_index())
+ DISPLAY_clear();
+ DISPLAY_output(out);
+}
diff --git a/deps/fff/examples/embedded_ui/src/UI_test_ansic.c b/deps/fff/examples/embedded_ui/src/UI_test_ansic.c
new file mode 100644
index 0000000..3e3fce9
--- /dev/null
+++ b/deps/fff/examples/embedded_ui/src/UI_test_ansic.c
@@ -0,0 +1,183 @@
+#include "UI.h"
+#include "fff.h"
+#include "SYSTEM.h"
+#include "DISPLAY.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Test Framework :-) */
+void setup();
+#define TEST_F(SUITE, NAME) void NAME()
+#define RUN_TEST(SUITE, TESTNAME) printf(" Running %s.%s: \n", #SUITE, #TESTNAME); setup(); TESTNAME(); printf(" SUCCESS\n");
+
+DEFINE_FFF_GLOBALS;
+
+/* SYSTEM.h */
+FAKE_VOID_FUNC2(SYSTEM_register_irq, irq_func_t, unsigned int);
+/* DISPLAY.h */
+FAKE_VOID_FUNC(DISPLAY_init);
+FAKE_VOID_FUNC(DISPLAY_clear);
+FAKE_VOID_FUNC(DISPLAY_output, char *);
+FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_capacity);
+FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_insert_index);
+
+FAKE_VOID_FUNC0(button_press_cbk);
+
+
+
+/* Initialializers called for every test */
+void setup()
+{
+ RESET_FAKE(SYSTEM_register_irq);
+
+ RESET_FAKE(DISPLAY_init)
+ RESET_FAKE(DISPLAY_clear)
+ RESET_FAKE(DISPLAY_output)
+ RESET_FAKE(DISPLAY_get_line_capacity)
+ RESET_FAKE(DISPLAY_get_line_insert_index);
+
+ RESET_FAKE(button_press_cbk);
+
+ FFF_RESET_HISTORY();
+
+ DISPLAY_get_line_capacity_fake.return_val = 2;
+}
+
+/* Tests go here */
+TEST_F(UITests, init_will_initialise_display)
+{
+ UI_init();
+ assert(DISPLAY_init_fake.call_count == 1);
+}
+
+TEST_F(UITests, init_will_register_interrupt_gpio2)
+{
+ UI_init();
+ assert(SYSTEM_register_irq_fake.call_count == 1);
+ assert(SYSTEM_register_irq_fake.arg0_val == UI_button_irq_handler);
+ assert(SYSTEM_register_irq_fake.arg1_val == IRQ_GPIO_2);
+}
+
+TEST_F(UITests, when_no_irq_then_missed_irq_counter_zero)
+{
+ assert(UI_get_missed_irqs() == 0);
+}
+
+TEST_F(UITests, when_one_irq_and_no_handler_then_missed_irq_counter_one)
+{
+ UI_button_irq_handler();
+ assert(UI_get_missed_irqs() == 1);
+}
+
+TEST_F(UITests, when_one_irq_and_valid_callback_then_missed_irq_counter_zero)
+{
+ UI_init();
+ UI_register_button_cbk(button_press_cbk);
+ UI_button_irq_handler();
+ assert(UI_get_missed_irqs() == 0);
+}
+
+TEST_F(UITests, when_one_irq_and_valid_callback_then_callback_called)
+{
+ UI_register_button_cbk(button_press_cbk);
+ UI_button_irq_handler();
+ assert(button_press_cbk_fake.call_count == 1);
+}
+
+TEST_F(UITests, write_line_outputs_lines_to_display)
+{
+ char msg[] = "helloworld";
+ UI_write_line(msg);
+ assert(DISPLAY_output_fake.call_count == 1);
+ assert(strncmp(DISPLAY_output_fake.arg0_val, msg, 26) == 0);
+}
+
+TEST_F(UITests, when_no_empty_lines_write_line_clears_screen_and_outputs_lines_to_display)
+{
+ DISPLAY_get_line_insert_index_fake.return_val = 2;
+ char msg[] = "helloworld";
+
+ UI_write_line(msg);
+
+ assert(DISPLAY_clear_fake.call_count == 1);
+ assert(DISPLAY_output_fake.call_count == 1);
+ // Check the order of the calls: Don't care about the first two:
+ // DISPLAY_get_line_capacity and DISPLAY_get_line_insert_index
+ assert(fff.call_history_idx == 4);
+ assert(fff.call_history[2] == (void *) DISPLAY_clear);
+ assert(fff.call_history[3] == (void *) DISPLAY_output);
+}
+
+TEST_F(UITests, when_empty_lines_write_line_doesnt_clear_screen)
+{
+ // given
+ DISPLAY_get_line_insert_index_fake.return_val = 1;
+ char msg[] = "helloworld";
+ // when
+ UI_write_line(msg);
+ // then
+ assert(DISPLAY_clear_fake.call_count == 0);
+}
+
+TEST_F(UITests, when_string_longer_than_26_then_truncated_string_output)
+{
+ // given
+ char input[] = "abcdefghijklmnopqrstuvwxyz0123456789";
+ char expected[] = "abcdefghijklmnopqrstuvwxyz";
+ // when
+ UI_write_line(input);
+ // then
+ assert(strncmp(expected, DISPLAY_output_fake.arg0_val, 37) == 0);
+}
+
+TEST_F(UITests, when_outputting_to_full_display_then_previous_inserted)
+{
+ // given
+ DISPLAY_get_line_insert_index_fake.return_val = 1;
+ char oldest[] = "oldest";
+ char newest[] = "newest";
+ // when
+ UI_write_line(oldest);
+ UI_write_line(newest);
+ // then
+
+ assert(DISPLAY_output_fake.call_count == 2);
+
+ // fills last line
+ assert(strncmp(oldest, DISPLAY_output_fake.arg0_history[0], 37) == 0);
+ //clears
+ assert(DISPLAY_clear_fake.call_count == 1);
+ // inserts old line at first
+ assert(strncmp(oldest, DISPLAY_output_fake.arg0_history[1], 37) == 0);
+ // then inserts new line
+ assert(strncmp(newest, DISPLAY_output_fake.arg0_history[2], 37) == 0);
+}
+
+int main()
+{
+ setbuf(stdout, NULL);
+ fprintf(stdout, "-------------\n");
+ fprintf(stdout, "Running Tests\n");
+ fprintf(stdout, "-------------\n\n");
+ fflush(0);
+
+ /* Run tests */
+ RUN_TEST(UITests, init_will_initialise_display);
+ RUN_TEST(UITests, init_will_register_interrupt_gpio2);
+ RUN_TEST(UITests, when_no_irq_then_missed_irq_counter_zero);
+ RUN_TEST(UITests, when_one_irq_and_no_handler_then_missed_irq_counter_one);
+ RUN_TEST(UITests, when_one_irq_and_valid_callback_then_missed_irq_counter_zero);
+ RUN_TEST(UITests, when_one_irq_and_valid_callback_then_callback_called);
+ RUN_TEST(UITests, write_line_outputs_lines_to_display);
+ RUN_TEST(UITests, when_no_empty_lines_write_line_clears_screen_and_outputs_lines_to_display);
+ RUN_TEST(UITests, when_empty_lines_write_line_doesnt_clear_screen);
+ RUN_TEST(UITests, when_string_longer_than_26_then_truncated_string_output);
+
+ printf("\n-------------\n");
+ printf("Complete\n");
+ printf("-------------\n\n");
+
+ return 0;
+}
diff --git a/deps/fff/examples/embedded_ui/src/UI_test_cpp.cpp b/deps/fff/examples/embedded_ui/src/UI_test_cpp.cpp
new file mode 100644
index 0000000..e7d9bba
--- /dev/null
+++ b/deps/fff/examples/embedded_ui/src/UI_test_cpp.cpp
@@ -0,0 +1,136 @@
+extern "C"{
+#include "UI.h"
+#include "SYSTEM.h"
+#include "DISPLAY.h"
+}
+#include <gtest/gtest.h>
+
+
+#include "fff.h"
+DEFINE_FFF_GLOBALS;
+
+/* SYSTEM.h */
+FAKE_VOID_FUNC(SYSTEM_register_irq, irq_func_t, unsigned int);
+/* DISPLAY.h */
+FAKE_VOID_FUNC(DISPLAY_init);
+FAKE_VOID_FUNC(DISPLAY_clear);
+FAKE_VOID_FUNC(DISPLAY_output, char *);
+FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_capacity);
+FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_insert_index);
+
+FAKE_VOID_FUNC(button_press_cbk);
+
+
+class UITests : public testing::Test
+{
+public:
+
+ void SetUp()
+ {
+ // Register resets
+ RESET_FAKE(SYSTEM_register_irq);
+
+ RESET_FAKE(DISPLAY_init)
+ RESET_FAKE(DISPLAY_clear)
+ RESET_FAKE(DISPLAY_output)
+ RESET_FAKE(DISPLAY_get_line_capacity)
+ RESET_FAKE(DISPLAY_get_line_insert_index);
+
+ RESET_FAKE(button_press_cbk);
+
+ FFF_RESET_HISTORY();
+ // non default init
+ DISPLAY_get_line_capacity_fake.return_val = 2;
+ }
+};
+
+
+
+/* Tests go here */
+TEST_F(UITests, init_will_initialise_display)
+{
+ UI_init();
+ ASSERT_EQ(DISPLAY_init_fake.call_count, 1);
+}
+
+TEST_F(UITests, init_will_register_interrupt_gpio2)
+{
+ UI_init();
+ ASSERT_EQ(SYSTEM_register_irq_fake.call_count, 1);
+ ASSERT_EQ((void *)SYSTEM_register_irq_fake.arg0_val, (void *)UI_button_irq_handler);
+ ASSERT_EQ(SYSTEM_register_irq_fake.arg1_val, IRQ_GPIO_2);
+}
+
+TEST_F(UITests, when_no_irq_then_missed_irq_counter_zero)
+{
+ ASSERT_EQ(UI_get_missed_irqs(), 0);
+}
+
+TEST_F(UITests, when_one_irq_and_no_handler_then_missed_irq_counter_one)
+{
+ UI_button_irq_handler();
+ ASSERT_EQ(UI_get_missed_irqs(), 1);
+}
+
+TEST_F(UITests, when_one_irq_and_valid_callback_then_missed_irq_counter_zero)
+{
+ UI_init();
+ UI_register_button_cbk(button_press_cbk);
+ UI_button_irq_handler();
+ ASSERT_EQ(UI_get_missed_irqs(), 0);
+}
+
+TEST_F(UITests, when_one_irq_and_valid_callback_then_callback_called)
+{
+ UI_register_button_cbk(button_press_cbk);
+ UI_button_irq_handler();
+ ASSERT_EQ(button_press_cbk_fake.call_count, 1);
+}
+
+TEST_F(UITests, write_line_outputs_lines_to_display)
+{
+ char msg[] = "helloworld";
+ UI_write_line(msg);
+ ASSERT_EQ(DISPLAY_output_fake.call_count, 1);
+ ASSERT_EQ(strncmp(DISPLAY_output_fake.arg0_val, msg, 26), 0);
+}
+
+TEST_F(UITests, when_no_empty_lines_write_line_clears_screen_and_outputs_lines_to_display)
+{
+ DISPLAY_get_line_insert_index_fake.return_val = 2;
+ char msg[] = "helloworld";
+
+ UI_write_line(msg);
+
+ ASSERT_EQ(DISPLAY_clear_fake.call_count, 1);
+ ASSERT_EQ(DISPLAY_output_fake.call_count, 1);
+ // Check the order of the calls: Don't care about the first two:
+ // DISPLAY_get_line_capacity and DISPLAY_get_line_insert_index
+ ASSERT_EQ(fff.call_history_idx, 4);
+ ASSERT_EQ(fff.call_history[2], (void *) DISPLAY_clear);
+ ASSERT_EQ(fff.call_history[3], (void *) DISPLAY_output);
+}
+
+TEST_F(UITests, when_empty_lines_write_line_doesnt_clear_screen)
+{
+ // given
+ DISPLAY_get_line_insert_index_fake.return_val = 1;
+ char msg[] = "helloworld";
+ // when
+ UI_write_line(msg);
+ // then
+ ASSERT_EQ(DISPLAY_clear_fake.call_count, 0);
+}
+
+TEST_F(UITests, when_string_longer_than_26_then_truncated_string_output)
+{
+ // given
+ char input[] = "abcdefghijklmnopqrstuvwxyz0123456789";
+ char expected[] = "abcdefghijklmnopqrstuvwxyz";
+ // when
+ UI_write_line(input);
+ // then
+ ASSERT_EQ(strncmp(expected, DISPLAY_output_fake.arg0_val, 37), 0);
+}
+
+
diff --git a/deps/fff/examples/weak_linking/CMakeLists.txt b/deps/fff/examples/weak_linking/CMakeLists.txt
new file mode 100644
index 0000000..b1d5679
--- /dev/null
+++ b/deps/fff/examples/weak_linking/CMakeLists.txt
@@ -0,0 +1,54 @@
+# Copyright 2022 Google LLC
+# SPDX-License-Identifier: Apache-2.0
+
+# Skip these tests for Windows
+if(WIN32)
+ message(STATUS "Weak linking requires __attribute__((weak)) which isn't supported on MS VS, skipping tests")
+ return()
+endif()
+
+# Set the global FFF_GCC_FUNCTION_ATTRIBUTES for config.h
+set(FFF_GCC_FUNCTION_ATTRIBUTES "__attribute__((weak))")
+configure_file(config/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+
+# Create a libfakes static library that will be used in the executables below.
+# This library will depend on the above generated config.h which will add the
+# FFF 'weak' function attributes.
+add_library(libfakes STATIC
+ test/src/bus.fake.c
+ test/src/display.fake.c
+ test/src/error.fake.c
+ test/src/sensor.fake.c
+ test/src/test_common.c
+)
+target_precompile_headers(libfakes PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+target_include_directories(libfakes PUBLIC include test/include)
+target_link_libraries(libfakes PUBLIC fff)
+
+# Create the main test binary
+add_executable(test_main src/main.c test/src/main.test.c)
+target_link_libraries(test_main PRIVATE libfakes)
+
+# Create the sensor test binary
+add_executable(test_sensor src/sensor.c test/src/sensor.test.c)
+target_link_libraries(test_sensor PRIVATE libfakes)
+
+# Create the display test binary
+add_executable(test_display src/display.c test/src/display.test.c ${LIBFAKES_SRCS})
+target_link_libraries(test_display PRIVATE libfakes)
+
+# Add tests to ctest
+add_test(
+ NAME test_main
+ COMMAND $<TARGET_FILE:test_main>
+)
+
+add_test(
+ NAME test_sensor
+ COMMAND $<TARGET_FILE:test_sensor>
+)
+
+add_test(
+ NAME test_display
+ COMMAND $<TARGET_FILE:test_display>
+)
diff --git a/deps/fff/examples/weak_linking/config/config.h.in b/deps/fff/examples/weak_linking/config/config.h.in
new file mode 100644
index 0000000..30121ce
--- /dev/null
+++ b/deps/fff/examples/weak_linking/config/config.h.in
@@ -0,0 +1,5 @@
+/* Copyright 2022 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#cmakedefine FFF_GCC_FUNCTION_ATTRIBUTES @FFF_GCC_FUNCTION_ATTRIBUTES@
diff --git a/deps/fff/examples/weak_linking/include/bus.h b/deps/fff/examples/weak_linking/include/bus.h
new file mode 100644
index 0000000..84a56cf
--- /dev/null
+++ b/deps/fff/examples/weak_linking/include/bus.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "error.h"
+
+bool bus_read_write( uint8_t dev, uint8_t registry, uint8_t* buffer, int len, bool assume_echo );
+bool bus_write( uint8_t dev, uint8_t registry, const uint8_t* buffer, int len, bool assume_echo );
diff --git a/deps/fff/examples/weak_linking/include/display.h b/deps/fff/examples/weak_linking/include/display.h
new file mode 100644
index 0000000..da1ee1f
--- /dev/null
+++ b/deps/fff/examples/weak_linking/include/display.h
@@ -0,0 +1,5 @@
+#pragma once
+#include "error.h"
+
+bool display_init();
+void display_update( const char* info );
diff --git a/deps/fff/examples/weak_linking/include/error.h b/deps/fff/examples/weak_linking/include/error.h
new file mode 100644
index 0000000..dd52269
--- /dev/null
+++ b/deps/fff/examples/weak_linking/include/error.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+void runtime_error( const char* msg );
+char* runtime_error_nice_print( const char* msg );
diff --git a/deps/fff/examples/weak_linking/include/sensor.h b/deps/fff/examples/weak_linking/include/sensor.h
new file mode 100644
index 0000000..e199e45
--- /dev/null
+++ b/deps/fff/examples/weak_linking/include/sensor.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "error.h"
+
+bool sensor_init();
+float sensor_read();
diff --git a/deps/fff/examples/weak_linking/src/bus.c b/deps/fff/examples/weak_linking/src/bus.c
new file mode 100644
index 0000000..5706932
--- /dev/null
+++ b/deps/fff/examples/weak_linking/src/bus.c
@@ -0,0 +1,30 @@
+#pragma once
+
+uint16_t* BUS_REGISTER_BASE = (uint16_t*)0xDEADBEEF;
+
+typedef struct
+{
+ uint16_t action;
+ uint16_t reg;
+ uint8_t input;
+ uint8_t output
+} BusDevice;
+
+BusDevice* BUS = (BusDevice*)BUS_REGISTER_BASE;
+
+bool bus_read_write( uint8_t dev, uint8_t registry, uint8_t* buffer, int len, bool assume_echo )
+{
+ // Something that we dont want to run, since the emulation would be hard.
+ BUS->action = 0x01;
+ BUS->reg = registry;
+ for ( int loop =0 ; loop < len; loop ++ )
+ {
+ char output = buffer[loop];
+ BUS->output = output;
+ buffer[loop] = BUS->input;
+
+ if ( ( assume_echo ) && ( buffer[loop] != output ) )
+ return false;
+ }
+ return true;
+}
diff --git a/deps/fff/examples/weak_linking/src/display.c b/deps/fff/examples/weak_linking/src/display.c
new file mode 100644
index 0000000..1b9a7d6
--- /dev/null
+++ b/deps/fff/examples/weak_linking/src/display.c
@@ -0,0 +1,29 @@
+#include <string.h>
+
+#include "display.h"
+#include "bus.h"
+
+#define DISPLAY_ADDRESS 0xAF
+#define DISPLAY_REG_INIT 0x10
+#define DISPLAY_REG_UPDATE 0x20
+
+bool display_init()
+{
+ char init_config[] = { 0xDE, 0xFE, 0x00 };
+ bus_read_write( DISPLAY_ADDRESS, DISPLAY_REG_INIT, (uint8_t*)init_config, 3, false );
+
+ if (init_config[2] != 0x10)
+ return false;
+
+ return true;
+}
+
+void display_update( const char* info )
+{
+ int len = strlen( info );
+
+ if ( bus_write( DISPLAY_ADDRESS, DISPLAY_REG_UPDATE, (const uint8_t*)info, len, true ) != true )
+ {
+ runtime_error("display update failed!");
+ }
+}
diff --git a/deps/fff/examples/weak_linking/src/error.c b/deps/fff/examples/weak_linking/src/error.c
new file mode 100644
index 0000000..5e7db63
--- /dev/null
+++ b/deps/fff/examples/weak_linking/src/error.c
@@ -0,0 +1,10 @@
+#include <assert.h>
+#include "error.h"
+
+char* runtime_error_nice_print( const char* msg )
+{
+ char* buffer = malloc(512);
+ snprintf(buffer, 512, "Got error: %s", msg );
+ buffer[511] = 0;
+ return buffer;
+}
diff --git a/deps/fff/examples/weak_linking/src/main.c b/deps/fff/examples/weak_linking/src/main.c
new file mode 100644
index 0000000..88be84c
--- /dev/null
+++ b/deps/fff/examples/weak_linking/src/main.c
@@ -0,0 +1,27 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "display.h"
+#include "sensor.h"
+
+void give_error( const char* msg )
+{
+ char* buffer = runtime_error_nice_print( msg );
+ runtime_error( buffer );
+ free(buffer);
+}
+
+int update_main( void )
+{
+ if ( !sensor_init() )
+ runtime_error("sensor init failed");
+
+ if ( !display_init() )
+ runtime_error("display init failed");
+
+ char buffer[32];
+ float reading = sensor_read();
+ snprintf( buffer, 32, "Sensor: %0.1f", reading );
+ display_update( buffer );
+ return 0;
+}
diff --git a/deps/fff/examples/weak_linking/src/sensor.c b/deps/fff/examples/weak_linking/src/sensor.c
new file mode 100644
index 0000000..bff6642
--- /dev/null
+++ b/deps/fff/examples/weak_linking/src/sensor.c
@@ -0,0 +1,29 @@
+#include <string.h>
+
+#include "sensor.h"
+#include "bus.h"
+
+#define SENSOR_ADDRESS 0xAA
+#define SENSOR_REG_READ 0xF0
+
+float LOCAL_buffer[4];
+
+bool sensor_init()
+{
+ memset( LOCAL_buffer, 0x00, sizeof(LOCAL_buffer));
+ return true;
+}
+
+float sensor_read()
+{
+ char data[4] = { 0xFF, 0xFF, 0x00, 0x00 };
+ bus_read_write( SENSOR_ADDRESS, SENSOR_REG_READ, (uint8_t*)&data, 4, false );
+
+ if (data[0] != 0x10)
+ {
+ runtime_error("sensor read failed");
+ }
+
+ float ret_value = data[1] + data[2] / 256.0;
+ return ret_value;
+}
diff --git a/deps/fff/examples/weak_linking/test/include/bus.fake.h b/deps/fff/examples/weak_linking/test/include/bus.fake.h
new file mode 100644
index 0000000..170e45a
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/include/bus.fake.h
@@ -0,0 +1,10 @@
+#ifndef _AUTOFAKE_BUS_H
+#define _AUTOFAKE_BUS_H
+
+#include "fff.h"
+#include "bus.h"
+
+DECLARE_FAKE_VALUE_FUNC( bool, bus_read_write, uint8_t, uint8_t, uint8_t*, int, bool );
+DECLARE_FAKE_VALUE_FUNC( bool, bus_write, uint8_t, uint8_t, const uint8_t*, int, bool );
+
+#endif // _AUTOFAKE_BUS_H
diff --git a/deps/fff/examples/weak_linking/test/include/display.fake.h b/deps/fff/examples/weak_linking/test/include/display.fake.h
new file mode 100644
index 0000000..ef2adae
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/include/display.fake.h
@@ -0,0 +1,10 @@
+#ifndef _AUTOFAKE_DISPLAY_H
+#define _AUTOFAKE_DISPLAY_H
+
+#include "fff.h"
+#include "display.h"
+
+DECLARE_FAKE_VALUE_FUNC( bool, display_init );
+DECLARE_FAKE_VOID_FUNC( display_update, const char* );
+
+#endif // _AUTOFAKE_DISPLAY_H
diff --git a/deps/fff/examples/weak_linking/test/include/error.fake.h b/deps/fff/examples/weak_linking/test/include/error.fake.h
new file mode 100644
index 0000000..ee127ec
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/include/error.fake.h
@@ -0,0 +1,10 @@
+#ifndef _AUTOFAKE_ERROR_H
+#define _AUTOFAKE_ERROR_H
+
+#include "fff.h"
+#include "error.h"
+
+DECLARE_FAKE_VOID_FUNC( runtime_error, const char* );
+DECLARE_FAKE_VALUE_FUNC( char*, runtime_error_nice_print, const char* );
+
+#endif // _AUTOFAKE_ERROR_H
diff --git a/deps/fff/examples/weak_linking/test/include/sensor.fake.h b/deps/fff/examples/weak_linking/test/include/sensor.fake.h
new file mode 100644
index 0000000..ae363f8
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/include/sensor.fake.h
@@ -0,0 +1,13 @@
+
+#ifndef _AUTOMOCK_SENSOR_H
+#define _AUTOMOCK_SENSOR_H
+
+#include "fff.h"
+#include "sensor.h"
+
+DECLARE_FAKE_VALUE_FUNC( bool, sensor_init );
+DECLARE_FAKE_VALUE_FUNC( float, sensor_read );
+
+void TEST_sensor_generate_data( char* buffer, float value );
+
+#endif // _AUTOMOCK_SENSOR_H
diff --git a/deps/fff/examples/weak_linking/test/include/test_common.h b/deps/fff/examples/weak_linking/test/include/test_common.h
new file mode 100644
index 0000000..a282dd1
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/include/test_common.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "fff.h"
+#include "bus.fake.h"
+#include "error.fake.h"
+
+
+void init_tests();
+
+extern char GLOBAL_TEST_bus_read_ret[32];
diff --git a/deps/fff/examples/weak_linking/test/src/bus.fake.c b/deps/fff/examples/weak_linking/test/src/bus.fake.c
new file mode 100644
index 0000000..e3a9f76
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/src/bus.fake.c
@@ -0,0 +1,4 @@
+#include "bus.fake.h"
+
+DEFINE_FAKE_VALUE_FUNC( bool, bus_read_write, uint8_t, uint8_t, uint8_t*, int, bool );
+DEFINE_FAKE_VALUE_FUNC( bool, bus_write, uint8_t, uint8_t, const uint8_t*, int, bool );
diff --git a/deps/fff/examples/weak_linking/test/src/display.fake.c b/deps/fff/examples/weak_linking/test/src/display.fake.c
new file mode 100644
index 0000000..f8dec66
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/src/display.fake.c
@@ -0,0 +1,4 @@
+#include "display.fake.h"
+
+DEFINE_FAKE_VALUE_FUNC( bool, display_init );
+DEFINE_FAKE_VOID_FUNC( display_update, const char* );
diff --git a/deps/fff/examples/weak_linking/test/src/display.test.c b/deps/fff/examples/weak_linking/test/src/display.test.c
new file mode 100644
index 0000000..269ae32
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/src/display.test.c
@@ -0,0 +1,24 @@
+#include "test_common.h"
+#include "display.h"
+
+DEFINE_FFF_GLOBALS;
+
+
+int main(void)
+{
+ init_tests(); // Resets common and hook errors to asserts.
+
+ GLOBAL_TEST_bus_read_ret[2] = 0x10;
+ assert( display_init() == true );
+ assert( bus_read_write_fake.call_count == 1);
+
+ display_update( "TEST INFO" );
+ assert( bus_read_write_fake.call_count == 1 );
+ assert( bus_write_fake.call_count == 1 );
+
+ GLOBAL_TEST_bus_read_ret[2] = 0x00;
+ assert( display_init() == false );
+
+ printf("Test " __FILE__ " ok\n");
+ return 0;
+}
diff --git a/deps/fff/examples/weak_linking/test/src/error.fake.c b/deps/fff/examples/weak_linking/test/src/error.fake.c
new file mode 100644
index 0000000..0a39478
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/src/error.fake.c
@@ -0,0 +1,4 @@
+#include "error.fake.h"
+
+DEFINE_FAKE_VOID_FUNC( runtime_error, const char* );
+DEFINE_FAKE_VALUE_FUNC( char*, runtime_error_nice_print, const char* );
diff --git a/deps/fff/examples/weak_linking/test/src/main.test.c b/deps/fff/examples/weak_linking/test/src/main.test.c
new file mode 100644
index 0000000..6ac023c
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/src/main.test.c
@@ -0,0 +1,26 @@
+
+#include "display.fake.h"
+#include "sensor.fake.h"
+#include "test_common.h"
+
+DEFINE_FFF_GLOBALS;
+
+
+int update_main( void );
+
+int main(void)
+{
+ init_tests(); // Resets common and hook errors to asserts.
+
+ sensor_init_fake.return_val = true;
+ display_init_fake.return_val = true;
+
+ update_main();
+
+ assert( sensor_init_fake.call_count == 1 );
+ assert( display_init_fake.call_count == 1 );
+ assert( display_update_fake.call_count == 1 );
+
+ printf("Test " __FILE__ " ok\n");
+ return 0;
+}
diff --git a/deps/fff/examples/weak_linking/test/src/sensor.fake.c b/deps/fff/examples/weak_linking/test/src/sensor.fake.c
new file mode 100644
index 0000000..4fdaa66
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/src/sensor.fake.c
@@ -0,0 +1,11 @@
+#include "sensor.fake.h"
+
+DEFINE_FAKE_VALUE_FUNC( bool, sensor_init );
+DEFINE_FAKE_VALUE_FUNC( float, sensor_read );
+
+void TEST_sensor_generate_data( char* buffer, float value )
+{
+ buffer[0] = 0x10;
+ buffer[1] = (int)(value);
+ buffer[2] = (value - buffer[1])*255;
+}
diff --git a/deps/fff/examples/weak_linking/test/src/sensor.test.c b/deps/fff/examples/weak_linking/test/src/sensor.test.c
new file mode 100644
index 0000000..8126cb6
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/src/sensor.test.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+#include "test_common.h"
+
+#include "sensor.h"
+#include "sensor.fake.h"
+
+DEFINE_FFF_GLOBALS;
+
+
+int main(void)
+{
+ init_tests();
+
+ assert( sensor_init() == true );
+
+ TEST_sensor_generate_data( GLOBAL_TEST_bus_read_ret, 1.5f );
+ float value = sensor_read();
+ float value_error = value - 1.5f;
+ assert( value_error < 0.1f && value_error > -0.1f );
+ printf("Test " __FILE__ " ok\n");
+ return 0;
+}
diff --git a/deps/fff/examples/weak_linking/test/src/test_common.c b/deps/fff/examples/weak_linking/test/src/test_common.c
new file mode 100644
index 0000000..58c3b44
--- /dev/null
+++ b/deps/fff/examples/weak_linking/test/src/test_common.c
@@ -0,0 +1,33 @@
+#include "test_common.h"
+#include <assert.h>
+#include <stdio.h>
+
+char GLOBAL_TEST_bus_read_ret[32];
+
+
+void spoof_runtime_error( const char* info )
+{
+ fprintf(stderr, "Runtime error: %s\n", info );
+ assert(0);
+}
+
+bool spoof_bus_read_write( uint8_t dev, uint8_t registry, uint8_t* buffer, int len, bool assume_echo )
+{
+ memcpy( buffer, GLOBAL_TEST_bus_read_ret, len );
+ fprintf(stderr, "bus spoof %d %d\n", (int)dev, (int)registry );
+ return true;
+}
+
+void init_tests()
+{
+ memset( GLOBAL_TEST_bus_read_ret, 0x00, sizeof(GLOBAL_TEST_bus_read_ret));
+ FFF_RESET_HISTORY();
+
+ RESET_FAKE(bus_read_write);
+ RESET_FAKE(bus_write);
+ RESET_FAKE(runtime_error);
+
+ runtime_error_fake.custom_fake = spoof_runtime_error;
+ bus_read_write_fake.custom_fake = spoof_bus_read_write;
+ bus_write_fake.return_val = true;
+} \ No newline at end of file