1 /** A Better assert.
2 
3 	Copyright: Per Nordlöw 2022-.
4 	License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
5 	Authors: $(WEB Per Nordlöw)
6 
7 	TODO: make these pure nothrow @safe @nogc by utilizing dynamic_array and printf
8 
9 	extend to something like:
10 
11 	- must!"a == b"(x, y);
12 	- check!"a == b"(x, y);
13 	- require!"a == b"(x, y);
14 */
15 module nxt.assert_ex;
16 
17 // import std.string : format;
18 import core.exception : AssertError;
19 import std.conv: to;
20 
21 @trusted:
22 
23 /// Returns: true if the expression throws.
24 bool assertThrows(T:Throwable = Exception, E)(lazy E expression,
25 											  string msg = T.stringof,
26 											  string file = __FILE__,
27 											  int line = __LINE__ ) {
28 	try {
29 		std.exception.assertThrown!T(expression, msg, file, line);
30 		return true;
31 	} catch (Throwable exc) {
32 		// FIXTHIS: unhelpful error message
33 		writeln("failed at ", baseName(file), "(", line, "):",
34 				" Did not throw \"", msg, "\".");
35 		return false;
36 	}
37 }
38 
39 nothrow:
40 
41 /** A Better assert.
42 	See_Also: http://poita.org/2012/09/02/a-better-assert-for-d.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+poita+%28poita.org%29
43 	TODO: Can we convert args to strings like GCC's __STRING(expression)?
44 	TODO: Make these be able to be called in unittest placed in struct scopes
45 */
46 void assertTrue(T,
47 				string file = __FILE__, uint line = __LINE__,
48 				Args...) (T test, lazy Args args) {
49 	version (assert) if (!test) {
50 		throw new AssertError("at \n" ~file~ ":" ~to!string(line)~ ":\n  test: " ~to!string(test));
51 	}
52 }
53 alias assertT = assertTrue;
54 
55 void assertEqual(T, U,
56 				 string file = __FILE__, uint line = __LINE__,
57 				 Args...)(T lhs, U rhs,
58 						  lazy Args args) /+ TODO: use args +/
59 {
60 	version (assert) if (lhs != rhs) {
61 		throw new AssertError("at \n" ~file~ ":" ~to!string(line)~ ":\n  lhs: " ~to!string(lhs)~ " !=\n  rhs: " ~to!string(rhs));
62 	}
63 }
64 alias assertE = assertEqual;
65 
66 void assertLessThanOrEqual(T, U,
67 						   string file = __FILE__,
68 						   uint line = __LINE__,
69 						   Args...) (T lhs, U rhs,
70 									 lazy Args args) /+ TODO: use args +/
71 {
72 	version (assert) if (lhs > rhs) {
73 		throw new AssertError("at \n" ~file~ ":" ~to!string(line)~ ":\n  lhs: " ~to!string(lhs)~ " >\n  rhs: " ~to!string(rhs));
74 	}
75 }
76 alias assertLTE = assertLessThanOrEqual;
77 
78 void assertLessThan(T, U,
79 					string file = __FILE__, uint line = __LINE__,
80 					Args...) (T lhs, U rhs,
81 							  lazy Args args) /+ TODO: use args +/
82 {
83 	version (assert) if (lhs >= rhs) {
84 		throw new AssertError("at \n" ~file~ ":" ~to!string(line)~ ":\n  lhs: " ~to!string(lhs)~ " >=\n  rhs: " ~to!string(rhs));
85 	}
86 }
87 alias assertLT = assertLessThan;
88 
89 void assertNotEqual(T, U,
90 					string file = __FILE__, uint line = __LINE__,
91 					Args...) (T lhs, U rhs,
92 							  lazy Args args) /+ TODO: use args +/
93 {
94 	version (assert) if (lhs == rhs) {
95 		throw new AssertError("at \n" ~file~ ":" ~to!string(line)~ ":\n  lhs: " ~to!string(lhs)~ " ==\n  rhs: " ~to!string(rhs));
96 	}
97 }
98 alias assertNE = assertNotEqual;