mlua_probe_core/lib.rs
1//! Core debug and testing engine for mlua.
2//!
3//! Provides two main capabilities for Lua code running inside an
4//! mlua `Lua` instance:
5//!
6//! - **Debugging** — breakpoints, stepping, variable inspection, and
7//! expression evaluation via [`DebugSession`] / [`DebugController`].
8//! - **Testing** — BDD test framework via [`mlua_lspec`], re-exported
9//! as the [`testing`] module.
10//!
11//! # Architecture
12//!
13//! The debug engine uses a **VM-thread blocking** model:
14//!
15//! - A Lua debug hook pauses the VM thread when a breakpoint or step
16//! condition is met.
17//! - While paused, the hook dispatches inspection commands (locals,
18//! upvalues, evaluate) **on the VM thread** — required because
19//! `lua_getlocal` and friends are not thread-safe.
20//! - A resume command (continue / step) unblocks the hook and lets
21//! Lua execution proceed.
22//!
23//! The testing module is independent of the debug engine. It creates
24//! a fresh Lua VM per test run, so tests are fully isolated.
25//!
26//! # Debugging example
27//!
28//! ```rust,no_run
29//! use mlua::prelude::*;
30//! use mlua_probe_core::{DebugSession, DebugEvent};
31//!
32//! let lua = Lua::new();
33//! let (session, controller) = DebugSession::new();
34//! session.attach(&lua).unwrap();
35//!
36//! controller.set_breakpoint("@main.lua", 3, None).unwrap();
37//!
38//! // Run Lua on a separate thread so the current thread can
39//! // interact with the controller.
40//! let handle = std::thread::spawn(move || {
41//! lua.load(r#"
42//! local x = 1
43//! local y = 2
44//! local z = x + y
45//! return z
46//! "#)
47//! .set_name("@main.lua")
48//! .eval::<i64>()
49//! });
50//!
51//! // Wait for the VM to pause.
52//! let event = controller.wait_event().unwrap();
53//! // Inspect, step, continue …
54//! controller.continue_execution().unwrap();
55//!
56//! let result = handle.join().unwrap().unwrap();
57//! assert_eq!(result, 3);
58//! ```
59//!
60//! # Testing example
61//!
62//! ```rust
63//! use mlua_probe_core::testing;
64//!
65//! let summary = testing::framework::run_tests(r#"
66//! local describe, it, expect = lust.describe, lust.it, lust.expect
67//! describe('math', function()
68//! it('adds', function()
69//! expect(1 + 1).to.equal(2)
70//! end)
71//! end)
72//! "#, "@test.lua").unwrap();
73//!
74//! assert_eq!(summary.passed, 1);
75//! assert_eq!(summary.failed, 0);
76//! ```
77
78mod debug;
79
80/// BDD test framework for Lua, re-exported from [`mlua_lspec`].
81pub mod testing {
82 pub use mlua_lspec::{TestResult, TestSummary};
83
84 pub mod framework {
85 pub use mlua_lspec::{collect_results, register, run_tests};
86 }
87
88 pub use mlua_lspec::doubles;
89}
90
91pub use debug::breakpoint::Breakpoint;
92pub use debug::controller::DebugController;
93pub use debug::engine::{CompletionNotifier, DebugSession};
94pub use debug::error::DebugError;
95pub use debug::types::{
96 BreakpointId, DebugEvent, FrameKind, OutputCategory, PauseReason, SessionState, StackFrame,
97 StepMode, Variable, VariableRef,
98};