mirror of
https://github.com/eclipse/upm.git
synced 2025-07-25 21:21:18 +03:00
C++ Core: Add base class per sensor/actuator type
Adding base classes for UPM sensors and actuators. Signed-off-by: Noel Eck <noel.eck@intel.com>
This commit is contained in:
@ -18,10 +18,29 @@ target_link_libraries(json_tests GTest::GTest GTest::Main)
|
||||
target_include_directories(json_tests PRIVATE "${UPM_COMMON_HEADER_DIRS}/")
|
||||
gtest_add_tests(json_tests "" AUTO)
|
||||
|
||||
# Unit tests - core library
|
||||
add_executable(core_tests
|
||||
core/iUpmObject_tests.cxx
|
||||
|
||||
core/iSensortType_tests.cxx
|
||||
|
||||
core/iActuatorType_tests.cxx
|
||||
core/iServoActuator_tests.cxx
|
||||
|
||||
core/sensortype_example.json
|
||||
core/actuatortype_example.json)
|
||||
|
||||
configure_file(core/sensortype_example.json sensortype_example.json COPYONLY)
|
||||
configure_file(core/actuatortype_example.json actuatortype_example.json COPYONLY)
|
||||
|
||||
target_link_libraries(core_tests core GTest::GTest GTest::Main)
|
||||
gtest_add_tests(core_tests "" AUTO)
|
||||
|
||||
# Add a custom target for unit tests
|
||||
add_custom_target(tests-unit ALL
|
||||
DEPENDS
|
||||
utilities_tests
|
||||
json_tests
|
||||
core_tests
|
||||
COMMENT "UPM unit test collection")
|
||||
|
||||
|
39
tests/unit/core/actuatortype_example.json
Normal file
39
tests/unit/core/actuatortype_example.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"Library": "core_tests",
|
||||
"Description": "Unit test JSON example",
|
||||
"Sensor Class": {
|
||||
"ServoTest": {
|
||||
"Name": "This is a name",
|
||||
"Description": "This is a description",
|
||||
"Aliases": ["Alias blibbity", "Alias blah"],
|
||||
"Categories": ["servo"],
|
||||
"Connections": ["uart"],
|
||||
"Project Type": ["industrial", "commercial"],
|
||||
"Manufacturers": ["Omega"],
|
||||
"Commands" : {
|
||||
"axis0": {
|
||||
"unit": "degrees",
|
||||
"min" : 0.0,
|
||||
"max" : 180.0,
|
||||
"accuracy" : 1.0
|
||||
}
|
||||
},
|
||||
"Specifications": {
|
||||
"Vsource": {
|
||||
"unit": "V",
|
||||
"min": 5.0,
|
||||
"max": 5.0
|
||||
},
|
||||
"Operating Temperature": {
|
||||
"unit": "°C",
|
||||
"min": -40,
|
||||
"max": 85
|
||||
}
|
||||
}
|
||||
},
|
||||
"Urls": {
|
||||
"Product Pages": ["http://www.omega.com/pptst/RH-USB.html"],
|
||||
"Datasheets": ["http://www.omega.com/das/pdf/RH-USB.pdf"]
|
||||
}
|
||||
}
|
||||
}
|
41
tests/unit/core/iActuatorType_tests.cxx
Normal file
41
tests/unit/core/iActuatorType_tests.cxx
Normal file
@ -0,0 +1,41 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "iUpmObject.hpp"
|
||||
#include "iActuatorType.hpp"
|
||||
#include "iServoActuator.hpp"
|
||||
#include "external/json/json.hpp"
|
||||
#include <vector>
|
||||
|
||||
/* Interfaces test fixture */
|
||||
class iActuatorType_unit : public ::testing::Test, public virtual upm::iActuatorType
|
||||
{
|
||||
protected:
|
||||
/* One-time setup logic if needed */
|
||||
iActuatorType_unit()
|
||||
{
|
||||
this->initFromJsonLibDesc("./actuatortype_example.json");
|
||||
}
|
||||
|
||||
/* One-time tear-down logic if needed */
|
||||
virtual ~iActuatorType_unit() {}
|
||||
|
||||
/* Per-test setup logic if needed */
|
||||
virtual void SetUp() {}
|
||||
|
||||
/* Per-test tear-down logic if needed */
|
||||
virtual void TearDown() {}
|
||||
};
|
||||
|
||||
|
||||
TEST_F(iActuatorType_unit, test_commands_deserialize)
|
||||
{
|
||||
/* Deserialize the JSON to a map of commands */
|
||||
std::map<std::string, upm::ActuatorSink<float>> commands =
|
||||
LibraryJson()["Sensor Class"]["ServoTest"]["Commands"];
|
||||
|
||||
ASSERT_EQ(1, commands.size());
|
||||
|
||||
ASSERT_TRUE(commands.find("axis0") != commands.end());
|
||||
ASSERT_EQ("degrees", commands["axis0"].unit);
|
||||
ASSERT_EQ(0.0, commands["axis0"].min);
|
||||
ASSERT_EQ(180.0, commands["axis0"].max);
|
||||
}
|
70
tests/unit/core/iSensortType_tests.cxx
Normal file
70
tests/unit/core/iSensortType_tests.cxx
Normal file
@ -0,0 +1,70 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "iUpmObject.hpp"
|
||||
#include "iSensorType.hpp"
|
||||
#include "iTemperatureSensor.hpp"
|
||||
#include "external/json/json.hpp"
|
||||
#include <vector>
|
||||
|
||||
|
||||
/* Interfaces test fixture */
|
||||
class iSensorType_unit : public ::testing::Test, public virtual upm::iSensorType
|
||||
{
|
||||
protected:
|
||||
/* One-time setup logic if needed */
|
||||
iSensorType_unit()
|
||||
{
|
||||
this->initFromJsonLibDesc("./sensortype_example.json");
|
||||
}
|
||||
|
||||
/* One-time tear-down logic if needed */
|
||||
virtual ~iSensorType_unit() {}
|
||||
|
||||
/* Per-test setup logic if needed */
|
||||
virtual void SetUp() {}
|
||||
|
||||
/* Per-test tear-down logic if needed */
|
||||
virtual void TearDown() {}
|
||||
|
||||
//TestSensorClass& obj;
|
||||
};
|
||||
|
||||
|
||||
TEST_F(iSensorType_unit, test_sources_deserialize)
|
||||
{
|
||||
/* Deserialize the JSON to a map of sources */
|
||||
std::map<std::string, upm::SensorSource<float>> sources =
|
||||
LibraryJson()["Sensor Class"]["TestSensorClass"]["Sources"];
|
||||
|
||||
ASSERT_EQ(2, sources.size());
|
||||
|
||||
ASSERT_TRUE(sources.find("temperature") != sources.end());
|
||||
ASSERT_TRUE(sources.find("humidity-relative") != sources.end());
|
||||
ASSERT_EQ("C", sources["temperature"].unit);
|
||||
ASSERT_EQ(-17.0, sources["temperature"].min);
|
||||
ASSERT_EQ(49.0, sources["temperature"].max);
|
||||
ASSERT_EQ(1.0, sources["temperature"].accuracy);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(iSensorType_unit, test_iTemperatureSensor)
|
||||
{
|
||||
/* Mock RHUSB class */
|
||||
class RHUSB : public virtual upm::iTemperatureSensor
|
||||
{
|
||||
std::map<std::string, float> TemperatureForSources(std::vector<std::string> sources)
|
||||
{
|
||||
std::map<std::string, float> fake_temps;
|
||||
|
||||
if (std::find(sources.begin(), sources.end(), "temperature") != sources.end())
|
||||
fake_temps["temperature"] = 25.5;
|
||||
|
||||
return fake_temps;
|
||||
}
|
||||
};
|
||||
|
||||
RHUSB ts;
|
||||
ts.initFromJsonLibDesc("../../../src/rhusb/rhusb.json");
|
||||
|
||||
ASSERT_EQ(2, ts.Sources().size());
|
||||
ASSERT_EQ(25.5, ts.TemperatureForSource("temperature"));
|
||||
}
|
104
tests/unit/core/iServoActuator_tests.cxx
Normal file
104
tests/unit/core/iServoActuator_tests.cxx
Normal file
@ -0,0 +1,104 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "iUpmObject.hpp"
|
||||
#include "iServoActuator.hpp"
|
||||
#include "external/json/json.hpp"
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
/* Use the string literal operator from nlohmann */
|
||||
using namespace nlohmann;
|
||||
|
||||
/* Mock ServoTest class */
|
||||
class ES08A : public virtual upm::iServoActuator
|
||||
{
|
||||
public:
|
||||
std::map<std::string, float> sinks;
|
||||
|
||||
ES08A()
|
||||
{
|
||||
sinks["axis0"] = 0.0;
|
||||
sinks["axis1"] = 0.0;
|
||||
|
||||
/* Add a second command for testing */
|
||||
AddCommand("axis1", "degrees");
|
||||
}
|
||||
|
||||
void AngleForCommands(std::map<std::string, float> commands)
|
||||
{
|
||||
for(std::map<std::string, float>::const_iterator it = commands.begin(); it != commands.end(); ++it)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
std::cout << "Received set angle command for: " << it->first << " value: " << it->second << std::endl;
|
||||
#endif
|
||||
|
||||
std::map<std::string, float>::iterator sit = sinks.find(it->first);
|
||||
|
||||
if (sit == sinks.end())
|
||||
throw std::invalid_argument("Servo axis: " + it->first + " not found");
|
||||
|
||||
sit->second = it->second;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Interfaces test fixture */
|
||||
class iServoActuator_unit : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
iServoActuator_unit() {}
|
||||
virtual ~iServoActuator_unit() {}
|
||||
virtual void SetUp()
|
||||
{
|
||||
/* Initialize from servo.json */
|
||||
sref.initFromJsonLibDesc("../../../src/servo/servo.json");
|
||||
}
|
||||
virtual void TearDown() {}
|
||||
|
||||
ES08A sref;
|
||||
};
|
||||
|
||||
TEST_F(iServoActuator_unit, test_iServoActuator_basic)
|
||||
{
|
||||
ASSERT_EQ(2, sref.Commands().size());
|
||||
}
|
||||
|
||||
TEST_F(iServoActuator_unit, test_iServoActuator_serialize_command)
|
||||
{
|
||||
upm::ActuatorCommand<float> acmd;
|
||||
acmd.command = "axis0";
|
||||
acmd.unit = "degrees";
|
||||
acmd.value = 30.0;
|
||||
json jcmd = acmd;
|
||||
|
||||
ASSERT_EQ("{\"command\":\"axis0\",\"unit\":\"degrees\",\"value\":30.0}", jcmd.dump());
|
||||
}
|
||||
|
||||
TEST_F(iServoActuator_unit, test_iServoActuator_deserialize_command)
|
||||
{
|
||||
json jcmd = "{\"command\":\"axis0\",\"unit\":\"degrees\",\"value\":30.0}"_json;
|
||||
upm::ActuatorCommand<float> acmd = jcmd;
|
||||
}
|
||||
|
||||
TEST_F(iServoActuator_unit, test_iServoActuator_run_command)
|
||||
{
|
||||
sref.AngleFromJson("{\"command\":\"axis0\",\"unit\":\"radians\",\"value\":3.14159}");
|
||||
|
||||
ASSERT_FLOAT_EQ(3.14159, sref.sinks["axis0"]);
|
||||
}
|
||||
|
||||
TEST_F(iServoActuator_unit, test_iServoActuator_run_command_invalid_command)
|
||||
{
|
||||
ASSERT_THROW(sref.AngleFromJson("{\"command\":\"axis_doesn't_exist\",\"unit\":\"radians\",\"value\":3.14159}"),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST_F(iServoActuator_unit, test_iServoActuator_run_command_fail_deserialization)
|
||||
{
|
||||
ASSERT_THROW(sref.AngleFromJson("This is not }{ a valid JSON string"),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST_F(iServoActuator_unit, test_iServoActuator_run_commands)
|
||||
{
|
||||
sref.AngleFromJson("[{\"command\":\"axis0\",\"unit\":\"degrees\",\"value\":30.0},{\"command\":\"axis1\",\"unit\":\"radians\",\"value\":3.1}]");
|
||||
}
|
55
tests/unit/core/iUpmObject_tests.cxx
Normal file
55
tests/unit/core/iUpmObject_tests.cxx
Normal file
@ -0,0 +1,55 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "iUpmObject.hpp"
|
||||
#include "iSensorType.hpp"
|
||||
|
||||
class TestSensorClass : public virtual upm::iUpmObject
|
||||
{
|
||||
};
|
||||
|
||||
/* Interfaces test fixture */
|
||||
class iUpmObject_unit : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
/* One-time setup logic if needed */
|
||||
iUpmObject_unit()
|
||||
{
|
||||
/* Load a specific JSON library descriptor file */
|
||||
obj.initFromJsonLibDesc("./sensortype_example.json");
|
||||
}
|
||||
|
||||
/* One-time tear-down logic if needed */
|
||||
virtual ~iUpmObject_unit() {}
|
||||
|
||||
/* Per-test setup logic if needed */
|
||||
virtual void SetUp() {}
|
||||
|
||||
/* Per-test tear-down logic if needed */
|
||||
virtual void TearDown() {}
|
||||
|
||||
/* Instance of the test class */
|
||||
TestSensorClass obj;
|
||||
};
|
||||
|
||||
TEST_F(iUpmObject_unit, test_json_basic)
|
||||
{
|
||||
/* Basic checking */
|
||||
ASSERT_EQ(obj.DerivedClassName(), "TestSensorClass");
|
||||
ASSERT_EQ(obj.Description(), "This is a description");
|
||||
ASSERT_EQ(obj.LibraryBaseName(), "core_tests");
|
||||
ASSERT_EQ(obj.Name(), "TestSensorClass");
|
||||
}
|
||||
|
||||
TEST_F(iUpmObject_unit, test_json_deserialize_basic)
|
||||
{
|
||||
/* Basic checking */
|
||||
ASSERT_EQ(obj.Name(), "TestSensorClass");
|
||||
ASSERT_EQ(obj.Description(), "This is a description");
|
||||
}
|
||||
|
||||
/* Currently no need for a custom main (use gtest's)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
*/
|
45
tests/unit/core/sensortype_example.json
Normal file
45
tests/unit/core/sensortype_example.json
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"Library": "core_tests",
|
||||
"Description": "Unit test JSON example",
|
||||
"Sensor Class": {
|
||||
"TestSensorClass": {
|
||||
"Name": "This is a name",
|
||||
"Description": "This is a description",
|
||||
"Aliases": ["Alias blibbity", "Alias blah"],
|
||||
"Categories": ["humidity", "temperature"],
|
||||
"Connections": ["uart"],
|
||||
"Project Type": ["industrial", "commercial"],
|
||||
"Manufacturers": ["Omega"],
|
||||
"Sources" : {
|
||||
"temperature": {
|
||||
"unit": "C",
|
||||
"min" : -17,
|
||||
"max" : 49,
|
||||
"accuracy" : 1
|
||||
},
|
||||
"humidity-relative": {
|
||||
"unit": "%",
|
||||
"min" : 2,
|
||||
"max" : 98,
|
||||
"accuracy" : 3
|
||||
}
|
||||
},
|
||||
"Specifications": {
|
||||
"Vsource": {
|
||||
"unit": "V",
|
||||
"min": 5.0,
|
||||
"max": 5.0
|
||||
},
|
||||
"Operating Temperature": {
|
||||
"unit": "°C",
|
||||
"min": -40,
|
||||
"max": 85
|
||||
}
|
||||
}
|
||||
},
|
||||
"Urls": {
|
||||
"Product Pages": ["http://www.omega.com/pptst/RH-USB.html"],
|
||||
"Datasheets": ["http://www.omega.com/das/pdf/RH-USB.pdf"]
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user