From b4eb4d73b366116d8ad6151b8d5a0290fbeea40f Mon Sep 17 00:00:00 2001 From: Balaji Srinivasan Date: Mon, 14 Oct 2024 21:59:31 +0200 Subject: [PATCH] Add googletest example --- drivers/gpio_singleton.h | 56 +++++++++++++++++++ examples/led_driver_test_gtest/CMakeLists.txt | 39 +++++++++++++ examples/led_driver_test_gtest/led_test.cpp | 39 +++++++++++++ uut_cpp/include/led.h | 15 +++++ uut_cpp/src/led.cpp | 28 ++++++++++ 5 files changed, 177 insertions(+) create mode 100644 drivers/gpio_singleton.h create mode 100644 examples/led_driver_test_gtest/CMakeLists.txt create mode 100644 examples/led_driver_test_gtest/led_test.cpp create mode 100644 uut_cpp/include/led.h create mode 100644 uut_cpp/src/led.cpp diff --git a/drivers/gpio_singleton.h b/drivers/gpio_singleton.h new file mode 100644 index 0000000..ab4ed6b --- /dev/null +++ b/drivers/gpio_singleton.h @@ -0,0 +1,56 @@ +#ifndef GPIO_H +#define GPIO_H + +#include +#include +#include +using namespace std; + +class Gpio { +public: + // Get the singleton instance of Gpio + static Gpio& getInstance() { + static Gpio instance; + return instance; + } + + /** API to initialize GPIO. + * + * @retval 0 on success + * @retval -1 on failure + */ + virtual int init() + { + cout << "Virtual Init" << endl; + return 0; + } + + /* API that accepts multiple parameters and returns through reference. + * @param[out] name Name + * @param[in] name_len Name length in bytes + * @param[in] level Level + * @param[in] drive Drive + * + * @retval 0 on success + * @retval -1 on failure + */ + virtual int config(char* name, uint8_t name_len, int level, int drive) + { + return 0; + } + + + // Deleted copy constructor and assignment operator + Gpio(const Gpio&) = delete; + void operator=(const Gpio&) = delete; + +protected: + Gpio() {} + +private: + // Internal private methods for the actual implementation + int gpio_init_impl(); + int gpio_config_impl(char* name, uint8_t name_len, int level, int drive); +}; + +#endif // GPIO_H diff --git a/examples/led_driver_test_gtest/CMakeLists.txt b/examples/led_driver_test_gtest/CMakeLists.txt new file mode 100644 index 0000000..2fb8598 --- /dev/null +++ b/examples/led_driver_test_gtest/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.20.0) +project(led_driver_test_gtest) + +add_executable(led_driver_test_gtest led_test.cpp) + +set(WORKSPACE_ROOT ${PROJECT_SOURCE_DIR}/../../) + +project(my_project) + +# GoogleTest requires at least C++14 +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +# For Windows: Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + +enable_testing() + +target_link_libraries( + led_driver_test_gtest + GTest::gtest_main + GTest::gmock_main +) + +target_sources(led_driver_test_gtest PRIVATE ${WORKSPACE_ROOT}/uut_cpp/src/led.cpp) + +target_include_directories(led_driver_test_gtest PRIVATE ${WORKSPACE_ROOT}/drivers) +target_include_directories(led_driver_test_gtest PRIVATE ${WORKSPACE_ROOT}/uut_cpp/include) + +include(GoogleTest) +gtest_discover_tests(led_driver_test_gtest) + +add_compile_options(-Werror -Wall -g -O0 --coverage) diff --git a/examples/led_driver_test_gtest/led_test.cpp b/examples/led_driver_test_gtest/led_test.cpp new file mode 100644 index 0000000..f6ea26d --- /dev/null +++ b/examples/led_driver_test_gtest/led_test.cpp @@ -0,0 +1,39 @@ +#include +#include +#include "gpio_singleton.h" +#include "led.h" + +using ::testing::Return; + +class MockGpio : public Gpio { + public: + MOCK_METHOD(int, init, (), (override)); + MOCK_METHOD(int, config, (char* name, uint8_t name_len, int level, int drive), (override)); +}; + +// Declare external mock function +extern Gpio& getInstance(); + +// Create a fake version of getInstance() that returns the mock singleton +Gpio& getInstance() { + static MockGpio mockInstance; + return mockInstance; +} + +TEST(test_when_led_init_is_called_it_calls_gpio_init_and_returns_success, GpioInit) { + // Cast the singleton instance from Gpio& to MockGpio& to access mock-specific methods + MockGpio& mockgpio = dynamic_cast(getInstance()); + + EXPECT_CALL(mockgpio, init()).Times(1); + + Led led; + + EXPECT_EQ(0, led.init()); +} + + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + ::testing::GTEST_FLAG(throw_on_failure) = true; // Fail on unmet expectations + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/uut_cpp/include/led.h b/uut_cpp/include/led.h new file mode 100644 index 0000000..1516741 --- /dev/null +++ b/uut_cpp/include/led.h @@ -0,0 +1,15 @@ +#ifndef LED_H +#define LED_H + +#include +#include + +class Led { +public: + // Public methods for LED functionality + int init(); + void light_up(); + int config(); +}; + +#endif // LED_H diff --git a/uut_cpp/src/led.cpp b/uut_cpp/src/led.cpp new file mode 100644 index 0000000..839a7b7 --- /dev/null +++ b/uut_cpp/src/led.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include +using namespace std; +#include "gpio_singleton.h" +#include "variadic_module.h" +#include "get_inline.h" +#include "led.h" + +// Get the singleton instance of Gpio +Gpio& gpio = Gpio::getInstance(); + +int Led::init() { + cout << "Init" << endl; + return gpio.init(); // Use the singleton Gpio class for initialization +} + +int Led::config() { + const int NAME_LEN = 10; + char name[NAME_LEN]; + + // Use the singleton Gpio class for configuration + int result = gpio.config(name, sizeof(name), 1, 2); + + // Return 0 if name matches "MagicName", otherwise return -1 + return (std::strcmp(name, "MagicName") == 0) ? 0 : -1; +}