blob: 023970f5f8b31e9e6324f2ae9e6977557229a7cf [file] [log] [blame]
/*
*
* Copyright (c) 2022 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <app/clusters/bindings/PendingNotificationMap.h>
#include <app/clusters/bindings/binding-table.h>
#include <lib/core/StringBuilderAdapters.h>
#include <lib/support/TestPersistentStorageDelegate.h>
#include <lib/support/tests/ExtraPwTestMacros.h>
#include <pw_unit_test/framework.h>
using namespace chip;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::Binding;
namespace {
class TestPendingNotificationMap : public ::testing::Test
{
public:
static void SetUpTestSuite()
{
static chip::TestPersistentStorageDelegate storage;
Binding::Table::GetInstance().SetPersistentStorage(&storage);
}
};
void ClearBindingTable(Binding::Table & table)
{
auto iter = table.begin();
while (iter != table.end())
{
EXPECT_SUCCESS(table.RemoveAt(iter));
}
}
void CreateDefaultFullBindingTable(Binding::Table & table)
{
for (uint8_t i = 0; i < Binding::Table::kMaxBindingEntries; i++)
{
EXPECT_SUCCESS(table.Add(Binding::TableEntry(i / 10, i % 5, 0, 0, std::make_optional<ClusterId>(i))));
}
}
TEST_F(TestPendingNotificationMap, TestEmptyMap)
{
PendingNotificationMap pendingMap;
EXPECT_EQ(pendingMap.begin(), pendingMap.end());
chip::ScopedNodeId peer;
EXPECT_EQ(pendingMap.FindLRUConnectPeer(peer), CHIP_ERROR_NOT_FOUND);
}
TEST_F(TestPendingNotificationMap, TestAddRemove)
{
PendingNotificationMap pendingMap;
ClearBindingTable(Binding::Table::GetInstance());
CreateDefaultFullBindingTable(Binding::Table::GetInstance());
for (uint8_t i = 0; i < Binding::Table::kMaxBindingEntries; i++)
{
EXPECT_EQ(pendingMap.AddPendingNotification(i, nullptr), CHIP_NO_ERROR);
}
// Confirm adding in one more element fails
EXPECT_EQ(pendingMap.AddPendingNotification(Binding::Table::kMaxBindingEntries, nullptr), CHIP_ERROR_NO_MEMORY);
auto iter = pendingMap.begin();
for (uint8_t i = 0; i < Binding::Table::kMaxBindingEntries; i++)
{
PendingNotificationEntry entry = *iter;
EXPECT_EQ(entry.mBindingEntryId, i);
++iter;
}
EXPECT_EQ(iter, pendingMap.end());
pendingMap.RemoveAllEntriesForNode(chip::ScopedNodeId());
size_t pendingMapCount = 0;
for (iter = pendingMap.begin(); iter != pendingMap.end(); ++iter)
{
PendingNotificationEntry entry = *iter;
Binding::TableEntry bindingEntry = Binding::Table::GetInstance().GetAt(entry.mBindingEntryId);
pendingMapCount++;
EXPECT_NE(chip::ScopedNodeId(bindingEntry.nodeId, bindingEntry.fabricIndex), chip::ScopedNodeId());
}
EXPECT_EQ(pendingMapCount, Binding::Table::kMaxBindingEntries - 2);
pendingMap.RemoveAllEntriesForFabric(0);
pendingMapCount = 0;
for (iter = pendingMap.begin(); iter != pendingMap.end(); ++iter)
{
PendingNotificationEntry entry = *iter;
Binding::TableEntry bindingEntry = Binding::Table::GetInstance().GetAt(entry.mBindingEntryId);
pendingMapCount++;
EXPECT_NE(bindingEntry.fabricIndex, 0);
}
EXPECT_EQ(pendingMapCount, Binding::Table::kMaxBindingEntries - 10);
const FabricIndex maxFabricIndex = static_cast<FabricIndex>(Binding::Table::kMaxBindingEntries / 10);
for (FabricIndex index = 1; index <= maxFabricIndex; index++)
{
pendingMap.RemoveAllEntriesForFabric(index);
}
EXPECT_EQ(pendingMap.begin(), pendingMap.end());
}
TEST_F(TestPendingNotificationMap, TestLRUEntry)
{
PendingNotificationMap pendingMap;
ClearBindingTable(Binding::Table::GetInstance());
CreateDefaultFullBindingTable(Binding::Table::GetInstance());
EXPECT_EQ(pendingMap.AddPendingNotification(0, nullptr), CHIP_NO_ERROR);
EXPECT_EQ(pendingMap.AddPendingNotification(1, nullptr), CHIP_NO_ERROR);
EXPECT_EQ(pendingMap.AddPendingNotification(5, nullptr), CHIP_NO_ERROR);
EXPECT_EQ(pendingMap.AddPendingNotification(7, nullptr), CHIP_NO_ERROR);
EXPECT_EQ(pendingMap.AddPendingNotification(11, nullptr), CHIP_NO_ERROR);
chip::ScopedNodeId node;
EXPECT_EQ(pendingMap.FindLRUConnectPeer(node), CHIP_NO_ERROR);
EXPECT_EQ(node.GetFabricIndex(), 0u);
EXPECT_EQ(node.GetNodeId(), 1u);
pendingMap.RemoveEntry(1);
EXPECT_EQ(pendingMap.FindLRUConnectPeer(node), CHIP_NO_ERROR);
EXPECT_EQ(node.GetFabricIndex(), 0u);
EXPECT_EQ(node.GetNodeId(), 0u);
pendingMap.RemoveAllEntriesForFabric(0);
EXPECT_EQ(pendingMap.FindLRUConnectPeer(node), CHIP_NO_ERROR);
EXPECT_EQ(node.GetFabricIndex(), 1u);
EXPECT_EQ(node.GetNodeId(), 1u);
}
} // namespace