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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# 0.5.1 (March 27, 2026)

- Add `InjectorPP::new_global()` constructor for cross-thread fake visibility.
- Fakes registered through `new_global()` use direct code patching (0.4.0-style) and are visible to **all threads**, including background threads, timers, and thread pools like rayon.
- `new()` remains the default with thread-local dispatch for parallel test execution.
- `new_global()` acquires an exclusive lock, serializing tests that use it.
- Fix fakes not visible from rayon worker threads and background timer threads (issue #121).
- Add IAT thunk resolution to PatchGuard path on Windows x86_64.

# 0.5.0 (March 15, 2026)

- Add macOS support.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "injectorpp"
version = "0.5.0"
version = "0.5.1"
authors = ["Jingyu Ma <mazong1123us@gmail.com>"]
license = "MIT"
readme = "README.md"
Expand Down
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Add `injectorpp` to the `Cargo.toml`:

```toml
[dev-dependencies]
injectorpp = "0.5.0"
injectorpp = "0.5.1"
```

Below `profile.test` config is recommended to make sure `injectorpp` working correctly in tests. If you have workspace, make sure add this on the top level of `Cargo.toml`:
Expand All @@ -88,6 +88,27 @@ use injectorpp::interface::injector::*;

Below are multiple ways to config the function behavior.

## Thread-local vs Global mode

By default, `InjectorPP::new()` uses **thread-local dispatch** — fakes are only visible on the thread that created the injector. This enables parallel test execution without interference between tests.

However, if your code under test spawns background threads, timers, or uses thread pools, those worker threads won't see thread-local fakes. For these cases, use `InjectorPP::new_global()`:

```rust
// Thread-local mode (default) — fakes only visible on the current thread
let mut injector = InjectorPP::new();

// Global mode — fakes visible to ALL threads (background threads, timers, thread pools)
let mut injector = InjectorPP::new_global();
```

`new_global()` uses direct code patching, making fakes visible process-wide. It acquires an exclusive lock, so tests using `new_global()` run serialized to prevent interference.

**When to use `new_global()`:**
- Your faked function is called from a background thread or timer
- You use thread pool APIs that execute work on worker threads
- You need the same behavior as injectorpp 0.4.0

## `will_return_boolean`

If the function only returns boolean and you only want to make it constantly returns a specific boolean value, you can use `will_return_boolean`:
Expand Down
2 changes: 1 addition & 1 deletion injectorpp-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "injectorpp-macros"
version = "0.5.0"
version = "0.5.1"
authors = ["Jingyu Ma <mazong1123us@gmail.com>"]
license = "MIT"
repository = "https://github.com/microsoft/injectorppforrust"
Expand Down
2 changes: 1 addition & 1 deletion tests/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ fn test_global_fake_unchecked_cross_thread() {
}

/// Verifies that `new()` (thread-local mode) still works correctly — fakes are NOT visible
/// from spawned threads (default 0.5.0 behavior).
/// from spawned threads (default thread-local behavior).
#[test]
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "arm"))]
fn test_thread_local_mode_not_visible_from_spawned_thread() {
Expand Down
Loading