307 lines
11 KiB
C++
307 lines
11 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "DHCPUtils.h"
|
|
#include "gtest/gtest.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsString.h"
|
|
#include "nsWindowsDHCPClient.h"
|
|
|
|
using namespace mozilla::toolkit::system::windowsDHCPClient;
|
|
|
|
class WindowsNetworkFunctionsMock : public WindowsNetworkFunctionsWrapper {
|
|
public:
|
|
WindowsNetworkFunctionsMock() : mAddressesToReturn(nullptr) {
|
|
memset(mOptions, 0, sizeof(char*) * 256);
|
|
}
|
|
|
|
ULONG GetAdaptersAddressesWrapped(
|
|
_In_ ULONG Family, _In_ ULONG Flags, _In_ PVOID Reserved,
|
|
_Inout_ PIP_ADAPTER_ADDRESSES AdapterAddresses,
|
|
_Inout_ PULONG SizePointer) {
|
|
if (*SizePointer < sizeof(*mAddressesToReturn)) {
|
|
*SizePointer = sizeof(*mAddressesToReturn);
|
|
return ERROR_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
*SizePointer = sizeof(*mAddressesToReturn);
|
|
memcpy(AdapterAddresses, mAddressesToReturn, *SizePointer);
|
|
return 0;
|
|
}
|
|
|
|
DWORD DhcpRequestParamsWrapped(_In_ DWORD Flags, _In_ LPVOID Reserved,
|
|
_In_ LPWSTR AdapterName,
|
|
_In_ LPDHCPCAPI_CLASSID ClassId,
|
|
_In_ DHCPCAPI_PARAMS_ARRAY SendParams,
|
|
_Inout_ DHCPCAPI_PARAMS_ARRAY RecdParams,
|
|
_In_ LPBYTE Buffer, _Inout_ LPDWORD pSize,
|
|
_In_ LPWSTR RequestIdStr) {
|
|
mLastRequestedNetworkAdapterName.Assign(AdapterName);
|
|
|
|
if (mOptions[RecdParams.Params[0].OptionId] == nullptr) {
|
|
RecdParams.Params[0].nBytesData = 0;
|
|
} else {
|
|
RecdParams.Params[0].Data = Buffer;
|
|
size_t lengthOfValue = strlen(mOptions[RecdParams.Params[0].OptionId]);
|
|
if (*pSize > lengthOfValue) {
|
|
memcpy(Buffer, mOptions[RecdParams.Params[0].OptionId], lengthOfValue);
|
|
RecdParams.Params[0].nBytesData = lengthOfValue;
|
|
} else {
|
|
*pSize = lengthOfValue;
|
|
return ERROR_MORE_DATA;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void AddAdapterAddresses(IP_ADAPTER_ADDRESSES& aAddressesToAdd) {
|
|
if (mAddressesToReturn == nullptr) {
|
|
mAddressesToReturn = &aAddressesToAdd;
|
|
return;
|
|
}
|
|
IP_ADAPTER_ADDRESSES* tail = mAddressesToReturn;
|
|
|
|
while (tail->Next != nullptr) {
|
|
tail = tail->Next;
|
|
}
|
|
tail->Next = &aAddressesToAdd;
|
|
}
|
|
|
|
void SetDHCPOption(uint8_t option, const char* value) {
|
|
mOptions[option] = value;
|
|
}
|
|
|
|
nsString GetLastRequestedNetworkAdapterName() {
|
|
return mLastRequestedNetworkAdapterName;
|
|
}
|
|
|
|
private:
|
|
IP_ADAPTER_ADDRESSES* mAddressesToReturn = nullptr;
|
|
const char* mOptions[256];
|
|
nsString mLastRequestedNetworkAdapterName;
|
|
};
|
|
|
|
class TestDHCPUtils : public ::testing::Test {
|
|
protected:
|
|
RefPtr<WindowsNetworkFunctionsMock> mMockWindowsFunctions;
|
|
nsCString mDefaultAdapterName;
|
|
|
|
virtual void SetUp() {
|
|
mMockWindowsFunctions = new WindowsNetworkFunctionsMock();
|
|
mDefaultAdapterName.AssignLiteral("my favourite network adapter");
|
|
}
|
|
|
|
void Given_DHCP_Option_Is(uint8_t option, const char* value) {
|
|
mMockWindowsFunctions.get()->SetDHCPOption(option, value);
|
|
}
|
|
|
|
void Given_Network_Adapter_Called(IP_ADAPTER_ADDRESSES& adapterAddresses,
|
|
const char* adapterName) {
|
|
adapterAddresses.AdapterName = const_cast<char*>(adapterName);
|
|
adapterAddresses.Next = nullptr;
|
|
adapterAddresses.Dhcpv4Server.iSockaddrLength = 0;
|
|
adapterAddresses.Dhcpv6Server.iSockaddrLength = 0;
|
|
adapterAddresses.Flags |= IP_ADAPTER_DHCP_ENABLED;
|
|
AddAdapterAddresses(adapterAddresses);
|
|
}
|
|
|
|
void Given_Network_Adapter_Supports_DHCP_V4(
|
|
IP_ADAPTER_ADDRESSES& adapterAddresses) {
|
|
adapterAddresses.Dhcpv4Server.iSockaddrLength = 4;
|
|
}
|
|
|
|
void Given_Network_Adapter_Supports_DHCP_V6(
|
|
IP_ADAPTER_ADDRESSES& adapterAddresses) {
|
|
adapterAddresses.Dhcpv6Server.iSockaddrLength = 12;
|
|
}
|
|
|
|
void Given_Network_Adapter_Has_Operational_Status(
|
|
IP_ADAPTER_ADDRESSES& adapterAddresses, IF_OPER_STATUS operStatus) {
|
|
adapterAddresses.OperStatus = operStatus;
|
|
}
|
|
|
|
private:
|
|
void AddAdapterAddresses(IP_ADAPTER_ADDRESSES& aAddressToAdd) {
|
|
mMockWindowsFunctions.get()->AddAdapterAddresses(aAddressToAdd);
|
|
}
|
|
};
|
|
|
|
// following class currently just distinguishes tests of nsWindowsDHCPClient
|
|
// from tests of DHCPUtils.
|
|
class TestNsWindowsDHCPClient : public TestDHCPUtils {};
|
|
|
|
TEST_F(TestDHCPUtils, TestGetAdaptersAddresses) {
|
|
IP_ADAPTER_ADDRESSES adapterAddresses = {};
|
|
Given_Network_Adapter_Called(adapterAddresses,
|
|
"my favourite network adapter");
|
|
Given_Network_Adapter_Supports_DHCP_V4(adapterAddresses);
|
|
Given_Network_Adapter_Has_Operational_Status(adapterAddresses,
|
|
IfOperStatusUp);
|
|
|
|
nsCString networkAdapterName;
|
|
|
|
ASSERT_EQ(NS_OK, GetActiveDHCPNetworkAdapterName(networkAdapterName,
|
|
mMockWindowsFunctions));
|
|
|
|
ASSERT_STREQ(networkAdapterName.Data(), "my favourite network adapter");
|
|
}
|
|
|
|
TEST_F(TestDHCPUtils, TestGetAdaptersAddressesNoAvailableNetworks) {
|
|
IP_ADAPTER_ADDRESSES adapterAddresses = {};
|
|
Given_Network_Adapter_Called(adapterAddresses,
|
|
"my favourite network adapter");
|
|
Given_Network_Adapter_Supports_DHCP_V4(adapterAddresses);
|
|
Given_Network_Adapter_Has_Operational_Status(adapterAddresses,
|
|
IfOperStatusDown);
|
|
|
|
nsCString networkAdapterName;
|
|
ASSERT_EQ(NS_ERROR_NOT_AVAILABLE,
|
|
GetActiveDHCPNetworkAdapterName(networkAdapterName,
|
|
mMockWindowsFunctions));
|
|
|
|
ASSERT_STREQ(networkAdapterName.Data(), "");
|
|
}
|
|
|
|
TEST_F(TestDHCPUtils, TestGetAdaptersAddressesNoNetworksWithDHCP) {
|
|
IP_ADAPTER_ADDRESSES adapterAddresses = {};
|
|
Given_Network_Adapter_Called(adapterAddresses,
|
|
"my favourite network adapter");
|
|
Given_Network_Adapter_Has_Operational_Status(adapterAddresses,
|
|
IfOperStatusUp);
|
|
|
|
nsCString networkAdapterName;
|
|
ASSERT_EQ(NS_ERROR_NOT_AVAILABLE,
|
|
GetActiveDHCPNetworkAdapterName(networkAdapterName,
|
|
mMockWindowsFunctions));
|
|
|
|
ASSERT_STREQ(networkAdapterName.Data(), "");
|
|
}
|
|
|
|
TEST_F(TestDHCPUtils, TestGetAdaptersAddressesSecondNetworkIsAvailable) {
|
|
IP_ADAPTER_ADDRESSES adapterAddresses = {};
|
|
Given_Network_Adapter_Called(adapterAddresses,
|
|
"my favourite network adapter");
|
|
Given_Network_Adapter_Supports_DHCP_V4(adapterAddresses);
|
|
Given_Network_Adapter_Has_Operational_Status(adapterAddresses,
|
|
IfOperStatusDown);
|
|
|
|
IP_ADAPTER_ADDRESSES secondAdapterAddresses = {};
|
|
Given_Network_Adapter_Called(secondAdapterAddresses,
|
|
"my second favourite network adapter");
|
|
Given_Network_Adapter_Supports_DHCP_V6(secondAdapterAddresses);
|
|
Given_Network_Adapter_Has_Operational_Status(secondAdapterAddresses,
|
|
IfOperStatusUp);
|
|
|
|
nsCString networkAdapterName;
|
|
ASSERT_EQ(NS_OK, GetActiveDHCPNetworkAdapterName(networkAdapterName,
|
|
mMockWindowsFunctions));
|
|
|
|
ASSERT_STREQ(networkAdapterName.Data(),
|
|
"my second favourite network adapter");
|
|
}
|
|
|
|
TEST_F(TestDHCPUtils, TestGetOption) {
|
|
const char* pacURL = "http://pac.com";
|
|
Given_DHCP_Option_Is(1, "My network option");
|
|
Given_DHCP_Option_Is(252, pacURL);
|
|
|
|
std::vector<char> optionValue(255, *"originalValue originalValue");
|
|
memcpy(optionValue.data(), "originalValue originalValue",
|
|
strlen("originalValue originalValue") + 1);
|
|
|
|
uint32_t size = 255;
|
|
|
|
nsresult retVal = RetrieveOption(mDefaultAdapterName, 252, optionValue, &size,
|
|
mMockWindowsFunctions);
|
|
|
|
ASSERT_EQ(strlen(pacURL), size);
|
|
ASSERT_STREQ("http://pac.comoriginalValue", optionValue.data());
|
|
ASSERT_EQ(NS_OK, retVal);
|
|
}
|
|
|
|
TEST_F(TestDHCPUtils, TestGetAbsentOption) {
|
|
std::vector<char> optionValue(255);
|
|
uint32_t size = 256;
|
|
memcpy(optionValue.data(), "originalValue", strlen("originalValue") + 1);
|
|
|
|
nsresult retVal = RetrieveOption(mDefaultAdapterName, 252, optionValue, &size,
|
|
mMockWindowsFunctions);
|
|
|
|
ASSERT_EQ(0U, size);
|
|
ASSERT_EQ(NS_ERROR_NOT_AVAILABLE, retVal);
|
|
}
|
|
|
|
TEST_F(TestDHCPUtils, TestGetTooLongOption) {
|
|
Given_DHCP_Option_Is(252, "http://pac.com");
|
|
|
|
std::vector<char> optionValue(255);
|
|
memcpy(optionValue.data(), "originalValue", strlen("originalValue") + 1);
|
|
uint32_t size = 4;
|
|
nsresult retVal = RetrieveOption(mDefaultAdapterName, 252, optionValue, &size,
|
|
mMockWindowsFunctions);
|
|
|
|
ASSERT_STREQ("httpinalValue", optionValue.data());
|
|
ASSERT_EQ(NS_ERROR_LOSS_OF_SIGNIFICANT_DATA, retVal);
|
|
ASSERT_EQ(strlen("http://pac.com"), size);
|
|
}
|
|
|
|
TEST_F(TestNsWindowsDHCPClient, TestGettingOptionThroughNSWindowsDHCPClient) {
|
|
IP_ADAPTER_ADDRESSES adapterAddresses = {};
|
|
Given_Network_Adapter_Called(adapterAddresses,
|
|
"my favourite network adapter");
|
|
Given_Network_Adapter_Supports_DHCP_V4(adapterAddresses);
|
|
Given_Network_Adapter_Has_Operational_Status(adapterAddresses,
|
|
IfOperStatusUp);
|
|
Given_DHCP_Option_Is(252, "http://pac.com");
|
|
|
|
nsCString optionValue;
|
|
nsCOMPtr<nsIDHCPClient> dhcpClient =
|
|
new nsWindowsDHCPClient(mMockWindowsFunctions);
|
|
nsresult retVal = dhcpClient->GetOption(252, optionValue);
|
|
|
|
ASSERT_STREQ("http://pac.com", optionValue.Data());
|
|
ASSERT_STREQ(
|
|
L"my favourite network adapter",
|
|
mMockWindowsFunctions->GetLastRequestedNetworkAdapterName().Data());
|
|
ASSERT_EQ(NS_OK, retVal);
|
|
}
|
|
|
|
TEST_F(
|
|
TestNsWindowsDHCPClient,
|
|
TestGettingOptionThroughNSWindowsDHCPClientWhenNoAvailableNetworkAdapter) {
|
|
IP_ADAPTER_ADDRESSES adapterAddresses = {};
|
|
Given_Network_Adapter_Called(adapterAddresses,
|
|
"my favourite network adapter");
|
|
Given_Network_Adapter_Has_Operational_Status(adapterAddresses,
|
|
IfOperStatusDown);
|
|
Given_DHCP_Option_Is(252, "http://pac.com");
|
|
|
|
nsCString optionValue;
|
|
nsCOMPtr<nsIDHCPClient> dhcpClient =
|
|
new nsWindowsDHCPClient(mMockWindowsFunctions);
|
|
nsresult retVal = dhcpClient->GetOption(252, optionValue);
|
|
|
|
ASSERT_STREQ("", optionValue.Data());
|
|
ASSERT_EQ(NS_ERROR_NOT_AVAILABLE, retVal);
|
|
}
|
|
|
|
TEST_F(TestNsWindowsDHCPClient,
|
|
TestGettingAbsentOptionThroughNSWindowsDHCPClient) {
|
|
IP_ADAPTER_ADDRESSES adapterAddresses = {};
|
|
Given_Network_Adapter_Called(adapterAddresses,
|
|
"my favourite network adapter");
|
|
Given_Network_Adapter_Supports_DHCP_V6(adapterAddresses);
|
|
Given_Network_Adapter_Has_Operational_Status(adapterAddresses,
|
|
IfOperStatusUp);
|
|
|
|
nsCString optionValue;
|
|
nsCOMPtr<nsIDHCPClient> dhcpClient =
|
|
new nsWindowsDHCPClient(mMockWindowsFunctions);
|
|
nsresult retVal = dhcpClient->GetOption(252, optionValue);
|
|
|
|
ASSERT_STREQ("", optionValue.Data());
|
|
ASSERT_EQ(NS_ERROR_NOT_AVAILABLE, retVal);
|
|
}
|