|
10 | 10 | (* *) |
11 | 11 | (**************************************************************************) |
12 | 12 |
|
13 | | -open EzCompat |
14 | | -(* open Ez_win32.V1 *) |
15 | 13 | open Ezcmd.V2 |
16 | | -(* open EZCMD.TYPES *) |
17 | | -open Ez_file.V1 |
18 | | -(* open Ez_call.V1 *) |
19 | | -open Ez_subst.V2 |
| 14 | +open EZCMD.TYPES |
20 | 15 |
|
21 | | -module Misc = Autofonce_misc.Misc |
| 16 | +module Patch_lines = Autofonce_patch.Patch_lines |
22 | 17 | module Parser = Autofonce_core.Parser |
| 18 | +module Misc = Autofonce_misc.Misc |
| 19 | +open Types |
| 20 | +open Filter |
23 | 21 |
|
24 | | -let regen_file filename = |
25 | | - let lines = EzFile.read_lines filename in |
26 | | - let dirname = Filename.dirname filename in |
27 | | - let b = Buffer.create 10000 in |
28 | | - |
29 | | - let must_cleanup = ref false in |
30 | | - let topmap = ref StringMap.empty in |
31 | | - let map = ref StringMap.empty in |
32 | | - |
33 | | - let cleanup () = |
34 | | - if !must_cleanup then begin |
35 | | - Printf.bprintf b "\nAT_CLEANUP\n\n"; |
36 | | - must_cleanup := false ; |
37 | | - map := !topmap ; |
38 | | - end else begin |
39 | | - topmap := !map |
40 | | - end; |
41 | | - Printf.bprintf b |
42 | | - "\n\n\n#############################################################\n\n"; |
43 | | - in |
| 22 | +(* TODO: check why the ignore pattern does not work *) |
| 23 | +let diff args = Patch_lines.Diff { exclude = [ "^# promoted on .*" ]; args } |
| 24 | +let todo = ref (diff None) |
| 25 | +let not_exit = ref false |
44 | 26 |
|
45 | | - let unescape s = |
46 | | - let len = String.length s in |
47 | | - if len >=2 && s.[0] = '"' && s.[len-1] = '"' then |
48 | | - String.sub s 1 (len-2) |
49 | | - else s |
| 27 | +let promote ~filter_args ~exec_args p tc suite = |
| 28 | + filter_args.arg_only_failed <- true ; |
| 29 | + Patch_lines.reset (); |
| 30 | + let state = Runner_common.create_state ~exec_args p tc suite in |
| 31 | + Unix.chdir state.state_run_dir ; |
| 32 | + (* |
| 33 | + let comment_line = |
| 34 | + let t = Unix.gettimeofday () in |
| 35 | + let tm = Unix.localtime t in |
| 36 | + Printf.sprintf "# promoted on %04d-%02d-%02dT%02d:%02d" |
| 37 | + ( 1900 + tm.tm_year ) |
| 38 | + ( 1 + tm.tm_mon ) |
| 39 | + tm.tm_mday |
| 40 | + tm.tm_hour |
| 41 | + tm.tm_min |
50 | 42 | in |
| 43 | +*) |
| 44 | + let promote_test t = |
51 | 45 |
|
52 | | - let get lnum s = try |
53 | | - StringMap.find s !map |
54 | | - with Not_found -> |
55 | | - Misc.error "%s:%d: variable %S not found" filename lnum s |
56 | | - in |
57 | | - |
58 | | - let subst lnum s = |
59 | | - let brace lnum s = |
60 | | - let rec iter var cmds = |
61 | | - match cmds with |
62 | | - | [] -> var |
63 | | - | cmd :: cmds -> |
64 | | - let var = match cmd with |
65 | | - | "basename" -> Filename.remove_extension var |
66 | | - | "get" -> get lnum var |
67 | | - | "read" -> EzFile.read_file (Filename.concat dirname var) |
68 | | - | "read?" -> |
69 | | - let file = Filename.concat dirname var in |
70 | | - if Sys. file_exists file then EzFile.read_file file |
71 | | - else "" |
72 | | - | _ -> Misc.error "Subst: function %%{%s} not defined" cmd |
73 | | - in |
74 | | - iter var cmds |
75 | | - in |
76 | | - let s = String.lowercase_ascii s in |
77 | | - let list = List.rev @@ EzString.split s ':' in |
78 | | - match list with |
79 | | - | [] -> Misc.error "Subst: empty string" |
80 | | - | var :: "string" :: cmds -> iter var cmds |
81 | | - | var :: cmds -> |
82 | | - let var = |
83 | | - let maybe_not_found, var = |
84 | | - let len = String.length var in |
85 | | - if len > 0 && var.[0] = '?' then |
86 | | - true, String.sub var 1 (len-1) |
87 | | - else |
88 | | - false, var |
89 | | - in |
90 | | - try StringMap.find var !map with |
91 | | - | _ -> |
92 | | - if maybe_not_found then "" else |
93 | | - Misc.error "Subst: variable %%{%s} not defined" var |
94 | | - in |
95 | | - iter var cmds |
| 46 | + let rec check actions = |
| 47 | + match actions with |
| 48 | + | [] -> false |
| 49 | + | AF_COMMENT comment :: |
| 50 | + AT_DATA _ :: |
| 51 | + _ when EzString.starts_with comment ~prefix:"autofonce.read:" |
| 52 | + -> true |
| 53 | + | _ :: actions -> check actions |
96 | 54 | in |
97 | | - EZ_SUBST.string ~ctxt: lnum ~sep:'%' ~brace s |
98 | | - in |
99 | | - let set name value = |
100 | | - map := StringMap.add name value !map |
101 | | - in |
102 | | - let rec reset value = |
103 | | - if StringMap.mem value !map then begin |
104 | | - map := StringMap.remove value !map; |
105 | | - reset value |
106 | | - end else |
107 | | - match StringMap.find value !topmap with |
108 | | - | exception Not_found -> () |
109 | | - | v -> |
110 | | - map := StringMap.add value v !map |
111 | | - in |
| 55 | + if check t.test_actions then |
| 56 | + let file = t.test_loc.file in |
| 57 | + Printf.eprintf "Promoting test %d %s\n%!" |
| 58 | + t.test_id ( Parser.name_of_loc t.test_loc ); |
| 59 | + let line_first = t.test_loc.line in |
| 60 | + let line_last = |
| 61 | + match List.rev t.test_actions with |
| 62 | + | AT_CLEANUP { loc } :: _ -> loc.line |
| 63 | + | _ -> Misc.error |
| 64 | + "Last test in %s does not end with AT_CLEANUP ?" file |
| 65 | + in |
112 | 66 |
|
113 | | - set "num" ""; |
114 | | - set "exit" "0"; |
115 | | - set "stdout" ""; |
116 | | - set "stderr" ""; |
117 | | - |
118 | | - Array.iteri (fun lnum line -> |
119 | | - |
120 | | - let len = String.length line in |
121 | | - if len > 0 && line.[0] <> '#' then |
122 | | - let cmd, value = EzString.cut_at line ':' in |
123 | | - let value = String.trim value in |
124 | | - match cmd with |
125 | | - | "test" -> |
126 | | - cleanup (); |
127 | | - Printf.bprintf b "\n\nAT_SETUP(%s)\n" (Parser.m4_escape value); |
128 | | - must_cleanup := true |
129 | | - | "keywords" -> |
| 67 | + let b = Buffer.create 10000 in |
| 68 | + |
| 69 | + Printf.bprintf b "AT_SETUP(%s)\n" (Parser.m4_escape t.test_name); |
| 70 | + |
| 71 | + begin |
| 72 | + match t.test_keywords with |
| 73 | + | [] -> () |
| 74 | + | list -> |
130 | 75 | Printf.bprintf b "AT_KEYWORDS(%s)\n\n" |
131 | | - (Parser.m4_escape (subst lnum value)) |
132 | | - | "reset" -> |
133 | | - let values = EzString.split value ',' in |
134 | | - List.iter reset values |
135 | | - | "set" -> |
136 | | - let name, value = EzString.cut_at value ':' in |
137 | | - let name = String.trim name in |
138 | | - let value = unescape @@ String.trim value in |
139 | | - set name value |
140 | | - | "comment" -> Printf.bprintf b "# %s\n" value |
141 | | - | "skip" -> Printf.bprintf b "%s" |
142 | | - ( String.make (try int_of_string value with _ -> 1) '\n' ) |
143 | | - | "data" -> |
144 | | - let file1, file2 = |
145 | | - let file1, file2 = EzString.cut_at value ':' in |
146 | | - let file2 = if file2 = "" then file1 else file2 in |
147 | | - file1, file2 |
148 | | - in |
149 | | - let basename = Filename.basename file1 in |
150 | | - let contents = EzFile.read_file (Filename.concat dirname file2) in |
151 | | - Printf.bprintf b "AT_DATA(%s,%s)\n" |
152 | | - (Parser.m4_escape basename) |
153 | | - (Parser.m4_escape contents); |
154 | | - | "target" -> |
155 | | - let file1, file2 = |
156 | | - let file1, file2 = EzString.cut_at value ':' in |
157 | | - let file2 = if file2 = "" then file1 else file2 in |
158 | | - file1, file2 |
159 | | - in |
160 | | - let basename = Filename.basename file1 in |
161 | | - let contents = EzFile.read_file (Filename.concat dirname file2) in |
162 | | - Printf.bprintf b "AT_DATA(%s,%s)\n" |
163 | | - (Parser.m4_escape basename) |
164 | | - (Parser.m4_escape contents); |
165 | | - set "target" basename |
166 | | - | "check" -> |
167 | | - set "check" value ; |
168 | | - let command = subst lnum @@ get lnum value in |
169 | | - let exit = subst lnum @@ get lnum "exit" in |
170 | | - let stdout = subst lnum @@ get lnum "stdout" in |
171 | | - let stderr = subst lnum @@ get lnum "stderr" in |
172 | | - Printf.bprintf b "\nAT_CHECK(%s, %s, %s, %s)\n" |
173 | | - (Parser.m4_escape command) |
174 | | - (Parser.m4_escape exit) |
175 | | - (Parser.m4_escape stdout) |
176 | | - (Parser.m4_escape stderr) |
177 | | - | "save" -> |
178 | | - |
179 | | - cleanup (); |
180 | | - let output = Filename.concat dirname value in |
181 | | - let new_contents = Buffer.contents b in |
182 | | - Buffer.clear b; |
183 | | - let old_contents = try EzFile.read_file output with _ -> "" in |
184 | | - if new_contents <> old_contents then begin |
185 | | - EzFile.write_file output new_contents; |
186 | | - Printf.eprintf "File %S regenerated\n%!" output |
187 | | - end |
188 | | - | _ -> Misc.error "Unknown command %S" cmd |
189 | | - ) lines |
190 | | - |
191 | | -let regen () = |
192 | | - let rec iter dirname = |
193 | | - let files = Sys.readdir dirname in |
194 | | - Array.iter (fun basename -> |
195 | | - let filename = Filename.concat dirname basename in |
196 | | - if try Sys.is_directory filename with _ -> false then |
197 | | - iter filename |
198 | | - else |
199 | | - let ext = Filename.extension basename in |
200 | | - if ext = ".atscript" then |
201 | | - regen_file filename |
202 | | - ) files |
| 76 | + (Parser.m4_escape (String.concat " " list)) |
| 77 | + end; |
| 78 | + Promote.print_actions |
| 79 | + ~not_exit:!not_exit |
| 80 | + ~keep_old:true |
| 81 | + t b t.test_actions; |
| 82 | + |
| 83 | + let content = Buffer.contents b in |
| 84 | + Patch_lines.replace_block ~file ~line_first ~line_last content |
203 | 85 | in |
204 | | - iter "." |
| 86 | + List.iter promote_test suite.suite_tests; |
| 87 | + Patch_lines.commit_to_disk ~action:!todo (); |
| 88 | + () |
| 89 | + |
| 90 | +let args auto_promote_arg ~exec_args = [ |
| 91 | + |
| 92 | + [ "not-exit" ], Arg.Set not_exit, |
| 93 | + EZCMD.info "Do not promote exit code" ; |
| 94 | + |
| 95 | + [ "diff-args" ], Arg.String (fun s -> todo := diff (Some s)), |
| 96 | + EZCMD.info ~docv:"ARGS" "Pass these args to the diff command" ; |
| 97 | + |
| 98 | + [ auto_promote_arg ], Arg.Int (fun n -> |
| 99 | + exec_args.arg_auto_promote <- n ; |
| 100 | + todo := Apply ; |
| 101 | + ), |
| 102 | + EZCMD.info |
| 103 | + "Promote and run until all tests have been promoted" |
| 104 | + |
| 105 | +] |
| 106 | + |
| 107 | +let action ~filter_args ~exec_args p tc suite = |
| 108 | + promote ~filter_args ~exec_args p tc suite |
205 | 109 |
|
206 | 110 | let cmd = |
207 | | - let args = [] in |
208 | | - EZCMD.sub "regen" regen |
| 111 | + let testsuite_args, get_testsuite_args = Testsuite.args () in |
| 112 | + let filter_args, get_filter_args = Filter.args () in |
| 113 | + let runner_args, exec_args = Runner_common.args () in |
| 114 | + let args = |
| 115 | + runner_args @ |
| 116 | + testsuite_args @ |
| 117 | + filter_args @ |
| 118 | + args ~exec_args "auto-run" @ |
| 119 | + [ |
| 120 | + |
| 121 | + [ "apply" ], Arg.Unit (fun () -> todo := Apply), |
| 122 | + EZCMD.info "Apply promotion (default is to diff)" ; |
| 123 | + |
| 124 | + [ "diff" ], Arg.Unit (fun () -> todo := diff None), |
| 125 | + EZCMD.info "Diff promotion (default)" ; |
| 126 | + |
| 127 | + [ "fake" ], Arg.String (fun ext -> todo := Fake ext), |
| 128 | + EZCMD.info ~docv:".EXT" |
| 129 | + "Apply promotion to create new files with extension $(docv)" ; |
| 130 | + |
| 131 | + ] |
| 132 | + in |
| 133 | + EZCMD.sub |
| 134 | + "regen" |
| 135 | + (fun () -> |
| 136 | + let filter_args = get_filter_args () in |
| 137 | + let p, tc, suite = Testsuite.find ( get_testsuite_args () ) in |
| 138 | + action ~filter_args ~exec_args p tc suite |
| 139 | + ) |
209 | 140 | ~args |
210 | | - ~doc: "Generate a testsuite" |
| 141 | + ~doc: "Regen tests from templates" |
211 | 142 | ~man:[ |
212 | 143 | `S "DESCRIPTION"; |
213 | 144 | `Blocks [ |
214 | | - `P {|Generates a full testsuite in directory tests/ from a set of data files.|} |
| 145 | + `P {|.|} ; |
215 | 146 | ]; |
216 | 147 | ] |
0 commit comments