|
4 | 4 | module main |
5 | 5 |
|
6 | 6 | import os |
| 7 | +import time |
7 | 8 | import v2.pref |
8 | 9 | import v2.builder |
9 | 10 |
|
10 | 11 | fn main() { |
11 | 12 | compile_args, runtime_args := split_eval_runtime_args(os.args[1..]) |
12 | 13 |
|
13 | | - // Check for 'ast' subcommand |
| 14 | + // Check for subcommands |
14 | 15 | if compile_args.len > 0 && compile_args[0] == 'ast' { |
15 | 16 | run_ast_command(compile_args[1..]) |
16 | 17 | return |
17 | 18 | } |
| 19 | + if compile_args.len > 0 && compile_args[0] == 'test-self' { |
| 20 | + run_test_self() |
| 21 | + return |
| 22 | + } |
18 | 23 |
|
19 | 24 | mut prefs := pref.new_preferences_from_args(compile_args) |
20 | 25 |
|
@@ -119,3 +124,128 @@ fn get_files(args []string) []string { |
119 | 124 | } |
120 | 125 | return files |
121 | 126 | } |
| 127 | + |
| 128 | +fn resolve_own_path() string { |
| 129 | + arg0 := os.args[0] |
| 130 | + if os.is_abs_path(arg0) { |
| 131 | + return arg0 |
| 132 | + } |
| 133 | + return os.join_path(os.getwd(), arg0) |
| 134 | +} |
| 135 | + |
| 136 | +// detect_vroot walks up from `start` looking for a directory containing vlib/builtin. |
| 137 | +fn detect_vroot(start string) string { |
| 138 | + mut dir := start |
| 139 | + if !os.is_abs_path(dir) { |
| 140 | + dir = os.join_path(os.getwd(), dir) |
| 141 | + } |
| 142 | + for _ in 0 .. 10 { |
| 143 | + if os.is_dir(os.join_path(dir, 'vlib', 'builtin')) { |
| 144 | + return dir |
| 145 | + } |
| 146 | + parent := os.dir(dir) |
| 147 | + if parent == dir { |
| 148 | + break |
| 149 | + } |
| 150 | + dir = parent |
| 151 | + } |
| 152 | + return dir |
| 153 | +} |
| 154 | + |
| 155 | +fn run_test_self() { |
| 156 | + t0 := time.now() |
| 157 | + // Resolve the v2 binary's own path. Cannot use @VEXE because when v1 |
| 158 | + // compiles v2, @VEXE bakes in v1's path instead of v2's. |
| 159 | + vexe := resolve_own_path() |
| 160 | + // Walk up from the binary to find the repo root (directory containing vlib/builtin). |
| 161 | + // This allows running from subdirectories like cmd/v2/. |
| 162 | + vroot := detect_vroot(vexe) |
| 163 | + v2_dir := os.join_path(vroot, 'cmd', 'v2') |
| 164 | + |
| 165 | + mut all_test_files := []string{} |
| 166 | + |
| 167 | + // Builtin test files |
| 168 | + for name in ['array_test.v', 'string_test.v', 'map_test.v'] { |
| 169 | + all_test_files << os.join_path(vroot, 'vlib', 'builtin', name) |
| 170 | + } |
| 171 | + |
| 172 | + // Math test |
| 173 | + all_test_files << os.join_path(vroot, 'vlib', 'math', 'math_test.v') |
| 174 | + |
| 175 | + // Sumtype tests in cmd/v2/ |
| 176 | + v2_files := os.ls(v2_dir) or { []string{} } |
| 177 | + for file in v2_files { |
| 178 | + if file.starts_with('test_sumtype') && file.ends_with('.v') { |
| 179 | + all_test_files << os.join_path(v2_dir, file) |
| 180 | + } |
| 181 | + } |
| 182 | + |
| 183 | + // Cleanc regression tests |
| 184 | + cleanc_tests_dir := os.join_path(vroot, 'vlib', 'v2', 'gen', 'cleanc', 'tests') |
| 185 | + cleanc_files := os.ls(cleanc_tests_dir) or { []string{} } |
| 186 | + for file in cleanc_files { |
| 187 | + if file.ends_with('.v') && file != 'run_tests.v' { |
| 188 | + all_test_files << os.join_path(cleanc_tests_dir, file) |
| 189 | + } |
| 190 | + } |
| 191 | + |
| 192 | + total := all_test_files.len |
| 193 | + mut passed := 0 |
| 194 | + mut failed := 0 |
| 195 | + mut failed_files := []string{} |
| 196 | + |
| 197 | + eprintln('---- v2 test-self: ${total} test files ----') |
| 198 | + |
| 199 | + for i, test_file in all_test_files { |
| 200 | + short_name := test_file.replace(vroot + '/', '') |
| 201 | + t1 := time.now() |
| 202 | + |
| 203 | + // Determine output binary path |
| 204 | + base := os.file_name(test_file).all_before_last('.v') |
| 205 | + out_bin := os.join_path(os.temp_dir(), 'v2_test_self_${base}') |
| 206 | + |
| 207 | + // Compile (use os.system to avoid pipe deadlocks with popen/GC) |
| 208 | + compile_cmd := '${vexe} -o ${out_bin} "${test_file}" > /dev/null 2>&1' |
| 209 | + compile_ret := os.system(compile_cmd) |
| 210 | + compile_ms := f64(time.since(t1)) / f64(time.millisecond) |
| 211 | + |
| 212 | + if compile_ret != 0 || !os.exists(out_bin) { |
| 213 | + failed++ |
| 214 | + failed_files << short_name |
| 215 | + eprintln(' FAIL [${i + 1:4}/${total}] C: ${compile_ms:7.1} ms ${short_name}') |
| 216 | + os.rm(out_bin) or {} |
| 217 | + os.rm('${out_bin}.c') or {} |
| 218 | + continue |
| 219 | + } |
| 220 | + |
| 221 | + // Run the compiled binary |
| 222 | + t2 := time.now() |
| 223 | + run_ret := os.system(out_bin + ' > /dev/null 2>&1') |
| 224 | + run_ms := f64(time.since(t2)) / f64(time.millisecond) |
| 225 | + |
| 226 | + if run_ret != 0 { |
| 227 | + failed++ |
| 228 | + failed_files << short_name |
| 229 | + eprintln(' FAIL [${i + 1:4}/${total}] C: ${compile_ms:7.1} ms, R: ${run_ms:7.1} ms ${short_name}') |
| 230 | + } else { |
| 231 | + passed++ |
| 232 | + eprintln('OK [${i + 1:4}/${total}] C: ${compile_ms:7.1} ms, R: ${run_ms:7.1} ms ${short_name}') |
| 233 | + } |
| 234 | + |
| 235 | + os.rm(out_bin) or {} |
| 236 | + os.rm('${out_bin}.c') or {} |
| 237 | + } |
| 238 | + |
| 239 | + elapsed := time.since(t0) |
| 240 | + eprintln('------------------------------------------------------------------------') |
| 241 | + eprintln('${passed} passed, ${failed} failed, ${total} total (${elapsed})') |
| 242 | + if failed_files.len > 0 { |
| 243 | + eprintln('Failed:') |
| 244 | + for f in failed_files { |
| 245 | + eprintln(' ${f}') |
| 246 | + } |
| 247 | + } |
| 248 | + if failed > 0 { |
| 249 | + exit(1) |
| 250 | + } |
| 251 | +} |
0 commit comments