-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIocpSmokeTest.cpp
More file actions
132 lines (112 loc) · 4.56 KB
/
Copy pathIocpSmokeTest.cpp
File metadata and controls
132 lines (112 loc) · 4.56 KB
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Windows-only smoke test for IocpLoop — build and run this on the real
// machine the way VectorSmokeTest.cpp was used to catch the earlier MSVC
// build error. This is a separate console-app project/target from
// forge.exe (same reasoning as VectorSmokeTest.cpp: both have their own
// main() and are not added to forge/moz.build).
//
// This does NOT exercise real async file/socket I/O yet (Phase 5/6 will
// add that) — it only proves the loop itself builds against the real
// Win32 API and correctly runs timers plus a manually-posted completion,
// which is everything IocpLoop currently does.
//
// Expected output, if everything works:
// IocpSmokeTest: loop initialized
// IocpSmokeTest: posted completion fired (bytes=7, key=42, ok=1)
// IocpSmokeTest: timer fired (count=1)
// IocpSmokeTest: timer fired (count=2)
// IocpSmokeTest: timer fired (count=3)
// IocpSmokeTest: all checks passed
#include "forge-core/platform/IoLoop.h"
#include <cstdio>
#include <cstdlib>
using namespace forge::core;
using namespace forge::core::platform;
namespace
{
int g_failures = 0;
#define CHECK(cond) \
do \
{ \
if (!(cond)) \
{ \
std::fprintf(stderr, "CHECK FAILED at %s:%d: %s\n", __FILE__, \
__LINE__, #cond); \
++g_failures; \
} \
} while (0)
struct CompletionState
{
bool fired{ false };
DWORD bytesTransferred{ 0 };
ULONG_PTR completionKey{ 0 };
bool succeeded{ false };
};
struct TimerState
{
IoLoop* loop{ nullptr };
int fireCount{ 0 };
};
} // namespace
int main()
{
IoLoop loop;
Result<void> initResult = loop.Initialize();
CHECK(!initResult.HasError());
std::printf("IocpSmokeTest: loop initialized\n");
// 1) A manually-posted completion — no real device handle needed,
// exercises PostCompletion() + RunOnce()'s dispatch path for real.
CompletionState completionState;
IoCompletion completion{};
completion.Pointer = &completionState;
completion.callback = [](IoCompletion* self, DWORD bytesTransferred, ULONG_PTR completionKey, bool succeeded, DWORD /*errorCode*/) noexcept
{
auto* state = static_cast<CompletionState*>(self->Pointer);
state->fired = true;
state->bytesTransferred = bytesTransferred;
state->completionKey = completionKey;
state->succeeded = succeeded;
};
Result<void> postResult = loop.PostCompletion(&completion, 7, 42);
CHECK(!postResult.HasError());
Result<void> runOnceResult = loop.RunOnce();
CHECK(!runOnceResult.HasError());
CHECK(completionState.fired);
CHECK(completionState.bytesTransferred == 7);
CHECK(completionState.completionKey == 42);
CHECK(completionState.succeeded);
std::printf(
"IocpSmokeTest: posted completion fired (bytes=%lu, key=%zu, ok=%d)\n",
static_cast<unsigned long>(completionState.bytesTransferred),
static_cast<size_t>(completionState.completionKey),
completionState.succeeded ? 1 : 0);
// 2) A repeating timer, driven through Run(), stopping itself after
// 3 firings — exercises ScheduleTimer(), the timer-driven wait
// timeout in RunOnce(), and RequestStop() together, against the
// real OS this time (not the mock from IocpLoopTest.cpp).
TimerState timerState;
timerState.loop = &loop;
Result<TimerId> timerResult = loop.ScheduleTimer(
10, /*repeat=*/true,
[](void* userData) noexcept
{
auto* state = static_cast<TimerState*>(userData);
++state->fireCount;
std::printf("IocpSmokeTest: timer fired (count=%d)\n", state->fireCount);
if (state->fireCount >= 3)
{
state->loop->RequestStop();
}
},
&timerState);
CHECK(timerResult.HasValue());
Result<void> runResult = loop.Run();
CHECK(!runResult.HasError());
CHECK(timerState.fireCount == 3);
if (g_failures == 0)
{
std::printf("IocpSmokeTest: all checks passed\n");
return 0;
}
std::printf("IocpSmokeTest: %d CHECK(S) FAILED\n", g_failures);
return 1;
}