2016-07-20 17:44:06 +02:00
|
|
|
import mock
|
2017-04-11 04:47:54 +02:00
|
|
|
import json
|
2017-10-17 04:11:20 +02:00
|
|
|
import unittest
|
2018-05-02 01:30:48 +02:00
|
|
|
from os import path
|
2017-04-26 19:27:24 +02:00
|
|
|
|
2016-12-02 20:39:01 +01:00
|
|
|
from twisted.internet import defer
|
2017-10-17 04:11:20 +02:00
|
|
|
from twisted import trial
|
2017-04-26 19:27:24 +02:00
|
|
|
|
2018-05-02 01:30:48 +02:00
|
|
|
from faker import Faker
|
|
|
|
|
2017-04-11 04:47:54 +02:00
|
|
|
from lbryschema.decode import smart_decode
|
2018-02-12 20:19:15 +01:00
|
|
|
from lbryum.wallet import NewWallet
|
2017-04-26 19:27:24 +02:00
|
|
|
from lbrynet import conf
|
2017-01-26 02:06:17 +01:00
|
|
|
from lbrynet.core import Session, PaymentRateManager, Wallet
|
2018-02-12 20:19:15 +01:00
|
|
|
from lbrynet.database.storage import SQLiteStorage
|
2017-06-26 03:04:33 +02:00
|
|
|
from lbrynet.daemon.Daemon import Daemon as LBRYDaemon
|
2018-05-02 01:30:48 +02:00
|
|
|
from lbrynet.file_manager.EncryptedFileManager import EncryptedFileManager
|
|
|
|
from lbrynet.file_manager.EncryptedFileDownloader import ManagedEncryptedFileDownloader
|
2016-07-20 17:44:06 +02:00
|
|
|
|
2017-09-28 19:21:26 +02:00
|
|
|
from lbrynet.tests import util
|
|
|
|
from lbrynet.tests.mocks import mock_conf_settings, FakeNetwork
|
|
|
|
from lbrynet.tests.mocks import BlobAvailabilityTracker as DummyBlobAvailabilityTracker
|
|
|
|
from lbrynet.tests.mocks import ExchangeRateManager as DummyExchangeRateManager
|
|
|
|
from lbrynet.tests.mocks import BTCLBCFeed, USDBTCFeed
|
2017-10-17 04:11:20 +02:00
|
|
|
from lbrynet.tests.util import is_android
|
|
|
|
|
2016-12-02 20:39:01 +01:00
|
|
|
|
2017-10-10 19:31:07 +02:00
|
|
|
import logging
|
|
|
|
logging.getLogger("lbryum").setLevel(logging.WARNING)
|
|
|
|
|
|
|
|
|
2016-12-04 22:18:13 +01:00
|
|
|
def get_test_daemon(data_rate=None, generous=True, with_fee=False):
|
|
|
|
if data_rate is None:
|
2017-01-17 04:23:20 +01:00
|
|
|
data_rate = conf.ADJUSTABLE_SETTINGS['data_rate'][1]
|
2016-12-04 22:18:13 +01:00
|
|
|
|
2016-12-02 20:39:01 +01:00
|
|
|
rates = {
|
2017-01-26 02:06:17 +01:00
|
|
|
'BTCLBC': {'spot': 3.0, 'ts': util.DEFAULT_ISO_TIME + 1},
|
|
|
|
'USDBTC': {'spot': 2.0, 'ts': util.DEFAULT_ISO_TIME + 2}
|
|
|
|
}
|
2017-08-07 22:42:14 +02:00
|
|
|
daemon = LBRYDaemon(None)
|
2016-12-02 20:39:01 +01:00
|
|
|
daemon.session = mock.Mock(spec=Session.Session)
|
2017-04-11 04:47:54 +02:00
|
|
|
daemon.session.wallet = mock.Mock(spec=Wallet.LBRYumWallet)
|
2018-02-12 20:19:15 +01:00
|
|
|
daemon.session.wallet.wallet = mock.Mock(spec=NewWallet)
|
|
|
|
daemon.session.wallet.wallet.use_encryption = False
|
|
|
|
daemon.session.wallet.network = FakeNetwork()
|
|
|
|
daemon.session.storage = mock.Mock(spec=SQLiteStorage)
|
2017-05-31 20:15:15 +02:00
|
|
|
market_feeds = [BTCLBCFeed(), USDBTCFeed()]
|
|
|
|
daemon.exchange_rate_manager = DummyExchangeRateManager(market_feeds, rates)
|
2016-12-02 20:39:01 +01:00
|
|
|
base_prm = PaymentRateManager.BasePaymentRateManager(rate=data_rate)
|
2017-01-26 02:06:17 +01:00
|
|
|
prm = PaymentRateManager.NegotiatedPaymentRateManager(base_prm, DummyBlobAvailabilityTracker(),
|
|
|
|
generous=generous)
|
2016-12-02 20:39:01 +01:00
|
|
|
daemon.session.payment_rate_manager = prm
|
2017-06-09 19:47:13 +02:00
|
|
|
|
2016-12-02 20:39:01 +01:00
|
|
|
metadata = {
|
2016-12-04 22:18:13 +01:00
|
|
|
"author": "fake author",
|
2017-04-11 04:47:54 +02:00
|
|
|
"language": "en",
|
2016-12-04 22:18:13 +01:00
|
|
|
"content_type": "fake/format",
|
|
|
|
"description": "fake description",
|
|
|
|
"license": "fake license",
|
|
|
|
"license_url": "fake license url",
|
2016-12-02 20:39:01 +01:00
|
|
|
"nsfw": False,
|
|
|
|
"sources": {
|
2017-10-02 18:13:45 +02:00
|
|
|
"lbry_sd_hash": 'd2b8b6e907dde95245fe6d144d16c2fdd60c4e0c6463ec98'
|
|
|
|
'b85642d06d8e9414e8fcfdcb7cb13532ec5454fb8fe7f280'
|
2016-12-04 22:18:13 +01:00
|
|
|
},
|
|
|
|
"thumbnail": "fake thumbnail",
|
|
|
|
"title": "fake title",
|
2016-12-02 20:39:01 +01:00
|
|
|
"ver": "0.0.3"
|
|
|
|
}
|
|
|
|
if with_fee:
|
2017-01-26 02:06:17 +01:00
|
|
|
metadata.update(
|
2017-04-11 04:47:54 +02:00
|
|
|
{"fee": {"USD": {"address": "bQ6BGboPV2SpTMEP7wLNiAcnsZiH8ye6eA", "amount": 0.75}}})
|
2016-12-04 22:18:13 +01:00
|
|
|
daemon._resolve_name = lambda _: defer.succeed(metadata)
|
2017-04-12 23:42:55 +02:00
|
|
|
migrated = smart_decode(json.dumps(metadata))
|
2017-09-29 12:44:22 +02:00
|
|
|
daemon.session.wallet.resolve = lambda *_: defer.succeed(
|
|
|
|
{"test": {'claim': {'value': migrated.claim_dict}}})
|
2016-12-02 20:39:01 +01:00
|
|
|
return daemon
|
|
|
|
|
|
|
|
|
2017-10-17 04:11:20 +02:00
|
|
|
class TestCostEst(trial.unittest.TestCase):
|
2016-12-02 20:39:01 +01:00
|
|
|
def setUp(self):
|
2017-01-17 04:23:20 +01:00
|
|
|
mock_conf_settings(self)
|
2016-12-02 20:39:01 +01:00
|
|
|
util.resetTime(self)
|
|
|
|
|
2016-12-04 22:18:13 +01:00
|
|
|
def test_fee_and_generous_data(self):
|
2016-12-02 20:39:01 +01:00
|
|
|
size = 10000000
|
2016-12-04 22:18:13 +01:00
|
|
|
correct_result = 4.5
|
2016-12-02 20:39:01 +01:00
|
|
|
daemon = get_test_daemon(generous=True, with_fee=True)
|
2016-12-04 22:18:13 +01:00
|
|
|
self.assertEquals(daemon.get_est_cost("test", size).result, correct_result)
|
2016-12-02 20:39:01 +01:00
|
|
|
|
2016-12-04 22:18:13 +01:00
|
|
|
def test_fee_and_ungenerous_data(self):
|
2016-12-02 20:39:01 +01:00
|
|
|
size = 10000000
|
|
|
|
fake_fee_amount = 4.5
|
2017-01-17 04:23:20 +01:00
|
|
|
data_rate = conf.ADJUSTABLE_SETTINGS['data_rate'][1]
|
2017-01-26 02:06:17 +01:00
|
|
|
correct_result = size / 10 ** 6 * data_rate + fake_fee_amount
|
2016-12-02 20:39:01 +01:00
|
|
|
daemon = get_test_daemon(generous=False, with_fee=True)
|
2016-12-04 22:18:13 +01:00
|
|
|
self.assertEquals(daemon.get_est_cost("test", size).result, correct_result)
|
2016-12-02 20:39:01 +01:00
|
|
|
|
2016-12-04 22:18:13 +01:00
|
|
|
def test_generous_data_and_no_fee(self):
|
2016-12-02 20:39:01 +01:00
|
|
|
size = 10000000
|
2016-12-04 22:18:13 +01:00
|
|
|
correct_result = 0.0
|
2016-12-02 20:39:01 +01:00
|
|
|
daemon = get_test_daemon(generous=True)
|
2016-12-04 22:18:13 +01:00
|
|
|
self.assertEquals(daemon.get_est_cost("test", size).result, correct_result)
|
2016-12-02 20:39:01 +01:00
|
|
|
|
2016-12-04 22:18:13 +01:00
|
|
|
def test_ungenerous_data_and_no_fee(self):
|
2016-12-02 20:39:01 +01:00
|
|
|
size = 10000000
|
2017-01-17 04:23:20 +01:00
|
|
|
data_rate = conf.ADJUSTABLE_SETTINGS['data_rate'][1]
|
2017-01-26 02:06:17 +01:00
|
|
|
correct_result = size / 10 ** 6 * data_rate
|
2016-12-02 20:39:01 +01:00
|
|
|
daemon = get_test_daemon(generous=False)
|
2016-12-04 22:18:13 +01:00
|
|
|
self.assertEquals(daemon.get_est_cost("test", size).result, correct_result)
|
2017-01-26 02:06:17 +01:00
|
|
|
|
|
|
|
|
2017-10-17 04:11:20 +02:00
|
|
|
class TestJsonRpc(trial.unittest.TestCase):
|
2017-01-26 02:06:17 +01:00
|
|
|
def setUp(self):
|
2017-02-21 19:47:47 +01:00
|
|
|
def noop():
|
|
|
|
return None
|
|
|
|
|
2017-01-26 02:06:17 +01:00
|
|
|
mock_conf_settings(self)
|
|
|
|
util.resetTime(self)
|
|
|
|
self.test_daemon = get_test_daemon()
|
2018-02-12 20:19:15 +01:00
|
|
|
self.test_daemon.session.wallet.is_first_run = False
|
2017-02-21 19:47:47 +01:00
|
|
|
self.test_daemon.session.wallet.get_best_blockhash = noop
|
2017-01-26 02:06:17 +01:00
|
|
|
|
|
|
|
def test_status(self):
|
|
|
|
d = defer.maybeDeferred(self.test_daemon.jsonrpc_status)
|
|
|
|
d.addCallback(lambda status: self.assertDictContainsSubset({'is_running': False}, status))
|
|
|
|
|
2017-10-17 04:11:20 +02:00
|
|
|
@unittest.skipIf(is_android(),
|
|
|
|
'Test cannot pass on Android because PYTHONOPTIMIZE removes the docstrings.')
|
2017-01-26 02:06:17 +01:00
|
|
|
def test_help(self):
|
|
|
|
d = defer.maybeDeferred(self.test_daemon.jsonrpc_help, command='status')
|
2017-03-09 13:58:36 +01:00
|
|
|
d.addCallback(lambda result: self.assertSubstring('daemon status', result['help']))
|
2017-01-26 02:06:17 +01:00
|
|
|
# self.assertSubstring('daemon status', d.result)
|
2018-05-02 01:30:48 +02:00
|
|
|
|
|
|
|
|
|
|
|
class TestFileListSorting(trial.unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
|
|
mock_conf_settings(self)
|
|
|
|
util.resetTime(self)
|
|
|
|
self.faker = Faker('en_US')
|
|
|
|
self.faker.seed(66410)
|
|
|
|
self.test_daemon = get_test_daemon()
|
|
|
|
self.test_daemon.lbry_file_manager = mock.Mock(spec=EncryptedFileManager)
|
|
|
|
self.test_daemon.lbry_file_manager.lbry_files = self._get_fake_lbry_files()
|
|
|
|
|
|
|
|
# Pre-sorted lists of prices and file names in ascending order produced by
|
|
|
|
# faker with seed 66410. This seed was chosen becacuse it produces 3 results
|
|
|
|
# 'points_paid' at 6.0 and 2 results at 4.5 to test multiple sort criteria.
|
|
|
|
self.test_prices = [0.2, 2.9, 4.5, 4.5, 6.0, 6.0, 6.0, 6.8, 7.1, 9.2]
|
|
|
|
self.test_file_names = ['also.mp3', 'better.css', 'call.mp3', 'pay.jpg',
|
|
|
|
'record.pages', 'sell.css', 'strategy.pages',
|
|
|
|
'thousand.pages', 'town.mov', 'vote.ppt']
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def test_sort_by_price_no_direction_specified(self):
|
|
|
|
sort_options = ['price']
|
|
|
|
file_list = yield self.test_daemon.jsonrpc_file_list(sort=sort_options)
|
|
|
|
received = [f['points_paid'] for f in file_list]
|
|
|
|
self.assertEquals(self.test_prices, received)
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def test_sort_by_price_ascending(self):
|
|
|
|
sort_options = ['price,asc']
|
|
|
|
file_list = yield self.test_daemon.jsonrpc_file_list(sort=sort_options)
|
|
|
|
received = [f['points_paid'] for f in file_list]
|
|
|
|
self.assertEquals(self.test_prices, received)
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def test_sort_by_price_descending(self):
|
|
|
|
sort_options = ['price, desc']
|
|
|
|
file_list = yield self.test_daemon.jsonrpc_file_list(sort=sort_options)
|
|
|
|
received = [f['points_paid'] for f in file_list]
|
|
|
|
expected = list(reversed(self.test_prices))
|
|
|
|
self.assertEquals(expected, received)
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def test_sort_by_name_no_direction_specified(self):
|
|
|
|
sort_options = ['name']
|
|
|
|
file_list = yield self.test_daemon.jsonrpc_file_list(sort=sort_options)
|
|
|
|
received = [f['file_name'] for f in file_list]
|
|
|
|
self.assertEquals(self.test_file_names, received)
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def test_sort_by_name_ascending(self):
|
|
|
|
sort_options = ['name,\nasc']
|
|
|
|
file_list = yield self.test_daemon.jsonrpc_file_list(sort=sort_options)
|
|
|
|
received = [f['file_name'] for f in file_list]
|
|
|
|
self.assertEquals(self.test_file_names, received)
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def test_sort_by_name_descending(self):
|
|
|
|
sort_options = ['\tname,\n\tdesc']
|
|
|
|
file_list = yield self.test_daemon.jsonrpc_file_list(sort=sort_options)
|
|
|
|
received = [f['file_name'] for f in file_list]
|
|
|
|
expected = list(reversed(self.test_file_names))
|
|
|
|
self.assertEquals(expected, received)
|
|
|
|
|
|
|
|
@defer.inlineCallbacks
|
|
|
|
def test_sort_by_multiple_criteria(self):
|
|
|
|
sort_options = ['name,asc', 'price,desc']
|
|
|
|
file_list = yield self.test_daemon.jsonrpc_file_list(sort=sort_options)
|
|
|
|
received = ['name={}, price={}'.format(f['file_name'], f['points_paid']) for f in file_list]
|
|
|
|
expected = ['name=record.pages, price=9.2',
|
|
|
|
'name=vote.ppt, price=7.1',
|
|
|
|
'name=strategy.pages, price=6.8',
|
|
|
|
'name=also.mp3, price=6.0',
|
|
|
|
'name=better.css, price=6.0',
|
|
|
|
'name=town.mov, price=6.0',
|
|
|
|
'name=sell.css, price=4.5',
|
|
|
|
'name=thousand.pages, price=4.5',
|
|
|
|
'name=call.mp3, price=2.9',
|
|
|
|
'name=pay.jpg, price=0.2']
|
|
|
|
self.assertEquals(expected, received)
|
|
|
|
|
|
|
|
# Check that the list is not sorted as expected when sorted only by name.
|
|
|
|
sort_options = ['name,asc']
|
|
|
|
file_list = yield self.test_daemon.jsonrpc_file_list(sort=sort_options)
|
|
|
|
received = ['name={}, price={}'.format(f['file_name'], f['points_paid']) for f in file_list]
|
|
|
|
self.assertNotEqual(expected, received)
|
|
|
|
|
|
|
|
# Check that the list is not sorted as expected when sorted only by price.
|
|
|
|
sort_options = ['price,desc']
|
|
|
|
file_list = yield self.test_daemon.jsonrpc_file_list(sort=sort_options)
|
|
|
|
received = ['name={}, price={}'.format(f['file_name'], f['points_paid']) for f in file_list]
|
|
|
|
self.assertNotEqual(expected, received)
|
|
|
|
|
|
|
|
# Check that the list is not sorted as expected when not sorted at all.
|
|
|
|
file_list = yield self.test_daemon.jsonrpc_file_list()
|
|
|
|
received = ['name={}, price={}'.format(f['file_name'], f['points_paid']) for f in file_list]
|
|
|
|
self.assertNotEqual(expected, received)
|
|
|
|
|
|
|
|
def _get_fake_lbry_files(self):
|
|
|
|
return [self._get_fake_lbry_file() for _ in xrange(10)]
|
|
|
|
|
|
|
|
def _get_fake_lbry_file(self):
|
|
|
|
lbry_file = mock.Mock(spec=ManagedEncryptedFileDownloader)
|
|
|
|
|
|
|
|
file_path = self.faker.file_path()
|
|
|
|
stream_name = self.faker.file_name()
|
|
|
|
faked_attributes = {
|
|
|
|
'channel_claim_id': self.faker.sha1(),
|
|
|
|
'channel_name': '@' + self.faker.simple_profile()['username'],
|
|
|
|
'claim_id': self.faker.sha1(),
|
|
|
|
'claim_name': '-'.join(self.faker.words(4)),
|
|
|
|
'completed': self.faker.boolean(),
|
|
|
|
'download_directory': path.dirname(file_path),
|
|
|
|
'download_path': file_path,
|
|
|
|
'file_name': path.basename(file_path),
|
|
|
|
'key': self.faker.md5(),
|
|
|
|
'metadata': {},
|
|
|
|
'mime_type': self.faker.mime_type(),
|
|
|
|
'nout': abs(self.faker.pyint()),
|
|
|
|
'outpoint': self.faker.md5() + self.faker.md5(),
|
|
|
|
'points_paid': self.faker.pyfloat(left_digits=1, right_digits=1, positive=True),
|
|
|
|
'sd_hash': self.faker.md5() + self.faker.md5() + self.faker.md5(),
|
|
|
|
'stopped': self.faker.boolean(),
|
|
|
|
'stream_hash': self.faker.md5() + self.faker.md5() + self.faker.md5(),
|
|
|
|
'stream_name': stream_name,
|
|
|
|
'suggested_file_name': stream_name,
|
|
|
|
'txid': self.faker.md5() + self.faker.md5(),
|
|
|
|
'written_bytes': self.faker.pyint(),
|
|
|
|
}
|
|
|
|
|
|
|
|
for key in faked_attributes:
|
|
|
|
setattr(lbry_file, key, faked_attributes[key])
|
|
|
|
|
|
|
|
return lbry_file
|