# Copyright 2020 Istvan Ruzman # SPDX-License-Identifier: MIT OR Apache-2.0 from io import StringIO import pytest from pyrad3.dictionary import Dictionary, ParseError @pytest.mark.parametrize( "filename", ["dictionaries/self_recursive", "dictionaries/mutual_recursive"] ) def test_dictionary_recursion(filename): with pytest.raises(ParseError): Dictionary("tests/" + filename) @pytest.mark.parametrize( "line", [ "$INCLUDE", "BEGIN-VENDOR", "END-VENDOR", "VENDOR", "VENDOR NAME", "ATTRIBUTE", "ATTRIBUTE NAME", "VALUE", "VALUE ATTRNAME", "VALUE ATTRNAME VALUENAME", ], ) def test_lines_missing_tokens(line): dictionary = StringIO(line) with pytest.raises(ParseError): Dictionary("", dictionary) @pytest.mark.parametrize( "vendor", [ "VENDOR test 1234", "VENDOR test 1234 format=1,1", "VENDOR test 1234 format=2,2", "VENDOR test 1234 format=1,2", "VENDOR test 1234 format=4,2", "VENDOR test 1234 format=4,0", "VENDOR WiMAX 1234 format=1,1,c", ], ) def test_valid_vendor_definitions(vendor): dictionary = StringIO(vendor) Dictionary("", dictionary) @pytest.mark.parametrize( "vendor", [ "VENDOR test 1234 1,1", "VENDOR test 1234 format=3,1", "VENDOR test 1234 format=2", "VENDOR test 1234 format=1,2,c", "VENDOR test 1234 format=1,9", "VENDOR test 1234 format=4,4 suffix", "VENDOR test 1234 format=a,b suffix", ], ) def test_invalid_vendor_definitions(vendor): dictionary = StringIO(vendor) with pytest.raises(ParseError): Dictionary("", dictionary) @pytest.mark.parametrize( "number", [ "ATTRIBUTE NAME 0x01 byte", "ATTRIBUTE NAME 0x0001 byte", "ATTRIBUTE NAME 0o123 byte", "ATTRIBUTE NAME 5 byte", ], ) def test_valid_attribute_numbers(number): dictionary = StringIO(number) Dictionary("", dictionary) @pytest.mark.parametrize( "invalid_number", ["ABCD", "-1", "inf", "INF", "-INF", "2e4", "2.5e3"], ) def test_invalid_attribute_numbers(invalid_number): dictionary = StringIO(f"ATTRIBUTE NAME {invalid_number} integer64") with pytest.raises(ParseError): Dictionary("", dictionary) @pytest.mark.parametrize("type_length", [1, 2, 4]) def test_attribute_number_limits(type_length): too_big = 2 ** (8 * type_length) max_value = too_big - 1 dictionary = StringIO( f"VENDOR TEST 1234 format={type_length},1\n" "BEGIN-VENDOR TEST\n" f"ATTRIBUTE TEST {max_value} byte\n" "END-VENDOR TEST\n" ) Dictionary("", dictionary) dictionary = StringIO( f"VENDOR TEST 1234 format={type_length},1\n" "BEGIN-VENDOR TEST\n" f"ATTRIBUTE TEST {too_big} byte\n" "END-VENDOR TEST\n" ) with pytest.raises(ParseError): Dictionary("", dictionary) @pytest.mark.parametrize("value", ["1", "0x1", "0o1"]) def test_value_definition(value): dictionary = StringIO( "ATTRIBUTE TEST-ATTRIBUTE 1 byte\n" f"VALUE TEST-ATTRIBUTE TEST-VALUE {value}" ) Dictionary("", dictionary) @pytest.mark.parametrize( "value_num, attr_type", [ (0, "byte"), (255, "byte"), (0, "short"), (2 ** 16 - 1, "short"), (0, "integer"), (2 ** 32 - 1, "integer"), ((-(2 ** 31)), "signed"), (2 ** 31 - 1, "signed"), (0, "integer64"), (2 ** 64 - 1, "integer64"), ], ) def test_value_number_within_limit(value_num, attr_type): dictionary = StringIO( f"ATTRIBUTE TEST-ATTRIBUTE 1 {attr_type}\n" f"VALUE TEST-ATTRIBUTE TEST-VALUE {value_num}" ) Dictionary("", dictionary) dictionary = StringIO( "VENDOR TEST-VENDOR 1234\n" "BEGIN-VENDOR TEST-VENDOR\n" f"ATTRIBUTE TEST-ATTRIBUTE 1 {attr_type}\n" f"VALUE TEST-ATTRIBUTE TEST-VALUE {value_num}\n" "END-VENDOR TEST-VEDNOR" ) @pytest.mark.parametrize( "value_num, attr_type", [ (-1, "byte"), (256, "byte"), (-1, "short"), (2 ** 16, "short"), (-1, "integer"), (2 ** 32, "integer"), (2 ** 31, "signed"), ((-(2 ** 31)) - 1, "signed"), (-1, "integer64"), (2 ** 64, "integer64"), ], ) def test_value_number_out_of_limit(value_num, attr_type): dictionary = StringIO( f"ATTRIBUTE TEST-ATTRIBUTE 1 {attr_type}\n" f"VALUE TEST-ATTRIBUTE TEST-VALUE {value_num}" ) with pytest.raises(ParseError): Dictionary("", dictionary) dictionary = StringIO( "VENDOR TEST-VENDOR 1234\n" "BEGIN-VENDOR TEST-VENDOR\n" f"ATTRIBUTE TEST-ATTRIBUTE 1 {attr_type}\n" f"VALUE TEST-ATTRIBUTE TEST-VALUE {value_num}\n" "END-VENDOR TEST-VEDNOR" ) with pytest.raises(ParseError): Dictionary("", dictionary) @pytest.mark.parametrize( "datatype", [ "string", "octets", "abinary", "byte", "short", "integer", "signed", "integer64", "ipaddr", "ipv4prefix", "ipv6addr", "ipv6prefix", "combo-ip", "ifid", "ether", "concat", "tlv", "extended", "long-extended", "evs", ], ) def test_all_datatypes_rfc_space(datatype): dictionary = StringIO(f"ATTRIBUTE TEST-ATTRIBUTE 1 {datatype}\n") Dictionary("", dictionary) @pytest.mark.parametrize( "datatype", [ "string", "octets", "abinary", "byte", "short", "integer", "signed", "integer64", "ipaddr", "ipv4prefix", "ipv6addr", "ipv6prefix", "combo-ip", "ifid", "ether", "tlv", ], ) def test_valid_datatypes_in_vendor_space(datatype): dictionary = StringIO( "VENDOR TEST 1234\n" "BEGIN-VENDOR TEST\n" f"ATTRIBUTE TEST-ATTRIBUTE 1 {datatype}\n" "END-VENDOR TEST\n" ) Dictionary("", dictionary) @pytest.mark.parametrize( "datatype", ["concat", "extended", "long-extended", "evs",] ) def test_invalid_datatypes_in_vendor_space(datatype): dictionary = StringIO( "VENDOR TEST 1234\n" "BEGIN-VENDOR TEST\n" f"ATTRIBUTE TEST-ATTRIBUTE 1 {datatype}\n" "END-VENDOR TEST\n" ) with pytest.raises(ParseError): Dictionary("", dictionary) @pytest.mark.parametrize( "invalid_number", ["ABCD", "-1", "inf", "INF", "-INF", "0.1", "2e4", "2.5e3"], ) def test_invalid_attribute_numbers(invalid_number): dictionary = StringIO( f"ATTRIBUTE TEST-ATTRIBUTE 1 integer\n" f"VALUE TEST-ATTRIBUTE TEST-VALUE {invalid_number}") with pytest.raises(ParseError): Dictionary("", dictionary)