def test_TupleElement_store_into(): tests: List[List[abi.TypeSpec]] = [ [], [abi.Uint64TypeSpec()], [ abi.TupleTypeSpec(abi.Uint64TypeSpec(), abi.Uint64TypeSpec()), abi.Uint64TypeSpec(), ], [abi.BoolTypeSpec()] * 8, ] for i, test in enumerate(tests): tupleValue = abi.Tuple(abi.TupleTypeSpec(*test)) for j in range(len(test)): element = TupleElement(tupleValue, j) output = test[j].new_instance() expr = element.store_into(output) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expectedExpr = _index_tuple(test, tupleValue.encode(), j, output) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected, "Test at index {} failed".format(i)
def test_Tuple_length(): tests: List[List[abi.TypeSpec]] = [ [], [abi.Uint64TypeSpec()], [ abi.TupleTypeSpec(abi.Uint64TypeSpec(), abi.Uint64TypeSpec()), abi.Uint64TypeSpec(), ], [abi.BoolTypeSpec()] * 8, ] for i, test in enumerate(tests): tupleValue = abi.Tuple(abi.TupleTypeSpec(*test)) expr = tupleValue.length() assert expr.type_of() == pt.TealType.uint64 assert not expr.has_return() expectedLength = len(test) expected = pt.TealSimpleBlock([pt.TealOp(None, pt.Op.int, expectedLength)]) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected, "Test at index {} failed".format(i)
def test_Tuple_set_Computed(): tupleValue = abi.Tuple( abi.TupleTypeSpec( abi.Uint8TypeSpec(), abi.Uint16TypeSpec(), abi.Uint32TypeSpec() ) ) computed = ContainerType( tupleValue.type_spec(), pt.Bytes("internal representation") ) expr = tupleValue.set(computed) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expected = pt.TealSimpleBlock( [ pt.TealOp(None, pt.Op.byte, '"internal representation"'), pt.TealOp(None, pt.Op.store, tupleValue.stored_value.slot), ] ) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected with pytest.raises(pt.TealInputError): tupleValue.set(computed, computed) with pytest.raises(pt.TealInputError): tupleValue.set( ContainerType(abi.TupleTypeSpec(abi.ByteTypeSpec()), pt.Bytes(b"a")) )
def test_Tuple_encode(): tupleValue = abi.Tuple(abi.TupleTypeSpec(abi.Uint64TypeSpec())) expr = tupleValue.encode() assert expr.type_of() == pt.TealType.bytes assert not expr.has_return() expected = pt.TealSimpleBlock( [pt.TealOp(None, pt.Op.load, tupleValue.stored_value.slot)] ) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected
def test_Tuple_set(): tupleValue = abi.Tuple( abi.TupleTypeSpec( abi.Uint8TypeSpec(), abi.Uint16TypeSpec(), abi.Uint32TypeSpec() ) ) uint8 = abi.Uint8() uint16 = abi.Uint16() uint32 = abi.Uint32() with pytest.raises(pt.TealInputError): tupleValue.set() with pytest.raises(pt.TealInputError): tupleValue.set(uint8, uint16) with pytest.raises(pt.TealInputError): tupleValue.set(uint8, uint16, uint32, uint32) with pytest.raises(pt.TealInputError): tupleValue.set(uint8, uint32, uint16) with pytest.raises(pt.TealInputError): tupleValue.set(uint8, uint16, uint16) expr = tupleValue.set(uint8, uint16, uint32) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expectedExpr = tupleValue.stored_value.store(_encode_tuple([uint8, uint16, uint32])) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected
def test_Tuple_decode(): encoded = pt.Bytes("encoded") tupleValue = abi.Tuple(abi.TupleTypeSpec(abi.Uint64TypeSpec())) for start_index in (None, pt.Int(1)): for end_index in (None, pt.Int(2)): for length in (None, pt.Int(3)): if end_index is not None and length is not None: with pytest.raises(pt.TealInputError): tupleValue.decode( encoded, start_index=start_index, end_index=end_index, length=length, ) continue expr = tupleValue.decode( encoded, start_index=start_index, end_index=end_index, length=length ) assert expr.type_of() == pt.TealType.none assert not expr.has_return() expectedExpr = tupleValue.stored_value.store( substring_for_decoding( encoded, start_index=start_index, end_index=end_index, length=length, ) ) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected
def test_Tuple_getitem(): tests: List[List[abi.TypeSpec]] = [ [], [abi.Uint64TypeSpec()], [ abi.TupleTypeSpec(abi.Uint64TypeSpec(), abi.Uint64TypeSpec()), abi.Uint64TypeSpec(), ], [abi.BoolTypeSpec()] * 8, ] for i, test in enumerate(tests): tupleValue = abi.Tuple(abi.TupleTypeSpec(*test)) for j in range(len(test)): element = tupleValue[j] assert type(element) is TupleElement, "Test at index {} failed".format(i) assert element.tuple is tupleValue, "Test at index {} failed".format(i) assert element.index == j, "Test at index {} failed".format(i) with pytest.raises(pt.TealInputError): tupleValue[-1] with pytest.raises(pt.TealInputError): tupleValue[len(test)]
def test_ArrayElement_store_into(): for elementType in STATIC_TYPES + DYNAMIC_TYPES: staticArrayType = abi.StaticArrayTypeSpec(elementType, 100) staticArray = staticArrayType.new_instance() index = pt.Int(9) element = abi.ArrayElement(staticArray, index) output = elementType.new_instance() expr = element.store_into(output) encoded = staticArray.encode() stride = pt.Int(staticArray.type_spec()._stride()) expectedLength = staticArray.length() if elementType == abi.BoolTypeSpec(): expectedExpr = cast(abi.Bool, output).decode_bit(encoded, index) elif not elementType.is_dynamic(): expectedExpr = output.decode(encoded, start_index=stride * index, length=stride) else: expectedExpr = output.decode( encoded, start_index=pt.ExtractUint16(encoded, stride * index), end_index=pt.If(index + pt.Int(1) == expectedLength).Then( pt.Len(encoded)).Else( pt.ExtractUint16(encoded, stride * index + pt.Int(2))), ) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected with pytest.raises(pt.TealInputError): element.store_into(abi.Tuple(abi.TupleTypeSpec(elementType))) for elementType in STATIC_TYPES + DYNAMIC_TYPES: dynamicArrayType = abi.DynamicArrayTypeSpec(elementType) dynamicArray = dynamicArrayType.new_instance() index = pt.Int(9) element = abi.ArrayElement(dynamicArray, index) output = elementType.new_instance() expr = element.store_into(output) encoded = dynamicArray.encode() stride = pt.Int(dynamicArray.type_spec()._stride()) expectedLength = dynamicArray.length() if elementType == abi.BoolTypeSpec(): expectedExpr = cast(abi.Bool, output).decode_bit(encoded, index + pt.Int(16)) elif not elementType.is_dynamic(): expectedExpr = output.decode(encoded, start_index=stride * index + pt.Int(2), length=stride) else: expectedExpr = output.decode( encoded, start_index=pt.ExtractUint16( encoded, stride * index + pt.Int(2)) + pt.Int(2), end_index=pt.If(index + pt.Int(1) == expectedLength).Then( pt.Len(encoded)).Else( pt.ExtractUint16( encoded, stride * index + pt.Int(2) + pt.Int(2)) + pt.Int(2)), ) expected, _ = expectedExpr.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) with pt.TealComponent.Context.ignoreExprEquality(): with pt.TealComponent.Context.ignoreScratchSlotEquality(): assert actual == expected assert pt.TealBlock.MatchScratchSlotReferences( pt.TealBlock.GetReferencedScratchSlots(actual), pt.TealBlock.GetReferencedScratchSlots(expected), ) with pytest.raises(pt.TealInputError): element.store_into(abi.Tuple(abi.TupleTypeSpec(elementType)))
def test_encodeTuple(): class EncodeTest(NamedTuple): types: List[abi.BaseType] expected: pt.Expr # variables used to construct the tests uint64_a = abi.Uint64() uint64_b = abi.Uint64() uint16_a = abi.Uint16() uint16_b = abi.Uint16() bool_a = abi.Bool() bool_b = abi.Bool() tuple_a = abi.Tuple(abi.TupleTypeSpec(abi.BoolTypeSpec(), abi.BoolTypeSpec())) dynamic_array_a = abi.DynamicArray(abi.DynamicArrayTypeSpec(abi.Uint64TypeSpec())) dynamic_array_b = abi.DynamicArray(abi.DynamicArrayTypeSpec(abi.Uint16TypeSpec())) dynamic_array_c = abi.DynamicArray(abi.DynamicArrayTypeSpec(abi.BoolTypeSpec())) tail_holder = pt.ScratchVar() encoded_tail = pt.ScratchVar() tests: List[EncodeTest] = [ EncodeTest(types=[], expected=pt.Bytes("")), EncodeTest(types=[uint64_a], expected=uint64_a.encode()), EncodeTest( types=[uint64_a, uint64_b], expected=pt.Concat(uint64_a.encode(), uint64_b.encode()), ), EncodeTest(types=[bool_a], expected=bool_a.encode()), EncodeTest( types=[bool_a, bool_b], expected=_encode_bool_sequence([bool_a, bool_b]) ), EncodeTest( types=[bool_a, bool_b, uint64_a], expected=pt.Concat( _encode_bool_sequence([bool_a, bool_b]), uint64_a.encode() ), ), EncodeTest( types=[uint64_a, bool_a, bool_b], expected=pt.Concat( uint64_a.encode(), _encode_bool_sequence([bool_a, bool_b]) ), ), EncodeTest( types=[uint64_a, bool_a, bool_b, uint64_b], expected=pt.Concat( uint64_a.encode(), _encode_bool_sequence([bool_a, bool_b]), uint64_b.encode(), ), ), EncodeTest( types=[uint64_a, bool_a, uint64_b, bool_b], expected=pt.Concat( uint64_a.encode(), bool_a.encode(), uint64_b.encode(), bool_b.encode() ), ), EncodeTest(types=[tuple_a], expected=tuple_a.encode()), EncodeTest( types=[uint64_a, tuple_a, bool_a, bool_b], expected=pt.Concat( uint64_a.encode(), tuple_a.encode(), _encode_bool_sequence([bool_a, bool_b]), ), ), EncodeTest( types=[dynamic_array_a], expected=pt.Concat( pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(2), uint16_a.encode(), ), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2), uint16_a.encode(), ), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a, uint64_b], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 8), uint16_a.encode(), ), uint64_b.encode(), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a, bool_a, bool_b], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 1), uint16_a.encode(), ), _encode_bool_sequence([bool_a, bool_b]), tail_holder.load(), ), ), EncodeTest( types=[uint64_a, dynamic_array_a, uint64_b, dynamic_array_b], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 8 + 2), uint16_b.set(uint16_a.get() + pt.Len(encoded_tail.load())), uint16_a.encode(), ), uint64_b.encode(), pt.Seq( encoded_tail.store(dynamic_array_b.encode()), tail_holder.store( pt.Concat(tail_holder.load(), encoded_tail.load()) ), uint16_a.set(uint16_b), uint16_a.encode(), ), tail_holder.load(), ), ), EncodeTest( types=[ uint64_a, dynamic_array_a, uint64_b, dynamic_array_b, bool_a, bool_b, dynamic_array_c, ], expected=pt.Concat( uint64_a.encode(), pt.Seq( encoded_tail.store(dynamic_array_a.encode()), tail_holder.store(encoded_tail.load()), uint16_a.set(8 + 2 + 8 + 2 + 1 + 2), uint16_b.set(uint16_a.get() + pt.Len(encoded_tail.load())), uint16_a.encode(), ), uint64_b.encode(), pt.Seq( encoded_tail.store(dynamic_array_b.encode()), tail_holder.store( pt.Concat(tail_holder.load(), encoded_tail.load()) ), uint16_a.set(uint16_b), uint16_b.set(uint16_a.get() + pt.Len(encoded_tail.load())), uint16_a.encode(), ), _encode_bool_sequence([bool_a, bool_b]), pt.Seq( encoded_tail.store(dynamic_array_c.encode()), tail_holder.store( pt.Concat(tail_holder.load(), encoded_tail.load()) ), uint16_a.set(uint16_b), uint16_a.encode(), ), tail_holder.load(), ), ), ] for i, test in enumerate(tests): expr = _encode_tuple(test.types) assert expr.type_of() == pt.TealType.bytes assert not expr.has_return() expected, _ = test.expected.__teal__(options) expected.addIncoming() expected = pt.TealBlock.NormalizeBlocks(expected) actual, _ = expr.__teal__(options) actual.addIncoming() actual = pt.TealBlock.NormalizeBlocks(actual) if any(t.type_spec().is_dynamic() for t in test.types): with pt.TealComponent.Context.ignoreExprEquality(): with pt.TealComponent.Context.ignoreScratchSlotEquality(): assert actual == expected, "Test at index {} failed".format(i) assert pt.TealBlock.MatchScratchSlotReferences( pt.TealBlock.GetReferencedScratchSlots(actual), pt.TealBlock.GetReferencedScratchSlots(expected), ) continue with pt.TealComponent.Context.ignoreExprEquality(): assert actual == expected, "Test at index {} failed".format(i)