blob: 660d6473ef4e2b4b2e1947a1153859c2d95fd082 [file] [log] [blame]
#include "app/server/JointFabricDatastore.h"
#include <pw_unit_test/framework.h>
using namespace chip;
using namespace chip::app;
namespace {
class DummyListener : public JointFabricDatastore::Listener
{
public:
void MarkNodeListChanged() override { mNotified = true; }
void Reset() { mNotified = false; }
bool mNotified = false;
};
TEST(JointFabricDatastoreTest, AddPendingNodeNotifiesListener)
{
JointFabricDatastore store;
DummyListener listener;
store.AddListener(listener);
// Add a pending node — should notify the listener via MarkNodeListChange
CHIP_ERROR err = store.AddPendingNode(123, CharSpan::fromCharString("controller-a"));
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_TRUE(listener.mNotified);
}
TEST(JointFabricDatastoreTest, RemoveListenerPreventsNotification)
{
JointFabricDatastore store;
DummyListener listener;
store.AddListener(listener);
store.RemoveListener(listener);
listener.Reset();
CHIP_ERROR err = store.AddPendingNode(456, CharSpan::fromCharString("controller-b"));
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_FALSE(listener.mNotified);
}
class DummyDelegate : public JointFabricDatastore::Delegate
{
public:
CHIP_ERROR
SyncNode(NodeId nodeId,
const Clusters::JointFabricDatastore::Structs::DatastoreEndpointGroupIDEntryStruct::Type & endpointGroupIDEntry,
std::function<void()> onSuccess) override
{
onSuccess();
return CHIP_NO_ERROR;
}
CHIP_ERROR
SyncNode(NodeId nodeId, const Clusters::JointFabricDatastore::Structs::DatastoreNodeKeySetEntryStruct::Type & nodeKeySetEntry,
std::function<void()> onSuccess) override
{
onSuccess();
return CHIP_NO_ERROR;
}
CHIP_ERROR
SyncNode(NodeId nodeId, const Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type & bindingEntry,
std::function<void()> onSuccess) override
{
onSuccess();
return CHIP_NO_ERROR;
}
CHIP_ERROR
SyncNode(NodeId nodeId,
std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type> & bindingEntries,
std::function<void()> onSuccess) override
{
onSuccess();
return CHIP_NO_ERROR;
}
CHIP_ERROR SyncNode(NodeId nodeId, const Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type & aclEntry,
std::function<void()> onSuccess) override
{
onSuccess();
return CHIP_NO_ERROR;
}
CHIP_ERROR
SyncNode(NodeId nodeId,
const std::vector<app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type> & aclEntries,
std::function<void()> onSuccess) override
{
onSuccess();
return CHIP_NO_ERROR;
}
CHIP_ERROR SyncNode(NodeId nodeId,
const Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & groupKeySet,
std::function<void()> onSuccess) override
{
onSuccess();
return CHIP_NO_ERROR;
}
CHIP_ERROR FetchEndpointList(
NodeId nodeId,
std::function<void(CHIP_ERROR,
const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointEntryStruct::Type> &)>
onSuccess) override
{
onSuccess(CHIP_NO_ERROR, {});
return CHIP_NO_ERROR;
}
CHIP_ERROR FetchEndpointGroupList(
NodeId nodeId, EndpointId endpointId,
std::function<void(
CHIP_ERROR, const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreGroupInformationEntryStruct::Type> &)>
onSuccess) override
{
onSuccess(CHIP_NO_ERROR, {});
return CHIP_NO_ERROR;
}
CHIP_ERROR FetchEndpointBindingList(
NodeId nodeId, EndpointId endpointId,
std::function<void(CHIP_ERROR,
const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type> &)>
onSuccess) override
{
onSuccess(CHIP_NO_ERROR, {});
return CHIP_NO_ERROR;
}
CHIP_ERROR FetchGroupKeySetList(
NodeId nodeId,
std::function<void(CHIP_ERROR,
const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type> &)>
onSuccess) override
{
onSuccess(CHIP_NO_ERROR, {});
return CHIP_NO_ERROR;
}
CHIP_ERROR FetchACLList(
NodeId nodeId,
std::function<void(CHIP_ERROR, const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type> &)>
onSuccess) override
{
onSuccess(CHIP_NO_ERROR, {});
return CHIP_NO_ERROR;
}
};
TEST(JointFabricDatastoreTest, RefreshNodeUpdatesExistingNode)
{
JointFabricDatastore store;
DummyListener listener;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
store.AddListener(listener);
// Add initial pending node
err = store.AddPendingNode(123, CharSpan::fromCharString("controller-a"));
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_TRUE(listener.mNotified);
listener.Reset();
// Refresh the node
err = store.RefreshNode(123);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_TRUE(listener.mNotified);
}
TEST(JointFabricDatastoreTest, RefreshNonExistentNodeFails)
{
JointFabricDatastore store;
DummyListener listener;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
store.AddListener(listener);
// Attempt to refresh a node that doesn't exist
err = store.RefreshNode(999);
EXPECT_NE(err, CHIP_NO_ERROR);
EXPECT_FALSE(listener.mNotified);
}
TEST(JointFabricDatastoreTest, UpdateNodeChangesNameAndNotifies)
{
JointFabricDatastore store;
DummyListener listener;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
store.AddListener(listener);
err = store.AddPendingNode(123, CharSpan::fromCharString("original-name"));
EXPECT_EQ(err, CHIP_NO_ERROR);
listener.Reset();
err = store.UpdateNode(123, CharSpan::fromCharString("updated-name"));
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_TRUE(listener.mNotified);
}
TEST(JointFabricDatastoreTest, RemoveNodeDeletesAndNotifies)
{
JointFabricDatastore store;
DummyListener listener;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
store.AddListener(listener);
err = store.AddPendingNode(123, CharSpan::fromCharString("test-node"));
EXPECT_EQ(err, CHIP_NO_ERROR);
listener.Reset();
err = store.RemoveNode(123);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_TRUE(listener.mNotified);
}
TEST(JointFabricDatastoreTest, AddGroupKeySetEntry)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type keySet;
keySet.groupKeySetID = 1;
err = store.AddGroupKeySetEntry(keySet);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, RemoveGroupKeySetEntry)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type keySet;
keySet.groupKeySetID = 1;
err = store.AddGroupKeySetEntry(keySet);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.RemoveGroupKeySetEntry(1);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, UpdateGroupKeySetEntry)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
GroupId groupId = 1;
uint16_t groupKeySetId = 1;
NodeId nodeId = 123;
err = store.TestAddNodeKeySetEntry(groupId, groupKeySetId, nodeId);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type keySet;
keySet.groupKeySetID = 1;
err = store.AddGroupKeySetEntry(keySet);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.UpdateGroupKeySetEntry(keySet);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, AddAndRemoveAdmin)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Structs::DatastoreAdministratorInformationEntryStruct::Type admin;
admin.nodeID = 100;
err = store.AddAdmin(admin);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.RemoveAdmin(100);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, UpdateAdmin)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Structs::DatastoreAdministratorInformationEntryStruct::Type admin;
admin.nodeID = 100;
err = store.AddAdmin(admin);
EXPECT_EQ(err, CHIP_NO_ERROR);
uint8_t icacData[] = { 0x01, 0x02 };
err = store.UpdateAdmin(100, CharSpan::fromCharString("new-name"), ByteSpan(icacData));
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, RemoveGroupIDFromEndpoint)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
EndpointId endpointId = 1;
GroupId groupId = 10;
uint16_t groupKeySetId = 1;
NodeId nodeId = 123;
err = store.TestAddNodeKeySetEntry(groupId, groupKeySetId, nodeId);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.TestAddEndpointEntry(endpointId, nodeId, CharSpan::fromCharString("test-endpoint"));
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Commands::AddGroup::DecodableType addGroupData;
addGroupData.groupID = groupId;
addGroupData.friendlyName = CharSpan::fromCharString("test-group");
addGroupData.groupKeySetID = groupKeySetId;
err = store.AddGroup(addGroupData);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.AddPendingNode(nodeId, CharSpan::fromCharString("test"));
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.AddGroupIDToEndpointForNode(nodeId, endpointId, groupId);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.RemoveGroupIDFromEndpointForNode(nodeId, endpointId, groupId);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, AddGroup)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Commands::AddGroup::DecodableType commandData;
// Note: You'll need to populate commandData fields based on the actual struct definition
err = store.AddGroup(commandData);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, UpdateGroup)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Commands::AddGroup::DecodableType addData;
err = store.AddGroup(addData);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Commands::UpdateGroup::DecodableType updateData;
err = store.UpdateGroup(updateData);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, RemoveGroup)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Commands::AddGroup::DecodableType addData;
err = store.AddGroup(addData);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Commands::RemoveGroup::DecodableType removeData;
err = store.RemoveGroup(removeData);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, UpdateEndpointForNode)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
NodeId nodeId = 123;
EndpointId endpointId = 1;
err = store.AddPendingNode(nodeId, CharSpan::fromCharString("test-node"));
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.TestAddEndpointEntry(endpointId, nodeId, CharSpan::fromCharString("initial-endpoint"));
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.UpdateEndpointForNode(nodeId, endpointId, CharSpan::fromCharString("endpoint-name"));
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, UpdateEndpointForNonExistentNodeFails)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.UpdateEndpointForNode(999, 1, CharSpan::fromCharString("endpoint-name"));
EXPECT_NE(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, AddBindingToEndpointForNode)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
NodeId nodeId = 123;
EndpointId endpointId = 1;
err = store.AddPendingNode(nodeId, CharSpan::fromCharString("test-node"));
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.TestAddEndpointEntry(endpointId, nodeId, CharSpan::fromCharString("test-endpoint"));
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Structs::DatastoreBindingTargetStruct::Type binding;
err = store.AddBindingToEndpointForNode(nodeId, endpointId, binding);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, RemoveBindingFromEndpointForNode)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
NodeId nodeId = 123;
EndpointId endpointId = 1;
uint16_t listId = 0;
err = store.AddPendingNode(nodeId, CharSpan::fromCharString("test-node"));
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.TestAddEndpointEntry(endpointId, nodeId, CharSpan::fromCharString("test-endpoint"));
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Structs::DatastoreBindingTargetStruct::Type binding;
err = store.AddBindingToEndpointForNode(nodeId, endpointId, binding);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.RemoveBindingFromEndpointForNode(listId, nodeId, endpointId);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, RemoveBindingFromNonExistentNodeFails)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.RemoveBindingFromEndpointForNode(0, 999, 1);
EXPECT_NE(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, AddACLToNode)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.AddPendingNode(123, CharSpan::fromCharString("test-node"));
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Structs::DatastoreAccessControlEntryStruct::DecodableType aclEntry;
err = store.AddACLToNode(123, aclEntry);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, AddACLToNonExistentNodeFails)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Structs::DatastoreAccessControlEntryStruct::DecodableType aclEntry;
err = store.AddACLToNode(999, aclEntry);
EXPECT_NE(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, RemoveACLFromNode)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.AddPendingNode(123, CharSpan::fromCharString("test-node"));
EXPECT_EQ(err, CHIP_NO_ERROR);
Clusters::JointFabricDatastore::Structs::DatastoreAccessControlEntryStruct::DecodableType aclEntry;
err = store.AddACLToNode(123, aclEntry);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.RemoveACLFromNode(0, 123);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(JointFabricDatastoreTest, RemoveACLFromNonExistentNodeFails)
{
JointFabricDatastore store;
DummyDelegate delegate;
CHIP_ERROR err = store.SetDelegate(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = store.RemoveACLFromNode(0, 999);
EXPECT_NE(err, CHIP_NO_ERROR);
}
} // namespace