Adding back changes to tests/

This commit is contained in:
kdmukai
2022-02-19 16:52:39 -06:00
parent fed8b4e252
commit 61997e1e1d
4 changed files with 204 additions and 38 deletions
+59 -9
View File
@@ -2,6 +2,7 @@ import configparser
import pytest
from mock import MagicMock
from seedsigner.controller import Controller
from seedsigner.models.settings import Settings
@@ -17,6 +18,13 @@ def test_singleton_get_instance_without_configure_fails():
def test_singleton_get_instance_preserves_state():
""" Changes to the Controller singleton should be preserved across calls to get_instance() """
# Must reset Singleton instances; pytest cannot properly isolate Singletons for us
# automatically.
# TODO: Cleaner solution here would be nice.
Settings._instance = None
Controller._instance = None
settings = """
[system]
debug = False
@@ -25,6 +33,53 @@ def test_singleton_get_instance_preserves_state():
[display]
text_color = ORANGE
qr_background_color = FFFFFF
camera_rotation = 0
[wallet]
network = main
software = Prompt
qr_density = 2
custom_derivation = m/0/0
compact_seedqr_enabled = False
"""
config = configparser.ConfigParser()
config.read_string(settings)
# Initialize the instance and verify that it read the config settings
Controller.configure_instance(config, disable_hardware=True)
controller = Controller.get_instance()
assert controller.color == "ORANGE"
# Change a value in the instance...
controller.color = "purple"
# ...get a new copy of the instance and confirm change
controller = Controller.get_instance()
assert controller.color == "purple"
def test_missing_settings_get_defaults():
""" Should gracefully handle any missing fields from `settings.ini` """
# TODO: This is not complete; currently only handles missing compact_seedqr_enabled.
# Must reset Singleton instances; pytest cannot properly isolate Singletons for us
# automatically.
# TODO: Cleaner solution here would be nice.
Settings._instance = None
Controller._instance = None
# Intentionally omit `compact_seedqr_enabled` from settings:
settings = """
[system]
debug = False
default_language = en
persistent_settings = False
[display]
text_color = ORANGE
qr_background_color = FFFFFF
camera_rotation = 0
[wallet]
network = main
@@ -35,14 +90,9 @@ def test_singleton_get_instance_preserves_state():
config = configparser.ConfigParser()
config.read_string(settings)
# Initialize the instance and verify that it read the config settings
Controller.configure_instance(config)
controller = Controller.get_instance()
assert controller.color == "ORANGE"
# Controller should parse the settings fine, even though a field is missing
Controller.configure_instance(config, disable_hardware=True)
# Change a value in the instance...
controller.color = "purple"
# ...get a new copy of the instance and confirm change
# Controller should still have a default value
controller = Controller.get_instance()
assert controller.color == "purple"
assert controller.settings.compact_seedqr_enabled is False
+28 -28
View File
@@ -41,7 +41,7 @@ def test_ur_qr_decode_multisig():
d = DecodeQR(wordlist=bip39.WORDLIST)
for i in qrcodes:
d.addString(i)
d.add_data(i)
assert d.qrType() == QRType.PSBTUR2
#complete should be true
@@ -63,7 +63,7 @@ def test_base64_single_frame_singlsig():
d = DecodeQR(wordlist=bip39.WORDLIST)
for i in qrcodes:
d.addString(i)
d.add_data(i)
assert d.qrType() == QRType.PSBTBASE64
#complete should be true
@@ -108,7 +108,7 @@ def test_ur2_sparrow_singlesig_to_self():
d = DecodeQR(wordlist=bip39.WORDLIST)
for i in qrcodes:
d.addString(i)
d.add_data(i)
assert d.qrType() == QRType.PSBTUR2
#complete should be true
@@ -127,7 +127,7 @@ def test_base64_2_input_p2wsh():
base64_psbt = "cHNidP8BALICAAAAAq1DhxRK+mUH4T6uUNob8bUaZ7MP+44MW4+Y9bOxpjhZAAAAAAD9////aWclWQ+45HKrI07r878E2UrAupT2paT4QurbmtNjYNQBAAAAAP3///8CQEIPAAAAAAAiACCpkDPDhmIzPlkJrjw9A71xjbIUWf3VUB7ooFJhTVm04tjSIQEAAAAAIgAgjQKFDauIXsV5u23LBdYgOwX1FwGGrLiQfWzBtFKZ7dIAAAAATwEENYfPBD5i336AAAACQStJhNVJul7vHKbo83VdmuAW2m0WaXLKDlFANn7dUNoCNbhLMdw4Knz7Q7o6exdL6UFhQegW9nJb0SUStbLEpawUAgjLdzAAAIABAACAAAAAgAIAAIBPAQQ1h88EnbHQAIAAAAI/2Nc7x7iMpJNapTe/OJTV4oifqzQcYY9KV2+PGRjCdQJoww1WnSNqfcxXGyux0q1PqfmzUqgJNqKJCpmqI9t47BQmu4PEMAAAgAEAAIAAAACAAgAAgE8BBDWHzwS6wUg5gAAAAh1Pvr3ZZ+GvcUwJl9OPz2cLXOnTAcBEC7zDtqIOt3IcA1aOofNgUZFu0baQw54SqOcGA7KAvTDOXygfKRilU2OqFHPF2gowAACAAQAAgAAAAIACAACAAAEBK4CWmAAAAAAAIgAgiYAxcG7dnrEiZ4VHFVHOo18XCalvhZYuMqBr9n7HESQBBWlSIQJOjQgMfX26XEf+trHIEk3rYkEX5Y2NfrFKQARPcd2X8iEDBWHUgq25PfHvE+hlcBryJG7wo2y8jKUSPY7sd85OOMchA2iVcuKLD+2p1pgcAjfZ5d7b/sFt5xQ/aAoC7V0Vn3WHU64iBgJOjQgMfX26XEf+trHIEk3rYkEX5Y2NfrFKQARPcd2X8hwmu4PEMAAAgAEAAIAAAACAAgAAgAAAAAABAAAAIgYDBWHUgq25PfHvE+hlcBryJG7wo2y8jKUSPY7sd85OOMccAgjLdzAAAIABAACAAAAAgAIAAIAAAAAAAQAAACIGA2iVcuKLD+2p1pgcAjfZ5d7b/sFt5xQ/aAoC7V0Vn3WHHHPF2gowAACAAQAAgAAAAIACAACAAAAAAAEAAAAAAQErgJaYAAAAAAAiACAzd60wM9EFnPHSNbsSJfyipL8myVLVP2/vwzotVUSNxQEFaVIhAiKCMRLlzIhLkRbLIUIMx5KYJM0v6LcjW/mS6K7eFGwiIQKDzUflU23LeecRgzDo5IBCEvaWGfHW7JkNxzXvuc7FdCEDC5DtLoa61/Kk/pdpu0F9e6nKoRJIB9v7Ni377rZefgFTriIGAiKCMRLlzIhLkRbLIUIMx5KYJM0v6LcjW/mS6K7eFGwiHAIIy3cwAACAAQAAgAAAAIACAACAAAAAAAAAAAAiBgKDzUflU23LeecRgzDo5IBCEvaWGfHW7JkNxzXvuc7FdBwmu4PEMAAAgAEAAIAAAACAAgAAgAAAAAAAAAAAIgYDC5DtLoa61/Kk/pdpu0F9e6nKoRJIB9v7Ni377rZefgEcc8XaCjAAAIABAACAAAAAgAIAAIAAAAAAAAAAAAABAWlSIQKtIdmtKKuZrH7f2R4iIU8RWVOrCdHVWBCS+0e9pZJy/iEDoH074LrWPIA10hyXtBCJDT06GdLkA6+z/PxoJqomPHYhA6GoQ/otQdk71nUpYZFfbkSKdBkkSj4CuPTPYrzGp6JrU64iAgKtIdmtKKuZrH7f2R4iIU8RWVOrCdHVWBCS+0e9pZJy/hwCCMt3MAAAgAEAAIAAAACAAgAAgAEAAAAAAAAAIgIDoH074LrWPIA10hyXtBCJDT06GdLkA6+z/PxoJqomPHYcc8XaCjAAAIABAACAAAAAgAIAAIABAAAAAAAAACICA6GoQ/otQdk71nUpYZFfbkSKdBkkSj4CuPTPYrzGp6JrHCa7g8QwAACAAQAAgAAAAIACAACAAQAAAAAAAAAAAA=="
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(base64_psbt)
d.add_data(base64_psbt)
assert d.qrType() == QRType.PSBTBASE64
tx = d.getPSBT()
@@ -154,7 +154,7 @@ def test_base64_1_input_p2sh_p2wsh():
base64_psbt = "cHNidP8BAHICAAAAAR30J629i3Y/R8woRpLQ9JUa31rKxyM+Ny4NEsme48GWAAAAAAD9////Atw5XQUAAAAAF6kUdSESczdYagEyToVUSXyT8VTNz+OHgJaYAAAAAAAWABTmav7/w4OOcfCiewfjsA7eaujhYAAAAABPAQQ1h88EPmLffoAAAAHdXEj2dn8EYJ+rRdXEYu5laq6lJI5Mp+3t63ckwty05QKrJBNPewhwQaGPYRif6+XaxozFXvTXn7pU24H6fRy1FxQCCMt3MAAAgAEAAIAAAACAAQAAgE8BBDWHzwSdsdAAgAAAAeeOv56oeaaFTrNonMKDHk1C8brbWGFvdlecVue+v0/RAn/g4yI3oYsyen7OOcT7caYl4Mn7nQbyonHcusUR+GhzFCa7g8QwAACAAQAAgAAAAIABAACATwEENYfPBLrBSDmAAAABpzrb4oeEh2NNy/w/fr3osfyZTx7AaGDPAcP+LqeR3bYC5ioqmXPuazp69HwimlvecLylm9BLuyl/VpPXqiVrl20Uc8XaCjAAAIABAACAAAAAgAEAAIAAAQEgAOH1BQAAAAAXqRSv3gkn8731qcPbSDu4TJOlJJZ/PocBBCIAIOeiFBX5x0vX6CacrAUVovrs1DDCcKJS5qptFS3sjpDpAQVpUiECZ+pFYkOTVjB+eG+vQFA3MNjZWiA6DjRcs1Wl36A/zgMhA2Ygckuwjah29wiVRgA6wFx51+6ayrzeCIQ2eE4zfxPtIQOnUlBn22cn2CPCZkMSI6cDaZK2SlLV20rT6pqMoQCJsFOuIgYCZ+pFYkOTVjB+eG+vQFA3MNjZWiA6DjRcs1Wl36A/zgMcc8XaCjAAAIABAACAAAAAgAEAAIAAAAAAAAAAACIGA2Ygckuwjah29wiVRgA6wFx51+6ayrzeCIQ2eE4zfxPtHCa7g8QwAACAAQAAgAAAAIABAACAAAAAAAAAAAAiBgOnUlBn22cn2CPCZkMSI6cDaZK2SlLV20rT6pqMoQCJsBwCCMt3MAAAgAEAAIAAAACAAQAAgAAAAAAAAAAAAAEAIgAgZBwTq05RkpqKv6FV6LQjuM07Qv0/bYfWVc9NUQOFvwQBAWlSIQI32jVSdTgeu7+YZKrWfgOZ2J/LV36c5rBoApTzhrNlDCEC+hEqm3XmRt862AFFeyJ7p1m8A+V7czj6OajUNgCfg4EhA/MUVfxGh4k3Po3LB8CmMRsvIHcGNO0elUgETaITZA3UU64iAgI32jVSdTgeu7+YZKrWfgOZ2J/LV36c5rBoApTzhrNlDBwCCMt3MAAAgAEAAIAAAACAAQAAgAEAAAAAAAAAIgIC+hEqm3XmRt862AFFeyJ7p1m8A+V7czj6OajUNgCfg4EcJruDxDAAAIABAACAAAAAgAEAAIABAAAAAAAAACICA/MUVfxGh4k3Po3LB8CmMRsvIHcGNO0elUgETaITZA3UHHPF2gowAACAAQAAgAAAAIABAACAAQAAAAAAAAAAAA=="
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(base64_psbt)
d.add_data(base64_psbt)
assert d.qrType() == QRType.PSBTBASE64
tx = d.getPSBT()
@@ -208,7 +208,7 @@ def test_ur_legacy():
d = DecodeQR(wordlist=bip39.WORDLIST)
for i in qrcodes:
if d.addString(i) == DecodeQRStatus.COMPLETE:
if d.add_data(i) == DecodeQRStatus.COMPLETE:
break
assert d.qrType() == QRType.PSBTURLEGACY
@@ -242,7 +242,7 @@ def test_specter_multisig_animated_qr():
d = DecodeQR(wordlist=bip39.WORDLIST)
for i in qrcodes:
if d.addString(i) == DecodeQRStatus.COMPLETE:
if d.add_data(i) == DecodeQRStatus.COMPLETE:
break
assert d.qrType() == QRType.PSBTSPECTER
@@ -280,7 +280,7 @@ def test_specter_multisig_animated_qr():
d2 = DecodeQR(wordlist=bip39.WORDLIST)
for i in qrcodes2:
if d2.addString(i) == DecodeQRStatus.COMPLETE:
if d2.add_data(i) == DecodeQRStatus.COMPLETE:
break
assert d2.qrType() == QRType.PSBTSPECTER
@@ -313,22 +313,22 @@ def test_mnemonic_qr():
mnemonic = "height demise useless trap grow lion found off key clown transfer enroll"
d = DecodeQR(wordlist=bip39.WORDLIST)
assert d.addString(mnemonic) == DecodeQRStatus.COMPLETE
assert d.add_data(mnemonic) == DecodeQRStatus.COMPLETE
assert d.getSeedPhrase() == mnemonic.split()
bad_mnemonic = "height useless trap grow lion found off key clown transfer enroll"
d2 = DecodeQR(wordlist=bip39.WORDLIST)
assert d2.addString(bad_mnemonic) == DecodeQRStatus.INVALID
assert d2.add_data(bad_mnemonic) == DecodeQRStatus.INVALID
bad2_mnemonic = "words not in the list of bip39"
d3 = DecodeQR(wordlist=bip39.WORDLIST)
assert d3.addString(bad2_mnemonic) == DecodeQRStatus.INVALID
assert d3.add_data(bad2_mnemonic) == DecodeQRStatus.INVALID
def test_short_4_letter_mnemonic_qr():
short_nm = "heig demi usel trap grow lion foun off key clow tran enro"
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(short_nm)
d.add_data(short_nm)
assert d.isComplete() == True
assert d.getSeedPhrase() == ["height", "demise", "useless", "trap", "grow", "lion", "found", "off", "key", "clown", "transfer", "enroll"]
@@ -352,54 +352,54 @@ def test_bitcoin_address():
main_bech32_address3 = "BITCOIN:bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq?junk"
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(bad1)
d.add_data(bad1)
assert d.qrType() == QRType.INVALID
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(legacy_address1)
d.add_data(legacy_address1)
assert d.getAddress() == legacy_address1
assert d.getAddressType() == "P2PKH-main"
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(legacy_address2)
d.add_data(legacy_address2)
assert d.getAddress() == legacy_address2
assert d.getAddressType() == "P2PKH-main"
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(main_bech32_address)
d.add_data(main_bech32_address)
assert d.getAddress() == main_bech32_address
assert d.getAddressType() == "Bech32-main"
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(test_bech32_address)
d.add_data(test_bech32_address)
assert d.getAddress() == test_bech32_address
assert d.getAddressType() == "Bech32-test"
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(main_nested_segwit_address)
d.add_data(main_nested_segwit_address)
assert d.getAddress() == main_nested_segwit_address
assert d.getAddressType() == "P2SH-main"
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(test_nested_segwit_address)
d.add_data(test_nested_segwit_address)
assert d.getAddress() == test_nested_segwit_address
assert d.getAddressType() == "P2SH-test"
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(main_bech32_address2)
d.add_data(main_bech32_address2)
assert d.getAddress() == "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq"
assert d.getAddressType() == "Bech32-main"
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(main_bech32_address3)
d.add_data(main_bech32_address3)
assert d.getAddress() == "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq"
assert d.getAddressType() == "Bech32-main"
@@ -408,9 +408,9 @@ def test_seed_qr():
seed = "121802020768124106400009195602431595117715840445"
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(seed)
d.add_data(seed)
assert d.qrType() == QRType.SEEDSSQR
assert d.qrType() == QRType.SEEDQR
assert d.getSeedPhrase() == "obscure bone gas open exotic abuse virus bunker shuffle nasty ship dash".split()
def test_specter_wallet_json():
@@ -422,9 +422,9 @@ def test_specter_wallet_json():
]
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(parts[1])
d.addString(parts[2])
d.addString(parts[0])
d.add_data(parts[1])
d.add_data(parts[2])
d.add_data(parts[0])
assert d.qrType() == QRType.SPECTERWALLETQR
assert d.isComplete() == True
@@ -432,10 +432,10 @@ def test_specter_wallet_json():
def test_specter_wallet_json2():
1_part = '{"label": "Testnet Single Zone", "blockheight": 2090512, "descriptor": "wpkh([990a73ad/84h/1h/0h]tpubDDHQMDnFdan2GyHBsG32VW9qiygbhVizGRTjiS3H79M49FSvpsvLXqLgp1yC7r43dXVHozWavi2Fc4WHUpZmQYmzoQbit28qJhLjScbAQWU/0/*)#ujr0xunp","devices": [{"type": "seedsigner", "label": "Single Seed Zone Testnet"}]}'
part = '{"label": "Testnet Single Zone", "blockheight": 2090512, "descriptor": "wpkh([990a73ad/84h/1h/0h]tpubDDHQMDnFdan2GyHBsG32VW9qiygbhVizGRTjiS3H79M49FSvpsvLXqLgp1yC7r43dXVHozWavi2Fc4WHUpZmQYmzoQbit28qJhLjScbAQWU/0/*)#ujr0xunp","devices": [{"type": "seedsigner", "label": "Single Seed Zone Testnet"}]}'
d = DecodeQR(wordlist=bip39.WORDLIST)
d.addString(1_part)
d.add_data(part)
assert d.qrType() == QRType.SPECTERWALLETQR
assert d.isComplete() == True
+11 -1
View File
@@ -60,7 +60,7 @@ def test_seedsigner_qr():
mnemonic = "obscure bone gas open exotic abuse virus bunker shuffle nasty ship dash"
e = EncodeQR(seed_phrase=mnemonic.split(" "), qr_type=QRType.SEEDSSQR, wordlist=bip39.WORDLIST)
e = EncodeQR(seed_phrase=mnemonic.split(" "), qr_type=QRType.SEEDQR, wordlist=bip39.WORDLIST)
print(e.nextPart())
@@ -85,4 +85,14 @@ def test_specter_xpub_qr():
assert e.nextPart() == "p3of4 MxfrVggXj5NJmaNEToWpax8GMMucozvAdqf1bW1J"
assert e.nextPart() == "p4of4 sZsfdBzsK3VUC5"
def test_ur_xpub_qr():
mnemonic = "obscure bone gas open exotic abuse virus bunker shuffle nasty ship dash"
e = EncodeQR(seed_phrase=mnemonic.split(" "), passphrase="pass", qr_type=QRType.URXPUBQR, network="test", derivation="m/48h/1h/0h/2h", qr_density=EncodeQRDensity.MEDIUM, wordlist=bip39.WORDLIST)
assert e.nextPart() == "UR:CRYPTO-ACCOUNT/1-4/LPADAACSJKCYYNRDRTYAHDCAOEADCYSSMECPONAOLYTAADMETAADDLOXAXHDCLAOKSRLNLKPUEGYATHPMNRTAAOLAH"
assert e.nextPart() == "UR:CRYPTO-ACCOUNT/2-4/LPAOAACSJKCYYNRDRTYAHDCASNKKGHZMLUZORPVDGUOTECSTTKTOLPCWPTNTLKZTTIZTBEAAHDCXVDTPMYQDLAWNGL"
assert e.nextPart() == "UR:CRYPTO-ACCOUNT/3-4/LPAXAACSJKCYYNRDRTYAHDCARSTDSPZSBZSPGERLGDATUYNLPYBTGYIYYKBTWTAOSWKSVTSGCHBYDKYAVDSEPDJLAT"
assert e.nextPart() == "UR:CRYPTO-ACCOUNT/4-4/LPAAAACSJKCYYNRDRTYAHDCAAMTAADDYOEADLOCSDYYKADYKAEYKAOYKAOCYSSMECPONAYCYIOREKKJKAECADRRKIE"
+106
View File
@@ -0,0 +1,106 @@
import os
import pyzbar
from embit import bip39
from seedsigner.helpers.qr import QR
from seedsigner.helpers.ur2.bytewords import decode
from seedsigner.models.decode_qr import DecodeQR, DecodeQRStatus
from seedsigner.models.encode_qr import EncodeQR
from seedsigner.models.qr_type import QRType
def run_encode_decode_test(entropy: bytes, mnemonic_length, qr_type):
""" Helper method to re-run multiple variations of the same encode/decode test """
print(entropy)
seed_phrase = bip39.mnemonic_from_bytes(entropy).split()
print(seed_phrase)
assert len(seed_phrase) == mnemonic_length
e = EncodeQR(seed_phrase=seed_phrase, qr_type=qr_type, wordlist=bip39.WORDLIST)
data = e.nextPart()
print(data)
qr = QR()
image = qr.qrimage(
data=data,
width=240,
height=240,
border=3
)
decoder = DecodeQR(wordlist=bip39.WORDLIST)
status = decoder.addImage(image)
assert status == DecodeQRStatus.COMPLETE
decoded_seed_phrase = decoder.getSeedPhrase()
print(decoded_seed_phrase)
assert seed_phrase == decoded_seed_phrase
def test_standard_seedqr_encode_decode_():
""" Should encode 24- and 12- word mnemonics to Standard SeedQR format and decode
them back again to their original mnemonic seed phrase.
"""
# 24-word seed
run_encode_decode_test(os.urandom(32), mnemonic_length=24, qr_type=QRType.SEEDQR)
# 12-word seed
run_encode_decode_test(os.urandom(16), mnemonic_length=12, qr_type=QRType.SEEDQR)
def test_compact_seedqr_encode_decode():
""" Should encode 24- and 12- word mnemonics to CompactSeedQR format and decode
them back again to their original mnemonic seed phrase.
"""
# 24-word seed
run_encode_decode_test(os.urandom(32), mnemonic_length=24, qr_type=QRType.COMPACTSEEDQR)
# 12-word seed
run_encode_decode_test(os.urandom(16), mnemonic_length=12, qr_type=QRType.COMPACTSEEDQR)
def test_compact_seedqr_handles_null_bytes():
""" Should properly encode a CompactSeedQR with null bytes (b'\x00') in the input
entropy and decode it back to the original mnemonic seed.
"""
# 24-word seed, null bytes at the front
entropy = b'\x00' + os.urandom(31)
run_encode_decode_test(entropy, mnemonic_length=24, qr_type=QRType.COMPACTSEEDQR)
# 24-word seed, null bytes in the middle
entropy = os.urandom(10) + b'\x00' + os.urandom(21)
run_encode_decode_test(entropy, mnemonic_length=24, qr_type=QRType.COMPACTSEEDQR)
# 24-word seed, null bytes at the end
entropy = os.urandom(31) + b'\x00'
run_encode_decode_test(entropy, mnemonic_length=24, qr_type=QRType.COMPACTSEEDQR)
# 24-word seed, multiple null bytes
entropy = os.urandom(5) + b'\x00' + os.urandom(5) + b'\x00' + os.urandom(20)
run_encode_decode_test(entropy, mnemonic_length=24, qr_type=QRType.COMPACTSEEDQR)
# 24-word seed, multiple null bytes in a row
entropy = os.urandom(10) + b'\x00\x00' + os.urandom(20)
run_encode_decode_test(entropy, mnemonic_length=24, qr_type=QRType.COMPACTSEEDQR)
# 12-word seed, null bytes at the beginning
entropy = b'\x00' + os.urandom(15)
run_encode_decode_test(entropy, mnemonic_length=12, qr_type=QRType.COMPACTSEEDQR)
# 12-word seed, null bytes in the middle
entropy = os.urandom(5) + b'\x00' + os.urandom(10)
run_encode_decode_test(entropy, mnemonic_length=12, qr_type=QRType.COMPACTSEEDQR)
# 12-word seed, null bytes at the end
entropy = os.urandom(15) + b'\x00'
run_encode_decode_test(entropy, mnemonic_length=12, qr_type=QRType.COMPACTSEEDQR)
# 12-word seed, multiple null bytes
entropy = os.urandom(5) + b'\x00' + os.urandom(5) + b'\x00' + os.urandom(4)
run_encode_decode_test(entropy, mnemonic_length=12, qr_type=QRType.COMPACTSEEDQR)
# 12-word seed, multiple null bytes in a row
entropy = os.urandom(10) + b'\x00\x00' + os.urandom(4)
run_encode_decode_test(entropy, mnemonic_length=12, qr_type=QRType.COMPACTSEEDQR)