diff --git a/pysmi/codegen/base.py b/pysmi/codegen/base.py index 827f8b0..41f1a90 100644 --- a/pysmi/codegen/base.py +++ b/pysmi/codegen/base.py @@ -293,11 +293,11 @@ def gen_index(self, mibsMap, **kwargs): @staticmethod def is_binary(s): - return isinstance(s, str) and s[0] == "'" and s[-2:] in ("'b", "'B") + return isinstance(s, str) and s and s[0] == "'" and s[-2:] in ("'b", "'B") @staticmethod def is_hex(s): - return isinstance(s, str) and s[0] == "'" and s[-2:] in ("'h", "'H") + return isinstance(s, str) and s and s[0] == "'" and s[-2:] in ("'h", "'H") def str2int(self, s): if self.is_binary(s): diff --git a/pysmi/codegen/intermediate.py b/pysmi/codegen/intermediate.py index 4fdc30b..a7e9ed9 100644 --- a/pysmi/codegen/intermediate.py +++ b/pysmi/codegen/intermediate.py @@ -13,10 +13,6 @@ from pysmi.codegen.base import AbstractCodeGen from pysmi.mibinfo import MibInfo -if sys.version_info[0] > 2: - unicode = str - long = int - class IntermediateCodeGen(AbstractCodeGen): """Turns MIB AST into an intermediate representation. @@ -220,7 +216,23 @@ def get_base_type(self, symName, module): else: baseSymType, baseSymSubtype = self.get_base_type(*symType) - if isinstance(baseSymSubtype, list): + + if isinstance(baseSymSubtype, dict): + # An enumeration (INTEGER or BITS). Combine the enumeration + # lists when applicable. That is a bit more permissive than + # strictly needed, as syntax refinement may only remove entries + # from the base enumeration (RFC 2578 Sec. 9 point (2)). + if isinstance(symSubtype, dict): + baseSymSubtype.update(symSubtype) + symSubtype = baseSymSubtype + + elif isinstance(baseSymSubtype, list): + # A value range or size constraint. Note that each list is an + # intersection of unions of ranges. Taking the intersection + # instead of the most-top level union of ranges is a bit more + # restrictive than strictly needed, as range syntax refinement + # may only remove allowed values from the base type (RFC 2578 + # Sec. 9. points (1) and (3)), but it matches what pyasn1 does. if isinstance(symSubtype, list): symSubtype += baseSymSubtype else: @@ -486,7 +498,7 @@ def gen_object_type(self, data): oidStr, parentOid = oid indexStr, fakeSyms, fakeSymDicts = index or ("", [], []) - defval = self.gen_def_val(defval, objname=pysmiName) + defval = self.process_defval(defval, objname=pysmiName) outDict = OrderedDict() outDict["name"] = name @@ -667,125 +679,207 @@ def gen_contact_info(self, data): text = data[0] return self.textFilter("contact-info", text) + def is_in_range(self, intersection, value): + """Check whether the given value falls within the given constraints. + + The given list represents an intersection and contains elements that + represent unions of individual ranges. Each individual range consists + of one or two elements (a single value, or a low..high range). The + given value is considered in range if it falls within range for each of + the unions within the intersection. If the intersection is empty, the + value is accepted as well. + """ + for union in intersection: + in_range = False + for rng in union: + if self.str2int(rng[0]) <= value <= self.str2int(rng[-1]): + in_range = True + break + if not in_range: + return False + return True + # noinspection PyUnusedLocal def gen_display_hint(self, data): return data[0] - # noinspection PyUnusedLocal - def gen_def_val(self, data, objname=None): - if not data: - return {} + # noinspection PyMethodMayBeStatic,PyUnusedLocal + def gen_def_val(self, data): + return data[0] - if not objname: - return data + def _process_integer_defval(self, defval, defvalType): + """Process a DEFVAL value for an integer/enumeration type.""" + if isinstance(defval, int): # decimal + value = defval - defval = data[0] - defvalType = self.get_base_type(objname, self.moduleName[0]) + elif self.is_hex(defval): # hex + value = int(defval[1:-2] or "0", 16) + + elif self.is_binary(defval): # binary + value = int(defval[1:-2] or "0", 2) + + elif isinstance(defvalType[1], dict): # enumeration label + # For enumerations, the ASN.1 DEFVAL statements contain names, + # whereas the code generation template expects integer values + # (represented as strings). + nameToValueMap = defvalType[1] + + # buggy MIB: DEFVAL { { ... } } + if isinstance(defval, list): + defval = [dv for dv in defval if dv in nameToValueMap] + if defval: + defval = defval[0] + # (fall through) + + # good MIB: DEFVAL { ... } + if defval not in nameToValueMap: + raise ValueError("unknown enumeration label") + + # Return early so as to skip the enumeration value check below. + # After all, we already know the resulting number is valid. + return str(nameToValueMap[defval]), "decimal" + + else: + raise ValueError("wrong input type for integer") + + if isinstance(defvalType[1], dict): # enumeration number + # For numerical values given for enumerated integers, make sure + # that they are valid, because pyasn1 will not check this case and + # thus let us set a default value that is not valid for the type. + if value not in defvalType[1].values(): + raise ValueError("wrong enumeration value") + + elif isinstance(defvalType[1], list): # range constraints + if not self.is_in_range(defvalType[1], value): + raise ValueError("value does not conform to range constraints") + + return str(value), "decimal" + + def _process_string_defval(self, defval, defvalType): + """Process a DEFVAL value for a string type (including BITS).""" + defvalBaseType = defvalType[0][0] # either "OctetString" or "Bits" - outDict = OrderedDict(basetype=defvalType[0][0]) + if isinstance(defval, int): # decimal + if defvalBaseType != "Bits": + raise ValueError("decimal values have no meaning for OCTET STRING") - if isinstance(defval, (int, long)): # number - outDict.update(value=defval, format="decimal") + # Convert the value to a hex string. Add padding if needed. + value = defval and hex(defval)[2:] or "" + value = ("0" + value) if len(value) % 2 == 1 else value + + fmt = "hex" elif self.is_hex(defval): # hex - # common bug in MIBs - if defvalType[0][0] in ("Integer32", "Integer"): - outDict.update( - value=str(int(len(defval) > 3 and defval[1:-2] or "0", 16)), - format="hex", - ) + # Extract the value as hex string. Add padding if needed. + value = defval[1:-2] + value = ("0" + value) if len(value) % 2 == 1 else value - else: - outDict.update(value=defval[1:-2], format="hex") + fmt = "hex" elif self.is_binary(defval): # binary binval = defval[1:-2] - # common bug in MIBs - if defvalType[0][0] in ("Integer32", "Integer"): - outDict.update(value=str(int(binval or "0", 2)), format="bin") + # Make sure not to lose any leading zeroes. Add padding if needed. + width = ((len(binval) + 7) // 8) * 2 + value = width and "{:0{width}x}".format(int(binval, 2), width=width) or "" + fmt = "hex" - else: - hexval = binval and hex(int(binval, 2))[2:] or "" - outDict.update(value=hexval, format="hex") + elif defval and defval[0] == '"' and defval[-1] == '"': # quoted string + if defvalBaseType != "OctetString": + raise ValueError("quoted strings have no meaning for BITS") + + value = defval[1:-1] + fmt = "string" + + elif defvalBaseType == "Bits" and isinstance(defval, list): # bit labels + defvalBits = [] - # quoted string - elif defval and defval[0] == defval[-1] and defval[0] == '"': - # common bug in MIBs - if defval[1:-1] == "" and defvalType != "OctetString": - # a warning should be here - return {} # we will set no default value + bits = defvalType[1] - outDict.update(value=defval[1:-1], format="string") + for bit in defval: + bitValue = bits.get(bit, None) + if bitValue is not None: + defvalBits.append((bit, bitValue)) + else: + raise ValueError("unknown bit") + + return self.gen_bits([defvalBits])[1], "bits" - # symbol (oid as defval) or name for enumeration member else: - # oid - if defvalType[0][0] == "ObjectIdentifier" and ( - self.trans_opers(defval) in self.symbolTable[self.moduleName[0]] - or self.trans_opers(defval) in self._importMap - ): - pysmiDefval = self.trans_opers(defval) - module = self._importMap.get(pysmiDefval, self.moduleName[0]) - - try: - val = str( - self.gen_numeric_oid( - self.symbolTable[module][pysmiDefval]["oid"] - ) - ) + raise ValueError("wrong input type for string") - outDict.update(value=val, format="oid") + if defvalBaseType == "OctetString" and isinstance( + defvalType[1], list + ): # size constraints + size = len(value) // 2 if fmt == "hex" else len(value) - except Exception: - # or no module if it will be borrowed later - raise error.PySmiSemanticError( - f'no symbol "{defval}" in module "{module}"' - ) + if not self.is_in_range(defvalType[1], size): + raise ValueError("value does not conform to size constraints") - # enumeration - elif defvalType[0][0] in ("Integer32", "Integer") and isinstance( - defvalType[1], list - ): - # For enumerations, the ASN.1 DEFVAL statements contain names, - # whereas the code generation template expects integer values - # (represented as strings). - nameToValueMap = dict(defvalType[1]) - - # buggy MIB: DEFVAL { { ... } } - if isinstance(defval, list): - defval = [dv for dv in defval if dv in nameToValueMap] - if defval: - outDict.update( - value=str(nameToValueMap[defval[0]]), format="enum" - ) - - # good MIB: DEFVAL { ... } - elif defval in nameToValueMap: - outDict.update(value=str(nameToValueMap[defval]), format="enum") - - elif defvalType[0][0] == "Bits": - defvalBits = [] - - bits = dict(defvalType[1]) - - for bit in defval: - bitValue = bits.get(bit, None) - if bitValue is not None: - defvalBits.append((bit, bitValue)) + return value, fmt - else: - raise error.PySmiSemanticError( - f'no such bit as "{bit}" for symbol "{objname}"' - ) + def _process_oid_defval(self, defval, defvalType): + """Process a DEFVAL value for an object identifier.""" + if isinstance(defval, str) and ( + self.trans_opers(defval) in self.symbolTable[self.moduleName[0]] + or self.trans_opers(defval) in self._importMap + ): + pysmiDefval = self.trans_opers(defval) + module = self._importMap.get(pysmiDefval, self.moduleName[0]) - outDict.update(value=self.gen_bits([defvalBits])[1], format="bits") + value = self.gen_numeric_oid(self.symbolTable[module][pysmiDefval]["oid"]) - else: - raise error.PySmiSemanticError( - f'unknown type "{defvalType}" for defval "{defval}" of symbol "{objname}"' - ) + return str(value), "oid" + + else: + raise ValueError("wrong input type for object identifier") + + def process_defval(self, defval, objname): + if defval is None: + return {} + + defvalType = self.get_base_type(objname, self.moduleName[0]) + defvalBaseType = defvalType[0][0] + + # Our general policy is that DEFVAL values are considered discardable: + # any values that were accepted by the parser but turn out to be + # invalid, are dropped here, so that they will not keep the MIB from + # being compiled or loaded. The underlying idea is that DEFVAL values + # are not all that important, and therefore better discarded than the + # cause of a MIB loading failure. + # + # For each combination of input value and object type, the following + # table shows whether the combination is: + # - required to be supported by RFC 2578; + # - accepted out of lenience by our implementation; or, + # - discarded for being no meaningful combination. + # Note that enumerations are also Integer32/Integer types, but handled + # slightly differently, so they are a separate column in this table. + # + # Input Integer Enumeration OctetString ObjectId. Bits + # ------------- ----------- ----------- ----------- ----------- --------- + # decimal required accepted discarded discarded accepted + # hex accepted accepted required discarded accepted + # binary accepted accepted required discarded accepted + # quoted string discarded discarded required discarded discarded + # symbol/label discarded required discarded required discarded + # brackets discarded accepted discarded discarded required + + try: + if defvalBaseType in ("Integer32", "Integer"): + value, fmt = self._process_integer_defval(defval, defvalType) + elif defvalBaseType in ("OctetString", "Bits"): + value, fmt = self._process_string_defval(defval, defvalType) + elif defvalBaseType == "ObjectIdentifier": + value, fmt = self._process_oid_defval(defval, defvalType) + else: # pragma: no cover + raise ValueError("unknown base type") + + except ValueError: + # Discard the given default value. + return {} + outDict = OrderedDict(basetype=defvalBaseType, value=value, format=fmt) return {"default": outDict} # noinspection PyMethodMayBeStatic @@ -903,11 +997,11 @@ def gen_oid(self, data): out = () parent = "" for el in data[0]: - if isinstance(el, (str, unicode)): + if isinstance(el, str): parent = self.trans_opers(el) out += ((parent, self._importMap.get(parent, self.moduleName[0])),) - elif isinstance(el, (int, long)): + elif isinstance(el, int): out += (el,) elif isinstance(el, tuple): diff --git a/pysmi/codegen/symtable.py b/pysmi/codegen/symtable.py index 5223b0d..6dd0856 100644 --- a/pysmi/codegen/symtable.py +++ b/pysmi/codegen/symtable.py @@ -312,9 +312,6 @@ def gen_object_type(self, data, classmode=False): if augmention: parents.append(self.trans_opers(augmention)) - if defval: # XXX - symProps["defval"] = defval - if index and index[1]: namepart, fakeIndexes, fakeSymSyntax = index for fakeIdx, fakeSyntax in zip(fakeIndexes, fakeSymSyntax): @@ -384,7 +381,7 @@ def gen_bit_names(self, data, classmode=False): # noinspection PyUnusedLocal,PyMethodMayBeStatic def gen_bits(self, data, classmode=False): - bits = data[0] + bits = dict(data[0]) return ("Bits", ""), bits # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic @@ -406,34 +403,9 @@ def gen_contact_info(self, data, classmode=False): def gen_display_hint(self, data, classmode=False): return "" - # noinspection PyUnusedLocal - def gen_def_val(self, data, classmode=False): # XXX should be fixed, see pysnmp.py - defval = data[0] - - if isinstance(defval, int): # number - val = str(defval) - - elif self.is_hex(defval): # hex - val = 'hexValue="' + defval[1:-2] + '"' # not working for Integer baseTypes - - elif self.is_binary(defval): # binary - binval = defval[1:-2] - hexval = binval and hex(int(binval, 2))[2:] or "" - val = 'hexValue="' + hexval + '"' - - elif isinstance(defval, list): # bits list - val = defval - - elif defval and defval[0] == defval[-1] and defval[0] == '"': # quoted string - val = dorepr(defval[1:-1]) - - else: # symbol (oid as defval) or name for enumeration member - if defval in self._out or defval in self._importMap: - val = defval + ".getName()" - else: - val = dorepr(defval) - - return val + # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic + def gen_def_val(self, data, classmode=False): + return "" # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic def gen_description(self, data, classmode=False): @@ -472,7 +444,7 @@ def gen_index(self, data, classmode=False): # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic def gen_integer_subtype(self, data, classmode=False): - return "" + return [data[0]] # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic def gen_max_access(self, data, classmode=False): @@ -480,7 +452,7 @@ def gen_max_access(self, data, classmode=False): # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic def gen_octetstring_subtype(self, data, classmode=False): - return "" + return [data[0]] # noinspection PyUnusedLocal def gen_oid(self, data, classmode=False): diff --git a/pysmi/codegen/templates/pysnmp/mib-definitions.j2 b/pysmi/codegen/templates/pysnmp/mib-definitions.j2 index ff1d348..0a7c729 100644 --- a/pysmi/codegen/templates/pysnmp/mib-definitions.j2 +++ b/pysmi/codegen/templates/pysnmp/mib-definitions.j2 @@ -177,23 +177,11 @@ if mibBuilder.loadTexts: {% if definition['default']['default']['format'] == 'decimal' %} defaultValue = {{ definition['default']['default']['value'] }} {% elif definition['default']['default']['format'] == 'hex' %} - {# TODO: pyasn1 Integer does not have defaultHexValue #} - {% if definition['default']['default']['basetype'] in ('Integer', 'Integer32') %} - defaultHexValue = {{ definition['default']['default']['value'] }} - {% else %} defaultHexValue = "{{ definition['default']['default']['value'] }}" - {% endif %} - {# TODO: pyasn1 Integer does not have defaultBinValue #} - {% elif definition['default']['default']['format'] == 'bin' %} - {% if definition['default']['default']['basetype'] in ('Integer', 'Integer32') %} - defaultBinValue = {{ definition['default']['default']['value'] }} - {% else %} - defaultBinValue = "{{ definition['default']['default']['value'] }}" - {% endif %} {% elif definition['default']['default']['format'] == 'string' %} {# TODO: pyasn1 does not like defaulted strings #} defaultValue = OctetString({{ definition['default']['default']['value']|pythonstr }}) - {% elif definition['default']['default']['format'] in ('oid', 'enum') %} + {% elif definition['default']['default']['format'] == 'oid' %} defaultValue = {{ definition['default']['default']['value'] }} {% elif definition['default']['default']['format'] == 'bits' %} {# TODO: pyasn1 does not like default named bits #} diff --git a/tests/__main__.py b/tests/__main__.py index 1574b5b..fce7baf 100644 --- a/tests/__main__.py +++ b/tests/__main__.py @@ -14,6 +14,7 @@ [ "test_zipreader", "test_agentcapabilities_smiv2_pysnmp", + "test_defval_smiv2_pysnmp", "test_imports_smiv2_pysnmp", "test_modulecompliance_smiv2_pysnmp", "test_moduleidentity_smiv2_pysnmp", diff --git a/tests/test_defval_smiv2_pysnmp.py b/tests/test_defval_smiv2_pysnmp.py new file mode 100644 index 0000000..a8a2213 --- /dev/null +++ b/tests/test_defval_smiv2_pysnmp.py @@ -0,0 +1,2628 @@ +# +# This file is part of pysmi software. +# +# Copyright (c) 2015-2020, Ilya Etingof; Copyright (c) 2022-2024, others +# License: https://www.pysnmp.com/pysmi/license.html +# +import sys +import textwrap + +try: + import unittest2 as unittest + +except ImportError: + import unittest + +from pysmi.parser.smi import parserFactory +from pysmi.codegen.pysnmp import PySnmpCodeGen +from pysmi.codegen.symtable import SymtableCodeGen +from pysnmp.smi.builder import MibBuilder + + +class DefaultIntegerTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE, + Integer32 + FROM SNMPv2-SMI; + + testObjectType OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 123456 } + ::= { 1 3 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testIntegerDefvalSyntax(self): + self.assertEqual(self.ctx["testObjectType"].getSyntax(), 123456, "bad DEFVAL") + + +class DefaultIntegerZeroTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE, + Integer32 + FROM SNMPv2-SMI; + + testObjectType OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 0 } + ::= { 1 3 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testIntegerDefvalZeroSyntax(self): + self.assertEqual(self.ctx["testObjectType"].getSyntax(), 0, "bad DEFVAL") + + +class DefaultIntegerNegativeTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE, + Integer32 + FROM SNMPv2-SMI; + + + testObjectType OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -123 } + ::= { 1 3 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testIntegerDefvalSyntaxIsValue(self): + # This test basically verifies that isValue is working at all, so that + # we can be sure the assertFalse tests in the extended tests (further + # below) are meaningful. + self.assertTrue(self.ctx["testObjectType"].getSyntax().isValue, "bad DEFVAL") + + def testIntegerDefvalNegativeSyntax(self): + self.assertEqual(self.ctx["testObjectType"].getSyntax(), -123, "bad DEFVAL") + + +class DefaultIntegerFormatTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE, + Integer32 + FROM SNMPv2-SMI; + + testObjectTypeHex OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 'abCD0e'H } + ::= { 1 3 } + + testObjectTypeBinary OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '11011100'B } + ::= { 1 4 } + + testObjectTypeString OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "0" } + ::= { 1 5 } + + testObjectTypeSymbol OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { testObjectTypeString } + ::= { 1 6 } + + testObjectTypeBrackets OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { 0 } } + ::= { 1 7 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testIntegerDefvalHexSyntax(self): + self.assertEqual( + self.ctx["testObjectTypeHex"].getSyntax(), 0xABCD0E, "bad DEFVAL" + ) + + def testIntegerDefvalBinarySyntax(self): + self.assertEqual( + self.ctx["testObjectTypeBinary"].getSyntax(), 220, "bad DEFVAL" + ) + + def testIntegerDefvalStringSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeString"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalSymbolSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeSymbol"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalBracketsSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeBrackets"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultIntegerValueTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE, + Integer32 + FROM SNMPv2-SMI; + + testObjectTypePaddedHex OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '00abCD0e'H } + ::= { 1 3 } + + testObjectTypePaddedBinary OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '0000000011011100'B } + ::= { 1 4 } + + testObjectTypeZeroHex OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { ''H } + ::= { 1 5 } + + testObjectTypeZeroBinary OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { ''B } + ::= { 1 6 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testIntegerDefvalPaddedHexSyntax(self): + self.assertEqual( + self.ctx["testObjectTypePaddedHex"].getSyntax(), 0xABCD0E, "bad DEFVAL" + ) + + def testIntegerDefvalPaddedBinarySyntax(self): + self.assertEqual( + self.ctx["testObjectTypePaddedBinary"].getSyntax(), 220, "bad DEFVAL" + ) + + def testIntegerDefvalZeroHexSyntax(self): + self.assertEqual(self.ctx["testObjectTypeZeroHex"].getSyntax(), 0, "bad DEFVAL") + + def testIntegerDefvalZeroBinarySyntax(self): + self.assertEqual( + self.ctx["testObjectTypeZeroBinary"].getSyntax(), 0, "bad DEFVAL" + ) + + +class DefaultIntegerConstraintsTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE, + Integer32 + FROM SNMPv2-SMI; + + testObjectTypeDecimal1 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -3 } + ::= { 1 3 1 } + + testObjectTypeDecimal2 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -2 } + ::= { 1 3 2 } + + testObjectTypeDecimal3 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -1 } + ::= { 1 3 3 } + + testObjectTypeDecimal4 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 0 } + ::= { 1 3 4 } + + testObjectTypeDecimal5 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 1 } + ::= { 1 3 5 } + + testObjectTypeDecimal6 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 2 } + ::= { 1 3 6 } + + testObjectTypeDecimal7 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 3 } + ::= { 1 3 7 } + + testObjectTypeDecimal8 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 4 } + ::= { 1 3 8 } + + testObjectTypeDecimal9 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 5 } + ::= { 1 3 9 } + + testObjectTypeDecimal10 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 6 } + ::= { 1 3 10 } + + testObjectTypeDecimal11 OBJECT-TYPE + SYNTAX Integer32 (-2..-1 | 3 | 5..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 7 } + ::= { 1 3 11 } + + testObjectTypeHex1 OBJECT-TYPE + SYNTAX Integer32 (12345) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '3038'H } + ::= { 1 4 1 } + + testObjectTypeHex2 OBJECT-TYPE + SYNTAX Integer32 (12345) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '3039'H } + ::= { 1 4 2 } + + testObjectTypeHex3 OBJECT-TYPE + SYNTAX Integer32 (12345) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '303A'H } + ::= { 1 4 3 } + + testObjectTypeHex4 OBJECT-TYPE + SYNTAX Integer32 (12345) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '003039'H } + ::= { 1 4 4 } + + testObjectTypeBinary1 OBJECT-TYPE + SYNTAX Integer32 (67..68) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '01000010'B } + ::= { 1 5 1 } + + testObjectTypeBinary2 OBJECT-TYPE + SYNTAX Integer32 (67..68) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '01000011'B } + ::= { 1 5 2 } + + testObjectTypeBinary3 OBJECT-TYPE + SYNTAX Integer32 (67..68) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '0000000001000100'B } + ::= { 1 5 3 } + + testObjectTypeBinary4 OBJECT-TYPE + SYNTAX Integer32 (67..68) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '01000101'B } + ::= { 1 5 4 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testIntegerDefvalDecimalSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeDecimal1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalDecimalSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeDecimal2"].getSyntax(), -2, "bad DEFVAL" + ) + + def testIntegerDefvalDecimalSyntax3(self): + self.assertEqual( + self.ctx["testObjectTypeDecimal3"].getSyntax(), -1, "bad DEFVAL" + ) + + def testIntegerDefvalDecimalSyntaxIsValue4(self): + self.assertFalse( + self.ctx["testObjectTypeDecimal4"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalDecimalSyntaxIsValue5(self): + self.assertFalse( + self.ctx["testObjectTypeDecimal5"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalDecimalSyntaxIsValue6(self): + self.assertFalse( + self.ctx["testObjectTypeDecimal6"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalDecimalSyntax7(self): + self.assertEqual( + self.ctx["testObjectTypeDecimal7"].getSyntax(), 3, "bad DEFVAL" + ) + + def testIntegerDefvalDecimalSyntaxIsValue8(self): + self.assertFalse( + self.ctx["testObjectTypeDecimal8"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalDecimalSyntax9(self): + self.assertEqual( + self.ctx["testObjectTypeDecimal9"].getSyntax(), 5, "bad DEFVAL" + ) + + def testIntegerDefvalDecimalSyntax10(self): + self.assertEqual( + self.ctx["testObjectTypeDecimal10"].getSyntax(), 6, "bad DEFVAL" + ) + + def testIntegerDefvalDecimalSyntaxIsValue11(self): + self.assertFalse( + self.ctx["testObjectTypeDecimal11"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalHexSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeHex1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalHexSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeHex2"].getSyntax(), 12345, "bad DEFVAL" + ) + + def testIntegerDefvalHexSyntaxIsValue3(self): + self.assertFalse( + self.ctx["testObjectTypeHex3"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalHexSyntax4(self): + self.assertEqual( + self.ctx["testObjectTypeHex4"].getSyntax(), 12345, "bad DEFVAL" + ) + + def testIntegerDefvalBinarySyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeBinary1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalBinarySyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeBinary2"].getSyntax(), 67, "bad DEFVAL" + ) + + def testIntegerDefvalBinarySyntax3(self): + self.assertEqual( + self.ctx["testObjectTypeBinary3"].getSyntax(), 68, "bad DEFVAL" + ) + + def testIntegerDefvalBinarySyntaxIsValue4(self): + self.assertFalse( + self.ctx["testObjectTypeBinary4"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultIntegerConstraintsLayersTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE, + Integer32 + FROM SNMPv2-SMI + TEXTUAL-CONVENTION + FROM SNMPv2-TC; + + SimpleConstrainedInteger ::= Integer32 (1..2) + + testObjectTypeSimple1 OBJECT-TYPE + SYNTAX SimpleConstrainedInteger + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -1 } + ::= { 1 3 1 } + + testObjectTypeSimple2 OBJECT-TYPE + SYNTAX SimpleConstrainedInteger + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 0 } + ::= { 1 3 2 } + + testObjectTypeSimple3 OBJECT-TYPE + SYNTAX SimpleConstrainedInteger + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 1 } + ::= { 1 3 3 } + + -- The extra constraints are not correct, as they are not a subset of the + -- original constraints, but pysmi should deal with them properly. + testObjectTypeLayeredSimple1 OBJECT-TYPE + SYNTAX SimpleConstrainedInteger (2..3) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 1 } + ::= { 1 3 4 } + + testObjectTypeLayeredSimple2 OBJECT-TYPE + SYNTAX SimpleConstrainedInteger (2..3) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 2 } + ::= { 1 3 5 } + + testObjectTypeLayeredSimple3 OBJECT-TYPE + SYNTAX SimpleConstrainedInteger (2..3) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 3 } + ::= { 1 3 6 } + + TextualConstrainedInteger ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION "Test TC" + SYNTAX Integer32 (-4..-3) + + testObjectTypeTextual1 OBJECT-TYPE + SYNTAX TextualConstrainedInteger + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -5 } + ::= { 1 4 1 } + + testObjectTypeTextual2 OBJECT-TYPE + SYNTAX TextualConstrainedInteger + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 4 } + ::= { 1 4 2 } + + testObjectTypeTextual3 OBJECT-TYPE + SYNTAX TextualConstrainedInteger + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -4 } + ::= { 1 4 3 } + + testObjectTypeLayeredTextual1 OBJECT-TYPE + SYNTAX TextualConstrainedInteger (-3..-2) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -4 } + ::= { 1 4 4 } + + testObjectTypeLayeredTextual2 OBJECT-TYPE + SYNTAX TextualConstrainedInteger (-3..-2) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -3 } + ::= { 1 4 5 } + + testObjectTypeLayeredTextual3 OBJECT-TYPE + SYNTAX TextualConstrainedInteger (-3..-2) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -2 } + ::= { 1 4 6 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testIntegerDefvalSimpleSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeSimple1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalSimpleSyntaxIsValue2(self): + self.assertFalse( + self.ctx["testObjectTypeSimple2"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalSimpleSyntax3(self): + self.assertEqual(self.ctx["testObjectTypeSimple3"].getSyntax(), 1, "bad DEFVAL") + + def testIntegerDefvalLayeredSimpleSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeLayeredSimple1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalLayeredSimpleSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeLayeredSimple2"].getSyntax(), 2, "bad DEFVAL" + ) + + def testIntegerDefvalLayeredSimpleSyntaxIsValue3(self): + self.assertFalse( + self.ctx["testObjectTypeLayeredSimple3"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalTextualSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeTextual1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalTextualSyntaxIsValue2(self): + self.assertFalse( + self.ctx["testObjectTypeTextual2"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalTextualSyntax3(self): + self.assertEqual( + self.ctx["testObjectTypeTextual3"].getSyntax(), -4, "bad DEFVAL" + ) + + def testIntegerDefvalLayeredTextualSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeLayeredTextual1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalLayeredTextualSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeLayeredTextual2"].getSyntax(), -3, "bad DEFVAL" + ) + + def testIntegerDefvalLayeredTextualSyntaxIsValue3(self): + self.assertFalse( + self.ctx["testObjectTypeLayeredTextual3"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultIntegerConstraintsFormatTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE, + Integer32 + FROM SNMPv2-SMI; + + testObjectTypeHexFormat1 OBJECT-TYPE + SYNTAX Integer32 ('02'H..'03'H | '01FE'H) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 1 } + ::= { 1 3 1 } + + testObjectTypeHexFormat2 OBJECT-TYPE + SYNTAX Integer32 ('02'H..'03'H | '01FE'H) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 2 } + ::= { 1 3 2 } + + testObjectTypeHexFormat3 OBJECT-TYPE + SYNTAX Integer32 ('02'H..'03'H | '01FE'H) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 3 } + ::= { 1 3 3 } + + testObjectTypeHexFormat4 OBJECT-TYPE + SYNTAX Integer32 ('02'H..'03'H | '01FE'H) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 4 } + ::= { 1 3 4 } + + testObjectTypeHexFormat5 OBJECT-TYPE + SYNTAX Integer32 ('02'H..'03'H | '01FE'H) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 509 } + ::= { 1 3 5 } + + testObjectTypeHexFormat6 OBJECT-TYPE + SYNTAX Integer32 ('02'H..'03'H | '01FE'H) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 510 } + ::= { 1 3 6 } + + testObjectTypeHexFormat7 OBJECT-TYPE + SYNTAX Integer32 ('02'H..'03'H | '01FE'H) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 511 } + ::= { 1 3 7 } + + testObjectTypeBinaryFormat1 OBJECT-TYPE + SYNTAX Integer32 ('00000001'B | '00011110001001000000'B..'00011110001001000010'B) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 0 } + ::= { 1 4 1 } + + testObjectTypeBinaryFormat2 OBJECT-TYPE + SYNTAX Integer32 ('00000001'B | '00011110001001000000'B..'00011110001001000010'B) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 1 } + ::= { 1 4 2 } + + testObjectTypeBinaryFormat3 OBJECT-TYPE + SYNTAX Integer32 ('00000001'B | '00011110001001000000'B..'00011110001001000010'B) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 2 } + ::= { 1 4 3 } + + testObjectTypeBinaryFormat4 OBJECT-TYPE + SYNTAX Integer32 ('00000001'B | '00011110001001000000'B..'00011110001001000010'B) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 123455 } + ::= { 1 4 4 } + + testObjectTypeBinaryFormat5 OBJECT-TYPE + SYNTAX Integer32 ('00000001'B | '00011110001001000000'B..'00011110001001000010'B) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 123456 } + ::= { 1 4 5 } + + testObjectTypeBinaryFormat6 OBJECT-TYPE + SYNTAX Integer32 ('00000001'B | '00011110001001000000'B..'00011110001001000010'B) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '01E241'H } + ::= { 1 4 6 } + + testObjectTypeBinaryFormat7 OBJECT-TYPE + SYNTAX Integer32 ('00000001'B | '00011110001001000000'B..'00011110001001000010'B) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 123458 } + ::= { 1 4 7 } + + testObjectTypeBinaryFormat8 OBJECT-TYPE + SYNTAX Integer32 ('00000001'B | '00011110001001000000'B..'00011110001001000010'B) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 123459 } + ::= { 1 4 8 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testIntegerDefvalHexFormatSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeHexFormat1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalHexFormatSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeHexFormat2"].getSyntax(), 2, "bad DEFVAL" + ) + + def testIntegerDefvalHexFormatSyntax3(self): + self.assertEqual( + self.ctx["testObjectTypeHexFormat3"].getSyntax(), 3, "bad DEFVAL" + ) + + def testIntegerDefvalHexFormatSyntaxIsValue4(self): + self.assertFalse( + self.ctx["testObjectTypeHexFormat4"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalHexFormatSyntaxIsValue5(self): + self.assertFalse( + self.ctx["testObjectTypeHexFormat5"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalHexFormatSyntax6(self): + self.assertEqual( + self.ctx["testObjectTypeHexFormat6"].getSyntax(), 510, "bad DEFVAL" + ) + + def testIntegerDefvalHexFormatSyntaxIsValue7(self): + self.assertFalse( + self.ctx["testObjectTypeHexFormat7"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalBinaryFormatSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeBinaryFormat1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalBinaryFormatSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeBinaryFormat2"].getSyntax(), 1, "bad DEFVAL" + ) + + def testIntegerDefvalBinaryFormatSyntaxIsValue3(self): + self.assertFalse( + self.ctx["testObjectTypeBinaryFormat3"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalBinaryFormatSyntaxIsValue4(self): + self.assertFalse( + self.ctx["testObjectTypeBinaryFormat4"].getSyntax().isValue, "bad DEFVAL" + ) + + def testIntegerDefvalBinaryFormatSyntax5(self): + self.assertEqual( + self.ctx["testObjectTypeBinaryFormat5"].getSyntax(), 123456, "bad DEFVAL" + ) + + def testIntegerDefvalBinaryFormatSyntax6(self): + self.assertEqual( + self.ctx["testObjectTypeBinaryFormat6"].getSyntax(), 123457, "bad DEFVAL" + ) + + def testIntegerDefvalBinaryFormatSyntax7(self): + self.assertEqual( + self.ctx["testObjectTypeBinaryFormat7"].getSyntax(), 123458, "bad DEFVAL" + ) + + def testIntegerDefvalBinaryFormatSyntaxIsValue8(self): + self.assertFalse( + self.ctx["testObjectTypeBinaryFormat8"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultEnumTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectType OBJECT-TYPE + SYNTAX INTEGER { + enable(1), + disable(2) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { enable } + ::= { 1 3 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testEnumDefvalSyntax(self): + self.assertEqual(self.ctx["testObjectType"].getSyntax(), 1, "bad DEFVAL") + + +class DefaultEnumNegativeTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectType OBJECT-TYPE + SYNTAX INTEGER { + enable(-1), + disable(-2) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { disable } + ::= { 1 3 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testEnumDefvalNegativeSyntax(self): + self.assertEqual(self.ctx["testObjectType"].getSyntax(), -2, "bad DEFVAL") + + +class DefaultEnumFormatTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectTypeDecimal OBJECT-TYPE + SYNTAX INTEGER { unknown(0), enable(1), disable(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 0 } + ::= { 1 3 } + + testObjectTypeHex OBJECT-TYPE + SYNTAX INTEGER { unknown(0), enable(1), disable(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '01'H } + ::= { 1 4 } + + testObjectTypeBinary OBJECT-TYPE + SYNTAX INTEGER { unknown(0), enable(1), disable(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '00000010'B } + ::= { 1 5 } + + testObjectTypeString OBJECT-TYPE + SYNTAX INTEGER { unknown(0), enable(1), disable(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "0" } + ::= { 1 6 } + + testObjectTypeSymbol OBJECT-TYPE + SYNTAX INTEGER { unknown(0), enable(1), disable(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { testObjectTypeString } + ::= { 1 7 } + + testObjectTypeBrackets OBJECT-TYPE + SYNTAX INTEGER { enable(1), disable(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { disable } } + ::= { 1 8 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testEnumDefvalDecimalSyntax(self): + self.assertEqual(self.ctx["testObjectTypeDecimal"].getSyntax(), 0, "bad DEFVAL") + + def testEnumDefvalHexSyntax(self): + self.assertEqual(self.ctx["testObjectTypeHex"].getSyntax(), 1, "bad DEFVAL") + + def testEnumDefvalBinarySyntax(self): + self.assertEqual(self.ctx["testObjectTypeBinary"].getSyntax(), 2, "bad DEFVAL") + + def testEnumDefvalStringSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeString"].getSyntax().isValue, "bad DEFVAL" + ) + + def testEnumDefvalSymbolSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeSymbol"].getSyntax().isValue, "bad DEFVAL" + ) + + def testEnumDefvalBracketsSyntax(self): + self.assertEqual( + self.ctx["testObjectTypeBrackets"].getSyntax(), 2, "bad DEFVAL" + ) + + +class DefaultEnumValueTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectTypeBadDecimal OBJECT-TYPE + SYNTAX INTEGER { unknown(0), enable(1), disable(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { -1 } + ::= { 1 3 } + + testObjectTypeBadHex OBJECT-TYPE + SYNTAX INTEGER { unknown(0), enable(1), disable(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 'FF'H } + ::= { 1 4 } + + testObjectTypeBadBinary OBJECT-TYPE + SYNTAX INTEGER { unknown(0), enable(1), disable(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '00000011'B } + ::= { 1 5 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testEnumDefvalBadDecimalSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeBadDecimal"].getSyntax().isValue, "bad DEFVAL" + ) + + def testEnumDefvalBadHexSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeBadHex"].getSyntax().isValue, "bad DEFVAL" + ) + + def testEnumDefvalBadBinarySyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeBadBinary"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultStringTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectType OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "test value" } + ::= { 1 3 } + + testObjectTypeEmpty OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "" } + ::= { 1 4 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testStringDefvalSyntax(self): + self.assertEqual( + self.ctx["testObjectType"].getSyntax(), b"test value", "bad DEFVAL" + ) + + def testStringDefvalEmptySyntax(self): + self.assertEqual(self.ctx["testObjectTypeEmpty"].getSyntax(), b"", "bad DEFVAL") + + +class DefaultStringTextTestCase(unittest.TestCase): + R""" + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectType OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "\ntest + value\" } + ::= { 1 3 } + + END + """ + + def setUp(self): + docstring = textwrap.dedent(self.__class__.__doc__) + ast = parserFactory()().parse(docstring)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testStringDefvalTextSyntax(self): + self.assertEqual( + self.ctx["testObjectType"].getSyntax(), + b"\\ntest\nvalue\\", + "bad DEFVAL", + ) + + +class DefaultStringFormatTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectTypeDecimal OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 0 } + ::= { 1 3 } + + testObjectTypeHex OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 'abCD'H } + ::= { 1 4 } + + testObjectTypeBinary OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '000100100011010001010110'B } + ::= { 1 5 } + + testObjectTypeSymbol OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { testObjectTypeString } + ::= { 1 6 } + + testObjectTypeBrackets OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { string } } + ::= { 1 7 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testStringDefvalDecimalSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeDecimal"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalHexSyntax(self): + self.assertEqual( + self.ctx["testObjectTypeHex"].getSyntax(), + bytes((0xAB, 0xCD)), + "bad DEFVAL", + ) + + def testStringDefvalBinarySyntax(self): + self.assertEqual( + self.ctx["testObjectTypeBinary"].getSyntax(), + bytes((0x12, 0x34, 0x56)), + "bad DEFVAL", + ) + + def testStringDefvalSymbolSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeSymbol"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalBracketsSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeBrackets"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultStringValueTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectTypeEmptyHex OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { ''H } + ::= { 1 3 } + + testObjectTypeEmptyBinary OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { ''B } + ::= { 1 4 } + + testObjectTypePaddedHex OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '00abCD'H } + ::= { 1 5 } + + testObjectTypePaddedBinary OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '0000000000000000000100100011010001010110'B } + ::= { 1 6 } + + testObjectTypeUnpaddedHex OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '789'H } + ::= { 1 7 } + + testObjectTypeUnpaddedBinary OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '100100011'B } + ::= { 1 8 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testStringDefvalEmptyHexSyntax(self): + self.assertEqual( + self.ctx["testObjectTypeEmptyHex"].getSyntax(), bytes(), "bad DEFVAL" + ) + + def testStringDefvalEmptyBinarySyntax(self): + self.assertEqual( + self.ctx["testObjectTypeEmptyBinary"].getSyntax(), bytes(), "bad DEFVAL" + ) + + def testStringDefvalPaddedHexSyntax(self): + self.assertEqual( + self.ctx["testObjectTypePaddedHex"].getSyntax(), + bytes((0x00, 0xAB, 0xCD)), + "bad DEFVAL", + ) + + def testStringDefvalPaddedBinarySyntax(self): + self.assertEqual( + self.ctx["testObjectTypePaddedBinary"].getSyntax(), + bytes((0x00, 0x00, 0x12, 0x34, 0x56)), + "bad DEFVAL", + ) + + def testStringDefvalUnpaddedHexSyntax(self): + self.assertEqual( + self.ctx["testObjectTypeUnpaddedHex"].getSyntax(), + bytes((0x07, 0x89)), + "bad DEFVAL", + ) + + def testStringDefvalUnpaddedBinarySyntax(self): + self.assertEqual( + self.ctx["testObjectTypeUnpaddedBinary"].getSyntax(), + bytes((0x01, 0x23)), + "bad DEFVAL", + ) + + +class DefaultStringConstraintsTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectTypeString1 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (1..3)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "" } + ::= { 1 3 1 } + + testObjectTypeString2 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (1..3)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "a" } + ::= { 1 3 2 } + + testObjectTypeString3 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (1..3)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "ab" } + ::= { 1 3 3 } + + testObjectTypeString4 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (1..3)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "abc" } + ::= { 1 3 4 } + + testObjectTypeString5 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (1..3)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "abcd" } + ::= { 1 3 5 } + + testObjectTypeZeroString1 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "" } + ::= { 1 3 6 } + + testObjectTypeZeroString2 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "x" } + ::= { 1 3 7 } + + testObjectTypeHex1 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (4 | 6)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '414243'H } + ::= { 1 4 1 } + + testObjectTypeHex2 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (4 | 6)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '41424344'H } + ::= { 1 4 2 } + + testObjectTypeHex3 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (4 | 6)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '4142434445'H } + ::= { 1 4 3 } + + testObjectTypeHex4 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (4 | 6)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '414243444546'H } + ::= { 1 4 4 } + + testObjectTypeHex5 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (4 | 6)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '41424344454647'H } + ::= { 1 4 5 } + + testObjectTypeBinary1 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (3)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '0011000100110010'B } + ::= { 1 5 1 } + + testObjectTypeBinary2 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (3)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '001100010011001000110011'B } + ::= { 1 5 2 } + + testObjectTypeBinary3 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (3)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '00110001001100100011001100110100'B } + ::= { 1 5 3 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testStringDefvalStringSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeString1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalStringSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeString2"].getSyntax(), b"a", "bad DEFVAL" + ) + + def testStringDefvalStringSyntax3(self): + self.assertEqual( + self.ctx["testObjectTypeString3"].getSyntax(), b"ab", "bad DEFVAL" + ) + + def testStringDefvalStringSyntax4(self): + self.assertEqual( + self.ctx["testObjectTypeString4"].getSyntax(), b"abc", "bad DEFVAL" + ) + + def testStringDefvalStringSyntaxIsValue5(self): + self.assertFalse( + self.ctx["testObjectTypeString5"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalZeroStringSyntax1(self): + self.assertEqual( + self.ctx["testObjectTypeZeroString1"].getSyntax(), b"", "bad DEFVAL" + ) + + def testStringDefvalZeroStringSyntaxIsValue2(self): + self.assertFalse( + self.ctx["testObjectTypeZeroString2"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalHexSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeHex1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalHexSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeHex2"].getSyntax(), b"ABCD", "bad DEFVAL" + ) + + def testStringDefvalHexSyntaxIsValue3(self): + self.assertFalse( + self.ctx["testObjectTypeHex3"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalHexSyntax4(self): + self.assertEqual( + self.ctx["testObjectTypeHex4"].getSyntax(), b"ABCDEF", "bad DEFVAL" + ) + + def testStringDefvalHexSyntaxIsValue5(self): + self.assertFalse( + self.ctx["testObjectTypeHex5"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalBinarySyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeBinary1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalBinarySyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeBinary2"].getSyntax(), b"123", "bad DEFVAL" + ) + + def testStringDefvalBinarySyntaxIsValue3(self): + self.assertFalse( + self.ctx["testObjectTypeBinary3"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultStringConstraintsLayersTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI + TEXTUAL-CONVENTION + FROM SNMPv2-TC; + + SimpleConstrainedString ::= OCTET STRING (SIZE (2 | 4)) + + testObjectTypeSimple1 OBJECT-TYPE + SYNTAX SimpleConstrainedString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "ab" } + ::= { 1 3 1 } + + testObjectTypeSimple2 OBJECT-TYPE + SYNTAX SimpleConstrainedString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "abc" } + ::= { 1 3 2 } + + testObjectTypeSimple3 OBJECT-TYPE + SYNTAX SimpleConstrainedString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "abcd" } + ::= { 1 3 3 } + + -- The extra constraints are not correct, as they are not a subset of the + -- original constraints, but pysmi should deal with them properly. + testObjectTypeLayeredSimple1 OBJECT-TYPE + SYNTAX SimpleConstrainedString (SIZE (1..2)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "a" } + ::= { 1 3 4 } + + testObjectTypeLayeredSimple2 OBJECT-TYPE + SYNTAX SimpleConstrainedString (SIZE (1..2)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "ab" } + ::= { 1 3 5 } + + testObjectTypeLayeredSimple3 OBJECT-TYPE + SYNTAX SimpleConstrainedString (SIZE (1..2)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "abcd" } + ::= { 1 3 6 } + + TextualConstrainedString ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION "Test TC" + SYNTAX OCTET STRING (SIZE (0..1)) + + testObjectTypeTextual1 OBJECT-TYPE + SYNTAX TextualConstrainedString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "" } + ::= { 1 4 1 } + + testObjectTypeTextual2 OBJECT-TYPE + SYNTAX TextualConstrainedString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "a" } + ::= { 1 4 2 } + + testObjectTypeTextual3 OBJECT-TYPE + SYNTAX TextualConstrainedString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "ab" } + ::= { 1 4 3 } + + testObjectTypeLayeredTextual1 OBJECT-TYPE + SYNTAX TextualConstrainedString (SIZE (0 | 2)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "" } + ::= { 1 4 4 } + + testObjectTypeLayeredTextual2 OBJECT-TYPE + SYNTAX TextualConstrainedString (SIZE (0 | 2)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "a" } + ::= { 1 4 5 } + + testObjectTypeLayeredTextual3 OBJECT-TYPE + SYNTAX TextualConstrainedString (SIZE (0 | 2)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "ab" } + ::= { 1 4 6 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testStringDefvalSimpleSyntax1(self): + self.assertEqual( + self.ctx["testObjectTypeSimple1"].getSyntax(), b"ab", "bad DEFVAL" + ) + + def testStringDefvalSimpleSyntaxIsValue2(self): + self.assertFalse( + self.ctx["testObjectTypeSimple2"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalSimpleSyntax3(self): + self.assertEqual( + self.ctx["testObjectTypeSimple3"].getSyntax(), b"abcd", "bad DEFVAL" + ) + + def testStringDefvalLayeredSimpleSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeLayeredSimple1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalLayeredSimpleSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeLayeredSimple2"].getSyntax(), b"ab", "bad DEFVAL" + ) + + def testStringDefvalLayeredSimpleSyntaxIsValue3(self): + self.assertFalse( + self.ctx["testObjectTypeLayeredSimple3"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalTextualSyntax1(self): + self.assertEqual( + self.ctx["testObjectTypeTextual1"].getSyntax(), b"", "bad DEFVAL" + ) + + def testStringDefvalTextualSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeTextual2"].getSyntax(), b"a", "bad DEFVAL" + ) + + def testStringDefvalTextualSyntaxIsValue3(self): + self.assertFalse( + self.ctx["testObjectTypeTextual3"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalLayeredTextualSyntax1(self): + self.assertEqual( + self.ctx["testObjectTypeLayeredTextual1"].getSyntax(), b"", "bad DEFVAL" + ) + + def testStringDefvalLayeredTextualSyntaxIsValue2(self): + self.assertFalse( + self.ctx["testObjectTypeLayeredTextual2"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalLayeredTextualSyntaxIsValue3(self): + self.assertFalse( + self.ctx["testObjectTypeLayeredTextual3"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultStringConstraintsFormatTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectTypeHexFormat1 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('01'H..'02'H | '03'H)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "" } + ::= { 1 3 1 } + + testObjectTypeHexFormat2 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('01'H..'02'H | '03'H)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "a" } + ::= { 1 3 2 } + + testObjectTypeHexFormat3 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('01'H..'02'H | '03'H)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "ab" } + ::= { 1 3 3 } + + testObjectTypeHexFormat4 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('01'H..'02'H | '03'H)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "abc" } + ::= { 1 3 4 } + + testObjectTypeHexFormat5 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('01'H..'02'H | '03'H)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "abcd" } + ::= { 1 3 5 } + + testObjectTypeBinaryFormat1 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('00000001'B | '00001110'B..'00001111'B)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "" } + ::= { 1 4 1 } + + testObjectTypeBinaryFormat2 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('00000001'B | '00001110'B..'00001111'B)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "a" } + ::= { 1 4 2 } + + testObjectTypeBinaryFormat3 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('00000001'B | '00001110'B..'00001111'B)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "ab" } + ::= { 1 4 3 } + + testObjectTypeBinaryFormat4 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('00000001'B | '00001110'B..'00001111'B)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "this is a tes" } + ::= { 1 4 4 } + + testObjectTypeBinaryFormat5 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('00000001'B | '00001110'B..'00001111'B)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "this is a test" } + ::= { 1 4 5 } + + testObjectTypeBinaryFormat6 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('00000001'B | '00001110'B..'00001111'B)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "this is a test!" } + ::= { 1 4 6 } + + testObjectTypeBinaryFormat7 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE ('00000001'B | '00001110'B..'00001111'B)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "this is a test!?" } + ::= { 1 4 7 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testStringDefvalHexFormatSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeHexFormat1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalHexFormatSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeHexFormat2"].getSyntax(), b"a", "bad DEFVAL" + ) + + def testStringDefvalHexFormatSyntax3(self): + self.assertEqual( + self.ctx["testObjectTypeHexFormat3"].getSyntax(), b"ab", "bad DEFVAL" + ) + + def testStringDefvalHexFormatSyntax4(self): + self.assertEqual( + self.ctx["testObjectTypeHexFormat4"].getSyntax(), b"abc", "bad DEFVAL" + ) + + def testStringDefvalHexFormatSyntaxIsValue5(self): + self.assertFalse( + self.ctx["testObjectTypeHexFormat5"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalBinaryFormatSyntaxIsValue1(self): + self.assertFalse( + self.ctx["testObjectTypeBinaryFormat1"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalBinaryFormatSyntax2(self): + self.assertEqual( + self.ctx["testObjectTypeBinaryFormat2"].getSyntax(), b"a", "bad DEFVAL" + ) + + def testStringDefvalBinaryFormatSyntaxIsValue3(self): + self.assertFalse( + self.ctx["testObjectTypeBinaryFormat3"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalBinaryFormatSyntaxIsValue4(self): + self.assertFalse( + self.ctx["testObjectTypeBinaryFormat4"].getSyntax().isValue, "bad DEFVAL" + ) + + def testStringDefvalBinaryFormatSyntax5(self): + self.assertEqual( + self.ctx["testObjectTypeBinaryFormat5"].getSyntax(), + b"this is a test", + "bad DEFVAL", + ) + + def testStringDefvalBinaryFormatSyntax6(self): + self.assertEqual( + self.ctx["testObjectTypeBinaryFormat6"].getSyntax(), + b"this is a test!", + "bad DEFVAL", + ) + + def testStringDefvalBinaryFormatSyntaxIsValue7(self): + self.assertFalse( + self.ctx["testObjectTypeBinaryFormat7"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultBitsTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectType1 OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { present, absent } } + ::= { 1 3 } + + testObjectType2 OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { changed } } + ::= { 1 4 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testBitsDefvalSyntax1(self): + self.assertEqual( + self.ctx["testObjectType1"].getSyntax(), + bytes((0xC0,)), + "bad DEFVAL", + ) + + def testBitsDefvalSyntax2(self): + self.assertEqual( + self.ctx["testObjectType2"].getSyntax(), + bytes((0x20,)), + "bad DEFVAL", + ) + + +class DefaultBitsMultiOctetTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectType OBJECT-TYPE + SYNTAX BITS { a(0), b(1), c(2), d(3), e(4), f(5), g(6), h(7), i(8), j(9), k(10), l(11), m(12), n(13), o(14), p(15), q(16) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { b, c, m } } + ::= { 1 3 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testBitsDefvalMultiOctetSyntax(self): + self.assertEqual( + self.ctx["testObjectType"].getSyntax(), + bytes((0x60, 0x08)), + "bad DEFVAL", + ) + + +class DefaultBitsEmptySetTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectType OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { } } + ::= { 1 3 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testBitsDefvalEmptySyntax(self): + self.assertEqual( + self.ctx["testObjectType"].getSyntax(), + bytes((0x00,)), + "bad DEFVAL", + ) + + +class DefaultBitsFormatTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectTypeDecimal OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 1 } + ::= { 1 3 } + + testObjectTypeHex OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '04'H } + ::= { 1 4 } + + testObjectTypeBinary OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '00000111'B } + ::= { 1 5 } + + testObjectTypeString OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "0" } + ::= { 1 6 } + + testObjectTypeSymbol OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { present } + ::= { 1 7 } + + testObjectTypeBrackets OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { 0 } } + ::= { 1 8 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testBitsDefvalDecimalSyntax(self): + self.assertEqual( + self.ctx["testObjectTypeDecimal"].getSyntax(), + bytes((0x01,)), + "bad DEFVAL", + ) + + def testBitsDefvalHexSyntax(self): + self.assertEqual( + self.ctx["testObjectTypeHex"].getSyntax(), + bytes((0x04,)), + "bad DEFVAL", + ) + + def testBitsDefvalBinarySyntax(self): + self.assertEqual( + self.ctx["testObjectTypeBinary"].getSyntax(), + bytes((0x07,)), + "bad DEFVAL", + ) + + def testBitsDefvalStringSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeString"].getSyntax().isValue, "bad DEFVAL" + ) + + def testBitsDefvalSymbolSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeSymbol"].getSyntax().isValue, "bad DEFVAL" + ) + + def testBitsDefvalBracketsSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeBrackets"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultBitsValueTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectTypeDuplicateLabel OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { absent, absent } } + ::= { 1 3 } + + testObjectTypeBadLabel OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { unchanged } } + ::= { 1 4 } + + testObjectTypeOneBadLabel OBJECT-TYPE + SYNTAX BITS { present(0), absent(1), changed(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { present, unchanged, absent } } + ::= { 1 5 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testBitsDefvalDuplicateLabelSyntax(self): + self.assertEqual( + self.ctx["testObjectTypeDuplicateLabel"].getSyntax(), + bytes((0x40,)), + "bad DEFVAL", + ) + + def testBitsDefvalBadLabelSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeBadLabel"].getSyntax().isValue, "bad DEFVAL" + ) + + def testBitsDefvalOneBadLabelSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeOneBadLabel"].getSyntax().isValue, "bad DEFVAL" + ) + + +class DefaultObjectIdentifierTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE, Integer32 + FROM SNMPv2-SMI; + + testTargetObjectType OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test target object" + ::= { 1 3 } + + testObjectType OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { testTargetObjectType } + ::= { 1 4 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testObjectIdentifierDefvalSyntax(self): + self.assertEqual( + self.ctx["testObjectType"].getSyntax(), + (1, 3), + "bad DEFVAL", + ) + + +class DefaultObjectIdentifierInvalidTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectType OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { 0 0 } } + ::= { 1 3 } + + END + """ + + def testObjectIdentifierDefvalInvalidSyntax(self): + # The "{{0 0}}" type notation is invalid and currently not supported. + # This test verifies that such notations can be parsed at all, which + # is why the parsing is part of the actual test, and why successful + # instantiation of the syntax is enough here. + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + self.ctx["testObjectType"].getSyntax() + + +class DefaultObjectIdentifierHyphenTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + test-target-object-type OBJECT IDENTIFIER ::= { 1 3 } + global OBJECT IDENTIFIER ::= { 1 4 } -- a reserved Python keyword + + testObjectType1 OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { test-target-object-type } + ::= { 1 5 } + + testObjectType2 OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { global } + ::= { 1 6 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testObjectIdentifierDefvalHyphenSyntax(self): + self.assertEqual( + self.ctx["testObjectType1"].getSyntax(), + (1, 3), + "bad DEFVAL", + ) + + def testObjectIdentifierDefvalKeywordSyntax(self): + self.assertEqual( + self.ctx["testObjectType2"].getSyntax(), + (1, 4), + "bad DEFVAL", + ) + + +class DefaultObjectIdentifierFormatTestCase(unittest.TestCase): + """ + TEST-MIB DEFINITIONS ::= BEGIN + IMPORTS + OBJECT-TYPE + FROM SNMPv2-SMI; + + testObjectTypeDecimal OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { 0 } + ::= { 1 3 } + + testObjectTypeHex OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '00'H } + ::= { 1 4 } + + testObjectTypeBinary OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { '00000000'B } + ::= { 1 5 } + + testObjectTypeString OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { "0" } + ::= { 1 6 } + + testObjectTypeSymbol OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { doesNotExist } + ::= { 1 7 } + + testObjectTypeBrackets OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Test object" + DEFVAL { { testObjectTypeSymbol } } + ::= { 1 8 } + + END + """ + + def setUp(self): + ast = parserFactory()().parse(self.__class__.__doc__)[0] + mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) + self.mibInfo, pycode = PySnmpCodeGen().gen_code( + ast, {mibInfo.name: symtable}, genTexts=True + ) + codeobj = compile(pycode, "test", "exec") + + self.ctx = {"mibBuilder": MibBuilder()} + + exec(codeobj, self.ctx, self.ctx) + + def testObjectIdentifierDefvalDecimalSyntax(self): + self.assertFalse( + self.ctx["testObjectTypeDecimal"].getSyntax().isValue, "bad DEFVAL" + ) + + def testObjectIdentifierDefvalHexSyntax(self): + self.assertFalse( + self.ctx["testObjectTypeHex"].getSyntax().isValue, "bad DEFVAL" + ) + + def testObjectIdentifierDefvalBinarySyntax(self): + self.assertFalse( + self.ctx["testObjectTypeBinary"].getSyntax().isValue, "bad DEFVAL" + ) + + def testObjectIdentifierDefvalStringSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeString"].getSyntax().isValue, "bad DEFVAL" + ) + + def testObjectIdentifierDefvalSymbolSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeSymbol"].getSyntax().isValue, "bad DEFVAL" + ) + + def testObjectIdentifierDefvalBracketsSyntaxIsValue(self): + self.assertFalse( + self.ctx["testObjectTypeBrackets"].getSyntax().isValue, "bad DEFVAL" + ) + + +suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + +if __name__ == "__main__": + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/tests/test_objecttype_smiv2_pysnmp.py b/tests/test_objecttype_smiv2_pysnmp.py index ff15709..2b94e9e 100644 --- a/tests/test_objecttype_smiv2_pysnmp.py +++ b/tests/test_objecttype_smiv2_pysnmp.py @@ -253,190 +253,6 @@ def testObjectTypeUnits(self): self.assertEqual(self.ctx["testObjectType"].getUnits(), "", "bad UNITS") -class ObjectTypeIntegerDefaultTestCase(unittest.TestCase): - """ - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE, - Integer32 - FROM SNMPv2-SMI; - - testObjectType OBJECT-TYPE - SYNTAX Integer32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { 123456 } - ::= { 1 3 } - - END - """ - - def setUp(self): - ast = parserFactory()().parse(self.__class__.__doc__)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - def testObjectTypeSyntax(self): - self.assertEqual(self.ctx["testObjectType"].getSyntax(), 123456, "bad DEFVAL") - - -class ObjectTypeIntegerDefaultZeroTestCase(unittest.TestCase): - """ - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE, - Integer32 - FROM SNMPv2-SMI; - - testObjectType OBJECT-TYPE - SYNTAX Integer32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { 0 } - ::= { 1 3 } - - END - """ - - def setUp(self): - ast = parserFactory()().parse(self.__class__.__doc__)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - def testObjectTypeSyntax(self): - self.assertEqual(self.ctx["testObjectType"].getSyntax(), 0, "bad DEFVAL") - - -class ObjectTypeEnumDefaultTestCase(unittest.TestCase): - """ - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE - FROM SNMPv2-SMI; - - testObjectType OBJECT-TYPE - SYNTAX INTEGER { - enable(1), - disable(2) - } - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { enable } - ::= { 1 3 } - - END - """ - - def setUp(self): - ast = parserFactory()().parse(self.__class__.__doc__)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - def testObjectTypeSyntax(self): - self.assertEqual(self.ctx["testObjectType"].getSyntax(), 1, "bad DEFVAL") - - -class ObjectTypeStringDefaultTestCase(unittest.TestCase): - """ - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE - FROM SNMPv2-SMI; - - testObjectType OBJECT-TYPE - SYNTAX OCTET STRING - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { "test value" } - ::= { 1 3 } - - END - """ - - def setUp(self): - ast = parserFactory()().parse(self.__class__.__doc__)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - # TODO: pyasn1 does not like OctetString.defaultValue - def testObjectTypeSyntax(self): - self.assertEqual( - self.ctx["testObjectType"].getSyntax(), b"test value", "bad DEFVAL" - ) - - -class ObjectTypeStringDefaultTextTestCase(unittest.TestCase): - R""" - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE - FROM SNMPv2-SMI; - - testObjectType OBJECT-TYPE - SYNTAX OCTET STRING - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { "\ntest - value\" } - ::= { 1 3 } - - END - """ - - def setUp(self): - docstring = textwrap.dedent(self.__class__.__doc__) - ast = parserFactory()().parse(docstring)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - def testObjectTypeSyntax(self): - self.assertEqual( - self.ctx["testObjectType"].getSyntax(), - b"\\ntest\nvalue\\", - "bad DEFVAL", - ) - - class ObjectTypeWithIntegerConstraintTestCase(unittest.TestCase): """ TEST-MIB DEFINITIONS ::= BEGIN @@ -589,258 +405,6 @@ def testObjectTypeSyntax(self): ) -class ObjectTypeBitsDefaultTestCase(unittest.TestCase): - """ - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE - FROM SNMPv2-SMI; - - testObjectType OBJECT-TYPE - SYNTAX BITS { present(0), absent(1), changed(2) } - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { { present, absent } } - ::= { 1 3 } - - END - """ - - def setUp(self): - ast = parserFactory()().parse(self.__class__.__doc__)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - def testObjectTypeSyntax(self): - self.assertEqual( - self.ctx["testObjectType"].getSyntax(), - bytes((0xC0,)), - "bad DEFVAL", - ) - - -class ObjectTypeBitsDefaultMultiOctetTestCase(unittest.TestCase): - """ - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE - FROM SNMPv2-SMI; - - testObjectType OBJECT-TYPE - SYNTAX BITS { a(0), b(1), c(2), d(3), e(4), f(5), g(6), h(7), i(8), j(9), k(10), l(11), m(12), n(13), o(14), p(15), q(16) } - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { { b, c, m } } - ::= { 1 3 } - - END - """ - - def setUp(self): - ast = parserFactory()().parse(self.__class__.__doc__)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - def testObjectTypeSyntax(self): - self.assertEqual( - self.ctx["testObjectType"].getSyntax(), - bytes((0x60, 0x08)), - "bad DEFVAL", - ) - - -class ObjectTypeBitsDefaultEmptySetTestCase(unittest.TestCase): - """ - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE - FROM SNMPv2-SMI; - - testObjectType OBJECT-TYPE - SYNTAX BITS { present(0), absent(1), changed(2) } - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { { } } - ::= { 1 3 } - - END - """ - - def setUp(self): - ast = parserFactory()().parse(self.__class__.__doc__)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - def testObjectTypeSyntax(self): - self.assertEqual( - self.ctx["testObjectType"].getSyntax(), - bytes((0x00,)), - "bad DEFVAL", - ) - - -class ObjectTypeObjectIdentifierTestCase(unittest.TestCase): - """ - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE, Integer32 - FROM SNMPv2-SMI; - - testTargetObjectType OBJECT-TYPE - SYNTAX Integer32 - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test target object" - ::= { 1 3 } - - testObjectType OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { testTargetObjectType } - ::= { 1 4 } - - END - """ - - def setUp(self): - ast = parserFactory()().parse(self.__class__.__doc__)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - def testObjectTypeSyntax(self): - self.assertEqual( - self.ctx["testObjectType"].getSyntax(), - (1, 3), - "bad DEFVAL", - ) - - -class ObjectTypeObjectIdentifierInvalidTestCase(unittest.TestCase): - """ - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE - FROM SNMPv2-SMI; - - testObjectType OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { { 0 0 } } - ::= { 1 3 } - - END - """ - - def testObjectTypeSyntax(self): - # The "{{0 0}}" type notation is invalid and currently not supported. - # This test verifies that such notations can be parsed at all, which - # is why the parsing is part of the actual test, and why successful - # instantiation of the syntax is enough here. - ast = parserFactory()().parse(self.__class__.__doc__)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - self.ctx["testObjectType"].getSyntax() - - -class ObjectTypeObjectIdentifierHyphenTestCase(unittest.TestCase): - """ - TEST-MIB DEFINITIONS ::= BEGIN - IMPORTS - OBJECT-TYPE - FROM SNMPv2-SMI; - - test-target-object-type OBJECT IDENTIFIER ::= { 1 3 } - global OBJECT IDENTIFIER ::= { 1 4 } -- a reserved Python keyword - - testObjectType1 OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { test-target-object-type } - ::= { 1 5 } - - testObjectType2 OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - MAX-ACCESS read-only - STATUS current - DESCRIPTION "Test object" - DEFVAL { global } - ::= { 1 6 } - - END - """ - - def setUp(self): - ast = parserFactory()().parse(self.__class__.__doc__)[0] - mibInfo, symtable = SymtableCodeGen().gen_code(ast, {}, genTexts=True) - self.mibInfo, pycode = PySnmpCodeGen().gen_code( - ast, {mibInfo.name: symtable}, genTexts=True - ) - codeobj = compile(pycode, "test", "exec") - - self.ctx = {"mibBuilder": MibBuilder()} - - exec(codeobj, self.ctx, self.ctx) - - def testObjectTypeSyntax1(self): - self.assertEqual( - self.ctx["testObjectType1"].getSyntax(), - (1, 3), - "bad DEFVAL", - ) - - def testObjectTypeSyntax2(self): - self.assertEqual( - self.ctx["testObjectType2"].getSyntax(), - (1, 4), - "bad DEFVAL", - ) - - class ObjectTypeMibTableTestCase(unittest.TestCase): """ TEST-MIB DEFINITIONS ::= BEGIN