blob: 72fe57754e8976f1e32204e94330a4b85af2cdd4 [file] [log] [blame]
/*
*
* Copyright (c) 2020-2021 Project CHIP Authors
* All rights reserved.
*
* 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.
*/
/**
* @file
* This file implements unit tests for the SessionManager implementation.
*/
#include <errno.h>
#include <gtest/gtest.h>
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <lib/support/TestPersistentStorageDelegate.h>
#include <transport/GroupPeerMessageCounter.h>
#include <transport/PeerMessageCounter.h>
namespace {
using namespace chip;
class TestGroupOutgoingCounters : public chip::Transport::GroupOutgoingCounters
{
public:
TestGroupOutgoingCounters(){};
TestGroupOutgoingCounters(chip::PersistentStorageDelegate * storage_delegate) : GroupOutgoingCounters(storage_delegate){};
void SetCounter(bool isControl, uint32_t value)
{
uint32_t temp = 0;
StorageKeyName key = StorageKeyName::Uninitialized();
if (isControl)
{
mGroupControlCounter = value;
key = DefaultStorageKeyAllocator::GroupControlCounter();
}
else
{
mGroupDataCounter = value;
key = DefaultStorageKeyAllocator::GroupDataCounter();
}
if (mStorage == nullptr)
{
return;
}
// Always Update storage for Test purposes
temp = value + GROUP_MSG_COUNTER_MIN_INCREMENT;
mStorage->SyncSetKeyValue(key.KeyName(), &temp, sizeof(uint32_t));
}
};
class TestGroupPeerTable : public chip::Transport::GroupPeerTable
{
public:
TestGroupPeerTable(){};
FabricIndex GetFabricIndexAt(uint8_t index)
{
if (index < CHIP_CONFIG_MAX_FABRICS)
{
return mGroupFabrics[index].mFabricIndex;
}
return kUndefinedFabricIndex;
}
NodeId GetNodeIdAt(uint8_t fabricIndex, uint8_t index, bool isControl)
{
if (fabricIndex < CHIP_CONFIG_MAX_FABRICS)
{
if (isControl && index < CHIP_CONFIG_MAX_GROUP_CONTROL_PEERS)
{
return mGroupFabrics[fabricIndex].mControlGroupSenders[index].mNodeId;
}
if (!isControl && index < CHIP_CONFIG_MAX_GROUP_DATA_PEERS)
{
return mGroupFabrics[fabricIndex].mDataGroupSenders[index].mNodeId;
}
}
return kUndefinedNodeId;
}
};
TEST(TestGroupMessageCounter, AddPeerTest)
{
NodeId peerNodeId = 1234;
FabricIndex fabricIndex = 1;
int i = 0;
CHIP_ERROR err = CHIP_NO_ERROR;
chip::Transport::PeerMessageCounter * counter = nullptr;
chip::Transport::GroupPeerTable mGroupPeerMsgCounter;
do
{
err = mGroupPeerMsgCounter.FindOrAddPeer(fabricIndex, peerNodeId++, false, counter);
i++;
} while (err != CHIP_ERROR_TOO_MANY_PEER_NODES);
EXPECT_EQ(i, CHIP_CONFIG_MAX_GROUP_DATA_PEERS + 1);
i = 1;
do
{
err = mGroupPeerMsgCounter.FindOrAddPeer(++fabricIndex, peerNodeId, false, counter);
i++;
} while (err != CHIP_ERROR_TOO_MANY_PEER_NODES);
EXPECT_EQ(i, CHIP_CONFIG_MAX_FABRICS + 1);
}
TEST(TestGroupMessageCounter, RemovePeerTest)
{
NodeId peerNodeId = 1234;
FabricIndex fabricIndex = 1;
CHIP_ERROR err = CHIP_NO_ERROR;
chip::Transport::PeerMessageCounter * counter = nullptr;
TestGroupPeerTable mGroupPeerMsgCounter;
// Fill table up (max fabric and mac peer)
for (uint32_t it = 0; it < CHIP_CONFIG_MAX_FABRICS; it++)
{
for (uint32_t peerId = 0; peerId < CHIP_CONFIG_MAX_GROUP_CONTROL_PEERS; peerId++)
{
err = mGroupPeerMsgCounter.FindOrAddPeer(fabricIndex, peerNodeId++, true, counter);
}
fabricIndex++;
}
// Verify that table is indeed full (for control Peer)
err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter);
EXPECT_EQ(err, CHIP_ERROR_TOO_MANY_PEER_NODES);
// Clear all Peer
fabricIndex = 1;
peerNodeId = 1234;
for (uint32_t it = 0; it < CHIP_CONFIG_MAX_FABRICS; it++)
{
for (uint32_t peerId = 0; peerId < CHIP_CONFIG_MAX_GROUP_CONTROL_PEERS; peerId++)
{
err = mGroupPeerMsgCounter.RemovePeer(fabricIndex, peerNodeId++, true);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
fabricIndex++;
}
// Try re-adding the previous peer without any error
err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = mGroupPeerMsgCounter.FindOrAddPeer(104, 99, true, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = mGroupPeerMsgCounter.FindOrAddPeer(105, 99, true, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = mGroupPeerMsgCounter.FindOrAddPeer(106, 99, true, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
// Fabric removal test
err = mGroupPeerMsgCounter.FabricRemoved(123);
EXPECT_EQ(err, CHIP_ERROR_NOT_FOUND);
err = mGroupPeerMsgCounter.FabricRemoved(99);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = mGroupPeerMsgCounter.FabricRemoved(99);
EXPECT_EQ(err, CHIP_ERROR_NOT_FOUND);
// Verify that the Fabric List was compacted.
EXPECT_EQ(106, mGroupPeerMsgCounter.GetFabricIndexAt(0));
}
TEST(TestGroupMessageCounter, PeerRetrievalTest)
{
NodeId peerNodeId = 1234;
FabricIndex fabricIndex = 1;
CHIP_ERROR err = CHIP_NO_ERROR;
chip::Transport::PeerMessageCounter * counter = nullptr;
chip::Transport::PeerMessageCounter * counter2 = nullptr;
chip::Transport::GroupPeerTable mGroupPeerMsgCounter;
err = mGroupPeerMsgCounter.FindOrAddPeer(fabricIndex, peerNodeId, true, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_NE(counter, nullptr);
err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter2);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_NE(counter2, nullptr);
EXPECT_NE(counter2, counter);
err = mGroupPeerMsgCounter.FindOrAddPeer(fabricIndex, peerNodeId, true, counter2);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_EQ(counter2, counter);
}
TEST(TestGroupMessageCounter, CounterCommitRolloverTest)
{
CHIP_ERROR err = CHIP_NO_ERROR;
chip::Transport::PeerMessageCounter * counter = nullptr;
chip::Transport::GroupPeerTable mGroupPeerMsgCounter;
err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_NE(counter, nullptr);
err = counter->VerifyOrTrustFirstGroup(UINT32_MAX);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(UINT32_MAX);
err = counter->VerifyOrTrustFirstGroup(0);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(0);
err = counter->VerifyOrTrustFirstGroup(1);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(1);
}
TEST(TestGroupMessageCounter, CounterTrustFirstTest)
{
CHIP_ERROR err = CHIP_NO_ERROR;
chip::Transport::PeerMessageCounter * counter = nullptr;
chip::Transport::GroupPeerTable mGroupPeerMsgCounter;
err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_NE(counter, nullptr);
err = counter->VerifyOrTrustFirstGroup(5656);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(5656);
err = counter->VerifyOrTrustFirstGroup(5756);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(5756);
err = counter->VerifyOrTrustFirstGroup(4756);
EXPECT_NE(err, CHIP_NO_ERROR);
// test sequential reception
err = counter->VerifyOrTrustFirstGroup(5757);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(5757);
err = counter->VerifyOrTrustFirstGroup(5758);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(5758);
err = counter->VerifyOrTrustFirstGroup(5756);
EXPECT_NE(err, CHIP_NO_ERROR);
// Test Roll over
err = mGroupPeerMsgCounter.FindOrAddPeer(1, 99, true, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_NE(counter, nullptr);
err = counter->VerifyOrTrustFirstGroup(UINT32_MAX - 6);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(UINT32_MAX - 6);
err = counter->VerifyOrTrustFirstGroup(UINT32_MAX - 1);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(UINT32_MAX - 1);
err = counter->VerifyOrTrustFirstGroup(UINT32_MAX);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = counter->VerifyOrTrustFirstGroup(0);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = counter->VerifyOrTrustFirstGroup(1);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = counter->VerifyOrTrustFirstGroup(2);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = counter->VerifyOrTrustFirstGroup(3);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = counter->VerifyOrTrustFirstGroup(4);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = counter->VerifyOrTrustFirstGroup(5);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = counter->VerifyOrTrustFirstGroup(6);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = counter->VerifyOrTrustFirstGroup(7);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
TEST(TestGroupMessageCounter, ReorderPeerRemovalTest)
{
CHIP_ERROR err = CHIP_NO_ERROR;
chip::Transport::PeerMessageCounter * counter = nullptr;
TestGroupPeerTable mGroupPeerMsgCounter;
err = mGroupPeerMsgCounter.FindOrAddPeer(1, 1, true, counter);
err = mGroupPeerMsgCounter.FindOrAddPeer(1, 2, true, counter);
err = mGroupPeerMsgCounter.RemovePeer(1, 1, true);
EXPECT_EQ(mGroupPeerMsgCounter.GetNodeIdAt(0, 0, true), 2u);
// with other list
err = mGroupPeerMsgCounter.FindOrAddPeer(2, 1, false, counter);
err = mGroupPeerMsgCounter.FindOrAddPeer(2, 2, false, counter);
err = mGroupPeerMsgCounter.FindOrAddPeer(2, 3, false, counter);
err = mGroupPeerMsgCounter.FindOrAddPeer(2, 4, false, counter);
err = mGroupPeerMsgCounter.FindOrAddPeer(2, 5, false, counter);
err = mGroupPeerMsgCounter.FindOrAddPeer(2, 6, false, counter);
err = mGroupPeerMsgCounter.FindOrAddPeer(2, 7, false, counter);
err = mGroupPeerMsgCounter.FindOrAddPeer(2, 8, false, counter);
err = mGroupPeerMsgCounter.FindOrAddPeer(2, 9, false, counter);
err = mGroupPeerMsgCounter.RemovePeer(2, 7, false);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_EQ(mGroupPeerMsgCounter.GetNodeIdAt(1, 6, false), 9u);
err = mGroupPeerMsgCounter.RemovePeer(2, 4, false);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_EQ(mGroupPeerMsgCounter.GetNodeIdAt(1, 3, false), 8u);
err = mGroupPeerMsgCounter.RemovePeer(2, 1, false);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_EQ(mGroupPeerMsgCounter.GetNodeIdAt(1, 0, false), 9u);
}
TEST(TestGroupMessageCounter, ReorderFabricRemovalTest)
{
CHIP_ERROR err = CHIP_NO_ERROR;
chip::Transport::PeerMessageCounter * counter = nullptr;
TestGroupPeerTable mGroupPeerMsgCounter;
for (uint8_t i = 0; i < CHIP_CONFIG_MAX_FABRICS; i++)
{
err = mGroupPeerMsgCounter.FindOrAddPeer(static_cast<chip::FabricIndex>(i + 1), 1, false, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
}
// Try removing last Fabric first
err = counter->VerifyOrTrustFirstGroup(1234);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(1234);
err = mGroupPeerMsgCounter.FabricRemoved(CHIP_CONFIG_MAX_FABRICS);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_EQ(mGroupPeerMsgCounter.GetFabricIndexAt(CHIP_CONFIG_MAX_FABRICS - 1), kUndefinedFabricIndex);
err = mGroupPeerMsgCounter.FindOrAddPeer(CHIP_CONFIG_MAX_FABRICS, 1, false, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
// Verify that the counter was indeed cleared
err = counter->VerifyOrTrustFirstGroup(1234);
EXPECT_EQ(err, CHIP_NO_ERROR);
// Set a counter that will be moved around
err = counter->VerifyOrTrustFirstGroup(5656);
EXPECT_EQ(err, CHIP_NO_ERROR);
counter->CommitGroup(5656);
err = counter->VerifyOrTrustFirstGroup(4756);
EXPECT_NE(err, CHIP_NO_ERROR);
// Per Spec CHIP_CONFIG_MAX_FABRICS can only be as low as 4
err = mGroupPeerMsgCounter.RemovePeer(3, 1, false);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_EQ(mGroupPeerMsgCounter.GetFabricIndexAt(2), CHIP_CONFIG_MAX_FABRICS);
err = mGroupPeerMsgCounter.RemovePeer(2, 1, false);
EXPECT_EQ(err, CHIP_NO_ERROR);
EXPECT_EQ(mGroupPeerMsgCounter.GetFabricIndexAt(1), CHIP_CONFIG_MAX_FABRICS - 1);
// Validate that counter value were moved around correctly
err = mGroupPeerMsgCounter.FindOrAddPeer(CHIP_CONFIG_MAX_FABRICS, 1, false, counter);
EXPECT_EQ(err, CHIP_NO_ERROR);
err = counter->VerifyOrTrustFirstGroup(4756);
EXPECT_NE(err, CHIP_NO_ERROR);
}
TEST(TestGroupMessageCounter, GroupMessageCounterTest)
{
chip::TestPersistentStorageDelegate delegate;
TestGroupOutgoingCounters groupCientCounter;
uint32_t controlCounter = 0, dataCounter = 0;
CHIP_ERROR err = groupCientCounter.Init(&delegate);
EXPECT_EQ(err, CHIP_NO_ERROR);
// Start Test with Control counter
// Counter should be random
controlCounter = groupCientCounter.GetCounter(true);
dataCounter = groupCientCounter.GetCounter(false);
groupCientCounter.IncrementCounter(true);
EXPECT_EQ((groupCientCounter.GetCounter(true) - controlCounter), 1u);
groupCientCounter.SetCounter(true, UINT32_MAX - GROUP_MSG_COUNTER_MIN_INCREMENT);
EXPECT_EQ(groupCientCounter.GetCounter(true), UINT32_MAX - GROUP_MSG_COUNTER_MIN_INCREMENT);
// Test Persistence
TestGroupOutgoingCounters groupCientCounter2(&delegate);
EXPECT_EQ(groupCientCounter2.GetCounter(true), UINT32_MAX);
EXPECT_EQ((groupCientCounter2.GetCounter(false) - dataCounter), (uint32_t) GROUP_MSG_COUNTER_MIN_INCREMENT);
// Test Roll over
groupCientCounter2.IncrementCounter(true);
EXPECT_EQ(groupCientCounter2.GetCounter(true), 0u);
TestGroupOutgoingCounters groupCientCounter3(&delegate);
EXPECT_EQ(groupCientCounter3.GetCounter(true), (UINT32_MAX + GROUP_MSG_COUNTER_MIN_INCREMENT));
// Redo the test with the second counter
// Start Test with Control counter
dataCounter = groupCientCounter.GetCounter(false);
groupCientCounter.IncrementCounter(false);
EXPECT_EQ((groupCientCounter.GetCounter(false) - dataCounter), 1u);
groupCientCounter.SetCounter(false, UINT32_MAX - GROUP_MSG_COUNTER_MIN_INCREMENT);
EXPECT_EQ(groupCientCounter.GetCounter(false), UINT32_MAX - GROUP_MSG_COUNTER_MIN_INCREMENT);
// Test Persistence
TestGroupOutgoingCounters groupCientCounter4(&delegate);
EXPECT_EQ(groupCientCounter4.GetCounter(false), UINT32_MAX);
// Test Roll over
groupCientCounter4.IncrementCounter(false);
EXPECT_EQ(groupCientCounter4.GetCounter(false), 0u);
TestGroupOutgoingCounters groupCientCounter5(&delegate);
EXPECT_EQ(groupCientCounter5.GetCounter(false), (UINT32_MAX + GROUP_MSG_COUNTER_MIN_INCREMENT));
}
} // namespace