Skip to content

Commit

Permalink
Merge pull request #5427 from devos50/devel_update
Browse files Browse the repository at this point in the history
Merge release-7.5 into devel
  • Loading branch information
devos50 authored Jul 1, 2020
2 parents c98871b + d751ae1 commit fd748af
Show file tree
Hide file tree
Showing 16 changed files with 131 additions and 64 deletions.
3 changes: 0 additions & 3 deletions build/mac/makedist_macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ export RESOURCES=build/mac/resources

# ----- Build
PI=pyinstaller
if [ "$(which pyinstaller-2.7)" != "" ]; then
PI=pyinstaller-2.7
fi
$PI tribler.spec

mkdir -p dist/installdir
Expand Down
2 changes: 1 addition & 1 deletion src/pyipv8
Submodule pyipv8 updated 75 files
+5 −1 create_test_coverage_report.py
+222 −0 doc/basics/identity_tutorial.rst
+50 −96 doc/basics/overlay_tutorial.rst
+3 −3 doc/conf.py
+0 −0 doc/deprecated/attestation_prototype.rst
+0 −0 doc/deprecated/attestation_tutorial.rst
+ doc/deprecated/resources/android_rest_api.png
+ doc/deprecated/resources/attestation_req.png
+ doc/deprecated/resources/output_SQjlvW.gif
+ doc/deprecated/resources/peer_rest_api.png
+10 −4 doc/index.rst
+ doc/resources/healthy_IPv8_overlay_collection.png
+165 −43 github_increment_version.py
+234 −0 ipv8/REST/asyncio_endpoint.py
+6 −6 ipv8/REST/attestation_endpoint.py
+1 −0 ipv8/REST/base_endpoint.py
+0 −114 ipv8/REST/health_endpoint.py
+589 −0 ipv8/REST/identity_endpoint.py
+30 −8 ipv8/REST/rest_manager.py
+5 −3 ipv8/REST/root_endpoint.py
+270 −0 ipv8/attestation/communication_manager.py
+17 −6 ipv8/attestation/identity/community.py
+8 −3 ipv8/attestation/wallet/community.py
+2 −1 ipv8/community.py
+208 −1 ipv8/configuration.py
+6 −3 ipv8/dht/community.py
+1 −0 ipv8/messaging/anonymization/community.py
+1 −1 ipv8/messaging/lazy_payload.py
+11 −4 ipv8/requestcache.py
+19 −11 ipv8/taskmanager.py
+24 −9 ipv8/test/REST/attestationendpoint/test_attestation_endpoint.py
+0 −0 ipv8/test/REST/identity/__init__.py
+379 −0 ipv8/test/REST/identity/test_identity_endpoint.py
+12 −2 ipv8/test/REST/rest_base.py
+3 −3 ipv8/test/attestation/identity/test_manager.py
+2 −3 ipv8/test/attestation/tokentree/test_token.py
+4 −4 ipv8/test/attestation/tokentree/test_tree.py
+2 −3 ipv8/test/attestation/trustchain/test_block.py
+2 −3 ipv8/test/attestation/trustchain/test_database.py
+2 −3 ipv8/test/attestation/wallet/bonehexact/test_attestation.py
+2 −3 ipv8/test/attestation/wallet/bonehexact/test_structs.py
+3 −3 ipv8/test/attestation/wallet/irmaexact/test_algorithm.py
+3 −3 ipv8/test/attestation/wallet/irmaexact/test_builder.py
+3 −3 ipv8/test/attestation/wallet/irmaexact/test_credential.py
+2 −3 ipv8/test/attestation/wallet/irmaexact/test_keys.py
+3 −3 ipv8/test/attestation/wallet/irmaexact/test_proofs.py
+2 −3 ipv8/test/attestation/wallet/pengbaorange/test_boudot.py
+2 −3 ipv8/test/attestation/wallet/primitives/test_boneh.py
+2 −3 ipv8/test/attestation/wallet/primitives/test_ec.py
+2 −3 ipv8/test/attestation/wallet/primitives/test_value.py
+1 −1 ipv8/test/attestation/wallet/test_attestation_community.py
+9 −2 ipv8/test/base.py
+9 −1 ipv8/test/dht/test_community.py
+2 −3 ipv8/test/dht/test_storage.py
+2 −3 ipv8/test/keyvault/test_crypto.py
+2 −3 ipv8/test/keyvault/test_serialization.py
+2 −3 ipv8/test/keyvault/test_signature.py
+0 −3 ipv8/test/messaging/anonymization/test_datachecker.py
+2 −3 ipv8/test/messaging/deprecated/test_encoding.py
+2 −3 ipv8/test/messaging/deprecated/test_sorting.py
+5 −5 ipv8/test/messaging/interfaces/udp/test_endpoint.py
+2 −3 ipv8/test/messaging/test_lazy_payload.py
+3 −2 ipv8/test/messaging/test_serialization.py
+1 −1 ipv8/test/peerdiscovery/test_edge_discovery.py
+2 −3 ipv8/test/peerdiscovery/test_network.py
+317 −0 ipv8/test/test_configuration.py
+2 −3 ipv8/test/test_database.py
+2 −3 ipv8/test/test_peer.py
+2 −3 ipv8/test/test_requestcache.py
+2 −1 ipv8/test/test_taskmanager.py
+10 −0 ipv8/util.py
+8 −0 ipv8_service.py
+73 −52 run_all_tests.py
+20 −7 scripts/ipv8_plugin.py
+5 −2 setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,14 @@ def test_get_index_no_metainfo(self):
"""
t = TorrentDef()
self.assertRaises(ValueError, t.get_index_of_file_in_files, u'?')

def test_get_name_as_unicode(self):
name_bytes = b'\xe8\xaf\xad\xe8\xa8\x80\xe5\xa4\x84\xe7\x90\x86'
name_unicode = name_bytes.decode()
t = TorrentDef()
t.metainfo = {b'info': {b'name.utf-8': name_bytes}}
self.assertEqual(t.get_name_as_unicode(), name_unicode)
t.metainfo = {b'info': {b'name': name_bytes}}
self.assertEqual(t.get_name_as_unicode(), name_unicode)
t.metainfo = {b'info': {b'name': b'test\xff' + name_bytes}}
self.assertEqual(t.get_name_as_unicode(), 'test?????????????')
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,10 @@ def get_name_as_unicode(self):
try:
def filter_characters(name):
def filter_character(char):
if 0 < ord(char) < 128:
if 0 < char < 128:
return chr(char)
else:
self._logger.debug("Bad character filter %s, isalnum? %s", bytes(char), char.isalnum())
return u"?"
self._logger.debug("Bad character %s", bytes(char))
return u"?"
return u"".join([filter_character(char) for char in name])
return str(filter_characters(self.metainfo[b"info"][b"name"]))
except UnicodeError:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import asyncio
from asyncio import get_event_loop, wait_for
from asyncio import CancelledError, get_event_loop, wait_for

from ipv8.database import database_blob
from ipv8.taskmanager import TaskManager, task
Expand Down Expand Up @@ -271,8 +271,12 @@ async def download_channel(self, channel):
tdef = TorrentDef(metainfo=metainfo)

download = self.session.dlmgr.start_download(tdef=tdef, config=dcfg, hidden=True)
await download.future_finished
self.channels_processing_queue[channel.infohash] = (PROCESS_CHANNEL_DIR, channel)
try:
await download.future_finished
except CancelledError:
pass
else:
self.channels_processing_queue[channel.infohash] = (PROCESS_CHANNEL_DIR, channel)
return download

async def process_channel_dir_threaded(self, channel):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def test_get_tracker_for_check(self):
self.assertFalse(self.tracker_manager.get_next_tracker_for_auto_check())

self.tracker_manager.add_tracker("http://test1.com:80/announce")
self.assertEqual('http://test1.com/announce', self.tracker_manager.get_next_tracker_for_auto_check())
self.assertEqual('http://test1.com/announce', self.tracker_manager.get_next_tracker_for_auto_check().url)

def test_get_tracker_for_check_blacklist(self):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from tribler_core.modules.torrent_checker.torrent_checker import TorrentChecker
from tribler_core.modules.torrent_checker.torrentchecker_session import HttpTrackerSession, UdpSocketManager
from tribler_core.modules.tracker_manager import TrackerManager
from tribler_core.tests.tools.base_test import MockObject
from tribler_core.tests.tools.test_as_server import TestAsServer
from tribler_core.tests.tools.tools import timeout
from tribler_core.utilities.unicode import hexlify
Expand Down Expand Up @@ -74,7 +75,7 @@ async def test_health_check_blacklisted_trackers(self):
with db_session:
tracker = self.session.mds.TrackerState(url="http://localhost/tracker")
self.session.mds.TorrentState(infohash=b'a' * 20, seeders=5, leechers=10, trackers={tracker},
last_check=int(time.time()))
last_check=int(time.time()))

self.session.tracker_manager.blacklist.append("http://localhost/tracker")
result = await self.torrent_checker.check_torrent_health(b'a' * 20)
Expand All @@ -89,7 +90,7 @@ async def test_health_check_cached(self):
with db_session:
tracker = self.session.mds.TrackerState(url="http://localhost/tracker")
self.session.mds.TorrentState(infohash=b'a' * 20, seeders=5, leechers=10, trackers={tracker},
last_check=int(time.time()))
last_check=int(time.time()))

result = await self.torrent_checker.check_torrent_health(b'a' * 20)
self.assertTrue('db' in result)
Expand All @@ -98,18 +99,48 @@ async def test_health_check_cached(self):

@timeout(10)
async def test_task_select_no_tracker(self):
await self.torrent_checker.check_random_tracker()
"""
Test whether we are not checking a random tracker if there are no trackers in the database.
"""
result = await self.torrent_checker.check_random_tracker()
self.assertFalse(result)

@timeout(10)
async def test_check_random_tracker_shutdown(self):
"""
Test whether we are not performing a tracker check if we are shutting down.
"""
await self.torrent_checker.shutdown()
result = await self.torrent_checker.check_random_tracker()
self.assertFalse(result)

@timeout(10)
async def test_check_random_tracker_not_alive(self):
"""
Test whether we correctly update the tracker state when the number of failures is too large.
"""
with db_session:
self.session.mds.TrackerState(url="http://localhost/tracker", failures=1000, alive=True)

result = await self.torrent_checker.check_random_tracker()
self.assertFalse(result)

with db_session:
tracker = self.session.tracker_manager.tracker_store.get()
self.assertFalse(tracker.alive)

@timeout(10)
async def test_task_select_tracker(self):
with db_session:
tracker = self.session.mds.TrackerState(url="http://localhost/tracker")
self.session.mds.TorrentState(infohash=b'a' * 20, seeders=5, leechers=10, trackers={tracker})

controlled_session = HttpTrackerSession(None, None, None, None)
controlled_session = HttpTrackerSession("127.0.0.1", ("localhost", 8475), "/announce", 5)
controlled_session.connect_to_tracker = lambda: succeed(None)

self.torrent_checker._create_session_for_request = lambda *args, **kwargs: controlled_session
await self.torrent_checker.check_random_tracker()
result = await self.torrent_checker.check_random_tracker()
self.assertFalse(result)

self.assertEqual(len(controlled_session.infohash_list), 1)

Expand All @@ -121,8 +152,9 @@ async def test_tracker_test_error_resolve(self):
with db_session:
tracker = self.session.mds.TrackerState(url="http://localhost/tracker")
self.session.mds.TorrentState(infohash=b'a' * 20, seeders=5, leechers=10, trackers={tracker},
last_check=int(time.time()))
await self.torrent_checker.check_random_tracker()
last_check=int(time.time()))
result = await self.torrent_checker.check_random_tracker()
self.assertFalse(result)

# Verify whether we successfully cleaned up the session after an error
self.assertEqual(len(self.torrent_checker._session_list), 1)
Expand All @@ -133,25 +165,31 @@ async def test_tracker_no_infohashes(self):
Test the check of a tracker without associated torrents
"""
self.session.tracker_manager.add_tracker('http://trackertest.com:80/announce')
await self.torrent_checker.check_random_tracker()
result = await self.torrent_checker.check_random_tracker()
self.assertFalse(result)

