File: automake2junit.ml

package info (click to toggle)
libguestfs 1%3A1.44.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 118,932 kB
  • sloc: ansic: 458,017; ml: 51,424; sh: 13,191; java: 9,578; makefile: 7,931; cs: 6,328; haskell: 5,674; python: 3,871; perl: 3,528; erlang: 2,446; xml: 1,347; ruby: 350; pascal: 257; javascript: 157; lex: 135; yacc: 128; cpp: 10
file content (207 lines) | stat: -rwxr-xr-x 6,687 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/ocamlrun ocaml

(* Copyright (C) 2010-2014 Red Hat Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *)

open Printf
#load "str.cma"
#load "unix.cma"

type test_result =
  | Pass
  | Skip
  | XFail
  | Fail
  | XPass
  | Error

let (//) = Filename.concat

let read_whole_file path =
  let buf = Buffer.create 16384 in
  let chan = open_in path in
  let maxlen = 16384 in
  let s = String.create maxlen in
  let rec loop () =
    let r = input chan s 0 maxlen in
    if r > 0 then (
      Buffer.add_subbytes buf s 0 r;
      loop ()
    )
  in
  loop ();
  close_in chan;
  Buffer.contents buf

let string_charsplit sep =
  Str.split (Str.regexp_string sep)

let rec string_find s sub =
  let len = String.length s in
  let sublen = String.length sub in
  let rec loop i =
    if i <= len-sublen then (
      let rec loop2 j =
        if j < sublen then (
          if s.[i+j] = sub.[j] then loop2 (j+1)
          else -1
        ) else
          i (* found *)
      in
      let r = loop2 0 in
      if r = -1 then loop (i+1) else r
    ) else
      -1 (* not found *)
  in
  loop 0

let rec string_replace s s1 s2 =
  let len = String.length s in
  let sublen = String.length s1 in
  let i = string_find s s1 in
  if i = -1 then s
  else (
    let s' = String.sub s 0 i in
    let s'' = String.sub s (i+sublen) (len-i-sublen) in
    s' ^ s2 ^ string_replace s'' s1 s2
  )

let find_trs basedir =
  let split_dirs_and_files items =
    let rec work dirs files = function
      | [] -> dirs, files
      | ((_, full_x) as x) :: xs ->
        match (Unix.LargeFile.lstat full_x).Unix.LargeFile.st_kind with
        | Unix.S_REG -> work dirs (x :: files) xs
        | Unix.S_DIR -> work (x :: dirs) files xs
        | _ -> work dirs files xs
    in
    work [] [] items
  in
  let rec internal_find_trs basedir stack =
    let items = Array.to_list (Sys.readdir basedir) in
    let items = List.map (fun x -> x, basedir // x) items in
    let dirs, files = split_dirs_and_files items in
    let files = List.filter (fun (x, _) -> Filename.check_suffix x ".trs") files in
    let files = List.map (fun (_, full_x) -> stack, full_x) files in
    let subdirs_files = List.fold_left (
      fun acc (fn, dir) ->
        (internal_find_trs dir (fn :: stack)) :: acc
    ) [] dirs in
    let subdirs_files = List.rev subdirs_files in
    List.concat (files :: subdirs_files)
  in
  internal_find_trs basedir ["tests"]

let sanitize_log log =
  let log = string_replace log "\x1b[0;32m" "" in
  let log = string_replace log "\x1b[1;31m" "" in
  let log = string_replace log "\x1b[1;34m" "" in
  let log = string_replace log "\x1b[1;35m" "" in
  let log = string_replace log "\x1b[0m" "" in
  let log = string_replace log "\x0d" "" in
  log

let escape_text text =
  let text = string_replace text "&" "&amp;" in
  let text = string_replace text "\"" "&quot;" in
  let text = string_replace text "<" "&lt;" in
  text

let iterate_results trs_files =
  let total = ref 0 in
  let failures = ref 0 in
  let errors = ref 0 in
  let skipped = ref 0 in
  let total_time = ref 0 in
  let buf = Buffer.create 16384 in
  let read_trs file =
    let log_filename = (Filename.chop_suffix file ".trs") ^ ".log" in
    let content = read_whole_file file in
    let lines = string_charsplit "\n" content in
    let testname = ref (Filename.chop_suffix (Filename.basename file) ".trs") in
    let res = ref Pass in
    let time = ref 0 in
    List.iter (
      fun line ->
        let line = string_charsplit " " line in
        (match line with
        | ":test-result:" :: result :: rest ->
          let name = String.concat " " rest in
          if String.length name > 0 then testname := name;
          res :=
            (match result with
            | "PASS" -> Pass
            | "SKIP" -> Skip
            | "XFAIL" -> XFail
            | "FAIL" -> Fail
            | "XPASS" -> XPass
            | "ERROR" | _ -> Error);
        | ":guestfs-time:" :: delta :: _ ->
          time := int_of_string delta
        | _ -> ()
        );
    ) lines;
    !testname, !res, !time, log_filename in
  List.iter (
    fun (stack, file) ->
      let testname, result, time, log_filename = read_trs file in
      let log = try read_whole_file log_filename with _ -> "" in
      let log = sanitize_log log in
      let print_tag_with_log tag =
        Buffer.add_string buf (sprintf "  <testcase name=\"%s\" classname=\"%s\" time=\"%d\">\n" testname (String.concat "." (List.rev stack)) time);
        Buffer.add_string buf (sprintf "    <%s><![CDATA[%s]]></%s>\n" tag log tag);
        Buffer.add_string buf (sprintf "  </testcase>\n")
      in
      (match result with
      | Pass ->
        print_tag_with_log "system-out"
      | Skip ->
        skipped := !skipped + 1;
        Buffer.add_string buf (sprintf "  <testcase name=\"%s\" classname=\"%s\" time=\"%d\">\n" testname (String.concat "." (List.rev stack)) time);
        Buffer.add_string buf (sprintf "    <skipped message=\"%s\"></skipped>\n" (escape_text log));
        Buffer.add_string buf (sprintf "  </testcase>\n")
      | XFail | Fail | XPass ->
        failures := !failures + 1;
        print_tag_with_log "error"
      | Error ->
        errors := !errors + 1;
        print_tag_with_log "error"
      );
      total := !total + 1;
      total_time := !total_time + time
  ) trs_files;
  Buffer.contents buf, !total, !failures, !errors, !skipped, !total_time

let sort_trs (_, f1) (_, f2) =
  compare f1 f2

let () =
  if Array.length Sys.argv < 3 then (
    printf "%s PROJECTNAME BASEDIR\n" Sys.argv.(0);
    exit 1
  );
  let name = Sys.argv.(1) in
  let basedir = Sys.argv.(2) in
  let trs_files = List.sort sort_trs (find_trs basedir) in
  let buf, total, failures, errors, skipped, time =
    iterate_results trs_files in
  printf "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<testsuite name=\"%s\" tests=\"%d\" failures=\"%d\" skipped=\"%d\" errors=\"%d\" time=\"%d\">
<properties />
%s</testsuite>
" name total failures skipped errors time buf