Files
SpacetimeDB/sdks/rust/tests/test.rs
Shubham Mishra 2560846f22 Rust: client query builder (#4003)
# Description of Changes
Client Query builder for rust, as per proposal -
https://github.com/clockworklabs/SpacetimeDBPrivate/pull/2356.

1. Pach moves query builder to its separate crate, so that it can be
shared between module and sdk.
2. Implements `TypedSubscriptionBuilder` in `sdks/rust` as mentioned in
proposal
3. Modify codegen to extend types to support query builder as mentioned
in proposal
4. a test

# API and ABI breaking changes
NA, additive changes.

# Expected complexity level and risk
2

# Testing
Added a test.

---------

Signed-off-by: Shubham Mishra <shivam828787@gmail.com>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2026-01-22 15:37:22 +00:00

411 lines
12 KiB
Rust

macro_rules! declare_tests_with_suffix {
($lang:ident, $suffix:literal) => {
mod $lang {
use spacetimedb_testing::sdk::Test;
const MODULE: &str = concat!("sdk-test", $suffix);
const CLIENT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/test-client");
fn make_test(subcommand: &str) -> Test {
Test::builder()
.with_name(subcommand)
.with_module(MODULE)
.with_client(CLIENT)
.with_language("rust")
.with_bindings_dir("src/module_bindings")
.with_compile_command("cargo build")
.with_run_command(format!("cargo run -- {}", subcommand))
.build()
}
#[test]
fn insert_primitive() {
make_test("insert-primitive").run();
}
#[test]
fn subscribe_and_cancel() {
make_test("subscribe-and-cancel").run();
}
#[test]
fn subscribe_and_unsubscribe() {
make_test("subscribe-and-unsubscribe").run();
}
#[test]
fn subscription_error_smoke_test() {
make_test("subscription-error-smoke-test").run();
}
#[test]
fn delete_primitive() {
make_test("delete-primitive").run();
}
#[test]
fn update_primitive() {
make_test("update-primitive").run();
}
#[test]
fn insert_identity() {
make_test("insert-identity").run();
}
#[test]
fn insert_caller_identity() {
make_test("insert-caller-identity").run();
}
#[test]
fn delete_identity() {
make_test("delete-identity").run();
}
#[test]
fn update_identity() {
make_test("delete-identity").run();
}
#[test]
fn insert_connection_id() {
make_test("insert-connection-id").run();
}
#[test]
fn insert_caller_connection_id() {
make_test("insert-caller-connection-id").run();
}
#[test]
fn delete_connection_id() {
make_test("delete-connection-id").run();
}
#[test]
fn update_connection_id() {
make_test("delete-connection-id").run();
}
#[test]
fn insert_timestamp() {
make_test("insert-timestamp").run();
}
#[test]
fn insert_call_uuid_v4() {
make_test("insert-call-uuid-v4").run();
}
#[test]
fn insert_call_uuid_v7() {
make_test("insert-call-uuid-v7").run();
}
#[test]
fn insert_uuid() {
make_test("insert-uuid").run();
}
#[test]
fn delete_uuid() {
make_test("delete-uuid").run();
}
#[test]
fn update_uuid() {
make_test("delete-uuid").run();
}
#[test]
fn on_reducer() {
make_test("on-reducer").run();
}
#[test]
fn fail_reducer() {
make_test("fail-reducer").run();
}
#[test]
fn insert_vec() {
make_test("insert-vec").run();
}
#[test]
fn insert_option_some() {
make_test("insert-option-some").run();
}
#[test]
fn insert_option_none() {
make_test("insert-option-none").run();
}
#[test]
fn insert_struct() {
make_test("insert-struct").run();
}
#[test]
fn insert_simple_enum() {
make_test("insert-simple-enum").run();
}
#[test]
fn insert_enum_with_payload() {
make_test("insert-enum-with-payload").run();
}
#[test]
fn insert_delete_large_table() {
make_test("insert-delete-large-table").run();
}
#[test]
fn insert_primitives_as_strings() {
make_test("insert-primitives-as-strings").run();
}
// #[test]
// fn resubscribe() {
// make_test("resubscribe").run();
// }
#[test]
#[should_panic]
fn should_fail() {
make_test("should-fail").run();
}
#[test]
fn reauth() {
make_test("reauth-part-1").run();
make_test("reauth-part-2").run();
}
#[test]
fn reconnect_different_connection_id() {
make_test("reconnect-different-connection-id").run();
}
#[test]
fn connect_disconnect_callbacks() {
Test::builder()
.with_name(concat!("connect-disconnect-callback-", stringify!($lang)))
.with_module(concat!("sdk-test-connect-disconnect", $suffix))
.with_client(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/connect_disconnect_client"
))
.with_language("rust")
.with_bindings_dir("src/module_bindings")
.with_compile_command("cargo build")
.with_run_command("cargo run")
.build()
.run();
}
#[test]
fn caller_always_notified() {
make_test("caller-always-notified").run();
}
#[test]
fn subscribe_all_select_star() {
make_test("subscribe-all-select-star").run();
}
#[test]
fn caller_alice_receives_reducer_callback_but_not_bob() {
make_test("caller-alice-receives-reducer-callback-but-not-bob").run();
}
#[test]
fn row_deduplication() {
make_test("row-deduplication").run();
}
#[test]
fn row_deduplication_join_r_and_s() {
make_test("row-deduplication-join-r-and-s").run();
}
#[test]
fn row_deduplication_r_join_s_and_r_join_t8() {
make_test("row-deduplication-r-join-s-and-r-joint").run();
}
#[test]
fn test_lhs_join_update() {
make_test("test-lhs-join-update").run()
}
#[test]
fn test_lhs_join_update_disjoint_queries() {
make_test("test-lhs-join-update-disjoint-queries").run()
}
#[test]
fn test_intra_query_bag_semantics_for_join() {
make_test("test-intra-query-bag-semantics-for-join").run()
}
#[test]
fn two_different_compression_algos() {
make_test("two-different-compression-algos").run();
}
#[test]
fn test_parameterized_subscription() {
make_test("test-parameterized-subscription").run();
}
#[test]
fn test_rls_subscription() {
make_test("test-rls-subscription").run()
}
#[test]
fn pk_simple_enum() {
make_test("pk-simple-enum").run();
}
#[test]
fn indexed_simple_enum() {
make_test("indexed-simple-enum").run();
}
#[test]
fn overlapping_subscriptions() {
make_test("overlapping-subscriptions").run();
}
#[test]
fn sorted_uuids_insert() {
make_test("sorted-uuids-insert").run();
}
}
};
}
declare_tests_with_suffix!(rust, "");
declare_tests_with_suffix!(typescript, "-ts");
// TODO: migrate csharp to snake_case table names
declare_tests_with_suffix!(csharp, "-cs");
macro_rules! procedure_tests {
($mod_name:ident, $suffix:literal) => {
mod $mod_name {
//! Tests of procedure functionality, using <./procedure_client> and <../../../modules/sdk-test-procedure>.
//!
//! These are separate from the existing client and module because as of writing (pgoldman 2025-10-30),
//! we do not have procedure support in all of the module languages we have tested.
use spacetimedb_testing::sdk::Test;
const MODULE: &str = concat!("sdk-test-procedure", $suffix);
const CLIENT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/procedure-client");
fn make_test(subcommand: &str) -> Test {
Test::builder()
.with_name(subcommand)
.with_module(MODULE)
.with_client(CLIENT)
.with_language("rust")
.with_bindings_dir("src/module_bindings")
.with_compile_command("cargo build")
.with_run_command(format!("cargo run -- {}", subcommand))
.build()
}
#[test]
fn return_values() {
make_test("procedure-return-values").run()
}
#[test]
fn observe_panic() {
make_test("procedure-observe-panic").run()
}
#[test]
fn with_tx_commit() {
make_test("insert-with-tx-commit").run()
}
#[test]
fn with_tx_rollback() {
make_test("insert-with-tx-rollback").run()
}
#[test]
fn http_ok() {
make_test("procedure-http-ok").run()
}
#[test]
fn http_err() {
make_test("procedure-http-err").run()
}
#[test]
fn schedule_procedure() {
make_test("schedule-procedure").run()
}
}
};
}
procedure_tests!(rust_procedures, "");
procedure_tests!(typescript_procedures, "-ts");
mod view {
use spacetimedb_testing::sdk::Test;
const MODULE: &str = "sdk-test-view";
const CLIENT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/view-client");
fn make_test(subcommand: &str) -> Test {
Test::builder()
.with_name(subcommand)
.with_module(MODULE)
.with_client(CLIENT)
.with_language("rust")
.with_bindings_dir("src/module_bindings")
.with_compile_command("cargo build")
.with_run_command(format!("cargo run -- {}", subcommand))
.build()
}
#[test]
fn subscribe_anonymous_view() {
make_test("view-anonymous-subscribe").run()
}
#[test]
fn subscribe_anonymous_view_query_builder() {
make_test("view-anonymous-subscribe-with-query-builder").run()
}
#[test]
fn subscribe_non_anonymous_view() {
make_test("view-non-anonymous-subscribe").run()
}
#[test]
fn subscribe_view_non_table_return() {
make_test("view-non-table-return").run()
}
#[test]
fn subscribe_view_non_table_query_builder_return() {
make_test("view-non-table-query-builder-return").run()
}
#[test]
fn subscription_updates_for_view() {
make_test("view-subscription-update").run()
}
}