Skip to content

Commit

Permalink
Complete Luhn algorithm (#1167)
Browse files Browse the repository at this point in the history
* Luhn algorithm bug fixed

* Robust tests for payment card number

* changes file

* Robust tests for Luhn algorithm

* remove bad quotes

* Styling changes done

* Some little changes
  • Loading branch information
andreshndz authored and samuelcolvin committed Jan 20, 2020
1 parent 07271ca commit 4f8f939
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 6 deletions.
1 change: 1 addition & 0 deletions changes/1166-cuencandres.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
completing Luhn algorithm for `PaymentCardNumber`.
2 changes: 2 additions & 0 deletions pydantic/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,8 @@ def validate_luhn_check_digit(cls, card_number: str) -> str:
digit = int(card_number[i])
if i % 2 == parity:
digit *= 2
if digit > 9:
digit -= 9
sum_ += digit
valid = sum_ % 10 == 0
if not valid:
Expand Down
46 changes: 40 additions & 6 deletions tests/test_types_payment_card_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@

VALID_AMEX = '370000000000002'
VALID_MC = '5100000000000003'
VALID_VISA = '4000000000000002'
VALID_VISA = '4050000000000001'
VALID_OTHER = '2000000000000000008'
LUHN_INVALID = '4000000000000000'
LEN_INVALID = '40000000000000006'


# Mock PaymentCardNumber
PCN = namedtuple('PaymentCardNumber', ['card_number', 'brand'])
PCN.__len__ = lambda v: len(v.card_number)
Expand All @@ -30,10 +31,43 @@ def test_validate_digits():
PaymentCardNumber.validate_digits('hello')


def test_validate_luhn_check_digit():
assert PaymentCardNumber.validate_luhn_check_digit(VALID_VISA) == VALID_VISA
with pytest.raises(LuhnValidationError):
PaymentCardNumber.validate_luhn_check_digit(LUHN_INVALID)
@pytest.mark.parametrize(
'card_number, valid',
[
('0', True),
('00', True),
('18', True),
('0000000000000000', True),
('4242424242424240', False),
('4242424242424241', False),
('4242424242424242', True),
('4242424242424243', False),
('4242424242424244', False),
('4242424242424245', False),
('4242424242424246', False),
('4242424242424247', False),
('4242424242424248', False),
('4242424242424249', False),
('42424242424242426', True),
('424242424242424267', True),
('4242424242424242675', True),
('5164581347216566', True),
('4345351087414150', True),
('343728738009846', True),
('5164581347216567', False),
('4345351087414151', False),
('343728738009847', False),
('000000018', True),
('99999999999999999999', True),
('99999999999999999999999999999999999999999999999999999999999999999997', True),
],
)
def test_validate_luhn_check_digit(card_number: str, valid: bool):
if valid:
assert PaymentCardNumber.validate_luhn_check_digit(card_number) == card_number
else:
with pytest.raises(LuhnValidationError):
PaymentCardNumber.validate_luhn_check_digit(card_number)


@pytest.mark.parametrize(
Expand Down Expand Up @@ -71,7 +105,7 @@ def test_get_brand(card_number: str, brand: PaymentCardBrand):
def test_valid():
card = PaymentCard(card_number=VALID_VISA)
assert str(card.card_number) == VALID_VISA
assert card.card_number.masked == '400000******0002'
assert card.card_number.masked == '405000******0001'


@pytest.mark.parametrize(
Expand Down

0 comments on commit 4f8f939

Please sign in to comment.