tests.rs
Overview
This file provides a comprehensive suite of tests and supporting functions for verifying the functionality and integration of the msquic-based QUIC transport implementation. It includes utilities to initialize logging, generate test credentials, and run various asynchronous integration and unit tests. The tests cover connection establishment, TLS credential validation, message sending and receiving, and low-level stream reading behavior. The file leverages both the msquic crate and the higher-level transport abstractions defined elsewhere in the project to validate inter-component behavior.
Detailed Explanations
Static Variables
LOG_INIT
AOnceCell<()>instance used to ensure that logging initialization happens exactly once during test execution, avoiding duplicate logger setups.
Functions
init_logs()
Initializes the logging subsystem for test runs.
Behavior:
Uses tracing_subscriber to set up a formatted logger with environment-based filtering (EnvFilter::from_default_env()) and directs logs to the test output (with_test_writer()).Usage:
Call at the start of async tests that require logging for debug output.Example:
#[tokio::test] async fn example_test() { init_logs(); // test logic here }
get_test_cred() -> Credential
Generates or loads a self-signed test TLS credential using OpenSSL CLI.
Behavior:
Checks for existing PEM files (
key.pemandcert.pem) in a temporary directory (temp_dir()/msquic_test_rs).If missing, it creates the directory and generates a new RSA 4096-bit self-signed certificate valid for 10 years using
opensslCLI.Returns a
Credential::CertificateFilereferencing the generated key and cert files.
Usage:
Provides a ready-to-usemsquic::Credentialfor test connections requiring TLS authentication.Notes:
Utilizesstd::process::Commandto invoke external OpenSSL commands, which requires OpenSSL installed on the test machine.Example:
let cred = get_test_cred();
Module: unit_tests
Contains multiple asynchronous and synchronous tests validating the transport layer and utility functions.
Async Test: test_msquic_transport()
Purpose:
Validates full client-server connection lifecycle usingMsQuicTransport, including ALPN negotiation, identity verification, and message exchange.Setup:
Generates server and client credentials with trusted keys.
Starts a server listener on localhost:5555.
Runs client connection to the server.
Sends a "hello" message from client to server and verifies reception.
Key Assertions:
Client's identity matches remote identity on the server side.
ALPN protocol negotiated matches expected protocols.
Correct message content is received.
Test Attribute:
Marked#[ignore]to exclude from normal test runs, likely due to network or environment dependencies.
Struct: CertTest
Purpose:
Encapsulates certificate trust scenarios for client and server, testing mutual TLS trust and message sending direction.Fields:
server_trusted: bool— Whether the server trusts the client's public key.client_trusted: bool— Whether the client trusts the server's public key.server_send: bool— Whether the server initiates sending the message.
Method:
run(self) -> impl Future
Runs the test scenario by setting up credentials with trust based on the fields, spawning server and client tasks, and exchanging messages accordingly.Functionality:
Tests different trust configurations and validates successful or failed connection/message exchanges accordingly.Usage Example:
CertTest { server_trusted: true, client_trusted: false, server_send: true }.run().await;
Async Test: test_cert_rejection()
Purpose:
Executes multipleCertTestscenarios with varying combinations of client/server trust and message directions to verify correct certificate rejection or acceptance behavior.Test Attribute:
Marked#[ignore].
Async Test: test_example_raw_msquick_async()
Purpose:
Demonstrates usage of the lower-levelmsquic_asyncAPI directly, including creating a listener, accepting connections, and sending data over unidirectional streams.Behavior:
Sets up a server listener with a self-signed credential.
Spawns a thread that creates a client connection to the server.
Client sends a "hello" message on a unidirectional stream.
Server reads the message and asserts correctness.
Notes:
Shows interaction withmsquic_async::Listenerandmsquic_async::Connectionand use of Tokio runtime within a thread.
Struct: MockAsyncReader
Purpose:
A mock implementation oftokio::io::AsyncReadused to simulate asynchronous stream reading in tests of theread_message_from_streamfunction.Fields:
chunks: Vec<Bytes>— Data chunks to be read sequentially.current: usize— Index of current chunk.offset: usize— Offset within the current chunk.
Implementation:
Implementspoll_readto provide data chunk by chunk, allowing tests to simulate fragmented or partial reads.
Function: create_transport_message(payload: &[u8]) -> Vec<u8>
Purpose:
Helper to create a length-prefixed transport message where the first 4 bytes represent the length of the payload in big-endian order.Usage:
Used to prepare test data for stream reading tests.Example:
let msg = create_transport_message(b"hello");
Async Tests for read_message_from_stream
These tests validate the behavior of the read_message_from_stream function under various conditions:
test_read_complete_message_in_one_chunk()
Reads a complete message provided in a single chunk.test_read_message_in_multiple_chunks()
Reads a message split across multiple chunks.test_read_empty_message()
Reads a message with an empty payload.test_zero_reads()
Simulates a reader that intermittently returns zero bytes read to verify robustness.
Synchronous Test: test_cert()
Purpose:
Validates creation ofNetCredentialand construction of a server configuration using it.Behavior:
Usesrcgento generate a self-signed certificate and key, wraps it inNetCredential, and builds a config withConfigFactory.Output:
Prints "ok" on success.
Important Implementation Details and Algorithms
Credential Generation:
Theget_test_credfunction uses the OpenSSL command-line tool to generate test certificates dynamically if not present. This approach leverages external tooling for cryptographic operations instead of pure Rust implementations.Async Stream Reading:
TheMockAsyncReaderand tests forread_message_from_streamsimulate how partial data arrival is handled, ensuring that the message length prefix is correctly parsed and the full payload is buffered before returning.Concurrent Task Management:
Tests usetokio::task::JoinSetto concurrently run server and client tasks and await their completion, facilitating end-to-end asynchronous testing of connection establishment and message exchange.Certificate Trust Simulation:
TheCertTeststruct manipulates trusted public keys on client and server credentials to simulate trust and mistrust scenarios, testing TLS mutual authentication rejection/acceptance paths.
Interaction with Other Parts
Relies on
msquiccrate types and primitives (Credential,Registration,Configuration, etc.) for QUIC and TLS-related operations.Uses
MsQuicTransport,NetCredential,NetConnection, and related abstractions presumably defined in the same crate or module to perform higher-level QUIC transport testing.Calls
read_message_from_streamfrom the crate's msquic module to test message reading behavior on asynchronous streams.Uses
ConfigFactoryto build client and server QUIC configurations for tests.Interacts with Tokio runtime and asynchronous primitives for concurrency and async IO testing.
Depends on external OpenSSL CLI for certificate generation in the testing environment.
Visual Diagram of the File Structure and Main Functions
flowchart TD
init_logs --> get_test_cred
get_test_cred --> test_msquic_transport
test_msquic_transport --> CertTest
CertTest --> test_cert_rejection
test_example_raw_msquick_async --> MockAsyncReader
MockAsyncReader --> create_transport_message
create_transport_message --> test_read_complete_message_in_one_chunk
create_transport_message --> test_read_message_in_multiple_chunks
create_transport_message --> test_read_empty_message
create_transport_message --> test_zero_reads
test_cert
classDef testfill fill:#f9f,stroke:#333,stroke-width:1px,color:#000
class init_logs,get_test_cred,test_msquic_transport,CertTest,test_cert_rejection,test_example_raw_msquick_async,MockAsyncReader,create_transport_message,test_read_complete_message_in_one_chunk,test_read_message_in_multiple_chunks,test_read_empty_message,test_zero_reads,test_cert testfill
Notation of Main Entities in Diagram
init_logs: Logging initialization function.
get_test_cred: Generates or loads test TLS credentials.
test_msquic_transport: Integration test of MsQuicTransport client-server communication.
CertTest: Struct encapsulating certificate trust scenarios and test runner.
test_cert_rejection: Runs multiple CertTest configurations.
test_example_raw_msquick_async: Low-level async msquic usage test.
MockAsyncReader: Mock AsyncRead implementation for stream tests.
create_transport_message: Helper to create length-prefixed messages.
test_read_*: Tests validating message reading under various conditions.
test_cert: Synchronous test of certificate creation and config building.