def test_get_valid_next_tracker_for_auto_check(self):
""" Test if only valid tracker url is used for auto check """
test_tracker_list = ["http://anno nce.torrentsmd.com:8080/announce",
"http://announce.torrentsmd.com:8080/announce"]
"""
Test if only valid tracker url are used for auto check
"""
mock_tracker_state_invalid = MockObject()
mock_tracker_state_invalid.url = "http://anno nce.torrentsmd.com:8080/announce"
mock_tracker_state_valid = MockObject()
mock_tracker_state_valid.url = "http://announce.torrentsmd.com:8080/announce"
tracker_states = [mock_tracker_state_invalid, mock_tracker_state_valid]

def get_next_tracker_for_auto_check():
return test_tracker_list[0] if test_tracker_list else None
return tracker_states[0] if tracker_states else None

def remove_tracker(tracker_url):
test_tracker_list.remove(tracker_url)
def remove_tracker(_):
tracker_states.remove(mock_tracker_state_invalid)

self.torrent_checker.get_next_tracker_for_auto_check = get_next_tracker_for_auto_check
self.torrent_checker.remove_tracker = remove_tracker

next_tracker_url = self.torrent_checker.get_valid_next_tracker_for_auto_check()
self.assertEqual(len(test_tracker_list), 1)
self.assertEqual(next_tracker_url, "http://announce.torrentsmd.com:8080/announce")
next_tracker = self.torrent_checker.get_valid_next_tracker_for_auto_check()
self.assertEqual(len(tracker_states), 1)
self.assertEqual(next_tracker.url, "http://announce.torrentsmd.com:8080/announce")

