1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 using System.Diagnostics;
7 using System.Runtime.Serialization;
11 public enum ErrorHandlingAction
13 // If you add an item here, remember to add it to all of the methods below
19 /// Static class containing methods to report errors.
21 /// The StressTest executor will eat exceptions that are thrown and write them out to the console. In theory these should all be
22 /// either harmless exceptions or product bugs, however at present there are a large number of test issues that will cause a flood
23 /// of exceptions. Therefore if something actually bad happens (e.g. a known product bug is hit due to regression, or a major test
24 /// programming error) this error would be easy to miss if it were reported just by throwing an exception. To solve this, we use
25 /// this class for structured & consistent handling of errors.
27 public static class DataStressErrors
29 private static void DebugBreak(string message, Exception exception)
31 // Print out the error before breaking to make debugging easier
32 Console.WriteLine(message);
33 if (exception != null)
35 Console.WriteLine(exception);
42 /// Reports that a product bug has been hit. The action that will be taken is configurable in the .config file.
43 /// This can be used to check for regressions of known product bugs.
45 /// <param name="description">A description of the product bug hit (e.g. title, bug number & database, more information)</param>
46 /// <param name="exception">The exception that was thrown that indicates a product bug, or null if the product bug was detected without
47 /// having thrown an exception</param>
48 /// <returns>An exception that the caller should throw.</returns>
49 public static Exception ProductError(string description, Exception exception = null)
51 switch (DataStressSettings.Instance.ActionOnProductError)
53 case ErrorHandlingAction.DebugBreak:
54 DebugBreak("Hit product error: " + description, exception);
55 return new ProductErrorException(description, exception);
57 case ErrorHandlingAction.ThrowException:
58 return new ProductErrorException(description, exception);
61 throw UnhandledCaseError(DataStressSettings.Instance.ActionOnProductError);
66 /// Reports that a non-fatal test error has been hit. The action that will be taken is configurable in the .config file.
67 /// This should be used for test errors that do not prevent the test from running.
69 /// <param name="description">A description of the error</param>
70 /// <param name="exception">The exception that was thrown that indicates an error, or null if the error was detected without
71 /// <returns>An exception that the caller should throw.</returns>
72 public static Exception TestError(string description, Exception exception = null)
74 switch (DataStressSettings.Instance.ActionOnTestError)
76 case ErrorHandlingAction.DebugBreak:
77 DebugBreak("Hit test error: " + description, exception);
78 return new TestErrorException(description, exception);
80 case ErrorHandlingAction.ThrowException:
81 return new TestErrorException(description, exception);
84 throw UnhandledCaseError(DataStressSettings.Instance.ActionOnTestError);
89 /// Reports that a programming error in the test code has occurred. The action that will be taken is configurable in the .config file.
90 /// This must strictly be used to report programming errors. It should not be in any way possible to see one of these errors unless
91 /// you make an incorrect change to the code, for example having an unhandled case in a switch statement.
93 /// <param name="description">A description of the error</param>
94 /// <param name="exception">The exception that was thrown that indicates an error, or null if the error was detected without
95 /// having thrown an exception</param>
96 /// <returns>An exception that the caller should throw.</returns>
97 private static Exception ProgrammingError(string description, Exception exception = null)
99 switch (DataStressSettings.Instance.ActionOnProgrammingError)
101 case ErrorHandlingAction.DebugBreak:
102 DebugBreak("Hit programming error: " + description, exception);
103 return new ProgrammingErrorException(description, exception);
105 case ErrorHandlingAction.ThrowException:
106 return new ProgrammingErrorException(description, exception);
109 // If we are here then it's a programming error, but calling UnhandledCaseError here would cause an inifite loop.
110 goto case ErrorHandlingAction.DebugBreak;
115 /// Reports that an unhandled case in a switch statement in the test code has occurred. The action that will be taken is configurable
116 /// as a programming error in the .config file. It should not be in any way possible to see one of these errors unless
117 /// you make an incorrect change to the test code, for example having an unhandled case in a switch statement.
119 /// <param name="unhandledValue">The value that was not handled in the switch statement</param>
120 /// <returns>An exception that the caller should throw.</returns>
121 public static Exception UnhandledCaseError<T>(T unhandledValue)
123 return ProgrammingError("Unhandled case in switch statement: " + unhandledValue);
127 /// Asserts that a condition is true. If the condition is false then throws a ProgrammingError.
128 /// This must strictly be used to report programming errors. It should not be in any way possible to see one of these errors unless
129 /// you make an incorrect change to the code, for example having an unhandled case in a switch statement.
131 /// <param name="condition">A condition to assert</param>
132 /// <param name="description">A description of the error</param>
133 /// <exception cref="ProgrammingErrorException">if the condition is false</exception>
134 public static void Assert(bool condition, string description)
138 throw ProgrammingError(description);
143 /// Reports that a fatal error has happened. This is an error that completely prevents the test from continuing,
144 /// for example a setup failure. Ordinary programming errors should not be handled by this method.
146 /// <param name="description">A description of the error</param>
147 /// <returns>An exception that the caller should throw.</returns>
148 public static Exception FatalError(string description)
150 Console.WriteLine("Fatal test error: {0}", description);
151 Debugger.Break(); // Give the user a chance to debug
152 Environment.FailFast("Fatal error. Exit.");
153 return new Exception(); // Caller should throw this to indicate to the compiler that any code after the call is unreachable
156 #region Exception types
158 // These exception types are provided so that they can be easily found in logs, i.e. just do a text search in the console
159 // output log for "ProductErrorException"
161 private class ProductErrorException : Exception
163 public ProductErrorException()
168 public ProductErrorException(string message)
173 public ProductErrorException(string message, Exception innerException)
174 : base(message, innerException)
179 private class ProgrammingErrorException : Exception
181 public ProgrammingErrorException()
186 public ProgrammingErrorException(string message)
191 public ProgrammingErrorException(string message, Exception innerException)
192 : base(message, innerException)
197 private class TestErrorException : Exception
199 public TestErrorException()
204 public TestErrorException(string message)
209 public TestErrorException(string message, Exception innerException)
210 : base(message, innerException)