Testing against PocketSCION
PocketSCION is a SCION network in one process. The SDK examples run on it, as Getting started shows. An application can use it in its tests too. To add it to your crate, see Add the SDK to your own project.
The chat has one test that runs its server and its Rust client on a PocketSCION network, in two
different ASes:
tests/scion.rs.
The fixture
The fixture starts the network, puts the server in one AS, and returns a client that is attached to the other AS:
/// Starts two ASes, puts the server in one, and returns a client attached to the other.
async fn fixture() -> Fixture {
let network = minimal_topology(UnderlayType::Snap).await;
let client_api = network
.endhost_api(IA132)
.expect("the client's endhost api");
let server_api = network
.endhost_api(IA212)
.expect("the server's endhost api");
let data = TempDir::new().expect("a temporary directory");
let auth_token_file = data.path().join("snap.token");
std::fs::write(&auth_token_file, dev_auth_token()).expect("the token is written");
// Made before the server starts, so the path the client pins is the one the server presents.
let certificate = cert::ServerCert::load_or_create(data.path()).expect("a certificate");
let shutdown = CancellationToken::new();
let (host, port) = serve(
data.path(),
server_api.as_ref(),
&auth_token_file,
&shutdown,
)
.await;
let client = ChatClient::new(ClientConfig {
transport: TransportKind::Scion(ScionConfig {
endhost_api: client_api.to_string().parse().expect("an endhost api"),
credential: Credential::Token(SnapToken::new(dev_auth_token())),
// This topology has no TSAR records.
target: Some(host),
trust: Trust::Pinned(certificate.cert_path.clone()),
}),
server_url: format!("https://{}:{port}", cert::SERVER_NAME)
.parse()
.expect("a server url"),
poll: PollConfig::default(),
})
.await
.expect("a client");
await_ready(&client).await;
Fixture {
client,
_network: network,
_data: data,
shutdown,
}
}
minimal_topologystarts two ASes,1-ff00:0:132and2-ff00:0:212, with one link. Getting started shows the same network.endhost_apireturns the endhost API of an AS. The server uses the endhost API ofIA212, and the client uses the endhost API ofIA132.dev_auth_tokenreturns a token that PocketSCION accepts. The server reads the token from a file, and the client gets it as aCredential::Token.- The test makes the certificate before the server starts. Thus the client pins the certificate that the server presents.
- The network has no TSAR records, so the client gets the address of the server as
target. await_readysends health requests until the server answers. The server binds its socket before it reads from the socket, so the first requests can get lost.
The serve helper in the same file binds the server on port 0, and then reads the port that the
socket got. It gives the host and the port to the fixture, for the client.
The test
The test uses the client in the same way as the app does:
/// The acceptance criterion: everything the client does works with a SCION network under it, and
/// what was written in one AS reads back from another.
#[tokio::test(flavor = "multi_thread")]
async fn the_client_holds_a_conversation_over_scion() {
let fixture = fixture().await;
let client = &fixture.client;
let info = client
.server_info()
.await
.expect("the server describes itself");
assert_eq!(info.max_message_bytes, 4096);
client
.register("ada", "a password")
.await
.expect("an account");
client.login("ada", "a password").await.expect("a session");
let room = client.create_room("general").await.expect("a room");
client.send(room.id, "across the link").await.expect("sent");
let seen: Vec<(String, String)> = client
.messages_newest(room.id, 10)
.await
.expect("the room reads back")
.into_iter()
.map(|message| (message.username, message.body))
.collect();
assert_eq!(seen, [("ada".to_owned(), "across the link".to_owned())]);
}
The test reads the server information, registers a user, logs in, creates a room and sends a message. Then it reads the room and compares the message. Each request goes from the AS of the client to the AS of the server, so the test covers the SCION code of the server and of the client.
When the test ends, it drops the fixture. The fixture then cancels its CancellationToken, and the
server stops.
A larger network
chat-dev builds a network of three ASes from the same building blocks as minimal_topology: a
topology, and an endhost API and a SNAP for each AS.
From a local SCION network to a real network shows
the code.
Where to go next
- PocketSCION: the other topologies and underlays that you can simulate.
- The chat application: the other pages of this section.