2 using System
.Collections
.Generic
;
4 using System
.Runtime
.CompilerServices
;
5 using System
.Reflection
;
6 using System
.Web
.Script
.Serialization
;
7 using Diag
= System
.Diagnostics
;
8 using System
.Runtime
.InteropServices
;
14 public static List
<Tuple
<String
, Action
>> Crashers
;
15 public static int StresserIndex
;
17 static CrasherClass ()
19 Crashers
= new List
<Tuple
<String
, Action
>> ();
21 // Basic functionality
22 Crashers
.Add(new Tuple
<String
, Action
> ("MerpCrashManaged", MerpCrashManaged
));
23 // Run this test for stress tests
25 // I've ran a burn-in with all of them of
26 // 1,000 - 10,000 runs already.
28 // Feel free to change by moving this line.
29 StresserIndex
= Crashers
.Count
- 1;
31 Crashers
.Add(new Tuple
<String
, Action
> ("MerpCrashMalloc", MerpCrashMalloc
));
33 Crashers
.Add(new Tuple
<String
, Action
> ("MerpCrashNullFp", MerpCrashNullFp
));
34 Crashers
.Add(new Tuple
<String
, Action
> ("MerpCrashExceptionHook", MerpCrashUnhandledExceptionHook
));
36 // Specific Edge Cases
37 Crashers
.Add(new Tuple
<String
, Action
> ("MerpCrashDladdr", MerpCrashDladdr
));
38 Crashers
.Add(new Tuple
<String
, Action
> ("MerpCrashSnprintf", MerpCrashSnprintf
));
39 Crashers
.Add(new Tuple
<String
, Action
> ("MerpCrashDomainUnload", MerpCrashDomainUnload
));
40 Crashers
.Add(new Tuple
<String
, Action
> ("MerpCrashUnbalancedGCSafe", MerpCrashUnbalancedGCSafe
));
46 unsafe { Console.WriteLine("{0}
", *(int*) -1); }
49 [DllImport("libtest
")]
50 public static extern void mono_test_MerpCrashSnprintf ();
52 // This test tries to test the writer's reentrancy
56 mono_test_MerpCrashSnprintf ();
59 [DllImport("libtest
")]
60 public static extern void mono_test_MerpCrashDladdr ();
65 mono_test_MerpCrashDladdr ();
68 [DllImport("libtest
")]
69 public static extern void mono_test_MerpCrashMalloc ();
74 mono_test_MerpCrashMalloc ();
77 [DllImport("libtest
")]
78 public static extern void mono_test_MerpCrashLoaderLock ();
81 MerpCrashLoaderLock ()
83 mono_test_MerpCrashLoaderLock ();
86 [DllImport("libtest
")]
87 public static extern void mono_test_MerpCrashDomainUnload ();
90 MerpCrashDomainUnload ()
92 mono_test_MerpCrashDomainUnload ();
95 [DllImport("libtest
")]
96 public static extern void mono_test_MerpCrashUnbalancedGCSafe ();
99 MerpCrashUnbalancedGCSafe ()
101 mono_test_MerpCrashUnbalancedGCSafe ();
104 [DllImport("libtest
")]
105 public static extern void mono_test_MerpCrashNullFp ();
110 mono_test_MerpCrashNullFp ();
113 [DllImport("libtest
")]
114 public static extern void mono_test_MerpCrashUnhandledExceptionHook ();
117 MerpCrashUnhandledExceptionHook ()
119 AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(HandleException);
120 throw new Exception ("This
is Unhandled
");
123 public static void HandleException (object sender, UnhandledExceptionEventArgs e)
125 Console.WriteLine ("And now to crash inside the hook
");
126 mono_test_MerpCrashUnhandledExceptionHook ();
130 static string configDir = "./merp
-crash
-test
/";
133 CrashWithMerp (int testNum)
135 SetupCrash (configDir);
136 CrasherClass.Crashers [Convert.ToInt32 (testNum)].Item2 ();
139 public static string env = Environment.GetEnvironmentVariable ("MONO_PATH
");
140 public static string this_assembly_path = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location);
143 SetupCrash (string configDir)
145 var monoType = Type.GetType ("Mono
.Runtime
", false);
146 var m = monoType.GetMethod("EnableMicrosoftTelemetry
", BindingFlags.NonPublic | BindingFlags.Static);
148 // This leads to open -a /bin/cat, which errors out, but errors
149 // in invoking merp are only logged errors, not fatal assertions.
150 var merpGUIPath = "/bin
/cat
";
151 var appBundleId = "com
.xam
.Minimal
";
152 var appSignature = "Test
.Xam
.Minimal
";
153 var appVersion = "123456";
154 var eventType = "AppleAppCrash
";
155 var appPath = "/where
/mono
/lives
";
156 var m_params = new object[] { appBundleId, appSignature, appVersion, merpGUIPath, eventType, appPath, configDir };
158 m.Invoke(null, m_params);
164 TestValidate (string configDir, bool silent)
168 var xmlFilePath = String.Format("{0}CustomLogsMetadata
.xml
", configDir);
169 var paramsFilePath = String.Format("{0}MERP
.uploadparams
.txt
", configDir);
170 var crashFilePath = String.Format("{0}lastcrashlog
.txt
", configDir);
172 // Fixme: Maybe parse these json files rather than
173 // just checking they exist
174 var xmlFileExists = File.Exists (xmlFilePath);
175 var paramsFileExists = File.Exists (paramsFilePath);
176 var crashFileExists = File.Exists (crashFilePath);
179 var text = File.ReadAllText (xmlFilePath);
181 Console.WriteLine ("Xml file {0}
", text);
182 File.Delete (xmlFilePath);
184 Console.WriteLine ("Xml file {0} missing
", xmlFilePath);
187 if (paramsFileExists) {
188 var text = File.ReadAllText (paramsFilePath);
190 Console.WriteLine ("Params file {0}
", text);
191 File.Delete (paramsFilePath);
193 Console.WriteLine ("Params file {0} missing
", paramsFilePath);
196 if (crashFileExists) {
197 var crashFile = File.ReadAllText (crashFilePath);
198 File.Delete (crashFilePath);
200 var checker = new JavaScriptSerializer ();
202 // Throws if invalid json
204 Console.WriteLine("Validating
: {0}
", crashFile);
206 var obj = checker.DeserializeObject (crashFile);
207 } catch (Exception e) {
208 throw new Exception (String.Format ("Invalid json
: {0}
", crashFile));
211 File.Delete (crashFilePath);
212 // Assert it has the required merp fields
214 Console.WriteLine ("Crash file {0} missing
", crashFilePath);
218 throw new Exception (String.Format ("Did not produce {0}
", xmlFilePath));
220 if (!paramsFileExists)
221 throw new Exception (String.Format ("Did not produce {0}
", paramsFilePath));
223 if (!crashFileExists)
224 throw new Exception (String.Format ("Did not produce {0}
", crashFilePath));
228 Cleanup (string configDir)
230 Directory.Delete (configDir, true);
233 static void DumpLogSet ()
235 var monoType = Type.GetType ("Mono
.Runtime
", false);
236 var convert = monoType.GetMethod("EnableCrashReportLog
", BindingFlags.NonPublic | BindingFlags.Static);
237 convert.Invoke(null, new object[] { "./" });
240 static void DumpLogUnset ()
242 var monoType = Type.GetType ("Mono
.Runtime
", false);
243 var convert = monoType.GetMethod("EnableCrashReportLog
", BindingFlags.NonPublic | BindingFlags.Static);
244 convert.Invoke(null, new object[] { null });
247 static void DumpLogCheck ()
249 var monoType = Type.GetType ("Mono
.Runtime
", false);
250 var convert = monoType.GetMethod("CheckCrashReportLog
", BindingFlags.NonPublic | BindingFlags.Static);
251 var result = (int) convert.Invoke(null, new object[] { "./", true });
253 string [] levels = new string [] { "None", "Setup", "SuspendHandshake", "UnmanagedStacks", "ManagedStacks", "StateWriter", "StateWriterDone", "MerpWriter", "MerpInvoke", "Cleanup", "Done", "DoubleFault" };
255 if ("MerpInvoke
" == levels [result]) {
256 Console.WriteLine ("Merp invoke command failed
, expected failure
?");
257 } else if ("Done
" != levels [result]) {
258 throw new Exception (String.Format ("Crash level not done
, failed
in stage
: {0}
", levels [result]));
264 SpawnCrashingRuntime (string runtime, int testNum, bool silent)
266 var asm = "merp
-crash
-test
.exe
";
267 var pi = new Diag.ProcessStartInfo ();
268 pi.UseShellExecute = false;
269 pi.FileName = runtime;
270 pi.Arguments = String.Format ("{0} {1}
", asm, testNum);;
271 pi.Environment ["MONO_PATH
"] = env;
274 Console.WriteLine ("Running {0}
", CrasherClass.Crashers [testNum].Item1);
275 Console.WriteLine ("MONO_PATH
={0} {1} {2} {3}
", env, runtime, asm, testNum);
278 if (Directory.Exists (configDir)) {
279 Console.WriteLine ("Cleaning up left over configDir {0}
", configDir);
283 Directory.CreateDirectory (configDir);
286 var process = Diag.Process.Start (pi);
287 process.WaitForExit ();
289 TestValidate (configDir, silent);
295 public static int Main (string [] args)
297 if (args.Length == 0) {
298 string processExe = Diag.Process.GetCurrentProcess ().MainModule.FileName;
299 if (processExe == null)
300 throw new ArgumentException ("Couldn
't get name of running file");
301 else if (string.IsNullOrEmpty (processExe))
302 throw new ArgumentException ("Couldn't find mono runtime
.");
303 else if (!Path.GetFileName (processExe).StartsWith ("mono
"))
304 throw new ArgumentException (String.Format("Running native app {0} isn
't 'mono
'"));
306 var failures = new Exception [CrasherClass.Crashers.Count];
307 int failure_count = 0;
308 for (int i=0; i < CrasherClass.Crashers.Count; i++) {
310 SpawnCrashingRuntime (processExe, i, false);
311 } catch (Exception e) {
313 if (e.InnerException != null)
314 failures [i] = e.InnerException;
319 Console.WriteLine ("\n\n##################");
320 Console.WriteLine ("Merp Test Results:");
321 Console.WriteLine ("##################\n\n");
323 if (failure_count > 0) {
324 for (int i=0; i < CrasherClass.Crashers.Count; i++) {
325 if (failures [i] != null) {
326 Console.WriteLine ("Crash reporter failed test {0}", CrasherClass.Crashers [i].Item1);
327 Console.WriteLine ("Cause: {0}\n{1}\n", failures [i].Message, failures [i].StackTrace);
332 if (failure_count > 0)
335 Console.WriteLine ("\n\n##################");
336 Console.WriteLine ("Merp Stress Test:");
337 Console.WriteLine ("##################\n\n");
339 Console.WriteLine ("Starting crash stress test\n");
341 for (iter=0; iter < 20; iter++) {
342 Console.WriteLine ("\n#############################################");
343 Console.WriteLine ("\tMerp Stress Test Iteration {0}", iter);
344 Console.WriteLine ("#############################################\n");
346 SpawnCrashingRuntime (processExe, CrasherClass.StresserIndex, true);
347 } catch (Exception e) {
348 Console.WriteLine ("Stress test caught failure. Shutting down after {1} iterations.\n {0} \n\n", e.InnerException, iter);
352 Console.WriteLine ("Ending crash stress test. No failures caught.\n");
356 CrashWithMerp (Convert.ToInt32 (args [0]));