def test_on_health_check_completed(self):
tracker1 = 'udp://localhost:2801'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,52 +86,55 @@ async def check_random_tracker(self):
"""
Calling this method will fetch a random tracker from the database, select some torrents that have this
tracker, and perform a request to these trackers.
Return whether the check was successful.
"""
tracker_url = self.get_valid_next_tracker_for_auto_check()
if tracker_url is None:
if self._should_stop:
self._logger.warning("Not performing tracker check since we are shutting down")
return False

tracker = self.get_valid_next_tracker_for_auto_check()
if tracker is None:
self._logger.warning(u"No tracker to select from, skip")
return
return False

self._logger.debug(u"Start selecting torrents on tracker %s.", tracker_url)
self._logger.debug(u"Start selecting torrents on tracker %s.", tracker.url)

# get the torrents that should be checked
with db_session:
tracker = self.tribler_session.mds.TrackerState.get(url=tracker_url)
if not tracker:
return
dynamic_interval = TORRENT_CHECK_RETRY_INTERVAL * (2 ** tracker.failures)
# FIXME: this is a really dumb fix for update_tracker_info not being called in some cases
if tracker.failures >= MAX_TRACKER_FAILURES:
tracker.alive = False
return
self.update_tracker_info(tracker.url, False)
return False
torrents = select(ts for ts in tracker.torrents if ts.last_check + dynamic_interval < int(time.time()))
infohashes = [t.infohash for t in torrents[:MAX_TORRENTS_CHECKED_PER_SESSION]]

