def test_container_manipulation(data, size): sedes, values = data.draw(container_sedes_and_values_st(size=size)) value = data.draw(values) replacement_value = data.draw(values) hashable_value = to_hashable_value(value, sedes) hashable_replacement_value = to_hashable_value(replacement_value, sedes) replacement_index_st = st.integers(min_value=-size, max_value=size - 1) replacement_indices = data.draw(st.lists(replacement_index_st, unique=True)) replacement_names = [ hashable_replacement_value._meta.fields[index][0] for index in replacement_indices ] replacements = [replacement_value[index] for index in replacement_indices] hashable_replacements = [ hashable_replacement_value[index] for index in replacement_indices ] indices_names_replacements = zip( replacement_indices, replacement_names, hashable_replacements ) # expected result replaced_value = list(value) for index, new_value in zip(replacement_indices, replacements): replaced_value[index] = new_value replaced_value = tuple(replaced_value) # set by index, name, and attr hashable_value_set_index = hashable_value hashable_value_set_name = hashable_value evolver = hashable_value.evolver() for index, name, new_value in indices_names_replacements: hashable_value_set_index = hashable_value_set_index.set(index, new_value) hashable_value_set_name = hashable_value_set_name.set(name, new_value) setattr(evolver, name, new_value) for container in (hashable_value_set_index, hashable_value_set_name, evolver): assert container[index] == new_value assert container[name] == new_value assert getattr(container, name) == new_value hashable_value_evolved = evolver.persistent() # mset by index and name hashable_value_mset_index = hashable_value.mset( *itertools.chain.from_iterable(zip(replacement_indices, hashable_replacements)) ) hashable_value_mset_name = hashable_value.mset( *itertools.chain.from_iterable(zip(replacement_names, hashable_replacements)) ) assert to_plain_value(hashable_value_set_index, sedes) == replaced_value assert hashable_value_set_name == hashable_value_set_index assert hashable_value_evolved == hashable_value_set_index assert hashable_value_mset_index == hashable_value_set_index assert hashable_value_mset_name == hashable_value_set_index
def test_container_access(data, sedes_and_values): sedes, values = sedes_and_values value = data.draw(values) hashable_value = to_hashable_value(value, sedes) field_names = [f"field{index}" for index in range(len(value))] # __len__ assert len(hashable_value) == len(value) # __getitem__ with int for index, field_sedes in enumerate(sedes.field_sedes): index_neg = index - len(value) plain_value = to_plain_value(hashable_value[index], field_sedes) plain_value_neg = to_plain_value(hashable_value[index_neg], field_sedes) assert plain_value == value[index] assert plain_value_neg == value[index_neg] # __getitem__ with field name and __getattr__ for index, (field_name, field_sedes) in enumerate( zip(field_names, sedes.field_sedes) ): value_item = hashable_value[field_name] value_attr = getattr(hashable_value, field_name) plain_value_item = to_plain_value(value_item, field_sedes) plain_value_attr = to_plain_value(value_attr, field_sedes) assert plain_value_item == value[index] assert plain_value_attr == value[index] # __iter__ for hashable_element, plain_element, field_sedes in zip( hashable_value, value, sedes.field_sedes ): assert to_plain_value(hashable_element, field_sedes) == plain_element
def test_equality(data, sedes_and_values_1, sedes_and_values_2): sedes1, values1 = sedes_and_values_1 sedes2, values2 = sedes_and_values_2 value1 = data.draw(values1) value2 = data.draw(values2) assume(sedes1 != sedes2 or value1 != value2) hashable_value_1 = to_hashable_value(value1, sedes1) hashable_value_2 = to_hashable_value(value2, sedes2) assert hashable_value_1 == hashable_value_1 assert hashable_value_2 == hashable_value_2 assert hash(hashable_value_1) == hash(hashable_value_1) assert hash(hashable_value_2) == hash(hashable_value_2) assert hashable_value_1 != hashable_value_2 assert hash(hashable_value_1) != hash(hashable_value_2)
def test_transform(data, sedes_and_values): sedes, values = sedes_and_values value = data.draw(values) hashable_value = to_hashable_value(value, sedes) transform_path = data.draw(transform_path_st(hashable_value)) original_value = get_in(transform_path, hashable_value, no_default=True) if isinstance(original_value, bool): def transformation(value): return not value new_value = transformation(original_value) elif isinstance(original_value, int): def transformation(value): # safe for all integer sizes return 1 if value == 0 else value - 1 new_value = transformation(original_value) else: # bail out if the path does not lead to a atomic value (e.g. if there's an empty list on # the path) assume(False) transform_set = hashable_value.transform(transform_path, new_value) transform_applied = hashable_value.transform(transform_path, transformation) assert transform_set == transform_applied assert get_in(transform_path, transform_set, new_value) == new_value assert get_in(transform_path, transform_applied, new_value) == new_value
def test_sequence_manipulation(data, sequence_type_and_values_st, sequence_size): sedes, values = data.draw(sequence_type_and_values_st(size=sequence_size)) value = data.draw(values) replacement_value = data.draw(values) hashable_value = to_hashable_value(value, sedes) hashable_replacement_value = to_hashable_value(replacement_value, sedes) replacement_index_st = st.integers( min_value=-sequence_size, max_value=sequence_size - 1 ) replacement_indices = data.draw(st.lists(replacement_index_st, unique=True)) replacements = [(index, replacement_value[index]) for index in replacement_indices] hashable_replacements = [ (index, hashable_replacement_value[index]) for index in replacement_indices ] # expected result replaced_value = list(value) for index, new_value in replacements: replaced_value[index] = new_value replaced_value = type(value)(replaced_value) # set hashable_value_set = hashable_value for index, new_value in hashable_replacements: hashable_value_set = hashable_value_set.set(index, new_value) assert hashable_value_set[index] == new_value # mset hashable_value_mset = hashable_value.mset( *itertools.chain.from_iterable(hashable_replacements) ) # evolver evolver = hashable_value.evolver() for index, new_value in hashable_replacements: evolver[index] = new_value assert evolver[index] == new_value hashable_value_evolved = evolver.persistent() assert to_plain_value(hashable_value_mset, sedes) == replaced_value assert hashable_value_set == hashable_value_mset assert hashable_value_evolved == hashable_value_mset
def test_encoding(data, sedes_and_values): sedes, values = sedes_and_values value = data.draw(values) serializable_value = to_serializable_value(value, sedes) serializable_encoding = ssz.encode(serializable_value, sedes) hashable_value = to_hashable_value(value, sedes) hashable_encoding = ssz.encode(hashable_value, sedes) assert serializable_encoding == hashable_encoding
def test_root(data, sedes_and_values): sedes, values = sedes_and_values value = data.draw(values) serializable_value = to_serializable_value(value, sedes) serializable_root = ssz.get_hash_tree_root(serializable_value, sedes) hashable_value = to_hashable_value(value, sedes) hashable_root = ssz.get_hash_tree_root(hashable_value, sedes) assert serializable_root == hashable_root
def test_list_extend(data, list_sedes_and_values): sedes, values = list_sedes_and_values value = data.draw(values) extension = data.draw(values)[: sedes.max_length - len(value)] hashable_value = to_hashable_value(value, sedes) hashable_extension = to_hashable_value(extension, sedes) # expected result extended_value = value + extension # extend with appends hashable_value_appended = hashable_value append_evolver = hashable_value.evolver() for num_appended, element in enumerate(hashable_extension, start=1): hashable_value_appended = hashable_value_appended.append(element) append_evolver.append(element) for intermediate in (hashable_value_appended, append_evolver): assert len(intermediate) == len(value) + num_appended assert intermediate[len(intermediate) - 1] == element assert intermediate[-1] == element hashable_value_append_evolved = append_evolver.persistent() # extend with extend hashable_value_extended = hashable_value.extend(hashable_extension) extend_evolver = hashable_value.evolver() extend_evolver.extend(hashable_extension) hashable_value_extend_evolved = extend_evolver.persistent() # extend with + hashable_value_plussed = hashable_value + hashable_extension # compare results assert to_plain_value(hashable_value_appended, sedes) == extended_value assert hashable_value_append_evolved == hashable_value_appended assert hashable_value_extended == hashable_value_appended assert hashable_value_extend_evolved == hashable_value_appended assert hashable_value_plussed == hashable_value_appended
def test_signing_root(data, sedes_and_values): unsigned_sedes, unsigned_values = sedes_and_values unsigned_value = data.draw(unsigned_values) unsigned_hashable_value = to_hashable_value(unsigned_value, unsigned_sedes) class SignedValueClass(SignedHashableContainer): fields = unsigned_hashable_value._meta.fields + (("signature", bytes96),) signature = data.draw(st.binary(min_size=96, max_size=96)) kwargs = { field_name: unsigned_hashable_value[field_name] for field_name in SignedValueClass._meta.field_names if field_name != "signature" } hashable_value = SignedValueClass.create(**kwargs, signature=signature) assert hashable_value.signing_root == unsigned_hashable_value.hash_tree_root
def test_sequence_access(data, sequence_sedes_and_values): sedes, values = sequence_sedes_and_values value = data.draw(values) element_sedes = sedes.element_sedes hashable_value = to_hashable_value(value, sedes) # __len__ assert len(hashable_value) == len(value) # __getitem__ for index in range(len(value)): index_neg = index - len(value) plain_value = to_plain_value(hashable_value[index], element_sedes) plain_value_neg = to_plain_value(hashable_value[index_neg], element_sedes) assert plain_value == value[index] assert plain_value_neg == value[index_neg] # __iter__ for hashable_element, plain_element in zip(hashable_value, value): assert to_plain_value(hashable_element, sedes.element_sedes) == plain_element