Skip to content
Permalink
Browse files

functional_tests: improve RPC blockchain tests

  • Loading branch information...
moneromooo-monero committed Mar 12, 2019
1 parent 1d1a02e commit b9d32503fe2b557d3a6936fc82322a5599b0e886
@@ -28,75 +28,129 @@
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Test blockchain RPC calls
import time

"""Test daemon blockchain RPC calls
Test the following RPCs:
- get_info
- generateblocks
- misc block retrieval
- pop_blocks
- [TODO: many tests still need to be written]
"""

from test_framework.daemon import Daemon
from test_framework.wallet import Wallet

class BlockchainTest():
def run_test(self):
self._test_get_info()
self._test_hardfork_info()
self._test_generateblocks(5)

def _test_get_info(self):
print('Test get_info')

daemon = Daemon()
res = daemon.get_info()

# difficulty should be set to 1 for this test
assert 'difficulty' in res.keys()
assert res['difficulty'] == 1;

# nettype should not be TESTNET
assert 'testnet' in res.keys()
assert res['testnet'] == False;

# nettype should not be STAGENET
assert 'stagenet' in res.keys()
assert res['stagenet'] == False;

# nettype should be FAKECHAIN
assert 'nettype' in res.keys()
assert res['nettype'] == "fakechain";

# free_space should be > 0
assert 'free_space' in res.keys()
assert res['free_space'] > 0

# height should be greater or equal to 1
assert 'height' in res.keys()
assert res['height'] >= 1


def _test_hardfork_info(self):
print('Test hard_fork_info')

daemon = Daemon()
res = daemon.hard_fork_info()

# hard_fork version should be set at height 1
assert 'earliest_height' in res.keys()
assert res['earliest_height'] == 1;


def _test_generateblocks(self, blocks):
print("Test generating", blocks, 'blocks')
assert blocks >= 2

print "Test generating", blocks, 'blocks'

daemon = Daemon()
res = daemon.get_info()
height = res['height']
res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', blocks)

assert res['height'] == height + blocks - 1
# check info/height before generating blocks
res_info = daemon.get_info()
height = res_info['height']
prev_block = res_info['top_block_hash']
res_height = daemon.get_height()
assert res_height['height'] == height
assert int(res_info['wide_cumulative_difficulty']) == (res_info['cumulative_difficulty_top64'] << 64) + res_info['cumulative_difficulty']
cumulative_difficulty = int(res_info['wide_cumulative_difficulty'])

# we should not see a block at height
ok = False
try: daemon.getblock(height)
except: ok = True
assert ok

# generate blocks
res_generateblocks = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', blocks)

# check info/height after generateblocks blocks
assert res_generateblocks['height'] == height + blocks - 1
res_info = daemon.get_info()
assert res_info['height'] == height + blocks
assert res_info['top_block_hash'] != prev_block
res_height = daemon.get_height()
assert res_height['height'] == height + blocks

# get the blocks, check they have the right height
res_getblock = []
for n in range(blocks):
res_getblock.append(daemon.getblock(height + n))
block_header = res_getblock[n]['block_header']
assert abs(block_header['timestamp'] - time.time()) < 10 # within 10 seconds
assert block_header['height'] == height + n
assert block_header['orphan_status'] == False
assert block_header['depth'] == blocks - n - 1
assert block_header['prev_hash'] == prev_block, prev_block
assert int(block_header['wide_difficulty']) == (block_header['difficulty_top64'] << 64) + block_header['difficulty']
assert int(block_header['wide_cumulative_difficulty']) == (block_header['cumulative_difficulty_top64'] << 64) + block_header['cumulative_difficulty']
assert block_header['reward'] >= 300000000000 # tail emission
cumulative_difficulty += int(block_header['wide_difficulty'])
assert cumulative_difficulty == int(block_header['wide_cumulative_difficulty'])
assert block_header['block_size'] > 0
assert block_header['block_weight'] >= block_header['block_size']
assert block_header['long_term_weight'] > 0
prev_block = block_header['hash']

# we should not see a block after that
ok = False
try: daemon.getblock(height + blocks)
except: ok = True
assert ok

# getlastblockheader and by height/hash should return the same block
res_getlastblockheader = daemon.getlastblockheader()
assert res_getlastblockheader['block_header'] == block_header
res_getblockheaderbyhash = daemon.getblockheaderbyhash(prev_block)
assert res_getblockheaderbyhash['block_header'] == block_header
res_getblockheaderbyheight = daemon.getblockheaderbyheight(height + blocks - 1)
assert res_getblockheaderbyheight['block_header'] == block_header

# getting a block template after that should have the right height, etc
res_getblocktemplate = daemon.getblocktemplate('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm')
assert res_getblocktemplate['height'] == height + blocks
assert res_getblocktemplate['reserved_offset'] > 0
assert res_getblocktemplate['prev_hash'] == res_info['top_block_hash']
assert res_getblocktemplate['expected_reward'] >= 300000000000
assert len(res_getblocktemplate['blocktemplate_blob']) > 0
assert len(res_getblocktemplate['blockhashing_blob']) > 0
assert int(res_getblocktemplate['wide_difficulty']) == (res_getblocktemplate['difficulty_top64'] << 64) + res_getblocktemplate['difficulty']

