This repository contains code and data for testing the compliance of Automated Frequency Coordinator (AFC) software. The AFC is defined by the FCC in proceeding 18-295 on Unlicensed Use of the 6 GHz Band. This repository contains procedures, documentation, and tests for such software, and for the devices authorized by it. To contribute, please first read the CONTRIBUTING file in the repository for instructions.
14
stars
3
forks
source link
Unintuitive log messages if test-required fields violate SDI spec #18
In many places throughout the test harness, we attempt to suppress errors and continue on until something critical fails. One such critical failure is an inability to create a dataclass representation of the object (indicating a name or type error of the message fields in some fashion), if the issue is related to a field used by the actual test in question. Some fields (e.g., vendorExtensions) are not critical spec violations (i.e., the broken field is not required by the test), and should be suppressed. For example:
if self.vendorExtensions is not None:
with suppress(TypeError):
self.vendorExtensions = init_from_dicts(self.vendorExtensions, VendorExtension)
will attempt to replace self.vendorExtensions with a list of VendorExtension objects. If an error occurs during the object initialization, the original value for self.vendorExtensions will be left in place. This retains the information in the object for manual inspection, but the extensions cannot be manipulated as VendorExtensions.
However, for a required sub-field, such as .availableSpectrumInquiryResponses, we would want this type of error to prevent execution of the actual test. We check for this condition already in test_main.py (lines 254-260):
logger.debug(f'Parsing received response as a response object...')
try:
response_obj = AvailableSpectrumInquiryResponseMessage(**response)
except TypeError as ex:
logger.error(f'Exception converting response for comparison: {ex}. Test SKIPPED.\n')
results.add_result(test_name, TestResult.SKIPPED)
continue
However, because .availableSpectrumInquiryResponses is subject to similar TypeError suppression as VendorExtensions
with suppress(TypeError):
self.availableSpectrumInquiryResponses = init_from_dicts(
self.availableSpectrumInquiryResponses,
AvailableSpectrumInquiryResponse)
an invalid AvailableSpectrumInquiryResponse will allow the "successful" creation of the enclosing AvailableSpectrumInquiryResponseMessage, and the try/except block will not catch the issue before proceeding to the test.
Potential Fixes
Selective removal of the suppress(Error) wrappers for "critical" sub-fields would allow the error to propagate upwards and trigger the except clause in test_main.py. However, this would also prevent the partial initialization of any parent object, which is not desired by other code (i.e., the validators).
An alternate fix may be to explicitly validate the presence of the dataclass version of the provided and accessed objects in response_mask_runner.py to ensure field-access errors (using dot-notation to access fields of dicts, etc.) are avoided, and the root issue (failure to create the dataclass representation) is reported clearly.
Acknowledgements
Thanks to Commscope for contributing a test case that reveals this issue.
Problem Description
In many places throughout the test harness, we attempt to suppress errors and continue on until something critical fails. One such critical failure is an inability to create a dataclass representation of the object (indicating a name or type error of the message fields in some fashion), if the issue is related to a field used by the actual test in question. Some fields (e.g.,
vendorExtensions
) are not critical spec violations (i.e., the broken field is not required by the test), and should be suppressed. For example:will attempt to replace
self.vendorExtensions
with a list ofVendorExtension
objects. If an error occurs during the object initialization, the original value forself.vendorExtensions
will be left in place. This retains the information in the object for manual inspection, but the extensions cannot be manipulated asVendorExtensions
.However, for a required sub-field, such as
.availableSpectrumInquiryResponses
, we would want this type of error to prevent execution of the actual test. We check for this condition already intest_main.py
(lines 254-260):However, because
.availableSpectrumInquiryResponses
is subject to similarTypeError
suppression asVendorExtensions
an invalid
AvailableSpectrumInquiryResponse
will allow the "successful" creation of the enclosingAvailableSpectrumInquiryResponseMessage
, and the try/except block will not catch the issue before proceeding to the test.Potential Fixes
Selective removal of the
suppress(Error)
wrappers for "critical" sub-fields would allow the error to propagate upwards and trigger the except clause intest_main.py
. However, this would also prevent the partial initialization of any parent object, which is not desired by other code (i.e., the validators).An alternate fix may be to explicitly validate the presence of the dataclass version of the provided and accessed objects in
response_mask_runner.py
to ensure field-access errors (using dot-notation to access fields of dicts, etc.) are avoided, and the root issue (failure to create the dataclass representation) is reported clearly.Acknowledgements
Thanks to Commscope for contributing a test case that reveals this issue.