| /* |
| * 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 <gtest/gtest.h> |
| |
| #include <lib/address_resolve/AddressResolve_DefaultImpl.h> |
| |
| using namespace chip; |
| using namespace chip::AddressResolve; |
| |
| namespace { |
| |
| using chip::Dnssd::IPAddressSorter::IpScore; |
| using chip::Dnssd::IPAddressSorter::ScoreIpAddress; |
| |
| constexpr uint8_t kNumberOfAvailableSlots = CHIP_CONFIG_MDNS_RESOLVE_LOOKUP_RESULTS; |
| |
| Transport::PeerAddress GetAddressWithLowScore(uint16_t port = CHIP_PORT, Inet::InterfaceId interfaceId = Inet::InterfaceId::Null()) |
| { |
| // Unique Local - expect score "3" |
| Inet::IPAddress ipAddress; |
| if (!Inet::IPAddress::FromString("fdff:aabb:ccdd:1::4", ipAddress)) |
| { |
| ChipLogError(NotSpecified, "!!!!!!!! IP Parse failure"); |
| } |
| return Transport::PeerAddress::UDP(ipAddress, port, interfaceId); |
| } |
| |
| Transport::PeerAddress GetAddressWithMediumScore(uint16_t port = CHIP_PORT, |
| Inet::InterfaceId interfaceId = Inet::InterfaceId::Null()) |
| { |
| |
| // Global Unicast - expect score '4' |
| Inet::IPAddress ipAddress; |
| if (!Inet::IPAddress::FromString("2001::aabb:ccdd:2233:4455", ipAddress)) |
| { |
| ChipLogError(NotSpecified, "!!!!!!!! IP Parse failure"); |
| } |
| return Transport::PeerAddress::UDP(ipAddress, port, interfaceId); |
| } |
| |
| Transport::PeerAddress GetAddressWithHighScore(uint16_t port = CHIP_PORT, Inet::InterfaceId interfaceId = Inet::InterfaceId::Null()) |
| { |
| // LinkLocal - expect score '7' |
| // Likely that the interfaceId is wrong (link local needs it), |
| // however we do not expect sorter to care |
| Inet::IPAddress ipAddress; |
| if (!Inet::IPAddress::FromString("fe80::aabb:ccdd:2233:4455", ipAddress)) |
| { |
| ChipLogError(NotSpecified, "!!!!!!!! IP Parse failure"); |
| } |
| return Transport::PeerAddress::UDP(ipAddress, port, interfaceId); |
| } |
| |
| TEST(TestAddressResolveDefaultImpl, TestLookupResult) |
| { |
| ResolveResult lowResult; |
| lowResult.address = GetAddressWithLowScore(); |
| |
| ResolveResult mediumResult; |
| mediumResult.address = GetAddressWithMediumScore(); |
| |
| ResolveResult highResult; |
| highResult.address = GetAddressWithHighScore(); |
| |
| // Ensure test expectations regarding ordering is matched |
| |
| IpScore lowScore = ScoreIpAddress(lowResult.address.GetIPAddress(), Inet::InterfaceId::Null()); |
| IpScore mediumScore = ScoreIpAddress(mediumResult.address.GetIPAddress(), Inet::InterfaceId::Null()); |
| IpScore highScore = ScoreIpAddress(highResult.address.GetIPAddress(), Inet::InterfaceId::Null()); |
| |
| EXPECT_LT(to_underlying(lowScore), to_underlying(mediumScore)); |
| EXPECT_LT(to_underlying(mediumScore), to_underlying(highScore)); |
| |
| 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. |
| EXPECT_FALSE(handle.HasLookupResult()); |
| |
| // Fill a single slot. |
| handle.LookupResult(lowResult); |
| |
| // Check that a result exists. |
| EXPECT_TRUE(handle.HasLookupResult()); |
| |
| // Check that the result match what has been inserted. |
| outResult = handle.TakeLookupResult(); |
| EXPECT_EQ(lowResult.address, outResult.address); |
| |
| // Check that the result has been consumed properly |
| EXPECT_FALSE(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++) |
| { |
| EXPECT_TRUE(handle.HasLookupResult()); |
| outResult = handle.TakeLookupResult(); |
| EXPECT_EQ(lowResult.address, outResult.address); |
| } |
| |
| // Check that the results has been consumed properly. |
| EXPECT_FALSE(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++) |
| { |
| EXPECT_TRUE(handle.HasLookupResult()); |
| outResult = handle.TakeLookupResult(); |
| EXPECT_EQ(lowResult.address, outResult.address); |
| } |
| |
| // Check that the results has been consumed properly. |
| EXPECT_FALSE(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); |
| EXPECT_TRUE(handle.HasLookupResult()); |
| outResult = handle.TakeLookupResult(); |
| EXPECT_EQ(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); |
| EXPECT_TRUE(handle.HasLookupResult()); |
| outResult = handle.TakeLookupResult(); |
| EXPECT_EQ(highResult.address, outResult.address); |
| |
| if (kNumberOfAvailableSlots > 1) |
| { |
| // Ensure the second result is the medium result. |
| EXPECT_TRUE(handle.HasLookupResult()); |
| outResult = handle.TakeLookupResult(); |
| EXPECT_EQ(mediumResult.address, outResult.address); |
| } |
| |
| if (kNumberOfAvailableSlots > 2) |
| { |
| // Ensure that all the other results are low results. |
| for (auto i = 2; i < kNumberOfAvailableSlots; i++) |
| { |
| EXPECT_TRUE(handle.HasLookupResult()); |
| outResult = handle.TakeLookupResult(); |
| EXPECT_EQ(lowResult.address, outResult.address); |
| } |
| } |
| |
| // Check that the results has been consumed properly. |
| EXPECT_FALSE(handle.HasLookupResult()); |
| } |
| } // namespace |