From 1b57ace71409797226e031aeacf3b382000d3f80 Mon Sep 17 00:00:00 2001 From: diminator Date: Tue, 10 Jan 2017 14:41:02 +0100 Subject: [PATCH 1/7] implement GET /blocks endpoint --- bigchaindb/web/routes.py | 3 + bigchaindb/web/views/blocks.py | 62 ++++++++++++++++++++ tests/web/test_blocks.py | 104 +++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 bigchaindb/web/views/blocks.py create mode 100644 tests/web/test_blocks.py diff --git a/bigchaindb/web/routes.py b/bigchaindb/web/routes.py index f6ee1886..c159f3a9 100644 --- a/bigchaindb/web/routes.py +++ b/bigchaindb/web/routes.py @@ -1,6 +1,7 @@ """ API routes definition """ from flask_restful import Api from bigchaindb.web.views import ( + blocks, info, statuses, transactions as tx, @@ -23,6 +24,8 @@ def r(*args, **kwargs): ROUTES_API_V1 = [ r('/', info.ApiV1Index), + r('blocks/', blocks.BlockApi), + r('blocks/', blocks.BlockListApi), r('statuses/', statuses.StatusApi), r('transactions/', tx.TransactionApi), r('transactions', tx.TransactionListApi), diff --git a/bigchaindb/web/views/blocks.py b/bigchaindb/web/views/blocks.py new file mode 100644 index 00000000..bb415a3e --- /dev/null +++ b/bigchaindb/web/views/blocks.py @@ -0,0 +1,62 @@ +"""This module provides the blueprint for the blocks API endpoints. + +For more information please refer to the documentation on ReadTheDocs: + - https://docs.bigchaindb.com/projects/server/en/latest/drivers-clients/ + http-client-server-api.html +""" +from flask import current_app +from flask_restful import Resource, reqparse + +from bigchaindb.web.views.base import make_error + + +class BlockApi(Resource): + def get(self, block_id): + """API endpoint to get details about a block. + + Args: + block_id (str): the id of the block. + + Return: + A JSON string containing the data about the block. + """ + + pool = current_app.config['bigchain_pool'] + + with pool() as bigchain: + block = bigchain.get_block(block_id=block_id) + + if not block: + return make_error(404) + + return block + + +class BlockListApi(Resource): + def get(self): + """API endpoint to get the related blocks and statuses of a transaction. + + Return: + A ``dict`` in the format ``{'block_id': }``, where + ```` is one of "valid", "invalid", "undecided", "backlog". + It's possible to return multiple keys of 'block_id'. + """ + parser = reqparse.RequestParser() + parser.add_argument('tx_id', type=str) + + args = parser.parse_args(strict=True) + + if sum(arg is not None for arg in args.values()) != 1: + return make_error(400, "Provide exactly one query parameter. Choices are: block_id, tx_id") + + pool = current_app.config['bigchain_pool'] + blocks = None + + with pool() as bigchain: + if args['tx_id']: + blocks = bigchain.get_blocks_status_containing_tx(args['tx_id']) + + if not blocks: + return make_error(404) + + return blocks diff --git a/tests/web/test_blocks.py b/tests/web/test_blocks.py new file mode 100644 index 00000000..5587442c --- /dev/null +++ b/tests/web/test_blocks.py @@ -0,0 +1,104 @@ +import pytest + +from bigchaindb.models import Transaction + +BLOCKS_ENDPOINT = '/api/v1/blocks/' + + +@pytest.mark.bdb +@pytest.mark.usefixtures('inputs') +def test_get_block_endpoint(b, client): + tx = Transaction.create([b.me], [([b.me], 1)]) + tx = tx.sign([b.me_private]) + + block = b.create_block([tx]) + b.write_block(block) + + res = client.get(BLOCKS_ENDPOINT + block.id) + assert block.to_dict() == res.json + assert res.status_code == 200 + + +@pytest.mark.bdb +@pytest.mark.usefixtures('inputs') +def test_get_block_returns_404_if_not_found(client): + res = client.get(BLOCKS_ENDPOINT + '123') + assert res.status_code == 404 + + res = client.get(BLOCKS_ENDPOINT + '123/') + assert res.status_code == 404 + + +@pytest.mark.bdb +@pytest.mark.usefixtures('inputs') +def test_get_blocks_by_txid_endpoint(b, client): + tx = Transaction.create([b.me], [([b.me], 1)]) + tx = tx.sign([b.me_private]) + + tx2 = Transaction.create([b.me], [([b.me], 10)]) + tx2 = tx2.sign([b.me_private]) + + block_invalid = b.create_block([tx]) + b.write_block(block_invalid) + + res = client.get(BLOCKS_ENDPOINT + "?tx_id=" + tx.id) + # test if block is retrieved as undecided + assert res.status_code == 200 + assert block_invalid.id in res.json + assert res.json[block_invalid.id] == b.block_election_status(block_invalid.id, block_invalid.voters) + assert res.json[block_invalid.id] == 'undecided' + assert len(res.json) == 1 + + # vote the block invalid + vote = b.vote(block_invalid.id, b.get_last_voted_block().id, False) + b.write_vote(vote) + + res = client.get(BLOCKS_ENDPOINT + "?tx_id=" + tx.id) + # test if block is retrieved as invalid + assert res.status_code == 200 + assert block_invalid.id in res.json + assert res.json[block_invalid.id] == b.block_election_status(block_invalid.id, block_invalid.voters) + assert res.json[block_invalid.id] == 'invalid' + assert len(res.json) == 1 + + # create a new block containing the same tx (and tx2 to avoid block id collision) + block_valid = b.create_block([tx, tx2]) + b.write_block(block_valid) + + res = client.get(BLOCKS_ENDPOINT + "?tx_id=" + tx.id) + # test if block is retrieved as undecided + assert res.status_code == 200 + assert block_valid.id in res.json + assert res.json[block_valid.id] == b.block_election_status(block_valid.id, block_valid.voters) + assert res.json[block_valid.id] == 'undecided' + assert len(res.json) == 2 + + # vote the block valid + vote = b.vote(block_valid.id, block_invalid.id, True) + b.write_vote(vote) + + res = client.get(BLOCKS_ENDPOINT + "?tx_id=" + tx.id) + # test if block is retrieved as valid + assert res.status_code == 200 + assert block_valid.id in res.json + assert res.json[block_valid.id] == b.block_election_status(block_valid.id, block_valid.voters) + assert res.json[block_valid.id] == 'valid' + assert len(res.json) == 2 + + +@pytest.mark.bdb +def test_get_blocks_by_txid_endpoint_returns_404_if_not_found(client): + res = client.get(BLOCKS_ENDPOINT + "?tx_id=123") + assert res.status_code == 404 + + +@pytest.mark.bdb +def test_get_blocks_by_txid_endpoint_returns_400_bad_query_params(client): + res = client.get(BLOCKS_ENDPOINT) + assert res.status_code == 400 + + res = client.get(BLOCKS_ENDPOINT + "?ts_id=123") + assert res.status_code == 400 + + res = client.get(BLOCKS_ENDPOINT + "?tx_id=123&block_id=123") + assert res.status_code == 400 From 1cc46fb86ea2431ceb3170c053f74ca03589a50e Mon Sep 17 00:00:00 2001 From: diminator Date: Wed, 11 Jan 2017 18:44:21 +0100 Subject: [PATCH 2/7] return list of block_id implement status query param test --- bigchaindb/web/views/blocks.py | 23 +++++------ tests/web/test_blocks.py | 70 +++++++++++++++++++++++++++++----- 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/bigchaindb/web/views/blocks.py b/bigchaindb/web/views/blocks.py index bb415a3e..fc6a7566 100644 --- a/bigchaindb/web/views/blocks.py +++ b/bigchaindb/web/views/blocks.py @@ -34,27 +34,28 @@ class BlockApi(Resource): class BlockListApi(Resource): def get(self): - """API endpoint to get the related blocks and statuses of a transaction. + """API endpoint to get the related blocks for a transaction. Return: - A ``dict`` in the format ``{'block_id': }``, where - ```` is one of "valid", "invalid", "undecided", "backlog". - It's possible to return multiple keys of 'block_id'. + A ``list`` of ``block_id`` that may be filtered when provided + a status query parameter: "valid", "invalid", "undecided". """ parser = reqparse.RequestParser() - parser.add_argument('tx_id', type=str) + parser.add_argument('tx_id', type=str, required=True) + parser.add_argument('status', type=str, choices=['valid', 'invalid', 'undecided']) args = parser.parse_args(strict=True) - - if sum(arg is not None for arg in args.values()) != 1: - return make_error(400, "Provide exactly one query parameter. Choices are: block_id, tx_id") + tx_id = args['tx_id'] + status = args['status'] pool = current_app.config['bigchain_pool'] - blocks = None with pool() as bigchain: - if args['tx_id']: - blocks = bigchain.get_blocks_status_containing_tx(args['tx_id']) + blocks = bigchain.get_blocks_status_containing_tx(tx_id) + if blocks: + if status: + blocks = {k: v for k, v in blocks.items() if v == status} + blocks = list(blocks.keys()) if not blocks: return make_error(404) diff --git a/tests/web/test_blocks.py b/tests/web/test_blocks.py index 5587442c..cab50cce 100644 --- a/tests/web/test_blocks.py +++ b/tests/web/test_blocks.py @@ -45,8 +45,6 @@ def test_get_blocks_by_txid_endpoint(b, client): # test if block is retrieved as undecided assert res.status_code == 200 assert block_invalid.id in res.json - assert res.json[block_invalid.id] == b.block_election_status(block_invalid.id, block_invalid.voters) - assert res.json[block_invalid.id] == 'undecided' assert len(res.json) == 1 # vote the block invalid @@ -57,8 +55,6 @@ def test_get_blocks_by_txid_endpoint(b, client): # test if block is retrieved as invalid assert res.status_code == 200 assert block_invalid.id in res.json - assert res.json[block_invalid.id] == b.block_election_status(block_invalid.id, block_invalid.voters) - assert res.json[block_invalid.id] == 'invalid' assert len(res.json) == 1 # create a new block containing the same tx (and tx2 to avoid block id collision) @@ -69,8 +65,6 @@ def test_get_blocks_by_txid_endpoint(b, client): # test if block is retrieved as undecided assert res.status_code == 200 assert block_valid.id in res.json - assert res.json[block_valid.id] == b.block_election_status(block_valid.id, block_valid.voters) - assert res.json[block_valid.id] == 'undecided' assert len(res.json) == 2 # vote the block valid @@ -81,11 +75,52 @@ def test_get_blocks_by_txid_endpoint(b, client): # test if block is retrieved as valid assert res.status_code == 200 assert block_valid.id in res.json - assert res.json[block_valid.id] == b.block_election_status(block_valid.id, block_valid.voters) - assert res.json[block_valid.id] == 'valid' assert len(res.json) == 2 +@pytest.mark.bdb +@pytest.mark.usefixtures('inputs') +def test_get_blocks_by_txid_and_status_endpoint(b, client): + tx = Transaction.create([b.me], [([b.me], 1)]) + tx = tx.sign([b.me_private]) + + tx2 = Transaction.create([b.me], [([b.me], 10)]) + tx2 = tx2.sign([b.me_private]) + + block_invalid = b.create_block([tx]) + b.write_block(block_invalid) + + # vote the block invalid + vote = b.vote(block_invalid.id, b.get_last_voted_block().id, False) + b.write_vote(vote) + + # create a new block containing the same tx (and tx2 to avoid block id collision) + block_valid = b.create_block([tx, tx2]) + b.write_block(block_valid) + + res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, 'invalid')) + # test if block is retrieved as invalid + assert res.status_code == 200 + assert block_invalid.id in res.json + assert len(res.json) == 1 + + res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, 'undecided')) + # test if block is retrieved as undecided + assert res.status_code == 200 + assert block_valid.id in res.json + assert len(res.json) == 1 + + # vote the block valid + vote = b.vote(block_valid.id, block_invalid.id, True) + b.write_vote(vote) + + res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, 'valid')) + # test if block is retrieved as valid + assert res.status_code == 200 + assert block_valid.id in res.json + assert len(res.json) == 1 + + @pytest.mark.bdb def test_get_blocks_by_txid_endpoint_returns_404_if_not_found(client): res = client.get(BLOCKS_ENDPOINT + "?tx_id=123") @@ -99,6 +134,23 @@ def test_get_blocks_by_txid_endpoint_returns_400_bad_query_params(client): res = client.get(BLOCKS_ENDPOINT + "?ts_id=123") assert res.status_code == 400 + assert res.json == { + 'message': { + 'tx_id': 'Missing required parameter in the JSON body or the post body or the query string' + } + } - res = client.get(BLOCKS_ENDPOINT + "?tx_id=123&block_id=123") + res = client.get(BLOCKS_ENDPOINT + "?tx_id=123&foo=123") assert res.status_code == 400 + assert res.json == { + 'message': 'Unknown arguments: foo' + } + + res = client.get(BLOCKS_ENDPOINT + "?tx_id=123&status=123") + assert res.status_code == 400 + assert res.json == { + 'message': { + 'status': '123 is not a valid choice' + } + } + From f018a4f6e7f4e1736c3f9588e30b1183be3f236b Mon Sep 17 00:00:00 2001 From: diminator Date: Thu, 12 Jan 2017 10:06:48 +0100 Subject: [PATCH 3/7] replace status strings by Bigchain attributes --- bigchaindb/web/views/blocks.py | 4 +++- tests/web/test_blocks.py | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/bigchaindb/web/views/blocks.py b/bigchaindb/web/views/blocks.py index fc6a7566..6f63b5d7 100644 --- a/bigchaindb/web/views/blocks.py +++ b/bigchaindb/web/views/blocks.py @@ -7,6 +7,7 @@ For more information please refer to the documentation on ReadTheDocs: from flask import current_app from flask_restful import Resource, reqparse +from bigchaindb import Bigchain from bigchaindb.web.views.base import make_error @@ -42,7 +43,8 @@ class BlockListApi(Resource): """ parser = reqparse.RequestParser() parser.add_argument('tx_id', type=str, required=True) - parser.add_argument('status', type=str, choices=['valid', 'invalid', 'undecided']) + parser.add_argument('status', type=str, + choices=[Bigchain.BLOCK_VALID, Bigchain.BLOCK_INVALID, Bigchain.BLOCK_UNDECIDED]) args = parser.parse_args(strict=True) tx_id = args['tx_id'] diff --git a/tests/web/test_blocks.py b/tests/web/test_blocks.py index cab50cce..81bc80c3 100644 --- a/tests/web/test_blocks.py +++ b/tests/web/test_blocks.py @@ -81,6 +81,8 @@ def test_get_blocks_by_txid_endpoint(b, client): @pytest.mark.bdb @pytest.mark.usefixtures('inputs') def test_get_blocks_by_txid_and_status_endpoint(b, client): + from bigchaindb import Bigchain + tx = Transaction.create([b.me], [([b.me], 1)]) tx = tx.sign([b.me_private]) @@ -98,13 +100,13 @@ def test_get_blocks_by_txid_and_status_endpoint(b, client): block_valid = b.create_block([tx, tx2]) b.write_block(block_valid) - res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, 'invalid')) + res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_INVALID)) # test if block is retrieved as invalid assert res.status_code == 200 assert block_invalid.id in res.json assert len(res.json) == 1 - res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, 'undecided')) + res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_UNDECIDED)) # test if block is retrieved as undecided assert res.status_code == 200 assert block_valid.id in res.json @@ -114,7 +116,7 @@ def test_get_blocks_by_txid_and_status_endpoint(b, client): vote = b.vote(block_valid.id, block_invalid.id, True) b.write_vote(vote) - res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, 'valid')) + res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_VALID)) # test if block is retrieved as valid assert res.status_code == 200 assert block_valid.id in res.json @@ -153,4 +155,3 @@ def test_get_blocks_by_txid_endpoint_returns_400_bad_query_params(client): 'status': '123 is not a valid choice' } } - From 3919cc3d5d3c960f012ec2bf0878a8615e03d35f Mon Sep 17 00:00:00 2001 From: diminator Date: Thu, 12 Jan 2017 16:36:13 +0100 Subject: [PATCH 4/7] return empty list if no blocks found --- bigchaindb/web/views/blocks.py | 5 ++--- docker-compose.yml | 2 +- tests/web/test_blocks.py | 11 +++++------ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/bigchaindb/web/views/blocks.py b/bigchaindb/web/views/blocks.py index 6f63b5d7..4f185d12 100644 --- a/bigchaindb/web/views/blocks.py +++ b/bigchaindb/web/views/blocks.py @@ -58,8 +58,7 @@ class BlockListApi(Resource): if status: blocks = {k: v for k, v in blocks.items() if v == status} blocks = list(blocks.keys()) - - if not blocks: - return make_error(404) + else: + blocks = [] return blocks diff --git a/docker-compose.yml b/docker-compose.yml index 072b8725..ebb7aabe 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -40,7 +40,7 @@ services: BIGCHAINDB_DATABASE_HOST: rdb BIGCHAINDB_SERVER_BIND: 0.0.0.0:9984 ports: - - "9984" + - "9984:9984" command: bigchaindb start bdb-mdb: diff --git a/tests/web/test_blocks.py b/tests/web/test_blocks.py index 81bc80c3..c61bf27b 100644 --- a/tests/web/test_blocks.py +++ b/tests/web/test_blocks.py @@ -38,6 +38,11 @@ def test_get_blocks_by_txid_endpoint(b, client): tx2 = Transaction.create([b.me], [([b.me], 10)]) tx2 = tx2.sign([b.me_private]) + res = client.get(BLOCKS_ENDPOINT + "?tx_id=" + tx.id) + # test if block is retrieved as undecided + assert res.status_code == 200 + assert len(res.json) == 0 + block_invalid = b.create_block([tx]) b.write_block(block_invalid) @@ -123,12 +128,6 @@ def test_get_blocks_by_txid_and_status_endpoint(b, client): assert len(res.json) == 1 -@pytest.mark.bdb -def test_get_blocks_by_txid_endpoint_returns_404_if_not_found(client): - res = client.get(BLOCKS_ENDPOINT + "?tx_id=123") - assert res.status_code == 404 - - @pytest.mark.bdb def test_get_blocks_by_txid_endpoint_returns_400_bad_query_params(client): res = client.get(BLOCKS_ENDPOINT) From 8b286819f546c48441a435224673db0af2344b14 Mon Sep 17 00:00:00 2001 From: diminator Date: Thu, 12 Jan 2017 16:39:22 +0100 Subject: [PATCH 5/7] revert docker compose --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index ebb7aabe..072b8725 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -40,7 +40,7 @@ services: BIGCHAINDB_DATABASE_HOST: rdb BIGCHAINDB_SERVER_BIND: 0.0.0.0:9984 ports: - - "9984:9984" + - "9984" command: bigchaindb start bdb-mdb: From 08d9e462c78932c126083248548ab681a7818ea9 Mon Sep 17 00:00:00 2001 From: Brett Sun Date: Fri, 13 Jan 2017 18:24:05 +0100 Subject: [PATCH 6/7] Use list comprehension to calculate block API result --- bigchaindb/web/views/blocks.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/bigchaindb/web/views/blocks.py b/bigchaindb/web/views/blocks.py index 4f185d12..9d509460 100644 --- a/bigchaindb/web/views/blocks.py +++ b/bigchaindb/web/views/blocks.py @@ -53,12 +53,8 @@ class BlockListApi(Resource): pool = current_app.config['bigchain_pool'] with pool() as bigchain: - blocks = bigchain.get_blocks_status_containing_tx(tx_id) - if blocks: - if status: - blocks = {k: v for k, v in blocks.items() if v == status} - blocks = list(blocks.keys()) - else: - blocks = [] + block_statuses = bigchain.get_blocks_status_containing_tx(tx_id) + blocks = [block_id for block_id, block_status in block_statuses.items() + if not status or block_status == status] return blocks From ded7f3e28f69c1af67b0a3fca46d1158da22f2c7 Mon Sep 17 00:00:00 2001 From: Brett Sun Date: Fri, 13 Jan 2017 18:24:31 +0100 Subject: [PATCH 7/7] PR comments --- bigchaindb/web/views/blocks.py | 5 +-- tests/web/test_blocks.py | 58 +++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/bigchaindb/web/views/blocks.py b/bigchaindb/web/views/blocks.py index 9d509460..7e840fe5 100644 --- a/bigchaindb/web/views/blocks.py +++ b/bigchaindb/web/views/blocks.py @@ -38,8 +38,9 @@ class BlockListApi(Resource): """API endpoint to get the related blocks for a transaction. Return: - A ``list`` of ``block_id`` that may be filtered when provided - a status query parameter: "valid", "invalid", "undecided". + A ``list`` of ``block_id``s that contain the given transaction. The + list may be filtered when provided a status query parameter: + "valid", "invalid", "undecided". """ parser = reqparse.RequestParser() parser.add_argument('tx_id', type=str, required=True) diff --git a/tests/web/test_blocks.py b/tests/web/test_blocks.py index c61bf27b..b0581061 100644 --- a/tests/web/test_blocks.py +++ b/tests/web/test_blocks.py @@ -38,11 +38,6 @@ def test_get_blocks_by_txid_endpoint(b, client): tx2 = Transaction.create([b.me], [([b.me], 10)]) tx2 = tx2.sign([b.me_private]) - res = client.get(BLOCKS_ENDPOINT + "?tx_id=" + tx.id) - # test if block is retrieved as undecided - assert res.status_code == 200 - assert len(res.json) == 0 - block_invalid = b.create_block([tx]) b.write_block(block_invalid) @@ -97,37 +92,64 @@ def test_get_blocks_by_txid_and_status_endpoint(b, client): block_invalid = b.create_block([tx]) b.write_block(block_invalid) - # vote the block invalid - vote = b.vote(block_invalid.id, b.get_last_voted_block().id, False) - b.write_vote(vote) - # create a new block containing the same tx (and tx2 to avoid block id collision) block_valid = b.create_block([tx, tx2]) b.write_block(block_valid) res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_INVALID)) - # test if block is retrieved as invalid + # test if no blocks are retrieved as invalid + assert res.status_code == 200 + assert len(res.json) == 0 + + res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_UNDECIDED)) + # test if both blocks are retrieved as undecided + assert res.status_code == 200 + assert block_valid.id in res.json + assert block_invalid.id in res.json + assert len(res.json) == 2 + + res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_VALID)) + # test if no blocks are retrieved as valid + assert res.status_code == 200 + assert len(res.json) == 0 + + # vote one of the blocks invalid + vote = b.vote(block_invalid.id, b.get_last_voted_block().id, False) + b.write_vote(vote) + + # vote the other block valid + vote = b.vote(block_valid.id, block_invalid.id, True) + b.write_vote(vote) + + res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_INVALID)) + # test if the invalid block is retrieved as invalid assert res.status_code == 200 assert block_invalid.id in res.json assert len(res.json) == 1 res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_UNDECIDED)) - # test if block is retrieved as undecided + # test if no blocks are retrieved as undecided assert res.status_code == 200 - assert block_valid.id in res.json - assert len(res.json) == 1 - - # vote the block valid - vote = b.vote(block_valid.id, block_invalid.id, True) - b.write_vote(vote) + assert len(res.json) == 0 res = client.get("{}?tx_id={}&status={}".format(BLOCKS_ENDPOINT, tx.id, Bigchain.BLOCK_VALID)) - # test if block is retrieved as valid + # test if the valid block is retrieved as valid assert res.status_code == 200 assert block_valid.id in res.json assert len(res.json) == 1 +@pytest.mark.bdb +def test_get_blocks_by_txid_endpoint_returns_empty_list_not_found(client): + res = client.get(BLOCKS_ENDPOINT + "?tx_id=") + assert res.status_code == 200 + assert len(res.json) == 0 + + res = client.get(BLOCKS_ENDPOINT + "?tx_id=123") + assert res.status_code == 200 + assert len(res.json) == 0 + + @pytest.mark.bdb def test_get_blocks_by_txid_endpoint_returns_400_bad_query_params(client): res = client.get(BLOCKS_ENDPOINT)