blob: 05d2491475ecef4d18434e547fecd7ade72483c2 [file] [log] [blame]
/*
*
* Copyright (c) 2021 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 <lib/address_resolve/AddressResolve_DefaultImpl.h>
#include <lib/support/UnitTestRegistration.h>
#include <nlunit-test.h>
using namespace chip;
using namespace chip::AddressResolve;
namespace {
constexpr uint8_t kNumberOfAvailableSlots = CHIP_CONFIG_MDNS_RESOLVE_LOOKUP_RESULTS;
Transport::PeerAddress GetAddressWithLowScore(uint16_t port = CHIP_PORT, Inet::InterfaceId interfaceId = Inet::InterfaceId::Null())
{
// Embedded IPv4
Inet::IPAddress ipAddress;
Inet::IPAddress::FromString("0:0:0:0:0:0:111.22.33.44", ipAddress);
return Transport::PeerAddress::UDP(ipAddress, port, interfaceId);
}
Transport::PeerAddress GetAddressWithMediumScore(uint16_t port = CHIP_PORT,
Inet::InterfaceId interfaceId = Inet::InterfaceId::Null())
{
// Unique Local
Inet::IPAddress ipAddress;
Inet::IPAddress::FromString("fdff:aabb:ccdd:1::4", ipAddress);
return Transport::PeerAddress::UDP(ipAddress, port, interfaceId);
}
Transport::PeerAddress GetAddressWithHighScore(uint16_t port = CHIP_PORT, Inet::InterfaceId interfaceId = Inet::InterfaceId::Null())
{
// Global Unicast
Inet::IPAddress ipAddress;
Inet::IPAddress::FromString("2001::aabb:ccdd:2233:4455", ipAddress);
return Transport::PeerAddress::UDP(ipAddress, port, interfaceId);
}
void TestLookupResult(nlTestSuite * inSuite, void * inContext)
{
ResolveResult lowResult;
lowResult.address = GetAddressWithLowScore();
ResolveResult mediumResult;
mediumResult.address = GetAddressWithMediumScore();
ResolveResult highResult;
highResult.address = GetAddressWithHighScore();
ResolveResult outResult;
AddressResolve::NodeLookupHandle handle;
auto now = System::SystemClock().GetMonotonicTimestamp();
auto request = NodeLookupRequest(chip::PeerId(1, 2));
handle.ResetForLookup(now, request);
// Check that no result exists.
NL_TEST_ASSERT(inSuite, !handle.HasLookupResult());
// Fill a single slot.
handle.LookupResult(lowResult);
// Check that a result exists.
NL_TEST_ASSERT(inSuite, handle.HasLookupResult());
// Check that the result match what has been inserted.
outResult = handle.TakeLookupResult();
NL_TEST_ASSERT(inSuite, lowResult.address == outResult.address);
// Check that the result has been consumed properly
NL_TEST_ASSERT(inSuite, !handle.HasLookupResult());
handle.ResetForLookup(now, request);
// Fill all the possible slots.
for (auto i = 0; i < kNumberOfAvailableSlots; i++)
{
handle.LookupResult(lowResult);
}
// Read back all results and validate that they match the input.
for (auto i = 0; i < kNumberOfAvailableSlots; i++)
{
NL_TEST_ASSERT(inSuite, handle.HasLookupResult());
outResult = handle.TakeLookupResult();
NL_TEST_ASSERT(inSuite, lowResult.address == outResult.address);
}
// Check that the results has been consumed properly.
NL_TEST_ASSERT(inSuite, !handle.HasLookupResult());
handle.ResetForLookup(now, request);
// Fill all the possible slots by giving it 2 times more results than the available slots.
for (auto i = 0; i < kNumberOfAvailableSlots * 2; i++)
{
handle.LookupResult(lowResult);
}
// Read back all results and validate that they match the input.
for (auto i = 0; i < kNumberOfAvailableSlots; i++)
{
NL_TEST_ASSERT(inSuite, handle.HasLookupResult());
outResult = handle.TakeLookupResult();
NL_TEST_ASSERT(inSuite, lowResult.address == outResult.address);
}
// Check that the results has been consumed properly.
NL_TEST_ASSERT(inSuite, !handle.HasLookupResult());
handle.ResetForLookup(now, request);
// Fill all the possible slots.
for (auto i = 0; i < kNumberOfAvailableSlots; i++)
{
handle.LookupResult(lowResult);
}
// Add a result with a medium score and ensure it sits at the top.
handle.LookupResult(mediumResult);
NL_TEST_ASSERT(inSuite, handle.HasLookupResult());
outResult = handle.TakeLookupResult();
NL_TEST_ASSERT(inSuite, mediumResult.address == outResult.address);
handle.ResetForLookup(now, request);
// Fill all the possible slots.
for (auto i = 0; i < kNumberOfAvailableSlots; i++)
{
handle.LookupResult(lowResult);
}
// Add a result with a medium score and a result with a high score and ensure the result with the high score comes first.
handle.LookupResult(mediumResult);
handle.LookupResult(highResult);
NL_TEST_ASSERT(inSuite, handle.HasLookupResult());
outResult = handle.TakeLookupResult();
NL_TEST_ASSERT(inSuite, highResult.address == outResult.address);
if (kNumberOfAvailableSlots > 1)
{
// Ensure the second result is the medium result.
NL_TEST_ASSERT(inSuite, handle.HasLookupResult());
outResult = handle.TakeLookupResult();
NL_TEST_ASSERT(inSuite, mediumResult.address == outResult.address);
}
if (kNumberOfAvailableSlots > 2)
{
// Ensure that all the other results are low results.
for (auto i = 2; i < kNumberOfAvailableSlots; i++)
{
NL_TEST_ASSERT(inSuite, handle.HasLookupResult());
outResult = handle.TakeLookupResult();
NL_TEST_ASSERT(inSuite, lowResult.address == outResult.address);
}
}
// Check that the results has been consumed properly.
NL_TEST_ASSERT(inSuite, !handle.HasLookupResult());
}
const nlTest sTests[] = {
NL_TEST_DEF("TestLookupResult", TestLookupResult), //
NL_TEST_SENTINEL() //
};
} // namespace
int TestAddressResolve_DefaultImpl()
{
nlTestSuite theSuite = { "AddressResolve_DefaultImpl", sTests, nullptr, nullptr };
nlTestRunner(&theSuite, nullptr);
return nlTestRunnerStats(&theSuite);
}
CHIP_REGISTER_TEST_SUITE(TestAddressResolve_DefaultImpl)