aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/cmd/tools/vtest.v
blob: d116d297dd530d252d42bc750a77ccaef247edce (plain)
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
module main

import os
import os.cmdline
import testing
import v.pref

fn main() {
	args := os.args.clone()
	if os.args.last() == 'test' {
		show_usage()
		return
	}
	args_to_executable := args[1..]
	args_before := cmdline.options_before(args_to_executable, ['test'])
	args_after := cmdline.options_after(args_to_executable, ['test'])
	if args_after.join(' ') == 'v' {
		eprintln('`v test v` has been deprecated.')
		eprintln('Use `v test-all` instead.')
		exit(1)
	}
	backend_pos := args_before.index('-b')
	backend := if backend_pos == -1 { '.c' } else { args_before[backend_pos + 1] } // this giant mess because closures are not implemented

	mut ts := testing.new_test_session(args_before.join(' '), true)
	for targ in args_after {
		if os.is_dir(targ) {
			// Fetch all tests from the directory
			files, skip_files := should_test_dir(targ.trim_right(os.path_separator), backend)
			ts.files << files
			ts.skip_files << skip_files
			continue
		} else if os.exists(targ) {
			match should_test(targ, backend) {
				.test {
					ts.files << targ
					continue
				}
				.skip {
					ts.files << targ
					ts.skip_files << targ
					continue
				}
				.ignore {}
			}
		} else {
			eprintln('\nUnrecognized test file `$targ`.\n `v test` can only be used with folders and/or _test.v files.\n')
			show_usage()
			exit(1)
		}
	}
	testing.header('Testing...')
	ts.test()
	println(ts.benchmark.total_message('all V _test.v files'))
	if ts.failed {
		exit(1)
	}
}

fn show_usage() {
	println('Usage:')
	println('   A)')
	println('      v test folder/ : run all v tests in the given folder.')
	println('      v -stats test folder/ : the same, but print more stats.')
	println('   B)')
	println('      v test file_test.v : run test functions in a given test file.')
	println('      v -stats test file_test.v : as above, but with more stats.')
	println('   NB: you can also give many and mixed folder/ file_test.v arguments after `v test` .')
	println('')
}

pub fn should_test_dir(path string, backend string) ([]string, []string) { // return is (files, skip_files)
	mut files := os.ls(path) or { return []string{}, []string{} }
	mut local_path_separator := os.path_separator
	if path.ends_with(os.path_separator) {
		local_path_separator = ''
	}
	mut res_files := []string{}
	mut skip_files := []string{}
	for file in files {
		p := path + local_path_separator + file
		if os.is_dir(p) && !os.is_link(p) {
			if file == 'testdata' {
				continue
			}
			ret_files, ret_skip_files := should_test_dir(p, backend)
			res_files << ret_files
			skip_files << ret_skip_files
		} else if os.exists(p) {
			match should_test(p, backend) {
				.test {
					res_files << p
				}
				.skip {
					res_files << p
					skip_files << p
				}
				.ignore {}
			}
		}
	}
	return res_files, skip_files
}

enum ShouldTestStatus {
	test // do test
	skip
	ignore
}

fn should_test(path string, backend string) ShouldTestStatus {
	if path.ends_with('_test.v') {
		return .test
	}
	if path.ends_with('.v') && path.count('.') == 2 {
		if !path.all_before_last('.v').all_before_last('.').ends_with('_test') {
			return .ignore
		}
		backend_arg := path.all_before_last('.v').all_after_last('.')
		arch := pref.arch_from_string(backend_arg) or { pref.Arch._auto }
		if arch == pref.get_host_arch() {
			return .test
		} else if arch == ._auto {
			if backend_arg == 'c' { // .c.v
				return if backend == 'c' { ShouldTestStatus.test } else { ShouldTestStatus.skip }
			}
			if backend_arg == 'js' {
				return if backend == 'js' { ShouldTestStatus.test } else { ShouldTestStatus.skip }
			}
		} else {
			return .skip
		}
	}
	return .ignore
}