If you want to extend the Ziggurat test suite, we suggest starting with a pull request that includes

  1. The code for the test itself
  2. A specification in the description that includes what the test does, and why the test is beneficial to a node implementer. See the test index for examples of test spec.

Test Code

Ziggurat tests must be written as regular Rust tests, and must be included in the test folder of the project. Tests should fall into one of the three categories we defined: Conformance, Performance, and Resistance.

To simplify implementation, the tests can follow a similar structure to the following:

#[tokio::test]
async fn handshake_responder_side() {
    // ZG-CONFORMANCE-001

    // Spin up a node instance.
    let mut node = Node::new().unwrap();
    node.initial_action(Action::WaitForConnection)
        .start()
        .await
        .unwrap();

    // Create a synthetic node and enable handshaking.
    let synthetic_node = SyntheticNode::builder()
        .with_full_handshake()
        .build()
        .await
        .unwrap();

    // Connect to the node and initiate the handshake.
    synthetic_node.connect(node.addr()).await.unwrap();

    // This is only set post-handshake (if enabled).
    assert!(synthetic_node.is_connected(node.addr()));

    // Gracefully shut down the nodes.
    synthetic_node.shut_down();
    node.stop().await.unwrap();
}

Notes on the above:

Test Specification

A Ziggurat test specification must include a short description of what the test does and why it is needed, followed by a step by step description of the test steps.

The specification must not include a test index designation, as that will be assigned upon merging of the PR.

For example, here is the spec for ZG-CONFORMANCE-006:

The node rejects connections reusing its nonce (usually indicative of self-connection).

  1. The node under test initiates a connection (rpc: addnode).
  2. Respond to received Version with the node’s nonce.