if len(infohashes) == 0:
# We have no torrent to recheck for this tracker. Still update the last_check for this tracker.
self._logger.info("No torrent to check for tracker %s", tracker_url)
self.update_tracker_info(tracker_url, True)
return
self._logger.info("No torrent to check for tracker %s", tracker.url)
self.update_tracker_info(tracker.url, True)
return False

try:
session = self._create_session_for_request(tracker_url, timeout=30)
session = self._create_session_for_request(tracker.url, timeout=30)
except MalformedTrackerURLException as e:
# Remove the tracker from the database
self.remove_tracker(tracker_url)
self.remove_tracker(tracker.url)
self._logger.error(e)
return
return False

# We shuffle the list so that different infohashes are checked on subsequent scrape requests if the total
# number of infohashes exceeds the maximum number of infohashes we check.
random.shuffle(infohashes)
for infohash in infohashes:
session.add_infohash(infohash)

self._logger.info(u"Selected %d new torrents to check on tracker: %s", len(infohashes), tracker_url)
self._logger.info(u"Selected %d new torrents to check on tracker: %s", len(infohashes), tracker.url)
try:
await self.connect_to_tracker(session)
return True
except:
pass
return False

async def connect_to_tracker(self, session):
try:
Expand Down Expand Up @@ -174,20 +177,20 @@ def check_random_torrent(self):
return [bytes(random_torrent.infohash)]

def get_valid_next_tracker_for_auto_check(self):
tracker_url = self.get_next_tracker_for_auto_check()
while tracker_url and not is_valid_url(tracker_url):
self.remove_tracker(tracker_url)
tracker_url = self.get_next_tracker_for_auto_check()
return tracker_url
tracker = self.get_next_tracker_for_auto_check()
while tracker and not is_valid_url(tracker.url):
self.remove_tracker(tracker.url)
tracker = self.get_next_tracker_for_auto_check()
return tracker

