203 lines
9.5 KiB
Python
203 lines
9.5 KiB
Python
import logging
|
|
|
|
import typing
|
|
import random
|
|
import asyncio
|
|
from aiohttp import web
|
|
|
|
from lbrynet.testcase import CommandTestCase
|
|
|
|
import lbrynet.schema
|
|
lbrynet.schema.BLOCKCHAIN_NAME = 'lbrycrd_regtest'
|
|
|
|
|
|
class FakedCommentServer:
|
|
ERRORS = {
|
|
'INVALID_URI': {'code': 1, 'message': 'Invalid claim URI'},
|
|
'INVALID_PARAMS': {'code': -32602, 'message': 'Invalid parameters'},
|
|
'INTERNAL': {'code': -32603, 'message': 'An internal error'},
|
|
'UNKNOWN': {'code': -1, 'message': 'An unknown or very miscellaneous error'},
|
|
}
|
|
|
|
def __init__(self, port=2903):
|
|
self.port = port
|
|
self.app = web.Application(debug=True)
|
|
self.app.add_routes([web.post('/api', self.api)])
|
|
self.runner = None
|
|
self.server = None
|
|
|
|
def get_claim_comments(self, uri: str, better_keys: bool) -> typing.Union[dict, list, None]:
|
|
if not uri.startswith('lbry://'): # Very basic error case
|
|
return {'error': self.ERRORS['INVALID_URI']}
|
|
return [self.get_comment(i) for i in range(75)]
|
|
|
|
def get_comment(self, comment_id: int, parent_id: int = None) -> dict:
|
|
return {
|
|
'comment_id': comment_id,
|
|
'parent_id': parent_id,
|
|
'author': f'Person{comment_id}',
|
|
'message': f'comment {comment_id}',
|
|
'claim_id': random.randint(1, 2**16),
|
|
'time_posted': random.randint(2**16, 2**32 - 1),
|
|
'upvotes': random.randint(0, 9999), 'downvotes': random.randint(0, 9999)
|
|
}
|
|
|
|
def comment(self, uri: str, poster: str, message: str) -> typing.Union[int, dict, None]:
|
|
if not uri.startswith('lbry://'):
|
|
return {'error': self.ERRORS['INVALID_URI']}
|
|
return random.randint(1, 9999)
|
|
|
|
def reply(self, parent_id: int, poster: str, message: str) -> dict:
|
|
if 2 <= len(message) <= 2000 and 2 <= len(poster) <= 127 and parent_id > 0:
|
|
return random.randint(parent_id + 1, 2**32 - 1)
|
|
return {'error': self.ERRORS['INVALID_PARAMS']}
|
|
|
|
def get_comment_data(self, comm_index: int, better_keys: bool = False) -> typing.Union[dict, None]:
|
|
return self.get_comment(comm_index)
|
|
|
|
def get_comment_replies(self, comm_index: int) -> typing.Union[list, None]:
|
|
return [random.randint(comm_index, comm_index+250) for _ in range(75)]
|
|
|
|
methods = {
|
|
'get_claim_comments': get_claim_comments,
|
|
'get_comment_data': get_comment_data,
|
|
'get_comment_replies': get_comment_replies,
|
|
'comment': comment,
|
|
'reply': reply
|
|
}
|
|
|
|
def process_json(self, body) -> dict:
|
|
response = {'jsonrpc': '2.0', 'id': body['id']}
|
|
if body['method'] in self.methods:
|
|
params = body.get('params', {})
|
|
result = self.methods[body['method']](self, **params)
|
|
if type(result) is dict and 'error' in result:
|
|
response['error'] = result['error']
|
|
else:
|
|
response['result'] = result
|
|
else:
|
|
response['error'] = self.ERRORS['UNKNOWN']
|
|
return response
|
|
|
|
async def _start(self):
|
|
self.runner = web.AppRunner(self.app)
|
|
await self.runner.setup()
|
|
self.server = web.TCPSite(self.runner, 'localhost', self.port)
|
|
await self.server.start()
|
|
|
|
async def _stop(self):
|
|
await self.runner.cleanup()
|
|
|
|
async def run(self, max_timeout=3600):
|
|
try:
|
|
await self._start()
|
|
await asyncio.sleep(max_timeout)
|
|
except asyncio.CancelledError:
|
|
pass
|
|
finally:
|
|
await self._stop()
|
|
|
|
async def api(self, request):
|
|
body = await request.json()
|
|
if type(body) is list or type(body) is dict:
|
|
if type(body) is list:
|
|
response = [self.process_json(part) for part in body]
|
|
else:
|
|
response = self.process_json(body)
|
|
return web.json_response(response)
|
|
else:
|
|
return web.json_response({'error': self.ERRORS['UNKNOWN']})
|
|
|
|
|
|
class CommentCommands(CommandTestCase):
|
|
|
|
VERBOSITY = logging.WARN
|
|
|
|
async def asyncSetUp(self):
|
|
await super().asyncSetUp()
|
|
self.daemon.conf.comment_server = 'http://localhost:2903/api'
|
|
self.server = FakedCommentServer(2903)
|
|
self.server_task = asyncio.create_task(self.server.run(self.timeout))
|
|
|
|
async def asyncTearDown(self):
|
|
await super().asyncTearDown()
|
|
self.server_task.cancel()
|
|
if not self.server_task.cancelled():
|
|
await self.server_task
|
|
|
|
async def test_comment_create(self):
|
|
claim = await self.stream_create(name='doge', bid='0.001', data=b'loool')
|
|
self.assertIn('outputs', claim)
|
|
comment = await self.daemon.jsonrpc_comment_create(
|
|
claim_id=claim['outputs'][0]['claim_id'],
|
|
channel_id='Jimmy Buffett',
|
|
message="It's 5 O'Clock Somewhere"
|
|
)
|
|
self.assertIs(type(comment), dict, msg=f"Response type ({type(comment)})is not dict: {comment}")
|
|
self.assertIn('message', comment, msg=f"Response {comment} doesn't contain message")
|
|
self.assertIn('author', comment)
|
|
|
|
async def test_comment_create_reply(self):
|
|
claim = await self.stream_create(name='doge', bid='0.001')
|
|
self.assertIn('outputs', claim)
|
|
reply = await self.daemon.jsonrpc_comment_create(
|
|
claim_id=claim['outputs'][0]['claim_id'],
|
|
channel_id='Jimmy Buffett',
|
|
message='Let\'s all go to Margaritaville',
|
|
parent_comment_id=42
|
|
)
|
|
self.assertIs(type(reply), dict, msg=f'Response {type(reply)} is not dict\nResponse: {reply}')
|
|
self.assertIn('author', reply)
|
|
|
|
async def test_comment_list_root_level(self):
|
|
claim = await self.stream_create(name='doge', bid='0.001')
|
|
self.assertIn('outputs', claim)
|
|
claim_id = claim['outputs'][0]['claim_id']
|
|
comments = await self.daemon.jsonrpc_comment_list(claim_id)
|
|
self.assertIsNotNone(type(comments))
|
|
self.assertIs(type(comments), dict)
|
|
self.assertIn('comments', comments, f"'comments' field was not found in returned dict: {comments}")
|
|
self.assertIs(type(comments['comments']), list, msg=f'comment_list: {comments}')
|
|
comments = await self.daemon.jsonrpc_comment_list(claim_id, page_size=50)
|
|
self.assertIsNotNone(comments)
|
|
self.assertIs(type(comments), dict)
|
|
self.assertIn('comments', comments, f"'comments' field was not found in returned dict: {comments}")
|
|
comment_list = comments['comments']
|
|
self.assertEqual(len(comment_list), 50, msg=f'comment_list incorrect size {len(comment_list)}: {comment_list}')
|
|
comments = await self.daemon.jsonrpc_comment_list(claim_id, page_size=50, page=2)
|
|
self.assertEqual(len(comments['comments']), 25, msg=f'comment list page 2: {comments["comments"]}')
|
|
comments = await self.daemon.jsonrpc_comment_list(claim_id, page_size=50, page=3)
|
|
self.assertEqual(len(comments['comments']), 0, msg=f'comment list is non-zero: {comments["comments"]}')
|
|
|
|
async def test_comment_list_replies(self):
|
|
claim = await self.stream_create(name='doge', bid='0.001')
|
|
self.assertIn('outputs', claim)
|
|
claim_id = claim['outputs'][0]['claim_id']
|
|
replies = await self.daemon.jsonrpc_comment_list(claim_id, parent_comment_id=23)
|
|
self.assertIsInstance(replies['comments'], list, msg=f'Invalid type: {replies["comments"]} should be list')
|
|
self.assertGreater(len(replies['comments']), 0, msg='Returned replies are empty')
|
|
replies = (await self.daemon.jsonrpc_comment_list(claim_id, parent_comment_id=25, page_size=50))['comments']
|
|
self.assertEqual(len(replies), 50, f'Replies invalid length ({len(replies)})')
|
|
replies = (await self.daemon.jsonrpc_comment_list(claim_id, parent_comment_id=67,
|
|
page_size=23, page=5))['comments']
|
|
self.assertEqual(len(replies), 0, f'replies {replies} not 23: {len(replies)}')
|
|
replies = (await self.daemon.jsonrpc_comment_list(claim_id, parent_comment_id=79,
|
|
page_size=60, page=2))['comments']
|
|
self.assertEqual(len(replies), 15, f'Size of replies is incorrect, should be 15: {replies}')
|
|
|
|
async def test_comment_list_flatness_flatness_LA(self):
|
|
claim = await self.stream_create(name='doge', bid='0.001')
|
|
self.assertIn('outputs', claim)
|
|
claim_id = claim['outputs'][0]['claim_id']
|
|
replies = await self.daemon.jsonrpc_comment_list(claim_id, parent_comment_id=23, flat=True)
|
|
self.assertIsInstance(replies['comments'], list, msg=f'Invalid type: {replies["comments"]} should be list')
|
|
self.assertGreater(len(replies['comments']), 0, msg='Returned replies are empty')
|
|
replies = (await self.daemon.jsonrpc_comment_list(claim_id, parent_comment_id=25, flat=True,
|
|
max_replies_shown=0, page_size=50))['comments']
|
|
self.assertEqual(len(replies), 50, f'Replies invalid length ({len(replies)})')
|
|
replies = (await self.daemon.jsonrpc_comment_list(claim_id, parent_comment_id=67,
|
|
flat=True, page_size=23, page=5))['comments']
|
|
self.assertEqual(len(replies), 0, f'replies {replies} not 23: {len(replies)}')
|
|
replies = (await self.daemon.jsonrpc_comment_list(claim_id, parent_comment_id=79,
|
|
page_size=60, page=2))['comments']
|
|
self.assertGreaterEqual(len(replies), 15, f'Size of replies is incorrect, should be 15: {replies}')
|