diff --git a/cryptoconditions/types/threshold.py b/cryptoconditions/types/threshold.py index 96f1838..450c89a 100644 --- a/cryptoconditions/types/threshold.py +++ b/cryptoconditions/types/threshold.py @@ -4,7 +4,7 @@ from pyasn1.codec.native.decoder import decode as nat_decode from cryptoconditions.condition import Condition -from cryptoconditions.exceptions import MissingDataError +from cryptoconditions.exceptions import MissingDataError, ValidationError from cryptoconditions.fulfillment import Fulfillment from cryptoconditions.types.ed25519 import Ed25519Sha256 from cryptoconditions.types.base_sha256 import BaseSha256 @@ -55,8 +55,12 @@ def __init__(self, threshold=None): Args: threshold (int): Integer threshold """ - if threshold and (not isinstance(threshold, int) or threshold < 1): - raise ValueError('Threshold must be a integer greater than zero, was: {}'.format(threshold)) + if threshold is not None and ( + not isinstance(threshold, int) or threshold < 1): + raise ValueError( + 'Threshold must be a integer greater than zero, was: {}'. + format(threshold) + ) self.threshold = threshold self.subconditions = [] @@ -141,7 +145,7 @@ def asn1_dict_payload(self): key=lambda x: x['body'].cost, ) if len(subfulfillments) < self.threshold: - raise Exception('Not enough fulfillments') + raise ValidationError('Not enough fulfillments') minimal_fulfillments = subfulfillments[:self.threshold] remaining_conditions = chain( diff --git a/tests/types/test_threshold.py b/tests/types/test_threshold.py new file mode 100644 index 0000000..8b79df5 --- /dev/null +++ b/tests/types/test_threshold.py @@ -0,0 +1,86 @@ +from pytest import mark, raises + + +class TestThresholdSha256: + + @mark.parametrize('threshold', (0, 0.1, 'a')) + def test_init_with_invalid_threshold(self, threshold): + from cryptoconditions.types.threshold import ThresholdSha256 + with raises(ValueError) as exc: + ThresholdSha256(threshold=threshold) + assert exc.value.args == ( + 'Threshold must be a integer greater than zero, was: {}'. + format(threshold), + ) + + def test_add_subcondition_type_error(self): + from cryptoconditions.types.threshold import ThresholdSha256 + threshold_obj = ThresholdSha256() + with raises(TypeError) as exc: + threshold_obj.add_subcondition(123) + assert exc.value.args == ( + 'Subconditions must be URIs or objects of type Condition',) + + def test_add_subcondition_as_uri(self, minimal_threshold): + from cryptoconditions.types.threshold import ThresholdSha256 + from cryptoconditions.fulfillment import Fulfillment + threshold_obj = ThresholdSha256( + threshold=minimal_threshold.json['threshold']) + subfulfillment = Fulfillment.from_json( + minimal_threshold.json['subfulfillments'][0]) + subcondition_uri = subfulfillment.condition_uri + threshold_obj.add_subcondition(subcondition_uri) + threshold_obj.serialize_uri == minimal_threshold.fulfillment + + def test_add_subcondition_as_object(self, minimal_threshold): + from cryptoconditions.types.threshold import ThresholdSha256 + from cryptoconditions.fulfillment import Fulfillment + threshold_obj = ThresholdSha256( + threshold=minimal_threshold.json['threshold']) + subfulfillment = Fulfillment.from_json( + minimal_threshold.json['subfulfillments'][0]) + subcondition_object = subfulfillment.condition + threshold_obj.add_subcondition(subcondition_object) + threshold_obj.serialize_uri == minimal_threshold.fulfillment + + def test_add_subfulfillment_type_error(self): + from cryptoconditions.types.threshold import ThresholdSha256 + threshold_obj = ThresholdSha256() + with raises(TypeError) as exc: + threshold_obj.add_subfulfillment(123) + assert exc.value.args == ( + 'Subfulfillments must be URIs or objects of type Fulfillment',) + + def test_add_subfulfillment_as_uri(self, minimal_threshold): + from cryptoconditions.types.threshold import ThresholdSha256 + from cryptoconditions.fulfillment import Fulfillment + threshold_obj = ThresholdSha256( + threshold=minimal_threshold.json['threshold']) + subfulfillment = Fulfillment.from_json( + minimal_threshold.json['subfulfillments'][0]) + subfulfillment_uri = subfulfillment.serialize_uri() + threshold_obj.add_subfulfillment(subfulfillment_uri) + threshold_obj.serialize_uri == minimal_threshold.fulfillment + + def test_add_subfulfillment_as_object(self, minimal_threshold): + from cryptoconditions.types.threshold import ThresholdSha256 + from cryptoconditions.fulfillment import Fulfillment + threshold_obj = ThresholdSha256( + threshold=minimal_threshold.json['threshold']) + subfulfillment_object = Fulfillment.from_json( + minimal_threshold.json['subfulfillments'][0]) + threshold_obj.add_subfulfillment(subfulfillment_object) + threshold_obj.serialize_uri == minimal_threshold.fulfillment + + def test_asn1_dict_payload(self): + from cryptoconditions.exceptions import ValidationError + from cryptoconditions.types.threshold import ThresholdSha256 + threshold_obj = ThresholdSha256(threshold=1) + with raises(ValidationError) as exc: + threshold_obj.asn1_dict_payload + assert exc.value.args == ('Not enough fulfillments',) + + def test_calculate_worst_case_length(self): + from cryptoconditions.types.threshold import ThresholdSha256 + cost = ThresholdSha256.calculate_worst_case_length(1, ()) + assert cost == float('-inf')