def test_pass_compatible_types(self): """ The request contains values that can be converted to the expected types. """ filter_ = self._filter({ 'hashes': [ # Any sequence that can be converted into a TransactionHash is # valid. binary_type(self.trytes1), bytearray(self.trytes2), ], }) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'hashes': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], }, )
def test_pass_compatible_types(self): """ The request contains values that can be converted to expected types. """ filter_ = self._filter({ 'transactions': [ binary_type(self.trytes1), bytearray(self.trytes2), ], 'tips': [ binary_type(self.trytes1), bytearray(self.trytes2), ], }) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'transactions': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], 'tips': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], }, )
def test_pass_all_parameters(self): """ The request contains valid values for all parameters. """ request = { 'bundles': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], 'addresses': [ Address(self.trytes1), Address(self.trytes2), ], 'tags': [ Tag(self.trytes1), Tag(self.trytes3), ], 'approvees': [ TransactionHash(self.trytes1), TransactionHash(self.trytes3), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual(filter_.cleaned_data, request)
def test_pass_approvees_only(self): """ The request only includes approvees. """ request = { 'approvees': [ TransactionHash(self.trytes1), TransactionHash(self.trytes3), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'approvees': [ TransactionHash(self.trytes1), TransactionHash(self.trytes3), ], 'addresses': [], 'bundles': [], 'tags': [], }, )
def test_search_results(self): """ The incoming response contains lots of hashes. """ filter_ = self._filter({ 'hashes': [ 'RVORZ9SIIP9RCYMREUIXXVPQIPHVCNPQ9HZWYKFW' 'YWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVA', 'ZJVYUGTDRPDYFGFXMKOTV9ZWSGFK9CFPXTITQLQN' 'LPPG9YNAARMKNKYQO9GSCSBIOTGMLJUFLZWSY9999', ], 'duration': 42, }) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'hashes': [ TransactionHash( b'RVORZ9SIIP9RCYMREUIXXVPQIPHVCNPQ9HZWYKFW' b'YWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVA', ), TransactionHash( b'ZJVYUGTDRPDYFGFXMKOTV9ZWSGFK9CFPXTITQLQN' b'LPPG9YNAARMKNKYQO9GSCSBIOTGMLJUFLZWSY9999', ), ], 'duration': 42, }, )
def setUp(self): super(GetAccountDataCommandTestCase, self).setUp() self.adapter = MockAdapter() self.command = GetAccountDataCommand(self.adapter) # Define some tryte sequences we can re-use between tests. self.addy1 =\ Address( b'TESTVALUEONE9DONTUSEINPRODUCTION99999YDZ' b'E9TAFAJGJA9CECKDAEPHBICDR9LHFCOFRBQDHC9IG', key_index = 0, ) self.addy2 =\ Address( b'TESTVALUETWO9DONTUSEINPRODUCTION99999TES' b'GINEIDLEEHRAOGEBMDLENFDAFCHEIHZ9EBZDD9YHL', key_index = 1, ) self.hash1 =\ TransactionHash( b'TESTVALUE9DONTUSEINPRODUCTION99999O99IDB' b'MBPAPDXBSDWAMHV9DASEGCOGHBV9VAF9UGRHFDPFJ' ) self.hash2 =\ TransactionHash( b'TESTVALUE9DONTUSEINPRODUCTION99999OCNCHC' b'TEPBHEPBJEWFXERHSCQCH9TAAANDBBCCHCIDEAVBV' )
def test_pass_happy_path(self): """ Typical ``getTransactionsToApprove`` response. """ response = { 'trunkTransaction': 'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW' 'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999', 'branchTransaction': 'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW' 'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999', 'duration': 936, } filter_ = self._filter(response) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'trunkTransaction': TransactionHash(b'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW' b'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999'), 'branchTransaction': TransactionHash(b'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW' b'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999'), 'duration': 936, }, )
def test_fail_tips_wrong_type(self): """ ``tips`` is not an array. """ self.assertFilterErrors( { 'tips': TransactionHash(self.trytes2), 'transactions': [TransactionHash(self.trytes1)], }, { 'tips': [f.Type.CODE_WRONG_TYPE], }, )
def test_pass_happy_path(self): """ Request is valid. """ request = { 'hashes': [TransactionHash(self.hash1), TransactionHash(self.hash2)], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual(filter_.cleaned_data, request)
def test_fail_min_weight_magnitude_null(self): """ ``minWeightMagnitude`` is null. """ self.assertFilterErrors( { 'minWeightMagnitude': None, 'branchTransaction': TransactionHash(self.txn_id), 'trunkTransaction': TransactionHash(self.txn_id), 'trytes': [TryteString(self.trytes1)], }, { 'minWeightMagnitude': [f.Required.CODE_EMPTY], }, )
def test_fail_min_weight_magnitude_too_small(self): """ ``minWeightMagnitude`` is less than 1. """ self.assertFilterErrors( { 'minWeightMagnitude': 0, 'branchTransaction': TransactionHash(self.txn_id), 'trunkTransaction': TransactionHash(self.txn_id), 'trytes': [TryteString(self.trytes1)], }, { 'minWeightMagnitude': [f.Min.CODE_TOO_SMALL], }, )
def test_fail_trytes_null(self): """ ``trytes`` is null. """ self.assertFilterErrors( { 'trytes': None, 'branchTransaction': TransactionHash(self.txn_id), 'minWeightMagnitude': 13, 'trunkTransaction': TransactionHash(self.txn_id), }, { 'trytes': [f.Required.CODE_EMPTY], }, )
def test_fail_min_weight_magnitude_float(self): """ ``minWeightMagnitude`` is a float. """ self.assertFilterErrors( { # I don't care if the fpart is empty; it's still not an int! 'minWeightMagnitude': 20.0, 'branchTransaction': TransactionHash(self.txn_id), 'trunkTransaction': TransactionHash(self.txn_id), 'trytes': [TryteString(self.trytes1)], }, { 'minWeightMagnitude': [f.Type.CODE_WRONG_TYPE], }, )
def test_fail_tips_contents_invalid(self): """ ``tips`` contains invalid values. """ self.assertFilterErrors( { 'tips': [ b'', text_type(self.trytes1, 'ascii'), True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes1), 2130706433, b'9' * 82, ], 'transactions': [TransactionHash(self.trytes1)], }, { 'tips.0': [f.Required.CODE_EMPTY], 'tips.1': [f.Type.CODE_WRONG_TYPE], 'tips.2': [f.Type.CODE_WRONG_TYPE], 'tips.3': [f.Required.CODE_EMPTY], 'tips.4': [Trytes.CODE_NOT_TRYTES], 'tips.6': [f.Type.CODE_WRONG_TYPE], 'tips.7': [Trytes.CODE_WRONG_FORMAT], }, )
def test_fail_min_weight_magnitude_string(self): """ ``minWeightMagnitude`` is a string. """ self.assertFilterErrors( { # For want of an int cast, the transaction was lost. 'minWeightMagnitude': '20', 'branchTransaction': TransactionHash(self.txn_id), 'trunkTransaction': TransactionHash(self.txn_id), 'trytes': [TryteString(self.trytes1)], }, { 'minWeightMagnitude': [f.Type.CODE_WRONG_TYPE], }, )
def test_pass_compatible_types(self): """ Incoming values can be converted into the expected types. """ filter_ = self._filter({ # Any value that can be converted into a TransactionHash is valid # here. 'trunkTransaction': binary_type(self.txn_id), 'branchTransaction': bytearray(self.txn_id), 'trytes': [ # ``trytes`` can contain any value that can be converted into a # TryteString. binary_type(self.trytes1), # This is probably wrong, but technically it's valid. TransactionHash( b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA', ), ], # This still has to be an int, however. 'minWeightMagnitude': 30, }) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, # After running through the filter, all of the values have been # converted to the correct types. { 'trunkTransaction': TransactionHash(self.txn_id), 'branchTransaction': TransactionHash(self.txn_id), 'minWeightMagnitude': 30, 'trytes': [ TransactionTrytes(self.trytes1), TransactionTrytes( b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHD' b'WCTCEAKDCDFD9DSCSA99999999999999999999999', ), ], })
def test_fail_trytes_wrong_type(self): """ ``trytes`` is not an array. """ self.assertFilterErrors( { # You have to specify an array, even if you only want to attach # a single tryte sequence. 'trytes': TryteString(self.trytes1), 'branchTransaction': TransactionHash(self.txn_id), 'minWeightMagnitude': 13, 'trunkTransaction': TransactionHash(self.txn_id), }, { 'trytes': [f.Type.CODE_WRONG_TYPE], }, )
def test_pass_compatible_types(self): """ The request contains values that can be converted to the expected types. """ filter_ = self._filter({ 'bundles': [ binary_type(self.trytes1), bytearray(self.trytes2), ], 'addresses': [ binary_type(self.trytes1), bytearray(self.trytes2), ], 'tags': [ binary_type(self.trytes1), bytearray(self.trytes3), ], 'approvees': [ binary_type(self.trytes1), bytearray(self.trytes3), ], }) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'bundles': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], 'addresses': [ Address(self.trytes1), Address(self.trytes2), ], 'tags': [ Tag(self.trytes1), Tag(self.trytes3), ], 'approvees': [ TransactionHash(self.trytes1), TransactionHash(self.trytes3), ], }, )
def test_fail_trytes_empty(self): """ ``trytes`` is an array, but it's empty. """ self.assertFilterErrors( { # Ok, you got the list part down, but you have to put something # inside it. 'trytes': [], 'branchTransaction': TransactionHash(self.txn_id), 'minWeightMagnitude': 13, 'trunkTransaction': TransactionHash(self.txn_id), }, { 'trytes': [f.Required.CODE_EMPTY], }, )
def test_non_tail_transaction(self): """ Trying to get a bundle for a non-tail transaction. This is not valid; you have to start with a tail transaction. """ self.adapter.seed_response( 'getTrytes', { 'trytes': [ b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999999999999999999999999999999999999999999999999999999999999' b'999999999WUQXEGBVIECGIWO9IGSYKWWPYCIVUJJGSJPWGIAFJPYSF9NSQOHWAHS9P' b'9PWQHOBXNNQIF9IRHVQXKPZW999999999999999999999999999999999999999999' b'999999999999HNLFMVD99A99999999A99999999PDQWLVVDPUU9VIBODGMRIAZPGQX' b'DOGSEXIHKIBWSLDAWUKZCZMK9Z9YZSPCKBDJSVDPRQLJSTKUMTNVSXBGUEHHGAIWWQ' b'BCJZHZAQOWZMAIDAFUZBVMUVPWQJLUGGQKNKLMGTWXXNZKUCBJLEDAMYVRGABAWBY9' b'999MYIYBTGIOQYYZFJBLIAWMPSZEFFTXUZPCDIXSLLQDQSFYGQSQOGSPKCZNLVSZ9L' b'MCUWVNGEN9EJEW9999XZUIENOTTBKJMDPRXWGQYG9PWGTXUO9AXMP9FLMDRMADLRPW' b'CZCJBROYCDRJMYU9HDYJM9NDBFUPIZVTR' ], }) with self.assertRaises(BadApiResponse): self.command(transaction=TransactionHash( b'FSEWUNJOEGNUI9QOCRFMYSIFAZLJHKZBPQZZYFG9' b'ORYCRDX9TOMJPFCRB9R9KPUUGFPVOWYXFIWEW9999'), )
def test_fail_unexpected_parameters(self): """ The request contains unexpected parameters. """ self.assertFilterErrors( { 'addresses': [Address(self.trytes1)], 'approvees': [TransactionHash(self.trytes1)], 'bundles': [TransactionHash(self.trytes1)], 'tags': [Tag(self.trytes1)], # Hey, you're not allowed in he-argh! 'foo': 'bar', }, { 'foo': [f.FilterMapper.CODE_EXTRA_KEY], }, )
def test_fail_unexpected_parameters(self): """ The incoming request contains unexpected parameters. """ self.assertFilterErrors( { 'branchTransaction': TransactionHash(self.txn_id), 'minWeightMagnitude': 20, 'trunkTransaction': TransactionHash(self.txn_id), 'trytes': [TryteString(self.trytes1)], # Hey, how'd that get in there? 'foo': 'bar', }, { 'foo': [f.FilterMapper.CODE_EXTRA_KEY], }, )
def test_pass_happy_path(self): """ Request is valid. """ request = {'transaction': TransactionHash(self.transaction)} filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual(filter_.cleaned_data, request)
def test_missing_transaction(self): """ Unable to find the requested transaction. """ self.adapter.seed_response('getTrytes', {'trytes': []}) with self.assertRaises(BadApiResponse): self.command(transaction=TransactionHash( b'FSEWUNJOEGNUI9QOCRFMYSIFAZLJHKZBPQZZYFG9' b'ORYCRDX9TOMJPFCRB9R9KPUUGFPVOWYXFIWEW9999'), )
def test_fail_approvees_wrong_type(self): """ ``approvees`` is not an array. """ self.assertFilterErrors( { 'approvees': TransactionHash(self.trytes1), }, { 'approvees': [f.Type.CODE_WRONG_TYPE], }, )
def test_pass_happy_path(self): """ The incoming request is valid. """ request = { 'trunkTransaction': TransactionHash(self.txn_id), 'branchTransaction': TransactionHash(self.txn_id), 'minWeightMagnitude': 20, 'trytes': [ TransactionTrytes(self.trytes1), TransactionTrytes(self.trytes2), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual(filter_.cleaned_data, request)
def test_start(self): """ Using ``start`` to offset the key range. """ self.adapter.seed_response('getBalances', { 'balances': [86], }) # ``getInputs`` uses ``findTransactions`` to identify unused # addresses. # noinspection SpellCheckingInspection self.adapter.seed_response( 'findTransactions', { 'hashes': [ TransactionHash( b'TESTVALUE9DONTUSEINPRODUCTION99999YFXGOD' b'GISBJAX9PDJIRDMDV9DCRDCAEG9FN9KECCBDDFZ9H'), ], }) self.adapter.seed_response('findTransactions', { 'hashes': [], }) # To keep the unit test nice and speedy, we will mock the address # generator. We already have plenty of unit tests for that # functionality, so we can get away with mocking it here. # noinspection PyUnusedLocal def mock_address_generator(ag, start, step=1): # If ``start`` has the wrong value, return garbage to make the # test asplode. for addy in [None, self.addy1, self.addy2][start::step]: yield addy # When ``stop`` is None, the command uses a generator internally. with patch( 'cornode.crypto.addresses.AddressGenerator.create_iterator', mock_address_generator, ): response = self.command( seed=Seed.random(), start=1, ) self.assertEqual(response['totalBalance'], 86) self.assertEqual(len(response['inputs']), 1) input0 = response['inputs'][0] self.assertIsInstance(input0, Address) self.assertEqual(input0, self.addy1) self.assertEqual(input0.balance, 86) self.assertEqual(input0.key_index, 1)
def test_fail_hashes_wrong_type(self): """ ``hashes`` is not an array. """ self.assertFilterErrors( { # It's gotta be an array, even if there's only one hash. 'hashes': TransactionHash(self.hash1), }, { 'hashes': [f.Type.CODE_WRONG_TYPE], }, )
def test_pass_happy_path(self): """ Typical ``getInclusionStates`` request. """ request = { 'transactions': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], 'tips': [ # These values would normally be different from # ``transactions``, but for purposes of this unit test, we just # need to make sure the format is correct. TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual(filter_.cleaned_data, request)
def test_pass_optional_parameters_omitted(self): """ The request omits optional parameters. """ filter_ = self._filter({ 'transactions': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], }) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'tips': [], 'transactions': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], }, )