import pytest
from argparse import Namespace
import private_key_to_address as pa




# Notes:
# - "work directory" = directory that contains this file.
# - Running the command {pytest} in the work directory should load and run the tests in this file.
# -- You can also use: { pytest test_private_key_to_address.py }
# - Run a specific test:
# -- pytest test_private_key_to_address.py::test_1
# - Run quietly:
# -- pytest -q
# - Print log data during a single test:
# -- pytest -o log_cli=true --log-cli-level=DEBUG --log-format="%(levelname)s [%(lineno)s: %(funcName)s] %(message)s" test_private_key_to_address.py::test_1
# -- This is very useful when you want to manually check the operation of the functions during the test.




# Rename function for convenience. 
f1 = pa.deriveBitcoinAddress




# Global config.
# - n is the order of the base point G of the elliptic curve secp256k1.
# - The domain of a bitcoin private key is [1,n-1].
n_hex = "FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141".replace(' ','')
n_int = int(n_hex, 16)




### TEST SECTION
# Basic domain checks. 


def test_zero():
	# private key must be at least 1.
	privateKey = '00'*32
	with pytest.raises(Exception):
		address = f1(privateKey)


def test_one():
	privateKey = '00'*31 + '01'
	address = f1(privateKey)
	expectedAddress ='1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm'
	assert address == expectedAddress


def test_inside_domain():
	privateKey = '55'*32
	address = f1(privateKey)
	expectedAddress = '1HGnVyPcaVD9uBe17BdH49ZUhB9kGuGCEj'
	assert address == expectedAddress


def test_outside_domain():
	# This value is outside the acceptable domain for a private key.
	privateKey = 'ff'*32
	with pytest.raises(Exception):
		address = f1(privateKey)


def test_n_minus_1():
	privateKey = '{:x}'.format(n_int - 1)
	address = f1(privateKey)
	expectedAddress = '1JPbzbsAx1HyaDQoLMapWGoqf9pD5uha5m'
	assert address == expectedAddress


def test_n():
	# This value is outside the acceptable domain for a private key.
	privateKey = '{:x}'.format(n_int)
	with pytest.raises(Exception):
		address = f1(privateKey)


def test_n_plus_1():
	# This value is outside the acceptable domain for a private key.
	privateKey = '{:x}'.format(n_int + 1)
	with pytest.raises(Exception):
		address = f1(privateKey)




### TEST SECTION
# Test data source:
# http://edgecase.net/articles/bitcoin_address_test_set


def test_pair_1():
	privateKey = '0000000000000000000000007468655f6c6962726172795f6f665f626162656c'
	expectedAddress = '1CTumCMjzBfccCJBTkHoPQmAwEqU9Uj2sQ'
	address = f1(privateKey)
	assert address == expectedAddress


def test_pair_2():
	privateKey = '000000000000000000000000000000007468655f6579655f6f665f6172676f6e'
	expectedAddress = '12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f'
	address = f1(privateKey)
	assert address == expectedAddress


# Test the rest of the address test set in one go.
pairs1 = [	
	('00000000000000000000000000000000000000000068656c6c6f5f776f726c64', '19VdGCFG8QH3CmYXjMXd3UQCK2HdC3UodP'),
	('b675ceedba0843d19934d1e0508cde736b4bb7f0a56b9585329ebcbfed559346', '1FJdRWN7tAd8rnivBm7yojppwvDmS7F55X'),
	('00000000000000000000007468655f6d6f74655f696e5f676f6427735f657965', '138obEZkdWaWEQ4x8ZAYw4MybHSZtX1Nam'),
	('0000000000000000000000000000000000726f6164736964655f7069636e6963', '13xPBB175FtPbPQ84iB8KuawaVy3mHrady'), 
	('a26e15954d2dafcee70eeaaa084eab8a4c1a30b0f71a42be4d8da20123bff121', '1AGygbyEFYduWkkmZbbvirgS9kuBBMLJCP'),
	('c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca', '1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK'),
	('1fbc45dc460d14c07bcac41b8e17649455e92d9bfda29a89ba3addeee0eccaaa', '17rEGTR4ss7xhVVMwL969Y8xszS7FaFsae'),
	('7972b641101c0ad67b0e401b800a9b6f3225c97fc6b8115042cf66968c2fb2e5', '16ASCUS3s7D4UQh6J9oHGuT19agPvD3PFj'),
	('d45941cae4e31c824b041407053c9c15624e6234f9649bfd7d5bb5a93c53fe85', '1KHDLNmqBtiBELUsmTCkNASg79jfEVKrig'),
	('1faf3c86105fe6ee328b29e94197de7e8500ddb8308385a9a8b0cba08d59ce27', '1DLg5i1kBjXYXy9f82xZcHokEMC9dtct7P'),
	('7a0d11f6015f941ea486922e45310535c5b71c59d8489447648eebdb6a39e2a8', '17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn'),
	('cbac84458fcfbb39f87fca7ab9a9ef2f76812a6f999a75dfa25dbcbb0ee3eb6f', '1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8'),
	('7d37c1a74d3b87d3994ac6db65b4f298f64a8ed6144edfdb2cacea70cf3070af', '19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4'),
	('419292d169b515be1aec881018157f0a41883ea54da2b2405e10fd8a6abb76ec', '17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s'),
	('dd23f217012efd9ac3dec71d0c2b42212a58bff75d9e97af900403cf5657bad3', '15BLTZb6uQr24MrxqXJaPpRGz1tKrzq7iC'),
]


@pytest.mark.parametrize('privateKey,expectedAddress', pairs1)
def test_multiple_pairs(privateKey, expectedAddress):
	address = f1(privateKey)
	assert address == expectedAddress