1 /**
2  * Tests/Examples of Pijamas
3  *
4  * Authors: Pedro Tacla Yamada, Luis Panadero Guardeño
5  * License: Licensed under the MIT license. See LICENSE for more information.
6  */
7 module pijamas_spec;
8 
9 import std.exception;
10 
11 import pijamas;
12 import pijamas.exception : AssertException;
13 
14 version (Debug_Failing_Tests) {
15   @("Failing test")
16   unittest {
17     10.should.be.equal(0);
18   }
19 
20   @("Failing test with native assert")
21   unittest {
22     assert(10 == 0);
23   }
24 
25   @("Error test")
26   unittest {
27     throw new Exception("Some exception");
28   }
29 }
30 
31 @("Should Assertion.exist")
32 @trusted unittest {
33   //  it("existence of string",
34   {
35     // String
36     string str;
37     str.should.not.exist;
38     assertNotThrown!AssertException(str.should.not.exist);
39     assertThrown!AssertException(str.should.exist);
40 
41     string str2 = null;
42     str2.should.not.exist;
43 
44   }
45 
46   //  it("With not nullable, must do nothing
47   {
48     int i = 10;
49     i.should.exist;
50     i.should.not.exist;
51 
52     struct S {
53       int x;
54     }
55 
56     S s;
57     assertNotThrown!AssertException(s.should.exist);
58     assertNotThrown!AssertException(s.should.not.exist);
59   }
60 
61   //  it("Pointer not being a null pointer"
62   {
63     // Ptr
64     int* ptr = null;
65     ptr.should.not.exist;
66     assertThrown!AssertException(ptr.should.exist);
67 
68     int value;
69     ptr = &value;
70     ptr.should.exist;
71   }
72 
73   //  it("Class reference"
74   {
75     // Class
76     class C {
77       int x;
78       this() {
79       }
80     }
81 
82     C c;
83     c.should.not.exist;
84     assertThrown!AssertException(c.should.exist);
85 
86     c = new C();
87     c.should.exist;
88   }
89 }
90 
91 @("Asserting a field of a no copiable Struct")
92 @safe unittest {
93   struct S {
94     this(this) @disable;
95 
96     int x;
97     size_t length;
98   }
99 
100   auto s = S(123, 10);
101   s.x.should.be.equal(123);
102   //s.should.have.length(10); // Error is not copyable because it is annotated with @disable
103 }
104 
105 @("Should Assertion.True")
106 @trusted unittest {
107   // it("returns and asserts for true",
108   {
109     true.should.be.True;
110     (1 == 1).should.be.True;
111   }
112 
113   // it("throws for false",
114   {
115     (1 != 1).should.not.be.True;
116     assertThrown!AssertException(false.should.be.True);
117   }
118 }
119 
120 @("Should Assertion.False")
121 @trusted unittest {
122   // it("returns and asserts for false",
123   {
124     false.should.be.False;
125     (1 != 1).should.be.False;
126   }
127 
128   // it("throws for true",
129   {
130     true.should.not.be.False;
131     assertThrown!AssertException((1 == 1).should.be.False);
132   }
133 }
134 
135   @("Should Assertion.equal")
136   @trusted unittest {
137     //  it("asserts whether two values are equal",
138     {
139       10.should.be.equal(10);
140       10.expect.to.be.equal(10);
141       10.should.not.be.equal(5);
142       10.should.not;
143       assertThrown!AssertException(10.should.be.equal(2));
144     }
145 
146     //  it("works for arrays",
147     {
148       [1, 2, 3, 4].should.be.equal([1, 2, 3, 4]);
149 
150       byte[] a2 = [0, 2, 1];
151       a2.should.not.be.equal([1, 2, 3, 5]);
152       assertThrown!AssertException(a2.should.be.equal([100, 200, 4]));
153     }
154 
155     //  it("works for ranges",
156     /*
157     // FIX Fix for ranges ... if "other" is an array, should convert the range to an array and compare.
158     // also, must be careful with infinite ranges
159     {
160     import std.range : iota;
161     auto r = iota(1, 4);
162     r.should.be.equal([1, 2, 3, 4]);
163     }
164     */
165 
166     //  it("works for structs",
167     {
168       struct ExampleS {
169         bool a = false;
170         string f = "something";
171       }
172 
173       auto e = ExampleS(true, "here");
174       e.should.be.equal(ExampleS(true, "here"));
175       e.should.be.not.equal(ExampleS(true, "asdf"));
176       assertThrown!AssertException(e.should.be.equal(ExampleS(true, "asdf")));
177     }
178 
179     //  it("works for classes",
180     {
181       class ExampleC {
182         int x;
183         this(int x) {
184           this.x = x;
185         }
186 
187         override bool opEquals(Object o) const  // @trusted
188         {
189           if (ExampleC rhs = cast(ExampleC) o) {
190             return this.x == rhs.x;
191           }
192           return false;
193         }
194       }
195 
196       class OtherClass {
197         int x;
198         this(int x) {
199           this.x = x;
200         }
201       }
202 
203       auto e = new ExampleC(33);
204       e.should.be.equal(new ExampleC(33));
205       e.should.be.not.equal(new ExampleC(1));
206       assertThrown!AssertException(e.should.be.equal(new ExampleC(1)));
207 
208       e.should.be.not.equal(new OtherClass(33));
209       assertThrown!AssertException(e.should.be.equal(new OtherClass(33)));
210 
211     }
212   }
213 
214 @("Should Assertion.approxEqual")
215 @trusted unittest {
216   // it("asserts that the identical value are identical")
217   {
218     float f = 0.01;
219     f.should.be.approxEqual(f);
220     f.should.be.close(f);
221 
222     double d = 0.01;
223     d.should.be.approxEqual(d);
224 
225     real r = 0.01;
226     r.should.be.approxEqual(r);
227   }
228 
229   // it("handles comparing diferent float types")
230   {
231     float f = 0.01;
232     double d = 0.01;
233     real r = 0.01;
234     f.should.be.approxEqual(d);
235     f.should.be.approxEqual(r);
236 
237     d.should.be.approxEqual(f);
238     d.should.be.approxEqual(r);
239 
240     r.should.be.approxEqual(f);
241     r.should.be.approxEqual(d);
242   }
243 
244   // it("asserts that two nearly identical float values are approximated equal")
245   {
246     float one = 1_000_000_000.0;
247     one.should.be.close(999_999_999.0);
248 
249     double d = 0.1;
250     double d2 = d + 1e-10;
251     d.should.not.be.equal(d2);
252     d.should.be.approxEqual(d2);
253 
254     // and("when increase the difference, it must not be approximated equals")
255     d2 += 1e-5;
256     d.should.not.be.equal(d2);
257     d.should.not.be.approxEqual(d2);
258     assertThrown!AssertException(d.should.be.approxEqual(d2));
259 
260     // and("Different default limits for different floating point types")
261     float oneFloat = 1.0f;
262     double oneDouble = 1.0;
263     oneFloat.should.be.close(0.999_99f);
264     oneDouble.should.not.be.close(0.999_99);
265   }
266 }
267 
268 version (MirNoGCException) {
269 } else {
270   @("Should Assertion.match")
271   @trusted unittest {
272     // it("returns whether a string type matches a Regex",
273     {
274       import std.regex : regex;
275 
276       string str = "Something weird";
277       str.should.match(regex(`[a-z]+`));
278       assertThrown!AssertException(str.should.match(regex(`[0-9]+`)));
279     }
280 
281     // it("returns whether a string type matches a StaticRegex",
282     {
283       import std.regex : ctRegex;
284 
285       string str = "something 2 weird";
286       str.should.match(ctRegex!`[a-z0-9]+`);
287       assertThrown!AssertException(str.should.match(ctRegex!`^[a-z]+$`));
288     }
289 
290     // it("returns whether a string type matches a string regex",
291     {
292       string str = "1234numbers";
293       str.should.match(`[0-9]+[a-z]+`);
294       str.should.not.match(`^[a-z]+`);
295       assertThrown!AssertException(str.should.match(`^[a-z]+`));
296     }
297   }
298 }
299 
300 @("Should Assertion.include")
301 @trusted unittest {
302   // it("asserts for arrays containing elements",
303   {
304     int[] a = [1, 2, 3, 4, 5, 6];
305     a.should.include!int(4);
306     a.should.not.include!int(7);
307     assertThrown!AssertException(a.should.include(7));
308   }
309 
310   // it("asserts for associative arrays containing values",
311   {
312     int[string] aa = ["something": 2, "else": 3];
313     aa.should.have.value(2);
314     aa.should.not.have.value(4);
315     assertThrown!AssertException(aa.should.have.value(42));
316   }
317 
318   // it("asserts for strings containing characters",
319   {
320     string str = "asdf1";
321     str.should.include('a');
322     version (MirNoGCException) {
323     } else {
324       str.should.include("sd");
325     }
326     str.should.not.include(2);
327     str.should.not.include('u');
328     assertThrown!AssertException(str.should.include('z'));
329   }
330 }
331 
332 @("Should Assertion.length")
333 @trusted unittest {
334   // it("asserts for length equality for strings",
335   {
336     auto str = "1234567";
337     str.should.have.length(7);
338     assertThrown!AssertException(str.should.have.length(17));
339   }
340 
341   // it("asserts for length equality for arrays",
342   {
343     auto a = [1, 2, 3, 4, 5, 6];
344     a.should.have.length(6);
345     assertThrown!AssertException(a.should.have.length(16));
346   }
347 
348   // it("asserts for length equality for associative arrays",
349   {
350     string[string] aa = [
351       "something": "here", "what": "is", "this": "stuff", "we're": "doing"
352     ];
353     aa.should.have.length(4);
354     assertThrown!AssertException(aa.should.have.length(24));
355   }
356 }
357 
358 @("Should Assertion.empty")
359 @trusted unittest {
360   // it("asserts that a string is empty"
361   {
362     auto str = "1234567";
363     str.should.not.be.empty;
364     assertThrown!AssertException(str.should.be.empty);
365     "".should.be.empty;
366   }
367 
368   // it("asserts that an array is empty"
369   {
370     auto a = [1, 2, 3, 4, 5, 6];
371     a.should.not.be.empty;
372     assertThrown!AssertException(a.should.be.empty);
373     int[] emptyArr;
374     emptyArr.should.be.empty;
375 
376     int[10] emptySArr;
377     emptySArr.should.not.be.empty;
378     // A static array contains N values of T.init, so never can be empty
379   }
380 
381   // it("asserts that an associative array is empty",
382   {
383     string[string] aa = [
384       "something": "here", "what": "is", "this": "stuff", "we're": "doing"
385     ];
386     aa.should.not.be.empty;
387     assertThrown!AssertException(aa.should.be.empty);
388     int[string] emptyAa;
389     emptyAa.should.be.empty;
390   }
391 }
392 
393 @("Should Assertion.Throw")
394 @trusted unittest {
395   // it("asserts whether an expressions throws",
396   {
397     void throwing() {
398       throw new Exception("I throw with 0!");
399     }
400 
401     assertThrown!Exception(throwing());
402     should(&throwing).Throw!Exception;
403 
404     void notThrowing() {
405       return;
406     }
407 
408     should(&notThrowing).not.Throw;
409   }
410 }
411 
412 @("Should Assertion.key")
413 @trusted unittest {
414   // it("asserts for `key` existence in types with `opIndex` defined",
415   {
416     auto aArr = ["something": "here",];
417 
418     aArr.should.have.key("something");
419     aArr.should.not.have.key("else");
420     assertThrown!AssertException(aArr.should.have.key("another"));
421   }
422 }
423 
424 @("Should Assertion.sorted")
425 @trusted unittest {
426   // it("asserts whether a range is sorted",
427   {
428     auto unsorted = [4, 3, 2, 1];
429     unsorted.should.not.be.sorted;
430     assertThrown!AssertException(unsorted.should.be.sorted);
431     auto sortedAr = [1, 2, 3, 4, 8];
432     sortedAr.should.be.sorted;
433     assertThrown!AssertException(sortedAr.should.not.be.sorted);
434   }
435 }
436 
437 @("Should Assertion.biggerThan")
438 @trusted unittest {
439   //it("asserts whether a value is bigger than other",
440   {
441     auto a1 = true;
442     a1.should.be.biggerThan(0);
443     a1.should.be.biggerThan(false);
444 
445     auto a2 = "aab";
446     a2.should.be.biggerThan("aaa");
447     a2.should.not.be.biggerThan("zz");
448     assertThrown!AssertException(a2.should.be.biggerThan("zz"));
449 
450     10.should.be.biggerOrEqualThan(10);
451     50.should.be.biggerOrEqualThan(10);
452   }
453 }
454 
455 @("Should Assertion.smallerThan")
456 @trusted unittest {
457   // it("asserts whether a value is smaller than other",
458   {
459     auto a1 = false;
460     a1.should.be.smallerThan(1);
461     a1.should.be.smallerThan(true);
462 
463     auto a2 = 1000;
464     a2.should.be.smallerThan(2000);
465     a2.should.be.not.smallerThan(99);
466     assertThrown!AssertException(a2.should.be.smallerThan(99));
467 
468     10.should.be.smallerOrEqualThan(10);
469     10.should.be.smallerOrEqualThan(50);
470   }
471 }
472