1 module cogito.tests.meter;
2 
3 import cogito;
4 import cogito.list;
5 import cogito.meter;
6 import std.array;
7 import dmd.identifier;
8 import dmd.globals;
9 import std.algorithm;
10 import std.sumtype;
11 
12 @("filename.d:line: identifier: score")
13 unittest
14 {
15     enum string filename = "filename.d";
16     auto meter = Meter(new Identifier(""), Loc(filename, 2, 1), Meter.Type.callable);
17     auto meters = List!Meter();
18 
19     meter.ownScore = 3;
20     meters.insert(meter);
21 
22     auto source = Source(meters, filename);
23     auto output = appender!string();
24     auto reporter = FlatReporter!((string x) => output.put(x))(source);
25 
26     reporter.report(Threshold(1, 50));
27 
28     assert(output.data == "filename.d:2: function (λ): 3\n");
29 }
30 
31 @("flat reporter prepends function identifiers with function")
32 unittest
33 {
34     enum string filename = "filename.d";
35     auto meter = Meter(new Identifier("f"), Loc(filename, 2, 1), Meter.Type.callable);
36     auto meters = List!Meter();
37 
38     meter.ownScore = 3;
39     meters.insert(meter);
40 
41     auto source = Source(meters, filename);
42     auto output = appender!string();
43     auto reporter = FlatReporter!((string x) => output.put(x))(source);
44 
45     reporter.report(Threshold(1, 50));
46 
47     assert(output.data == "filename.d:2: function f: 3\n");
48 }
49 
50 @("reports interface score")
51 unittest
52 {
53     enum string filename = "filename.d";
54     auto meter = Meter(new Identifier("I"), Loc(filename, 2, 1), Meter.Type.interface_);
55     auto meters = List!Meter();
56 
57     meter.ownScore = 3;
58     meters.insert(meter);
59 
60     auto source = Source(meters, filename);
61     auto output = appender!string();
62     auto reporter = FlatReporter!((string x) => output.put(x))(source);
63 
64     reporter.report(Threshold(1, 2));
65 
66     assert(output.data == "filename.d:2: interface I: 3\n");
67 }
68 
69 @("reports interface aggregate type")
70 unittest
71 {
72     auto meter = runOnCode(q{
73 interface I
74 {
75 }
76     });
77     auto output = appender!string();
78     auto reporter = meter.tryMatch!((Source source) =>
79             FlatReporter!((string x) => output.put(x))(source));
80 
81     reporter.report(Threshold());
82 
83     assert(output.data.canFind("interface I"));
84 }
85 
86 @("reports struct aggregate type")
87 unittest
88 {
89     auto meter = runOnCode(q{
90 struct S
91 {
92 }
93     });
94     auto output = appender!string();
95     auto reporter = meter.tryMatch!((Source source) =>
96             FlatReporter!((string x) => output.put(x))(source));
97 
98     reporter.report(Threshold());
99 
100     assert(output.data.canFind("struct S"));
101 }
102 
103 @("reports class aggregate type")
104 unittest
105 {
106     auto meter = runOnCode(q{
107 class C
108 {
109 }
110     });
111     auto output = appender!string();
112     auto reporter = meter.tryMatch!((Source source) =>
113             FlatReporter!((string x) => output.put(x))(source));
114 
115     reporter.report(Threshold());
116 
117     assert(output.data.canFind("class C"));
118 }
119 
120 @("reports union aggregate type")
121 unittest
122 {
123     auto meter = runOnCode(q{
124 union U
125 {
126     char a;
127     byte b;
128 }
129     });
130     auto output = appender!string();
131     auto reporter = meter.tryMatch!((Source source) =>
132             FlatReporter!((string x) => output.put(x))(source));
133 
134     reporter.report(Threshold());
135 
136     assert(output.data.canFind("union U"));
137 }
138 
139 @("reports template aggregate type")
140 unittest
141 {
142     auto meter = runOnCode(q{
143 template T()
144 {
145 }
146     });
147     auto output = appender!string();
148     auto reporter = meter.tryMatch!((Source source) =>
149             FlatReporter!((string x) => output.put(x))(source));
150 
151     reporter.report(Threshold());
152 
153     assert(output.data.canFind("template T"));
154 }
155 
156 @("FlatReporter reports only functions on function threshold violation")
157 unittest
158 {
159     auto meter = runOnCode(q{
160 struct S
161 {
162     void f()
163     {
164         if (true)
165         {
166         }
167         else
168         {
169         }
170     }
171 
172     void g()
173     {
174         if (true)
175         {
176         }
177         else
178         {
179         }
180     }
181 }
182     });
183     auto output = appender!string();
184     auto reporter = meter.tryMatch!((Source source) =>
185             FlatReporter!((string x) => output.put(x))(source));
186 
187     reporter.report(Threshold(1, 0));
188 
189     assert(!output.data.canFind("struct S"));
190 }
191 
192 @("FlatReporter reports only functions on function threshold violation if aggregate threshold is set")
193 unittest
194 {
195     auto meter = runOnCode(q{
196 struct S
197 {
198     void f()
199     {
200         if (true)
201         {
202         }
203         else
204         {
205         }
206     }
207 
208     void g()
209     {
210         if (true)
211         {
212         }
213         else
214         {
215         }
216     }
217 }
218     });
219     auto output = appender!string();
220     auto reporter = meter.tryMatch!((Source source) =>
221             FlatReporter!((string x) => output.put(x))(source));
222 
223     reporter.report(Threshold(1, 10));
224 
225     assert(!output.data.canFind("struct S"));
226 }