Addresses #663 partially

This commit is contained in:
Sylvain Bellemare 2017-01-17 11:32:30 +01:00 committed by Sylvain Bellemare
parent c1b6f60f70
commit 9766aa90a1
4 changed files with 49 additions and 21 deletions

View File

@ -1,18 +1,19 @@
""" """
Common classes and methods for API handlers Common classes and methods for API handlers
""" """
import logging
from flask import jsonify, request from flask import jsonify, request
logger = logging.getLogger(__name__)
def make_error(status_code, message=None): def make_error(status_code, message=None):
if status_code == 404 and message is None: if status_code == 404 and message is None:
message = 'Not found' message = 'Not found'
response_content = {'status': status_code, 'message': message}
response = jsonify({ logger.error('HTTP API error: %(status)s - %(message)s', response_content)
'status': status_code, response = jsonify(response_content)
'message': message
})
response.status_code = status_code response.status_code = status_code
return response return response

View File

@ -4,6 +4,8 @@ For more information please refer to the documentation on ReadTheDocs:
- https://docs.bigchaindb.com/projects/server/en/latest/drivers-clients/ - https://docs.bigchaindb.com/projects/server/en/latest/drivers-clients/
http-client-server-api.html http-client-server-api.html
""" """
import logging
from flask import current_app, request from flask import current_app, request
from flask_restful import Resource from flask_restful import Resource
@ -24,6 +26,8 @@ import bigchaindb
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.web.views.base import make_error from bigchaindb.web.views.base import make_error
logger = logging.getLogger(__name__)
class TransactionApi(Resource): class TransactionApi(Resource):
def get(self, tx_id): def get(self, tx_id):

View File

