From 6f1897bbae00ba559c07a671d3bcc0c296a0cee8 Mon Sep 17 00:00:00 2001 From: ricardo-casallas <77841255+ricardo-casallas@users.noreply.github.com> Date: Tue, 12 Oct 2021 07:38:30 -0400 Subject: [PATCH] Group Data Provider: RemoveFabric method added. (#10119) * Group Data Provider: RemoveFabric method added. * Group Data Provider: Code review corrections. --- src/credentials/GroupDataProvider.h | 33 ++- .../examples/GroupDataProviderExample.cpp | 88 +++++- .../tests/TestGroupDataProvider.cpp | 257 +++++++++++++++++- 3 files changed, 343 insertions(+), 35 deletions(-) diff --git a/src/credentials/GroupDataProvider.h b/src/credentials/GroupDataProvider.h index a1accc64adfa0d..89363c57074e45 100644 --- a/src/credentials/GroupDataProvider.h +++ b/src/credentials/GroupDataProvider.h @@ -176,29 +176,32 @@ class GroupDataProvider virtual void Finish() = 0; // Endpoints - virtual bool GroupMappingExists(chip::FabricIndex fabric_index, GroupMapping & mapping) = 0; - virtual CHIP_ERROR AddGroupMapping(chip::FabricIndex fabric_index, GroupMapping & mapping, const char * name) = 0; - virtual CHIP_ERROR RemoveGroupMapping(chip::FabricIndex fabric_index, GroupMapping & mapping) = 0; - virtual CHIP_ERROR RemoveAllGroupMappings(chip::FabricIndex fabric_index) = 0; - virtual GroupMappingIterator * IterateGroupMappings(chip::FabricIndex fabric_index, EndpointId endpoint) = 0; + virtual bool GroupMappingExists(chip::FabricIndex fabric_index, const GroupMapping & mapping) = 0; + virtual CHIP_ERROR AddGroupMapping(chip::FabricIndex fabric_index, const GroupMapping & mapping, const char * name) = 0; + virtual CHIP_ERROR RemoveGroupMapping(chip::FabricIndex fabric_index, const GroupMapping & mapping) = 0; + virtual CHIP_ERROR RemoveAllGroupMappings(chip::FabricIndex fabric_index) = 0; + virtual GroupMappingIterator * IterateGroupMappings(chip::FabricIndex fabric_index, EndpointId endpoint) = 0; // States - virtual CHIP_ERROR SetGroupState(uint16_t state_index, const GroupState & state) = 0; - virtual CHIP_ERROR GetGroupState(uint16_t state_index, GroupState & state) = 0; - virtual CHIP_ERROR RemoveGroupState(uint16_t state_index) = 0; - virtual GroupStateIterator * IterateGroupStates() = 0; - virtual GroupStateIterator * IterateGroupStates(chip::FabricIndex fabric_index) = 0; + virtual CHIP_ERROR SetGroupState(size_t state_index, const GroupState & state) = 0; + virtual CHIP_ERROR GetGroupState(size_t state_index, GroupState & state) = 0; + virtual CHIP_ERROR RemoveGroupState(size_t state_index) = 0; + virtual GroupStateIterator * IterateGroupStates() = 0; + virtual GroupStateIterator * IterateGroupStates(chip::FabricIndex fabric_index) = 0; // Keys - virtual CHIP_ERROR SetKeySet(chip::FabricIndex fabric_index, uint16_t key_set_index, KeySet & keys) = 0; - virtual CHIP_ERROR GetKeySet(chip::FabricIndex fabric_index, uint16_t key_set_index, KeySet & keys) = 0; - virtual CHIP_ERROR RemoveKeySet(chip::FabricIndex fabric_index, uint16_t key_set_index) = 0; - virtual KeySetIterator * IterateKeySets(chip::FabricIndex fabric_index) = 0; + virtual CHIP_ERROR SetKeySet(chip::FabricIndex fabric_index, uint16_t key_set_index, const KeySet & keys) = 0; + virtual CHIP_ERROR GetKeySet(chip::FabricIndex fabric_index, uint16_t key_set_index, KeySet & keys) = 0; + virtual CHIP_ERROR RemoveKeySet(chip::FabricIndex fabric_index, uint16_t key_set_index) = 0; + virtual KeySetIterator * IterateKeySets(chip::FabricIndex fabric_index) = 0; + // Fabrics + virtual CHIP_ERROR RemoveFabric(chip::FabricIndex fabric_index) = 0; + + // Listener void SetListener(GroupListener * listener) { mListener = listener; }; void RemoveListener() { mListener = nullptr; }; - // TODO: handle fabric deletion (reindex fabric entries!) protected: GroupListener * mListener = nullptr; }; diff --git a/src/credentials/examples/GroupDataProviderExample.cpp b/src/credentials/examples/GroupDataProviderExample.cpp index d3882a5037b522..0706c52fc55c81 100644 --- a/src/credentials/examples/GroupDataProviderExample.cpp +++ b/src/credentials/examples/GroupDataProviderExample.cpp @@ -37,12 +37,24 @@ class StaticGroupsProvider : public GroupDataProvider struct EndpointEntry : public GroupMapping { bool in_use = false; + void Clear() + { + endpoint = 0; + group = 0; + in_use = false; + } }; struct KeysEntry : public KeySet { bool in_use = false; - uint16_t key_set_index; + void Clear() + { + memset(epoch_keys, 0x00, sizeof(epoch_keys)); + key_set_index = 0; + num_keys_used = 0; + in_use = false; + } }; struct Fabric @@ -57,6 +69,21 @@ class StaticGroupsProvider : public GroupDataProvider size_t states_count; // Group key sets for fabric KeysEntry keys[kKeyEntriesMax]; + + void Clear() + { + in_use = false; + fabric_index = 0; + states_count = 0; + for (size_t i = 0; i < kEndpointEntriesMax; i++) + { + endpoints[i].Clear(); + } + for (size_t i = 0; i < kKeyEntriesMax; i++) + { + keys[i].Clear(); + } + } }; struct StateEntry : public GroupState @@ -65,11 +92,11 @@ class StaticGroupsProvider : public GroupDataProvider bool in_use = false; void Clear() { + in_use = false; fabric_index = 0; group = 0; key_set_index = 0; fabric = nullptr; - in_use = false; } }; @@ -292,7 +319,13 @@ class StaticGroupsProvider : public GroupDataProvider public: CHIP_ERROR Init() override { + // Clear-out all fabric entries + for (size_t i = 0; i < kNumFabrics; ++i) + { + mFabrics[i].Clear(); + } // Clear-out all entries of index mapping. + mGroupStatesCount = 0; for (size_t i = 0; i < kMaxNumGroupStates; ++i) { mGroupStates[i].Clear(); @@ -304,12 +337,12 @@ class StaticGroupsProvider : public GroupDataProvider void Finish() override { mInitialized = false; } // Endpoints - bool GroupMappingExists(chip::FabricIndex fabric_index, GroupMapping & mapping) override + bool GroupMappingExists(chip::FabricIndex fabric_index, const GroupMapping & mapping) override { VerifyOrReturnError(mInitialized, false); Fabric * fabric = GetExistingFabric(fabric_index); - VerifyOrReturnError(fabric, false); + VerifyOrReturnError(nullptr != fabric, false); for (uint16_t i = 0; fabric && i < kEndpointEntriesMax; ++i) { @@ -322,14 +355,14 @@ class StaticGroupsProvider : public GroupDataProvider return false; } - CHIP_ERROR AddGroupMapping(chip::FabricIndex fabric_index, GroupMapping & mapping, const char * name) override + CHIP_ERROR AddGroupMapping(chip::FabricIndex fabric_index, const GroupMapping & mapping, const char * name) override { VerifyOrReturnError(mInitialized, CHIP_ERROR_INTERNAL); (void) name; // Unused! Fabric * fabric = GetExistingFabricOrAllocateNew(fabric_index); - VerifyOrReturnError(fabric, CHIP_ERROR_NO_MEMORY); + VerifyOrReturnError(nullptr != fabric, CHIP_ERROR_NO_MEMORY); // Search for existing mapping for (uint16_t i = 0; i < kEndpointEntriesMax; ++i) @@ -356,12 +389,12 @@ class StaticGroupsProvider : public GroupDataProvider return CHIP_ERROR_NO_MEMORY; } - CHIP_ERROR RemoveGroupMapping(chip::FabricIndex fabric_index, GroupMapping & mapping) override + CHIP_ERROR RemoveGroupMapping(chip::FabricIndex fabric_index, const GroupMapping & mapping) override { VerifyOrReturnError(mInitialized, CHIP_ERROR_INTERNAL); Fabric * fabric = GetExistingFabric(fabric_index); - VerifyOrReturnError(fabric, CHIP_ERROR_INVALID_FABRIC_ID); + VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_FABRIC_ID); // Search for existing mapping for (uint16_t i = 0; fabric && i < kEndpointEntriesMax; ++i) @@ -383,7 +416,7 @@ class StaticGroupsProvider : public GroupDataProvider VerifyOrReturnError(mInitialized, CHIP_ERROR_INTERNAL); Fabric * fabric = GetExistingFabric(fabric_index); - VerifyOrReturnError(fabric, CHIP_ERROR_INVALID_FABRIC_ID); + VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_FABRIC_ID); // Remove all mappings from fabric for (uint16_t i = 0; fabric && i < kEndpointEntriesMax; ++i) @@ -403,7 +436,7 @@ class StaticGroupsProvider : public GroupDataProvider // States - CHIP_ERROR SetGroupState(uint16_t state_index, const GroupState & state) override + CHIP_ERROR SetGroupState(size_t state_index, const GroupState & state) override { VerifyOrReturnError(mInitialized, CHIP_ERROR_INTERNAL); @@ -411,7 +444,7 @@ class StaticGroupsProvider : public GroupDataProvider VerifyOrReturnError(static_cast(state_index) <= mGroupStatesCount, CHIP_ERROR_INVALID_ARGUMENT); Fabric * fabric = GetExistingFabricOrAllocateNew(state.fabric_index); - VerifyOrReturnError(fabric, CHIP_ERROR_NO_MEMORY); + VerifyOrReturnError(nullptr != fabric, CHIP_ERROR_NO_MEMORY); StateEntry & entry = mGroupStates[state_index]; bool appending = static_cast(state_index) == mGroupStatesCount; @@ -444,7 +477,7 @@ class StaticGroupsProvider : public GroupDataProvider return CHIP_NO_ERROR; } - CHIP_ERROR GetGroupState(uint16_t state_index, GroupState & state) override + CHIP_ERROR GetGroupState(size_t state_index, GroupState & state) override { VerifyOrReturnError(mInitialized, CHIP_ERROR_INTERNAL); VerifyOrReturnError(static_cast(state_index) < mGroupStatesCount, CHIP_ERROR_KEY_NOT_FOUND); @@ -460,7 +493,7 @@ class StaticGroupsProvider : public GroupDataProvider return CHIP_NO_ERROR; } - CHIP_ERROR RemoveGroupState(uint16_t state_index) override + CHIP_ERROR RemoveGroupState(size_t state_index) override { VerifyOrReturnError(mInitialized, CHIP_ERROR_INTERNAL); VerifyOrReturnError(static_cast(state_index) < mGroupStatesCount, CHIP_ERROR_KEY_NOT_FOUND); @@ -516,13 +549,15 @@ class StaticGroupsProvider : public GroupDataProvider void Release(AllGroupStateIterator * iterator) { mAllStateIterators.ReleaseObject(iterator); } // Keys - CHIP_ERROR SetKeySet(chip::FabricIndex fabric_index, uint16_t key_set_index, KeySet & keys) override + CHIP_ERROR SetKeySet(chip::FabricIndex fabric_index, uint16_t key_set_index, const KeySet & keys) override { VerifyOrReturnError(mInitialized, CHIP_ERROR_INTERNAL); - Fabric * fabric = GetExistingFabric(fabric_index); + Fabric * fabric = GetExistingFabricOrAllocateNew(fabric_index); KeysEntry * entry = nullptr; + VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_FABRIC_ID); + // Search for existing, or unused entry for (uint16_t i = 0; fabric && i < kKeyEntriesMax; ++i) { @@ -557,6 +592,8 @@ class StaticGroupsProvider : public GroupDataProvider { VerifyOrReturnError(mInitialized, CHIP_ERROR_INTERNAL); Fabric * fabric = GetExistingFabric(fabric_index); + VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_FABRIC_ID); + // Search for existing keys for (uint16_t i = 0; fabric && i < kKeyEntriesMax; ++i) { @@ -577,6 +614,8 @@ class StaticGroupsProvider : public GroupDataProvider { VerifyOrReturnError(mInitialized, CHIP_ERROR_INTERNAL); Fabric * fabric = GetExistingFabric(fabric_index); + VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_FABRIC_ID); + // Search for existing keys for (uint16_t i = 0; fabric && i < kKeyEntriesMax; ++i) { @@ -599,6 +638,25 @@ class StaticGroupsProvider : public GroupDataProvider void Release(KeysIterator * iterator) { return mKeyIterators.ReleaseObject(iterator); } + CHIP_ERROR RemoveFabric(chip::FabricIndex fabric_index) override + { + Fabric * fabric = GetExistingFabric(fabric_index); + VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_FABRIC_ID); + // Remove group states + for (size_t i = 0; i < kMaxNumGroupStates; ++i) + { + if (mGroupStates[i].fabric == fabric) + { + RemoveGroupState(i); + } + } + // Release other resources associated with the fabric entry, such as mapped + // endpoints (i.e. through the Groups cluster) and group key sets, both of which + // live in the `Fabric` data structure of this implementation. + fabric->Clear(); + return CHIP_NO_ERROR; + } + private: bool mInitialized = false; Fabric mFabrics[kNumFabrics]; diff --git a/src/credentials/tests/TestGroupDataProvider.cpp b/src/credentials/tests/TestGroupDataProvider.cpp index 42198e73f6faa9..3f9c0832eea801 100644 --- a/src/credentials/tests/TestGroupDataProvider.cpp +++ b/src/credentials/tests/TestGroupDataProvider.cpp @@ -272,8 +272,6 @@ void TestStates(nlTestSuite * apSuite, void * apContext) GroupDataProvider::GroupState state1b = { .fabric_index = 0, .group = 10, .key_set_index = 12 }; GroupDataProvider::GroupState state3b = { .fabric_index = 0, .group = 10, .key_set_index = 13 }; - state3b.group = 10; - state3b.key_set_index = 13; GroupDataProvider::GroupState state4a = { .fabric_index = 1, .group = 5, .key_set_index = 3 }; GroupDataProvider::GroupState state4b = { .fabric_index = 0, .group = 10, .key_set_index = 14 }; @@ -499,7 +497,6 @@ void TestKeys(nlTestSuite * apSuite, void * apContext) NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); auto * it = groups->IterateKeySets(kFabricIndex); - // err = groups->GetStateCount(fabric, count); NL_TEST_ASSERT(apSuite, it != nullptr); NL_TEST_ASSERT(apSuite, it->Count() == 2); @@ -507,13 +504,13 @@ void TestKeys(nlTestSuite * apSuite, void * apContext) NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); NL_TEST_ASSERT(apSuite, keys0a.policy == keys0b.policy); NL_TEST_ASSERT(apSuite, keys0a.num_keys_used == keys0b.num_keys_used); - NL_TEST_ASSERT(apSuite, !memcmp(keys0a.epoch_keys, keys0b.epoch_keys, sizeof(keys0a.epoch_keys[0]) * keys0a.num_keys_used)); + NL_TEST_ASSERT(apSuite, 0 == memcmp(keys0a.epoch_keys, keys0b.epoch_keys, sizeof(keys0a.epoch_keys[0]) * keys0a.num_keys_used)); err = groups->GetKeySet(kFabricIndex, 1, keys1b); NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); NL_TEST_ASSERT(apSuite, keys1a.policy == keys1b.policy); NL_TEST_ASSERT(apSuite, keys1a.num_keys_used == keys1b.num_keys_used); - NL_TEST_ASSERT(apSuite, !memcmp(keys1a.epoch_keys, keys1b.epoch_keys, sizeof(keys1a.epoch_keys[0]) * keys1a.num_keys_used)); + NL_TEST_ASSERT(apSuite, 0 == memcmp(keys1a.epoch_keys, keys1b.epoch_keys, sizeof(keys1a.epoch_keys[0]) * keys1a.num_keys_used)); err = groups->GetKeySet(kFabricIndex, 3, keys3); NL_TEST_ASSERT(apSuite, CHIP_ERROR_KEY_NOT_FOUND == err); @@ -582,6 +579,255 @@ void TestKeysIterator(nlTestSuite * apSuite, void * apContext) groups->Finish(); } +void TestPerFabricData(nlTestSuite * apSuite, void * apContext) +{ + GroupDataProvider * groups = GetGroupDataProvider(); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == groups->Init()); + + const chip::FabricIndex kFabricIndex1 = 33; + const chip::FabricIndex kFabricIndex2 = 77; + const chip::GroupId kGroupId1 = 111; + const chip::GroupId kGroupId2 = 222; + const chip::GroupId kGroupId3 = 333; + + const GroupDataProvider::GroupMapping group1a = { .endpoint = 101, .group = kGroupId1 }; + const GroupDataProvider::GroupMapping group1b = { .endpoint = 101, .group = kGroupId2 }; + const GroupDataProvider::GroupMapping group1c = { .endpoint = 101, .group = kGroupId3 }; + CHIP_ERROR err = CHIP_NO_ERROR; + bool exists = false; + + NL_TEST_ASSERT(apSuite, groups); + + // Mappings + + err = groups->AddGroupMapping(kFabricIndex1, group1a, "Group 1.1"); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->AddGroupMapping(kFabricIndex1, group1b, "Group 1.2"); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->AddGroupMapping(kFabricIndex1, group1c, "Group 1.3"); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->AddGroupMapping(kFabricIndex2, group1a, "Group 1.1"); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->AddGroupMapping(kFabricIndex2, group1c, "Group 1.3"); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + exists = groups->GroupMappingExists(kFabricIndex1, group1a); + NL_TEST_ASSERT(apSuite, exists); + + exists = groups->GroupMappingExists(kFabricIndex1, group1b); + NL_TEST_ASSERT(apSuite, exists); + + exists = groups->GroupMappingExists(kFabricIndex1, group1c); + NL_TEST_ASSERT(apSuite, exists); + + exists = groups->GroupMappingExists(kFabricIndex2, group1a); + NL_TEST_ASSERT(apSuite, exists); + + exists = groups->GroupMappingExists(kFabricIndex2, group1b); + NL_TEST_ASSERT(apSuite, !exists); + + exists = groups->GroupMappingExists(kFabricIndex2, group1c); + NL_TEST_ASSERT(apSuite, exists); + + // States + + const GroupDataProvider::GroupState state0a = { .fabric_index = kFabricIndex1, .group = kGroupId1, .key_set_index = 101 }; + GroupDataProvider::GroupState state0b = { .fabric_index = 0, .group = 0, .key_set_index = 0 }; + + const GroupDataProvider::GroupState state1a = { .fabric_index = kFabricIndex2, .group = kGroupId1, .key_set_index = 102 }; + GroupDataProvider::GroupState state1b = { .fabric_index = 0, .group = 0, .key_set_index = 0 }; + + const GroupDataProvider::GroupState state2a = { .fabric_index = kFabricIndex2, .group = kGroupId2, .key_set_index = 101 }; + GroupDataProvider::GroupState state2b = { .fabric_index = 0, .group = 0, .key_set_index = 0 }; + + const GroupDataProvider::GroupState state3a = { .fabric_index = kFabricIndex1, .group = kGroupId2, .key_set_index = 102 }; + GroupDataProvider::GroupState state4b = { .fabric_index = 0, .group = 0, .key_set_index = 0 }; + + err = groups->SetGroupState(0, state0a); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->SetGroupState(1, state1a); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->SetGroupState(2, state2a); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->SetGroupState(3, state3a); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->GetGroupState(0, state0b); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, state0a.fabric_index == state0b.fabric_index); + NL_TEST_ASSERT(apSuite, state0a.group == state0b.group); + NL_TEST_ASSERT(apSuite, state0a.key_set_index == state0b.key_set_index); + + err = groups->GetGroupState(1, state1b); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, state1a.fabric_index == state1b.fabric_index); + NL_TEST_ASSERT(apSuite, state1a.group == state1b.group); + NL_TEST_ASSERT(apSuite, state1a.key_set_index == state1b.key_set_index); + + err = groups->GetGroupState(2, state2b); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, state2a.fabric_index == state2b.fabric_index); + NL_TEST_ASSERT(apSuite, state2a.group == state2b.group); + NL_TEST_ASSERT(apSuite, state2a.key_set_index == state2b.key_set_index); + + err = groups->GetGroupState(4, state4b); + NL_TEST_ASSERT(apSuite, CHIP_ERROR_KEY_NOT_FOUND == err); + + // Keys + + KeySet keys0a = { .policy = KeySet::SecurityPolicy::kStandard, .num_keys_used = 3 }; + KeySet keys1a = { .policy = KeySet::SecurityPolicy::kLowLatency, .num_keys_used = 3 }; + KeySet keys_out = { .policy = KeySet::SecurityPolicy::kStandard, .num_keys_used = 0 }; + + NL_TEST_ASSERT(apSuite, groups); + + memcpy(keys0a.epoch_keys, epoch_keys1, sizeof(epoch_keys1)); + memcpy(keys1a.epoch_keys, epoch_keys1, sizeof(epoch_keys1)); + memcpy(keys_out.epoch_keys, epoch_keys0, sizeof(epoch_keys0)); + + err = groups->SetKeySet(kFabricIndex2, 101, keys0a); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->SetKeySet(kFabricIndex1, 202, keys0a); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->SetKeySet(kFabricIndex2, 303, keys1a); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->SetKeySet(kFabricIndex1, 404, keys1a); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->SetKeySet(kFabricIndex2, 505, keys0a); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->SetKeySet(kFabricIndex1, 606, keys0a); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + err = groups->GetKeySet(kFabricIndex2, 101, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, keys0a.policy == keys_out.policy); + NL_TEST_ASSERT(apSuite, keys0a.num_keys_used == keys_out.num_keys_used); + NL_TEST_ASSERT(apSuite, + 0 == memcmp(keys0a.epoch_keys, keys_out.epoch_keys, sizeof(keys0a.epoch_keys[0]) * keys0a.num_keys_used)); + + err = groups->GetKeySet(kFabricIndex2, 303, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, keys1a.policy == keys_out.policy); + NL_TEST_ASSERT(apSuite, keys1a.num_keys_used == keys_out.num_keys_used); + NL_TEST_ASSERT(apSuite, + 0 == memcmp(keys1a.epoch_keys, keys_out.epoch_keys, sizeof(keys1a.epoch_keys[0]) * keys1a.num_keys_used)); + + err = groups->GetKeySet(kFabricIndex2, 505, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, keys0a.policy == keys_out.policy); + NL_TEST_ASSERT(apSuite, keys0a.num_keys_used == keys_out.num_keys_used); + NL_TEST_ASSERT(apSuite, + 0 == memcmp(keys0a.epoch_keys, keys_out.epoch_keys, sizeof(keys0a.epoch_keys[0]) * keys0a.num_keys_used)); + + err = groups->GetKeySet(kFabricIndex1, 202, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, keys0a.policy == keys_out.policy); + NL_TEST_ASSERT(apSuite, keys0a.num_keys_used == keys_out.num_keys_used); + NL_TEST_ASSERT(apSuite, + 0 == memcmp(keys0a.epoch_keys, keys_out.epoch_keys, sizeof(keys0a.epoch_keys[0]) * keys0a.num_keys_used)); + + err = groups->GetKeySet(kFabricIndex1, 404, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, keys1a.policy == keys_out.policy); + NL_TEST_ASSERT(apSuite, keys1a.num_keys_used == keys_out.num_keys_used); + NL_TEST_ASSERT(apSuite, + 0 == memcmp(keys1a.epoch_keys, keys_out.epoch_keys, sizeof(keys1a.epoch_keys[0]) * keys1a.num_keys_used)); + + err = groups->GetKeySet(kFabricIndex1, 606, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, keys0a.policy == keys_out.policy); + NL_TEST_ASSERT(apSuite, keys0a.num_keys_used == keys_out.num_keys_used); + NL_TEST_ASSERT(apSuite, + 0 == memcmp(keys0a.epoch_keys, keys_out.epoch_keys, sizeof(keys0a.epoch_keys[0]) * keys0a.num_keys_used)); + + // Remove Fabric + err = groups->RemoveFabric(kFabricIndex1); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + + // Mappings + + exists = groups->GroupMappingExists(kFabricIndex1, group1a); + NL_TEST_ASSERT(apSuite, !exists); + + exists = groups->GroupMappingExists(kFabricIndex1, group1b); + NL_TEST_ASSERT(apSuite, !exists); + + exists = groups->GroupMappingExists(kFabricIndex1, group1c); + NL_TEST_ASSERT(apSuite, !exists); + + exists = groups->GroupMappingExists(kFabricIndex2, group1a); + NL_TEST_ASSERT(apSuite, exists); + + exists = groups->GroupMappingExists(kFabricIndex2, group1b); + NL_TEST_ASSERT(apSuite, !exists); + + exists = groups->GroupMappingExists(kFabricIndex2, group1c); + NL_TEST_ASSERT(apSuite, exists); + + // States: Removing the fabric shift the remaining groups states to a lower index + + err = groups->GetGroupState(0, state0b); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, state1a.fabric_index == state0b.fabric_index); + NL_TEST_ASSERT(apSuite, state1a.group == state0b.group); + NL_TEST_ASSERT(apSuite, state1a.key_set_index == state0b.key_set_index); + + err = groups->GetGroupState(1, state1b); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, state2a.fabric_index == state1b.fabric_index); + NL_TEST_ASSERT(apSuite, state2a.group == state1b.group); + NL_TEST_ASSERT(apSuite, state2a.key_set_index == state1b.key_set_index); + + err = groups->GetGroupState(2, state2b); + NL_TEST_ASSERT(apSuite, CHIP_ERROR_KEY_NOT_FOUND == err); + + // Keys + + err = groups->GetKeySet(kFabricIndex2, 101, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, keys0a.policy == keys_out.policy); + NL_TEST_ASSERT(apSuite, keys0a.num_keys_used == keys_out.num_keys_used); + NL_TEST_ASSERT(apSuite, + 0 == memcmp(keys0a.epoch_keys, keys_out.epoch_keys, sizeof(keys0a.epoch_keys[0]) * keys0a.num_keys_used)); + + err = groups->GetKeySet(kFabricIndex2, 303, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, keys1a.policy == keys_out.policy); + NL_TEST_ASSERT(apSuite, keys1a.num_keys_used == keys_out.num_keys_used); + NL_TEST_ASSERT(apSuite, + 0 == memcmp(keys1a.epoch_keys, keys_out.epoch_keys, sizeof(keys1a.epoch_keys[0]) * keys1a.num_keys_used)); + + err = groups->GetKeySet(kFabricIndex2, 505, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == err); + NL_TEST_ASSERT(apSuite, keys0a.policy == keys_out.policy); + NL_TEST_ASSERT(apSuite, keys0a.num_keys_used == keys_out.num_keys_used); + NL_TEST_ASSERT(apSuite, + 0 == memcmp(keys0a.epoch_keys, keys_out.epoch_keys, sizeof(keys0a.epoch_keys[0]) * keys0a.num_keys_used)); + + err = groups->GetKeySet(kFabricIndex1, 202, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_ERROR_INVALID_FABRIC_ID == err); + + err = groups->GetKeySet(kFabricIndex1, 404, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_ERROR_INVALID_FABRIC_ID == err); + + err = groups->GetKeySet(kFabricIndex1, 606, keys_out); + NL_TEST_ASSERT(apSuite, CHIP_ERROR_INVALID_FABRIC_ID == err); + + groups->Finish(); +} + } // namespace TestGroups } // namespace app } // namespace chip @@ -618,6 +864,7 @@ const nlTest sTests[] = { NL_TEST_DEF("TestEndpoints", chip::app::TestGroups::Te NL_TEST_DEF("TestStateIterator", chip::app::TestGroups::TestStateIterator), NL_TEST_DEF("TestKeys", chip::app::TestGroups::TestKeys), NL_TEST_DEF("TestKeysIterator", chip::app::TestGroups::TestKeysIterator), + NL_TEST_DEF("TestPerFabricData", chip::app::TestGroups::TestPerFabricData), NL_TEST_SENTINEL() }; } // namespace