# diff etc should be the same
assert res_getblocktemplate['prev_hash'] == res_info['top_block_hash']

res_getlastblockheader = daemon.getlastblockheader()

# pop a block
res_popblocks = daemon.pop_blocks(1)
assert res_popblocks['height'] == height + blocks - 1

res_info = daemon.get_info()
assert res_info['height'] == height + blocks - 1

# getlastblockheader and by height/hash should return the previous block
block_header = res_getblock[blocks - 2]['block_header']
block_header['depth'] = 0 # this will be different, ignore it
res_getlastblockheader = daemon.getlastblockheader()
assert res_getlastblockheader['block_header'] == block_header
res_getblockheaderbyhash = daemon.getblockheaderbyhash(block_header['hash'])
assert res_getblockheaderbyhash['block_header'] == block_header
res_getblockheaderbyheight = daemon.getblockheaderbyheight(height + blocks - 2)
assert res_getblockheaderbyheight['block_header'] == block_header

# we should not see the popped block anymore
ok = False
try: daemon.getblock(height + blocks - 1)
except: ok = True
assert ok


if __name__ == '__main__':
@@ -0,0 +1,88 @@
#!/usr/bin/env python3

# Copyright (c) 2018 The Monero Project
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are
# permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be
# used to endorse or promote products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Test daemon RPC calls
Test the following RPCs:
- get_info
- hard_fork_info
"""

from test_framework.daemon import Daemon

class DaemonGetInfoTest():
def run_test(self):
self._test_hardfork_info()
self._test_get_info()

def _test_hardfork_info(self):
print('Test hard_fork_info')

daemon = Daemon()
res = daemon.hard_fork_info()

# hard_fork version should be set at height 1
assert 'earliest_height' in res.keys()
assert res['earliest_height'] == 1;

def _test_get_info(self):
print('Test get_info')

daemon = Daemon()
res = daemon.get_info()

# difficulty should be set to 1 for this test
assert 'difficulty' in res.keys()
assert res['difficulty'] == 1;

# nettype should not be TESTNET
assert 'testnet' in res.keys()
assert res['testnet'] == False;

# nettype should not be STAGENET
assert 'stagenet' in res.keys()
assert res['stagenet'] == False;

# nettype should be FAKECHAIN
assert 'nettype' in res.keys()
assert res['nettype'] == "fakechain";

# free_space should be > 0
assert 'free_space' in res.keys()
assert res['free_space'] > 0

# height should be greater or equal to 1
assert 'height' in res.keys()
assert res['height'] >= 1


if __name__ == '__main__':
DaemonGetInfoTest().run_test()
@@ -33,7 +33,8 @@
class Daemon(object):

def __init__(self, protocol='http', host='127.0.0.1', port=18081, path='/json_rpc'):
self.rpc = JSONRPC('{protocol}://{host}:{port}{path}'.format(protocol=protocol, host=host, port=port, path=path))
self.rpc = JSONRPC('{protocol}://{host}:{port}'.format(protocol=protocol, host=host, port=port))
self.path = path

def getblocktemplate(self, address):
getblocktemplate = {
@@ -45,7 +46,7 @@ def getblocktemplate(self, address):
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_request(getblocktemplate)
return self.rpc.send_json_rpc_request(getblocktemplate)

def submitblock(self, block):
submitblock = {
@@ -54,7 +55,7 @@ def submitblock(self, block):
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_request(submitblock)
return self.rpc.send_json_rpc_request(submitblock)

def getblock(self, height=0):
getblock = {
@@ -65,31 +66,63 @@ def getblock(self, height=0):
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_request(getblock)
return self.rpc.send_json_rpc_request(getblock)

def getlastblockheader(self):
getlastblockheader = {
'method': 'getlastblockheader',
'params': {
},
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_json_rpc_request(getlastblockheader)

def getblockheaderbyhash(self, hash):
getblockheaderbyhash = {
'method': 'getblockheaderbyhash',
'params': {
'hash': hash,
},
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_json_rpc_request(getblockheaderbyhash)

def getblockheaderbyheight(self, height):
getblockheaderbyheight = {
'method': 'getblockheaderbyheight',
'params': {
'height': height,
},
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_json_rpc_request(getblockheaderbyheight)

def get_connections(self):
get_connections = {
'method': 'get_connections',
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_request(get_connections)
return self.rpc.send_json_rpc_request(get_connections)

def get_info(self):
get_info = {
'method': 'get_info',
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_request(get_info)
return self.rpc.send_json_rpc_request(get_info)

def hard_fork_info(self):
hard_fork_info = {
'method': 'hard_fork_info',
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_request(hard_fork_info)
return self.rpc.send_json_rpc_request(hard_fork_info)

def generateblocks(self, address, blocks=1):
generateblocks = {
@@ -102,4 +135,18 @@ def generateblocks(self, address, blocks=1):
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_request(generateblocks)
return self.rpc.send_json_rpc_request(generateblocks)

def get_height(self):
get_height = {
'method': 'get_height',
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_request("/get_height", get_height)

def pop_blocks(self, nblocks = 1):
pop_blocks = {
'nblocks' : nblocks,
}
return self.rpc.send_request("/pop_blocks", pop_blocks)

0 comments on commit b9d3250

Please sign in to comment.
You can’t perform that action at this time.