@ -47,6 +47,7 @@ tests_require = [
'flake8', 'flake8',
'pylint', 'pylint',
'pytest>=3.0.0', 'pytest>=3.0.0',
'pytest-catchlog>=1.2.2',
'pytest-cov>=2.2.1', 'pytest-cov>=2.2.1',
'pytest-xdist', 'pytest-xdist',
'pytest-flask', 'pytest-flask',

View File

@ -41,7 +41,7 @@ def test_post_create_transaction_endpoint(b, client):
assert res.json['outputs'][0]['public_keys'][0] == user_pub assert res.json['outputs'][0]['public_keys'][0] == user_pub
def test_post_create_transaction_with_invalid_id(b, client): def test_post_create_transaction_with_invalid_id(b, client, caplog):
from bigchaindb.common.exceptions import InvalidHash from bigchaindb.common.exceptions import InvalidHash
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user_priv, user_pub = crypto.generate_key_pair() user_priv, user_pub = crypto.generate_key_pair()
@ -51,14 +51,18 @@ def test_post_create_transaction_with_invalid_id(b, client):
tx['id'] = 'abcd' * 16 tx['id'] = 'abcd' * 16
res = client.post(TX_ENDPOINT, data=json.dumps(tx)) res = client.post(TX_ENDPOINT, data=json.dumps(tx))
assert res.status_code == 400 expected_status_code = 400
err_msg = ("The transaction's id '{}' isn't equal to " expected_error_message = (
"the hash of its body, i.e. it's not valid.").format(tx['id']) "Invalid transaction ({}): The transaction's id '{}' isn't equal to "
assert res.json['message'] == ( "the hash of its body, i.e. it's not valid."
'Invalid transaction ({}): {}'.format(InvalidHash.__name__, err_msg)) ).format(InvalidHash.__name__, tx['id'])
assert res.status_code == expected_status_code
assert res.json['message'] == expected_error_message
assert caplog.records[0].args['status'] == expected_status_code
assert caplog.records[0].args['message'] == expected_error_message
def test_post_create_transaction_with_invalid_signature(b, client): def test_post_create_transaction_with_invalid_signature(b, client, caplog):
from bigchaindb.common.exceptions import InvalidSignature from bigchaindb.common.exceptions import InvalidSignature
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user_priv, user_pub = crypto.generate_key_pair() user_priv, user_pub = crypto.generate_key_pair()
@ -68,10 +72,15 @@ def test_post_create_transaction_with_invalid_signature(b, client):
tx['inputs'][0]['fulfillment'] = 'cf:0:0' tx['inputs'][0]['fulfillment'] = 'cf:0:0'
res = client.post(TX_ENDPOINT, data=json.dumps(tx)) res = client.post(TX_ENDPOINT, data=json.dumps(tx))
assert res.status_code == 400 expected_status_code = 400
assert res.json['message'] == ( expected_error_message = (
"Invalid transaction ({}): Fulfillment URI " "Invalid transaction ({}): Fulfillment URI "
"couldn't been parsed".format(InvalidSignature.__name__)) "couldn't been parsed"
).format(InvalidSignature.__name__)
assert res.status_code == expected_status_code
assert res.json['message'] == expected_error_message
assert caplog.records[0].args['status'] == expected_status_code
assert caplog.records[0].args['message'] == expected_error_message
def test_post_create_transaction_with_invalid_structure(client): def test_post_create_transaction_with_invalid_structure(client):
@ -79,16 +88,20 @@ def test_post_create_transaction_with_invalid_structure(client):
assert res.status_code == 400 assert res.status_code == 400
def test_post_create_transaction_with_invalid_schema(client): def test_post_create_transaction_with_invalid_schema(client, caplog):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
user_priv, user_pub = crypto.generate_key_pair() user_priv, user_pub = crypto.generate_key_pair()
tx = Transaction.create( tx = Transaction.create(
[user_pub], [([user_pub], 1)]).sign([user_priv]).to_dict() [user_pub], [([user_pub], 1)]).sign([user_priv]).to_dict()
del tx['version'] del tx['version']
res = client.post(TX_ENDPOINT, data=json.dumps(tx)) res = client.post(TX_ENDPOINT, data=json.dumps(tx))
assert res.status_code == 400 expected_status_code = 400
assert res.json['message'] == ( expected_error_message = (
"Invalid transaction schema: 'version' is a required property") "Invalid transaction schema: 'version' is a required property")
assert res.status_code == expected_status_code
assert res.json['message'] == expected_error_message
assert caplog.records[0].args['status'] == expected_status_code
assert caplog.records[0].args['message'] == expected_error_message
@pytest.mark.parametrize('exc,msg', ( @pytest.mark.parametrize('exc,msg', (
@ -102,7 +115,7 @@ def test_post_create_transaction_with_invalid_schema(client):
('TransactionNotInValidBlock', 'Wait, maybe?'), ('TransactionNotInValidBlock', 'Wait, maybe?'),
('ValueError', '?'), ('ValueError', '?'),
)) ))
def test_post_invalid_transaction(client, exc, msg, monkeypatch): def test_post_invalid_transaction(client, exc, msg, monkeypatch, caplog):
from bigchaindb.common import exceptions from bigchaindb.common import exceptions
try: try:
exc_cls = getattr(exceptions, exc) exc_cls = getattr(exceptions, exc)
@ -117,9 +130,13 @@ def test_post_invalid_transaction(client, exc, msg, monkeypatch):
monkeypatch.setattr( monkeypatch.setattr(
'bigchaindb.models.Transaction.from_dict', lambda tx: None) 'bigchaindb.models.Transaction.from_dict', lambda tx: None)
res = client.post(TX_ENDPOINT, data=json.dumps({})) res = client.post(TX_ENDPOINT, data=json.dumps({}))
assert res.status_code == 400 expected_status_code = 400
expected_error_message = 'Invalid transaction ({}): {}'.format(exc, msg)
assert res.status_code == expected_status_code
assert (res.json['message'] == assert (res.json['message'] ==
'Invalid transaction ({}): {}'.format(exc, msg)) 'Invalid transaction ({}): {}'.format(exc, msg))
assert caplog.records[2].args['status'] == expected_status_code
assert caplog.records[2].args['message'] == expected_error_message
@pytest.mark.bdb @pytest.mark.bdb
@ -147,6 +164,7 @@ def test_post_transfer_transaction_endpoint(b, client, user_pk, user_sk):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_sk): def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_sk):
from bigchaindb.models import Transaction from bigchaindb.models import Transaction
from bigchaindb.common.exceptions import InvalidSignature
user_priv, user_pub = crypto.generate_key_pair() user_priv, user_pub = crypto.generate_key_pair()
@ -157,4 +175,8 @@ def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_
asset_id=create_tx.id) asset_id=create_tx.id)
res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict())) res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))
assert res.status_code == 400 expected_status_code = 400
expected_error_message = 'Invalid transaction ({}): {}'.format(
InvalidSignature.__name__, 'Transaction signature is invalid.')
assert res.status_code == expected_status_code
assert res.json['message'] == expected_error_message