Get the Damm module tested
This commit is contained in:
parent
4e35261dd1
commit
1f3854317c
5 changed files with 41 additions and 24 deletions
|
@ -1,20 +1,6 @@
|
||||||
py_library(
|
py_project(
|
||||||
name = "damm",
|
name = "damm",
|
||||||
srcs = [
|
test_deps = [
|
||||||
"damm.py",
|
py_requirement("hypothesis"),
|
||||||
],
|
],
|
||||||
imports = [
|
|
||||||
"."
|
|
||||||
],
|
|
||||||
visibility = [
|
|
||||||
"//visibility:public",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
py_pytest(
|
|
||||||
name = "test_damm",
|
|
||||||
srcs = glob(["test_*.py"]),
|
|
||||||
deps = [
|
|
||||||
":damm",
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -45,12 +45,20 @@ class Damm(NamedTuple):
|
||||||
return f"{self.__class__.__name__}({self.value}, {self.encode(self.value)})"
|
return f"{self.__class__.__name__}({self.value}, {self.encode(self.value)})"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def encode(cls, value):
|
def checkdigit(cls, value: int) -> int:
|
||||||
|
"""Compute a check digit for a given value."""
|
||||||
|
|
||||||
state = 0
|
state = 0
|
||||||
for digit in str(value):
|
for digit in str(value):
|
||||||
state = cls.MATRIX[state][int(digit)]
|
state = cls.MATRIX[state][int(digit)]
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def encode(cls, value: int) -> str:
|
||||||
|
"""'encode' a value with a check digit."""
|
||||||
|
|
||||||
|
return f"{value}-{cls.checkdigit(value)}"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def verify(cls, value: str) -> bool:
|
def verify(cls, value: str) -> bool:
|
||||||
"""Verify a Damm encoded number, returning its value if valid.
|
"""Verify a Damm encoded number, returning its value if valid.
|
||||||
|
@ -59,11 +67,13 @@ class Damm(NamedTuple):
|
||||||
the string is correctly Damm encoded, the Damm of the entire string will be 0.
|
the string is correctly Damm encoded, the Damm of the entire string will be 0.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return cls.encode(int(value.replace("-", ""))) == 0
|
|
||||||
|
return cls.checkdigit(int(value.replace("-", ""))) == 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_str(cls, value: str) -> "Damm":
|
def from_str(cls, value: str) -> "Damm":
|
||||||
"""Verify a Damm coded string, and return its decoding."""
|
"""Verify a Damm coded string, and return its decoding."""
|
||||||
|
|
||||||
if match := re.fullmatch(cls.DAMM_PATTERN, value):
|
if match := re.fullmatch(cls.DAMM_PATTERN, value):
|
||||||
given_value = match.group("value")
|
given_value = match.group("value")
|
||||||
computed_code = cls.encode(given_value)
|
computed_code = cls.encode(given_value)
|
15
projects/damm/test/python/test_damm.py
Normal file
15
projects/damm/test/python/test_damm.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
from damm import Damm
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('num', [
|
||||||
|
"0", # 0 itself is the start Damm state
|
||||||
|
"37", # [0, 3] => 7
|
||||||
|
"92", # [0, 9] => 2
|
||||||
|
"1234", # Amusingly, this is a 0-product.
|
||||||
|
])
|
||||||
|
def test_num_verifies(num):
|
||||||
|
"""Assert that known-good Damm checks pass."""
|
||||||
|
|
||||||
|
assert Damm.verify(num)
|
11
projects/damm/test/python/test_hypothesis.py
Normal file
11
projects/damm/test/python/test_hypothesis.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
from damm import Damm
|
||||||
|
|
||||||
|
from hypothesis import given
|
||||||
|
from hypothesis.strategies import integers
|
||||||
|
|
||||||
|
|
||||||
|
@given(integers(0, 1<<512))
|
||||||
|
def test_num_checks_verify(num):
|
||||||
|
"""Assert the generated Damm check for number verifies."""
|
||||||
|
|
||||||
|
assert Damm.verify(Damm.encode(num))
|
|
@ -1,5 +0,0 @@
|
||||||
"""
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
from damm import Damm
|
|
Loading…
Reference in a new issue