Skip to content
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
**/target/*
out.txt
extensions/muxio-ext-test/tests/auto_tests.rs
22 changes: 16 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ publish.workspace = true # Inherit from workspace
[workspace]
members = [
".",
"extensions/muxio-ext-test",
"extensions/muxio-rpc-service",
"extensions/muxio-rpc-service-caller",
"extensions/muxio-rpc-service-endpoint",
Expand Down Expand Up @@ -49,6 +50,7 @@ muxio-tokio-rpc-client = { path = "extensions/muxio-tokio-rpc-client", version =
async-trait = "0.1.88"
axum = { version = "0.8.4", features = ["ws"] }
bitcode = "0.6.6"
bytemuck = "1.23.1"
criterion = { version = "0.6.0" }
doc-comment = "0.3.3"
bytes = "1.10.1"
Expand Down
20 changes: 20 additions & 0 deletions extensions/muxio-ext-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "muxio-ext-test"
authors.workspace = true
version.workspace = true
edition.workspace = true
repository.workspace = true
license.workspace = true
publish = false

[dev-dependencies]
bytemuck.workspace = true
tracing-subscriber = { workspace = true, features = ["fmt"] }
muxio-tokio-rpc-client = { workspace = true }
example-muxio-rpc-service-definition.workspace = true
muxio-tokio-rpc-server = { workspace = true }
muxio-rpc-service = { workspace = true }
muxio-rpc-service-caller = { workspace = true }
muxio-rpc-service-endpoint = { workspace = true, features = ["tokio_support"] }
tracing = { workspace = true }
tokio = { workspace = true, features = ["full"] }
13 changes: 13 additions & 0 deletions extensions/muxio-ext-test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Muxio Ext Test

This crate is intended for testing of crates that would otherwise have circular dependencies (and therefore not publishable).

## Test discovery

Any Rust files placed under the `tests/` directory (recursively) will be auto-included
when running `cargo test`. A build script (`build.rs`) generates `tests/auto_tests.rs`
which declares modules for each discovered `*.rs` file. Do not edit `tests/auto_tests.rs`
manually; it is regenerated on test builds.

If you need to add tests, create `.rs` files under `tests/` (for example `tests/foo/bar.rs`).
The test runner will generate module names automatically.
118 changes: 118 additions & 0 deletions extensions/muxio-ext-test/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use std::collections::HashMap;
use std::env;
use std::fs::{self, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};

fn main() {
let crate_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("missing manifest dir"));
let tests_dir = crate_dir.join("tests");

if !tests_dir.is_dir() {
println!(
"cargo:rerun-if-changed={}",
crate_dir.join("tests").display()
);
return;
}

let mut discovered = Vec::new();
collect_test_files(&tests_dir, &tests_dir, &mut discovered)
.expect("failed to scan tests directory");
discovered.sort();

let out_path = tests_dir.join("auto_tests.rs");
let mut file = File::create(&out_path).expect("failed to create auto_tests.rs");

writeln!(file, "// @generated by build.rs. Do not edit.\n")
.expect("failed to write auto_tests header");

let mut suffix_counts: HashMap<String, usize> = HashMap::new();
for rel in &discovered {
if rel.file_name().and_then(|s| s.to_str()) == Some("auto_tests.rs") {
continue;
}
if rel.extension().and_then(|s| s.to_str()) != Some("rs") {
continue;
}

let rel_str = rel.to_string_lossy().replace('\\', "/");
let module_name = unique_ident(rel, &mut suffix_counts);

writeln!(file, "#[allow(non_snake_case)]").expect("failed to write attribute");
writeln!(file, "mod {} {{", module_name).expect("failed to start module");
writeln!(
file,
" include!(concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/tests/{}\"));",
rel_str
)
.expect("failed to write include");
writeln!(file, "}}\n").expect("failed to end module");
}

println!("cargo:rerun-if-changed={}", tests_dir.display());
for rel in &discovered {
println!("cargo:rerun-if-changed={}", tests_dir.join(rel).display());
}
}

fn collect_test_files(base: &Path, dir: &Path, acc: &mut Vec<PathBuf>) -> io::Result<()> {
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path
.file_name()
.and_then(|s| s.to_str())
.map(|s| s.starts_with('.'))
.unwrap_or(false)
{
continue;
}
if path.is_dir() {
collect_test_files(base, &path, acc)?;
} else if let Ok(rel) = path.strip_prefix(base) {
acc.push(rel.to_path_buf());
}
}
Ok(())
}

fn unique_ident(rel: &Path, suffix_counts: &mut HashMap<String, usize>) -> String {
let raw = rel.to_string_lossy();
let trimmed = raw.strip_suffix(".rs").unwrap_or(&raw);
let mut ident: String = trimmed
.chars()
.map(|c| match c {
'a'..='z' | 'A'..='Z' | '0'..='9' => c,
_ => '_',
})
.collect();

while ident.contains("__") {
ident = ident.replace("__", "_");
}
if ident.ends_with('_') {
ident.pop();
}
if ident.is_empty() {
ident.push_str("test");
}
if ident
.chars()
.next()
.map(|c| c.is_ascii_digit())
.unwrap_or(true)
{
ident.insert(0, '_');
}

let counter = suffix_counts.entry(ident.clone()).or_insert(0);
if *counter == 0 {
*counter = 1;
ident
} else {
let new_ident = format!("{}_{counter}", ident);
*counter += 1;
new_ident
}
}
1 change: 1 addition & 0 deletions extensions/muxio-ext-test/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// no-op library crate used for housing integration tests.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! This integration test verifies error propagation through a proxy server.
//!
//! Scenario: Client A -> Server (Proxy) -> Client B (Provider).
//! When Client B disconnects (crashes) while a call from Client A is pending,
//! the error must propagate back through Server to Client A.
// This integration test verifies error propagation through a proxy server.
//
// Scenario: Client A -> Server (Proxy) -> Client B (Provider).
// When Client B disconnects (crashes) while a call from Client A is pending,
// the error must propagate back through Server to Client A.

use example_muxio_rpc_service_definition::prebuffered::Echo;
use muxio_rpc_service::{
Expand Down
5 changes: 4 additions & 1 deletion extensions/muxio-tokio-rpc-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ futures = { workspace = true }
tracing = { workspace = true }

[dev-dependencies]
muxio-tokio-rpc-server = { workspace = true }
tokio = { workspace = true, features = ["full"] }
tokio-tungstenite = { workspace = true }
example-muxio-rpc-service-definition = { workspace = true }
futures-util = { workspace = true }
axum = { workspace = true }
muxio-tokio-rpc-server = { workspace = true }
8 changes: 0 additions & 8 deletions extensions/muxio-tokio-rpc-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,3 @@ muxio-rpc-service = { workspace = true }
muxio-rpc-service-endpoint = { workspace = true, features=["tokio_support"] }
async-trait = { workspace = true }
tracing = { workspace = true }

[dev-dependencies]
bitcode.workspace = true
bytemuck = "1.23.1"
example-muxio-rpc-service-definition.workspace = true
muxio-tokio-rpc-client.workspace = true
muxio-tokio-rpc-server.workspace = true
tracing-subscriber = { workspace = true, features = ["fmt"] }
1 change: 1 addition & 0 deletions extensions/muxio-tokio-rpc-server/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Note: `muxio-tokio-rpc-server` tests currently reside in [muxio-ext-test](../../muxio-ext-test/) in order to resolve issues with circular dependencies for publishing.