import itertools import random from unittest import mock from twisted.trial import unittest from lbrynet.p2p.PaymentRateManager import NegotiatedPaymentRateManager, BasePaymentRateManager from lbrynet.p2p.Strategy import BasicAvailabilityWeightedStrategy from lbrynet.p2p.Offer import Offer from tests.mocks\ import BlobAvailabilityTracker as DummyBlobAvailabilityTracker, mock_conf_settings MAX_NEGOTIATION_TURNS = 10 random.seed(12345) def get_random_sample(list_to_sample): result = list_to_sample[ random.randint(1, len(list_to_sample)):random.randint(1, len(list_to_sample))] if not result: return get_random_sample(list_to_sample) return result def calculate_negotation_turns(client_base, host_base, host_is_generous=True, client_is_generous=True): blobs = [ 'b2e48bb4c88cf46b76adf0d47a72389fae0cd1f19ed27dc5' '09138c99509a25423a4cef788d571dca7988e1dca69e6fa0', 'd7c82e6cac093b3f16107d2ae2b2c75424f1fcad2c7fbdbe' '66e4a13c0b6bd27b67b3a29c403b82279ab0f7c1c48d6787', '5a450b416275da4bdff604ee7b58eaedc7913c5005b7184f' 'c3bc5ef0b1add00613587f54217c91097fc039ed9eace9dd', 'f99d24cd50d4bfd77c2598bfbeeb8415bf0feef21200bdf0' 'b8fbbde7751a77b7a2c68e09c25465a2f40fba8eecb0b4e0', '9dbda74a472a2e5861a5d18197aeba0f5de67c67e401124c' '243d2f0f41edf01d7a26aeb0b5fc9bf47f6361e0f0968e2c', '91dc64cf1ff42e20d627b033ad5e4c3a4a96856ed8a6e3fb' '4cd5fa1cfba4bf72eefd325f579db92f45f4355550ace8e7', '6d8017aba362e5c5d0046625a039513419810a0397d72831' '8c328a5cc5d96efb589fbca0728e54fe5adbf87e9545ee07', '6af95cd062b4a179576997ef1054c9d2120f8592eea045e9' '667bea411d520262cd5a47b137eabb7a7871f5f8a79c92dd', '8c70d5e2f5c3a6085006198e5192d157a125d92e73787944' '72007a61947992768926513fc10924785bdb1761df3c37e6', 'c84aa1fd8f5009f7c4e71e444e40d95610abc1480834f835' 'eefb267287aeb10025880a3ce22580db8c6d92efb5bc0c9c' ] host = mock.Mock() host.host = "1.2.3.4" client = mock.Mock() client.host = "1.2.3.5" client_base_prm = BasePaymentRateManager(client_base) client_prm = NegotiatedPaymentRateManager(client_base_prm, DummyBlobAvailabilityTracker(), generous=client_is_generous) host_base_prm = BasePaymentRateManager(host_base) host_prm = NegotiatedPaymentRateManager(host_base_prm, DummyBlobAvailabilityTracker(), generous=host_is_generous) blobs_to_query = get_random_sample(blobs) accepted = False turns = 0 while not accepted: rate = client_prm.get_rate_blob_data(host, blobs_to_query) offer = Offer(rate) accepted = host_prm.accept_rate_blob_data(client, blobs_to_query, offer) turns += 1 return turns class AvailabilityWeightedStrategyTests(unittest.TestCase): def setUp(self): mock_conf_settings(self) def test_first_offer_is_zero_and_second_is_not_if_offer_not_accepted(self): strategy = BasicAvailabilityWeightedStrategy(DummyBlobAvailabilityTracker()) peer = "1.1.1.1" blobs = strategy.price_model.blob_tracker.availability.keys() offer1 = strategy.make_offer(peer, blobs) offer2 = strategy.make_offer(peer, blobs) self.assertEqual(offer1.rate, 0.0) self.assertNotEqual(offer2.rate, 0.0) def test_accept_zero_and_persist_if_accepted(self): host_strategy = BasicAvailabilityWeightedStrategy(DummyBlobAvailabilityTracker()) client_strategy = BasicAvailabilityWeightedStrategy(DummyBlobAvailabilityTracker()) client = "1.1.1.1" host = "1.1.1.2" blobs = host_strategy.price_model.blob_tracker.availability.keys() offer = client_strategy.make_offer(host, blobs) response1 = host_strategy.respond_to_offer(offer, client, blobs) client_strategy.update_accepted_offers(host, response1) offer = client_strategy.make_offer(host, blobs) response2 = host_strategy.respond_to_offer(offer, client, blobs) client_strategy.update_accepted_offers(host, response2) self.assertFalse(response1.is_too_low) self.assertTrue(response1.is_accepted) self.assertEqual(response1.rate, 0.0) self.assertFalse(response2.is_too_low) self.assertTrue(response2.is_accepted) self.assertEqual(response2.rate, 0.0) def test_how_many_turns_before_accept_with_similar_rate_settings(self): base_rates = [0.0001 * n for n in range(1, 10)] for host_base, client_base in itertools.product(base_rates, base_rates): turns = calculate_negotation_turns(host_base, client_base, client_is_generous=False, host_is_generous=False) self.assertGreater(MAX_NEGOTIATION_TURNS, turns) def test_generous_connects_in_one_turn(self): base_rates = [0.0001 * n for n in range(1, 10)] for host_base, client_base in itertools.product(base_rates, base_rates): turns = calculate_negotation_turns(host_base, client_base) self.assertEqual(1, turns) def test_how_many_turns_with_generous_client(self): base_rates = [0.0001 * n for n in range(1, 10)] for host_base, client_base in itertools.product(base_rates, base_rates): turns = calculate_negotation_turns(host_base, client_base, host_is_generous=False) self.assertGreater(MAX_NEGOTIATION_TURNS, turns) def test_how_many_turns_with_generous_host(self): base_rates = [0.0001 * n for n in range(1, 10)] for host_base, client_base in itertools.product(base_rates, base_rates): turns = calculate_negotation_turns(host_base, client_base, client_is_generous=False) self.assertGreater(MAX_NEGOTIATION_TURNS, turns)