from io import BytesIO from unittest import mock from twisted.internet import defer from twisted.test import proto_helpers from twisted.trial import unittest from lbrynet.p2p import Peer from lbrynet.p2p.PaymentRateManager import NegotiatedPaymentRateManager, BasePaymentRateManager from lbrynet.conf import Config from tests.mocks import BlobAvailabilityTracker as DummyBlobAvailabilityTracker class TestBlobRequestHandlerQueries(unittest.TestCase): def setUp(self): conf = Config() self.blob_manager = mock.Mock() self.payment_rate_manager = NegotiatedPaymentRateManager( BasePaymentRateManager(0.001, conf.min_info_rate), DummyBlobAvailabilityTracker(), conf.is_generous_host ) from lbrynet.p2p.server import BlobRequestHandler self.handler = BlobRequestHandler.BlobRequestHandler( self.blob_manager, None, self.payment_rate_manager, None) def test_empty_response_when_empty_query(self): self.assertEqual({}, self.handler.handle_queries({})) def test_error_set_when_rate_is_missing(self): query = {'requested_blob': 'blob'} response = {'incoming_blob': {'error': 'RATE_UNSET'}} self.assertEqual(response, self.handler.handle_queries(query)) def test_error_set_when_rate_too_low(self): query = { 'blob_data_payment_rate': -1.0, 'requested_blob': 'blob' } response = { 'blob_data_payment_rate': 'RATE_TOO_LOW', 'incoming_blob': {'error': 'RATE_UNSET'} } self.assertEqual(response, self.handler.handle_queries(query)) def test_response_when_rate_too_low(self): query = { 'blob_data_payment_rate': -1.0, } response = { 'blob_data_payment_rate': 'RATE_TOO_LOW', } self.assertEqual(response, self.handler.handle_queries(query)) def test_blob_unavailable_when_blob_not_validated(self): blob = mock.Mock() blob.get_is_verified.return_value = False self.blob_manager.get_blob.return_value = defer.succeed(blob) query = { 'blob_data_payment_rate': 1.0, 'requested_blob': 'blob' } response = { 'blob_data_payment_rate': 'RATE_ACCEPTED', 'incoming_blob': {'error': 'BLOB_UNAVAILABLE'} } self.assertEqual(response, self.handler.handle_queries(query)) def test_blob_unavailable_when_blob_cannot_be_opened(self): blob = mock.Mock() blob.get_is_verified.return_value = True blob.open_for_reading.return_value = None self.blob_manager.get_blob.return_value = defer.succeed(blob) query = { 'blob_data_payment_rate': 0.0, 'requested_blob': 'blob' } response = { 'blob_data_payment_rate': 'RATE_ACCEPTED', 'incoming_blob': {'error': 'BLOB_UNAVAILABLE'} } self.assertEqual(response, self.handler.handle_queries(query)) def test_blob_details_are_set_when_all_conditions_are_met(self): blob = mock.Mock() blob.get_is_verified.return_value = True blob.open_for_reading.return_value = True blob.blob_hash = 'DEADBEEF' blob.length = 42 peer = mock.Mock() peer.host = "1.2.3.4" self.handler.peer = peer self.blob_manager.get_blob.return_value = defer.succeed(blob) query = { 'blob_data_payment_rate': 1.0, 'requested_blob': 'blob' } response = { 'blob_data_payment_rate': 'RATE_ACCEPTED', 'incoming_blob': { 'blob_hash': 'DEADBEEF', 'length': 42 } } self.assertEqual(response, self.handler.handle_queries(query)) class TestBlobRequestHandlerSender(unittest.TestCase): def test_nothing_happens_if_not_currently_uploading(self): from lbrynet.p2p.server import BlobRequestHandler handler = BlobRequestHandler.BlobRequestHandler(None, None, None, None) handler.currently_uploading = None deferred = handler.send_blob_if_requested(None) self.assertTrue(self.successResultOf(deferred)) def test_file_is_sent_to_consumer(self): # TODO: also check that the expected payment values are set consumer = proto_helpers.StringTransport() test_file = BytesIO(b'test') from lbrynet.p2p.server import BlobRequestHandler handler = BlobRequestHandler.BlobRequestHandler(None, None, None, None) handler.peer = mock.create_autospec(Peer.Peer) handler.currently_uploading = mock.Mock() handler.read_handle = test_file handler.send_blob_if_requested(consumer) while consumer.producer: consumer.producer.resumeProducing() self.assertEqual(consumer.value(), b'test')