def test_div_simplified(self) -> None: self.assertEqual( Div(Value('X'), Number(1)).simplified(), Div(Value('X'), Number(1))) self.assertEqual(Div(Number(6), Number(2)).simplified(), Number(3)) self.assertEqual( Div(Number(9), Number(2)).simplified(), Div(Number(9), Number(2)))
def test_message_incoming(self) -> None: self.assertEqual(ETHERNET_FRAME.incoming(INITIAL), []) self.assertEqual( ETHERNET_FRAME.incoming(Field("Type_Length")), [ Link( Field("Type_Length_TPID"), Field("Type_Length"), NotEqual(Variable("Type_Length_TPID"), Number(0x8100, 16)), first=First("Type_Length_TPID"), ), Link(Field("TCI"), Field("Type_Length")), ], ) self.assertEqual( ETHERNET_FRAME.incoming(FINAL), [ Link( Field("Payload"), FINAL, And( GreaterEqual(Div(Length("Payload"), Number(8)), Number(46)), LessEqual(Div(Length("Payload"), Number(8)), Number(1500)), ), ) ], )
def test_distributivity_simplified(self) -> None: self.assertEqual( Add(Sub(Value('X'), Add(Value('X'), Number(1))), Add(Value('X'), Number(1))).simplified(), Value('X')) self.assertEqual( Div(Add(Mul(Value('X'), Number(8)), Number(144)), Number(8)).simplified(), Add(Value('X'), Number(18))) self.assertEqual( Div(Sub(Mul(Value('X'), Number(8)), Number(148)), Number(8)).simplified(), Add(Value('X'), Div(Number(-148), Number(8))))
def test_expr_variables_duplicates(self) -> None: self.assertEqual( And(Variable("X"), Variable("Y"), Variable("X")).variables(), [Variable("X"), Variable("Y")], ) self.assertEqual( Or(Variable("X"), Variable("Y"), Variable("X")).variables(), [Variable("X"), Variable("Y")], ) self.assertEqual( Add(Variable("X"), Variable("Y"), Variable("X")).variables(), [Variable("X"), Variable("Y")], ) self.assertEqual( Mul(Variable("X"), Variable("Y"), Variable("X")).variables(), [Variable("X"), Variable("Y")], ) self.assertEqual(Sub(Variable("X"), Variable("X")).variables(), [Variable("X")]) self.assertEqual(Div(Variable("X"), Variable("X")).variables(), [Variable("X")]) self.assertEqual( Or( Greater(Variable("X"), Number(42)), And(TRUE, Less(Variable("X"), Number(1))) ).variables(), [Variable("X")], )
def public_context_predicate() -> Expr: return And( GreaterEqual(Call(const.TYPES_BYTE_INDEX, [Variable("First")]), Variable("Buffer_First")), LessEqual(Call(const.TYPES_BYTE_INDEX, [Variable("Last")]), Variable("Buffer_Last")), LessEqual(Variable("First"), Variable("Last")), LessEqual(Variable("Last"), Div(Last(const.TYPES_BIT_INDEX), Number(2))), )
def parse_mathematical_expression(string: str, location: int, tokens: ParseResults) -> Expr: result: List[Expr] = tokens[0] while len(result) > 1: left = result.pop(0) operator = result.pop(0) right = result.pop(0) assert left.location, f'expression "{left}" without location' assert right.location, f'expression "{right}" without location' assert left.location.source == right.location.source, "expression with different source" locn = Location(left.location.start, left.location.source, left.location.end) expression: Expr if operator == "+": expression = Add(left, right) expression.location = locn elif operator == "-": expression = Sub(left, right, locn) elif operator == "*": expression = Mul(left, right) expression.location = locn elif operator == "/": expression = Div(left, right, locn) elif operator == "**": expression = Pow(left, right, locn) else: raise ParseFatalException(string, location, "unexpected mathematical operator") result.insert(0, expression) return result[0]
def enumeration_functions(enum: Enumeration) -> List[Subprogram]: common_precondition = And( Less(Value('Offset'), Number(8)), Equal( Length('Buffer'), Add( Div(Add(Size(enum.base_name), Value('Offset'), Number(-1)), Number(8)), Number(1)))) control_expression = LogCall( f'Convert_To_{enum.base_name} (Buffer, Offset)') validation_expression: Expr if enum.always_valid: validation_expression = Value('True') else: validation_cases: List[Tuple[Expr, Expr]] = [] validation_cases.extend( (value, Value('True')) for value in enum.literals.values()) validation_cases.append((Value('others'), Value('False'))) validation_expression = CaseExpression(control_expression, validation_cases) validation_function = ExpressionFunction( f'Valid_{enum.name}', 'Boolean', [('Buffer', 'Types.Bytes'), ('Offset', 'Natural')], validation_expression, [Precondition(common_precondition)]) function_name = f'Convert_To_{enum.name}' parameters = [('Buffer', 'Types.Bytes'), ('Offset', 'Natural')] precondition = Precondition( And(common_precondition, LogCall(f'Valid_{enum.name} (Buffer, Offset)'))) conversion_cases: List[Tuple[Expr, Expr]] = [] conversion_function: Subprogram if enum.always_valid: conversion_cases.extend((value, Aggregate(Value('True'), Value(key))) for key, value in enum.literals.items()) conversion_cases.append( (Value('others'), Aggregate(Value('False'), Value('Raw')))) conversion_function = Function( function_name, enum.name, parameters, [Declaration('Raw', enum.base_name, control_expression)], [ReturnStatement(CaseExpression(Value('Raw'), conversion_cases))], [precondition]) else: conversion_cases.extend( (value, Value(key)) for key, value in enum.literals.items()) conversion_cases.append( (Value('others'), LogCall(f'Unreachable_{enum.name}'))) conversion_function = ExpressionFunction( function_name, enum.name, parameters, CaseExpression(control_expression, conversion_cases), [precondition]) return [validation_function, conversion_function]
def bounded_composite_setter_preconditions(message: Message, field: Field) -> Sequence[Expr]: return [ Call( "Field_Condition", [ Variable("Ctx"), NamedAggregate(("Fld", Variable(field.affixed_name))) ] + ([Variable("Length")] if common.length_dependent_condition(message) else []), ), GreaterEqual( Call("Available_Space", [Variable("Ctx"), Variable(field.affixed_name)]), Variable("Length"), ), LessEqual( Add( Call("Field_First", [Variable("Ctx"), Variable(field.affixed_name)]), Variable("Length"), ), Div(Last(const.TYPES_BIT_INDEX), Number(2)), ), Or(*[ And( *[ Call("Valid", [Variable("Ctx"), Variable(field.affixed_name)]) for field in message.fields if Variable(field.name) in l.condition.variables() ], l.condition.substituted( mapping={ Variable(field.name): Call(f"Get_{field.name}", [Variable("Ctx")]) for field in message.fields if Variable(field.name) in l.condition.variables() }), ) for l in message.incoming(field) if Last("Message") in l.length ]), Equal( Mod( Call("Field_First", [Variable("Ctx"), Variable(field.affixed_name)]), Size(const.TYPES_BYTE), ), Number(1), ), Equal( Mod(Variable("Length"), Size(const.TYPES_BYTE)), Number(0), ), ]
def buffer_constraints(last: MathExpr) -> LogExpr: last = last.simplified() index_constraint = LessEqual(First('Buffer'), Div(Last('Types.Index_Type'), Number(2))) if last != Last('Buffer'): length_constraint = GreaterEqual( Length('Buffer'), Add(last, -First('Buffer'), Number(1))) return And(length_constraint, index_constraint) return index_constraint
def setter_preconditions(self, field: Field) -> Sequence[Expr]: return [ VALID_CONTEXT, Not(Constrained("Ctx")), Call("Has_Buffer", [Name("Ctx")]), Call("Valid_Next", [Name("Ctx"), Name(field.affixed_name)]), LessEqual( Call("Field_Last", [Name("Ctx"), Name(field.affixed_name)]), Div(Last(self.types.bit_index), Number(2)), ), ]
def setter_preconditions(field: Field) -> Sequence[Expr]: return [ Not(Constrained("Ctx")), Call("Has_Buffer", [Variable("Ctx")]), Call("Valid_Next", [Variable("Ctx"), Variable(field.affixed_name)]), LessEqual( Call("Field_Last", [Variable("Ctx"), Variable(field.affixed_name)]), Div(Last(const.TYPES_BIT_INDEX), Number(2)), ), ]
def create_ethernet_pdu() -> PDU: uint48 = ModularInteger('UINT48', Pow(Number(2), Number(48))) uint16 = RangeInteger('UINT16', Number(0), Sub(Pow(Number(2), Number(16)), Number(1)), Number(16)) payload_array = Array('Payload_Array') initial = InitialNode() destination = Node('Destination', uint48) source = Node('Source', uint48) tpid = Node('TPID', uint16) tci = Node('TCI', uint16) ether_type = Node('EtherType', uint16) payload = Node('Payload', payload_array) initial.edges = [Edge(destination)] destination.edges = [Edge(source)] source.edges = [Edge(tpid)] tpid.edges = [Edge(tci, Equal(Value('TPID'), Number(0x8100))), Edge(ether_type, NotEqual(Value('TPID'), Number(0x8100)), first=First('TPID'))] tci.edges = [Edge(ether_type)] ether_type.edges = [Edge(payload, LessEqual(Value('EtherType'), Number(1500)), Mul(LengthValue('EtherType'), Number(8))), Edge(payload, GreaterEqual(Value('EtherType'), Number(1536)), Sub(Last('Message'), Last('EtherType')))] payload.edges = [Edge(FINAL, And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)), LessEqual(Div(Length('Payload'), Number(8)), Number(1500))))] return PDU('Ethernet.Frame', initial)
def parse_mathematical_expression(string: str, location: int, tokens: list) -> MathExpr: result: List[MathExpr] = tokens[0] while len(result) > 1: left = result.pop(0) operator = result.pop(0) right = result.pop(0) expression: MathExpr if operator == '+': expression = Add(left, right) elif operator == '-': expression = Sub(left, right) elif operator == '*': expression = Mul(left, right) elif operator == '/': expression = Div(left, right) elif operator == '**': expression = Pow(left, right) else: raise ParseFatalException(string, location, 'unexpected mathematical operator') result.insert(0, expression) return result[0]
def parse_mathematical_expression(string: str, location: int, tokens: ParseResults) -> Expr: result: List[Expr] = tokens[0] while len(result) > 1: left = result.pop(0) operator = result.pop(0) right = result.pop(0) expression: Expr if operator == "+": expression = Add(left, right) elif operator == "-": expression = Sub(left, right) elif operator == "*": expression = Mul(left, right) elif operator == "/": expression = Div(left, right) elif operator == "**": expression = Pow(left, right) else: raise ParseFatalException(string, location, "unexpected mathematical operator") result.insert(0, expression) return result[0]
def bounded_composite_setter_preconditions( self, message: Message, field: Field ) -> Sequence[Expr]: return [ Call( "Field_Condition", [Name("Ctx"), NamedAggregate(("Fld", Name(field.affixed_name)))] + ([Name("Length")] if length_dependent_condition(message) else []), ), GreaterEqual( Call("Available_Space", [Name("Ctx"), Name(field.affixed_name)]), Name("Length"), ), LessEqual( Add(Call("Field_First", [Name("Ctx"), Name(field.affixed_name)]), Name("Length"),), Div(Last(self.types.bit_index), Number(2)), ), Or( *[ And( *[ Call("Valid", [Name("Ctx"), Name(field.affixed_name)]) for field in message.fields if Variable(field.name) in l.condition.variables() ], l.condition.simplified( { Variable(field.name): Call(f"Get_{field.name}", [Name("Ctx")]) for field in message.fields if Variable(field.name) in l.condition.variables() } ), ) for l in message.incoming(field) if Last("Message") in l.length ] ), ]
def test_div_simplified() -> None: assert Div(Variable("X"), Number(1)).simplified() == Div(Variable("X"), Number(1)) assert Div(Number(6), Number(2)).simplified() == Number(3) assert Div(Number(9), Number(2)).simplified() == Div(Number(9), Number(2))
def test_ethernet_spec() -> None: spec = { "Ethernet": Specification( ContextSpec([]), PackageSpec( "Ethernet", [ ModularInteger("__PACKAGE__.Address", Pow(Number(2), Number(48))), RangeInteger( "__PACKAGE__.Type_Length", Number(46), Sub(Pow(Number(2), Number(16)), Number(1)), Number(16), ), RangeInteger( "__PACKAGE__.TPID", Number(0x8100, 16), Number(0x8100, 16), Number(16) ), ModularInteger("__PACKAGE__.TCI", Pow(Number(2), Number(16))), MessageSpec( "__PACKAGE__.Frame", [ Component("Destination", "Address"), Component("Source", "Address"), Component( "Type_Length_TPID", "Type_Length", [ Then( "TPID", First("Type_Length_TPID"), UNDEFINED, Equal(Variable("Type_Length_TPID"), Number(33024, 16)), ), Then( "Type_Length", First("Type_Length_TPID"), UNDEFINED, NotEqual(Variable("Type_Length_TPID"), Number(33024, 16)), ), ], ), Component("TPID", "TPID"), Component("TCI", "TCI"), Component( "Type_Length", "Type_Length", [ Then( "Payload", UNDEFINED, Mul(Variable("Type_Length"), Number(8)), LessEqual(Variable("Type_Length"), Number(1500)), ), Then( "Payload", UNDEFINED, Sub(Last("Message"), Last("Type_Length")), GreaterEqual(Variable("Type_Length"), Number(1536)), ), ], ), Component( "Payload", "Opaque", [ Then( condition=And( GreaterEqual( Div(Length("Payload"), Number(8)), Number(46), ), LessEqual( Div(Length("Payload"), Number(8)), Number(1500), ), ), ) ], ), ], ), ], ), ) } assert_specifications_files([f"{SPECDIR}/ethernet.rflx"], spec)
def test_div(self) -> None: self.assertEqual( Div(Number(6), Number(3)).z3expr(), z3.IntVal(6) / z3.IntVal(3))
def test_div() -> None: assert Div(Number(6), Number(3)).z3expr() == z3.IntVal(6) / z3.IntVal(3)
def test_div_variables(self) -> None: self.assertEqual(Div(Variable("X"), Name("Y")).variables(), [Variable("X")]) self.assertEqual( Div(Variable("X"), Variable("Y")).variables(), [Variable("X"), Variable("Y")] )
def test_div_neg(self) -> None: self.assertEqual(-Div(Variable("X"), Number(1)), Div(Variable("X", True), Number(1)))
def test_term_to_bytes(self) -> None: self.assertEqual( Add(Mul(Number(8), Number(48)), Sub(Value('X'), Number(80)), Div(Number(8), Number(24))).to_bytes(), Add(Mul(Number(1), Number(6)), Sub(Value('X'), Number(10)), Div(Number(1), Number(3))))
def test_div_to_bytes(self) -> None: self.assertEqual( Div(Value('X'), Number(8)).to_bytes(), Div(Value('X'), Number(1)))
def test_div_variables() -> None: assert Div(Variable("X"), Call("Y")).variables() == [Variable("X")] assert Div(Variable("X"), Variable("Y")).variables() == [Variable("X"), Variable("Y")]
def create_composite_setter_procedures(self, message: Message) -> UnitPart: def specification(field: Field) -> ProcedureSpecification: return ProcedureSpecification(f"Set_{field.name}", [InOutParameter(["Ctx"], "Context")]) def specification_bounded(field: Field) -> ProcedureSpecification: return ProcedureSpecification( f"Set_Bounded_{field.name}", [ InOutParameter(["Ctx"], "Context"), Parameter(["Length"], const.TYPES_BIT_LENGTH) ], ) def formal_parameters( field: Field) -> Sequence[FormalSubprogramDeclaration]: return [ FormalSubprogramDeclaration( ProcedureSpecification( f"Process_{field.name}", [OutParameter([field.name], const.TYPES_BYTES)], )), FormalSubprogramDeclaration( FunctionSpecification( "Valid_Length", "Boolean", [Parameter(["Length"], const.TYPES_LENGTH)], )), ] return UnitPart( [ SubprogramDeclaration( specification(f), [ Precondition( AndThen( *self.setter_preconditions(f), *self.unbounded_composite_setter_preconditions( message, f), Call( "Valid_Length", [ Call( const.TYPES_LENGTH, [ Div( Call( "Field_Length", [ Variable("Ctx"), Variable( f.affixed_name) ], ), Size(const.TYPES_BYTE), ), ], ), ], ), )), Postcondition( And( *self.composite_setter_postconditions( message, f), )), ], formal_parameters(f), ) for f, t in message.types.items() if isinstance(t, Opaque) and unbounded_setter_required(message, f) ] + [ SubprogramDeclaration( specification_bounded(f), [ Precondition( AndThen( *self.setter_preconditions(f), *self.bounded_composite_setter_preconditions( message, f), Call( "Valid_Length", [ Call( const.TYPES_LENGTH, [ Div(Variable("Length"), Size(const.TYPES_BYTE)) ], ) ], ), )), Postcondition( And( *self.composite_setter_postconditions( message, f), )), ], formal_parameters(f), ) for f, t in message.types.items() if isinstance(t, Opaque) and bounded_setter_required(message, f) ], [ SubprogramBody( specification(f), [ *common.field_bit_location_declarations( Variable(f.affixed_name)), ExpressionFunctionDeclaration( FunctionSpecification("Buffer_First", const.TYPES_INDEX), Call(const.TYPES_BYTE_INDEX, [Variable("First")]), ), ExpressionFunctionDeclaration( FunctionSpecification("Buffer_Last", const.TYPES_INDEX), Call(const.TYPES_BYTE_INDEX, [Variable("Last")]), ), ], [ CallStatement(f"Initialize_{f.name}", [Variable("Ctx")]), CallStatement( f"Process_{f.name}", [ Slice( Selected(Variable("Ctx.Buffer"), "all"), Variable("Buffer_First"), Variable("Buffer_Last"), ), ], ), ], ) for f, t in message.types.items() if isinstance(t, Opaque) and unbounded_setter_required(message, f) ] + [ SubprogramBody( specification_bounded(f), [ ObjectDeclaration( ["First"], const.TYPES_BIT_INDEX, Call("Field_First", [Variable("Ctx"), Variable(f.affixed_name)]), True, ), ObjectDeclaration( ["Last"], const.TYPES_BIT_INDEX, Add(Variable("First"), Variable("Length"), -Number(1)), True, ), ExpressionFunctionDeclaration( FunctionSpecification("Buffer_First", const.TYPES_INDEX), Call(const.TYPES_BYTE_INDEX, [Variable("First")]), ), ExpressionFunctionDeclaration( FunctionSpecification("Buffer_Last", const.TYPES_INDEX), Call(const.TYPES_BYTE_INDEX, [Variable("Last")]), ), ], [ CallStatement(f"Initialize_Bounded_{f.name}", [Variable("Ctx"), Variable("Length")]), CallStatement( f"Process_{f.name}", [ Slice( Selected(Variable("Ctx.Buffer"), "all"), Variable("Buffer_First"), Variable("Buffer_Last"), ), ], ), ], ) for f, t in message.types.items() if isinstance(t, Opaque) and bounded_setter_required(message, f) ], )
Link( Field("Type_Length"), Field("Payload"), LessEqual(Variable("Type_Length"), Number(1500)), Mul(Variable("Type_Length"), Number(8)), ), Link( Field("Type_Length"), Field("Payload"), GreaterEqual(Variable("Type_Length"), Number(1536)), ), Link( Field("Payload"), FINAL, And( GreaterEqual(Div(Size("Payload"), Number(8)), Number(46)), LessEqual(Div(Size("Payload"), Number(8)), Number(1500)), ), ), ], { Field("Destination"): ETHERNET_ADDRESS, Field("Source"): ETHERNET_ADDRESS, Field("Type_Length_TPID"): ETHERNET_TYPE_LENGTH, Field("TPID"): ETHERNET_TPID, Field("TCI"): ETHERNET_TCI, Field("Type_Length"): ETHERNET_TYPE_LENGTH, Field("Payload"): OPAQUE, }, skip_proof=True, )
def context_predicate(self, message: Message, composite_fields: Sequence[Field]) -> Expr: def valid_predecessors_invariant() -> Expr: return AndThen( *[ If( [ ( Call( "Structural_Valid", [Indexed("Cursors", Name(f.affixed_name))] ), Or( *[ AndThen( Call( "Structural_Valid" if l.source in composite_fields else "Valid", [Indexed("Cursors", Name(l.source.affixed_name))], ), Equal( Selected( Indexed("Cursors", Name(f.affixed_name)), "Predecessor", ), Name(l.source.affixed_name), ), l.condition, ).simplified(self.substitution(message, False)) for l in message.incoming(f) ] ), ) ] ) for f in message.fields if f not in message.direct_successors(INITIAL) ] ) def invalid_successors_invariant() -> Expr: return AndThen( *[ If( [ ( AndThen( *[ Call("Invalid", [Indexed("Cursors", Name(p.affixed_name))]) for p in message.direct_predecessors(f) ] ), Call("Invalid", [Indexed("Cursors", Name(f.affixed_name))]), ) ] ) for f in message.fields if f not in message.direct_successors(INITIAL) ] ) return AndThen( If( [ ( NotEqual(Name(Name("Buffer")), NULL), And( Equal(First(Name("Buffer")), Name(Name("Buffer_First"))), Equal(Last(Name("Buffer")), Name(Name("Buffer_Last"))), ), ) ] ), GreaterEqual( Call(self.types.byte_index, [Name(Name("First"))]), Name(Name("Buffer_First")) ), LessEqual(Call(self.types.byte_index, [Name(Name("Last"))]), Name(Name("Buffer_Last"))), LessEqual(Name(Name("First")), Name(Name("Last"))), LessEqual(Name(Name("Last")), Div(Last(self.types.bit_index), Number(2))), ForAllIn( "F", ValueRange(First("Field"), Last("Field")), If( [ ( Call("Structural_Valid", [Indexed(Name("Cursors"), Name("F"))]), And( GreaterEqual( Selected(Indexed(Name("Cursors"), Name("F")), "First"), Name(Name("First")), ), LessEqual( Selected(Indexed(Name("Cursors"), Name("F")), "Last"), Name(Name("Last")), ), LessEqual( Selected(Indexed(Name("Cursors"), Name("F")), "First"), Add( Selected(Indexed(Name("Cursors"), Name("F")), "Last"), Number(1), ), ), Equal( Selected( Selected(Indexed(Name("Cursors"), Name("F")), "Value"), "Fld", ), Name("F"), ), ), ) ] ), ), valid_predecessors_invariant(), invalid_successors_invariant(), self.message_structure_invariant(message, prefix=False), )
def create_ethernet_frame() -> Message: address_type = ModularInteger("Ethernet.Address", Pow(Number(2), Number(48))) type_length_type = RangeInteger("Ethernet.Type_Length", Number(46), Sub(Pow(Number(2), Number(16)), Number(1)), Number(16)) tpid_type = RangeInteger("Ethernet.TPID", Number(0x8100, 16), Number(0x8100, 16), Number(16)) tci_type = ModularInteger("Ethernet.TCI", Pow(Number(2), Number(16))) structure = [ Link(INITIAL, Field("Destination")), Link(Field("Destination"), Field("Source")), Link(Field("Source"), Field("Type_Length_TPID")), Link( Field("Type_Length_TPID"), Field("TPID"), Equal(Variable("Type_Length_TPID"), Number(0x8100, 16)), first=First("Type_Length_TPID"), ), Link( Field("Type_Length_TPID"), Field("Type_Length"), NotEqual(Variable("Type_Length_TPID"), Number(0x8100, 16)), first=First("Type_Length_TPID"), ), Link(Field("TPID"), Field("TCI")), Link(Field("TCI"), Field("Type_Length")), Link( Field("Type_Length"), Field("Payload"), LessEqual(Variable("Type_Length"), Number(1500)), Mul(Variable("Type_Length"), Number(8)), ), Link( Field("Type_Length"), Field("Payload"), GreaterEqual(Variable("Type_Length"), Number(1536)), Sub(Last("Message"), Last("Type_Length")), ), Link( Field("Payload"), FINAL, And( GreaterEqual(Div(Length("Payload"), Number(8)), Number(46)), LessEqual(Div(Length("Payload"), Number(8)), Number(1500)), ), ), ] types = { Field("Destination"): address_type, Field("Source"): address_type, Field("Type_Length_TPID"): type_length_type, Field("TPID"): tpid_type, Field("TCI"): tci_type, Field("Type_Length"): type_length_type, Field("Payload"): Payload(), } return Message("Ethernet.Frame", structure, types)
def test_pdu_fields_ethernet(self) -> None: expected = OrderedDict([ ('Destination', Field('Destination', ModularInteger('UINT48', Pow(Number(2), Number(48))), TRUE, { '0': Variant( [], TRUE, { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47) }) })), ('Source', Field('Source', ModularInteger('UINT48', Pow(Number(2), Number(48))), TRUE, { '00': Variant( [ ('Destination', '0') ], TRUE, { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95) }) })), ('TPID', Field('TPID', RangeInteger('UINT16', Number(0), Sub(Pow(Number(2), Number(16)), Number(1)), Number(16)), Or(NotEqual(Value('TPID'), Number(0x8100)), Equal(Value('TPID'), Number(0x8100))), { '000': Variant( [ ('Destination', '0'), ('Source', '00') ], TRUE, { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111) }) })), ('TCI', Field('TCI', RangeInteger('UINT16', Number(0), Sub(Pow(Number(2), Number(16)), Number(1)), Number(16)), TRUE, { '0000': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000') ], Equal(Value('TPID'), Number(0x8100)), { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('TCI'): Number(16), First('TCI'): Number(112), Last('TCI'): Number(127) }) })), ('EtherType', Field('EtherType', RangeInteger('UINT16', Number(0), Sub(Pow(Number(2), Number(16)), Number(1)), Number(16)), Or(GreaterEqual(Value('EtherType'), Number(1536)), LessEqual(Value('EtherType'), Number(1500))), { '00000': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000'), ('TCI', '0000') ], TRUE, { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('TCI'): Number(16), First('TCI'): Number(112), Last('TCI'): Number(127), Length('EtherType'): Number(16), First('EtherType'): Number(128), Last('EtherType'): Number(143) }), '0001': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000') ], NotEqual(Value('TPID'), Number(0x8100)), { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('EtherType'): Number(16), First('EtherType'): Number(96), Last('EtherType'): Number(111) }) })), ('Payload', Field('Payload', Array('Payload_Array'), And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)), LessEqual(Div(Length('Payload'), Number(8)), Number(1500))), { '000000': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000'), ('TCI', '0000'), ('EtherType', '00000') ], LessEqual(Value('EtherType'), Number(1500)), { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('TCI'): Number(16), First('TCI'): Number(112), Last('TCI'): Number(127), Length('EtherType'): Number(16), First('EtherType'): Number(128), Last('EtherType'): Number(143), Length('Payload'): Mul(LengthValue('EtherType'), Number(8)), First('Payload'): Number(144), Last('Payload'): Add(Mul(LengthValue('EtherType'), Number(8)), Number(143)) }), '000001': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000'), ('TCI', '0000'), ('EtherType', '00000') ], GreaterEqual(Value('EtherType'), Number(1536)), { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('TCI'): Number(16), First('TCI'): Number(112), Last('TCI'): Number(127), Length('EtherType'): Number(16), First('EtherType'): Number(128), Last('EtherType'): Number(143), Length('Payload'): Add(Last('Message'), Number(-143)), First('Payload'): Number(144), Last('Payload'): Last('Message') }), '00010': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000'), ('EtherType', '0001') ], LessEqual(Value('EtherType'), Number(1500)), { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('EtherType'): Number(16), First('EtherType'): Number(96), Last('EtherType'): Number(111), Length('Payload'): Mul(LengthValue('EtherType'), Number(8)), First('Payload'): Number(112), Last('Payload'): Add(Mul(LengthValue('EtherType'), Number(8)), Number(111)) }), '00011': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000'), ('EtherType', '0001') ], GreaterEqual(Value('EtherType'), Number(1536)), { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('EtherType'): Number(16), First('EtherType'): Number(96), Last('EtherType'): Number(111), Length('Payload'): Add(Last('Message'), Number(-111)), First('Payload'): Number(112), Last('Payload'): Last('Message') }) })), ('FINAL', Field('FINAL', Null(), TRUE, { '0000000': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000'), ('TCI', '0000'), ('EtherType', '00000'), ('Payload', '000000') ], And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)), LessEqual(Div(Length('Payload'), Number(8)), Number(1500))), { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('TCI'): Number(16), First('TCI'): Number(112), Last('TCI'): Number(127), Length('EtherType'): Number(16), First('EtherType'): Number(128), Last('EtherType'): Number(143), Length('Payload'): Mul(LengthValue('EtherType'), Number(8)), First('Payload'): Number(144), Last('Payload'): Add(Mul(LengthValue('EtherType'), Number(8)), Number(143)) }), '0000010': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000'), ('TCI', '0000'), ('EtherType', '00000'), ('Payload', '000001') ], And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)), LessEqual(Div(Length('Payload'), Number(8)), Number(1500))), { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('TCI'): Number(16), First('TCI'): Number(112), Last('TCI'): Number(127), Length('EtherType'): Number(16), First('EtherType'): Number(128), Last('EtherType'): Number(143), Length('Payload'): Add(Last('Message'), Number(-143)), First('Payload'): Number(144), Last('Payload'): Last('Message') }), '000100': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000'), ('EtherType', '0001'), ('Payload', '00010') ], And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)), LessEqual(Div(Length('Payload'), Number(8)), Number(1500))), { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('EtherType'): Number(16), First('EtherType'): Number(96), Last('EtherType'): Number(111), Length('Payload'): Mul(LengthValue('EtherType'), Number(8)), First('Payload'): Number(112), Last('Payload'): Add(Mul(LengthValue('EtherType'), Number(8)), Number(111)) }), '000110': Variant( [ ('Destination', '0'), ('Source', '00'), ('TPID', '000'), ('EtherType', '0001'), ('Payload', '00011') ], And(GreaterEqual(Div(Length('Payload'), Number(8)), Number(46)), LessEqual(Div(Length('Payload'), Number(8)), Number(1500))), { Length('Destination'): Number(48), First('Destination'): Number(0), Last('Destination'): Number(47), Length('Source'): Number(48), First('Source'): Number(48), Last('Source'): Number(95), Length('TPID'): Number(16), First('TPID'): Number(96), Last('TPID'): Number(111), Length('EtherType'): Number(16), First('EtherType'): Number(96), Last('EtherType'): Number(111), Length('Payload'): Add(Last('Message'), Number(-111)), First('Payload'): Number(112), Last('Payload'): Last('Message') }) })) ]) self.assertEqual(ETHERNET_PDU.fields(), expected)
def test_div_neg(self) -> None: self.assertEqual(-Div(Value('X'), Number(1)), Div(Value('X', True), Number(1)))