refactor
This commit is contained in:
parent
df8ed1748e
commit
2a36b48d50
|
@ -48,16 +48,6 @@ class Node(ABC, Generic[TNetworkHandle, TInitialMetadata]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FileSharingNetwork(Generic[TNetworkHandle, TInitialMetadata], ABC):
|
|
||||||
"""A :class:`FileSharingNetwork` is a set of :class:`Node`s that share
|
|
||||||
an interest in a given file."""
|
|
||||||
|
|
||||||
@property
|
|
||||||
@abstractmethod
|
|
||||||
def nodes(self) -> Sequence[Node[TNetworkHandle, TInitialMetadata]]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class SharedFSNode(Node[TNetworkHandle, TInitialMetadata], ABC):
|
class SharedFSNode(Node[TNetworkHandle, TInitialMetadata], ABC):
|
||||||
"""A `SharedFSNode` is a :class:`Node` which shares a network volume with us. This means
|
"""A `SharedFSNode` is a :class:`Node` which shares a network volume with us. This means
|
||||||
we are able to upload files to it by means of simple file copies."""
|
we are able to upload files to it by means of simple file copies."""
|
||||||
|
|
|
@ -6,7 +6,28 @@ from typing import Generator
|
||||||
import pytest
|
import pytest
|
||||||
from urllib3.util import Url, parse_url
|
from urllib3.util import Url, parse_url
|
||||||
|
|
||||||
|
from benchmarks.core.deluge import DelugeNode
|
||||||
from benchmarks.core.utils import megabytes
|
from benchmarks.core.utils import megabytes
|
||||||
|
from benchmarks.tests.utils import shared_volume
|
||||||
|
|
||||||
|
|
||||||
|
def deluge_node(name: str, port: int) -> Generator[DelugeNode, None, None]:
|
||||||
|
node = DelugeNode(name, volume=shared_volume(), daemon_port=port)
|
||||||
|
node.wipe_all_torrents()
|
||||||
|
try:
|
||||||
|
yield node
|
||||||
|
finally:
|
||||||
|
node.wipe_all_torrents()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def deluge_node1() -> Generator[DelugeNode, None, None]:
|
||||||
|
yield from deluge_node('deluge-1', 6890)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def deluge_node2() -> Generator[DelugeNode, None, None]:
|
||||||
|
yield from deluge_node('deluge-2', 6893)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|
|
@ -1,31 +1,9 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Generator
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from urllib3.util import Url
|
from urllib3.util import Url
|
||||||
|
|
||||||
from benchmarks.core.deluge import DelugeNode, DelugeMeta
|
from benchmarks.core.deluge import DelugeNode, DelugeMeta
|
||||||
from benchmarks.core.utils import megabytes
|
from benchmarks.core.utils import megabytes
|
||||||
from benchmarks.tests.utils import shared_volume
|
|
||||||
|
|
||||||
|
|
||||||
def deluge_node(name: str, port: int) -> Generator[DelugeNode, None, None]:
|
|
||||||
node = DelugeNode(name, volume=shared_volume(), daemon_port=port)
|
|
||||||
node.wipe_all_torrents()
|
|
||||||
try:
|
|
||||||
yield node
|
|
||||||
finally:
|
|
||||||
node.wipe_all_torrents()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def deluge_node1() -> Generator[DelugeNode, None, None]:
|
|
||||||
yield from deluge_node('deluge-1', 6890)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def deluge_node2() -> Generator[DelugeNode, None, None]:
|
|
||||||
yield from deluge_node('deluge-2', 6893)
|
|
||||||
|
|
||||||
|
|
||||||
def test_should_seed_files(deluge_node1: DelugeNode, temp_random_file: Path, tracker: Url):
|
def test_should_seed_files(deluge_node1: DelugeNode, temp_random_file: Path, tracker: Url):
|
||||||
|
@ -44,7 +22,6 @@ def test_should_seed_files(deluge_node1: DelugeNode, temp_random_file: Path, tra
|
||||||
def test_should_download_files(
|
def test_should_download_files(
|
||||||
deluge_node1: DelugeNode, deluge_node2: DelugeNode,
|
deluge_node1: DelugeNode, deluge_node2: DelugeNode,
|
||||||
temp_random_file: Path, tracker: Url):
|
temp_random_file: Path, tracker: Url):
|
||||||
|
|
||||||
assert not deluge_node1.torrent_info(name='dataset1')
|
assert not deluge_node1.torrent_info(name='dataset1')
|
||||||
assert not deluge_node2.torrent_info(name='dataset1')
|
assert not deluge_node2.torrent_info(name='dataset1')
|
||||||
|
|
||||||
|
@ -59,4 +36,4 @@ def test_should_download_files(
|
||||||
|
|
||||||
assert info[b'name'] == b'dataset1'
|
assert info[b'name'] == b'dataset1'
|
||||||
assert info[b'total_size'] == megabytes(1)
|
assert info[b'total_size'] == megabytes(1)
|
||||||
assert info[b'is_seed'] == True
|
assert info[b'is_seed'] == True
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
from typing_extensions import Generic
|
from typing_extensions import Generic, List
|
||||||
|
|
||||||
from benchmarks.core.network import FileSharingNetwork, TInitialMetadata, TNetworkHandle
|
from benchmarks.core.network import TInitialMetadata, TNetworkHandle, Node
|
||||||
from benchmarks.core.utils import Sampler, DataGenerator
|
from benchmarks.core.utils import Sampler, DataGenerator
|
||||||
|
|
||||||
|
|
||||||
class StaticDisseminationExperiment(Generic[TNetworkHandle, TInitialMetadata]):
|
class StaticDisseminationExperiment(Generic[TNetworkHandle, TInitialMetadata]):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
network: FileSharingNetwork[TNetworkHandle, TInitialMetadata],
|
network: List[Node[TNetworkHandle, TInitialMetadata]],
|
||||||
seeders: int,
|
seeders: int,
|
||||||
sampler: Sampler,
|
sampler: Sampler,
|
||||||
generator: DataGenerator
|
generator: DataGenerator
|
||||||
):
|
):
|
||||||
self.network = network
|
self.nodes = network
|
||||||
self.sampler = sampler
|
self.sampler = sampler
|
||||||
self.generate_data = generator
|
self.generate_data = generator
|
||||||
self.seeders = seeders
|
self.seeders = seeders
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
sample = self.sampler(len(self.network.nodes))
|
sample = self.sampler(len(self.nodes))
|
||||||
seeder_indexes = [next(sample) for _ in range(0, self.seeders)]
|
seeder_indexes = [next(sample) for _ in range(0, self.seeders)]
|
||||||
seeders, leechers = (
|
seeders, leechers = (
|
||||||
[
|
[
|
||||||
self.network.nodes[i]
|
self.nodes[i]
|
||||||
for i in seeder_indexes
|
for i in seeder_indexes
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
self.network.nodes[i]
|
self.nodes[i]
|
||||||
for i in range(0, len(self.network.nodes))
|
for i in range(0, len(self.nodes))
|
||||||
if i not in seeder_indexes
|
if i not in seeder_indexes
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,7 +2,7 @@ from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, List, Tuple, Union, Sequence
|
from typing import Optional, List, Tuple, Union, Sequence
|
||||||
|
|
||||||
from benchmarks.core.network import FileSharingNetwork, Node, DownloadHandle
|
from benchmarks.core.network import Node, DownloadHandle
|
||||||
from benchmarks.core.utils import Sampler
|
from benchmarks.core.utils import Sampler
|
||||||
from benchmarks.experiments.static_experiment import StaticDisseminationExperiment
|
from benchmarks.experiments.static_experiment import StaticDisseminationExperiment
|
||||||
|
|
||||||
|
@ -50,18 +50,12 @@ class MockDownloadHandle(DownloadHandle):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class MockFileSharingNetwork(FileSharingNetwork[MockHandle, str]):
|
def mock_network(n: int) -> List[MockNode]:
|
||||||
|
return [MockNode() for _ in range(n)]
|
||||||
def __init__(self, n: int) -> None:
|
|
||||||
self._nodes = [MockNode() for _ in range(n)]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def nodes(self) -> Sequence[Node[MockHandle, str]]:
|
|
||||||
return self._nodes
|
|
||||||
|
|
||||||
|
|
||||||
def test_should_place_seeders():
|
def test_should_place_seeders():
|
||||||
network = MockFileSharingNetwork(n=13)
|
network = mock_network(n=13)
|
||||||
file = Path('/path/to/data')
|
file = Path('/path/to/data')
|
||||||
seeder_indexes = [9, 6, 3]
|
seeder_indexes = [9, 6, 3]
|
||||||
|
|
||||||
|
@ -75,7 +69,7 @@ def test_should_place_seeders():
|
||||||
experiment.run()
|
experiment.run()
|
||||||
|
|
||||||
actual_seeders = set()
|
actual_seeders = set()
|
||||||
for index, node in enumerate(network.nodes):
|
for index, node in enumerate(network):
|
||||||
if node.seeding is not None:
|
if node.seeding is not None:
|
||||||
actual_seeders.add(index)
|
actual_seeders.add(index)
|
||||||
assert node.seeding[0] == MockHandle(name='data', path=file)
|
assert node.seeding[0] == MockHandle(name='data', path=file)
|
||||||
|
@ -84,7 +78,7 @@ def test_should_place_seeders():
|
||||||
|
|
||||||
|
|
||||||
def test_should_download_at_remaining_nodes():
|
def test_should_download_at_remaining_nodes():
|
||||||
network = MockFileSharingNetwork(n=13)
|
network = mock_network(n=13)
|
||||||
file = Path('/path/to/data')
|
file = Path('/path/to/data')
|
||||||
seeder_indexes = [9, 6, 3]
|
seeder_indexes = [9, 6, 3]
|
||||||
|
|
||||||
|
@ -98,7 +92,7 @@ def test_should_download_at_remaining_nodes():
|
||||||
experiment.run()
|
experiment.run()
|
||||||
|
|
||||||
actual_leechers = set()
|
actual_leechers = set()
|
||||||
for index, node in enumerate(network.nodes):
|
for index, node in enumerate(network):
|
||||||
if node.leeching is not None:
|
if node.leeching is not None:
|
||||||
assert node.leeching.path == file
|
assert node.leeching.path == file
|
||||||
assert node.leeching.name == 'data'
|
assert node.leeching.name == 'data'
|
||||||
|
|
Loading…
Reference in New Issue