def get_next_tracker_for_auto_check(self):
return self.tribler_session.tracker_manager.get_next_tracker_for_auto_check()

def remove_tracker(self, tracker_url):
self.tribler_session.tracker_manager.remove_tracker(tracker_url)

def update_tracker_info(self, tracker_url, value):
self.tribler_session.tracker_manager.update_tracker_info(tracker_url, value)
def update_tracker_info(self, tracker_url, is_successful):
self.tribler_session.tracker_manager.update_tracker_info(tracker_url, is_successful)

def is_blacklisted_tracker(self, tracker_url):
return tracker_url in self.tribler_session.tracker_manager.blacklist
Expand Down
2 changes: 1 addition & 1 deletion src/tribler-core/tribler_core/modules/tracker_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,4 @@ def get_next_tracker_for_auto_check(self):

if not tracker:
return None
return tracker[0].url
return tracker[0]
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ def start_anon_download(self, hops=1):
"""
Start an anonymous download in the main Tribler session.
"""
self.session.config.set_libtorrent_dht_readiness_timeout(0)
dscfg = DownloadConfig()
dscfg.set_dest_dir(self.getDestDir())
dscfg.set_hops(hops)
Expand Down
2 changes: 1 addition & 1 deletion src/tribler-core/tribler_core/restapi/debug_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,4 +339,4 @@ async def start_profiler(self, request):
)
async def stop_profiler(self, request):
file_path = self.session.resource_monitor.stop_profiler()
return RESTResponse({"success": True, "profiler_file": file_path})
return RESTResponse({"success": True, "profiler_file": str(file_path)})
16 changes: 11 additions & 5 deletions src/tribler-core/tribler_core/tests/test_session.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from asyncio import get_event_loop
from asyncio import get_event_loop, sleep
from binascii import unhexlify
from unittest.mock import Mock

Expand Down Expand Up @@ -63,7 +63,7 @@ def function_that_triggers_exception():
self.assertTrue("function_that_triggers_exception" in m.call_args[0][0])
self.assertTrue("foobar" in m.call_args[0][0])

def test_error_observer_ignored_error(self):
async def test_error_observer_ignored_error(self):
"""
Testing whether some errors are ignored (like socket errors)
"""
Expand All @@ -78,19 +78,25 @@ def gen_except():
raise exception

get_event_loop().call_soon(gen_except)
self.loop._run_once()

exceptions_list = [exc_class(errno, "exc message") for exc_class, errno in IGNORED_ERRORS.keys()]
exceptions_list.append(RuntimeError(0, "invalid info-hash"))

for exception in exceptions_list:
generate_exception_on_reactor(exception)

# Even though we could have used _run_once instead of a sleep, it seems that _run_once does not always
# immediately clean the reactor, leading to a possibility that the test starts to shut down before the exception
# is raised.
await sleep(0.05)

self.session.api_manager.get_endpoint('state').on_tribler_exception.assert_not_called()
self.session.api_manager.get_endpoint('events').on_tribler_exception.assert_not_called()

# This is a "canary" to test that we can handle true exceptions
get_event_loop().call_soon(getaddrinfo, "dfdfddfd23424fdfdf", 2323)
self.loop._run_once()

await sleep(0.05)

self.session.api_manager.get_endpoint('state').on_tribler_exception.assert_not_called()
self.session.api_manager.get_endpoint('events').on_tribler_exception.assert_not_called()
Expand All @@ -100,7 +106,7 @@ def real_raise():
raise Exception()

get_event_loop().call_soon(real_raise)
self.loop._run_once()
await sleep(0.05)
self.session.api_manager.get_endpoint('state').on_tribler_exception.assert_called_once()
self.session.api_manager.get_endpoint('events').on_tribler_exception.assert_called_once()

Expand Down
5 changes: 3 additions & 2 deletions src/tribler-gui/tribler_gui/core_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ def __init__(self, api_port, api_key):

def on_core_read_ready(self):
raw_output = bytes(self.core_process.readAll())
decoded_output = raw_output.decode(errors="replace")
if b'Traceback' in raw_output:
self.core_traceback = raw_output.decode()
print(raw_output.decode().strip())
self.core_traceback = decoded_output
print(decoded_output.strip())

def on_core_finished(self, exit_code, exit_status):
if self.shutting_down and self.should_stop_on_shutdown:
Expand Down
Loading

0 comments on commit fd748af

Please sign in to comment.