Skip to content

vincentdephily/mqttest

Repository files navigation

MQTT test server

Mqttest is an MQTT server designed for unittesting clients.

Compared to a standard server like Mosquitto, Mqttest brings a CI-friendly binary, fast RC-free tests, detailed machine-readable packet dumps, network problem simulations, selectable implementaion quirks, running the server as a library, etc.

Initial development has been sponsored by Munic.

Current and planned features

  • Simplified CI image
    • Automatic open port discovery (simplifies parallel test execution)
    • Statically-built single-file CLI binary (no runtime deps or fancy install)
    • Use as a rust library
      • Decode file dumps to rust structs
      • Configure and start server
      • Runtime server control and client interaction using rust channels
      • Return dumps and stats after each run
    • Use as a library from other languages
  • Verbose log file and network dump
    • No need for RC-prone connection of an observer client
    • Json dump of mqtt packet data and metadata (time, connection id...)
    • Global or per-connection dump filename
    • Flexible payload decoding
  • Controllable connection behaviors:
    • Ack delay
    • Close connection after a number of packets or a timeout
    • Go offline
    • Bad packet flow (spurious/missing ack/publish)
    • Override session lifetime
    • Reject clients by id or password
    • Different pid-assignment strategies
    • Different behavior for subsequent connections
    • Stop server after a number of connections
    • Stop server after a max runtime
    • Your useful behavior here
  • Protocol support
    • MQTT 3.1.1
    • MQTT 5
    • IPv6
    • TLS
    • Warn about or reject extended client identifiers
    • Warn about MQTT3 idioms obsoletted by MQTT5
    • Documentation highlights MQTT implementation gotchas

Some "missing" features may already be partially implemented. They will be marked as done when fully done.

Non-features

  • Codec-level errors (better to unittest this at the codec library level).
  • Wildcard topics (at least for now - not useful ?).
  • Database or clustering support (offtopic).
  • High performance/scalability (though aim to be small and fast).

Usage

Install Rust >= 1.39.0 if necessary.

Standalone binary

# Build and install the executable
cargo install --path .

# See help
mqttest -h

Mqttest starts in just a few milliseconds. You can start a server with a different behaviour for each of your client unittest. Or you can start a single instance and leave it running while you do some ad-hoc testing.

Rust library

In your Cargo.toml:

[dev-dependencies]
# MQTT test server.
mqttest = { version = "0.2.0", default-features = false }
# mqttest needs to be started from a tokio async context.
tokio = "0.2"
# At your discretion, if you want to see server logs.
env_logger = "0.7"

In your unittests (see test.rs for more detailed examples) :

/// Boiler-plate to run and log async code from a unittest.
fn block_on<T>(f: impl Future<Output = T>) -> T {
    let _ = env_logger::builder().is_test(true).parse_filters("debug").try_init();
    tokio::runtime::Builder::new().basic_scheduler().enable_all().build().unwrap().block_on(f)
}

/// Example unittest. Bring your own client.
#[test]
fn connect() {
    let stats = block_on(async {
        // Create a server config
        let conf = Conf::new().max_connect(1);
        // Start the server
        let srv = Mqttest::start(conf).await.expect("Failed listen").await;
        // Start your client on the port that the server selected
        client::start(srv.port).await.expect("Client failure");
        // Wait for the server to finish
        srv.finish().await.unwrap()
    });
    // Check run results
    assert_eq!(1, stats.conn_count);
}

Optional features

cli

Required to build the binary (as opposed to the library). Enabled by default.

About

An MQTT server designed for unittesting MQTT clients.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages