1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use std::sync::Arc;
use sia_core::signing::{PrivateKey, PublicKey};
use sia_core::types::v2::{NetAddress, Protocol};
use crate::rhp4::{Client, mock};
use crate::time::Duration;
use crate::{AppKey, BuilderError, Host, Sdk, app_client};
/// An in-memory Sia network: a mock indexer paired with a mock host transport.
///
/// [`MockNetwork::sdk`] builds a real [`Sdk`] against them, so tests drive the
/// same public API an application uses rather than a parallel mock surface.
pub struct MockNetwork {
api: app_client::mock::Client,
transport: mock::Client,
}
impl MockNetwork {
pub fn new() -> Self {
Self {
api: app_client::mock::Client::new(),
transport: mock::Client::new(),
}
}
/// Adds `n` hosts that are usable for uploads and returns their keys.
///
/// Hosts must be added before [`MockNetwork::sdk`]; the SDK reads the
/// indexer's host list when it is created and then on a long interval.
pub fn add_hosts(&self, n: usize) -> Vec<PublicKey> {
let hosts: Vec<Host> = (0..n)
.map(|_| Host {
public_key: PrivateKey::from_seed(&rand::random::<[u8; 32]>()).public_key(),
addresses: vec![NetAddress {
protocol: Protocol::QUIC,
address: "localhost:9984".to_string(),
}],
country_code: "US".to_string(),
latitude: 0.0,
longitude: 0.0,
good_for_upload: true,
})
.collect();
let keys = hosts.iter().map(|h| h.public_key).collect();
self.api.add_hosts(hosts);
keys
}
/// Sets the given hosts as "slow" - they will sleep for the specified
/// duration before completing any write_sector or read_sector operation.
pub fn set_slow_hosts(&self, hosts: impl IntoIterator<Item = PublicKey>, delay: Duration) {
self.transport.set_slow_hosts(hosts, delay);
}
/// Clears all slow host settings.
pub fn reset_slow_hosts(&self) {
self.transport.reset_slow_hosts();
}
/// Discards every sector stored by the hosts. The indexer's objects and
/// slabs are untouched, so anything pinned before this becomes
/// undownloadable.
pub fn clear_sectors(&self) {
self.transport.clear();
}
/// The number of slabs currently pinned to the mock indexer.
pub fn pinned_slabs(&self) -> usize {
self.api.pinned_slabs()
}
/// Builds an [`Sdk`] backed by this network.
pub async fn sdk(&self, app_key: AppKey) -> Result<Sdk, BuilderError> {
Sdk::with_backends(
app_client::Client::Mock(self.api.clone()),
Client::Mock(self.transport.clone()),
Arc::new(app_key),
)
.await
}
}
impl Default for MockNetwork {
fn default() -> Self {
Self::new()
}
}