blob: 1df64fb0c2bb07797ae5944e712f8d84a993bd7e [file] [log] [blame]
#include "propertywatchtest.hpp"
#include "propertywatchimpl.hpp"
#include <array>
#include <functional>
using namespace std::string_literals;
using namespace phosphor::dbus::monitoring;
const std::array<std::string, 4> paths = {
"/xyz/openbmc_project/testing/inst1"s,
"/xyz/openbmc_project/testing/inst2"s,
"/xyz/openbmc_project/testing/inst3"s,
"/xyz/openbmc_project/testing/inst4"s,
};
const std::array<std::string, 2> interfaces = {
"xyz.openbmc_project.Iface1"s,
"xyz.openbmc_project.Iface2"s,
};
const std::array<std::string, 2> properties = {
"Value1"s,
"Value2"s,
};
const std::string meta;
std::array<std::tuple<std::any, std::any>, 8> storage = {};
const PropertyIndex watchIndex = {
{
{PropertyIndex::key_type{paths[0], interfaces[0], properties[0]},
PropertyIndex::mapped_type{meta, meta, storage[0]}},
{PropertyIndex::key_type{paths[0], interfaces[1], properties[1]},
PropertyIndex::mapped_type{meta, meta, storage[1]}},
{PropertyIndex::key_type{paths[1], interfaces[0], properties[0]},
PropertyIndex::mapped_type{meta, meta, storage[2]}},
{PropertyIndex::key_type{paths[1], interfaces[1], properties[1]},
PropertyIndex::mapped_type{meta, meta, storage[3]}},
{PropertyIndex::key_type{paths[2], interfaces[0], properties[0]},
PropertyIndex::mapped_type{meta, meta, storage[4]}},
{PropertyIndex::key_type{paths[2], interfaces[1], properties[1]},
PropertyIndex::mapped_type{meta, meta, storage[5]}},
{PropertyIndex::key_type{paths[3], interfaces[0], properties[0]},
PropertyIndex::mapped_type{meta, meta, storage[6]}},
{PropertyIndex::key_type{paths[3], interfaces[1], properties[1]},
PropertyIndex::mapped_type{meta, meta, storage[7]}},
},
};
template <typename T>
struct Values
{};
template <>
struct Values<uint8_t>
{
static auto& get(size_t i)
{
static const std::array<uint8_t, 8> values = {
{0, 1, 2, 3, 4, 5, 6, 7},
};
return values[i];
}
};
template <>
struct Values<uint16_t>
{
static auto& get(size_t i)
{
static const std::array<uint16_t, 8> values = {
{88, 77, 66, 55, 44, 33, 22, 11},
};
return values[i];
}
};
template <>
struct Values<uint32_t>
{
static auto& get(size_t i)
{
static const std::array<uint32_t, 8> values = {
{0xffffffff, 1, 3, 0, 5, 7, 9, 0xffffffff},
};
return values[i];
}
};
template <>
struct Values<uint64_t>
{
static auto& get(size_t i)
{
static const std::array<uint64_t, 8> values = {
{0xffffffffffffffff, 3, 7, 12234, 0, 3, 9, 0xffffffff},
};
return values[i];
}
};
template <>
struct Values<std::string>
{
static auto& get(size_t i)
{
static const std::array<std::string, 8> values = {
{""s, "foo"s, "bar"s, "baz"s, "hello"s, "string", "\x2\x3", "\\"},
};
return values[i];
}
};
template <typename T>
void nonFilteredCheck(const std::any& value, const size_t ndx)
{
ASSERT_EQ(value.has_value(), true);
ASSERT_EQ(std::any_cast<T>(value), Values<T>::get(ndx));
}
template <typename T>
struct FilteredValues
{};
template <>
struct FilteredValues<uint8_t>
{
static auto& opFilters()
{
static std::unique_ptr<OperandFilters<uint8_t>> filters =
std::make_unique<OperandFilters<uint8_t>>(
std::vector<std::function<bool(uint8_t)>>{
[](const auto& value) { return value < 4; }});
return filters;
}
static auto& expected(size_t i)
{
static const std::array<std::any, 8> values = {
{std::any(uint8_t(0)), std::any(uint8_t(1)), std::any(uint8_t(2)),
std::any(uint8_t(3)), std::any(), std::any(), std::any(),
std::any()}};
return values[i];
}
};
template <>
struct FilteredValues<uint16_t>
{
static auto& opFilters()
{
static std::unique_ptr<OperandFilters<uint16_t>> filters =
std::make_unique<OperandFilters<uint16_t>>(
std::vector<std::function<bool(uint16_t)>>{
[](const auto& value) { return value > 44; },
[](const auto& value) { return value != 88; }});
return filters;
}
static auto& expected(size_t i)
{
static const std::array<std::any, 8> values = {
{std::any(), std::any(uint16_t(77)), std::any(uint16_t(66)),
std::any(uint16_t(55)), std::any(), std::any(), std::any(),
std::any()}};
return values[i];
}
};
template <>
struct FilteredValues<uint32_t>
{
static auto& opFilters()
{
static std::unique_ptr<OperandFilters<uint32_t>> filters =
std::make_unique<OperandFilters<uint32_t>>(
std::vector<std::function<bool(uint32_t)>>{
[](const auto& value) { return value != 0xffffffff; },
[](const auto& value) { return value != 0; }});
return filters;
}
static auto& expected(size_t i)
{
static const std::array<std::any, 8> values = {
{std::any(), std::any(uint32_t(1)), std::any(uint32_t(3)),
std::any(), std::any(uint32_t(5)), std::any(uint32_t(7)),
std::any(uint32_t(9)), std::any()}};
return values[i];
}
};
template <>
struct FilteredValues<uint64_t>
{
static auto& opFilters()
{
static std::unique_ptr<OperandFilters<uint64_t>> filters =
std::make_unique<OperandFilters<uint64_t>>(
std::vector<std::function<bool(uint64_t)>>{
[](const auto& value) { return (value % 3) != 0; }});
return filters;
}
static auto& expected(size_t i)
{
static const std::array<std::any, 8> values = {
{std::any(), std::any(), std::any(uint64_t(7)), std::any(),
std::any(), std::any(), std::any(), std::any()}};
return values[i];
}
};
template <>
struct FilteredValues<std::string>
{
static auto& opFilters()
{
static std::unique_ptr<OperandFilters<std::string>> filters =
std::make_unique<OperandFilters<std::string>>(
std::vector<std::function<bool(std::string)>>{
[](const auto& value) { return value != ""s; },
[](const auto& value) { return value != "string"s; }});
return filters;
}
static auto& expected(size_t i)
{
static const std::array<std::any, 8> values = {
{std::any(), std::any("foo"s), std::any("bar"s), std::any("baz"s),
std::any("hello"s), std::any(), std::any("\x2\x3"s),
std::any("\\"s)}};
return values[i];
}
};
template <typename T>
void filteredCheck(const std::any& value, const size_t ndx)
{
ASSERT_EQ(value.has_value(), FilteredValues<T>::expected(ndx).has_value());
if (value.has_value())
{
ASSERT_EQ(std::any_cast<T>(value),
std::any_cast<T>(FilteredValues<T>::expected(ndx)));
}
}
template <typename T>
void testStart(std::function<void(const std::any&, const size_t)>&& checkState,
OperandFilters<T>* opFilters = nullptr)
{
using ::testing::_;
using ::testing::Return;
MockDBusInterface dbus;
MockDBusInterface::instance(dbus);
const std::vector<std::string> expectedMapperInterfaces;
PropertyWatchOfType<T, MockDBusInterface> watch(watchIndex, false,
opFilters);
auto ndx = static_cast<size_t>(0);
for (const auto& o : convert(watchIndex))
{
const auto& path = o.first.get();
const auto& interfaces = o.second;
std::vector<std::string> mapperResponse;
std::transform(interfaces.begin(), interfaces.end(),
std::back_inserter(mapperResponse),
// *INDENT-OFF*
[](const auto& item) { return item.first; });
// *INDENT-ON*
EXPECT_CALL(dbus, mapperGetObject(MAPPER_BUSNAME, MAPPER_PATH,
MAPPER_INTERFACE, "GetObject", path,
expectedMapperInterfaces))
.WillOnce(Return(GetObject({{"", mapperResponse}})));
EXPECT_CALL(
dbus, fwdAddMatch(
sdbusplus::bus::match::rules::interfacesAdded(path), _));
for (const auto& i : interfaces)
{
const auto& interface = i.first.get();
const auto& properties = i.second;
EXPECT_CALL(
dbus,
fwdAddMatch(sdbusplus::bus::match::rules::propertiesChanged(
path, interface),
_));
PropertiesChanged<T> serviceResponse;
for (const auto& p : properties)
{
serviceResponse[p] = Values<T>::get(ndx);
++ndx;
}
Expect<T>::getProperties(dbus, path, interface)
.WillOnce(Return(serviceResponse));
}
}
watch.start();
ndx = 0;
for (auto s : storage)
{
checkState(std::get<valueIndex>(s), ndx);
++ndx;
}
// Make sure start logic only runs the first time.
watch.start();
}
TEST(PropertyWatchTest, TestStart)
{
testStart<uint8_t>(nonFilteredCheck<uint8_t>);
testStart<uint16_t>(nonFilteredCheck<uint16_t>);
testStart<uint32_t>(nonFilteredCheck<uint32_t>);
testStart<uint64_t>(nonFilteredCheck<uint64_t>);
testStart<std::string>(nonFilteredCheck<std::string>);
}
TEST(PropertyWatchTest, TestFilters)
{
testStart<uint8_t>(filteredCheck<uint8_t>,
FilteredValues<uint8_t>::opFilters().get());
testStart<uint16_t>(filteredCheck<uint16_t>,
FilteredValues<uint16_t>::opFilters().get());
testStart<uint32_t>(filteredCheck<uint32_t>,
FilteredValues<uint32_t>::opFilters().get());
testStart<uint64_t>(filteredCheck<uint64_t>,
FilteredValues<uint64_t>::opFilters().get());
testStart<std::string>(filteredCheck<std::string>,
FilteredValues<std::string>::opFilters().get());
}
MockDBusInterface* MockDBusInterface::ptr = nullptr;