./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
38 / 38
100.0%
Branches:
40 / 40
100.0%
Functions:
5 / 5
100.0%

src/staged_reload.cpp
Line Branch Exec Source
1 /**
2 * @file staged_reload.cpp
3 * @brief The staged-reload baseline and Shutdown verdict over the diagnostics counters of this DMK copy.
4 */
5
6 #include "DetourModKit/staged_reload.hpp"
7
8 #include "DetourModKit/hook.hpp"
9
10 #include <array>
11 #include <cstddef>
12 #include <cstdint>
13
14 namespace DetourModKit
15 {
16 namespace staged_reload
17 {
18 namespace
19 {
20 using diagnostics::LeakSubsystem;
21 using diagnostics::ModulePinReason;
22
23 template <class Enum, std::size_t Size>
24 33637 [[nodiscard]] bool grew(
25 const std::array<std::size_t, Size> &now,
26 const std::array<std::size_t, Size> &baseline,
27 Enum which
28 ) noexcept
29 {
30 33637 const auto index = static_cast<std::size_t>(which);
31 33637 return now[index] > baseline[index];
32 }
33
34 [[nodiscard]] std::uint32_t
35 1655 classify(const hook::HookRetirement &retirement, const Baseline &baseline) noexcept
36 {
37
2/2
✓ Branch 2 → 3 taken 25 times.
✓ Branch 2 → 4 taken 1630 times.
1655 if (retirement.outcome == hook::RetirementOutcome::Busy)
38 {
39 25 return DMK_STAGED_RELOAD_BUSY;
40 }
41 1630 const Baseline now = capture();
42
4/4
✓ Branch 6 → 7 taken 1625 times.
✓ Branch 6 → 11 taken 2 times.
✓ Branch 8 → 9 taken 1621 times.
✓ Branch 8 → 11 taken 4 times.
3252 if (retirement.outcome == hook::RetirementOutcome::Refused || retirement.pinned != 0 ||
43
6/6
✓ Branch 5 → 6 taken 1627 times.
✓ Branch 5 → 11 taken 3 times.
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 12 taken 1619 times.
✓ Branch 13 → 14 taken 11 times.
✓ Branch 13 → 15 taken 1619 times.
4882 grew(now.intentional_leaks, baseline.intentional_leaks, LeakSubsystem::HookManager) ||
44 1621 grew(now.module_pins, baseline.module_pins, ModulePinReason::Hook))
45 {
46 11 return DMK_STAGED_RELOAD_RESTART_REQUIRED;
47 }
48
2/2
✓ Branch 26 → 16 taken 16099 times.
✓ Branch 26 → 27 taken 1596 times.
35390 for (std::size_t index = 0; index < now.intentional_leaks.size(); ++index)
49 {
50 16099 const auto subsystem = static_cast<LeakSubsystem>(index);
51
6/6
✓ Branch 16 → 17 taken 14503 times.
✓ Branch 16 → 20 taken 1596 times.
✓ Branch 18 → 19 taken 23 times.
✓ Branch 18 → 20 taken 14480 times.
✓ Branch 21 → 22 taken 23 times.
✓ Branch 21 → 23 taken 16076 times.
30602 if (subsystem != LeakSubsystem::HookResidue &&
52 14503 grew(now.intentional_leaks, baseline.intentional_leaks, subsystem))
53 {
54 23 return DMK_STAGED_RELOAD_RETAINED;
55 }
56 }
57
2/2
✓ Branch 38 → 28 taken 17468 times.
✓ Branch 38 → 39 taken 1578 times.
38092 for (std::size_t index = 0; index < now.module_pins.size(); ++index)
58 {
59 17468 const auto reason = static_cast<ModulePinReason>(index);
60
6/6
✓ Branch 28 → 29 taken 15888 times.
✓ Branch 28 → 32 taken 1580 times.
✓ Branch 30 → 31 taken 18 times.
✓ Branch 30 → 32 taken 15870 times.
✓ Branch 33 → 34 taken 18 times.
✓ Branch 33 → 35 taken 17450 times.
17468 if (reason != ModulePinReason::XInputTarget && grew(now.module_pins, baseline.module_pins, reason))
61 {
62 18 return DMK_STAGED_RELOAD_RETAINED;
63 }
64 }
65 1578 return DMK_STAGED_RELOAD_OK;
66 }
67 } // namespace
68
69 3211 Baseline capture() noexcept
70 {
71 3211 Baseline baseline;
72
2/2
✓ Branch 8 → 3 taken 32110 times.
✓ Branch 8 → 9 taken 3211 times.
38532 for (std::size_t index = 0; index < baseline.intentional_leaks.size(); ++index)
73 {
74 32110 baseline.intentional_leaks[index] =
75 32110 diagnostics::intentional_leak_count(static_cast<LeakSubsystem>(index));
76 }
77
2/2
✓ Branch 15 → 10 taken 35321 times.
✓ Branch 15 → 16 taken 3211 times.
41743 for (std::size_t index = 0; index < baseline.module_pins.size(); ++index)
78 {
79 35321 baseline.module_pins[index] = diagnostics::module_pin_count(static_cast<ModulePinReason>(index));
80 }
81 3211 return baseline;
82 }
83
84 1655 std::uint32_t verdict(
85 const hook::HookRetirement &retirement,
86 const Baseline &baseline,
87 std::uint32_t loader_abi_version
88 ) noexcept
89 {
90 1655 const std::uint32_t result = classify(retirement, baseline);
91 1655 const bool unknown_to_loader =
92
4/4
✓ Branch 3 → 4 taken 56 times.
✓ Branch 3 → 7 taken 1599 times.
✓ Branch 4 → 5 taken 45 times.
✓ Branch 4 → 6 taken 11 times.
1700 loader_abi_version < DMK_STAGED_RELOAD_ABI_VERSION &&
93
2/2
✓ Branch 5 → 6 taken 4 times.
✓ Branch 5 → 7 taken 41 times.
45 (result == DMK_STAGED_RELOAD_BUSY || result == DMK_STAGED_RELOAD_RESTART_REQUIRED);
94
2/2
✓ Branch 8 → 9 taken 15 times.
✓ Branch 8 → 10 taken 1640 times.
1655 return unknown_to_loader ? DMK_STAGED_RELOAD_REFUSED : result;
95 }
96 } // namespace staged_reload
97 } // namespace DetourModKit
98