2019-05-23 12:36:03 +02:00
|
|
|
import unittest
|
2019-07-24 08:11:30 +02:00
|
|
|
from multiprocessing.pool import Pool
|
|
|
|
|
2019-05-23 12:36:03 +02:00
|
|
|
import requests
|
|
|
|
import re
|
|
|
|
from itertools import *
|
2019-07-22 14:13:10 +02:00
|
|
|
|
|
|
|
import faker
|
2019-05-23 12:36:03 +02:00
|
|
|
from faker.providers import internet
|
|
|
|
from faker.providers import lorem
|
|
|
|
from faker.providers import misc
|
|
|
|
|
2019-07-24 07:46:08 +02:00
|
|
|
from settings import config
|
2019-05-23 12:36:03 +02:00
|
|
|
|
|
|
|
fake = faker.Faker()
|
|
|
|
fake.add_provider(internet)
|
|
|
|
fake.add_provider(lorem)
|
|
|
|
fake.add_provider(misc)
|
|
|
|
|
2019-07-22 14:13:10 +02:00
|
|
|
|
2019-07-22 02:09:22 +02:00
|
|
|
def fake_lbryusername():
|
|
|
|
return '@' + fake.user_name()
|
|
|
|
|
|
|
|
|
|
|
|
def jsonrpc_post(url, method, **params):
|
|
|
|
json_body = {
|
|
|
|
'jsonrpc': '2.0',
|
|
|
|
'id': None,
|
|
|
|
'method': method,
|
|
|
|
'params': params
|
|
|
|
}
|
|
|
|
return requests.post(url=url, json=json_body)
|
|
|
|
|
|
|
|
|
|
|
|
def nothing():
|
2019-07-22 14:13:10 +02:00
|
|
|
pass
|
2019-07-22 02:09:22 +02:00
|
|
|
|
2019-05-23 12:36:03 +02:00
|
|
|
|
2019-07-24 08:11:30 +02:00
|
|
|
replace = {
|
|
|
|
'claim_id': fake.sha1,
|
|
|
|
'comment': fake.text,
|
|
|
|
'channel_id': fake.sha1,
|
|
|
|
'channel_name': fake_lbryusername,
|
|
|
|
'signature': fake.uuid4,
|
|
|
|
'parent_id': fake.sha256
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
def create_test_comments(values: iter, **default):
|
|
|
|
vars_combo = chain.from_iterable(combinations(values, r) for r in range(1, len(values) + 1))
|
|
|
|
return [{k: replace[k]() if k in comb else v for k, v in default.items()}
|
|
|
|
for comb in vars_combo]
|
|
|
|
|
|
|
|
|
2019-05-23 12:36:03 +02:00
|
|
|
class ServerTest(unittest.TestCase):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.url = 'http://' + config['HOST'] + ':5921/api'
|
|
|
|
|
|
|
|
def post_comment(self, **params):
|
|
|
|
json_body = {
|
|
|
|
'jsonrpc': '2.0',
|
|
|
|
'id': None,
|
|
|
|
'method': 'create_comment',
|
|
|
|
'params': params
|
|
|
|
}
|
|
|
|
return requests.post(url=self.url, json=json_body)
|
|
|
|
|
2019-07-22 14:13:10 +02:00
|
|
|
def is_valid_message(self, comment=None, claim_id=None, parent_id=None,
|
|
|
|
channel_name=None, channel_id=None, signature=None, signing_ts=None):
|
2019-05-23 12:36:03 +02:00
|
|
|
try:
|
2019-07-22 14:13:10 +02:00
|
|
|
assert comment is not None and claim_id is not None
|
|
|
|
assert re.fullmatch('([a-f0-9]|[A-F0-9]){40}', claim_id)
|
|
|
|
assert 0 < len(comment) <= 2000
|
|
|
|
if parent_id is not None:
|
|
|
|
assert re.fullmatch('([a-f0-9]){64}', parent_id)
|
|
|
|
|
|
|
|
if channel_name or channel_id or signature or signing_ts:
|
|
|
|
assert channel_id is not None and channel_name is not None
|
|
|
|
assert re.fullmatch('([a-f0-9]|[A-F0-9]){40}', channel_id)
|
|
|
|
assert self.valid_channel_name(channel_name)
|
|
|
|
assert (signature is None and signing_ts is None) or \
|
|
|
|
(signature is not None and signing_ts is not None)
|
|
|
|
if signature:
|
|
|
|
assert len(signature) == 128
|
|
|
|
if parent_id:
|
|
|
|
assert parent_id.isalnum()
|
|
|
|
except Exception:
|
|
|
|
return False
|
|
|
|
return True
|
2019-05-23 12:36:03 +02:00
|
|
|
|
|
|
|
def setUp(self) -> None:
|
|
|
|
self.reply_id = 'ace7800f36e55c74c4aa6a698f97a7ee5f1ccb047b5a0730960df90e58c41dc2'
|
|
|
|
|
2019-07-22 14:13:10 +02:00
|
|
|
@staticmethod
|
|
|
|
def valid_channel_name(channel_name):
|
|
|
|
return re.fullmatch(
|
|
|
|
'^@(?:(?![\x00-\x08\x0b\x0c\x0e-\x1f\x23-\x26'
|
|
|
|
'\x2f\x3a\x3d\x3f-\x40\uFFFE-\U0000FFFF]).){1,255}$',
|
|
|
|
channel_name
|
|
|
|
)
|
|
|
|
|
2019-05-23 12:36:03 +02:00
|
|
|
def test01CreateCommentNoReply(self):
|
|
|
|
anonymous_test = create_test_comments(
|
|
|
|
('claim_id', 'channel_id', 'channel_name', 'comment'),
|
|
|
|
comment=None,
|
|
|
|
channel_name=None,
|
|
|
|
channel_id=None,
|
|
|
|
claim_id=None
|
|
|
|
)
|
|
|
|
for test in anonymous_test:
|
|
|
|
with self.subTest(test=test):
|
|
|
|
message = self.post_comment(**test)
|
|
|
|
message = message.json()
|
2019-07-22 14:13:10 +02:00
|
|
|
self.assertTrue('result' in message or 'error' in message)
|
|
|
|
if 'error' in message:
|
|
|
|
self.assertFalse(self.is_valid_message(**test))
|
2019-05-23 12:36:03 +02:00
|
|
|
else:
|
2019-07-22 14:13:10 +02:00
|
|
|
self.assertTrue(self.is_valid_message(**test))
|
2019-05-23 12:36:03 +02:00
|
|
|
|
|
|
|
def test02CreateNamedCommentsNoReply(self):
|
|
|
|
named_test = create_test_comments(
|
|
|
|
('channel_name', 'channel_id', 'signature'),
|
|
|
|
claim_id='1234567890123456789012345678901234567890',
|
|
|
|
channel_name='@JamieFoxx',
|
|
|
|
channel_id='1234567890'*4,
|
|
|
|
comment='blah blah blahbity blah',
|
|
|
|
signature=None
|
|
|
|
)
|
|
|
|
for test in named_test:
|
|
|
|
with self.subTest(test=test):
|
|
|
|
message = self.post_comment(**test)
|
|
|
|
message = message.json()
|
2019-07-22 14:13:10 +02:00
|
|
|
self.assertTrue('result' in message or 'error' in message)
|
|
|
|
if 'error' in message:
|
|
|
|
self.assertFalse(self.is_valid_message(**test))
|
2019-05-23 12:36:03 +02:00
|
|
|
else:
|
2019-07-22 14:13:10 +02:00
|
|
|
self.assertTrue(self.is_valid_message(**test))
|
2019-05-23 12:36:03 +02:00
|
|
|
|
|
|
|
def test03CreateAllTestComments(self):
|
|
|
|
test_all = create_test_comments(replace.keys(), **{
|
|
|
|
k: None for k in replace.keys()
|
|
|
|
})
|
|
|
|
for test in test_all:
|
|
|
|
with self.subTest(test=test):
|
|
|
|
message = self.post_comment(**test)
|
|
|
|
message = message.json()
|
2019-07-22 14:13:10 +02:00
|
|
|
self.assertTrue('result' in message or 'error' in message)
|
|
|
|
if 'error' in message:
|
|
|
|
self.assertFalse(self.is_valid_message(**test))
|
2019-05-23 12:36:03 +02:00
|
|
|
else:
|
2019-07-22 14:13:10 +02:00
|
|
|
self.assertTrue(self.is_valid_message(**test))
|
2019-05-23 12:36:03 +02:00
|
|
|
|
|
|
|
def test04CreateAllReplies(self):
|
|
|
|
claim_id = '1d8a5cc39ca02e55782d619e67131c0a20843be8'
|
|
|
|
parent_comment = self.post_comment(
|
|
|
|
channel_name='@KevinWalterRabie',
|
|
|
|
channel_id=fake.sha1(),
|
|
|
|
comment='Hello everybody and welcome back to my chan nel',
|
|
|
|
claim_id=claim_id,
|
|
|
|
)
|
|
|
|
parent_id = parent_comment.json()['result']['comment_id']
|
|
|
|
test_all = create_test_comments(
|
|
|
|
('comment', 'channel_name', 'channel_id', 'signature', 'parent_id'),
|
|
|
|
parent_id=parent_id,
|
|
|
|
comment=None,
|
|
|
|
channel_name=None,
|
|
|
|
channel_id=None,
|
|
|
|
signature=None,
|
|
|
|
claim_id=claim_id
|
|
|
|
)
|
|
|
|
for test in test_all:
|
2019-07-22 14:13:10 +02:00
|
|
|
with self.subTest(test=test):
|
2019-05-23 12:36:03 +02:00
|
|
|
if test['parent_id'] != parent_id:
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
message = self.post_comment(**test)
|
|
|
|
message = message.json()
|
2019-07-22 14:13:10 +02:00
|
|
|
self.assertTrue('result' in message or 'error' in message)
|
|
|
|
if 'error' in message:
|
|
|
|
self.assertFalse(self.is_valid_message(**test))
|
2019-05-23 12:36:03 +02:00
|
|
|
else:
|
2019-07-22 14:13:10 +02:00
|
|
|
self.assertTrue(self.is_valid_message(**test))
|
2019-05-23 12:36:03 +02:00
|
|
|
|
|
|
|
|
|
|
|
class ListCommentsTest(unittest.TestCase):
|
|
|
|
replace = {
|
|
|
|
'claim_id': fake.sha1,
|
|
|
|
'comment': fake.text,
|
|
|
|
'channel_id': fake.sha1,
|
|
|
|
'channel_name': fake_lbryusername,
|
|
|
|
'signature': nothing,
|
|
|
|
'parent_id': nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def post_comment(cls, **params):
|
|
|
|
json_body = {
|
|
|
|
'jsonrpc': '2.0',
|
|
|
|
'id': None,
|
|
|
|
'method': 'create_comment',
|
|
|
|
'params': params
|
|
|
|
}
|
|
|
|
return requests.post(url=cls.url, json=json_body)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls) -> None:
|
|
|
|
cls.url = 'http://' + config['HOST'] + ':5921/api'
|
|
|
|
cls.claim_id = '1d8a5cc39ca02e55782d619e67131c0a20843be8'
|
|
|
|
cls.comment_list = [{key: cls.replace[key]() for key in cls.replace.keys()} for _ in range(23)]
|
|
|
|
for comment in cls.comment_list:
|
|
|
|
comment['claim_id'] = cls.claim_id
|
|
|
|
cls.comment_ids = [cls.post_comment(**comm).json()['result']['comment_id']
|
2019-05-30 00:01:48 +02:00
|
|
|
for comm in cls.comment_list]
|
2019-05-23 12:36:03 +02:00
|
|
|
|
|
|
|
def testListComments(self):
|
|
|
|
response_one = jsonrpc_post(self.url, 'get_claim_comments', page_size=20,
|
2019-05-30 00:01:48 +02:00
|
|
|
page=1, top_level=1, claim_id=self.claim_id).json()
|
2019-05-23 12:36:03 +02:00
|
|
|
self.assertIsNotNone(response_one)
|
|
|
|
self.assertIn('result', response_one)
|
2019-05-30 00:01:48 +02:00
|
|
|
response_one: dict = response_one['result']
|
|
|
|
self.assertIs(type(response_one), dict)
|
2019-07-22 02:09:22 +02:00
|
|
|
self.assertEquals(response_one['page_size'], len(response_one['items']))
|
2019-05-30 00:01:48 +02:00
|
|
|
self.assertIn('items', response_one)
|
2019-07-22 02:09:22 +02:00
|
|
|
self.assertGreaterEqual(response_one['total_pages'], response_one['page'])
|
|
|
|
last_page = response_one['total_pages']
|
2019-05-23 12:36:03 +02:00
|
|
|
response = jsonrpc_post(self.url, 'get_claim_comments', page_size=20,
|
2019-07-22 02:09:22 +02:00
|
|
|
page=last_page, top_level=1, claim_id=self.claim_id).json()
|
2019-05-23 12:36:03 +02:00
|
|
|
self.assertIsNotNone(response)
|
|
|
|
self.assertIn('result', response)
|
2019-05-30 00:01:48 +02:00
|
|
|
response: dict = response['result']
|
2019-07-22 02:09:22 +02:00
|
|
|
self.assertIs(type(response['items']), list)
|
2019-05-30 00:01:48 +02:00
|
|
|
self.assertEqual(response['total_items'], response_one['total_items'])
|
2019-07-22 02:09:22 +02:00
|
|
|
self.assertEqual(response['total_pages'], response_one['total_pages'])
|
|
|
|
|
2019-05-23 12:36:03 +02:00
|
|
|
|
2019-07-24 08:11:30 +02:00
|
|
|
class ConcurrentWriteTest(unittest.TestCase):
|
|
|
|
@staticmethod
|
|
|
|
def make_comment(num):
|
|
|
|
return {
|
|
|
|
'jsonrpc': '2.0',
|
|
|
|
'id': num,
|
|
|
|
'method': 'create_comment',
|
|
|
|
'params': {
|
|
|
|
'comment': f'Comment #{num}',
|
|
|
|
'claim_id': '6d266af6c25c80fa2ac6cc7662921ad2e90a07e7',
|
|
|
|
}
|
|
|
|
}
|
2019-05-23 12:36:03 +02:00
|
|
|
|
2019-07-24 08:11:30 +02:00
|
|
|
@staticmethod
|
|
|
|
def send_comment_to_server(params):
|
|
|
|
with requests.post(params[0], json=params[1]) as req:
|
|
|
|
return req.json()
|
|
|
|
|
|
|
|
def test01Concurrency(self):
|
|
|
|
urls = [f'http://localhost:{port}/api' for port in range(5921, 5925)]
|
|
|
|
comments = [self.make_comment(i) for i in range(1, 5)]
|
|
|
|
inputs = list(zip(urls, comments))
|
|
|
|
with Pool(4) as pool:
|
|
|
|
results = pool.map(self.send_comment_to_server, inputs)
|
|
|
|
results = list(filter(lambda x: 'comment_id' in x['result'], results))
|
|
|
|
self.assertIsNotNone(results)
|
|
|
|
self.assertEqual(len(results), len(inputs))
|