Ejemplo n.º 1
0
  def test_routing(self):
    """
    Routing commands to different adapters.
    """
    default_adapter = MockAdapter()
    pow_adapter     = MockAdapter()

    wrapper = (
      RoutingWrapper(default_adapter)
        .add_route('attachToTangle', pow_adapter)
        .add_route('interruptAttachingToTangle', pow_adapter)
    )

    default_adapter.seed_response('getNodeInfo', {'id': 'default1'})
    pow_adapter.seed_response('attachToTangle', {'id': 'pow1'})
    pow_adapter.seed_response('interruptAttachingToTangle', {'id': 'pow2'})

    self.assertDictEqual(
      wrapper.send_request({'command': 'attachToTangle'}),
      {'id': 'pow1'},
    )

    self.assertDictEqual(
      wrapper.send_request({'command': 'interruptAttachingToTangle'}),
      {'id': 'pow2'},
    )

    # Any commands that aren't routed go to the default adapter.
    self.assertDictEqual(
      wrapper.send_request({'command': 'getNodeInfo'}),
      {'id': 'default1'},
    )
Ejemplo n.º 2
0
  def setUp(self):
    super(GetInputsCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = GetInputsCommand(self.adapter)

    # Define some valid tryte sequences that we can reuse between
    # tests.
    self.addy0 =\
      Address(
        trytes =
          b'TESTVALUE9DONTUSEINPRODUCTION99999FIODSG'
          b'IC9CCIFCNBTBDFIEHHE9RBAEVGK9JECCLCPBIINAX',

        key_index = 0,
      )

    self.addy1 =\
      Address(
        trytes =
          b'TESTVALUE9DONTUSEINPRODUCTION999999EPCNH'
          b'MBTEH9KDVFMHHESDOBTFFACCGBFGACEDCDDCGICIL',

        key_index = 1,
      )

    self.addy2 =\
      Address(
        trytes =
          b'TESTVALUE9DONTUSEINPRODUCTION99999YDOHWF'
          b'U9PFOFHGKFACCCBGDALGI9ZBEBABFAMBPDSEQ9XHJ',

        key_index = 2,
      )
Ejemplo n.º 3
0
  def setUp(self):
    super(GetNewAddressesCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = GetNewAddressesCommand(self.adapter)

    self.seed =\
      Seed(
        b'TESTVALUE9DONTUSEINPRODUCTION99999ZDCCUF'
        b'CBBIQCLGMEXAVFQEOF9DRAB9VCEBAGXAF9VF9FLHP',
      )

    self.addy_1 =\
      Address(
        b'NYMWLBUJEISSACZZBRENC9HEHYQXHCGQHSNHVCEA'
        b'ZDCTEVNGSDUEKTSYBSQGMVJRIEDHWDYSEYCFAZAH9',
      )

    self.addy_2 =\
      Address(
        b'NTPSEVZHQITARYWHIRTSIFSERINLRYVXLGIQKKHY'
        b'IWYTLQUUHDWSOVXLIKVJTYZBFKLABWRBFYVSMD9NB',
      )

    self.addy_1_checksum =\
      Address(
        b'NYMWLBUJEISSACZZBRENC9HEHYQXHCGQHSNHVCEA'
        b'ZDCTEVNGSDUEKTSYBSQGMVJRIEDHWDYSEYCFAZAH'
        b'9T9FPJROTW',
      )
class BroadcastAndStoreCommandTestCase(TestCase):
  # noinspection SpellCheckingInspection
  def setUp(self):
    super(BroadcastAndStoreCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = BroadcastAndStoreCommand(self.adapter)

    # Define a few valid values that we can reuse across tests.
    self.trytes1 = b'RBTC9D9DCDQAEASBYBCCKBFA'
    self.trytes2 =\
      b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA'

  def test_wireup(self):
    """
    Verify that the command is wired up correctly.
    """
    self.assertIsInstance(
      Iota(self.adapter).broadcastAndStore,
      BroadcastAndStoreCommand,
    )

  def test_happy_path(self):
    """
    Successful invocation of ``broadcastAndStore``.
    """
    self.adapter.seed_response('broadcastTransactions', {
      'trytes': [
        text_type(self.trytes1, 'ascii'),
        text_type(self.trytes2, 'ascii'),
      ],
    })

    self.adapter.seed_response('storeTransactions', {})

    trytes = [
      TransactionTrytes(self.trytes1),
      TransactionTrytes(self.trytes2),
    ]

    response = self.command(trytes=trytes)

    self.assertDictEqual(response, {'trytes': trytes})
  def setUp(self):
    super(BroadcastAndStoreCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = BroadcastAndStoreCommand(self.adapter)

    # Define a few valid values that we can reuse across tests.
    self.trytes1 = b'RBTC9D9DCDQAEASBYBCCKBFA'
    self.trytes2 =\
      b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA'
Ejemplo n.º 6
0
  def setUp(self):
    super(GetTransfersCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = GetTransfersCommand(self.adapter)

    # Define some tryte sequences we can re-use between tests.
    self.addy1 =\
      Address(
        b'TESTVALUEONE9DONTUSEINPRODUCTION99999YDZ'
        b'E9TAFAJGJA9CECKDAEPHBICDR9LHFCOFRBQDHC9IG'
      )

    self.addy2 =\
      Address(
        b'TESTVALUETWO9DONTUSEINPRODUCTION99999TES'
        b'GINEIDLEEHRAOGEBMDLENFDAFCHEIHZ9EBZDD9YHL'
      )
  def setUp(self):
    super(GetLatestInclusionCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = GetLatestInclusionCommand(self.adapter)

    # Define some tryte sequences that we can re-use across tests.
    self.milestone =\
      TransactionHash(
        b'TESTVALUE9DONTUSEINPRODUCTION99999W9KDIH'
        b'BALAYAFCADIDU9HCXDKIXEYDNFRAKHN9IEIDZFWGJ'
      )

    self.hash1 =\
      TransactionHash(
        b'TESTVALUE9DONTUSEINPRODUCTION99999TBPDM9'
        b'ADFAWCKCSFUALFGETFIFG9UHIEFE9AYESEHDUBDDF'
      )

    self.hash2 =\
      TransactionHash(
        b'TESTVALUE9DONTUSEINPRODUCTION99999CIGCCF'
        b'KIUFZF9EP9YEYGQAIEXDTEAAUGAEWBBASHYCWBHDX'
      )
Ejemplo n.º 8
0
  def setUp(self):
    super(CustomCommandTestCase, self).setUp()

    self.name     = 'helloWorld'
    self.adapter  = MockAdapter()
    self.command  = CustomCommand(self.adapter, self.name)
Ejemplo n.º 9
0
class StoreTransactionsRequestFilterTestCase(BaseFilterTestCase):
    filter_type = StoreTransactionsCommand(MockAdapter()).get_request_filter
    skip_value_check = True

    # noinspection SpellCheckingInspection
    def setUp(self):
        super(StoreTransactionsRequestFilterTestCase, self).setUp()

        # Define a few valid values here that we can reuse across multiple
        # tests.
        self.trytes1 = 'RBTC9D9DCDQAEASBYBCCKBFA'
        self.trytes2 =\
          'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA'

    def test_pass_happy_path(self):
        """
    The incoming request is valid.
    """
        request = {
            # Raw trytes are extracted to match the IRI's JSON protocol.
            'trytes': [
                text_type(TransactionTrytes(self.trytes1)),
                text_type(TransactionTrytes(self.trytes2)),
            ],
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)

    def test_pass_compatible_types(self):
        """
    The incoming request contains values that can be converted into the
    expected types.
    """
        filter_ = self._filter({
            # Any value that can be converted into an ASCII representation of
            # a TryteString is allowed here.
            'trytes': [
                TransactionTrytes(self.trytes1),
                bytearray(self.trytes2.encode('ascii')),
            ],
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                # Raw trytes are extracted to match the IRI's JSON protocol.
                'trytes': [
                    text_type(TransactionTrytes(self.trytes1)),
                    text_type(TransactionTrytes(self.trytes2)),
                ],
            },
        )

    def test_fail_empty(self):
        """
    The incoming request is empty.
    """
        self.assertFilterErrors(
            {},
            {
                'trytes': [f.FilterMapper.CODE_MISSING_KEY],
            },
        )

    def test_fail_unexpected_parameters(self):
        """
    The incoming value contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'trytes': [TryteString(self.trytes1)],

                # Alright buddy, let's see some ID.
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )

    def test_fail_trytes_null(self):
        """
    ``trytes`` is null.
    """
        self.assertFilterErrors(
            {
                'trytes': None,
            },
            {
                'trytes': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_trytes_wrong_type(self):
        """
    ``trytes`` is not an array.
    """
        self.assertFilterErrors(
            {
                # ``trytes`` has to be an array, even if there's only one
                # TryteString.
                'trytes': TryteString(self.trytes1),
            },
            {
                'trytes': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_trytes_empty(self):
        """
    ``trytes`` is an array, but it's empty.
    """
        self.assertFilterErrors(
            {
                'trytes': [],
            },
            {
                'trytes': [f.Required.CODE_EMPTY],
            },
        )

    def test_trytes_contents_invalid(self):
        """
    ``trytes`` is an array, but it contains invalid values.
    """
        self.assertFilterErrors(
            {
                'trytes': [
                    b'',
                    True,
                    None,
                    b'not valid trytes',

                    # This is actually valid; I just added it to make sure the
                    # filter isn't cheating!
                    TryteString(self.trytes2),
                    2130706433,
                    b'9' * (TransactionTrytes.LEN + 1),
                ],
            },
            {
                'trytes.0': [f.NotEmpty.CODE_EMPTY],
                'trytes.1': [f.Type.CODE_WRONG_TYPE],
                'trytes.2': [f.Required.CODE_EMPTY],
                'trytes.3': [Trytes.CODE_NOT_TRYTES],
                'trytes.5': [f.Type.CODE_WRONG_TYPE],
                'trytes.6': [Trytes.CODE_WRONG_FORMAT],
            },
        )
Ejemplo n.º 10
0
class SendTransferRequestFilterTestCase(BaseFilterTestCase):
    filter_type = SendTransferCommand(MockAdapter()).get_request_filter
    skip_value_check = True

    # noinspection SpellCheckingInspection
    def setUp(self):
        super(SendTransferRequestFilterTestCase, self).setUp()

        # Define some tryte sequences that we can reuse between tests.
        self.trytes1 = (b'TESTVALUEONE9DONTUSEINPRODUCTION99999JBW'
                        b'GEC99GBXFFBCHAEJHLC9DX9EEPAI9ICVCKBX9FFII')

        self.trytes2 = (b'TESTVALUETWO9DONTUSEINPRODUCTION99999THZ'
                        b'BODYHZM99IR9KOXLZXVUOJM9LQKCQJBWMTY999999')

        self.trytes3 = (b'TESTVALUETHREE9DONTUSEINPRODUCTIONG99999'
                        b'GTQ9CSNUFPYW9MBQ9LFQJSORCF9LGTY9BWQFY9999')

        self.trytes4 = (b'TESTVALUEFOUR9DONTUSEINPRODUCTION99999ZQ'
                        b'HOGCBZCOTZVZRFBEHQKHENBIZWDTUQXTOVWEXRIK9')

        self.transfer1 =\
          ProposedTransaction(
            address =
              Address(
                b'TESTVALUEFIVE9DONTUSEINPRODUCTION99999MG'
                b'AAAHJDZ9BBG9U9R9XEOHCBVCLCWCCCCBQCQGG9WHK'
              ),

            value = 42,
          )

        self.transfer2 =\
          ProposedTransaction(
            address =
              Address(
                b'TESTVALUESIX9DONTUSEINPRODUCTION99999GGT'
                b'FODSHHELBDERDCDRBCINDCGQEI9NAWDJBC9TGPFME'
              ),

            value = 86,
          )

    def test_pass_happy_path(self):
        """
    Request is valid.
    """
        request = {
            'changeAddress': Address(self.trytes1),
            'depth': 100,
            'minWeightMagnitude': 18,
            'seed': Seed(self.trytes2),
            'inputs': [
                Address(self.trytes3),
                Address(self.trytes4),
            ],
            'transfers': [self.transfer1, self.transfer2],
            'reference': TransactionHash(self.trytes1),
            'securityLevel': AddressGenerator.DEFAULT_SECURITY_LEVEL,
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)

    def test_pass_compatible_types(self):
        """
    Request contains values that can be converted to the expected
    types.
    """
        filter_ = self._filter({
            # Any TrytesCompatible values will work here.
            'changeAddress':
            binary_type(self.trytes1),
            'seed':
            bytearray(self.trytes2),
            'reference':
            binary_type(self.trytes1),
            'inputs': [
                binary_type(self.trytes3),
                bytearray(self.trytes4),
            ],

            # These values must have the correct type, however.
            'transfers': [self.transfer1, self.transfer2],
            'depth':
            100,
            'minWeightMagnitude':
            18,
            'securityLevel':
            None,
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data, {
                'changeAddress': Address(self.trytes1),
                'depth': 100,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes2),
                'reference': TransactionHash(self.trytes1),
                'inputs': [
                    Address(self.trytes3),
                    Address(self.trytes4),
                ],
                'transfers': [self.transfer1, self.transfer2],
                'securityLevel': AddressGenerator.DEFAULT_SECURITY_LEVEL
            })

    def test_pass_optional_parameters_omitted(self):
        """
    Request omits optional parameters.
    """
        filter_ = self._filter({
            'depth': 100,
            'minWeightMagnitude': 13,
            'seed': Seed(self.trytes2),
            'transfers': [self.transfer1, self.transfer2],
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data, {
                'changeAddress': None,
                'inputs': None,
                'reference': None,
                'depth': 100,
                'minWeightMagnitude': 13,
                'securityLevel': AddressGenerator.DEFAULT_SECURITY_LEVEL,
                'seed': Seed(self.trytes2),
                'transfers': [self.transfer1, self.transfer2],
            })

    def test_fail_empty(self):
        """
    Request is empty.
    """
        self.assertFilterErrors(
            {},
            {
                'depth': [f.FilterMapper.CODE_MISSING_KEY],
                'minWeightMagnitude': [f.FilterMapper.CODE_MISSING_KEY],
                'seed': [f.FilterMapper.CODE_MISSING_KEY],
                'transfers': [f.FilterMapper.CODE_MISSING_KEY],
            },
        )

    def test_fail_unexpected_parameters(self):
        """
    Request contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'depth': 100,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],

                # Maybe he's not that smart; maybe he's like a worker bee who
                # only knows how to push buttons or something.
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )

    def test_fail_seed_null(self):
        """
    ``seed`` is null.
    """
        self.assertFilterErrors(
            {
                'seed': None,
                'depth': 100,
                'minWeightMagnitude': 18,
                'transfers': [self.transfer1],
            },
            {
                'seed': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_seed_wrong_type(self):
        """
    ``seed`` is not a TrytesCompatible value.
    """
        self.assertFilterErrors(
            {
                'seed': 42,
                'depth': 100,
                'minWeightMagnitude': 18,
                'transfers': [self.transfer1],
            },
            {
                'seed': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_seed_not_trytes(self):
        """
    ``seed`` contains invalid characters.
    """
        self.assertFilterErrors(
            {
                'seed': b'not valid; must contain only uppercase and "9"',
                'depth': 100,
                'minWeightMagnitude': 18,
                'transfers': [self.transfer1],
            },
            {
                'seed': [Trytes.CODE_NOT_TRYTES],
            },
        )

    def test_fail_transfers_wrong_type(self):
        """
    ``transfers`` is not an array.
    """
        self.assertFilterErrors(
            {
                'transfers': self.transfer1,
                'depth': 100,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
            },
            {
                'transfers': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_transfers_empty(self):
        """
    ``transfers`` is an array, but it is empty.
    """
        self.assertFilterErrors(
            {
                'transfers': [],
                'depth': 100,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
            },
            {
                'transfers': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_transfers_contents_invalid(self):
        """
    ``transfers`` is a non-empty array, but it contains invalid values.
    """
        self.assertFilterErrors(
            {
                'transfers': [
                    None,

                    # This value is valid; just adding it to make sure the filter
                    # doesn't cheat!
                    ProposedTransaction(address=Address(self.trytes2),
                                        value=42),
                    {
                        'address': Address(self.trytes2),
                        'value': 42
                    },
                ],
                'depth':
                100,
                'minWeightMagnitude':
                18,
                'seed':
                Seed(self.trytes1),
            },
            {
                'transfers.0': [f.Required.CODE_EMPTY],
                'transfers.2': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_change_address_wrong_type(self):
        """
    ``changeAddress`` is not a TrytesCompatible value.
    """
        self.assertFilterErrors(
            {
                'changeAddress': 42,
                'depth': 100,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'changeAddress': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_change_address_not_trytes(self):
        """
    ``changeAddress`` contains invalid characters.
    """
        self.assertFilterErrors(
            {
                'changeAddress':
                b'not valid; must contain only uppercase and "9"',
                'depth': 100,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'changeAddress': [Trytes.CODE_NOT_TRYTES],
            },
        )

    def test_fail_inputs_wrong_type(self):
        """
    ``inputs`` is not an array.
    """
        self.assertFilterErrors(
            {
                # Must be an array, even if there's only one input.
                'inputs': Address(self.trytes4),
                'depth': 100,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'inputs': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_inputs_contents_invalid(self):
        """
    ``inputs`` is a non-empty array, but it contains invalid values.
    """
        self.assertFilterErrors(
            {
                'inputs': [
                    b'',
                    True,
                    None,
                    b'not valid trytes',

                    # This is actually valid; I just added it to make sure the
                    #   filter isn't cheating!
                    TryteString(self.trytes4),
                    2130706433,
                    b'9' * 82,
                ],
                'depth':
                100,
                'minWeightMagnitude':
                18,
                'seed':
                Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'inputs.0': [f.Required.CODE_EMPTY],
                'inputs.1': [f.Type.CODE_WRONG_TYPE],
                'inputs.2': [f.Required.CODE_EMPTY],
                'inputs.3': [Trytes.CODE_NOT_TRYTES],
                'inputs.5': [f.Type.CODE_WRONG_TYPE],
                'inputs.6': [Trytes.CODE_WRONG_FORMAT],
            },
        )

    def test_fail_depth_null(self):
        """
    ``depth`` is null.
    """
        self.assertFilterErrors(
            {
                'depth': None,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'depth': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_depth_string(self):
        """
    ``depth`` is a string.
    """
        self.assertFilterErrors(
            {
                # Too ambiguous; it must be an int.
                'depth': '2',
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'depth': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_depth_float(self):
        """
    ``depth`` is a float.
    """
        self.assertFilterErrors(
            {
                # Even with an empty fpart, floats are invalid.
                'depth': 100.0,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'depth': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_depth_too_small(self):
        """
    ``depth`` is < 1.
    """
        self.assertFilterErrors(
            {
                'depth': 0,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'depth': [f.Min.CODE_TOO_SMALL],
            },
        )

    def test_fail_min_weight_magnitude_null(self):
        """
    ``minWeightMagnitude`` is null.
    """
        self.assertFilterErrors(
            {
                'minWeightMagnitude': None,
                'depth': 100,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'minWeightMagnitude': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_min_weight_magnitude_string(self):
        """
    ``minWeightMagnitude`` is a string.
    """
        self.assertFilterErrors(
            {
                # Nope; it's gotta be an int.
                'minWeightMagnitude': '18',
                'depth': 100,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'minWeightMagnitude': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_min_weight_magnitude_float(self):
        """
    ``minWeightMagnitude`` is a float.
    """
        self.assertFilterErrors(
            {
                # Even with an empty fpart, floats are invalid.
                'minWeightMagnitude': 18.0,
                'depth': 100,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'minWeightMagnitude': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_min_weight_magnitude_too_small(self):
        """
    ``minWeightMagnitude`` is < 1.
    """
        self.assertFilterErrors(
            {
                'minWeightMagnitude': 0,
                'depth': 100,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],
            },
            {
                'minWeightMagnitude': [f.Min.CODE_TOO_SMALL],
            },
        )

    def test_fail_reference_wrong_type(self):
        """
    ``reference`` is not a TrytesCompatible value.
    """
        self.assertFilterErrors(
            {
                'reference': 42,
                'seed': Seed(self.trytes1),
                'depth': 100,
                'minWeightMagnitude': 18,
                'transfers': [self.transfer1],
            },
            {
                'reference': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_reference_not_trytes(self):
        """
    ``reference`` contains invalid characters.
    """
        self.assertFilterErrors(
            {
                'reference': b'not valid; must contain only uppercase and "9"',
                'seed': Seed(self.trytes1),
                'depth': 100,
                'minWeightMagnitude': 18,
                'transfers': [self.transfer1],
            },
            {
                'reference': [Trytes.CODE_NOT_TRYTES],
            },
        )

    def test_fail_wrong_security_level(self):
        """
    ``security_level`` is not one of integers 1, 2 or 3.
    """
        self.assertFilterErrors(
            {
                'depth': 100,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],

                # Maybe he's not that smart; maybe he's like a worker bee who
                # only knows how to push buttons or something.
                'securityLevel': 0,
            },
            {
                'securityLevel': [f.Min.CODE_TOO_SMALL],
            },
        )

    def test_fail_wrong_security_level_type(self):
        """
    ``security_level`` is not one of integers 1, 2 or 3.
    """
        self.assertFilterErrors(
            {
                'depth': 100,
                'minWeightMagnitude': 18,
                'seed': Seed(self.trytes1),
                'transfers': [self.transfer1],

                # Maybe he's not that smart; maybe he's like a worker bee who
                # only knows how to push buttons or something.
                'securityLevel': "2",
            },
            {
                'securityLevel': [f.Type.CODE_WRONG_TYPE],
            },
        )
Ejemplo n.º 11
0
 class CustomClient(object):
     client = StrictIota(MockAdapter())
Ejemplo n.º 12
0
    def setUp(self):
        super(GetNeighborsCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
Ejemplo n.º 13
0
    def setUp(self):
        super(TraverseBundleCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = TraverseBundleCommand(self.adapter)
Ejemplo n.º 14
0
 class CustomClient(object, metaclass=ABCMeta):
     client = StrictIota(MockAdapter())
Ejemplo n.º 15
0
    def setUp(self):
        super(GetTrytesCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
Ejemplo n.º 16
0
class GetTrytesRequestFilterTestCase(BaseFilterTestCase):
    filter_type = GetTrytesCommand(MockAdapter()).get_request_filter
    skip_value_check = True

    # noinspection SpellCheckingInspection
    def setUp(self):
        super(GetTrytesRequestFilterTestCase, self).setUp()

        # Define some valid tryte sequences that we can re-use between
        # tests.
        self.trytes1 = (b'OAATQS9VQLSXCLDJVJJVYUGONXAXOFMJOZNSYWRZ'
                        b'SWECMXAQQURHQBJNLD9IOFEPGZEPEMPXCIVRX9999')

        self.trytes2 = (b'ZIJGAJ9AADLRPWNCYNNHUHRRAC9QOUDATEDQUMTN'
                        b'OTABUVRPTSTFQDGZKFYUUIE9ZEBIVCCXXXLKX9999')

    def test_pass_happy_path(self):
        """
    The request is valid.
    """
        request = {
            'hashes': [
                TransactionHash(self.trytes1),
                TransactionHash(self.trytes2),
            ],
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)

    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_fail_empty(self):
        """
    The request is empty.
    """
        self.assertFilterErrors(
            {},
            {
                'hashes': [f.FilterMapper.CODE_MISSING_KEY],
            },
        )

    def test_fail_unexpected_parameters(self):
        """
    The request contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'hashes': [TransactionHash(self.trytes1)],

                # This is why we can't have nice things!
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )

    def test_fail_hashes_null(self):
        """
    ``hashes`` is null.
    """
        self.assertFilterErrors(
            {
                'hashes': None,
            },
            {
                'hashes': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_hashes_wrong_type(self):
        """
    ``hashes`` is not an array.
    """
        self.assertFilterErrors(
            {
                # ``hashes`` must be an array, even if we're only querying
                # against a single transaction.
                'hashes': TransactionHash(self.trytes1),
            },
            {
                'hashes': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_hashes_empty(self):
        """
    ``hashes`` is an array, but it is empty.
    """
        self.assertFilterErrors(
            {
                'hashes': [],
            },
            {
                'hashes': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_hashes_contents_invalid(self):
        """
    ``hashes`` is an array, but it contains invalid values.
    """
        self.assertFilterErrors(
            {
                'hashes': [
                    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,
                ],
            },
            {
                'hashes.0': [f.Required.CODE_EMPTY],
                'hashes.1': [f.Type.CODE_WRONG_TYPE],
                'hashes.2': [f.Type.CODE_WRONG_TYPE],
                'hashes.3': [f.Required.CODE_EMPTY],
                'hashes.4': [Trytes.CODE_NOT_TRYTES],
                'hashes.6': [f.Type.CODE_WRONG_TYPE],
                'hashes.7': [Trytes.CODE_WRONG_FORMAT],
            },
        )
Ejemplo n.º 17
0
    def setUp(self):
        super(GetBundlesCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = GetBundlesCommand(self.adapter)
Ejemplo n.º 18
0
  def setUp(self):
    super(InterruptAttachingToTangleCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
Ejemplo n.º 19
0
    def setUp(self):
        super(GetInclusionStatesCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
Ejemplo n.º 20
0
class GetInclusionStatesRequestFilterTestCase(BaseFilterTestCase):
    filter_type = GetInclusionStatesCommand(MockAdapter()).get_request_filter
    skip_value_check = True

    # noinspection SpellCheckingInspection
    def setUp(self):
        super(GetInclusionStatesRequestFilterTestCase, self).setUp()

        self.trytes1 = ('TESTVALUE9DONTUSEINPRODUCTION99999GCXWZZ'
                        'ZKNRIZENRRXGPAGJOSSWQQOJDD9VGQRMEFCOIFLQB')

        self.trytes2 = ('TESTVALUE9DONTUSEINPRODUCTION99999KGTGVN'
                        'GEDAJAXCTEPOJKF9FCJXXDHISFANKOPFXY9IDPMKC')

    def test_pass_happy_path(self):
        """
    Typical ``getInclusionStates`` request.
    """
        request = {
            # Raw trytes are extracted to match the IRI's JSON protocol.
            'transactions': [self.trytes1, self.trytes2],

            # 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.
            'tips': [self.trytes1, 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': [self.trytes1, self.trytes2],
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'tips': [],
                'transactions': [self.trytes1, self.trytes2],
            },
        )

    def test_pass_compatible_types(self):
        """
    The request contains values that can be converted to expected
    types.
    """
        filter_ = self._filter({
            'transactions': [
                TransactionHash(self.trytes1),
                bytearray(self.trytes2.encode('ascii')),
            ],
            'tips': [
                TransactionHash(self.trytes1),
                bytearray(self.trytes2.encode('ascii')),
            ],
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'tips': [self.trytes1, self.trytes2],
                'transactions': [self.trytes1, self.trytes2],
            },
        )

    def test_fail_empty(self):
        """
    The incoming request is empty.
    """
        self.assertFilterErrors(
            {},
            {
                'transactions': [f.FilterMapper.CODE_MISSING_KEY],
            },
        )

    def test_fail_unexpected_parameters(self):
        """
    The incoming request contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'transactions': [TransactionHash(self.trytes1)],

                # I bring scientists, you bring a rock star.
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )

    def test_fail_transactions_null(self):
        """
    ``transactions`` is null.
    """
        self.assertFilterErrors(
            {
                'transactions': None,
            },
            {
                'transactions': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_transactions_wrong_type(self):
        """
    ``transactions`` is not an array.
    """
        self.assertFilterErrors(
            {
                # Has to be an array, even if we're only querying for one
                # transaction.
                'transactions': TransactionHash(self.trytes1),
            },
            {
                'transactions': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_transactions_empty(self):
        """
    ``transactions`` is an array, but it is empty.
    """
        self.assertFilterErrors(
            {
                'transactions': [],
            },
            {
                'transactions': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_transactions_contents_invalid(self):
        """
    ``transactions`` is a non-empty array, but it contains invalid
    values.
    """
        self.assertFilterErrors(
            {
                'transactions': [
                    b'',
                    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.0': [f.Required.CODE_EMPTY],
                'transactions.1': [f.Type.CODE_WRONG_TYPE],
                'transactions.2': [f.Required.CODE_EMPTY],
                'transactions.3': [Trytes.CODE_NOT_TRYTES],
                'transactions.5': [f.Type.CODE_WRONG_TYPE],
                'transactions.6': [Trytes.CODE_WRONG_FORMAT],
            },
        )

    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_fail_tips_contents_invalid(self):
        """
    ``tips`` contains invalid values.
    """
        self.assertFilterErrors(
            {
                'tips': [
                    b'',
                    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.Required.CODE_EMPTY],
                'tips.3': [Trytes.CODE_NOT_TRYTES],
                'tips.5': [f.Type.CODE_WRONG_TYPE],
                'tips.6': [Trytes.CODE_WRONG_FORMAT],
            },
        )
Ejemplo n.º 21
0
class GetInputsCommandTestCase(TestCase):
  # noinspection SpellCheckingInspection
  def setUp(self):
    super(GetInputsCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = GetInputsCommand(self.adapter)

    # Define some valid tryte sequences that we can reuse between
    # tests.
    self.addy0 =\
      Address(
        trytes =
          b'TESTVALUE9DONTUSEINPRODUCTION99999FIODSG'
          b'IC9CCIFCNBTBDFIEHHE9RBAEVGK9JECCLCPBIINAX',

        key_index = 0,
      )

    self.addy1 =\
      Address(
        trytes =
          b'TESTVALUE9DONTUSEINPRODUCTION999999EPCNH'
          b'MBTEH9KDVFMHHESDOBTFFACCGBFGACEDCDDCGICIL',

        key_index = 1,
      )

    self.addy2 =\
      Address(
        trytes =
          b'TESTVALUE9DONTUSEINPRODUCTION99999YDOHWF'
          b'U9PFOFHGKFACCCBGDALGI9ZBEBABFAMBPDSEQ9XHJ',

        key_index = 2,
      )

  def test_wireup(self):
    """
    Verify that the command is wired up correctly.
    """
    self.assertIsInstance(
      Iota(self.adapter).getInputs,
      GetInputsCommand,
    )

  def test_stop_threshold_met(self):
    """
    ``stop`` provided, balance meets ``threshold``.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [42, 29],
    })

    # 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.
    mock_address_generator = mock.Mock(return_value=[self.addy0, self.addy1])

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.get_addresses',
        mock_address_generator,
    ):
      response = self.command(
        seed      = Seed.random(),
        stop      = 2,
        threshold = 71,
      )

    self.assertEqual(response['totalBalance'], 71)
    self.assertEqual(len(response['inputs']), 2)

    input0 = response['inputs'][0]
    self.assertIsInstance(input0, Address)

    self.assertEqual(input0, self.addy0)
    self.assertEqual(input0.balance, 42)
    self.assertEqual(input0.key_index, 0)

    input1 = response['inputs'][1]
    self.assertIsInstance(input1, Address)

    self.assertEqual(input1, self.addy1)
    self.assertEqual(input1.balance, 29)
    self.assertEqual(input1.key_index, 1)

  def test_stop_threshold_not_met(self):
    """
    ``stop`` provided, balance does not meet ``threshold``.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [42, 29],
    })

    # 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.
    mock_address_generator = mock.Mock(return_value=[self.addy0, self.addy1])

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.get_addresses',
        mock_address_generator,
    ):
      with self.assertRaises(BadApiResponse):
        self.command(
          seed      = Seed.random(),
          stop      = 2,
          threshold = 72,
        )

  def test_stop_threshold_zero(self):
    """
    ``stop`` provided, ``threshold`` is 0.
    """
    # Note that the first address has a zero balance.
    self.adapter.seed_response('getBalances', {
      'balances': [0, 1],
    })

    # 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.
    mock_address_generator = mock.Mock(return_value=[self.addy0, self.addy1])

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.get_addresses',
        mock_address_generator,
    ):
      response = self.command(
        seed      = Seed.random(),
        stop      = 2,
        threshold = 0,
      )

    self.assertEqual(response['totalBalance'], 1)
    self.assertEqual(len(response['inputs']), 1)

    # Address 0 was skipped because it has a zero balance.
    input0 = response['inputs'][0]
    self.assertIsInstance(input0, Address)

    self.assertEqual(input0, self.addy1)
    self.assertEqual(input0.balance, 1)
    self.assertEqual(input0.key_index, 1)

  def test_stop_no_threshold(self):
    """
    ``stop`` provided, no ``threshold``.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [42, 29],
    })

    # 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.
    mock_address_generator = mock.Mock(return_value=[self.addy0, self.addy1])

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.get_addresses',
        mock_address_generator,
    ):
      response = self.command(
        seed      = Seed.random(),
        start     = 0,
        stop      = 2,
      )

    self.assertEqual(response['totalBalance'], 71)
    self.assertEqual(len(response['inputs']), 2)

    input0 = response['inputs'][0]
    self.assertIsInstance(input0, Address)

    self.assertEqual(input0, self.addy0)
    self.assertEqual(input0.balance, 42)
    self.assertEqual(input0.key_index, 0)

    input1 = response['inputs'][1]
    self.assertIsInstance(input1, Address)

    self.assertEqual(input1, self.addy1)
    self.assertEqual(input1.balance, 29)
    self.assertEqual(input1.key_index, 1)

  def test_no_stop_threshold_met(self):
    """
    No ``stop`` provided, balance meets ``threshold``.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [42, 29],
    })

    # ``getInputs`` uses ``findTransactions`` to identify unused
    # addresses.
    # noinspection SpellCheckingInspection
    self.adapter.seed_response('findTransactions', {
      'hashes': [
        TransactionHash(
          b'TESTVALUE9DONTUSEINPRODUCTION99999WBL9KD'
          b'EIZDMEDFPEYDIIA9LEMEUCC9MFPBY9TEVCUGSEGGN'
        ),
      ],
    })

    # 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):
      for addy in [self.addy0, self.addy1, self.addy2][start::step]:
        yield addy

    # When ``stop`` is None, the command uses a generator internally.
    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        mock_address_generator,
    ):
      response = self.command(
        seed      = Seed.random(),
        threshold = 71,
      )

    self.assertEqual(response['totalBalance'], 71)
    self.assertEqual(len(response['inputs']), 2)

    input0 = response['inputs'][0]
    self.assertIsInstance(input0, Address)

    self.assertEqual(input0, self.addy0)
    self.assertEqual(input0.balance, 42)
    self.assertEqual(input0.key_index, 0)

    input1 = response['inputs'][1]
    self.assertIsInstance(input1, Address)

    self.assertEqual(input1, self.addy1)
    self.assertEqual(input1.balance, 29)
    self.assertEqual(input1.key_index, 1)

  def test_no_stop_threshold_not_met(self):
    """
    No ``stop`` provided, balance does not meet ``threshold``.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [42, 29, 0],
    })

    # 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):
      for addy in [self.addy0, self.addy1, self.addy2][start::step]:
        yield addy

    # When ``stop`` is None, the command uses a generator internally.
    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        mock_address_generator,
    ):
      with self.assertRaises(BadApiResponse):
        self.command(
          seed      = Seed.random(),
          threshold = 72,
        )

  def test_no_stop_threshold_zero(self):
    """
    No ``stop`` provided, ``threshold`` is 0.
    """
    # Note that the first address has a zero balance.
    self.adapter.seed_response('getBalances', {
      'balances': [0, 1],
    })

    # ``getInputs`` uses ``findTransactions`` to identify unused
    # addresses.
    # noinspection SpellCheckingInspection
    self.adapter.seed_response('findTransactions', {
      'hashes': [
        TransactionHash(
          b'TESTVALUE9DONTUSEINPRODUCTION99999WBL9KD'
          b'EIZDMEDFPEYDIIA9LEMEUCC9MFPBY9TEVCUGSEGGN'
        ),
      ],
    })

    # 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):
      for addy in [self.addy0, self.addy1, self.addy2][start::step]:
        yield addy

    # When ``stop`` is None, the command uses a generator internally.
    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        mock_address_generator,
    ):
      response = self.command(
        seed      = Seed.random(),
        threshold = 0,
      )

    self.assertEqual(response['totalBalance'], 1)
    self.assertEqual(len(response['inputs']), 1)

    # Because the first address had a zero balance, it was skipped.
    input0 = response['inputs'][0]
    self.assertIsInstance(input0, Address)

    self.assertEqual(input0, self.addy1)
    self.assertEqual(input0.balance, 1)
    self.assertEqual(input0.key_index, 1)

  def test_no_stop_no_threshold(self):
    """
    No ``stop`` provided, no ``threshold``.
    """
    self.adapter.seed_response('getBalances', {
      'balances': [42, 29],
    })

    # ``getInputs`` uses ``findTransactions`` to identify unused
    # addresses.
    # noinspection SpellCheckingInspection
    self.adapter.seed_response('findTransactions', {
      'hashes': [
        TransactionHash(
          b'TESTVALUE9DONTUSEINPRODUCTION99999WBL9KD'
          b'EIZDMEDFPEYDIIA9LEMEUCC9MFPBY9TEVCUGSEGGN'
        ),
      ],
    })

    # 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):
      for addy in [self.addy0, self.addy1, self.addy2][start::step]:
        yield addy

    # When ``stop`` is None, the command uses a generator internally.
    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        mock_address_generator,
    ):
      response = self.command(
        seed = Seed.random(),
      )

    self.assertEqual(response['totalBalance'], 71)
    self.assertEqual(len(response['inputs']), 2)

    input0 = response['inputs'][0]
    self.assertIsInstance(input0, Address)

    self.assertEqual(input0, self.addy0)
    self.assertEqual(input0.balance, 42)
    self.assertEqual(input0.key_index, 0)

    input1 = response['inputs'][1]
    self.assertIsInstance(input1, Address)

    self.assertEqual(input1, self.addy1)
    self.assertEqual(input1.balance, 29)
    self.assertEqual(input1.key_index, 1)

  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 mock.patch(
        'iota.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)
Ejemplo n.º 22
0
class GetNewAddressesCommandTestCase(TestCase):
  # noinspection SpellCheckingInspection
  def setUp(self):
    super(GetNewAddressesCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = GetNewAddressesCommand(self.adapter)

    self.seed =\
      Seed(
        b'TESTVALUE9DONTUSEINPRODUCTION99999ZDCCUF'
        b'CBBIQCLGMEXAVFQEOF9DRAB9VCEBAGXAF9VF9FLHP',
      )

    self.addy_1 =\
      Address(
        b'NYMWLBUJEISSACZZBRENC9HEHYQXHCGQHSNHVCEA'
        b'ZDCTEVNGSDUEKTSYBSQGMVJRIEDHWDYSEYCFAZAH9',
      )

    self.addy_2 =\
      Address(
        b'NTPSEVZHQITARYWHIRTSIFSERINLRYVXLGIQKKHY'
        b'IWYTLQUUHDWSOVXLIKVJTYZBFKLABWRBFYVSMD9NB',
      )

    self.addy_1_checksum =\
      Address(
        b'NYMWLBUJEISSACZZBRENC9HEHYQXHCGQHSNHVCEA'
        b'ZDCTEVNGSDUEKTSYBSQGMVJRIEDHWDYSEYCFAZAH'
        b'9T9FPJROTW',
      )

  def test_wireup(self):
    """
    Verify that the command is wired up correctly.
    """
    self.assertIsInstance(
      Iota(self.adapter).getNewAddresses,
      GetNewAddressesCommand,
    )

  def test_get_addresses_offline(self):
    """
    Generate addresses in offline mode (without filtering used
    addresses).
    """
    response =\
      self.command(
        count = 2,
        index = 0,
        seed  = self.seed,
      )

    self.assertDictEqual(
      response,
      {'addresses': [self.addy_1, self.addy_2]},
    )

    # No API requests were made.
    self.assertListEqual(self.adapter.requests, [])

  def test_security_level(self):
    """
    Generating addresses with a different security level.
    """
    response =\
      self.command(
        count         = 2,
        index         = 0,
        securityLevel = 1,
        seed          = self.seed,
      )

    # noinspection SpellCheckingInspection
    self.assertDictEqual(
      response,

      {
        'addresses':
          [
            Address(
              b'ERBTZTPT9SKDQEGETKMZLYNRQMZYZIDENGWCSGRF'
              b'9TLURIEFVKUBSWOIMLMWTWMWTTHSUREPISXDPLCQC',
            ),

            Address(
              b'QVHEMGYHVMCFAISJKTWPFSKDAFRZHXQZK9E9KOUQ'
              b'LOLVBN9BFAZDDY9O9EYYMHMDWZAKXI9OPBPEYM9FC',
            ),
          ],
      },
    )

  def test_get_addresses_online(self):
    """
    Generate address in online mode (filtering used addresses).
    """
    # Pretend that ``self.addy1`` has already been used, but not
    # ``self.addy2``.
    # noinspection SpellCheckingInspection
    self.adapter.seed_response('findTransactions', {
      'duration': 18,

      'hashes': [
        'TESTVALUE9DONTUSEINPRODUCTION99999ITQLQN'
        'LPPG9YNAARMKNKYQO9GSCSBIOTGMLJUFLZWSY9999',
      ],
    })

    self.adapter.seed_response('findTransactions', {
      'duration': 1,
      'hashes':   [],
    })

    response =\
      self.command(
        # If ``count`` is missing or ``None``, the command will operate
        # in online mode.
        # count = None,

        index = 0,
        seed  = self.seed,
      )

    # The command determined that ``self.addy1`` was already used, so
    # it skipped that one.
    self.assertDictEqual(response, {'addresses': [self.addy_2]})

    self.assertListEqual(
      self.adapter.requests,

      # The command issued two `findTransactions` API requests: one for
      # each address generated, until it found an unused address.
      [
        {
          'command':    'findTransactions',
          'addresses':  [self.addy_1],
        },

        {
          'command':    'findTransactions',
          'addresses':  [self.addy_2],
        },
      ],
    )

  def test_new_address_checksum(self):
    """
    Generate address with a checksum.
    """
    response =\
      self.command(
        checksum      = True,
        count         = 1,
        index         = 0,
        seed          = self.seed,
      )

    self.assertDictEqual(
      response,
      {'addresses': [self.addy_1_checksum]},
    )
Ejemplo n.º 23
0
class BroadcastTransactionsRequestFilterTestCase(BaseFilterTestCase):
    filter_type = BroadcastTransactionsCommand(
        MockAdapter()).get_request_filter
    print_var_type_n_val(var001=filter_type,
                         pointer="#23456FESDFDdsdfd")  #23456FESDFDdsdfd
    # Value:
    # # <bound method BroadcastTransactionsCommand.get_request_filter of <iota.commands.core.broadcast_transactions.BroadcastTransactionsCommand object at 0x00000173E70A88D0>>

    # Type: <class 'method'>
    skip_value_check = True

    # noinspection SpellCheckingInspection
    def setUp(self):
        super(BroadcastTransactionsRequestFilterTestCase, self).setUp()

        # Define a few valid values that we can reuse across tests.
        self.trytes1 = TransactionTrytes('RBTC9D9DCDQAEASBYBCCKBFA')
        self.trytes2 =\
          TransactionTrytes(
            'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA'
          )
        print_var_type_n_val(var001=self.trytes2,
                             pointer="#R43EDFdfsSDFDtre")  #R43EDFdfsSDFDtre


# Value: CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
# Type: <class 'iota.transaction.types.TransactionTrytes'>

    def test_pass_happy_path(self):
        """
    The incoming request is valid.
    """
        request = {
            'trytes': [
                text_type(self.trytes1),
                text_type(self.trytes2),
            ],
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)

    def test_pass_compatible_types(self):
        """
    The incoming request contains values that can be converted into the
    expected types.
    """
        # Any values that can be converted into TryteStrings are accepted.
        filter_ = self._filter({
            'trytes': [
                binary_type(self.trytes1),
                self.trytes2,
            ],
        })
        print_var_type_n_val(
            var001=filter_,
            pointer="#SDFTREzertg123498xcvb")  #SDFTREzertg123498xcvb
        # Value:
        # # BroadcastTransactionsRequestFilter(FilterChain(Type(Mapping, allow_subclass=True) | FilterMapper(trytes=FilterChain(Required(allow_none=False) | Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | Trytes() | Unicode(encoding='ascii')))))))

        # Type: <class 'filters.handlers.FilterRunner'>

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'trytes': [
                    # Raw trytes are extracted to match the IRI's JSON protocol.
                    text_type(self.trytes1),
                    text_type(self.trytes2),
                ],
            },
        )

    def test_fail_empty(self):
        """
    The incoming request is empty.
    """
        self.assertFilterErrors(
            {},
            {
                'trytes': [f.FilterMapper.CODE_MISSING_KEY],
            },
        )

    def test_fail_unexpected_parameters(self):
        """
    The incoming value contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'trytes': [TryteString(self.trytes1)],

                # Alright buddy, let's see some ID.
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )

    def test_fail_trytes_null(self):
        """
    ``trytes`` is null.
    """
        self.assertFilterErrors(
            {
                'trytes': None,
            },
            {
                'trytes': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_trytes_wrong_type(self):
        """
    ``trytes`` is not an array.
    """
        self.assertFilterErrors(
            {
                # ``trytes`` has to be an array, even if there's only one
                # TryteString.
                'trytes': TryteString(self.trytes1),
            },
            {
                'trytes': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_trytes_empty(self):
        """
    ``trytes`` is an array, but it's empty.
    """
        self.assertFilterErrors(
            {
                'trytes': [],
            },
            {
                'trytes': [f.Required.CODE_EMPTY],
            },
        )

    def test_trytes_contents_invalid(self):
        """
    ``trytes`` is an array, but it contains invalid values.
    """
        self.assertFilterErrors(
            {
                'trytes': [
                    b'',
                    True,
                    None,
                    b'not valid trytes',

                    # This is actually valid; I just added it to make sure the
                    # filter isn't cheating!
                    TryteString(self.trytes2),
                    2130706433,
                    b'9' * (TransactionTrytes.LEN + 1),
                ],
            },
            {
                'trytes.0': [f.NotEmpty.CODE_EMPTY],
                'trytes.1': [f.Type.CODE_WRONG_TYPE],
                'trytes.2': [f.Required.CODE_EMPTY],
                'trytes.3': [Trytes.CODE_NOT_TRYTES],
                'trytes.5': [f.Type.CODE_WRONG_TYPE],
                'trytes.6': [Trytes.CODE_WRONG_FORMAT],
            },
        )
Ejemplo n.º 24
0
class TraverseBundleCommandTestCase(TestCase):
    def setUp(self):
        super(TraverseBundleCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = TraverseBundleCommand(self.adapter)

    def test_wireup(self):
        """
        Verify that the command is wired up correctly. (sync)

        The API method indeed calls the appropiate command.
        """
        with patch(
                'iota.commands.extended.traverse_bundle.TraverseBundleCommand.__call__',
                MagicMock(return_value=async_return(
                    'You found me!'))) as mocked_command:

            api = Iota(self.adapter)

            # Don't need to call with proper args here.
            response = api.traverse_bundle('tail')

            self.assertTrue(mocked_command.called)

            self.assertEqual(response, 'You found me!')

    @async_test
    async def test_wireup(self):
        """
        Verify that the command is wired up correctly. (async)

        The API method indeed calls the appropiate command.
        """
        with patch(
                'iota.commands.extended.traverse_bundle.TraverseBundleCommand.__call__',
                MagicMock(return_value=async_return(
                    'You found me!'))) as mocked_command:

            api = AsyncIota(self.adapter)

            # Don't need to call with proper args here.
            response = await api.traverse_bundle('tail')

            self.assertTrue(mocked_command.called)

            self.assertEqual(response, 'You found me!')

    @async_test
    async def test_single_transaction(self):
        """
        Getting a bundle that contains a single transaction.
        """
        transaction =\
            Transaction(
                    current_index                     = 0,
                    last_index                        = 0,
                    tag                               = Tag(b''),
                    timestamp                         = 1484960990,
                    value                             = 0,
                    attachment_timestamp              = 1484960990,
                    attachment_timestamp_lower_bound  = 12,
                    attachment_timestamp_upper_bound  = 0,

                    # These values are not relevant for 0-value transactions.
                    nonce                       = Nonce(b''),
                    signature_message_fragment  = Fragment(b''),

                    # This value is computed automatically, so it has to be real.
                    hash_ =
                        TransactionHash(
                            b'XPJIYZWPF9LBCYZPNBFARDRCSUGJGF9TWZT9K9PX'
                            b'VYDFPZOZBGXUCKLTJEUCFBEKQQ9VCSQVQDMMJQAY9',
                        ),

                    address =
                        Address(
                            b'TESTVALUE9DONTUSEINPRODUCTION99999OCSGVF'
                            b'IBQA99KGTCPCZ9NHR9VGLGADDDIEGGPCGBDEDDTBC',
                        ),

                    bundle_hash =
                        BundleHash(
                            b'TESTVALUE9DONTUSEINPRODUCTION99999DIOAZD'
                            b'M9AIUHXGVGBC9EMGI9SBVBAIXCBFJ9EELCPDRAD9U',
                        ),

                    branch_transaction_hash =
                        TransactionHash(
                            b'TESTVALUE9DONTUSEINPRODUCTION99999BBCEDI'
                            b'ZHUDWBYDJEXHHAKDOCKEKDFIMB9AMCLFW9NBDEOFV',
                        ),

                    trunk_transaction_hash =
                        TransactionHash(
                            b'TESTVALUE9DONTUSEINPRODUCTION999999ARAYA'
                            b'MHCB9DCFEIWEWDLBCDN9LCCBQBKGDDAECFIAAGDAS',
                        ),
                )

        self.adapter.seed_response('getTrytes', {
            'trytes': [transaction.as_tryte_string()],
        })

        response = await self.command(transaction=transaction.hash)

        bundle = response['bundles'][0]  # type: Bundle
        self.assertEqual(len(bundle), 1)

        self.maxDiff = None
        self.assertDictEqual(
            bundle[0].as_json_compatible(),
            transaction.as_json_compatible(),
        )

    @async_test
    async def test_multiple_transactions(self):
        """
        Getting a bundle that contains multiple transactions.
        """
        bundle = Bundle.from_tryte_strings([
            TransactionTrytes(
                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'9PWQHOBXNNQIF9IRHVQXKPZW999999999999999999999999999XZUIENOTTBKJMDP'
                b'RXWGQYG9PWGTHNLFMVD99A99999999A99999999PDQWLVVDPUU9VIBODGMRIAZPGQX'
                b'DOGSEXIHKIBWSLDAWUKZCZMK9Z9YZSPCKBDJSVDPRQLJSTKUMTNVSXBGUEHHGAIWWQ'
                b'BCJZHZAQOWZMAIDAFUZBVMUVPWQJLUGGQKNKLMGTWXXNZKUCBJLEDAMYVRGABAWBY9'
                b'999MYIYBTGIOQYYZFJBLIAWMPSZEFFTXUZPCDIXSLLQDQSFYGQSQOGSPKCZNLVSZ9L'
                b'MCUWVNGEN9EJEW9999XZUIENOTTBKJMDPRXWGQYG9PWGTXUO9AXMP9FLMDRMADLRPW'
                b'CZCJBROYCDRJMYU9HDYJM9NDBFUPIZVTR'),

            # Well, it was bound to happen sooner or later... the ASCII
            # representation of this tryte sequence contains a very naughty
            # phrase.  But I don't feel like doing another POW, so... enjoy.
            TransactionTrytes(
                b'NBTCPCFDEACCPCBDVC9DTCQAJ9RBTC9D9DCDQAEAKDCDFD9DSCFAJ9VBCDJDTCQAJ9'
                b'ZBMDYBCCKB99999999999999999999999999999999999999999999999999999999'
                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'999999999999999999999999999999999999999999999999999SYRABNN9JD9PNDL'
                b'IKUNCECUELTOHNLFMVD99999999999A99999999PDQWLVVDPUU9VIBODGMRIAZPGQX'
                b'DOGSEXIHKIBWSLDAWUKZCZMK9Z9YZSPCKBDJSVDPRQLJSTKUMTNVSXFSEWUNJOEGNU'
                b'I9QOCRFMYSIFAZLJHKZBPQZZYFG9ORYCRDX9TOMJPFCRB9R9KPUUGFPVOWYXFIWEW9'
                b'999BGUEHHGAIWWQBCJZHZAQOWZMAIDAFUZBVMUVPWQJLUGGQKNKLMGTWXXNZKUCBJL'
                b'EDAMYVRGABAWBY9999SYRABNN9JD9PNDLIKUNCECUELTOQZPSBDILVHJQVCEOICFAD'
                b'YKZVGMOAXJRQNTCKMHGTAUMPGJJMX9LNF'),
        ])

        for txn in bundle:
            self.adapter.seed_response('getTrytes', {
                'trytes': [txn.as_tryte_string()],
            })

        self.adapter.seed_response(
            'getTrytes', {
                'trytes': [
                    'SPAMSPAMSPAM999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999JECDITWO9999999'
                    '999999999999ONLFMVD99999999999999999999VVCHSQSRVFKSBONDWB9EAQEMQOY'
                    'YRBIZHTBJLYNAVDHZPUZAZ9LYHXWKBEJ9IPR9FAMFLT9EEOHVYWUPRHHSRCILCLWFD'
                    'GBYBFFOKMCSAPVD9VGZZRRGBLGMZMXD9RMZQDBLMGN9BATWZGULRBCYQEIKIRBPHC9'
                    '999KTLTRSYOWBD9HVNP9GCUABARNGMYXUZKXWRPGOPETZLKYYC9Z9EYXIWVARUBMBM'
                    'BPXGORN9WPBLY99999ZRBVQWULRFXDNDYZKRKIXPZQT9JJJH9FZU9PVWZJWLXBPODP'
                    'EHMKTTAGEPLPHUQCZNLDSHERONOMHJCOI'
                ],
            })

        response = await self.command(transaction=TransactionHash(
            b'TOYJPHKMLQNDVLDHDILARUJCCIUMQBLUSWPCTIVA'
            b'DRXICGYDGSVPXFTILFFGAPICYHGGJ9OHXINFX9999'), )
        self.maxDiff = None
        self.assertListEqual(
            response['bundles'][0].as_json_compatible(),
            bundle.as_json_compatible(),
        )

    @async_test
    async 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):
            await self.command(transaction=TransactionHash(
                b'FSEWUNJOEGNUI9QOCRFMYSIFAZLJHKZBPQZZYFG9'
                b'ORYCRDX9TOMJPFCRB9R9KPUUGFPVOWYXFIWEW9999'), )

    @async_test
    async def test_missing_transaction(self):
        """
        Unable to find the requested transaction.
        """
        self.adapter.seed_response('getTrytes', {'trytes': []})

        with self.assertRaises(BadApiResponse):
            await self.command(transaction=TransactionHash(
                b'FSEWUNJOEGNUI9QOCRFMYSIFAZLJHKZBPQZZYFG9'
                b'ORYCRDX9TOMJPFCRB9R9KPUUGFPVOWYXFIWEW9999'), )

    @async_test
    async def test_missing_transaction_zero_trytes(self):
        """
        Unable to find the requested transaction.
        getTrytes returned only zeros, no tx was found.
        """
        zero_trytes = TransactionTrytes('')
        self.adapter.seed_response('getTrytes', {'trytes': [zero_trytes]})

        with self.assertRaises(BadApiResponse):
            await self.command(transaction=TransactionHash(
                b'FSEWUNJOEGNUI9QOCRFMYSIFAZLJHKZBPQZZYFG9'
                b'ORYCRDX9TOMJPFCRB9R9KPUUGFPVOWYXFIWEW9999'), )
Ejemplo n.º 25
0
    def setUp(self):
        super(BroadcastTransactionsCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
Ejemplo n.º 26
0
class TraverseBundleRequestFilterTestCase(BaseFilterTestCase):
    filter_type = TraverseBundleCommand(MockAdapter()).get_request_filter
    skip_value_check = True

    def setUp(self):
        super(TraverseBundleRequestFilterTestCase, self).setUp()

        self.transaction = ('TESTVALUE9DONTUSEINPRODUCTION99999KPZOTR'
                            'VDB9GZDJGZSSDCBIX9QOK9PAV9RMDBGDXLDTIZTWQ')

    def test_pass_happy_path(self):
        """
        Request is valid.
        """
        # Raw trytes are extracted to match the IRI's JSON protocol.
        request = {
            'transaction': self.transaction,
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)

    def test_pass_compatible_types(self):
        """
        Request contains values that can be converted to the expected
        types.
        """
        filter_ = self._filter({
            # Any TrytesCompatible value will work here.
            'transaction':
            TransactionHash(self.transaction),
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'transaction': self.transaction,
            },
        )

    def test_fail_empty(self):
        """
        Request is empty.
        """
        self.assertFilterErrors(
            {},
            {
                'transaction': [f.FilterMapper.CODE_MISSING_KEY],
            },
        )

    def test_fail_unexpected_parameters(self):
        """
        Request contains unexpected parameters.
        """
        self.assertFilterErrors(
            {
                'transaction': TransactionHash(self.transaction),

                # SAY "WHAT" AGAIN!
                'what': 'augh!',
            },
            {
                'what': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )

    def test_fail_transaction_wrong_type(self):
        """
        ``transaction`` is not a TrytesCompatible value.
        """
        self.assertFilterErrors(
            {
                'transaction': 42,
            },
            {
                'transaction': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_transaction_not_trytes(self):
        """
        ``transaction`` contains invalid characters.
        """
        self.assertFilterErrors(
            {
                'transaction':
                b'not valid; must contain only uppercase and "9"',
            },
            {
                'transaction': [Trytes.CODE_NOT_TRYTES],
            },
        )
Ejemplo n.º 27
0
class GetLatestInclusionCommandTestCase(TestCase):
    # noinspection SpellCheckingInspection
    def setUp(self):
        super(GetLatestInclusionCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = GetLatestInclusionCommand(self.adapter)

        # Define some tryte sequences that we can re-use across tests.
        self.milestone =\
          TransactionHash(
            b'TESTVALUE9DONTUSEINPRODUCTION99999W9KDIH'
            b'BALAYAFCADIDU9HCXDKIXEYDNFRAKHN9IEIDZFWGJ'
          )

        self.hash1 =\
          TransactionHash(
            b'TESTVALUE9DONTUSEINPRODUCTION99999TBPDM9'
            b'ADFAWCKCSFUALFGETFIFG9UHIEFE9AYESEHDUBDDF'
          )

        self.hash2 =\
          TransactionHash(
            b'TESTVALUE9DONTUSEINPRODUCTION99999CIGCCF'
            b'KIUFZF9EP9YEYGQAIEXDTEAAUGAEWBBASHYCWBHDX'
          )

    def test_wireup(self):
        """
    Verify that the command is wired up correctly.
    """
        self.assertIsInstance(
            Iota(self.adapter).getLatestInclusion,
            GetLatestInclusionCommand,
        )

    def test_happy_path(self):
        """
    Successfully requesting latest inclusion state.
    """
        self.adapter.seed_response(
            'getNodeInfo',
            {
                # ``getNodeInfo`` returns lots of info, but the only value that
                # matters for this test is ``latestSolidSubtangleMilestone``.
                'latestSolidSubtangleMilestone': self.milestone,
            },
        )

        self.adapter.seed_response('getInclusionStates', {
            'states': [True, False],
        })

        response = self.command(hashes=[self.hash1, self.hash2])

        self.assertDictEqual(response, {
            'states': {
                self.hash1: True,
                self.hash2: False,
            },
        })
Ejemplo n.º 28
0
class CustomCommandTestCase(TestCase):
    def setUp(self):
        super(CustomCommandTestCase, self).setUp()

        self.name = 'helloWorld'
        self.adapter = MockAdapter()
        self.command = CustomCommand(self.adapter, self.name)

    def test_call(self):
        """
        Sending a custom command.
        """
        expected_response = {'message': 'Hello, IOTA!'}

        self.adapter.seed_response('helloWorld', expected_response)

        response = self.command()

        self.assertEqual(response, expected_response)
        self.assertTrue(self.command.called)

        self.assertListEqual(
            self.adapter.requests,
            [{'command': 'helloWorld'}],
        )

    def test_call_with_parameters(self):
        """
        Sending a custom command with parameters.
        """
        expected_response = {'message': 'Hello, IOTA!'}

        self.adapter.seed_response('helloWorld', expected_response)

        response = self.command(foo='bar', baz='luhrmann')

        self.assertEqual(response, expected_response)
        self.assertTrue(self.command.called)

        self.assertListEqual(
            self.adapter.requests,
            [{'command': 'helloWorld', 'foo': 'bar', 'baz': 'luhrmann'}],
        )

    def test_call_error_already_called(self):
        """
        A command can only be called once.
        """
        self.adapter.seed_response('helloWorld', {})
        self.command()

        with self.assertRaises(RuntimeError):
            self.command(extra='params')

        self.assertDictEqual(self.command.request, {'command': 'helloWorld'})

    def test_call_reset(self):
        """
        Resetting a command allows it to be called more than once.
        """
        self.adapter.seed_response('helloWorld', {'message': 'Hello, IOTA!'})
        self.command()

        self.command.reset()

        self.assertFalse(self.command.called)
        self.assertIsNone(self.command.request)
        self.assertIsNone(self.command.response)

        expected_response = {'message': 'Welcome back!'}
        self.adapter.seed_response('helloWorld', expected_response)
        response = self.command(foo='bar')

        self.assertDictEqual(response, expected_response)
        self.assertDictEqual(self.command.response, expected_response)

        self.assertDictEqual(
            self.command.request,

            {
                'command': 'helloWorld',
                'foo': 'bar',
            },
        )
Ejemplo n.º 29
0
class GetAccountDataRequestFilterTestCase(BaseFilterTestCase):
    filter_type = GetAccountDataCommand(MockAdapter()).get_request_filter
    skip_value_check = True

    # noinspection SpellCheckingInspection
    def setUp(self):
        super(GetAccountDataRequestFilterTestCase, self).setUp()

        # Define a few tryte sequences that we can re-use between tests.
        self.seed = b'HELLOIOTA'

    def test_pass_happy_path(self):
        """
    Request is valid.
    """
        request = {
            'seed': Seed(self.seed),
            'start': 0,
            'stop': 10,
            'inclusionStates': True,
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)

    def test_pass_compatible_types(self):
        """
    The request contains values that can be converted to the expected
    types.
    """
        filter_ = self._filter({
            # ``seed`` can be any value that is convertible into a
            # TryteString.
            'seed': binary_type(self.seed),

            # These values must still be integers/bools, however.
            'start': 42,
            'stop': 86,
            'inclusionStates': True,
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'seed': Seed(self.seed),
                'start': 42,
                'stop': 86,
                'inclusionStates': True,
            },
        )

    def test_pass_optional_parameters_excluded(self):
        """
    The request contains only required parameters.
    """
        filter_ = self._filter({
            'seed': Seed(self.seed),
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data, {
                'seed': Seed(self.seed),
                'start': 0,
                'stop': None,
                'inclusionStates': False,
            })

    def test_fail_empty_request(self):
        """
    The request is empty.
    """
        self.assertFilterErrors(
            {},
            {
                'seed': [f.FilterMapper.CODE_MISSING_KEY],
            },
        )

    def test_fail_unexpected_parameters(self):
        """
    The request contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'seed': Seed(self.seed),

                # Your rules are really beginning to annoy me.
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )

    def test_fail_seed_null(self):
        """
    ``seed`` is null.
    """
        self.assertFilterErrors(
            {
                'seed': None,
            },
            {
                'seed': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_seed_wrong_type(self):
        """
    ``seed`` cannot be converted into a TryteString.
    """
        self.assertFilterErrors(
            {
                'seed': text_type(self.seed, 'ascii'),
            },
            {
                'seed': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_seed_malformed(self):
        """
    ``seed`` has the correct type, but it contains invalid characters.
    """
        self.assertFilterErrors(
            {
                'seed':
                b'not valid; seeds can only contain uppercase and "9".',
            },
            {
                'seed': [Trytes.CODE_NOT_TRYTES],
            },
        )

    def test_fail_start_string(self):
        """
    ``start`` is a string.
    """
        self.assertFilterErrors(
            {
                # Not valid; it must be an int.
                'start': '0',
                'seed': Seed(self.seed),
            },
            {
                'start': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_start_float(self):
        """
    ``start`` is a float.
    """
        self.assertFilterErrors(
            {
                # Even with an empty fpart, floats are not valid.
                # It's gotta be an int.
                'start': 8.0,
                'seed': Seed(self.seed),
            },
            {
                'start': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_start_too_small(self):
        """
    ``start`` is less than 0.
    """
        self.assertFilterErrors(
            {
                'start': -1,
                'seed': Seed(self.seed),
            },
            {
                'start': [f.Min.CODE_TOO_SMALL],
            },
        )

    def test_fail_stop_string(self):
        """
    ``stop`` is a string.
    """
        self.assertFilterErrors(
            {
                # Not valid; it must be an int.
                'stop': '0',
                'seed': Seed(self.seed),
            },
            {
                'stop': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_stop_float(self):
        """
    ``stop`` is a float.
    """
        self.assertFilterErrors(
            {
                # Even with an empty fpart, floats are not valid.
                # It's gotta be an int.
                'stop': 8.0,
                'seed': Seed(self.seed),
            },
            {
                'stop': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_stop_too_small(self):
        """
    ``stop`` is less than 0.
    """
        self.assertFilterErrors(
            {
                'stop': -1,
                'seed': Seed(self.seed),
            },
            {
                'stop': [f.Min.CODE_TOO_SMALL],
            },
        )

    def test_fail_stop_occurs_before_start(self):
        """
    ``stop`` is less than ``start``.
    """
        self.assertFilterErrors(
            {
                'start': 1,
                'stop': 0,
                'seed': Seed(self.seed),
            },
            {
                'start': [GetAccountDataRequestFilter.CODE_INTERVAL_INVALID],
            },
        )

    def test_fail_interval_too_large(self):
        """
    ``stop`` is way more than ``start``.
    """
        self.assertFilterErrors(
            {
                'start': 0,
                'stop': GetAccountDataRequestFilter.MAX_INTERVAL + 1,
                'seed': Seed(self.seed),
            },
            {
                'stop': [GetAccountDataRequestFilter.CODE_INTERVAL_TOO_BIG],
            },
        )

    def test_fail_inclusion_states_wrong_type(self):
        """
    ``inclusionStates`` is not a boolean.
    """
        self.assertFilterErrors(
            {
                'inclusionStates': '1',
                'seed': Seed(self.seed),
            },
            {
                'inclusionStates': [f.Type.CODE_WRONG_TYPE],
            },
        )
Ejemplo n.º 30
0
    def setUp(self):
        super(CustomCommandTestCase, self).setUp()

        self.name = 'helloWorld'
        self.adapter = MockAdapter()
        self.command = CustomCommand(self.adapter, self.name)
Ejemplo n.º 31
0
class IsPromotableRequestFilterTestCase(BaseFilterTestCase):
    filter_type = IsPromotableCommand(MockAdapter()).get_request_filter
    skip_value_check = True

    def setUp(self):
        super(IsPromotableRequestFilterTestCase, self).setUp()

        self.hash1 = (
            'TESTVALUE9DONTUSEINPRODUCTION99999DXSCAD'
            'YBVDCTTBLHFYQATFZPYPCBG9FOUKIGMYIGLHM9NEZ'
        )

        self.hash2 = (
            'TESTVALUE9DONTUSEINPRODUCTION99999EMFYSM'
            'HWODIAPUTTFDLQRLYIDAUIPJXXEXZZSBVKZEBWGAN'
        )

    def test_pass_happy_path(self):
        """
        Request is valid.
        """
        request = {
            # Raw trytes are extracted to match the IRI's JSON protocol.
            'tails': [self.hash1, self.hash2],
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)

    def test_pass_compatible_types(self):
        """
        Request contains values that can be converted to the expected
        types.
        """
        filter_ = self._filter({
            'tails': [
                # Any TrytesCompatible value can be used here.
                TransactionHash(self.hash1),
                bytearray(self.hash2.encode('ascii')),
            ],
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,

            {
                # Raw trytes are extracted to match the IRI's JSON protocol.
                'tails': [self.hash1, self.hash2],
            },
        )

    def test_fail_empty(self):
        """
        Request is empty.
        """
        self.assertFilterErrors(
            {},

            {
                'tails': [f.FilterMapper.CODE_MISSING_KEY],
            },
        )

    def test_fail_unexpected_parameters(self):
        """
        Request contains unexpected parameters.
        """
        self.assertFilterErrors(
            {
                'tails': [TransactionHash(self.hash1)],
                'foo': 'bar',
            },

            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )

    def test_fail_tails_null(self):
        """
        ``tails`` is null.
        """
        self.assertFilterErrors(
            {
                'tails': None,
            },

            {
                'tails': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_tails_wrong_type(self):
        """
        ``tails`` is not an array.
        """
        self.assertFilterErrors(
            {
                # It's gotta be an array, even if there's only one hash.
                'tails': TransactionHash(self.hash1),
            },

            {
                'tails': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_tails_empty(self):
        """
        ``tails`` is an array, but it is empty.
        """
        self.assertFilterErrors(
            {
                'tails': [],
            },

            {
                'tails': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_tails_contents_invalid(self):
        """
        ``tails`` is a non-empty array, but it contains invalid values.
        """
        self.assertFilterErrors(
            {
                'tails': [
                    b'',
                    True,
                    None,
                    b'not valid trytes',

                    # This is actually valid; I just added it to make sure the
                    #   filter isn't cheating!
                    TryteString(self.hash1),

                    2130706433,
                    b'9' * 82,
                    ],
            },

            {
                'tails.0':  [f.Required.CODE_EMPTY],
                'tails.1':  [f.Type.CODE_WRONG_TYPE],
                'tails.2':  [f.Required.CODE_EMPTY],
                'tails.3':  [Trytes.CODE_NOT_TRYTES],
                'tails.5':  [f.Type.CODE_WRONG_TYPE],
                'tails.6':  [Trytes.CODE_WRONG_FORMAT],
            },
        )
Ejemplo n.º 32
0
    def setUp(self):
        super(SendTransferCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = SendTransferCommand(self.adapter)
Ejemplo n.º 33
0
class IsPromotableCommandTestCase(TestCase):
    def setUp(self):
        super(IsPromotableCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = IsPromotableCommand(self.adapter)

        # Define some tryte sequences that we can re-use across tests.
        self.trytes1 = TransactionTrytes(
            'CCGCVADBEACCWCXCGDEAXCGDEAPCEAHDTCGDHDEAHDFDPCBDGDPCRCHDXCCDBDE'
            'ACDBD9DMDSA9999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999ETTEXDKDEUALTLRJVX'
            'RHCPRJDLGPJCEQBJOMOAGBZWZCWLNUEWHAUSYJMYPEZPYNBTPSPGUIPQ9VOUNQ9'
            '999999999999999999999999999JVPROMOTABLETEST99999999999USHRPBD99'
            '999999999999999999XFVLEXEJPTYI9TUA9ULFNHXBGDUCOEPDIBKSZFXEBO9HF'
            'EGLENBCOVKHZ99IWZVCVSTUGKTIBEOVFBJPCDYHBDEIIBLHRVQX9KVVRTUIQMOF'
            'XUUETRIQCCCLSMVREZSNEXLIZCIUYIYRBJIBOKNJCQAJTAHGNZ9999DYHBDEIIB'
            'LHRVQX9KVVRTUIQMOFXUUETRIQCCCLSMVREZSNEXLIZCIUYIYRBJIBOKNJCQAJT'
            'AHGNZ9999ISPROMOTABLETEST9999999999999BFQOIOF999999999MMMMMMMMM'
            'EL999999999AG99999999999999'
        )

        self.hash1 = TransactionHash(
            'MHNBILKFU9CADOPNWSFYOMILGKJAHEU9GSSOYUEAPBGOOLAIKGBYSACXMFQRJZE'
            'PBSHI9SDKMBRK99999'
        )

        self.trytes2 = TransactionTrytes(
           'CCGCVADBEACCWCXCGDEAXCGDEAPCEAHDTCGDHDEAHDFDPCBDGDPCRCHDXCCDBDEA'
           'CDBD9DMDSA999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '99999999999ETTEXDKDEUALTLRJVXRHCPRJDLGPJCEQBJOMOAGBZWZCWLNUEWHAU'
           'SYJMYPEZPYNBTPSPGUIPQ9VOUNQ9999999999999999999999999999JVPROMOTA'
           'BLETEST99999999999USHRPBD99999999999999999999XFVLEXEJPTYI9TUA9UL'
           'FNHXBGDUCOEPDIBKSZFXEBO9HFEGLENBCOVKHZ99IWZVCVSTUGKTIBEOVFBJPCDA'
           'WCMHRLDQPBBGISNENMIXOGGYSRYXGAFEJC9FOLXLYIQVUHFCMVRPBIEAXDUYYPYN'
           'EZPHH9KB9HZ9999DAWCMHRLDQPBBGISNENMIXOGGYSRYXGAFEJC9FOLXLYIQVUHF'
           'CMVRPBIEAXDUYYPYNEZPHH9KB9HZ9999ISPROMOTABLETEST99999999999IOCFQ'
           'OIOF999999999MMMMMMMMMCAA9999999UYA99999999999999'
        )

        self.hash2 = TransactionHash(
            'FLNPRAOEYMBIXZBBFMQGCEWLRKTZTMWWTVUQRNUNMZR9EMVKETRMWHRMBFWHJHX'
            'ZOIMUWZALX9IVZ9999'
        )

        # Tuesday, October 29, 2019 4:19:43.600 PM GMT+01:00
        self.valid_now = 1572362383600
        """
        Timestamp that is just greater than the later timestamp in self.trytes.
        """

    def test_wireup(self):
        """
        Verify that the command is wired up correctly. (sync)

        The API method indeed calls the appropiate command.
        """
        with patch('iota.commands.extended.is_promotable.IsPromotableCommand.__call__',
                MagicMock(return_value=async_return('You found me!'))
                ) as mocked_command:

            api = Iota(self.adapter)

            # Don't need to call with proper args here.
            response = api.is_promotable('tails')

            self.assertTrue(mocked_command.called)

            self.assertEqual(
                response,
                'You found me!'
            )

    @async_test
    async def test_wireup_async(self):
        """
        Verify that the command is wired up correctly. (async)

        The API method indeed calls the appropiate command.
        """
        with patch('iota.commands.extended.is_promotable.IsPromotableCommand.__call__',
                MagicMock(return_value=async_return('You found me!'))
                ) as mocked_command:

            api = AsyncIota(self.adapter)

            # Don't need to call with proper args here.
            response = await api.is_promotable('tails')

            self.assertTrue(mocked_command.called)

            self.assertEqual(
                response,
                'You found me!'
            )

    @async_test
    async def test_happy_path(self):
        """
        Successfully checking promotability.
        """

        self.adapter.seed_response('checkConsistency', {
            'state': True,
        })
        self.adapter.seed_response('getTrytes', {
            'trytes': [self.trytes1, self.trytes2]
        })
        
        with mock.patch('iota.commands.extended.is_promotable.get_current_ms',
            mock.MagicMock(return_value=self.valid_now)):
            response = await self.command(tails=[self.hash1, self.hash2])

            self.assertDictEqual(
                response,

                {
                    'promotable': True,
                }
            )

    @async_test
    async def test_not_consistent(self):
        """
        One of the tails is not consistent.
        """

        self.adapter.seed_response('checkConsistency', {
            'state': False,
            'info': 'Oops, something went wrong.',
        })

        # No need for mokcing `getTrytes` becasue we should not
        # reach that part

        response = await self.command(tails=[self.hash1, self.hash2])

        self.assertDictEqual(
            response,

            {
                'promotable': False,
                'info': 'Oops, something went wrong.',
            }
        )
    
    @async_test
    async def test_one_timestamp_invalid(self):
        """
        Test invalid timestamp in one of the transactions.
        """
        # Note that self.trytes2 will have the original and
        # therefore invalid (too old) timestamp
        tx = Transaction.from_tryte_string(self.trytes1)
        tx.attachment_timestamp = get_current_ms()
        self.trytes1 = tx.as_tryte_string()

        self.adapter.seed_response('checkConsistency', {
            'state': True,
        })
        self.adapter.seed_response('getTrytes', {
            'trytes': [self.trytes1, self.trytes2]
        })

        # Here we don`t mock get_current_ms.
        # Tx 1 will have updated, passing timestamp.
        # Tx 2 has the old one, so should fail.
        response = await self.command(tails=[self.hash1, self.hash2])

        self.assertDictEqual(
            response,

            {
                'promotable': False,
                'info': ['Transaction {tx_hash} is above max depth.'.format(
                    tx_hash=self.hash2
                )],
            }
        )

    def test_is_within_depth(self):
        """
        Test ``is_within_depth`` helper method.
        """
        # Timestamp is too old (depth=6)
        now = get_current_ms()
        old_timestamp = now - (6 * MILESTONE_INTERVAL - ONE_WAY_DELAY)

        self.assertEqual(
            is_within_depth(old_timestamp, now),
            False
        )

        # Timestamp points to the future (any number would do)
        future_timestamp = now + 10

        self.assertEqual(
            is_within_depth(future_timestamp, now),
            False
        )

        # Timestamp is valid ( appr. one second 'old')
        timestamp = now - 1000

        self.assertEqual(
            is_within_depth(timestamp, now),
            True
        )
Ejemplo n.º 34
0
class CustomCommandTestCase(TestCase):
  def setUp(self):
    super(CustomCommandTestCase, self).setUp()

    self.name     = 'helloWorld'
    self.adapter  = MockAdapter()
    self.command  = CustomCommand(self.adapter, self.name)

  def test_call(self):
    """
    Sending a custom command.
    """
    expected_response = {'message': 'Hello, IOTA!'}

    self.adapter.seed_response('helloWorld', expected_response)

    response = self.command()

    self.assertEqual(response, expected_response)
    self.assertTrue(self.command.called)

    self.assertListEqual(
      self.adapter.requests,
      [{'command': 'helloWorld'}],
    )

  def test_call_with_parameters(self):
    """
    Sending a custom command with parameters.
    """
    expected_response = {'message': 'Hello, IOTA!'}

    self.adapter.seed_response('helloWorld', expected_response)

    response = self.command(foo='bar', baz='luhrmann')

    self.assertEqual(response, expected_response)
    self.assertTrue(self.command.called)

    self.assertListEqual(
      self.adapter.requests,
      [{'command': 'helloWorld', 'foo': 'bar', 'baz': 'luhrmann'}],
    )

  def test_call_error_already_called(self):
    """
    A command can only be called once.
    """
    self.adapter.seed_response('helloWorld', {})
    self.command()

    with self.assertRaises(RuntimeError):
      self.command(extra='params')

    self.assertDictEqual(self.command.request, {'command': 'helloWorld'})

  def test_call_reset(self):
    """
    Resetting a command allows it to be called more than once.
    """
    self.adapter.seed_response('helloWorld', {'message': 'Hello, IOTA!'})
    self.command()

    self.command.reset()

    self.assertFalse(self.command.called)
    self.assertIsNone(self.command.request)
    self.assertIsNone(self.command.response)

    expected_response = {'message': 'Welcome back!'}
    self.adapter.seed_response('helloWorld', expected_response)
    response = self.command(foo='bar')

    self.assertDictEqual(response, expected_response)
    self.assertDictEqual(self.command.response, expected_response)

    self.assertDictEqual(
      self.command.request,

      {
        'command':  'helloWorld',
        'foo':      'bar',
      },
    )
Ejemplo n.º 35
0
class GetTransfersCommandTestCase(TestCase):
  def setUp(self):
    super(GetTransfersCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = GetTransfersCommand(self.adapter)

    # Define some tryte sequences we can re-use between tests.
    self.addy1 =\
      Address(
        b'TESTVALUEONE9DONTUSEINPRODUCTION99999YDZ'
        b'E9TAFAJGJA9CECKDAEPHBICDR9LHFCOFRBQDHC9IG'
      )

    self.addy2 =\
      Address(
        b'TESTVALUETWO9DONTUSEINPRODUCTION99999TES'
        b'GINEIDLEEHRAOGEBMDLENFDAFCHEIHZ9EBZDD9YHL'
      )

  def test_wireup(self):
    """
    Verify that the command is wired up correctly.
    """
    self.assertIsInstance(
      Iota(self.adapter).getTransfers,
      GetTransfersCommand,
    )

  def test_full_scan(self):
    """
    Scanning the Tangle for all transfers.
    """
    # To speed up the test, we will mock the address generator.
    # :py:class:`iota.crypto.addresses.AddressGenerator` already has
    # its own test case, so this does not impact the stability of the
    # codebase.
    # noinspection PyUnusedLocal
    def create_generator(ag, start, step=1):
      for addy in [self.addy1, self.addy2][start::step]:
        yield addy

    # The first address received IOTA.
    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 42,

        'hashes': [
          'TESTVALUEFIVE9DONTUSEINPRODUCTION99999VH'
          'YHRHJETGYCAFZGABTEUBWCWAS9WF99UHBHRHLIOFJ',
        ],
      },
    )

    # The second address is unused.
    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 1,
        'hashes':   [],
      },
    )

    self.adapter.seed_response(
      'getTrytes',

      {
        'duration': 99,

        # Thankfully, we do not have to seed a realistic response for
        # ``getTrytes``, as we will be mocking the ``getBundles``
        # command that uses on it.
        'trytes': [''],
      },
    )

    bundle = Bundle([
      Transaction(
        address = self.addy1,
        timestamp = 1483033814,

        # These values are not relevant to the test.
        hash_ = None,
        signature_message_fragment = None,
        value = 42,
        tag = Tag(b''),
        current_index = 0,
        last_index = 0,
        bundle_hash = None,
        trunk_transaction_hash = None,
        branch_transaction_hash = None,
        attachment_timestamp = 1483033814,
        attachment_timestamp_lower_bound = 12,
        attachment_timestamp_upper_bound = 0,
        nonce = None,
      )
    ])

    mock_get_bundles =\
      mock.Mock(return_value={
        'bundles': [bundle],
      })

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        create_generator,
    ):
      with mock.patch(
          'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
          mock_get_bundles,
      ):
        response = self.command(seed=Seed.random())

    self.assertDictEqual(
      response,

      {
        'bundles': [bundle],
      },
    )

  def test_no_transactions(self):
    """
    There are no transactions for the specified seed.
    """
    # To speed up the test, we will mock the address generator.
    # :py:class:`iota.crypto.addresses.AddressGenerator` already has
    # its own test case, so this does not impact the stability of the
    # codebase.
    # noinspection PyUnusedLocal
    def create_generator(ag, start, step=1):
      for addy in [self.addy1][start::step]:
        yield addy

    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 1,
        'hashes':   [],
      },
    )

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        create_generator,
    ):
      response = self.command(seed=Seed.random())

    self.assertDictEqual(response, {'bundles': []})

  def test_start(self):
    """
    Scanning the Tangle for all transfers, with start index.
    """
    # noinspection PyUnusedLocal
    def create_generator(ag, start, step=1):
      # Inject an invalid value into the generator, to ensure it is
      # skipped.
      for addy in [None, self.addy1, self.addy2][start::step]:
        yield addy

    # The first address received IOTA.
    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 42,

        'hashes': [
          'TESTVALUEFIVE9DONTUSEINPRODUCTION99999VH'
          'YHRHJETGYCAFZGABTEUBWCWAS9WF99UHBHRHLIOFJ',
        ],
      },
    )

    # The second address is unused.
    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 1,
        'hashes':   [],
      },
    )

    self.adapter.seed_response(
      'getTrytes',

      {
        'duration': 99,
        'trytes':   [''],
      },
    )

    bundle = Bundle([
      Transaction(
        address = self.addy1,
        timestamp = 1483033814,

        # These values are not relevant to the test.
        hash_ = None,
        signature_message_fragment = None,
        value = 42,
        tag = Tag(b''),
        current_index = 0,
        last_index = 0,
        bundle_hash = None,
        trunk_transaction_hash = None,
        branch_transaction_hash = None,
        attachment_timestamp = 1483033814,
        attachment_timestamp_lower_bound = 12,
        attachment_timestamp_upper_bound = 0,
        nonce = None,
      )
    ])

    mock_get_bundles = mock.Mock(return_value={
      'bundles': [bundle],
    })

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        create_generator,
    ):
      with mock.patch(
          'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
          mock_get_bundles,
      ):
        response = self.command(seed=Seed.random(), start=1)

    self.assertDictEqual(
      response,

      {
        'bundles': [bundle],
      },
    )

  def test_stop(self):
    """
    Scanning the Tangle for all transfers, with stop index.
    """
    # noinspection PyUnusedLocal
    def create_generator(ag, start, step=1):
      # Inject an invalid value into the generator, to ensure it is
      # skipped.
      for addy in [self.addy1, None][start::step]:
        yield addy

    # The first address received IOTA.
    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 42,

        'hashes': [
          'TESTVALUEFIVE9DONTUSEINPRODUCTION99999VH'
          'YHRHJETGYCAFZGABTEUBWCWAS9WF99UHBHRHLIOFJ',
        ],
      },
    )

    self.adapter.seed_response(
      'getTrytes',

      {
        'duration': 99,
        'trytes':   [''],
      },
    )

    bundle = Bundle([
      Transaction(
        address = self.addy1,
        timestamp = 1483033814,

        # These values are not relevant to the test.
        hash_ = None,
        signature_message_fragment = None,
        value = 42,
        tag = Tag(b''),
        current_index = 0,
        last_index = 0,
        bundle_hash = None,
        trunk_transaction_hash = None,
        branch_transaction_hash = None,
        attachment_timestamp = 1483033814,
        attachment_timestamp_lower_bound = 12,
        attachment_timestamp_upper_bound = 0,
        nonce = None,
      )
    ])

    mock_get_bundles = mock.Mock(return_value={
      'bundles': [bundle],
    })

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        create_generator,
    ):
      with mock.patch(
          'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
          mock_get_bundles,
      ):
        response = self.command(seed=Seed.random(), stop=1)

    self.assertDictEqual(
      response,

      {
        'bundles': [bundle],
      },
    )

  def test_get_inclusion_states(self):
    """
    Fetching inclusion states with transactions.
    """
    # noinspection PyUnusedLocal
    def create_generator(ag, start, step=1):
      for addy in [self.addy1][start::step]:
        yield addy

    # The first address received IOTA.
    self.adapter.seed_response(
      'findTransactions',

      {
        'duration': 42,

        'hashes': [
          'TESTVALUEFIVE9DONTUSEINPRODUCTION99999VH'
          'YHRHJETGYCAFZGABTEUBWCWAS9WF99UHBHRHLIOFJ',
        ],
      },
    )

    # For this test, we have to generate a real TryteString.
    transaction_trytes =\
      TryteString(
        b'KMYUMNEUAYODAQSNGWTAERRRHNZBZCOLMVVOBTVWLOFYCJKYMGRAMH9RQ9MTZOSZMH'
        b'QNZFHFEJEDFQ99HSUNVOTULDJGXEDULS9ZHABVDZODJUMCNWVCPNSCUVKVYWCEXBHW'
        b'RBZBSWFPQLWZWMUPGQIGAEGOVE9DDXBVCIPKQYCFZFBELTSMVFSIXLPTACTKAFMCTK'
        b'CPYD9BWDJMLKWAOBDSJNQYAHS9GFIQKZCROLFZJVUEIVXVNBRRLEIWTYVHURUXHSCG'
        b'DKEIEGPOCXKCYWIBUG9ABYCALYJVFLBNGMS9ARHGTQXBZFLENXCJVKHPVKD9KSAEOL'
        b'FFVAJCNKLDVHOCDARWUNKARDYMVKFKRSMUTYOUXSBFFYTKRREBDJZTLVUROQFCBXQN'
        b'SXDDYTZTEBRSXOBMLXHJKSJAVOOVCXATOWNQDWHT9CCUAAJUJKDOQLMAEZACSNFKXZ'
        b'IGWDQEUEFRZYAOSDNVMSXWYLVDAUXZSHNHAIBEMNPFUGORYUETNJK9UCEMSUJYBBDK'
        b'BHIPKEINQCGOVYCPKUPJMUCUVZOJSIWYRFMFXYUVSMOUALAQBWIMXBUBXSAETGKJRP'
        b'AHVAXHQJDMEVSRFYEXUSIEBKMGYCUKFD9JPGUV9AIYUVCRUURKMYUHMVE9OJCYYWTQ'
        b'WUWFMTBZYFXASHHVCMSWXKBRQFHHQVEQMEULJRWZKLWFFSGGKEHUZZFNDNITSRAUH9'
        b'PQK9OGLYMVBSHXQLLZHOBBIM9KVUWDLHZRDKQQVLQXGWYXEEVQPDZUO9PVXMALOMRQ'
        b'VCTHGIZLILSCFKTBRESYZGBZKHXEODNDJZ9GK9ROWYXNGFHZCCBHHZEYEOGWXRGSUD'
        b'SUZFUAUBXVXZHCUVJSYBWTCYCEDYKZNGWFZYKSQLW9FUYMWDVXKZEWT9SCVMQCODZK'
        b'DRNKTINTPNOJOLGQJDAJMFWRFSWZJLYZGSTSIDSXLUJBZRZNLEDNBKAUNGTCYUPDRW'
        b'JOCEBQ9YG9IZLLRMJITISJOTLQMOGXVQIZXHMTJVMMWM9FOIOT9KFZMANEPOEOV9HX'
        b'JNEGURUKRWDGYNPVGAWMWQVABIJNL9MDXKONEPMYACOZ9BE9UZMAFTKYWPFWIQWAPK'
        b'GUXQTOQVWYYVZYGQDLBIQDVOZIWGOMGOBAUARICQZVNXD9UVEFBBAJKQBHRHXTBUOW'
        b'VBFKYQWZWTMMXVKZRIZUBVPQ9XHLJHFHWFZUIZVSNAKBDHDFGJCYQETOMEDTOXIUT9'
        b'OAJVIHWAGTCNPEZTERMMN9EZEWSJHKQAUMXPBZTNQOEQCVXIMAAYO9NIUFLTCFIMK9'
        b'9AFAGWJFA9VOFPUDJLRAMORGSUDBLWWKXEDZ9XPQUZSGANGESHKKGGQSGSYDCRLHZD'
        b'PKA9HKYBKLKKCXYRQQIPXCFETJJDZYPCLUNHGBKEJDRCIHEXKCQQNOV9QFHLGFXOCR'
        b'HPAFCUTPMY9NOZVQHROYJSCMGRSVMOBWADAZNFIAHWGIQUUZBOVODSFAUNRTXSDU9W'
        b'EIRBXQNRSJXFRAQGHA9DYOQJGLVZUJKAQ9CTUOTT9ZKQOQNNLJDUPDXZJYPRCVLRZT'
        b'UCZPNBREYCCKHK9FUWGITAJATFPUOFLZDHPNJYUTXFGNYJOBRD9BVHKZENFXIUYDTL'
        b'CE9JYIIYMXMCXMWTHOLTQFKFHDLVPGMQNITEUXSYLAQULCZOJVBIPYP9M9X9QCNKBX'
        b'W9DVJEQFFY9KQVMKNVTAHQVRXUKEM9FZOJLHAGEECZBUHOQFZOSPRXKZOCCKAOHMSV'
        b'QCFG9CWAHKVWNA9QTLYQI9NKOSHWJCNGPJBLEQPUIWJBIOAWKLBXUCERTSL9FVCLYN'
        b'ADPYTPKJOIEMAQGWBVGSRCZINXEJODUDCT9FHOUMQM9ZHRMBJYSOMPNMEAJGEHICJI'
        b'PVXRKCYX9RZVT9TDZIMXGZJAIYJRGIVMSOICSUINRBQILMJOUQYXCYNJ9WGGJFHYTU'
        b'LWOIPUXXFNTIFNOJRZFSQQNAWBQZOLHHLVGHEPWTKKQEVIPVWZUN9ZBICZ9DZZBVII'
        b'BF9EPHARZJUFJGBQXQFQIBUECAWRSEKYJNYKNSVBCOWTFBZ9NAHFSAMRBPEYGPRGKW'
        b'WTWACZOAPEOECUO9OTMGABJVAIICIPXGSXACVINSYEQFTRCQPCEJXZCY9XZWVWVJRZ'
        b'CYEYNFUUBKPWCHICGJZXKE9GSUDXZYUAPLHAKAHYHDXNPHENTERYMMBQOPSQIDENXK'
        b'LKCEYCPVTZQLEEJVYJZV9BWU999999999999999999999999999FFL999999999999'
        b'9999999999999RJQGVD99999999999A99999999USGBXHGJUEWAUAKNPPRHJXDDMQV'
        b'YDSYZJSDWFYLOQVFGBOSLE9KHFDLDYHUYTXVSFAFCOCLQUHJXTEIQRNBTLHEGJFGVF'
        b'DJCE9IKAOCSYHLCLWPVVNWNESKLYAJG9FGGZOFXCEYOTWLVIJUHGY9QCU9FMZJY999'
        b'9999HYBUYQKKRNAVDPVGYBTVDZ9SVQBLCCVLJTPEQWWOIG9CQZIFQKCROH9YHUCNJT'
        b'SYPBVZVBNESX999999D9TARGPQTNIYRZURQGVHCAWEDRBJIIEJIUZYENVE9LLJQMXH'
        b'GSUUYUCPSOWBCXVFDCHHAZUDC9LUODYWO'
      )

    self.adapter.seed_response(
      'getTrytes',

      {
        'duration': 99,
        'trytes':   [binary_type(transaction_trytes)],
      },
    )

    transaction = Transaction.from_tryte_string(transaction_trytes)

    mock_get_bundles = mock.Mock(return_value={
      'bundles': [Bundle([transaction])],
    })

    mock_get_latest_inclusion = mock.Mock(return_value={
      'states': {
        transaction.hash: True,
      },
    })

    with mock.patch(
        'iota.crypto.addresses.AddressGenerator.create_iterator',
        create_generator,
    ):
      with mock.patch(
          'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
          mock_get_bundles,
      ):
        with mock.patch(
          'iota.commands.extended.get_latest_inclusion.GetLatestInclusionCommand._execute',
          mock_get_latest_inclusion,
        ):
          response = self.command(
            seed = Seed.random(),

            inclusionStates = True,

            # To keep the test focused, only retrieve a single
            # transaction.
            start = 0,
            stop  = 1,
          )

    bundle = response['bundles'][0] # type: Bundle
    self.assertTrue(bundle[0].is_confirmed)
Ejemplo n.º 36
0
class GetNewAddressesRequestFilterTestCase(BaseFilterTestCase):
    filter_type = GetNewAddressesCommand(MockAdapter()).get_request_filter
    skip_value_check = True

    # noinspection SpellCheckingInspection
    def setUp(self):
        super(GetNewAddressesRequestFilterTestCase, self).setUp()

        # Define a few tryte sequences that we can re-use between tests.
        self.seed = b'HELLOIOTA'

    def test_pass_happy_path(self):
        """
    Request is valid.
    """
        request = {
            'seed': Seed(self.seed),
            'index': 1,
            'count': 1,
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)

    def test_pass_optional_parameters_excluded(self):
        """
    Request omits ``index`` and ``count``.
    """
        filter_ = self._filter({
            'seed': Seed(self.seed),
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'seed': Seed(self.seed),
                'index': 0,
                'count': None,
            },
        )

    def test_pass_compatible_types(self):
        """
    Request contains values that can be converted to the expected
    types.
    """
        filter_ = self._filter({
            # ``seed`` can be any value that is convertible to TryteString.
            'seed': binary_type(self.seed),

            # These values must be integers, however.
            'index': 100,
            'count': 8,
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'seed': Seed(self.seed),
                'index': 100,
                'count': 8,
            },
        )

    def test_fail_empty(self):
        """
    Request is empty.
    """
        self.assertFilterErrors(
            {},
            {
                'seed': [f.FilterMapper.CODE_MISSING_KEY],
            },
        )

    def test_fail_unexpected_parameters(self):
        """
    Request contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'seed': Seed(self.seed),
                'index': None,
                'count': 1,

                # Some men just want to watch the world burn.
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )

    def test_fail_seed_null(self):
        """
    ``seed`` is null.
    """
        self.assertFilterErrors(
            {
                'seed': None,
            },
            {
                'seed': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_seed_wrong_type(self):
        """
    ``seed`` cannot be converted into a TryteString.
    """
        self.assertFilterErrors(
            {
                'seed': text_type(self.seed, 'ascii'),
            },
            {
                'seed': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_seed_malformed(self):
        """
    ``seed`` has the correct type, but it contains invalid characters.
    """
        self.assertFilterErrors(
            {
                'seed':
                b'not valid; seeds can only contain uppercase and "9".',
            },
            {
                'seed': [Trytes.CODE_NOT_TRYTES],
            },
        )

    def test_fail_count_string(self):
        """
    ``count`` is a string value.
    """
        self.assertFilterErrors(
            {
                # Not valid; it must be an int.
                'count': '42',
                'seed': Seed(self.seed),
            },
            {
                'count': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_count_float(self):
        """
    ``count`` is a float value.
    """
        self.assertFilterErrors(
            {
                # Not valid, even with an empty fpart; it must be an int.
                'count': 42.0,
                'seed': Seed(self.seed),
            },
            {
                'count': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_count_too_small(self):
        """
    ``count`` is less than 1.
    """
        self.assertFilterErrors(
            {
                'count': 0,
                'seed': Seed(self.seed),
            },
            {
                'count': [f.Min.CODE_TOO_SMALL],
            },
        )

    def test_fail_index_string(self):
        """
    ``index`` is a string value.
    """
        self.assertFilterErrors(
            {
                # Not valid; it must be an int.
                'index': '42',
                'seed': Seed(self.seed),
            },
            {
                'index': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_index_float(self):
        """
    ``index`` is a float value.
    """
        self.assertFilterErrors(
            {
                # Not valid, even with an empty fpart; it must be an int.
                'index': 42.0,
                'seed': Seed(self.seed),
            },
            {
                'index': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_index_too_small(self):
        """
    ``index`` is less than 0.
    """
        self.assertFilterErrors(
            {
                'index': -1,
                'seed': Seed(self.seed),
            },
            {
                'index': [f.Min.CODE_TOO_SMALL],
            },
        )
Ejemplo n.º 37
0
class PromoteTransactionRequestFilterTestCase(BaseFilterTestCase):
    filter_type = PromoteTransactionCommand(MockAdapter()).get_request_filter
    skip_value_check = True

    # noinspection SpellCheckingInspection
    def setUp(self):
        super(PromoteTransactionRequestFilterTestCase, self).setUp()

        self.trytes1 = (b'TESTVALUEONE9DONTUSEINPRODUCTION99999DAU'
                        b'9WFSFWBSFT9QATCXFIIKDVFLHIIJGGFCDYENBEDCF')

    def test_pass_happy_path(self):
        """
    Request is valid.
    """
        request = {
            'depth': 100,
            'minWeightMagnitude': 18,
            'transaction': TransactionHash(self.trytes1),
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)

    def test_pass_compatible_types(self):
        """
    Request contains values that can be converted to the expected
    types.
    """
        filter_ = self._filter({
            # This can be any TrytesCompatible value.
            'transaction': binary_type(self.trytes1),

            # These values must still be ints, however.
            'depth': 100,
            'minWeightMagnitude': 18,
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,
            {
                'depth': 100,
                'minWeightMagnitude': 18,
                'transaction': TransactionHash(self.trytes1),
            },
        )

    def test_fail_empty(self):
        """
    Request is empty.
    """
        self.assertFilterErrors(
            {},
            {
                'depth': [f.FilterMapper.CODE_MISSING_KEY],
                'minWeightMagnitude': [f.FilterMapper.CODE_MISSING_KEY],
                'transaction': [f.FilterMapper.CODE_MISSING_KEY],
            },
        )

    def test_fail_unexpected_parameters(self):
        """
    Request contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'depth': 100,
                'minWeightMagnitude': 18,
                'transaction': TransactionHash(self.trytes1),

                # That's a real nasty habit you got there.
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )

    def test_fail_transaction_null(self):
        """
    ``transaction`` is null.
    """
        self.assertFilterErrors(
            {
                'transaction': None,
                'depth': 100,
                'minWeightMagnitude': 18,
            },
            {
                'transaction': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_transaction_wrong_type(self):
        """
    ``transaction`` is not a TrytesCompatible value.
    """
        self.assertFilterErrors(
            {
                'transaction': 42,
                'depth': 100,
                'minWeightMagnitude': 18,
            },
            {
                'transaction': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_transaction_not_trytes(self):
        """
    ``transaction`` contains invalid characters.
    """
        self.assertFilterErrors(
            {
                'transaction':
                b'not valid; must contain only uppercase and "9"',
                'depth': 100,
                'minWeightMagnitude': 18,
            },
            {
                'transaction': [Trytes.CODE_NOT_TRYTES],
            },
        )

    def test_fail_depth_null(self):
        """
    ``depth`` is null.
    """
        self.assertFilterErrors(
            {
                'depth': None,
                'minWeightMagnitude': 18,
                'transaction': TransactionHash(self.trytes1),
            },
            {
                'depth': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_depth_string(self):
        """
    ``depth`` is a string.
    """
        self.assertFilterErrors(
            {
                # Too ambiguous; it's gotta be an int.
                'depth': '4',
                'minWeightMagnitude': 18,
                'transaction': TransactionHash(self.trytes1),
            },
            {
                'depth': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_depth_float(self):
        """
    ``depth`` is a float.
    """
        self.assertFilterErrors(
            {
                # Even with an empty fpart, float value is not valid.
                'depth': 8.0,
                'minWeightMagnitude': 18,
                'transaction': TransactionHash(self.trytes1),
            },
            {
                'depth': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_depth_too_small(self):
        """
    ``depth`` is < 1.
    """
        self.assertFilterErrors(
            {
                'depth': 0,
                'minWeightMagnitude': 18,
                'transaction': TransactionHash(self.trytes1),
            },
            {
                'depth': [f.Min.CODE_TOO_SMALL],
            },
        )

    def test_fail_min_weight_magnitude_null(self):
        """
    ``minWeightMagnitude`` is null.
    """
        self.assertFilterErrors(
            {
                'minWeightMagnitude': None,
                'depth': 100,
                'transaction': TransactionHash(self.trytes1),
            },
            {
                'minWeightMagnitude': [f.Required.CODE_EMPTY],
            },
        )

    def test_fail_min_weight_magnitude_string(self):
        """
    ``minWeightMagnitude`` is a string.
    """
        self.assertFilterErrors(
            {
                # It's gotta be an int!
                'minWeightMagnitude': '18',
                'depth': 100,
                'transaction': TransactionHash(self.trytes1),
            },
            {
                'minWeightMagnitude': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_min_weight_magnitude_float(self):
        """
    ``minWeightMagnitude`` is a float.
    """
        self.assertFilterErrors(
            {
                # Even with an empty fpart, float values are not valid.
                'minWeightMagnitude': 18.0,
                'depth': 100,
                'transaction': TransactionHash(self.trytes1),
            },
            {
                'minWeightMagnitude': [f.Type.CODE_WRONG_TYPE],
            },
        )

    def test_fail_min_weight_magnitude_too_small(self):
        """
    ``minWeightMagnitude`` is < 1.
    """
        self.assertFilterErrors(
            {
                'minWeightMagnitude': 0,
                'depth': 100,
                'transaction': TransactionHash(self.trytes1),
            },
            {
                'minWeightMagnitude': [f.Min.CODE_TOO_SMALL],
            },
        )
Ejemplo n.º 38
0
    def setUp(self):
        super(IsReattachableCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
Ejemplo n.º 39
0
class PromoteTransactionCommandTestCase(TestCase):
    def setUp(self):
        super(PromoteTransactionCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = PromoteTransactionCommand(self.adapter)

        self.trytes1 = b'RBTC9D9DCDQAEASBYBCCKBFA'
        self.trytes2 =\
          b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA'

        self.hash1 = TransactionHash(
            b'TESTVALUE9DONTUSEINPRODUCTION99999TBPDM9'
            b'ADFAWCKCSFUALFGETFIFG9UHIEFE9AYESEHDUBDDF')

    def test_wireup(self):
        """
    Verifies that the command is wired-up correctly.
    """
        self.assertIsInstance(
            Iota(self.adapter).promoteTransaction,
            PromoteTransactionCommand,
        )

    def test_happy_path(self):
        """
    Successfully promoting a bundle.
    """

        self.adapter.seed_response('checkConsistency', {
            'state': True,
        })

        result_bundle = Bundle.from_tryte_strings([
            TransactionTrytes(self.trytes1),
            TransactionTrytes(self.trytes2),
        ])
        mock_send_transfer = mock.Mock(return_value={
            'bundle': result_bundle,
        })

        with mock.patch(
                'iota.commands.extended.send_transfer.SendTransferCommand._execute',
                mock_send_transfer,
        ):

            response = self.command(
                transaction=self.hash1,
                depth=3,
                minWeightMagnitude=16,
            )

        self.assertDictEqual(response, {
            'bundle': result_bundle,
        })

    def test_not_promotable(self):
        """
    Bundle isn't promotable.
    """

        self.adapter.seed_response('checkConsistency', {
            'state': False,
        })

        with self.assertRaises(BadApiResponse):
            response = self.command(
                transaction=self.hash1,
                depth=3,
                minWeightMagnitude=16,
            )
Ejemplo n.º 40
0
    def setUp(self):
        super(IsPromotableCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = IsPromotableCommand(self.adapter)

        # Define some tryte sequences that we can re-use across tests.
        self.trytes1 = TransactionTrytes(
            'CCGCVADBEACCWCXCGDEAXCGDEAPCEAHDTCGDHDEAHDFDPCBDGDPCRCHDXCCDBDE'
            'ACDBD9DMDSA9999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999999999999999999999'
            '999999999999999999999999999999999999999999999ETTEXDKDEUALTLRJVX'
            'RHCPRJDLGPJCEQBJOMOAGBZWZCWLNUEWHAUSYJMYPEZPYNBTPSPGUIPQ9VOUNQ9'
            '999999999999999999999999999JVPROMOTABLETEST99999999999USHRPBD99'
            '999999999999999999XFVLEXEJPTYI9TUA9ULFNHXBGDUCOEPDIBKSZFXEBO9HF'
            'EGLENBCOVKHZ99IWZVCVSTUGKTIBEOVFBJPCDYHBDEIIBLHRVQX9KVVRTUIQMOF'
            'XUUETRIQCCCLSMVREZSNEXLIZCIUYIYRBJIBOKNJCQAJTAHGNZ9999DYHBDEIIB'
            'LHRVQX9KVVRTUIQMOFXUUETRIQCCCLSMVREZSNEXLIZCIUYIYRBJIBOKNJCQAJT'
            'AHGNZ9999ISPROMOTABLETEST9999999999999BFQOIOF999999999MMMMMMMMM'
            'EL999999999AG99999999999999'
        )

        self.hash1 = TransactionHash(
            'MHNBILKFU9CADOPNWSFYOMILGKJAHEU9GSSOYUEAPBGOOLAIKGBYSACXMFQRJZE'
            'PBSHI9SDKMBRK99999'
        )

        self.trytes2 = TransactionTrytes(
           'CCGCVADBEACCWCXCGDEAXCGDEAPCEAHDTCGDHDEAHDFDPCBDGDPCRCHDXCCDBDEA'
           'CDBD9DMDSA999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '9999999999999999999999999999999999999999999999999999999999999999'
           '99999999999ETTEXDKDEUALTLRJVXRHCPRJDLGPJCEQBJOMOAGBZWZCWLNUEWHAU'
           'SYJMYPEZPYNBTPSPGUIPQ9VOUNQ9999999999999999999999999999JVPROMOTA'
           'BLETEST99999999999USHRPBD99999999999999999999XFVLEXEJPTYI9TUA9UL'
           'FNHXBGDUCOEPDIBKSZFXEBO9HFEGLENBCOVKHZ99IWZVCVSTUGKTIBEOVFBJPCDA'
           'WCMHRLDQPBBGISNENMIXOGGYSRYXGAFEJC9FOLXLYIQVUHFCMVRPBIEAXDUYYPYN'
           'EZPHH9KB9HZ9999DAWCMHRLDQPBBGISNENMIXOGGYSRYXGAFEJC9FOLXLYIQVUHF'
           'CMVRPBIEAXDUYYPYNEZPHH9KB9HZ9999ISPROMOTABLETEST99999999999IOCFQ'
           'OIOF999999999MMMMMMMMMCAA9999999UYA99999999999999'
        )

        self.hash2 = TransactionHash(
            'FLNPRAOEYMBIXZBBFMQGCEWLRKTZTMWWTVUQRNUNMZR9EMVKETRMWHRMBFWHJHX'
            'ZOIMUWZALX9IVZ9999'
        )

        # Tuesday, October 29, 2019 4:19:43.600 PM GMT+01:00
        self.valid_now = 1572362383600
        """
Ejemplo n.º 41
0
class GetNewAddressesCommandTestCase(TestCase):
    def setUp(self):
        super(GetNewAddressesCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = GetNewAddressesCommand(self.adapter)

        # Create a few TryteStrings we can reuse across tests.
        self.addy1 =\
          Address(
            b'ADDYONE999AHHKVD9SBEYWQFNVQSNTGYQSQ9AGWD'
            b'JDZKBYCVTODUHFEVVMNMPQMIXOVXVCZRUENAWYNTO'
          )

        self.addy2 =\
          Address(
            b'ADDYTWO999AGAQKYXHRMSFAQNPWCIYUYTXPWUEUR'
            b'VNZTCTFUPQ9ESTKNSSLLIZWDQISJVEWIJDVGIECXF'
          )

    def test_wireup(self):
        """
    Verify that the command is wired up correctly.
    """
        self.assertIsInstance(
            Iota(self.adapter).getNewAddresses,
            GetNewAddressesCommand,
        )

    def test_get_addresses_offline(self):
        """
    Generate addresses in offline mode (without filtering used
    addresses).
    """

        # To speed up the test, we will mock the address generator.
        # :py:class:`iota.crypto.addresses.AddressGenerator` already has
        # its own test case, so this does not impact the stability of the
        # codebase.
        # noinspection PyUnusedLocal
        def create_generator(ag, start, step=1):
            for addy in [self.addy1, self.addy2][start::step]:
                yield addy

        with patch(
                target=
                'iota.crypto.addresses.AddressGenerator.create_generator',
                new=create_generator,
        ):
            response = self.command(
                count=2,
                index=0,
                seed=b'TESTSEED9DONTUSEINPRODUCTION99999',
            )

        self.assertDictEqual(response, {'addresses': [self.addy1, self.addy2]})

        # No API requests were made.
        self.assertListEqual(self.adapter.requests, [])

    def test_get_addresses_online(self):
        """
    Generate address in online mode (filtering used addresses).
    """
        # Pretend that ``self.addy1`` has already been used, but not
        # ``self.addy2``.
        self.adapter.seed_response(
            'findTransactions', {
                'duration':
                18,
                'hashes': [
                    'ZJVYUGTDRPDYFGFXMKOTV9ZWSGFK9CFPXTITQLQN'
                    'LPPG9YNAARMKNKYQO9GSCSBIOTGMLJUFLZWSY9999',
                ],
            })

        self.adapter.seed_response('findTransactions', {
            'duration': 1,
            'hashes': [],
        })

        # To speed up the test, we will mock the address generator.
        # :py:class:`iota.crypto.addresses.AddressGenerator` already has
        # its own test case, so this does not impact the stability of the
        # codebase.
        # noinspection PyUnusedLocal
        def create_generator(ag, start, step=1):
            for addy in [self.addy1, self.addy2][start::step]:
                yield addy

        with patch(
                target=
                'iota.crypto.addresses.AddressGenerator.create_generator',
                new=create_generator,
        ):
            response = self.command(
                # If ``count`` is missing or ``None``, the command will operate
                # in online mode.
                # count = None,
                index=0,
                seed=b'TESTSEED9DONTUSEINPRODUCTION99999',
            )

        # The command determined that ``self.addy1`` was already used, so
        # it skipped that one.
        self.assertDictEqual(response, {'addresses': [self.addy2]})

        self.assertListEqual(
            self.adapter.requests,

            # The command issued two `findTransactions` API requests: one for
            # each address generated, until it found an unused address.
            [
                {
                    'command': 'findTransactions',
                    'addresses': [self.addy1],
                    'approvees': [],
                    'bundles': [],
                    'tags': [],
                },
                {
                    'command': 'findTransactions',
                    'addresses': [self.addy2],
                    'approvees': [],
                    'bundles': [],
                    'tags': [],
                },
            ],
        )
Ejemplo n.º 42
0
    def setUp(self):
        super(GetMissingTransactionsCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
class GetLatestInclusionCommandTestCase(TestCase):
  # noinspection SpellCheckingInspection
  def setUp(self):
    super(GetLatestInclusionCommandTestCase, self).setUp()

    self.adapter = MockAdapter()
    self.command = GetLatestInclusionCommand(self.adapter)

    # Define some tryte sequences that we can re-use across tests.
    self.milestone =\
      TransactionHash(
        b'TESTVALUE9DONTUSEINPRODUCTION99999W9KDIH'
        b'BALAYAFCADIDU9HCXDKIXEYDNFRAKHN9IEIDZFWGJ'
      )

    self.hash1 =\
      TransactionHash(
        b'TESTVALUE9DONTUSEINPRODUCTION99999TBPDM9'
        b'ADFAWCKCSFUALFGETFIFG9UHIEFE9AYESEHDUBDDF'
      )

    self.hash2 =\
      TransactionHash(
        b'TESTVALUE9DONTUSEINPRODUCTION99999CIGCCF'
        b'KIUFZF9EP9YEYGQAIEXDTEAAUGAEWBBASHYCWBHDX'
      )

  def test_wireup(self):
    """
    Verify that the command is wired up correctly.
    """
    self.assertIsInstance(
      Iota(self.adapter).getLatestInclusion,
      GetLatestInclusionCommand,
    )

  def test_happy_path(self):
    """
    Successfully requesting latest inclusion state.
    """
    self.adapter.seed_response('getNodeInfo', {
        # ``getNodeInfo`` returns lots of info, but the only value that
        # matters for this test is ``latestSolidSubtangleMilestone``.
        'latestSolidSubtangleMilestone': self.milestone,
      },
    )

    self.adapter.seed_response('getInclusionStates', {
      'states': [True, False],
    })

    response = self.command(hashes=[self.hash1, self.hash2])

    self.assertDictEqual(
      response,

      {
        'states': {
          self.hash1: True,
          self.hash2: False,
        },
      }
    )