aboutsummaryrefslogtreecommitdiff
path: root/qa
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2016-04-19 14:57:45 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2016-04-19 14:58:23 +0200
commit0e6fd5e4af31ada6da8df006801b59e9178ecd85 (patch)
tree4e1e6ff06cb3678e4376f6ba65704eb245beaabb /qa
parent187186b0fe039010ea4b81edb671b9bdfc63d29a (diff)
parent5d217decc1145823a3c126658c82c60cf7dbfec8 (diff)
downloadbitcoin-0e6fd5e4af31ada6da8df006801b59e9178ecd85.tar.xz
Merge #7822: Add listunspent() test for spendable/unspendable UTXO
5d217de Add test to check spendable and unspendable UTXO on RPC listunspent (Joao Fonseca) fa942c7 Move method to check matches within arrays on util.py (Joao Fonseca)
Diffstat (limited to 'qa')
-rwxr-xr-xqa/rpc-tests/getblocktemplate_longpoll.py22
-rwxr-xr-xqa/rpc-tests/getblocktemplate_proposals.py22
-rwxr-xr-xqa/rpc-tests/keypool.py22
-rwxr-xr-xqa/rpc-tests/listtransactions.py71
-rwxr-xr-xqa/rpc-tests/receivedby.py40
-rw-r--r--qa/rpc-tests/test_framework/util.py29
-rwxr-xr-xqa/rpc-tests/wallet.py37
7 files changed, 98 insertions, 145 deletions
diff --git a/qa/rpc-tests/getblocktemplate_longpoll.py b/qa/rpc-tests/getblocktemplate_longpoll.py
index 3e85957ae2..e2a839f718 100755
--- a/qa/rpc-tests/getblocktemplate_longpoll.py
+++ b/qa/rpc-tests/getblocktemplate_longpoll.py
@@ -6,28 +6,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-
-def check_array_result(object_array, to_match, expected):
- """
- Pass in array of JSON objects, a dictionary with key/value pairs
- to match against, and another dictionary with expected key/value
- pairs.
- """
- num_matched = 0
- for item in object_array:
- all_match = True
- for key,value in to_match.items():
- if item[key] != value:
- all_match = False
- if not all_match:
- continue
- for key,value in expected.items():
- if item[key] != value:
- raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
- num_matched = num_matched+1
- if num_matched == 0:
- raise AssertionError("No objects matched %s"%(str(to_match)))
-
import threading
class LongpollThread(threading.Thread):
diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py
index 07bfe69c6d..be119031ba 100755
--- a/qa/rpc-tests/getblocktemplate_proposals.py
+++ b/qa/rpc-tests/getblocktemplate_proposals.py
@@ -10,28 +10,6 @@ from binascii import a2b_hex, b2a_hex
from hashlib import sha256
from struct import pack
-
-def check_array_result(object_array, to_match, expected):
- """
- Pass in array of JSON objects, a dictionary with key/value pairs
- to match against, and another dictionary with expected key/value
- pairs.
- """
- num_matched = 0
- for item in object_array:
- all_match = True
- for key,value in to_match.items():
- if item[key] != value:
- all_match = False
- if not all_match:
- continue
- for key,value in expected.items():
- if item[key] != value:
- raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
- num_matched = num_matched+1
- if num_matched == 0:
- raise AssertionError("No objects matched %s"%(str(to_match)))
-
def b2x(b):
return b2a_hex(b).decode('ascii')
diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py
index 5253d49c30..b86c085e00 100755
--- a/qa/rpc-tests/keypool.py
+++ b/qa/rpc-tests/keypool.py
@@ -10,28 +10,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-
-def check_array_result(object_array, to_match, expected):
- """
- Pass in array of JSON objects, a dictionary with key/value pairs
- to match against, and another dictionary with expected key/value
- pairs.
- """
- num_matched = 0
- for item in object_array:
- all_match = True
- for key,value in to_match.items():
- if item[key] != value:
- all_match = False
- if not all_match:
- continue
- for key,value in expected.items():
- if item[key] != value:
- raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
- num_matched = num_matched+1
- if num_matched == 0:
- raise AssertionError("No objects matched %s"%(str(to_match)))
-
class KeyPoolTest(BitcoinTestFramework):
def run_test(self):
diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py
index 0783a1f3d3..4e5809f4a7 100755
--- a/qa/rpc-tests/listtransactions.py
+++ b/qa/rpc-tests/listtransactions.py
@@ -16,27 +16,6 @@ def txFromHex(hexstring):
tx.deserialize(f)
return tx
-def check_array_result(object_array, to_match, expected):
- """
- Pass in array of JSON objects, a dictionary with key/value pairs
- to match against, and another dictionary with expected key/value
- pairs.
- """
- num_matched = 0
- for item in object_array:
- all_match = True
- for key,value in to_match.items():
- if item[key] != value:
- all_match = False
- if not all_match:
- continue
- for key,value in expected.items():
- if item[key] != value:
- raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
- num_matched = num_matched+1
- if num_matched == 0:
- raise AssertionError("No objects matched %s"%(str(to_match)))
-
class ListTransactionsTest(BitcoinTestFramework):
def setup_nodes(self):
@@ -48,28 +27,28 @@ class ListTransactionsTest(BitcoinTestFramework):
# Simple send, 0 to 1:
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
self.sync_all()
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"txid":txid},
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0})
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"txid":txid},
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0})
# mine a block, confirmations should change:
self.nodes[0].generate(1)
self.sync_all()
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"txid":txid},
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1})
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"txid":txid},
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1})
# send-to-self:
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"txid":txid, "category":"send"},
{"amount":Decimal("-0.2")})
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"txid":txid, "category":"receive"},
{"amount":Decimal("0.2")})
@@ -80,28 +59,28 @@ class ListTransactionsTest(BitcoinTestFramework):
self.nodes[1].getaccountaddress("toself") : 0.44 }
txid = self.nodes[1].sendmany("", send_to)
self.sync_all()
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.11")},
{"txid":txid} )
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"category":"receive","amount":Decimal("0.11")},
{"txid":txid} )
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.22")},
{"txid":txid} )
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"receive","amount":Decimal("0.22")},
{"txid":txid} )
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.33")},
{"txid":txid} )
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"category":"receive","amount":Decimal("0.33")},
{"txid":txid, "account" : "from1"} )
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.44")},
{"txid":txid, "account" : ""} )
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"receive","amount":Decimal("0.44")},
{"txid":txid, "account" : "toself"} )
@@ -111,7 +90,7 @@ class ListTransactionsTest(BitcoinTestFramework):
self.nodes[1].generate(1)
self.sync_all()
assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0)
- check_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True),
+ assert_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True),
{"category":"receive","amount":Decimal("0.1")},
{"txid":txid, "account" : "watchonly"} )
@@ -139,9 +118,9 @@ class ListTransactionsTest(BitcoinTestFramework):
# 1. Chain a few transactions that don't opt-in.
txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
assert(not is_opt_in(self.nodes[0], txid_1))
- check_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
sync_mempools(self.nodes)
- check_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
# Tx2 will build off txid_1, still not opting in to RBF.
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
@@ -155,9 +134,9 @@ class ListTransactionsTest(BitcoinTestFramework):
# ...and check the result
assert(not is_opt_in(self.nodes[1], txid_2))
- check_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
sync_mempools(self.nodes)
- check_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
# Tx3 will opt-in to RBF
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
@@ -171,9 +150,9 @@ class ListTransactionsTest(BitcoinTestFramework):
txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)
assert(is_opt_in(self.nodes[0], txid_3))
- check_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
sync_mempools(self.nodes)
- check_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
# Tx4 will chain off tx3. Doesn't signal itself, but depends on one
# that does.
@@ -185,9 +164,9 @@ class ListTransactionsTest(BitcoinTestFramework):
txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)
assert(not is_opt_in(self.nodes[1], txid_4))
- check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
sync_mempools(self.nodes)
- check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
# Replace tx3, and check that tx4 becomes unknown
tx3_b = tx3_modified
@@ -197,9 +176,9 @@ class ListTransactionsTest(BitcoinTestFramework):
txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
assert(is_opt_in(self.nodes[0], txid_3b))
- check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
sync_mempools(self.nodes)
- check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
# Check gettransaction as well:
for n in self.nodes[0:2]:
diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py
index 606426b394..7d8231f5e4 100755
--- a/qa/rpc-tests/receivedby.py
+++ b/qa/rpc-tests/receivedby.py
@@ -25,32 +25,6 @@ def get_sub_array_from_array(object_array, to_match):
return item
return []
-def check_array_result(object_array, to_match, expected, should_not_find = False):
- """
- Pass in array of JSON objects, a dictionary with key/value pairs
- to match against, and another dictionary with expected key/value
- pairs.
- If the should_not_find flag is true, to_match should not be found in object_array
- """
- if should_not_find == True:
- expected = { }
- num_matched = 0
- for item in object_array:
- all_match = True
- for key,value in to_match.items():
- if item[key] != value:
- all_match = False
- if not all_match:
- continue
- for key,value in expected.items():
- if item[key] != value:
- raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
- num_matched = num_matched+1
- if num_matched == 0 and should_not_find != True:
- raise AssertionError("No objects matched %s"%(str(to_match)))
- if num_matched > 0 and should_not_find == True:
- raise AssertionError("Objects was matched %s"%(str(to_match)))
-
class ReceivedByTest(BitcoinTestFramework):
def setup_nodes(self):
@@ -68,26 +42,26 @@ class ReceivedByTest(BitcoinTestFramework):
self.sync_all()
#Check not listed in listreceivedbyaddress because has 0 confirmations
- check_array_result(self.nodes[1].listreceivedbyaddress(),
+ assert_array_result(self.nodes[1].listreceivedbyaddress(),
{"address":addr},
{ },
True)
#Bury Tx under 10 block so it will be returned by listreceivedbyaddress
self.nodes[1].generate(10)
self.sync_all()
- check_array_result(self.nodes[1].listreceivedbyaddress(),
+ assert_array_result(self.nodes[1].listreceivedbyaddress(),
{"address":addr},
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
#With min confidence < 10
- check_array_result(self.nodes[1].listreceivedbyaddress(5),
+ assert_array_result(self.nodes[1].listreceivedbyaddress(5),
{"address":addr},
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
#With min confidence > 10, should not find Tx
- check_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
+ assert_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
#Empty Tx
addr = self.nodes[1].getnewaddress()
- check_array_result(self.nodes[1].listreceivedbyaddress(0,True),
+ assert_array_result(self.nodes[1].listreceivedbyaddress(0,True),
{"address":addr},
{"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]})
@@ -131,7 +105,7 @@ class ReceivedByTest(BitcoinTestFramework):
self.sync_all()
# listreceivedbyaccount should return received_by_account_json because of 0 confirmations
- check_array_result(self.nodes[1].listreceivedbyaccount(),
+ assert_array_result(self.nodes[1].listreceivedbyaccount(),
{"account":account},
received_by_account_json)
@@ -143,7 +117,7 @@ class ReceivedByTest(BitcoinTestFramework):
self.nodes[1].generate(10)
self.sync_all()
# listreceivedbyaccount should return updated account balance
- check_array_result(self.nodes[1].listreceivedbyaccount(),
+ assert_array_result(self.nodes[1].listreceivedbyaccount(),
{"account":account},
{"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))})
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index 8b720b54a1..27891f7f4c 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -478,6 +478,35 @@ def assert_is_hash_string(string, length=64):
raise AssertionError(
"String %r contains invalid characters for a hash." % string)
+def assert_array_result(object_array, to_match, expected, should_not_find = False):
+ """
+ Pass in array of JSON objects, a dictionary with key/value pairs
+ to match against, and another dictionary with expected key/value
+ pairs.
+ If the should_not_find flag is true, to_match should not be found
+ in object_array
+ """
+ if should_not_find == True:
+ expected = { }
+ num_matched = 0
+ for item in object_array:
+ all_match = True
+ for key,value in to_match.items():
+ if item[key] != value:
+ all_match = False
+ if not all_match:
+ continue
+ elif should_not_find == True:
+ num_matched = num_matched+1
+ for key,value in expected.items():
+ if item[key] != value:
+ raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
+ num_matched = num_matched+1
+ if num_matched == 0 and should_not_find != True:
+ raise AssertionError("No objects matched %s"%(str(to_match)))
+ if num_matched > 0 and should_not_find == True:
+ raise AssertionError("Objects were found %s"%(str(to_match)))
+
def satoshi_round(amount):
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index 8fdcea50b6..555f836482 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -32,6 +32,12 @@ class WalletTest (BitcoinTestFramework):
self.sync_all()
def run_test (self):
+
+ # Check that there's no UTXO on none of the nodes
+ assert_equal(len(self.nodes[0].listunspent()), 0)
+ assert_equal(len(self.nodes[1].listunspent()), 0)
+ assert_equal(len(self.nodes[2].listunspent()), 0)
+
print "Mining blocks..."
self.nodes[0].generate(1)
@@ -48,6 +54,11 @@ class WalletTest (BitcoinTestFramework):
assert_equal(self.nodes[1].getbalance(), 50)
assert_equal(self.nodes[2].getbalance(), 0)
+ # Check that only first and second nodes have UTXOs
+ assert_equal(len(self.nodes[0].listunspent()), 1)
+ assert_equal(len(self.nodes[1].listunspent()), 1)
+ assert_equal(len(self.nodes[2].listunspent()), 0)
+
# Send 21 BTC from 0 to 2 using sendtoaddress call.
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
@@ -259,6 +270,32 @@ class WalletTest (BitcoinTestFramework):
except JSONRPCException as e:
assert("not an integer" in e.error['message'])
+ # Import address and private key to check correct behavior of spendable unspents
+ # 1. Send some coins to generate new UTXO
+ address_to_import = self.nodes[2].getnewaddress()
+ txid = self.nodes[0].sendtoaddress(address_to_import, 1)
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ # 2. Import address from node2 to node1
+ self.nodes[1].importaddress(address_to_import)
+
+ # 3. Validate that the imported address is watch-only on node1
+ assert(self.nodes[1].validateaddress(address_to_import)["iswatchonly"])
+
+ # 4. Check that the unspents after import are not spendable
+ assert_array_result(self.nodes[1].listunspent(),
+ {"address": address_to_import},
+ {"spendable": False})
+
+ # 5. Import private key of the previously imported address on node1
+ priv_key = self.nodes[2].dumpprivkey(address_to_import)
+ self.nodes[1].importprivkey(priv_key)
+
+ # 6. Check that the unspents are now spendable on node1
+ assert_array_result(self.nodes[1].listunspent(),
+ {"address": address_to_import},
+ {"spendable": True})
# Mine a block from node0 to an address from node1
cbAddr = self.nodes[1].getnewaddress()