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