blob: ce9af9daed7fcae4d889be08d7b40910227ddc63 [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright 2022 The Fuchsia 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.
import random
from dataclasses import dataclass
from mobly import asserts, test_runner
from antlion.test_utils.dhcp import base_test
OPT_NUM_DOMAIN_SEARCH = 119
OPT_NUM_DOMAIN_NAME = 15
@dataclass
class Test:
name: str
dhcp_options: dict[str, int | str]
dhcp_parameters: dict[str, str]
class Dhcpv4InteropCombinatorialOptionsTest(base_test.Dhcpv4InteropFixture):
"""DhcpV4 tests which validate combinations of DHCP options."""
def setup_generated_tests(self) -> None:
def test_logic(t: Test) -> None:
self.run_test_case_expect_dhcp_success(t.dhcp_parameters, t.dhcp_options)
def name_func(t: Test) -> str:
return f"test_{t.name}"
self.generate_tests(
test_logic=test_logic,
name_func=name_func,
arg_sets=[
(t,)
for t in [
Test(
name="domain_name_valid",
dhcp_options={
"domain-name": '"example.test"',
"dhcp-parameter-request-list": OPT_NUM_DOMAIN_NAME,
},
dhcp_parameters={},
),
Test(
name="domain_name_invalid",
dhcp_options={
"domain-name": '"example.invalid"',
"dhcp-parameter-request-list": OPT_NUM_DOMAIN_NAME,
},
dhcp_parameters={},
),
Test(
name="domain_search_valid",
dhcp_options={
"domain-name": '"example.test"',
"dhcp-parameter-request-list": OPT_NUM_DOMAIN_SEARCH,
},
dhcp_parameters={},
),
Test(
name="domain_search_invalid",
dhcp_options={
"domain-name": '"example.invalid"',
"dhcp-parameter-request-list": OPT_NUM_DOMAIN_SEARCH,
},
dhcp_parameters={},
),
Test(
name="max_sized_message",
dhcp_options=self._generate_max_sized_message_dhcp_options(),
dhcp_parameters={},
),
]
],
)
def _generate_max_sized_message_dhcp_options(self) -> dict[str, int | str]:
"""Generates the DHCP options for max sized message test.
The RFC limits DHCP payloads to 576 bytes unless the client signals it
can handle larger payloads, which it does by sending DHCP option 57,
"Maximum DHCP Message Size". Despite being able to accept larger
payloads, clients typically don't advertise this. The test verifies that
the client accepts a large message split across multiple ethernet
frames. The test is created by sending many bytes of options through the
domain-name-servers option, which is of unbounded length (though is
compressed per RFC1035 section 4.1.4).
Returns:
A dict of DHCP options.
"""
typical_ethernet_mtu = 1500
long_dns_setting = ", ".join(
f'"ns{num}.example"'
for num in random.sample(range(100_000, 1_000_000), 250)
)
# RFC1035 compression means any shared suffix ('.example' in this case)
# will be deduplicated. Calculate approximate length by removing that
# suffix.
long_dns_setting_len = len(
long_dns_setting.replace(", ", "")
.replace('"', "")
.replace(".example", "")
.encode("utf-8")
)
asserts.assert_true(
long_dns_setting_len > typical_ethernet_mtu,
"Expected to generate message greater than ethernet mtu",
)
return {
"dhcp-max-message-size": long_dns_setting_len * 2,
"domain-search": long_dns_setting,
"dhcp-parameter-request-list": OPT_NUM_DOMAIN_SEARCH,
}
if __name__ == "__main__":
test_runner.main()