1 /**
2    Exception classes
3  */
4 module unit_threaded.exception;
5 
6 void fail(const string output, const string file, size_t line) @safe pure
7 {
8     throw new UnitTestException([output], file, line);
9 }
10 
11 void fail(const string[] lines, const string file, size_t line) @safe pure
12 {
13     throw new UnitTestException(lines, file, line);
14 }
15 
16 /**
17  * An exception to signal that a test case has failed.
18  */
19 public class UnitTestException : Exception
20 {
21     mixin UnitTestFailureImpl;
22 }
23 
24 public class UnitTestError : Error
25 {
26     mixin UnitTestFailureImpl;
27 }
28 
29 private template UnitTestFailureImpl()
30 {
31     this(const string msg, string file = __FILE__,
32          size_t line = __LINE__, Throwable next = null) @safe pure nothrow
33     {
34         this([msg], file, line, next);
35     }
36 
37     this(const string[] msgLines, string file = __FILE__,
38          size_t line = __LINE__, Throwable next = null) @safe pure nothrow
39     {
40         import std.string: join;
41         static if (is(typeof(this) : Exception))
42         {
43             super(msgLines.join("\n"), next, file.dup, line);
44         }
45         else
46         {
47             super(msgLines.join("\n"), file.dup, line, next);
48         }
49         this.msgLines = msgLines.dup;
50     }
51 
52     override string toString() @safe const pure scope
53     {
54         import std.algorithm: map;
55         import std.array: join;
56         return msgLines.map!(a => getOutputPrefix(file, line) ~ a).join("\n");
57     }
58 
59 private:
60 
61     const string[] msgLines;
62 
63     string getOutputPrefix(in string file, in size_t line) @safe const pure scope
64     {
65         import std.conv: text;
66         return text("    ", file, ":", line, " - ");
67     }
68 }