1 /**
2   Copyright: 2017 © LLC CERERIS
3   License: MIT
4   Authors: LLC CERERIS
5 */
6 
7 module checkit.assertion;
8 
9 import checkit.exception;
10 import core.exception;
11 import core.time;
12 import std.algorithm.comparison: max, min;
13 import std.conv;
14 import std.datetime;
15 import std.range;
16 import std..string;
17 import std.traits;
18 
19 private void fail(in string output, in string file, in size_t line) @safe pure
20 {
21   throw new UnitTestException([output], file, line);
22 }
23 
24 /** Used to assert that one value is equal to null.
25 
26   Params:
27     value = The value that should equal null.
28     message = The exception message.
29     file = The file name that the assert failed in. Should be left as default.
30     line = The file line that the assert failed in. Should be left as default.
31   Throws:
32     If value is NOT null, will throw an UnitTestException.
33 
34   Examples:
35     ---
36     // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): Expected <null>, got <blah>."
37     string test = "blah";
38     test.shouldBeNull();
39     ---
40 */
41 void shouldBeNull(T)( in auto ref T value, 
42                       in string message = null,
43                       in string file = __FILE__, 
44                       in size_t line = __LINE__)
45 {
46   if(value !is null)
47   {
48     fail(message !is null ? message : "Expected <null>", file, line);
49   }
50 }
51 
52 /** Used to assert that one value is not equal to null.
53 
54   Params:
55     value = The value that should not equal null.
56     message = The exception message.
57     file = The file name that the assert failed in. Should be left as default.
58     line = The file line that the assert failed in. Should be left as default.
59   Throws:
60     If value is null, will throw an UnitTestException.
61 
62   Examples:
63     ---
64     // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): Expected not <null>, got <null>"
65     string test = null;
66     test.shouldNotBeNull();
67     ---
68 */
69 void shouldNotBeNull(T)(in auto ref T value, 
70                         in string message = null, 
71                         in string file = __FILE__, 
72                         in size_t line = __LINE__)
73 {
74 	if(value is null)
75   {
76     fail(message !is null ? message : "Expected not <null>, got <null>", file, line);
77 	}
78 }
79 
80 private enum isObject(T) = is(T == class) || is(T == interface);
81 
82 private bool isEqual(V, E)(in auto ref V value, in auto ref E expected)
83   if(!isObject!V &&
84     (!isInputRange!V || !isInputRange!E) &&
85     !isFloatingPoint!V && !isFloatingPoint!E &&
86     is(typeof(value == expected) == bool))
87 {
88   return value == expected;
89 }
90 
91 private bool isEqual(V, E)(in V value, in E expected)
92  if (!isObject!V && (isFloatingPoint!V || isFloatingPoint!E) && is(typeof(value == expected) == bool))
93 {
94   return value == expected;
95 }
96 
97 private bool isEqual(V, E)(V value, E expected)
98 if (!isObject!V && isInputRange!V && isInputRange!E && is(typeof(value.front == expected.front) == bool))
99 {
100   import std.algorithm: equal;
101   return equal(value, expected);
102 }
103 
104 private bool isEqual(V, E)(V value, E expected)
105 if (!isObject!V &&
106     isInputRange!V && isInputRange!E && !is(typeof(value.front == expected.front) == bool) &&
107     isInputRange!(ElementType!V) && isInputRange!(ElementType!E))
108 {
109   import std.algorithm: equal;
110 
111   while(!value.empty && !expected.empty)
112   {
113     if(!equal(value.front, expected.front))
114       return false;
115 
116     value.popFront;
117     expected.popFront;
118   }
119     
120   return value.empty && expected.empty;
121 }
122 
123 private bool isEqual(V, E)(V value, E expected)
124 if (isObject!V && isObject!E)
125 {
126   static assert(is(typeof(()
127   {
128     string s1 = value.toString;
129     string s2 = expected.toString;
130   })), "Cannot compare instances of " ~ V.stringof ~ " or " ~ E.stringof ~ " unless toString is overridden for both");
131 
132   return value.tupleof == expected.tupleof;
133 }
134 
135 /** Used to assert that one value is equal to another value.
136 
137   Params:
138     value = The value.
139     expected = The expected value.
140     message = The exception message.
141     file = The file name that the assert failed in. Should be left as default.
142     line = The file line that the assert failed in. Should be left as default.
143   Throws:
144     If values are not equal, will throw an UnitTestException with expected and actual values.
145 
146   Examples:
147     ---
148     // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): <3> expected to equal <5>."
149     int z = 3;
150     z.shouldEqual(5);
151     ---
152 */
153 void shouldEqual(T, U)( auto ref T value, 
154                         auto ref U expected, 
155                         in string message = null, 
156                         in string file = __FILE__, 
157                         in size_t line = __LINE__)
158 {
159   if(!isEqual(value, expected))
160   {
161     fail(message !is null ? message : "Expected <%s>, got <%s>".format(expected, value), file, line);
162 	}
163 }
164 
165 /** Used to assert that one value is not equal to another value.
166 
167   Params:
168     value = The value to test.
169     expected = The value it should not be equal to.
170     message = The exception message.
171     file = The file name that the assert failed in. Should be left as default.
172     line = The file line that the assert failed in. Should be left as default.
173   Throws:
174     If values are equal, will throw an UnitTestException with expected and actual values.
175 
176   Examples:
177     ---
178     // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): Expected not <abc>, got <abc>"
179     "abc".shouldNotEqual("abc");
180     ---
181 */
182 void shouldNotEqual(T, U)(T value, U expected, 
183                           in string message = null, 
184                           in string file = __FILE__, 
185                           in size_t line = __LINE__)
186 {
187 	if(isEqual(value, expected))
188   {
189     fail(message !is null ? message : "Expected not <%s>, got <%s>".format(expected, value), file, line);
190 	}
191 }
192 
193 /** Used to assert that one value is equal to true.
194 
195   Params:
196     condition = The value that should equal true.
197     message = The exception message.
198     file = The file name that the assert failed in. Should be left as default.
199     line = The file line that the assert failed in. Should be left as default.
200   Throws:
201     If values are not true, will throw an UnitTestException with expected and actual values.
202 
203   Examples:
204     ---
205     // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): Expected <true>, got <false>"
206     false.shouldBeTrue();
207     ---
208 */
209 void shouldBeTrue(T)(lazy T condition, in string message = null, in string file = __FILE__, in size_t line = __LINE__)
210 {
211   shouldEqual(cast(bool) condition, true, message, file, line);
212 }
213 
214 /** Used to assert that one value is equal to false.
215 
216   Params:
217     condition = The value that should equal false.
218     message = The exception message.
219     file = The file name that the assert failed in. Should be left as default.
220     line = The file line that the assert failed in. Should be left as default.
221   Throws:
222     If values are not false, will throw an UnitTestException with expected and actual values.
223 
224   Examples:
225     ---
226     // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): Expected <false>, got <true>"
227     true.shouldBeFalse();
228     ---
229 */
230 void shouldBeFalse(T)(lazy T condition, in string message = null, in string file = __FILE__, in size_t line = __LINE__)
231 {
232   shouldEqual(cast(bool) condition, false, message, file, line);
233 }
234 
235 private auto threw(T: Throwable, E)(lazy E expr) @trusted
236 {
237   struct ThrowResult
238   {
239     bool threw;
240     TypeInfo typeInfo;
241     immutable(T) throwable;
242 
243     T opCast(T)() const pure if (is(T == bool))
244     {
245       return threw;
246     }
247   }
248 
249   try
250   {
251     expr();
252   }
253   catch(T e)
254   {
255     return ThrowResult(true, typeid(e), cast(immutable)e);
256   }
257 
258   return ThrowResult(false);
259 }
260 
261 /** Used for asserting that a expression will throw an exception.
262 
263   Params:
264     condition = The expression that is expected to throw the exception.
265     file = The file name that the assert failed in. Should be left as default.
266     line = The file line that the assert failed in. Should be left as default.
267   Throws:
268     If expression does not throw, will throw an UnitTestException.
269 
270   Examples:
271     ---
272     // Makes sure it throws with the message "test"
273     void noThrow(){};
274     void withThrow(){throw new Exception("test");};
275     
276     // Will throw an exception like "checkit.exception.UnitTestException@test/example.d(7): Expression did not throw"
277     noThrow.shouldThrow();
278     // Will throw an exception like "checkit.exception.UnitTestException@test/example.d(7): Expression did not throw"
279     noThrow.shouldThrow!Exception();
280 
281     // Will throw an exception like "checkit.exception.UnitTestException@test/example.d(7): Expected <UnitTestException>, but throw <object.Exception>"
282     withThrow.shouldThrow!UnitTestException();
283     ---
284 */
285 void shouldThrow(T: Throwable = Exception, E)(lazy E condition, in string file = __FILE__, in size_t line = __LINE__)
286 {
287   import std.conv: text;
288 
289   bool isThrow = true;
290 
291   () @trusted
292   {
293     try
294     {
295       if(!threw!T(condition))
296       {
297         isThrow = false;
298       }
299     }
300     catch(Throwable t)
301     {
302         fail(text("Expected <", T.stringof, ">, but throw <", typeid(t), ">"), file, line);
303     }
304   }();
305 
306   if(!isThrow)
307   {
308     fail("Expression did not throw", file, line);
309   }
310 }
311 
312 /** Used for asserting that a expression will not throw an exception.
313 
314   Params:
315     condition = The expression that is expected to not throw the exception.
316     file = The file name that the assert failed in. Should be left as default.
317     line = The file line that the assert failed in. Should be left as default.
318   Throws:
319     If expression does throw, will throw an UnitTestException.
320 
321   Examples:
322     ---
323     // Makes sure it throws with the message "test"
324     void noThrow(){};
325     void withThrow(){throw new Exception("test");};
326     
327     // Will throw an exception like "checkit.exception.UnitTestException@test/example.d(7): Expression threw"
328     noThrow.shouldNotThrow();
329     ---
330 */
331 void shouldNotThrow(T: Throwable = Exception, E)(lazy E condition, in string file = __FILE__, in size_t line = __LINE__)
332 {
333   if(threw!T(condition))
334   {
335     fail("Expression threw", file, line);
336   }
337 }
338 
339 /** Used for asserting that a expression will throw an exception with message.
340 
341   Params:
342     condition = The expression that is expected to throw the exception.
343     message = Expected message exception.
344     file = The file name that the assert failed in. Should be left as default.
345     line = The file line that the assert failed in. Should be left as default.
346   Throws:
347     If expression does throw and message not expected, will throw an UnitTestException.
348 
349   Examples:
350     ---
351     // Makes sure it throws with the message "test"
352     void withThrow(){throw new Exception("test");};
353     
354     // Will throw an exception like "checkit.exception.UnitTestException@test/example.d(7): Expression did not throw"
355     withThrow.shouldThrowWithMessage("bar");
356     ---
357 */
358 void shouldThrowWithMessage(T: Throwable = Exception, E)( lazy E condition, 
359                                                           in string message, 
360                                                           in string file = __FILE__, 
361                                                           in size_t line = __LINE__)
362 {
363   auto threw = threw!T(condition);
364 
365   if(!threw)
366     fail("Expression did not throw", file, line);
367 
368   if(message != threw.throwable.msg)
369   {
370     fail("Expected exception message <%s>, but got <%s>".format(message, threw.throwable.msg), file, line);
371   }
372 }
373 
374 /** Used to assert that object is instance of class.
375 
376   Params:
377     T = Excepted instance class.
378     object = The object it should be instance of specific class.
379     message = The exception message.
380     file = The file name that the assert failed in. Should be left as default.
381     line = The file line that the assert failed in. Should be left as default.
382   Throws:
383     If object is not instance of class, will throw an UnitTestException.
384 
385   Examples:
386     ---
387     interface DummyInterface
388     {
389       public:
390         void test();
391     }
392 
393     class Dummy: DummyInterface
394     {
395       public:
396         override test()
397         {
398         }
399     }
400 
401     auto a = new Dummy;
402     auto b = cast(DummyInterface) a;
403     b.shouldBeInstanceOf!Dummy();
404     ---
405 */
406 void shouldBeInstanceOf(T, U)(U object, in string message = null, in string file = __FILE__, in size_t line = __LINE__)
407 {
408   if(cast(T)object is null)
409   {
410     fail(message ? message : "<%s> expected to be instance of <%s>".format(object, T.classinfo.name), file, line);
411   }
412 }
413 
414 /** Used to assert that one value is greater than another value.
415 
416   Params:
417     value = The value to test.
418     expected = The value it should be greater than.
419     message = Exception message.
420     file = The file name that the assert failed in. Should be left as default.
421     line = The file line that the assert failed in. Should be left as default.
422 
423   Throws:
424     If the value is not greater, will throw an UnitTestException with expected and actual values.
425 
426   Examples:
427     ---
428     // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be greater than <10>."
429     5.shouldBeGreater(10);
430     ---
431 */
432 void shouldBeGreater(T, U)( T value, 
433                             U expected, 
434                             in string message = null, 
435                             in string file = __FILE__, 
436                             in size_t line = __LINE__)
437 {
438   if(value <= expected)
439   {
440     fail(message ? message : "<%s> expected to be greater than <%s>".format(value, expected), file, line);
441 	}
442 }
443 
444 /** Used to assert that one value is greater or equal than another value.
445 
446   Params:
447     value = The value to test.
448     expected = The value it should be greater or equal than.
449     message = Exception message.
450     file = The file name that the assert failed in. Should be left as default.
451     line = The file line that the assert failed in. Should be left as default.
452 
453   Throws:
454     If the value is not greater or equal, will throw an UnitTestException with expected and actual values.
455 
456   Examples:
457     ---
458     // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be greater or equal to <10>."
459     5.shouldBeGreater(10);
460     ---
461 */
462 void shouldBeGreaterOrEqual(T, U)(T value, 
463                                   U expected, 
464                                   in string message = null, 
465                                   in string file = __FILE__, 
466                                   in size_t line = __LINE__)
467 {
468   if(value < expected)
469   {
470     fail(message ? message : "<%s> expected to be greater or equal to <%s>".format(value, expected), file, line);
471 	}
472 }
473 
474 /** Used to assert that one value is less than another value.
475 
476   Params:
477     value = The value to test.
478     expected = The value it should be less than.
479     message = Exception message.
480     file = The file name that the assert failed in. Should be left as default.
481     line = The file line that the assert failed in. Should be left as default.
482 
483   Throws:
484     If the value is not less, will throw an UnitTestException with expected and actual values.
485 
486   Examples:
487     ---
488     // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be less than <10>."
489     10.shouldBeLess(5);
490     ---
491 */
492 void shouldBeLess(T, U)(T value, 
493                         U expected, 
494                         in string message = null, 
495                         in string file = __FILE__, 
496                         in size_t line = __LINE__)
497 {
498   if(value >= expected)
499   {
500     fail(message ? message : "<%s> expected to be less than <%s>".format(value, expected), file, line);
501 	}
502 }
503 
504 /** Used to assert that one value is less or equal than another value.
505 
506   Params:
507     value = The value to test.
508     expected = The value it should be less or equal than.
509     message = Exception message.
510     file = The file name that the assert failed in. Should be left as default.
511     line = The file line that the assert failed in. Should be left as default.
512 
513   Throws:
514     If the value is not less or equal, will throw an UnitTestException with expected and actual values.
515 
516   Examples:
517     ---
518     // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be less or equal to <10>."
519     10.shouldBeLessOrEqual(5);
520     ---
521 */
522 void shouldBeLessOrEqual(T, U)( T value, 
523                                 U expected, 
524                                 in string message = null, 
525                                 in string file = __FILE__, 
526                                 in size_t line = __LINE__)
527 {
528   if(value > expected)
529   {
530     fail(message ? message : "<%s> expected to be less or equal to <%s>".format(value, expected), file, line);
531 	}
532 }
533 
534 /** Used to assert that value is between two values.
535 
536   Params:
537     value = The expected value
538     left = The expected left value of range.
539     right = The expected right value of range.
540     message = Exception message.
541     file = The file name that the assert failed in. Should be left as default.
542     line = The file line that the assert failed in. Should be left as default.
543 
544   Throws:
545     If the value is not between, will throw an UnitTestException with expected and actual values.
546 
547   Examples:
548     ---
549     // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be between <15> and <20>."
550     10.shouldBeBetween(15, 20);
551     ---
552 */
553 void shouldBeBetween(T, U, C)(T value, 
554                               U left, 
555                               C right, 
556                               in string message = null, 
557                               in string file = __FILE__, 
558                               in size_t line = __LINE__)
559 {
560   if(value >= max(left,right) || value <= min(left,right))
561   {
562     fail( message ? message : "<%s> expected to be between <%s> and <%s>".format( value, 
563                                                                                   min(left, right), 
564                                                                                   max(left, right)),
565           file, 
566           line);
567 	}
568 }
569 
570 /** Used to assert that value is between or equal two values.
571 
572   Params:
573     value = The expected value
574     left = The expected left value of range.
575     right = The expected right value of range.
576     message = Exception message.
577     file = The file name that the assert failed in. Should be left as default.
578     line = The file line that the assert failed in. Should be left as default.
579 
580   Throws:
581     If the value is not between or equal, will throw an UnitTestException with expected and actual values.
582 
583   Examples:
584     ---
585     // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be between <15> and <20>."
586     10.shouldBeBetweenOrEqual(15, 20);
587     ---
588 */
589 void shouldBeBetweenOrEqual(T, U, C)( T value, 
590                                       U left, 
591                                       C right, 
592                                       string message = null, 
593                                       string file = __FILE__, 
594                                       size_t line = __LINE__)
595 {
596   if(value > max(left,right) || value < min(left,right))
597   {
598     fail( message ? message : "<%s> expected to be between or equal <%s> and <%s>".format( value, 
599                                                                                           min(left, right), 
600                                                                                           max(left, right)), 
601           file, 
602           line);
603 	}
604 }
605 
606 /** Used to assert that Range is empty.
607 
608   Params:
609     rng = The expected Range.
610     message = Exception message.
611     file = The file name that the assert failed in. Should be left as default.
612     line = The file line that the assert failed in. Should be left as default.
613 
614   Throws:
615     If the Range is not empty, will throw an UnitTestException with expected and actual values.
616 
617   Examples:
618     ---
619     // Will throw an exception like "UnitTestException@example.d(6): Expected empty Range, but got <[1]>"
620     [1].shouldBeEmpty();
621     ---
622 */
623 void shouldBeEmpty(R)(in auto ref R rng, in string message = null, in string file = __FILE__, in size_t line = __LINE__)
624 if (isInputRange!R)
625 {
626   if(!rng.empty)
627   {
628     fail(message ? message : "Expected empty Range, but got <%s>".format(rng), file, line);
629   }
630 }
631 
632 /** Used to assert that Associative array is empty.
633 
634   Params:
635     aa = The expected associative array.
636     message = Exception message.
637     file = The file name that the assert failed in. Should be left as default.
638     line = The file line that the assert failed in. Should be left as default.
639 
640   Throws:
641     If the Associative array is not empty, will throw an UnitTestException with expected and actual values.
642 
643   Examples:
644     ---
645     // Will throw an exception like "UnitTestException@example.d(6): Expected empty Associative Array, but got <["test":12]>"
646     ["test":12].shouldBeEmpty();
647     ---
648 */
649 void shouldBeEmpty(T)(auto ref T aa, in string message = null, in string file = __FILE__, in size_t line = __LINE__)
650 if(isAssociativeArray!T)
651 {
652   () @trusted
653   { 
654     if(!aa.keys.empty)
655     {
656       fail(message ? message : "Expected empty Associative Array, but got <%s>".format(aa), file, line); 
657     }
658   }();
659 }
660 
661 /** Used to assert that Range is not empty.
662 
663   Params:
664     rng = The expected Range.
665     message = Exception message.
666     file = The file name that the assert failed in. Should be left as default.
667     line = The file line that the assert failed in. Should be left as default.
668 
669   Throws:
670     If the Range is empty, will throw an UnitTestException with expected and actual values.
671 
672   Examples:
673     ---
674     // Will throw an exception like "UnitTestException@example.d(6): Expected is not empty Range"
675     [1].shouldBeEmpty();
676     ---
677 */
678 void shouldBeNotEmpty(R)( in auto ref R rng, 
679                           in string message = null, 
680                           in string file = __FILE__, 
681                           in size_t line = __LINE__)
682 if (isInputRange!R)
683 {
684   if(rng.empty)
685   {
686     fail(message ? message : "Expected is not empty Range", file, line);
687   }
688 }
689 
690 /** Used to assert that Associative array is not empty.
691 
692   Params:
693     aa = The expected associative array.
694     message = Exception message.
695     file = The file name that the assert failed in. Should be left as default.
696     line = The file line that the assert failed in. Should be left as default.
697 
698   Throws:
699     If the Associative array is empty, will throw an UnitTestException with expected and actual values.
700 
701   Examples:
702     ---
703     // Will throw an exception like "UnitTestException@example.d(6): Expected is not empty Associative Array"
704     ["test":12].shouldBeEmpty();
705     ---
706 */
707 void shouldBeNotEmpty(T)(auto ref T aa, in string message = null, in string file = __FILE__, in size_t line = __LINE__)
708 if(isAssociativeArray!T)
709 {
710   () @trusted
711   { 
712     if(aa.keys.empty)
713     {
714       fail(message ? message : "Expected is not empty Associative Array", file, line); 
715     }
716   }();
717 }
718 
719 /** Used to assert that one value is in an array of specified values.
720 
721   Params:
722     value = The value to test.
723     expected = An array of valid values.
724     message = Exception message.
725     file = The file name that the assert failed in. Should be left as default.
726     line = The file line that the assert failed in. Should be left as default.
727 
728   Throws:
729     If the value is not in the array, will throw an UnitTestException with the value and array values.
730 
731   Examples:
732     ---
733     // Will throw an exception like "UnitTestException@example.d(6): <Peter> is not in <[Andrew, Anatoly]>."
734     "Peter".shouldBeIn(["Andrew", "Anatoly"]);
735     ---
736 */
737 void shouldBeIn(T, U)(T value, 
738                       U expected, 
739                       in string message = null, 
740                       in string file = __FILE__, 
741                       in size_t line = __LINE__)
742 {
743   import std.algorithm: canFind;
744 
745   if(!expected.canFind(value))
746   {
747     fail(message ? message : "<%s> is not in <[%s]>".format(value, expected.join(", ")), file, line); 
748 	}
749 }
750 
751 /** Used to assert that array is contain of specified value.
752 
753   Params:
754     array = An array of values.
755     expected = The valid value.
756     message = Exception message.
757     file = The file name that the assert failed in. Should be left as default.
758     line = The file line that the assert failed in. Should be left as default.
759 
760   Throws:
761     If an array is not contain the value, will throw an UnitTestException with the value and array values.
762 
763   Examples:
764     ---
765     // Will throw an exception like "UnitTestException@example.d(6): <[Peter, Anatoliy]> is not contain <Andrew>."
766     ["Peter", "Anatoly"].shouldBeContain("Andrew");
767     ---
768 */
769 void shouldBeContain(T, U)( T[] array, 
770                             U expected, 
771                             in string message = null, 
772                             in string file = __FILE__, 
773                             in size_t line = __LINE__)
774 {
775   import std.algorithm: canFind;
776 
777   if(!array.canFind(expected))
778   {
779     fail(message ? message : "<[%s]> is not contain <%s>".format(array.join(", "), expected), file, line); 
780   }
781 }
782 
783 /** Used to assert that JSON object is equal.
784 
785   Params:
786     actual = The actual JSON object.
787     expected = The excpected JSON.
788     message = Exception message.
789     file = The file name that the assert failed in. Should be left as default.
790     line = The file line that the assert failed in. Should be left as default.
791 
792   Throws:
793     If an JSON objects is not equal, will throw an UnitTestException.
794 
795   Examples:
796     ---
797     // Will throw an exception like "UnitTestException@example.d(6): Error parsing JSON: Unexpected end of data. (Line 1:10)"
798     `{"test" :1`.shouldBeEqualJSON(`{"test":1}`);
799  
800     // Will throw an exception like "UnitTestException@example.d(6):`{"test" :1, "some" : "12"}`.shouldBeEqualJSON(`{"test":1}`);
801     `{"test" :1, "some" : "12"}`.shouldBeEqualJSON(`{"test":1}`);
802     ---
803 */
804 void shouldBeEqualJSON( in string actual, 
805                         in string expected, 
806                         in string message = null, 
807                         in string file = __FILE__, 
808                         in size_t line = __LINE__)
809 {
810   import std.json: JSONException, JSONValue, parseJSON;
811 
812   try
813   {
814     actual.parseJSON.toPrettyString.shouldEqual(expected.parseJSON.toPrettyString, message, file, line);
815   }
816   catch(JSONException e)
817   {
818     fail("Error parsing JSON: " ~ e.msg, file, line);
819   }
820 }
821 
822 /** Used to assert that expression should be run less duration
823 
824   Params:
825     condition = The run expression.
826     time = The maximum duration or running.
827     message = Exception message.
828     file = The file name that the assert failed in. Should be left as default.
829     line = The file line that the assert failed in. Should be left as default.
830 
831   Throws:
832     If expression run greater time, will throw an UnitTestException.
833 
834   Examples:
835     ---
836     // Will throw an exception like "UnitTestException@example.d(6): Expected run time <1 seconds>, but run <2 seconds>
837     {Thread.sleep(2.seconds)}.shouldRunLess(1.seconds);
838     ---
839 */
840 void shouldRunLess(E)(lazy E condition, 
841                       in Duration time, 
842                       in string message = null, 
843                       in string file = __FILE__, 
844                       in size_t line = __LINE__)
845 {
846   immutable auto startTime = Clock.currTime();
847   condition();
848   
849   auto delta = Clock.currTime() - startTime;
850   if(delta > time)
851   {
852     fail(message ? message : "Expected run time <%s>, but run <%s>".format(to!string(time), delta), file, line);
853   }
854 }