在 gTest 中模拟 FreeRTOS 函数
Mocking FreeRTOS functions in gTest
对于一个项目,我在嵌入式系统上用 C++ 实现了一个组件,该组件通过 FreeRTOS 队列 获取传感器数据并将它们处理成 FreeRTOS 任务.
由于硬件尚未到达和质量原因 (TDD),我想模拟 freeRTOS 功能并使用它们来模拟我的组件行为。
先谢谢你了。
一种选择是为您的主机构建您的应用程序,然后,当您的硬件到达时,您可以为该硬件重新编译它。
可以在主机 PC 上 运行 FreeRTOS 作为 CPU 上的 OS,但这不是 FreeRT 的目的[=34] =] 因此,在您的硬件上重新部署时,这可能会很棘手,或者导致一些不切实际的黑客攻击。
在 Windows 上 运行ning FreeRTOS 有一些支持,但我不太确定 Linux。
另一种选择是 freeRTOS 模拟器。需要注意的是,在模拟中,FreeRTOS 不是实际的内核(因为它会在您的目标硬件上),而是由 Windows/Linux 内核设置的线程 运行 FreeRTOS 代码。看到 FreeRTOS 是为硬时间限制而设计的,这个模拟远非理想,因为时间最终由主机的内核决定。
Windows 模拟器可以 运行 和 Visual Studio(免费版),并且该端口被维护。可能也有一些对 Eclipse 的支持。
Windows模拟器页面:http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html
Linux模拟器页面:http://www.freertos.org/FreeRTOS-simulator-for-Linux.html
所以我通过结合网站上的不同答案设法解决了我的问题:How to use google test for C++ to run through combinations of data & Can gmock be used for stubbing C functions?。
我的回答有点大,但是如果你想用的话,你可以简单地使用复制和过去。
要模拟 freeRTOS 元素,在我的测试文件夹中:
FreeRTOS_mock.hpp
/* Include freeRTOS headers */
#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"
/* Include gTest mockup functionality */
#include "gmock/gmock.h"
/* Mock all functions needed from FreeRTOS */
namespace freertos {
class FreeRTOSInterface
{
public:
virtual ~FreeRTOSInterface() {}
virtual QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType) = 0;
/* define other freeRTOS elements the same way */
};
class FreeRTOSMock : public FreeRTOSInterface
{
public:
virtual ~FreeRTOSMock() {}
MOCK_METHOD3(xQueueGenericCreate, QueueHandle_t(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType));
/* Align with what was defined above */
};
} /* namespace freertos */
FreeRTOS_mock.cpp
#include "FreeRTOS_mock.hpp"
freertos::FreeRTOSMock FreeRTOSMockObj;
QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType)
{
return FreeRTOSMockObj.xQueueGenericCreate(uxQueueLength, uxItemSize, ucQueueType);
}
/* Align with what is in the .hpp */
TestSuiteXXX_unittest.cpp
#include "FreeRTOS_mock.hpp"
extern freertos::FreeRTOSMock FreeRTOSMockObj;
/* Write my TCs by using the FreeRTOS functions*/
同样重要的是,您必须定义一个有效的 FreeRTOSConfig.h
并且在 makefile:
INCLUDE_DIRS = \
-I$(FREERTOS_DIR)/Source/include \
-I$(FREERTOS_DIR)/Source/portable/GCC/ARM_CM4F \
-I$(PRJ_FREERTOS_CFG) \
-I$(UNITTEST_INCLUDE_DIR)
SRC_FILES = \
./test/FreeRTOS_mock.cpp \
./src/XXX.cpp
#Specify all unittest files
UNITTEST_SRC_FILES = \
./test/TestSuiteXXX_unittest.cpp
模拟传感数据:
TestSuiteXXX_unittest.cpp
#include "FreeRTOS_mock.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <vector>
#include "Algo.hpp"
extern freertos::FreeRTOSMock FreeRTOSMockObj;
/* A sensor measurement */
std::vector<int32_t> input1 { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
std::vector<int32_t> output1 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
/* Not very pretty adaptation function but it does the job */
std::vector<std::tuple<int32_t, int32_t>> genSet(std::vector<int32_t> a, std::vector<int32_t> b)
{
uint32_t i(0);
std::vector<std::tuple<int32_t int32_t>> vectorToReturn(a.size());
for (i = 0 ; i < a.size(); i++)
{
vectorToReturn[i] = std::make_tuple(a[i], b[i]);
}
return vectorToReturn;
}
/** Define the Value-Parameterized Tests class */
class AlgoToTest: public ::testing::TestWithParam<std::tuple<int32_t, int32_t>>
{
public:
/* SetUp() is run immediately before a test starts. */
virtual void SetUp()
{
algo = new Algo::Algo();
}
/* TearDown() is invoked immediately after a test finishes. */
virtual void TearDown()
{
delete algo;
}
Algo::Algorithm* algo = NULL;
};
/* The test-case used to loop on */
TEST_P(AlgoToTest, AlgoTestCase1)
{
int32_t outputValue(0);
outputValue = algo->run(std::get<0>(GetParam()), std::get<1>(GetParam()));
ASSERT_EQ(outputValue, std::get<3>(GetParam()));
}
INSTANTIATE_TEST_CASE_P(AlgoTestRun1, AlgoToTest, ::testing::ValuesIn(genSet(input1, output1)));
如有改进建议,欢迎留言!
对于一个项目,我在嵌入式系统上用 C++ 实现了一个组件,该组件通过 FreeRTOS 队列 获取传感器数据并将它们处理成 FreeRTOS 任务.
由于硬件尚未到达和质量原因 (TDD),我想模拟 freeRTOS 功能并使用它们来模拟我的组件行为。
先谢谢你了。
一种选择是为您的主机构建您的应用程序,然后,当您的硬件到达时,您可以为该硬件重新编译它。
可以在主机 PC 上 运行 FreeRTOS 作为 CPU 上的 OS,但这不是 FreeRT 的目的[=34] =] 因此,在您的硬件上重新部署时,这可能会很棘手,或者导致一些不切实际的黑客攻击。
在 Windows 上 运行ning FreeRTOS 有一些支持,但我不太确定 Linux。
另一种选择是 freeRTOS 模拟器。需要注意的是,在模拟中,FreeRTOS 不是实际的内核(因为它会在您的目标硬件上),而是由 Windows/Linux 内核设置的线程 运行 FreeRTOS 代码。看到 FreeRTOS 是为硬时间限制而设计的,这个模拟远非理想,因为时间最终由主机的内核决定。
Windows 模拟器可以 运行 和 Visual Studio(免费版),并且该端口被维护。可能也有一些对 Eclipse 的支持。
Windows模拟器页面:http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html
Linux模拟器页面:http://www.freertos.org/FreeRTOS-simulator-for-Linux.html
所以我通过结合网站上的不同答案设法解决了我的问题:How to use google test for C++ to run through combinations of data & Can gmock be used for stubbing C functions?。
我的回答有点大,但是如果你想用的话,你可以简单地使用复制和过去。
要模拟 freeRTOS 元素,在我的测试文件夹中:
FreeRTOS_mock.hpp
/* Include freeRTOS headers */
#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"
/* Include gTest mockup functionality */
#include "gmock/gmock.h"
/* Mock all functions needed from FreeRTOS */
namespace freertos {
class FreeRTOSInterface
{
public:
virtual ~FreeRTOSInterface() {}
virtual QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType) = 0;
/* define other freeRTOS elements the same way */
};
class FreeRTOSMock : public FreeRTOSInterface
{
public:
virtual ~FreeRTOSMock() {}
MOCK_METHOD3(xQueueGenericCreate, QueueHandle_t(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType));
/* Align with what was defined above */
};
} /* namespace freertos */
FreeRTOS_mock.cpp
#include "FreeRTOS_mock.hpp"
freertos::FreeRTOSMock FreeRTOSMockObj;
QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType)
{
return FreeRTOSMockObj.xQueueGenericCreate(uxQueueLength, uxItemSize, ucQueueType);
}
/* Align with what is in the .hpp */
TestSuiteXXX_unittest.cpp
#include "FreeRTOS_mock.hpp"
extern freertos::FreeRTOSMock FreeRTOSMockObj;
/* Write my TCs by using the FreeRTOS functions*/
同样重要的是,您必须定义一个有效的 FreeRTOSConfig.h
并且在 makefile:
INCLUDE_DIRS = \
-I$(FREERTOS_DIR)/Source/include \
-I$(FREERTOS_DIR)/Source/portable/GCC/ARM_CM4F \
-I$(PRJ_FREERTOS_CFG) \
-I$(UNITTEST_INCLUDE_DIR)
SRC_FILES = \
./test/FreeRTOS_mock.cpp \
./src/XXX.cpp
#Specify all unittest files
UNITTEST_SRC_FILES = \
./test/TestSuiteXXX_unittest.cpp
模拟传感数据:
TestSuiteXXX_unittest.cpp
#include "FreeRTOS_mock.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <vector>
#include "Algo.hpp"
extern freertos::FreeRTOSMock FreeRTOSMockObj;
/* A sensor measurement */
std::vector<int32_t> input1 { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
std::vector<int32_t> output1 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
/* Not very pretty adaptation function but it does the job */
std::vector<std::tuple<int32_t, int32_t>> genSet(std::vector<int32_t> a, std::vector<int32_t> b)
{
uint32_t i(0);
std::vector<std::tuple<int32_t int32_t>> vectorToReturn(a.size());
for (i = 0 ; i < a.size(); i++)
{
vectorToReturn[i] = std::make_tuple(a[i], b[i]);
}
return vectorToReturn;
}
/** Define the Value-Parameterized Tests class */
class AlgoToTest: public ::testing::TestWithParam<std::tuple<int32_t, int32_t>>
{
public:
/* SetUp() is run immediately before a test starts. */
virtual void SetUp()
{
algo = new Algo::Algo();
}
/* TearDown() is invoked immediately after a test finishes. */
virtual void TearDown()
{
delete algo;
}
Algo::Algorithm* algo = NULL;
};
/* The test-case used to loop on */
TEST_P(AlgoToTest, AlgoTestCase1)
{
int32_t outputValue(0);
outputValue = algo->run(std::get<0>(GetParam()), std::get<1>(GetParam()));
ASSERT_EQ(outputValue, std::get<3>(GetParam()));
}
INSTANTIATE_TEST_CASE_P(AlgoTestRun1, AlgoToTest, ::testing::ValuesIn(genSet(input1, output1)));
如有改进建议,欢迎留言!