Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

root/tests/findregressions.d

Revision 552:648409a7fb0c, 6.9 kB (checked in by Christian Kamm <kamm incasoftware de>, 4 years ago)

Fix findregressions and makewebstatistics to adhere to our definition of
Improvement and Regression.

Line 
1 // Based on DSTRESS code by Thomas KÃŒhne
2
3 module findregressions;
4
5 private import std.string;
6 private import std.conv;
7 private import std.stdio;
8 private import std.stream;
9 private import std.file;
10 private import std.c.stdlib;
11 private import std.date;
12
13
14 enum Result{
15     UNTESTED    = 0,
16     PASS        = 1 << 2,
17     XFAIL       = 2 << 2,
18     XPASS       = 3 << 2,
19     FAIL        = 4 << 2,
20     ERROR       = 5 << 2,
21     BASE_MASK   = 7 << 2,
22
23     EXT_MASK    = 3,
24     BAD_MSG     = 1,
25     BAD_GDB     = 2,
26    
27     MAX     = BAD_GDB + BASE_MASK
28 }
29
30 char[] toString(Result r){
31     switch(r & Result.BASE_MASK){
32         case Result.PASS: return "PASS";
33         case Result.XPASS: return "XPASS";
34         case Result.FAIL: return "FAIL";
35         case Result.XFAIL: return "XFAIL";
36         case Result.ERROR: return "ERROR";
37         case Result.UNTESTED: return "UNTESTED";
38         default:
39             break;
40     }
41     throw new Exception(format("unhandled Result value %s", cast(int)r));
42 }
43
44 char[] dateString(){
45     static char[] date;
46     if(date is null){
47         auto time = getUTCtime();
48         auto year = YearFromTime(time);
49         auto month = MonthFromTime(time);
50         auto day = DateFromTime(time);
51         date = format("%d-%02d-%02d", year, month+1, day);
52     }
53     return date;
54 }
55
56 char[][] unique(char[][] a){
57     char[][] b = a.sort;
58     char[][] back;
59
60     back ~= b[0];
61
62     size_t ii=0;
63     for(size_t i=0; i<b.length; i++){
64         if(back[ii]!=b[i]){
65             back~=b[i];
66             ii++;
67         }
68     }
69
70     return back;   
71 }
72
73 private{
74     version(Windows){
75         import std.c.windows.windows;
76         extern(Windows) BOOL GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime);
77     }else version(linux){
78         import std.c.linux.linux;
79         version = Unix;
80     }else version(Unix){
81         import std.c.unix.unix;
82     }else{
83         static assert(0);
84     }
85
86     alias ulong FStime;
87
88     FStime getFStime(char[] fileName){
89         version(Windows){
90             HANDLE h;
91        
92             if (useWfuncs){
93                 wchar* namez = std.utf.toUTF16z(fileName);
94                 h = CreateFileW(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS,
95                     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
96             }else{
97                 char* namez = toMBSz(fileName);
98                 h = CreateFileA(namez,GENERIC_WRITE,0,null,OPEN_ALWAYS,
99                 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
100             }
101
102             if (h == INVALID_HANDLE_VALUE)
103                 goto err;
104
105             FILETIME creationTime;
106             FILETIME accessTime;
107             FILETIME writeTime;
108        
109             BOOL b = GetFileTime(h, &creationTime, &accessTime, &writeTime);
110             if(b==1){
111                 long modA = writeTime.dwLowDateTime;
112                 long modB = writeTime.dwHighDateTime;
113                 return modA  | (modB << (writeTime.dwHighDateTime.sizeof*8));
114             }
115
116 err:
117             CloseHandle(h);
118             throw new Exception("failed to query file modification : "~fileName);
119         }else version(Unix){
120             char* namez = toStringz(fileName);
121             struct_stat statbuf;
122        
123             if(stat(namez, &statbuf)){
124                 throw new FileException(fileName, getErrno());
125             }
126
127             return statbuf.st_mtime;
128         }else{
129             static assert(0);
130         }
131     }
132 }
133
134 char[] cleanFileName(char[] file){
135     char[] back;
136     bool hadSep;
137
138     foreach(char c; file){
139         if(c == '/' || c == '\\'){
140             if(!hadSep){
141                 back ~= '/';
142                 hadSep = true;
143             }
144         }else{
145             back ~= c;
146             hadSep = false;
147         }
148     }
149
150     size_t start = 0;
151     while(back[start] <= ' ' && start < back.length){
152         start++;
153     }
154
155     size_t end = back.length-1;
156     while(back[end] <= ' ' && end >= start){
157         end--;
158     }
159
160     back = back[start .. end+1];
161
162     return back;
163 }
164
165 class Test{
166     char[] name;
167     char[] file;
168     Result r;
169
170     this(char[] file){
171         this.file = file;
172
173         int start = rfind(file, "/");
174         if(start<0){
175             start = 0;
176         }else{
177             start += 1;
178         }
179        
180         int end = rfind(file, ".");
181         if(end < start){
182             end = file.length;
183         }
184
185         name = file[start .. end];
186     }
187 }
188
189
190 class Log{
191     Test[char[]] tests;
192
193     char[] id;
194
195     this(char[] id){
196         this.id = id;
197     }
198
199
200     void dropBogusResults(FStime recordTime, char[] testRoot){
201         uint totalCount = tests.length;
202        
203         char[][] sourcesTests = tests.keys;
204         foreach(char[] source; sourcesTests){
205             if(find(source, "complex/") < 0){
206                 try{
207                     FStime caseTime = getFStime(testRoot~std.path.sep~source);
208                     if(caseTime > recordTime){
209                         debug(drop) fwritefln(stderr, "dropped: %s", source);
210                         tests.remove(source);
211                     }
212                 }catch(Exception e){
213                     debug(drop) fwritefln(stderr, "dropped: %s", source);
214                     tests.remove(source);
215                 }
216             }
217             // asm-filter
218             int i = find(source, "asm_p");
219             if(i >= 0){
220                 tests.remove(source);
221             }
222         }
223         tests.rehash;
224        
225         writefln("dropped %s outdated tests (%s remaining)", totalCount - tests.length, tests.length);
226     }
227
228    
229     bool add(char[] line){
230         const char[] SUB = "Torture-Sub-";
231         const char[] TORTURE = "Torture:";
232
233         line = strip(line);
234         int id = -1;
235         Result r = Result.UNTESTED;
236
237         if(line.length > SUB.length && line[0 .. SUB.length] == SUB){
238             line = line[SUB.length .. $];
239             id = 0;
240             while(line[id] >= '0' && line[id] <= '9'){
241                 id++;
242             }
243             int start = id;
244             id = std.conv.toUint(line[0 .. id]);
245
246             while(line[start] != '-'){
247                 start++;
248             }
249             line = line[start+1 .. $];
250         }
251
252         char[][] token = split(line);
253         if(token.length < 2){
254             return false;
255         }
256         char[] file = strip(token[1]);
257
258         switch(token[0]){
259             case "PASS:":
260                 r = Result.PASS; break;
261             case "FAIL:":
262                 r = Result.FAIL; break;
263             case "XPASS:":
264                 r = Result.XPASS; break;
265             case "XFAIL:":
266                 r = Result.XFAIL; break;
267             case "ERROR:":
268                 r = Result.ERROR; break;
269             default:{
270                 if(token[0] == TORTURE){
271                     throw new Exception("not yet handled: "~line);
272                 }else if(id > -1){
273                     throw new Exception(format("bug in SUB line: (%s) %s", id, line));
274                 }
275             }
276         }
277
278         if(r != Result.UNTESTED){
279             if(std.string.find(line, "bad error message") > -1){
280                 r |= Result.BAD_MSG;   
281             }
282             if(std.string.find(line, "bad debugger message") > -1){
283                 r |= Result.BAD_MSG;   
284             }
285            
286             file = cleanFileName(file);
287            
288             if(id >= 0){
289                 // update sub
290                 id--;
291        
292                 Test* test = file in tests;
293
294                 if(test is null){
295                     Test t = new Test(file);
296                     tests[file] = t;
297                     t.r = r;
298                 }else{
299                     if(test.r != Result.UNTESTED){
300                         test.r = Result.UNTESTED;
301                     }
302                     test.r = r;
303                 }
304             }
305             return true;
306         }
307         return false;
308     }
309 }
310
311
312 int main(char[][] args){
313
314     if(args.length < 2){
315         fwritefln(stderr, "%s <old log> <new log>", args[0]);
316         return 1;
317     }
318    
319    
320     Log[] logs;
321
322     foreach(size_t id, char[] file; args[1 .. $]){
323         writefln("parsing: %s", file);
324         FStime logTime  = getFStime(file);
325         debug fwritefln(stderr, "sourceTime: %s", logTime);
326
327         Log l= new Log(file);
328         Stream source = new BufferedFile(file, FileMode.In);
329         while(!source.eof()){
330             l.add(source.readLine());
331         }
332        
333         l.dropBogusResults(logTime, "dstress");
334
335         logs ~= l;
336     }
337
338     Log oldLog = logs[0];
339     Log newLog = logs[1];
340
341     foreach(Test t; newLog.tests.values){
342         Test* oldT = t.file in oldLog.tests;
343
344         if(oldT !is null){
345             if(oldT.r == t.r)
346                 continue;
347             else if(t.r >= Result.XPASS && oldT.r && oldT.r <= Result.XFAIL){
348                 writef("Regression   ");
349             }
350             else if(t.r && t.r <= Result.XFAIL && oldT.r >= Result.XPASS){
351                 writef("Improvement  ");
352             }
353             else {
354                 writef("Change       ");
355             }
356             writefln(toString(oldT.r), " -> ", toString(t.r), " : ", t.name, " in ", t.file);
357         }
358     }
359    
360    
361     return 0;
362 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.