Branch data Line data Source code
1 : : #ifndef LINUXMOCK_H
2 : : #define LINUXMOCK_H
3 : :
4 : : #ifndef _WIN32
5 : : #include <chrono>
6 : : #include <optional>
7 : : #include <cstdint>
8 : : #include <cstring>
9 : : #include <algorithm>
10 : : #include <map>
11 : : #include <vector>
12 : : #include <string>
13 : : #include <cstdarg>
14 : : #include <cstdio>
15 : :
16 : : // Dummy typedefs for Linux compatibility
17 : : using DWORD = uint32_t;
18 : : using HANDLE = void*;
19 : : using HWND = void*;
20 : : using BOOL = int;
21 : : using UINT = unsigned int;
22 : : using LONG = long;
23 : : using SHORT = short;
24 : : using VOID = void;
25 : : using PVOID = void*;
26 : : using UINT_PTR = unsigned long;
27 : : using LPARAM = long;
28 : : using WPARAM = unsigned long;
29 : : using LRESULT = long;
30 : : using HRESULT = long;
31 : : using WORD = uint16_t;
32 : : using BYTE = uint8_t;
33 : : using LONG_PTR = intptr_t;
34 : : using ULONG_PTR = uintptr_t;
35 : : using LPDWORD = uint32_t*;
36 : : using HMODULE = void*;
37 : : using HICON = void*;
38 : : using HRSRC = void*;
39 : : using LPVOID = void*;
40 : : using LPCSTR = const char*;
41 : :
42 : : typedef struct _GUID {
43 : : uint32_t Data1;
44 : : uint16_t Data2;
45 : : uint16_t Data3;
46 : : uint8_t Data4[8];
47 : : } GUID;
48 : :
49 : : #ifndef __cdecl
50 : : #define __cdecl
51 : : #endif
52 : :
53 : : #ifndef TRUE
54 : : #define TRUE 1
55 : : #endif
56 : :
57 : : #ifndef FALSE
58 : : #define FALSE 0
59 : : #endif
60 : :
61 : : #ifndef NULL
62 : : #define NULL nullptr
63 : : #endif
64 : :
65 : : #ifndef MAX_PATH
66 : : #define MAX_PATH 260
67 : : #endif
68 : :
69 : : #ifndef _TRUNCATE
70 : : #define _TRUNCATE ((size_t)-1)
71 : : #endif
72 : :
73 : : // Windows Constants for Mocking
74 : : #define INVALID_HANDLE_VALUE (reinterpret_cast<HANDLE>(static_cast<intptr_t>(-1))) // NOLINT(performance-no-int-to-ptr)
75 : : #define PAGE_READWRITE 0x04
76 : : #define FILE_MAP_ALL_ACCESS 0xF001F
77 : : #define FILE_MAP_READ 0x04
78 : : #define ERROR_ALREADY_EXISTS 183
79 : : #define WAIT_OBJECT_0 0
80 : : #define WAIT_FAILED 0xFFFFFFFF
81 : : #define INFINITE 0xFFFFFFFF
82 : : #define SYNCHRONIZE 0x00100000L
83 : : #define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
84 : :
85 : : // Window Styles & Constants
86 : : #define WS_OVERLAPPEDWINDOW 0
87 : : #define WS_VISIBLE 0
88 : : #define GWL_EXSTYLE -20
89 : : #define WS_EX_TOPMOST 0x00000008L
90 : : #define HWND_TOPMOST (reinterpret_cast<HWND>(static_cast<intptr_t>(-1))) // NOLINT(performance-no-int-to-ptr)
91 : : #define HWND_NOTOPMOST (reinterpret_cast<HWND>(static_cast<intptr_t>(-2))) // NOLINT(performance-no-int-to-ptr)
92 : : #define SWP_NOMOVE 0x0002
93 : : #define SWP_NOSIZE 0x0001
94 : : #define SWP_FRAMECHANGED 0x0020
95 : :
96 : : // Resources
97 : : #define RT_GROUP_ICON (reinterpret_cast<LPCSTR>(static_cast<intptr_t>(14))) // NOLINT(performance-no-int-to-ptr)
98 : : #define LOAD_LIBRARY_AS_DATAFILE 0x00000002
99 : : #define MAKEINTRESOURCE(i) (reinterpret_cast<char*>(static_cast<intptr_t>(static_cast<WORD>(i)))) // NOLINT(performance-no-int-to-ptr)
100 : : #define MAKEINTRESOURCEA(i) (reinterpret_cast<char*>(static_cast<intptr_t>(static_cast<WORD>(i)))) // NOLINT(performance-no-int-to-ptr)
101 : :
102 : : // Memory Mapping Mock (Global Storage)
103 : : namespace MockSM {
104 : 50340 : inline std::map<std::string, std::vector<uint8_t>>& GetMaps() {
105 [ + + + - ]: 50340 : static std::map<std::string, std::vector<uint8_t>> maps;
106 : 50340 : return maps;
107 : : }
108 : 24846 : inline DWORD& LastError() {
109 : : static DWORD err = 0;
110 : 24846 : return err;
111 : : }
112 : 12436 : inline bool& FailNext() {
113 : : static bool fail = false;
114 : 12436 : return fail;
115 : : }
116 : 7 : inline DWORD& WaitResult() {
117 : : static DWORD res = 0; // WAIT_OBJECT_0
118 : 7 : return res;
119 : : }
120 : : }
121 : :
122 : : // Interlocked functions for Linux mocking
123 : 25930 : inline long InterlockedCompareExchange(long volatile* Destination, long Exchange, long Comparand) {
124 : 25930 : long old = *Destination;
125 [ + + ]: 25930 : if (old == Comparand) *Destination = Exchange;
126 : 25930 : return old;
127 : : }
128 : 4 : inline long InterlockedIncrement(long volatile* Addend) { return ++(*Addend); }
129 : 1 : inline long InterlockedDecrement(long volatile* Addend) { return --(*Addend); }
130 : 9926 : inline long InterlockedExchange(long volatile* Target, long Value) {
131 : 9926 : long old = *Target;
132 : 9926 : *Target = Value;
133 : 9926 : return old;
134 : : }
135 : :
136 : : // Memory and Event mocks
137 : 16000 : inline void YieldProcessor() {}
138 : : inline int sprintf_s(char* buf, size_t size, const char* fmt, ...) {
139 : : va_list args;
140 : : va_start(args, fmt);
141 : : int ret = vsnprintf(buf, size, fmt, args);
142 : : va_end(args);
143 : : return ret;
144 : : }
145 : 2 : inline int sprintf_s(char* buf, const char* fmt, ...) {
146 : : va_list args;
147 : 2 : va_start(args, fmt);
148 : 2 : int ret = vsprintf(buf, fmt, args);
149 : 2 : va_end(args);
150 : 2 : return ret;
151 : : }
152 : 4 : inline DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) {
153 [ + + ]: 4 : if (MockSM::WaitResult() != 0) {
154 : 1 : DWORD res = MockSM::WaitResult();
155 : 1 : MockSM::WaitResult() = 0;
156 : 1 : return res;
157 : : }
158 : 3 : return WAIT_OBJECT_0;
159 : : }
160 : 4769 : inline BOOL SetEvent(HANDLE hEvent) { return TRUE; }
161 : 37259 : inline BOOL CloseHandle(HANDLE hObject) {
162 [ + + + + ]: 37259 : if (hObject != reinterpret_cast<HANDLE>(static_cast<intptr_t>(0)) &&
163 [ + - ]: 24837 : hObject != reinterpret_cast<HANDLE>(static_cast<intptr_t>(1)) &&
164 [ + + ]: 24837 : hObject != reinterpret_cast<HANDLE>(static_cast<intptr_t>(2)) &&
165 : : hObject != INVALID_HANDLE_VALUE) {
166 [ + - ]: 24836 : delete static_cast<std::string*>(hObject);
167 : : }
168 : 37259 : return TRUE;
169 : : }
170 : 12421 : inline DWORD GetLastError() { return MockSM::LastError(); }
171 : :
172 : : // Shared Memory Mocks
173 : 12430 : inline HANDLE CreateFileMappingA(HANDLE hFile, void* lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, const char* lpName) {
174 [ + + ]: 12430 : if (MockSM::FailNext()) {
175 : 3 : MockSM::FailNext() = false;
176 : 3 : return nullptr;
177 : : }
178 [ + + ]: 12427 : if (lpName == nullptr) return reinterpret_cast<HANDLE>(static_cast<intptr_t>(1));
179 [ + - ]: 12425 : std::string name(lpName);
180 : 12425 : auto& maps = MockSM::GetMaps();
181 [ + - + + ]: 12425 : if (maps.find(name) == maps.end()) {
182 [ + - + - ]: 4 : maps[name].resize(dwMaximumSizeLow);
183 : 4 : MockSM::LastError() = 0;
184 : : } else {
185 : 12421 : MockSM::LastError() = ERROR_ALREADY_EXISTS;
186 : : }
187 [ + - + - : 12425 : return reinterpret_cast<HANDLE>(new std::string(name));
- - ]
188 : 12425 : }
189 : :
190 : 12421 : inline HANDLE OpenFileMappingA(DWORD dwDesiredAccess, BOOL bInheritHandle, const char* lpName) {
191 [ + + ]: 12421 : if (lpName == nullptr) return nullptr;
192 [ + - ]: 12418 : std::string name(lpName);
193 : 12418 : auto& maps = MockSM::GetMaps();
194 [ + - + + ]: 12418 : if (maps.find(name) != maps.end()) {
195 [ + - + - : 12411 : return reinterpret_cast<HANDLE>(new std::string(name));
- - ]
196 : : }
197 : 7 : return nullptr;
198 : 12418 : }
199 : :
200 : 24833 : inline void* MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, size_t dwNumberOfBytesToMap) {
201 [ + + + + : 24833 : if (hFileMappingObject == reinterpret_cast<HANDLE>(static_cast<intptr_t>(1)) || hFileMappingObject == nullptr || hFileMappingObject == INVALID_HANDLE_VALUE) return nullptr;
+ + ]
202 : 24830 : std::string* name = static_cast<std::string*>(hFileMappingObject);
203 : 24830 : return MockSM::GetMaps()[*name].data();
204 : : }
205 : :
206 : 24830 : inline BOOL UnmapViewOfFile(const void* lpBaseAddress) { return TRUE; }
207 : 12420 : inline HANDLE CreateEventA(void* lpEventAttributes, BOOL bManualReset, BOOL bInitialState, const char* lpName) { return reinterpret_cast<HANDLE>(static_cast<intptr_t>(1)); }
208 : :
209 : : // Window mocks
210 : : namespace MockGUI {
211 : 11 : inline LONG_PTR& ExStyle() { static LONG_PTR style = 0; return style; }
212 : : }
213 : :
214 : 1 : inline HWND GetConsoleWindow() { return reinterpret_cast<HWND>(static_cast<intptr_t>(1)); }
215 : 4773 : inline BOOL IsWindow(HWND hWnd) {
216 [ + + + + ]: 4773 : return (hWnd == reinterpret_cast<HWND>(static_cast<intptr_t>(1)) || hWnd == reinterpret_cast<HWND>(static_cast<intptr_t>(2))); // Accept our mock handles
217 : : }
218 : 1 : inline HWND CreateWindowA(const char* lpClassName, const char* lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, void* hMenu, HMODULE hInstance, void* lpParam) {
219 : 1 : return reinterpret_cast<HWND>(static_cast<intptr_t>(2));
220 : : }
221 : 7 : inline LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex) {
222 [ + + ]: 7 : if (nIndex == GWL_EXSTYLE) return MockGUI::ExStyle();
223 : 1 : return 0;
224 : : }
225 : 4 : inline BOOL SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags) {
226 [ + + ]: 4 : if (hWndInsertAfter == HWND_TOPMOST) MockGUI::ExStyle() |= WS_EX_TOPMOST;
227 [ + + ]: 4 : if (hWndInsertAfter == HWND_NOTOPMOST) MockGUI::ExStyle() &= ~WS_EX_TOPMOST;
228 : 4 : return TRUE;
229 : : }
230 : 1 : inline BOOL DestroyWindow(HWND hWnd) { return TRUE; }
231 : :
232 : : // Resource Mocks
233 : 2 : inline HMODULE GetModuleHandle(const char* lpModuleName) { return reinterpret_cast<HMODULE>(static_cast<intptr_t>(1)); }
234 : 1 : inline HICON LoadIcon(HMODULE hInstance, const char* lpIconName) { return reinterpret_cast<HICON>(static_cast<intptr_t>(1)); }
235 : 1 : inline DWORD GetModuleFileNameA(HMODULE hModule, char* lpFilename, DWORD nSize) {
236 : 1 : strncpy(lpFilename, "LMUFFB.exe", nSize);
237 : 1 : return strlen(lpFilename);
238 : : }
239 : 1 : inline HMODULE LoadLibraryExA(const char* lpLibFileName, HANDLE hFile, DWORD dwFlags) { return reinterpret_cast<HMODULE>(static_cast<intptr_t>(1)); }
240 : 1 : inline HRSRC FindResourceA(HMODULE hModule, const char* lpName, const char* lpType) { return reinterpret_cast<HRSRC>(static_cast<intptr_t>(1)); }
241 : 1 : inline BOOL FreeLibrary(HMODULE hLibModule) { return TRUE; }
242 : :
243 : : // Version Info Mocks
244 : 1 : inline DWORD GetFileVersionInfoSizeA(const char* lptstrFilename, LPDWORD lpdwHandle) {
245 [ + - ]: 1 : if (lpdwHandle) *lpdwHandle = 0;
246 : 1 : return 1024;
247 : : }
248 : 1 : inline BOOL GetFileVersionInfoA(const char* lptstrFilename, DWORD dwHandle, DWORD dwLen, void* lpData) {
249 : 1 : memset(lpData, 0, dwLen);
250 : 1 : return TRUE;
251 : : }
252 : 8 : inline BOOL VerQueryValueA(const void* pBlock, const char* lpSubBlock, void** lplpBuffer, UINT* puLen) {
253 : : static uint16_t translation[2] = { 0x0409, 0x04B0 }; // English (US), Unicode
254 [ + + ]: 8 : if (strstr(lpSubBlock, "Translation")) {
255 : 2 : *lplpBuffer = &translation;
256 [ + - ]: 2 : if (puLen) *puLen = sizeof(translation);
257 : 2 : return TRUE;
258 : : }
259 [ + + ]: 6 : if (strstr(lpSubBlock, "CompanyName")) {
260 : 2 : *lplpBuffer = (void*)"lmuFFB";
261 [ + - ]: 2 : if (puLen) *puLen = 7;
262 : 2 : return TRUE;
263 : : }
264 [ + + ]: 4 : if (strstr(lpSubBlock, "ProductVersion")) {
265 : 2 : *lplpBuffer = (void*)LMUFFB_VERSION;
266 [ + - ]: 2 : if (puLen) *puLen = (UINT)strlen(LMUFFB_VERSION) + 1;
267 : 2 : return TRUE;
268 : : }
269 : 2 : return FALSE;
270 : : }
271 : :
272 : : // D3D11 & DXGI Mocks for Issue #189
273 : : typedef enum D3D_DRIVER_TYPE { D3D_DRIVER_TYPE_HARDWARE = 0 } D3D_DRIVER_TYPE;
274 : : typedef enum D3D_FEATURE_LEVEL { D3D_FEATURE_LEVEL_10_0 = 0x1000, D3D_FEATURE_LEVEL_11_0 = 0xb000 } D3D_FEATURE_LEVEL;
275 : : #define D3D11_SDK_VERSION (7)
276 : :
277 : : typedef struct DXGI_SAMPLE_DESC { UINT Count; UINT Quality; } DXGI_SAMPLE_DESC;
278 : : typedef enum DXGI_FORMAT { DXGI_FORMAT_R8G8B8A8_UNORM = 28, DXGI_FORMAT_UNKNOWN = 0 } DXGI_FORMAT;
279 : : typedef enum DXGI_USAGE { DXGI_USAGE_RENDER_TARGET_OUTPUT = 1 << 4 } DXGI_USAGE;
280 : : typedef enum DXGI_SWAP_EFFECT { DXGI_SWAP_EFFECT_DISCARD = 0, DXGI_SWAP_EFFECT_FLIP_DISCARD = 4 } DXGI_SWAP_EFFECT;
281 : : typedef enum DXGI_SWAP_CHAIN_FLAG { DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH = 2 } DXGI_SWAP_CHAIN_FLAG;
282 : : typedef enum DXGI_SCALING { DXGI_SCALING_STRETCH = 0 } DXGI_SCALING;
283 : : typedef enum DXGI_ALPHA_MODE { DXGI_ALPHA_MODE_UNSPECIFIED = 0 } DXGI_ALPHA_MODE;
284 : :
285 : : typedef struct DXGI_SWAP_CHAIN_DESC1 {
286 : : UINT Width; UINT Height; DXGI_FORMAT Format; BOOL Stereo; DXGI_SAMPLE_DESC SampleDesc;
287 : : DXGI_USAGE BufferUsage; UINT BufferCount; DXGI_SCALING Scaling; DXGI_SWAP_EFFECT SwapEffect;
288 : : DXGI_ALPHA_MODE AlphaMode; UINT Flags;
289 : : } DXGI_SWAP_CHAIN_DESC1;
290 : :
291 : : typedef struct DXGI_SWAP_CHAIN_FULLSCREEN_DESC {
292 : : struct { UINT Numerator; UINT Denominator; } RefreshRate;
293 : : int ScanlineOrdering; int Scaling; BOOL Windowed;
294 : : } DXGI_SWAP_CHAIN_FULLSCREEN_DESC;
295 : :
296 : : // Mock interfaces
297 : : struct IUnknown {
298 : : virtual HRESULT QueryInterface(const GUID& riid, void** ppvObject) = 0;
299 : : virtual ULONG_PTR Release() = 0;
300 : : };
301 : :
302 : : struct IDXGIObject : public IUnknown {};
303 : : struct IDXGIDevice : public IDXGIObject {
304 : : virtual HRESULT GetAdapter(struct IDXGIAdapter** ppAdapter) = 0;
305 : : };
306 : : struct IDXGIAdapter : public IDXGIObject {
307 : : virtual HRESULT GetParent(const GUID& riid, void** ppParent) = 0;
308 : : };
309 : : struct IDXGIFactory2 : public IDXGIObject {
310 : : virtual HRESULT CreateSwapChainForHwnd(IUnknown* pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pDesc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, struct IDXGIOutput* pRestrictToOutput, struct IDXGISwapChain1** ppSwapChain) = 0;
311 : : };
312 : :
313 : : // Concrete mock for testing
314 : : struct MockDXGIFactory2 : public IDXGIFactory2 {
315 : 1 : HRESULT QueryInterface(const GUID& riid, void** ppvObject) override { return -1; }
316 : 1 : ULONG_PTR Release() override { return 0; }
317 : 3 : HRESULT CreateSwapChainForHwnd(IUnknown* pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pDesc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, struct IDXGIOutput* pRestrictToOutput, struct IDXGISwapChain1** ppSwapChain) override {
318 [ + + ]: 3 : if (pDesc) {
319 : : extern DXGI_SWAP_CHAIN_DESC1 g_captured_swap_chain_desc;
320 : 2 : g_captured_swap_chain_desc = *pDesc;
321 : : }
322 : 3 : return 0; // S_OK
323 : : }
324 : : };
325 : : struct IDXGISwapChain : public IDXGIObject {
326 : : virtual HRESULT GetBuffer(UINT Buffer, const GUID& riid, void** ppSurface) = 0;
327 : : virtual HRESULT Present(UINT SyncInterval, UINT Flags) = 0;
328 : : virtual HRESULT ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) = 0;
329 : : };
330 : : struct IDXGISwapChain1 : public IDXGISwapChain {};
331 : :
332 : : struct ID3D11DeviceChild : public IUnknown {};
333 : : struct ID3D11DeviceContext : public ID3D11DeviceChild {
334 : : virtual void OMSetRenderTargets(UINT NumViews, struct ID3D11RenderTargetView* const* ppRenderTargetViews, struct ID3D11DepthStencilView* pDepthStencilView) = 0;
335 : : virtual void ClearRenderTargetView(struct ID3D11RenderTargetView* pRenderTargetView, const float ColorRGBA[4]) = 0;
336 : : };
337 : : struct ID3D11Device : public IUnknown {
338 : : virtual HRESULT CreateRenderTargetView(struct ID3D11Resource* pResource, const struct D3D11_RENDER_TARGET_VIEW_DESC* pDesc, struct ID3D11RenderTargetView** ppRTView) = 0;
339 : : };
340 : :
341 : : #define IID_PPV_ARGS(ppType) GUID(), (void**)(ppType)
342 : :
343 : : #endif // _WIN32
344 : :
345 : : #endif // LINUXMOCK_H
|