1 module unit_threaded.attrs;
2 
3 import std.range.primitives : isInputRange, ElementType;
4 
5 
6 enum UnitTest; //opt-in to registration
7 enum DontTest; //opt-out of registration
8 enum Serial; //run tests in the module in one thread / serially
9 
10 alias SingleThreaded = Serial;
11 
12 ///Hide test. Not run by default but can be run.
13 struct HiddenTest {
14     string reason;
15 }
16 
17 /// The suite fails if the test passes.
18 struct ShouldFail {
19     string reason;
20 }
21 
22 /// The suite fails unless the test throws T
23 struct ShouldFailWith(T: Throwable) {
24     alias Type = T;
25     string reason;
26 }
27 
28 /// Associate a name with a unittest block.
29 struct Name {
30     string value;
31 }
32 
33 /// Associates one or more tags with the test
34 struct Tags {
35     this(string[] values...) { this.values = values;}
36     this(string[] values) { this.values =  values; }
37     this(string value)    { this.values = [value]; }
38     string[] values;
39 }
40 
41 /** Automatically assign @Tags for each parameterized test
42  e.g.
43 ---------------
44 @Values("foo", "bar") @AutoTags unittest { ... }
45 // there are now two unit tests, one for "foo" with tag "foo"
46 // and one for "bar" with tag "bar"
47 ---------------
48  */
49 enum AutoTags;
50 
51 /** Attachs these types to the a parametrized unit test.
52     The attached template function will be instantiated with
53     each type listed, e.g.
54 
55     ----------------
56     @Types!(int, byte) void testInit(T)() { T.init.shouldEqual(0); }
57     ----------------
58 
59     These would mean two testInit test runs.
60 
61     Normally this would be a template but I don't know how to write
62  *  the UDA code to filter a template out
63  */
64 struct Types(T...) {}
65 
66 
67 /**
68  Used as a UDA for built-in unittests to enable value-parametrized tests.
69  Example:
70  -------
71  @Values(1, 2, 3) unittest { assert(getValue!int % 2 == 0); }
72  -------
73  The example above results in unit_threaded running the unit tests 3 times,
74  once for each value declared.
75 
76  See `getValue`.
77  */
78 auto Values(T)(T[] values...) {
79     return ValuesImpl!T(values.dup);
80 }
81 
82 auto Values(R)(R values) if(isInputRange!R) {
83     import std.array: array;
84     return ValuesImpl!(ElementType!R)(values.array);
85 }
86 
87 
88 struct ValuesImpl(T) {
89     T[] values;
90 }
91 
92 /**
93  Retrieves the current test value of type T in a built-in unittest.
94  See `Values`.
95  */
96 T getValue(T, int index = 0)() {
97     return ValueHolder!T.values[index];
98 }
99 
100 package struct ValueHolder(T) {
101     static T[10] values;
102 }
103 
104 
105 enum Setup;
106 enum Shutdown;