1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! Test-support scaffolding for plugin-level unit tests.
//!
//! Plugin unit tests frequently construct a
//! [`bmux_plugin_sdk::NativeServiceContext`] directly and invoke the
//! plugin's handlers, bypassing the real plugin-loader/registry. That
//! bypass leaves cross-plugin `call_service_raw` dispatch unrouted —
//! there's no `ProviderId::Plugin(...)` in the context's `services`
//! list, and production `handle_core_service_call` only speaks to
//! core interfaces like `storage-query/v1`.
//!
//! [`install_test_service_router`] lets a test install a thread-local
//! closure that intercepts every `call_service_raw` call on the
//! current thread. Production code never installs one, so there is no
//! runtime cost outside tests.
//!
//! # Usage
//!
//! ```no_run
//! use bmux_plugin::test_support::{install_test_service_router, TestServiceRouter};
//! use bmux_plugin_sdk::{PluginError, Result, ServiceKind};
//!
//! let router: TestServiceRouter = std::sync::Arc::new(
//! |_caller_plugin, _caller_client, _capability, _kind, interface, operation, _payload| {
//! match (interface, operation) {
//! ("contexts-state", "list-contexts") => Ok(b"<serialized payload>".to_vec()),
//! _ => Err(PluginError::UnsupportedHostOperation {
//! operation: "test_router",
//! }),
//! }
//! },
//! );
//! let _guard = install_test_service_router(router);
//! // ... run the plugin handler here ...
//! // guard drops at end of scope; router uninstalled.
//! ```
use ;
use RefCell;
use Arc;
/// Closure signature for the test service router.
///
/// Receives the same information that `call_service_raw` would pass
/// into its capability/service-lookup logic. The closure returns the
/// raw byte payload the caller expects (same shape as
/// `encode_service_message` output), or a [`PluginError`] on failure.
///
/// Parameter order:
/// 1. `caller_plugin_id` — which plugin made the call.
/// 2. `caller_client_id` — the end-user client id, when known.
/// 3. `capability` — the capability string the caller is using.
/// 4. `kind` — Query / Command / Event.
/// 5. `interface_id` — the target interface id.
/// 6. `operation` — the operation name within the interface.
/// 7. `payload` — serialized request bytes.
pub type TestServiceRouter = ;
thread_local!
/// RAII guard that uninstalls the thread-local test service router
/// when dropped.
///
/// Always scope the guard to the lifetime of a single test. Never
/// `std::mem::forget` the guard — doing so permanently installs the
/// router on the thread and will leak behavior into subsequent tests.
/// Install a thread-local test service router for the duration of
/// the returned guard's lifetime.
///
/// Replaces any previously-installed router; the previous one is
/// restored when the guard drops.
/// Retrieve the currently-installed test service router, if any.
///
/// Used internally by `call_service_raw`; plugin authors normally
/// don't need to call this directly.