caudal/programa/pruebas/test_qr.py
esetheyers 4b158e662d Caudal 0.3.0
Link another Caudal (phone, USB) with a code or a QR instead of the password, choosing the server's root certificate as a file; read Bitcoin straight from Bitcoin Core or Knots, without an Electrum server; Android app (beta) and a Windows build script. Fixed: Save did nothing for expenses, refunds and dividends entered by hand.
2026-10-16 18:12:09 -05:00

64 lines
2.8 KiB
Python

"""
Pruebas del dibujo de códigos QR (cartera/qr.py). El generador se contrastó
módulo a módulo con una biblioteca de referencia para las doce versiones y las
ocho máscaras; aquí quedan fijadas unas huellas de aquel contraste, para que un
cambio que rompa el dibujo se note, y las reglas que se pueden comprobar solas.
python3 -m unittest discover -s pruebas -v
"""
from __future__ import annotations
import hashlib
import sys
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from cartera import qr # noqa: E402
def huella(texto: str, mascara: int) -> str:
m = qr.matriz(texto, mascara)
return hashlib.sha256("\n".join("".join("1" if v else "0" for v in f) for f in m).encode()).hexdigest()[:16]
HUELLAS = {
('hola', 0): (21, '4fc02fa450493e1a'),
('caudal://enlazar?u=https://caudal.midominio.local:54013&c=ABCDE-FGHJK', 3): (37, 'b999eb98ad128ff2'),
('ñandú €', 5): (21, 'f0376ed7bb1bb4b8'),
('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 7): (57, 'f4598565726ae33f'),
('yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', 2): (65, '4c6b554ce57e4951'),
}
class TestQr(unittest.TestCase):
def test_el_dibujo_no_ha_cambiado(self):
for (texto, mascara), (lado, esperada) in HUELLAS.items():
with self.subTest(texto=texto[:20], mascara=mascara):
self.assertEqual(len(qr.matriz(texto, mascara)), lado)
self.assertEqual(huella(texto, mascara), esperada)
def test_el_tamaño_crece_con_el_texto(self):
self.assertEqual([len(qr.matriz("x" * n)) for n in (1, 14, 15, 26, 27, 287)], [21, 21, 25, 25, 29, 65])
def test_los_tres_ojos_y_el_modulo_fijo(self):
m = qr.matriz("caudal")
n = len(m)
for x0, y0 in ((0, 0), (n - 7, 0), (0, n - 7)):
ojo = ["".join("1" if m[y0 + y][x0 + x] else "0" for x in range(7)) for y in range(7)]
self.assertEqual(ojo, ["1111111", "1000001", "1011101", "1011101", "1011101", "1000001", "1111111"])
self.assertTrue(m[n - 8][8])
def test_lo_que_no_cabe_se_dice(self):
with self.assertRaises(qr.TextoDemasiadoLargo):
qr.matriz("x" * 288)
def test_filas_como_texto(self):
filas = qr.filas("hola")
self.assertEqual((len(filas), {len(f) for f in filas}, set("".join(filas))), (21, {21}, {"0", "1"}))
if __name__ == "__main__":
unittest.main()