def __init__(self, *args, quality_check=False, **kwargs): """ Args: *args: quality_check (bool): there are times when we only establish a connection to check the quality of the node/address **kwargs: """ self._stream_reader = StreamReader() self._stream_writer = None nodemanager = kwargs.pop('nodemanager') self.client = NeoNode(self, nodemanager, quality_check) self._loop = events.get_event_loop() super().__init__(self._stream_reader)
def test_sendmany_good_simple(self): nodemgr = NodeManager() nodemgr.reset_for_test() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Send.prompt', side_effect=[ "neo", self.watch_addr_str, "1", "gas", self.watch_addr_str, "1", UserWalletTestCase.wallet_1_pass() ]): PromptData.Wallet = self.GetWallet1(recreate=True) args = ['sendmany', '2'] res = Wallet.CommandWallet().execute(args) self.assertTrue(res) # verify successful tx self.assertIn("Sending with fee: 0", mock_print.getvalue()) json_res = res.ToJson() # check for 2 transfers transfers = 0 for info in json_res['vout']: if info['address'] == self.watch_addr_str: transfers += 1 self.assertEqual(2, transfers)
def test_send_with_fee_and_from_addr(self): nodemgr = NodeManager() nodemgr.reset_for_test() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): PromptData.Wallet = self.GetWallet1(recreate=True) args = [ 'send', 'neo', self.watch_addr_str, '1', '--from-addr=AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3', '--fee=0.005' ] res = Wallet.CommandWallet().execute(args) self.assertTrue(res) # verify successful tx json_res = res.ToJson() self.assertEqual(self.watch_addr_str, json_res['vout'][0] ['address']) # verify correct address_to self.assertEqual( self.wallet_1_addr, json_res['vout'][1] ['address']) # verify correct address_from self.assertEqual(json_res['net_fee'], "0.005") # verify correct fee self.assertIn("Sending with fee: 0.005", mock_print.getvalue())
def test_send_token_ok(self): nodemgr = NodeManager() nodemgr.reset_for_test() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): with patch('neo.Prompt.Commands.Tokens.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): with patch('sys.stdout', new=StringIO()) as mock_print: PromptData.Wallet = self.GetWallet1(recreate=True) token_hash = '31730cc9a1844891a3bafd1aa929a4142860d8d3' ImportToken(PromptData.Wallet, token_hash) args = [ 'send', 'NXT4', self.watch_addr_str, '30', '--from-addr=%s' % self.wallet_1_addr ] res = Wallet.CommandWallet().execute(args) self.assertTrue(res) self.assertIn( "Will transfer 30.00000000 NXT4 from AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3 to AGYaEi3W6ndHPUmW7T12FFfsbQ6DWymkEm", mock_print.getvalue())
def test_wallet_claim_3(self): self.OpenWallet1() # test with bad --to-addr with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=[WalletFixtureTestCase.wallet_1_pass()]): args = ['claim', '--to-addr=AGYaEi3W6ndHPUmW7T12FFfsbQ6DWymkEn'] # bad address checksum claim_tx, relayed = CommandWallet().execute(args) self.assertEqual(claim_tx, None) self.assertFalse(relayed) self.assertIn("Address format error", mock_print.getvalue()) # test with an invalid --to-addr with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=[WalletFixtureTestCase.wallet_1_pass()]): args = ['claim', '--to-addr=blah'] # completely wrong address format claim_tx, relayed = CommandWallet().execute(args) self.assertEqual(claim_tx, None) self.assertFalse(relayed) self.assertIn("Not correct Address, wrong length", mock_print.getvalue()) # test with --to-addr nodemgr = NodeManager() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=[WalletFixtureTestCase.wallet_1_pass()]): with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): args = ['claim', '--to-addr=' + self.watch_addr_str] claim_tx, relayed = CommandWallet().execute(args) self.assertIsInstance(claim_tx, ClaimTransaction) self.assertTrue(relayed) json_tx = claim_tx.ToJson() self.assertEqual(json_tx['vout'][0]['address'], self.watch_addr_str) # note how the --to-addr supercedes the default change address nodemgr.reset_for_test()
def test_wallet_claim_2(self): self.OpenWallet2() # test with bad --from-addr with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=[WalletFixtureTestCase.wallet_2_pass()]): args = ['claim', '--from-addr=AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc'] # address is too short claim_tx, relayed = CommandWallet().execute(args) self.assertEqual(claim_tx, None) self.assertFalse(relayed) self.assertIn("Not correct Address, wrong length.", mock_print.getvalue()) # test with invalid --from-addr with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=[WalletFixtureTestCase.wallet_2_pass()]): args = ['claim', '--from-addr=VJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3'] # address does not start with 'A' claim_tx, relayed = CommandWallet().execute(args) self.assertEqual(claim_tx, None) self.assertFalse(relayed) self.assertIn("Address format error", mock_print.getvalue()) # successful test with --from-addr nodemgr = NodeManager() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=[WalletFixtureTestCase.wallet_2_pass()]): with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): args = ['claim', '--from-addr=' + self.wallet_1_addr] claim_tx, relayed = CommandWallet().execute(args) self.assertIsInstance(claim_tx, ClaimTransaction) self.assertTrue(relayed) json_tx = claim_tx.ToJson() self.assertEqual(json_tx['vout'][0]['address'], self.wallet_1_addr) nodemgr.reset_for_test()
def test_5_wallet_claim_ok(self): wallet = self.GetWallet1() nodemgr = NodeManager() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): with patch('neo.Prompt.Commands.Wallet.prompt', return_value=self.wallet_1_pass()): claim_tx, relayed = ClaimGas(wallet) self.assertIsInstance(claim_tx, ClaimTransaction) self.assertTrue(relayed)
def test_sendmany_good_complex(self): nodemgr = NodeManager() nodemgr.reset_for_test() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Send.prompt', side_effect=[ "neo", "AXjaFSP23Jkbe6Pk9pPGT6NBDs1HVdqaXK", "1", "gas", "AXjaFSP23Jkbe6Pk9pPGT6NBDs1HVdqaXK", "1", UserWalletTestCase.wallet_1_pass() ]): PromptData.Wallet = self.GetWallet1(recreate=True) args = [ 'sendmany', '2', '--from-addr=%s' % self.wallet_1_addr, '--change-addr=%s' % self.watch_addr_str, '--fee=0.005' ] address_from_account_state = Blockchain.Default( ).GetAccountState(self.wallet_1_addr).ToJson() address_from_gas = next( filter( lambda b: b['asset'] == '0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7', address_from_account_state['balances'])) address_from_gas_bal = address_from_gas['value'] res = Wallet.CommandWallet().execute(args) self.assertTrue(res) # verify successful tx json_res = res.ToJson() self.assertEqual("AXjaFSP23Jkbe6Pk9pPGT6NBDs1HVdqaXK", json_res['vout'][0] ['address']) # verify correct address_to self.assertEqual( self.watch_addr_str, json_res['vout'][2] ['address']) # verify correct change address self.assertEqual( float(address_from_gas_bal) - 1 - 0.005, float(json_res['vout'][3]['value'])) self.assertEqual('0.005', json_res['net_fee']) self.assertIn("Sending with fee: 0.005", mock_print.getvalue())
def test_send_gas(self): nodemgr = NodeManager() nodemgr.reset_for_test() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): PromptData.Wallet = self.GetWallet1(recreate=True) args = ['send', 'gas', self.watch_addr_str, '5'] res = Wallet.CommandWallet().execute(args) self.assertTrue(res) self.assertIn("Sending with fee: 0", mock_print.getvalue())
def test_wallet_claim_4(self): self.OpenWallet2() # test with --from-addr and --to-addr nodemgr = NodeManager() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=[WalletFixtureTestCase.wallet_2_pass()]): with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): args = ['claim', '--from-addr=' + self.wallet_1_addr, '--to-addr=' + self.wallet_2_addr] claim_tx, relayed = CommandWallet().execute(args) self.assertIsInstance(claim_tx, ClaimTransaction) self.assertTrue(relayed) json_tx = claim_tx.ToJson() self.assertEqual(json_tx['vout'][0]['address'], self.wallet_2_addr) # note how the --to-addr also supercedes the from address if both are specified nodemgr.reset_for_test()
def test_bad_attributes(self): nodemgr = NodeManager() nodemgr.reset_for_test() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): PromptData.Wallet = self.GetWallet1(recreate=True) args = [ 'send', 'gas', self.watch_addr_str, '2', '--tx-attr=[{"usa:241"data":his is a remark"}]' ] res = Wallet.CommandWallet().execute(args) self.assertTrue(res) self.assertEqual(1, len(res.Attributes))
def test_transaction_size_1(self): nodemgr = NodeManager() nodemgr.reset_for_test() nodemgr.nodes = [NeoNode(object, object)] with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): with patch('neo.Core.TX.Transaction.Transaction.Size', return_value=1026): # returns a size of 1026 PromptData.Wallet = self.GetWallet1(recreate=True) args = ['send', 'gas', self.watch_addr_str, '5'] res = Wallet.CommandWallet().execute(args) self.assertFalse(res) self.assertIn( 'Transaction cancelled. The tx size (1026) exceeds the max free tx size (1024).\nA network fee of 0.001 GAS is required.', mock_print.getvalue() ) # notice the required fee is equal to the low priority threshold
def test_wallet_claim_1(self): # test with no wallet with patch('sys.stdout', new=StringIO()) as mock_print: args = ['claim'] res = CommandWallet().execute(args) self.assertFalse(res) self.assertIn("Please open a wallet", mock_print.getvalue()) self.OpenWallet1() # test wrong password with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=["wrong"]): args = ['claim'] claim_tx, relayed = CommandWallet().execute(args) self.assertEqual(claim_tx, None) self.assertFalse(relayed) self.assertIn("Incorrect password", mock_print.getvalue()) # test successful nodemgr = NodeManager() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=[WalletFixtureTestCase.wallet_1_pass()]): with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): args = ['claim'] claim_tx, relayed = CommandWallet().execute(args) self.assertIsInstance(claim_tx, ClaimTransaction) self.assertTrue(relayed) json_tx = claim_tx.ToJson() self.assertEqual(json_tx['vout'][0]['address'], self.wallet_1_addr) nodemgr.reset_for_test() # test nothing to claim anymore with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=[WalletFixtureTestCase.wallet_1_pass()]): args = ['claim'] claim_tx, relayed = CommandWallet().execute(args) self.assertEqual(claim_tx, None) self.assertFalse(relayed) self.assertIn("No claims to process", mock_print.getvalue())
def test_attributes(self): nodemgr = NodeManager() nodemgr.reset_for_test() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): PromptData.Wallet = self.GetWallet1(recreate=True) args = [ 'send', 'gas', self.watch_addr_str, '2', '--tx-attr={"usage":241,"data":"This is a remark"}' ] res = Wallet.CommandWallet().execute(args) self.assertTrue(res) self.assertEqual( 2, len(res.Attributes) ) # By default the script_hash of the transaction sender is added to the TransactionAttribute list, therefore the Attributes length is `count` + 1
def test_9_send_neo_tx(self): with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): wallet = self.GetWallet1() tx = ContractTransaction() tx.outputs = [TransactionOutput(Blockchain.SystemShare().Hash, Fixed8.FromDecimal(10.0), self.import_watch_addr)] try: tx = wallet.MakeTransaction(tx) except (ValueError): pass cpc = ContractParametersContext(tx) wallet.Sign(cpc) tx.scripts = cpc.GetScripts() nodemgr = NodeManager() # we need at least 1 node for relay to be mocked nodemgr.nodes = [NeoNode(object, object)] result = nodemgr.relay(tx) self.assertEqual(result, True)
def test_6_split_unspent(self): wallet = self.GetWallet1(recreate=True) addr = wallet.ToScriptHash('AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3') nodemgr = NodeManager() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): # bad inputs tx = SplitUnspentCoin(None, self.NEO, addr, 0, 2) self.assertEqual(tx, None) tx = SplitUnspentCoin(wallet, self.NEO, addr, 3, 2) self.assertEqual(tx, None) tx = SplitUnspentCoin(wallet, 'bla', addr, 0, 2) self.assertEqual(tx, None) # should be ok with patch('neo.Prompt.Commands.WalletAddress.prompt', return_value=self.wallet_1_pass()): tx = SplitUnspentCoin(wallet, self.NEO, addr, 0, 2) self.assertIsNotNone(tx) # rebuild wallet and try with non-even amount of neo, should be split into integer values of NEO wallet = self.GetWallet1(True) tx = SplitUnspentCoin(wallet, self.NEO, addr, 0, 3) self.assertIsNotNone(tx) self.assertEqual([ Fixed8.FromDecimal(17), Fixed8.FromDecimal(17), Fixed8.FromDecimal(16) ], [item.Value for item in tx.outputs]) # try with gas wallet = self.GetWallet1(True) tx = SplitUnspentCoin(wallet, self.GAS, addr, 0, 3) self.assertIsNotNone(tx)
def test_show_nodes(self): nodemgr = NodeManager() nodemgr.reset_for_test() # test "nodes" with no nodes connected args = ['nodes'] with patch('sys.stdout', new=StringIO()) as mock_print: res = CommandShow().execute(args) self.assertFalse(res) self.assertIn('No nodes connected yet', mock_print.getvalue()) # test "nodes verbose" with no nodes connected args = ['nodes', 'verbose'] res = CommandShow().execute(args) self.assertIn('Addresses in queue: 0', res) self.assertIn('Known addresses: 0', res) self.assertIn('Bad addresses: 0', res) # test "nodes queued" with no nodes connected args = ['nodes', 'queued'] res = CommandShow().execute(args) self.assertIn('No queued addresses', res) # test "nodes known" with no nodes connected args = ['nodes', 'known'] res = CommandShow().execute(args) self.assertIn('No known addresses other than connect peers', res) # test "nodes bad" with no nodes connected args = ['nodes', 'bad'] res = CommandShow().execute(args) self.assertIn('No bad addresses', res) # query nodes with connected peers # first make sure we have a predictable state node1 = NeoNode(object, object) node2 = NeoNode(object, object) node1.address = "127.0.0.1:20333" node2.address = "127.0.0.1:20334" node1.best_height = 1025 node2.best_height = 1026 node1.version = MagicMock() node2.version = MagicMock() node1.version.user_agent = "test_user_agent" node2.version.user_agent = "test_user_agent" nodemgr.nodes = [node1, node2] queued_address = "127.0.0.1:20335" known_address = "127.0.0.1:20336" bad_address = "127.0.0.1:20337" nodemgr.queued_addresses.append(queued_address) nodemgr.known_addresses.append(known_address) nodemgr.bad_addresses.append(bad_address) # now use "node" args = ['node'] res = CommandShow().execute(args) self.assertIn("Connected: 2", res) self.assertIn("Peer 1", res) self.assertIn("1025", res) # test "nodes verbose" with queued, known, and bad addresses args = ['nodes', 'verbose'] res = CommandShow().execute(args) self.assertIn("Addresses in queue: 1", res) self.assertIn("Known addresses: 1", res) self.assertIn("Bad addresses: 1", res) # test "nodes queued" with queued, known, and bad addresses args = ['nodes', 'queued'] res = CommandShow().execute(args) self.assertIn("Queued addresses:", res) self.assertIn(queued_address, res) # test "nodes known" with queued, known, and bad addresses args = ['nodes', 'known'] res = CommandShow().execute(args) self.assertIn("Known addresses:", res) self.assertIn(known_address, res) # test "nodes bad" with queued, known, and bad addresses args = ['nodes', 'bad'] res = CommandShow().execute(args) self.assertIn("Bad addresses:", res) self.assertIn(bad_address, res) nodemgr.reset_for_test()
def test_sc_invoke(self): token_hash_str = '31730cc9a1844891a3bafd1aa929a4142860d8d3' # test no open wallet with patch('sys.stdout', new=StringIO()) as mock_print: args = ['invoke', token_hash_str, 'symbol', '[]'] res = CommandSC().execute(args) self.assertFalse(res) self.assertIn("Please open a wallet", mock_print.getvalue()) PromptData.Wallet = self.GetWallet3(recreate=True) # test invalid contract script hash with patch('sys.stdout', new=StringIO()) as mock_print: args = ['invoke', 'invalid_hash', 'invalid_params'] res = CommandSC().execute(args) self.assertFalse(res) self.assertIn("Invalid script hash", mock_print.getvalue()) # test invalid parameter count (missing required `contract`) with patch('sys.stdout', new=StringIO()) as mock_print: args = ['invoke', '--from-addr=bla'] res = CommandSC().execute(args) self.assertFalse(res) self.assertIn("Please specify the required parameters", mock_print.getvalue()) # test with an script_hash that cannot be found with patch('sys.stdout', new=StringIO()) as mock_print: bad_contract = 'a' * 40 # passes basic script_hash length check, but won't find actual contract args = ['invoke', bad_contract, 'name', '[]'] res = CommandSC().execute(args) self.assertFalse(res) self.assertIn("Error testing contract invoke", mock_print.getvalue()) # test with keyboard interrupt with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.SC.prompt', side_effect=[KeyboardInterrupt]): args = ['invoke', token_hash_str, 'symbol', '[]'] res = CommandSC().execute(args) self.assertFalse(res) self.assertIn("Invocation cancelled", mock_print.getvalue()) # test with negative fee with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.SC.prompt', side_effect=[self.wallet_3_pass()]): args = ['invoke', token_hash_str, 'symbol', '[]', '--fee=-0.001'] res = CommandSC().execute(args) self.assertFalse(res) self.assertIn("invalid amount format", mock_print.getvalue()) # test with weird fee with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.SC.prompt', side_effect=[self.wallet_3_pass()]): args = ['invoke', token_hash_str, 'symbol', '[]', '--fee=0.0abc'] res = CommandSC().execute(args) self.assertFalse(res) self.assertIn("invalid amount format", mock_print.getvalue()) # test ok, but bad passw to send to network with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.SC.prompt', side_effect=["blah"]): args = ['invoke', token_hash_str, 'symbol', '[]'] res = CommandSC().execute(args) self.assertFalse(res) self.assertIn("Incorrect password", mock_print.getvalue()) # test with no return-type override with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.SC.prompt', side_effect=[KeyboardInterrupt]): args = ['invoke', token_hash_str, 'totalSupply', '[]', ''] res = CommandSC().execute(args) a = mock_print.getvalue() self.assertIn("ByteArray", mock_print.getvalue()) # test with bad return-type override with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.SC.prompt', side_effect=[KeyboardInterrupt]): args = ['invoke', token_hash_str, 'totalSupply', '[]', '--return-type=99'] res = CommandSC().execute(args) self.assertFalse(res) # test with hex return-type override with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.SC.prompt', side_effect=[KeyboardInterrupt]): args = ['invoke', token_hash_str, 'totalSupply', '[]', '--return-type=02'] res = CommandSC().execute(args) self.assertIn("Integer", mock_print.getvalue()) # test with named return-type override with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.SC.prompt', side_effect=[KeyboardInterrupt]): args = ['invoke', token_hash_str, 'totalSupply', '[]', '--return-type=Integer'] res = CommandSC().execute(args) self.assertIn("Integer", mock_print.getvalue()) # test ok nodemgr = NodeManager() nodemgr.reset_for_test() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.SC.prompt', side_effect=[self.wallet_3_pass()]): args = ['invoke', token_hash_str, 'symbol', '[]', '--fee=0.001'] res = CommandSC().execute(args) # not the best check, but will do for now self.assertTrue(res) self.assertIn("Priority Fee (0.001) + Invoke TX Fee (0.0001) = 0.0011", mock_print.getvalue())
def test_config_maxpeers(self): nodemgr = NodeManager() nodemgr.reset_for_test() # test no input and verify output confirming current maxpeers with patch('sys.stdout', new=StringIO()) as mock_print: args = ['maxpeers'] res = CommandConfig().execute(args) self.assertFalse(res) self.assertEqual(settings.CONNECTED_PEER_MAX, 10) self.assertIn( f"Maintaining maxpeers at {settings.CONNECTED_PEER_MAX}", mock_print.getvalue()) # test changing the number of maxpeers with patch('sys.stdout', new=StringIO()) as mock_print: args = ['maxpeers', "6"] res = CommandConfig().execute(args) self.assertTrue(res) self.assertEqual(settings.CONNECTED_PEER_MAX, 6) self.assertEqual(int(res), settings.CONNECTED_PEER_MAX) self.assertIn(f"Maxpeers set to {settings.CONNECTED_PEER_MAX}", mock_print.getvalue()) # test trying to set maxpeers > 10 with patch('sys.stdout', new=StringIO()) as mock_print: args = ['maxpeers', "12"] res = CommandConfig().execute(args) self.assertFalse(res) self.assertIn("Max peers is limited to 10", mock_print.getvalue()) # test bad input with patch('sys.stdout', new=StringIO()) as mock_print: args = ['maxpeers', "blah"] res = CommandConfig().execute(args) self.assertFalse(res) self.assertIn("Invalid argument", mock_print.getvalue()) # test negative number with patch('sys.stdout', new=StringIO()) as mock_print: args = ['maxpeers', "-1"] res = CommandConfig().execute(args) self.assertFalse(res) self.assertIn("Please supply a positive integer for maxpeers", mock_print.getvalue()) # test if the new maxpeers < settings.CONNECTED_PEER_MAX # first make sure we have a predictable state node1 = NeoNode(object, object) node2 = NeoNode(object, object) node1.address = "127.0.0.1:20333" node2.address = "127.0.0.1:20334" nodemgr.nodes = [node1, node2] nodemgr.loop = object with patch("neo.Network.node.NeoNode.disconnect") as mock_disconnect: # first test if the number of connected peers !< new maxpeers self.assertEqual(nodemgr.max_clients, 6) # verifying the current number of maxpeers with patch('sys.stdout', new=StringIO()) as mock_print: args = ['maxpeers', "4"] res = CommandConfig().execute(args) self.assertTrue(res) self.assertEqual(nodemgr.max_clients, 4) self.assertFalse(mock_disconnect.called) self.assertEqual(settings.CONNECTED_PEER_MAX, 4) self.assertIn(f"Maxpeers set to {settings.CONNECTED_PEER_MAX}", mock_print.getvalue()) # now test if the number of connected peers < new maxpeers and < current minpeers self.assertEqual(settings.CONNECTED_PEER_MIN, 4) # verifying the current minpeers value with patch('sys.stdout', new=StringIO()) as mock_print: with patch('neo.Prompt.Commands.Config.wait_for'): args = ['maxpeers', "1"] res = CommandConfig().execute(args) self.assertTrue(res) self.assertEqual(nodemgr.max_clients, 1) self.assertTrue(mock_disconnect.called) self.assertEqual(settings.CONNECTED_PEER_MAX, 1) self.assertIn( f"Maxpeers set to {settings.CONNECTED_PEER_MAX}", mock_print.getvalue()) self.assertEqual(settings.CONNECTED_PEER_MIN, 1) self.assertIn( f"Minpeers set to {settings.CONNECTED_PEER_MIN}", mock_print.getvalue()) # reset for future tests nodemgr.reset_for_test() nodemgr.loop = None settings.set_max_peers(10)
class NeoProtocol(StreamReaderProtocol): def __init__(self, *args, quality_check=False, **kwargs): """ Args: *args: quality_check (bool): there are times when we only establish a connection to check the quality of the node/address **kwargs: """ self._stream_reader = StreamReader() self._stream_writer = None nodemanager = kwargs.pop('nodemanager') self.client = NeoNode(self, nodemanager, quality_check) self._loop = events.get_event_loop() super().__init__(self._stream_reader) def connection_made(self, transport: asyncio.transports.BaseTransport) -> None: super().connection_made(transport) self._stream_writer = StreamWriter(transport, self, self._stream_reader, self._loop) if self.client: asyncio.create_task(self.client.connection_made(transport)) def connection_lost(self, exc: Optional[Exception] = None) -> None: if self.client: task = asyncio.create_task(self.client.connection_lost(exc)) task.add_done_callback( lambda args: super(NeoProtocol, self).connection_lost(exc)) else: super().connection_lost(exc) def eof_received(self) -> bool: self._stream_reader.feed_eof() self.connection_lost() return True # False == Do not keep connection open, this makes sure that `connection_lost` gets called. # return False async def send_message(self, message: Message) -> None: try: self._stream_writer.write(message.to_array()) await self._stream_writer.drain() except ConnectionResetError: # print("connection reset") self.connection_lost(ConnectionResetError) except ConnectionError: # print("connection error") self.connection_lost(ConnectionError) except asyncio.CancelledError: # print("task cancelled, closing connection") self.connection_lost(asyncio.CancelledError) except Exception as e: # print(f"***** woah what happened here?! {traceback.format_exc()}") self.connection_lost() async def read_message(self, timeout: int = 30) -> Message: if timeout == 0: # avoid memleak. See: https://bugs.python.org/issue37042 timeout = None async def _read(): try: message_header = await self._stream_reader.readexactly(24) magic, command, payload_length, checksum = struct.unpack( 'I 12s I I', message_header) # uint32, 12byte-string, uint32, uint32 payload_data = await self._stream_reader.readexactly( payload_length) payload, = struct.unpack('{}s'.format(payload_length), payload_data) except Exception: # ensures we break out of the main run() loop of Node, which triggers a disconnect callback to clean up self.client.disconnecting = True return None m = Message(magic, command.rstrip(b'\x00').decode('utf-8'), payload) if checksum != m.get_checksum(payload): logger.debug("Message checksum incorrect") return None else: return m try: return await asyncio.wait_for(_read(), timeout) except Exception: return None def disconnect(self) -> None: if self._stream_writer: self._stream_writer.close()
def test_wallet_split(self): # test wallet split with no wallet open with patch('sys.stdout', new=StringIO()) as mock_print: args = ['address', 'split'] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("open a wallet", mock_print.getvalue()) self.OpenWallet1() # test wallet split with not enough arguments with patch('sys.stdout', new=StringIO()) as mock_print: args = ['address', 'split', self.wallet_1_addr] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("specify the required parameters", mock_print.getvalue()) # test wallet split with too much arguments with patch('sys.stdout', new=StringIO()) as mock_print: args = [ 'address', 'split', self.wallet_1_addr, 'neo', '0', '2', 'too', 'much' ] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Too many parameters supplied", mock_print.getvalue()) # test wallet split with invalid address with patch('sys.stdout', new=StringIO()) as mock_print: args = ['address', 'split', '123', 'neo', '0', '2'] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Invalid address specified", mock_print.getvalue()) # test wallet split with unknown asset with patch('sys.stdout', new=StringIO()) as mock_print: args = [ 'address', 'split', self.wallet_1_addr, 'unknownasset', '0', '2' ] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Unknown asset id", mock_print.getvalue()) # test wallet split with invalid index with patch('sys.stdout', new=StringIO()) as mock_print: args = ['address', 'split', self.wallet_1_addr, 'neo', 'abc', '2'] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Invalid unspent index value", mock_print.getvalue()) # test wallet split with invalid divisions with patch('sys.stdout', new=StringIO()) as mock_print: args = ['address', 'split', self.wallet_1_addr, 'neo', '0', 'abc'] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Invalid divisions value", mock_print.getvalue()) # test wallet split with invalid divisions (negative) with patch('sys.stdout', new=StringIO()) as mock_print: args = ['address', 'split', self.wallet_1_addr, 'neo', '0', '-3'] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Divisions cannot be lower than 2", mock_print.getvalue()) # test wallet split with invalid fee with patch('sys.stdout', new=StringIO()) as mock_print: args = [ 'address', 'split', self.wallet_1_addr, 'neo', '0', '2', 'abc' ] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Invalid fee value", mock_print.getvalue()) # test wallet split with negative fee with patch('sys.stdout', new=StringIO()) as mock_print: args = [ 'address', 'split', self.wallet_1_addr, 'neo', '0', '2', '-0.01' ] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Invalid fee value", mock_print.getvalue()) # test wallet split with wrong password with patch('neo.Prompt.Commands.WalletAddress.prompt', side_effect=["wrong_password"]): with patch('sys.stdout', new=StringIO()) as mock_print: args = [ 'address', 'split', self.wallet_1_addr, 'neo', '0', '2' ] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("incorrect password", mock_print.getvalue()) # test wallet split with keyboard interrupt with patch('neo.Prompt.Commands.WalletAddress.prompt', side_effect=[KeyboardInterrupt]): with patch('sys.stdout', new=StringIO()) as mock_print: args = [ 'address', 'split', self.wallet_1_addr, 'neo', '0', '2' ] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Splitting cancelled", mock_print.getvalue()) # test wallet split with fee bigger than the outputs with patch('neo.Prompt.Commands.WalletAddress.prompt', side_effect=[self.wallet_1_pass()]): with patch('sys.stdout', new=StringIO()) as mock_print: args = [ 'address', 'split', self.wallet_1_addr, 'neo', '0', '2', '100' ] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Fee could not be subtracted from outputs", mock_print.getvalue()) # # test wallet split with error during tx relay nodemgr = NodeManager() nodemgr.reset_for_test() nodemgr.nodes = [NeoNode(object, object)] with patch('neo.Prompt.Commands.WalletAddress.prompt', side_effect=[self.wallet_1_pass()]): with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(False)): with patch('sys.stdout', new=StringIO()) as mock_print: args = [ 'address', 'split', self.wallet_1_addr, 'neo', '0', '2' ] res = CommandWallet().execute(args) self.assertIsNone(res) self.assertIn("Could not relay tx", mock_print.getvalue()) # we have to clear the mempool because the previous test alread put a TX with the same hash in the mempool and so it will not try to relay again nodemgr.mempool.reset() # test wallet split neo successful with patch('neo.Prompt.Commands.WalletAddress.prompt', side_effect=[self.wallet_1_pass()]): with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): args = [ 'address', 'split', self.wallet_1_addr, 'neo', '0', '2' ] tx = CommandWallet().execute(args) self.assertIsInstance(tx, ContractTransaction) self.assertEqual( [Fixed8.FromDecimal(25), Fixed8.FromDecimal(25)], [item.Value for item in tx.outputs]) # test wallet split gas successful with patch('neo.Prompt.Commands.WalletAddress.prompt', side_effect=[self.wallet_1_pass()]): with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)): args = [ 'address', 'split', self.wallet_1_addr, 'gas', '0', '3' ] tx = CommandWallet().execute(args) self.assertIsInstance(tx, ContractTransaction) self.assertEqual(len(tx.outputs), 3) nodemgr.reset_for_test()