1 krisbash 1.1 //*****************************************************************************
2 // Copyright (C) 2008 Microsoft Corporation
3 // All rights reserved.
4 //*****************************************************************************
5
6 #ifndef __GLOBALS_H__
7 #define __GLOBALS_H__
8
9 #ifndef TEST_BUILD
10 #define TEST_BUILD
11 #endif
12
13 #ifdef _MSC_VER
14 #include <windows.h>
15 #else
16 #include <signal.h>
17 #endif
18 #include <vector>
19 #include <sstream>
20
21 #include <pal/palcommon.h>
22 krisbash 1.1
23 #ifndef NITS_EXPORT
24 # define NITS_EXPORT PAL_EXTERN_C PAL_EXPORT_API
25 #endif
26
27 #include "nits.h"
28 #include "Frame.h"
29
30 #include <pal/atomic.h>
31 #include <pal/sleep.h>
32 #include <pal/sem.h>
33 #include <pal/cpu.h>
34 #include <pal/shmem.h>
35 #include <pal/shlib.h>
36 #include <pal/thread.h>
37 #include <pal/format.h>
38
39 #define NITS_TRACING_LOCATION L"Microsoft\\NITS"
40
41 #define WPP_USE_NTDLL_FUNCTIONS
42 #define WPP_CONTROL_GUIDS \
43 krisbash 1.1 WPP_DEFINE_CONTROL_GUID(NITS,(95bef1fc,d949,42d0,951a,ff1af27a6549), \
44 WPP_DEFINE_BIT(TestLifetime) \
45 )
46
47 PAL_INLINE void Atomic_Lock(
48 _Inout_ volatile ptrdiff_t* dest)
49 {
50 while (Atomic_Swap(dest, 1) == 1)
51 while (*dest)
52 ;
53 }
54
55 PAL_INLINE void Atomic_Unlock(
56 _Inout_ volatile ptrdiff_t* dest)
57 {
58 Atomic_Swap(dest, 0);
59 }
60
61
62 enum NitsTraceLevel
63 {
64 krisbash 1.1 NitsTraceFailedTests = 1, //Shows nothing except failed test cases.
65 NitsTraceWarnedTests = 2, //Shows test cases with warnings.
66 NitsTraceAllTests = 3, //Shows all test cases.
67 NitsTraceAsserts = 3, //Shows individual asserts.
68 NitsTraceWarnings = 4, //Shows individual asserts/warnings.
69 NitsTraceIterations = 5, //Shows fault injection iterations.
70 NitsTraceVerbose = 6 //Shows product and other traces.
71 };
72
73 enum {
74 CallSite_NONE = -1, //Anonymous call site.
75 CallSite_ALL = -2 //Automatic fault loops.
76 };
77
78 struct Configuration
79 {
80 NitsTraceLevel traces;
81 NitsTestMode mode;
82 //NitsIsolationMode isolation;
83 //NitsResourceScope scope;
84 bool breakAssert;
85 krisbash 1.1 bool breakFault;
86 bool skipFlakyTests;
87 };
88
89 struct Statistics
90 {
91 unsigned faultIterations;
92 unsigned shouldFaults;
93 unsigned currentTestProcess;
94 unsigned frameLookups;
95 unsigned frameInsertions;
96 unsigned frameHashHits;
97 unsigned frameHits[16];
98 unsigned stackLookups;
99 unsigned stackTicks;
100 };
101
102 namespace TestSystem
103 {
104
105 using namespace std;
106 krisbash 1.1
107 bool StartsWith(_In_z_ const PAL_Char * str, _In_z_ const PAL_Char * prefix);
108 bool Equals(_In_z_ const PAL_Char * str, _In_z_ const PAL_Char * target);
109 bool EqualsCI(_In_z_ const PAL_Char * str, _In_z_ const PAL_Char * target);
110
111 PAL_Char *Copy(_In_opt_z_ const PAL_Char * str);
112
113 class Exception
114 {
115 public:
116 Exception(_In_ const PAL_Char * message = PAL_T("")) : m_message(message) {}
117
118 const PAL_Char * GetMessage() const {return m_message;}
119 private:
120 const PAL_Char * m_message;
121 };
122
123 inline void FatalError() {throw Exception();}
124
125 //Used for defining wostringstream objects in nits.h.
126 //Avoids public header file dependency on STL.
127 krisbash 1.1 class Buffer
128 {
129 public:
130 Buffer(wostringstream &data) : m_data(data) {}
131
132 operator wostringstream &() {return m_data;}
133
134 wostringstream &m_data;
135
136 Buffer(const Buffer&);
137 Buffer& operator=( const Buffer& );
138 };
139
140 //Used for defining vector objects in nits.h.
141 //Avoids public header file dependency on STL.
142 class ChildList
143 {
144 public:
145 operator vector<Switch *> const &() const {return m_list;}
146 operator vector<Switch *> &() {return m_list;}
147
148 krisbash 1.1 vector<Switch *> m_list;
149 };
150
151 enum SharedStatus
152 {
153 Unloaded = 0,
154 Loading,
155 Loaded
156 };
157
158 struct Mapping
159 {
160 PAL_Char *m_name;
161
162 Shmem *m_mapping;
163 ptrdiff_t volatile *m_status; //Initialization spinlock.
164
165 void *m_data; //Shared data section.
166 long m_bytes; //Length of data section.
167
168 void *m_copy; //Initial data values.
169 krisbash 1.1
170 DWORD Initialize(_In_reads_bytes_(bytes) void const *context, long bytes);
171
172 void Reset();
173 };
174
175 class Fault
176 {
177 public:
178 enum {
179 FileSize = 256
180 };
181
182 Fault();
183
184 void Reset(int site, int iteration, bool breakOnFault);
185 bool ShouldFault(CallSite const &site);
186 bool DidFault() const {return m_faulted;}
187 void Toggle(bool enabled);
188 CallSite GetFaultedSite() const;
189
190 krisbash 1.1 int m_site;
191 int m_iteration;
192 volatile ptrdiff_t m_attempt;
193 volatile ptrdiff_t m_lock;
194
195 bool m_break;
196 bool volatile m_faulted;
197 bool volatile m_filtered;
198 int m_hit;
199 int m_line;
200 char m_file[FileSize];
201
202 //Used for filtering causal anomalies.
203 ThreadID m_mainThread;
204 ptrdiff_t m_minimumAttemptDifferentThread;
205 ptrdiff_t m_firstAttemptDifferentThread;
206 ptrdiff_t m_faultedAttempt;
207 };
208
209 struct InjectorTarget
210 {
211 krisbash 1.1 void *signalSemaphore;
212 void *waitSemaphore;
213 void *lockSemaphore;
214 ptrdiff_t process;
215 };
216
217 static const int InjectorListSize = 1024;
218 static const int SharedMemoryVersion = 3; //Increment after each change to Globals.
219
220 enum PipeOutputType
221 {
222 NoMessage,
223 InfoMessage,
224 WttLogTestStart,
225 WttLogTestEnd
226 };
227
228 //Internal self-relative data structure.
229 //Propagates test commands and state across processes.
230 class Globals
231 {
232 krisbash 1.1 public:
233 int m_version; //Used to match against SharedMemoryVersion.
234 int m_unload; //Triggers the injector to self-unload everywhere.
235
236 enum {
237 PipeSize = 1024,
238 StringSize = 256
239 };
240
241 Globals();
242 ~Globals();
243
244 bool IsUnittestRunning();
245 bool StartRun(bool force = false);
246 void StopRun();
247 void CheckRun(); //Makes sure the test process is alive.
248
249 void Reset(); //Erases test status.
250 void AttachDebugger();
251 void CheckDebugger();
252 void SetFault(int site,
253 krisbash 1.1 int attempt,
254 HRESULT error,
255 _In_z_ const PAL_Char * event);
256 Fault &GetAutoFault() {return m_simAuto;}
257
258 NitsResult TestExpression(bool test, NitsFaultMode mode);
259 NitsResult ShouldFault(CallSite const &site, NitsFaultMode mode);
260 NitsResult DidFault();
261
262 void StopReportingIgnoredErrors()
263 {
264 //This function has no effect if the fault already happened.
265 //The purpose is to indicate that *future* faults are purposefully ignored.
266 if (!DidFault())
267 m_stopReportingIgnoredErrors = true;
268 }
269 bool ShouldReportIgnoredErrors() {return !m_stopReportingIgnoredErrors;}
270 void ResetIgnoredErrorReporting() {m_stopReportingIgnoredErrors = false;}
271
272 HRESULT GetFaultError() const {return m_faultError;}
273 Result GetResult() const {return m_result;}
274 krisbash 1.1 Configuration const &GetConfiguration() const {return m_config;}
275 void SetConfiguration(Configuration const &config) {m_config = config;}
276 Statistics &GetStats() {return m_stats;}
277 int *GetStatistics() {return m_statistics;}
278
279 void SetResult(Result result) {m_result = result;}
280 void SetDebugger(_In_z_ const PAL_Char * debugger);
281
282 void **GetStackTrace() {return m_stackTrace;}
283
284 void SetRunTime(double seconds) {m_runTimeInSeconds = seconds;}
285 double GetRunTime() {return m_runTimeInSeconds;}
286
287 #if defined(CONFIG_HAVE_BACKTRACE)
288 FrameCache m_frames;
289 #endif
290
291 public:
292 void PostPipe(_In_z_ const PAL_Char * text, PipeOutputType outputType = InfoMessage); //Adds text to out-of-proc buffer.
293 void DumpPipe(); //Dumps pipe to stderr.
294 bool IsPipeEmpty();
295 krisbash 1.1 void LockPipe();
296 void UnlockPipe();
297 void EmptyPipe();
298 PAL_Char *GetPipe() { return m_pipe; }
299 PipeOutputType GetPipeOutputType() { return m_pipeOutputType; }
300 ptrdiff_t volatile m_runLock; //PID of test run in progress.
301 private:
302 ptrdiff_t volatile m_attachLock; //PID of process being attached to debugger.
303 ptrdiff_t volatile m_pipeLock; //Pipe synchronization.
304 long m_pipeChars; //Buffer size used.
305
306 bool m_stopReportingIgnoredErrors;
307
308 Configuration m_config;
309 Statistics m_stats;
310
311 Result m_result; //Current test result.
312
313 public:
314 Fault m_simAuto;
315 Fault m_simManual;
316 krisbash 1.1
317 PAL_Char m_binaryFilter[1024];
318 PAL_Char m_binaryTarget[1024];
319 InjectorTarget m_injectors[InjectorListSize];
320 private:
321
322 int m_statistics[ResultCount];
323
324 HRESULT m_faultError;
325 PAL_Char m_faultEvent[Event::MaxName];
326 PAL_Char m_pipe[PipeSize];
327 PAL_Char m_debugger[1024]; //Used for automatic debugger attaching.
328
329 void *m_stackTrace[50];
330 double m_runTimeInSeconds;
331 PipeOutputType m_pipeOutputType;
332 };
333
334 class System
335 {
336 public:
337 krisbash 1.1 static System &GetInstance() {return s_system;}
338
339 System();
340 ~System();
341
342 NamedSem *GetPipeEvent() const {return (NamedSem *)&m_pipeEvent;}
343 Globals const &GetGlobals() const;
344 Globals &GetGlobals();
345 Mapping &GetMapping(_In_z_ const PAL_Char * name);
346 void ResetClientMappings();
347 private:
348 NamedSem m_pipeEvent;
349 Globals *m_globals;
350 vector<Mapping> m_mappings;
351 static System s_system;
352 };
353
354 inline Globals &GetGlobals() {return System::GetInstance().GetGlobals();}
355
356 }; //namespace TestSystem
357
358 krisbash 1.1 /*
359 **==============================================================================
360 **
361 ** Conversion functions between Ansi/WideChar/PAL_Char strings
362 **
363 **==============================================================================
364 */
365 PWSTR ConvertStringToW(_In_opt_z_ const char *buf);
366 PSTR ConvertStringToA(_In_opt_z_ const wchar_t *buf);
367 PAL_Char *ConvertStringAToPalChar(_In_opt_z_ const char *buf);
368 PAL_Char *ConvertStringWToPalChar(_In_opt_z_ const wchar_t *buf);
369 char *ConvertPalCharToStringA(_In_opt_z_ const PAL_Char *buf);
370
371 #ifdef _MSC_VER
372 #define MyDebugBreak DebugBreak()
373 #else
374 #define MyDebugBreak raise(SIGTRAP)
375 #endif
376
377 #endif // ndef __GLOBALS_H__
|