Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions crates/smoketests/DEVELOP.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ cargo smoketest

This command:
1. Builds `spacetimedb-cli` and `spacetimedb-standalone` binaries
2. Runs all smoketests in parallel using nextest (or cargo test if nextest isn't installed)
2. Builds the Rust fixture workspace in `crates/smoketests/modules/` to WASM
3. Runs all smoketests in parallel using nextest (or cargo test if nextest isn't installed)

To run specific tests:
```bash
Expand Down Expand Up @@ -51,7 +52,8 @@ cargo smoketest

# Option 2: Manually rebuild, then run tests directly
cargo build -p spacetimedb-cli -p spacetimedb-standalone --features spacetimedb-standalone/allow_loopback_http_for_tests
cargo nextest run -p spacetimedb-smoketests
cargo build --manifest-path crates/smoketests/modules/Cargo.toml --workspace --release --target wasm32-unknown-unknown
CARGO_BUILD_PROFILE=debug cargo nextest run -p spacetimedb-smoketests
```

**If you run `cargo nextest run` or `cargo test` directly without rebuilding,
Expand All @@ -75,44 +77,46 @@ Standard `cargo test` also works, but you must rebuild first:

```bash
cargo build -p spacetimedb-cli -p spacetimedb-standalone --features spacetimedb-standalone/allow_loopback_http_for_tests
cargo test -p spacetimedb-smoketests
cargo build --manifest-path crates/smoketests/modules/Cargo.toml --workspace --release --target wasm32-unknown-unknown
CARGO_BUILD_PROFILE=debug cargo test -p spacetimedb-smoketests
```

## Test Performance

Each test takes ~15-20s due to:
- **WASM compilation** (~12s): Each test compiles a fresh Rust module to WASM
- **Server spawn** (~2s): Each test starts its own SpacetimeDB server
- **Module publish** (~2s): Server processes and initializes the WASM module
Rust fixtures are compiled once during warmup and reused across tests. Ordinary
tests then start a server and publish the selected WASM without invoking Cargo.
Tests of build diagnostics explicitly compile temporary modules.

When running tests in parallel, resource contention increases individual test times but reduces overall runtime.

## Writing Tests

See existing tests for patterns. Key points:
Add a fixture crate under `crates/smoketests/modules/`, following an existing
crate's `Cargo.toml` and `src/lib.rs`, and list it in that workspace's members.
The package name `smoketest-module-example` makes it available as `example`:

```rust
use spacetimedb_smoketests::Smoketest;

const MODULE_CODE: &str = r#"
use spacetimedb::{ReducerContext, Table};

#[spacetimedb::table(accessor = example, public)]
pub struct Example { value: u64 }

#[spacetimedb::reducer]
pub fn add(ctx: &ReducerContext, value: u64) {
ctx.db.example().insert(Example { value });
}
"#;

#[test]
fn test_example() {
let test = Smoketest::builder()
.module_code(MODULE_CODE)
.precompiled_module("example")
.build();

test.call("add", &["42"]).unwrap();
test.assert_sql("SELECT * FROM example", "value\n-----\n42");
}
```

Place the table and `add` reducer in the fixture's `src/lib.rs`. Use
`test.use_precompiled_module("example-updated")` to switch fixtures for migration
tests. If no module is selected, publishing uses the precompiled `noop` fixture.
`autopublish(false)` leaves the database unpublished and does not need that fixture
until a publish is requested.

For tests that expect Rust build failures, use `build_rust_module(source, extra_deps)`
and assert the specific diagnostic in its raw output. This helper runs
`spacetime build` without starting a server. Keep ordinary test modules in the
fixture workspace. The `http-handlers-tutorial` fixture shows how a build script
can compile examples directly from current documentation during warmup.
7 changes: 6 additions & 1 deletion crates/smoketests/modules/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ members = [

# Views tests
"views-basic",
# "views-broken-namespace" - intentionally broken, uses runtime compilation
# "views-broken-namespace" is exercised by an explicit build-failure test
"views-broken-return-type",
"views-sql",
"views-auto-migrate",
Expand Down Expand Up @@ -47,6 +47,10 @@ members = [
"call-empty",
"call-many",

# Column defaults
"column-defaults-initial",
"column-defaults-updated",

# Auto-migration tests
"auto-migration-simple",
"auto-migration-incompatible",
Expand All @@ -63,6 +67,7 @@ members = [
"auto-migration-drop-event-table-after",

# HTTP tests
"http-handlers-tutorial",
"http-egress",
"http-routes",
"http-routes-example",
Expand Down
11 changes: 11 additions & 0 deletions crates/smoketests/modules/column-defaults-initial/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "smoketest-module-column-defaults-initial"
version = "0.1.0"
edition = "2021"
publish = false

[lib]
crate-type = ["cdylib"]

[dependencies]
spacetimedb.workspace = true
4 changes: 4 additions & 0 deletions crates/smoketests/modules/column-defaults-initial/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#[spacetimedb::table(accessor = defaults_test_table, public)]
pub struct DefaultsTestTable {
pub id: u32,
}
11 changes: 11 additions & 0 deletions crates/smoketests/modules/column-defaults-updated/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "smoketest-module-column-defaults-updated"
version = "0.1.0"
edition = "2021"
publish = false

[lib]
crate-type = ["cdylib"]

[dependencies]
spacetimedb.workspace = true
32 changes: 32 additions & 0 deletions crates/smoketests/modules/column-defaults-updated/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#[spacetimedb::table(accessor = defaults_test_table, public)]
pub struct DefaultsTestTable {
pub id: u32,
#[default(true)]
pub bool_value: bool,
#[default(-8)]
pub i8_value: i8,
#[default(8)]
pub u8_value: u8,
#[default(-16)]
pub i16_value: i16,
#[default(16)]
pub u16_value: u16,
#[default(-32)]
pub i32_value: i32,
#[default(32)]
pub u32_value: u32,
#[default(-64)]
pub i64_value: i64,
#[default(64)]
pub u64_value: u64,
#[default(32.5)]
pub f32_positive_value: f32,
#[default(-32.5)]
pub f32_negative_value: f32,
#[default(64.25)]
pub f64_positive_value: f64,
#[default(-64.25)]
pub f64_negative_value: f64,
#[default("default string")]
pub string_value: String,
}
11 changes: 11 additions & 0 deletions crates/smoketests/modules/http-handlers-tutorial/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "smoketest-module-http-handlers-tutorial"
version = "0.1.0"
edition = "2021"
publish = false

[lib]
crate-type = ["cdylib"]

[dependencies]
spacetimedb.workspace = true
25 changes: 25 additions & 0 deletions crates/smoketests/modules/http-handlers-tutorial/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use std::{env, fs, path::PathBuf};

fn main() {
let doc_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../../../docs/docs/00200-core-concepts/00200-functions/00600-HTTP-handlers.md");
println!("cargo:rerun-if-changed={}", doc_path.display());
let doc = fs::read_to_string(&doc_path).expect("Failed to read HTTP handlers tutorial");
let doc = doc.replace("\r\n", "\n");
let blocks: Vec<_> = doc
.split("```rust\n")
.skip(1)
.map(|block| {
block
.split_once("\n```")
.expect("Unterminated Rust code block in HTTP handlers tutorial")
.0
})
.collect();
assert!(
!blocks.is_empty(),
"No Rust code blocks found in HTTP handlers tutorial"
);
let out_path = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("module.rs");
fs::write(out_path, blocks.join("\n\n")).expect("Failed to write HTTP handlers tutorial module");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include!(concat!(env!("OUT_DIR"), "/module.rs"));
Loading