v / cmd / tools / vcomplete_test.v
238 lines · 226 sloc · 6.3 KB · f09826e928f9612bab9299faefff7cf34a503362
Raw
1import os
2
3const vexe = @VEXE
4const tfolder = os.join_path(os.vtmp_dir(), 'vcomplete_test')
5
6enum Shell {
7 bash
8 fish
9 zsh
10 powershell
11}
12
13fn string_to_shell(shell string) !Shell {
14 return match shell {
15 'bash' {
16 .bash
17 }
18 'fish' {
19 .fish
20 }
21 'zsh' {
22 .zsh
23 }
24 'powershell' {
25 .powershell
26 }
27 else {
28 error('${shell} is not supported')
29 }
30 }
31}
32
33fn testsuite_begin() {
34 os.mkdir_all(tfolder) or {}
35}
36
37fn testsuite_end() {
38 os.rmdir_all(tfolder) or {}
39}
40
41fn detect_shell() Shell {
42 forced_shell := os.getenv('VTEST_VCOMPLETE_SHELL')
43 if forced_shell != '' {
44 return string_to_shell(forced_shell) or { panic(err) }
45 }
46 $if linux || macos {
47 return .bash
48 }
49 $if windows {
50 return .powershell
51 }
52 return .bash
53}
54
55struct CompleteTestCase {
56 shell Shell = detect_shell()
57 structure []string
58 completes map[string][]string
59}
60
61const test_cases = [
62 CompleteTestCase{
63 // Tests the completion of "v complet<tab>" *completeception*
64 structure: [] // no test folders
65 completes: {
66 'v complet': ['complete']
67 }
68 },
69 CompleteTestCase{
70 // Tests the completion of "v ru<tab>"
71 structure: [] // no test folders
72 completes: {
73 'v ru': ['run']
74 }
75 },
76 CompleteTestCase{
77 // Tests with one sub-folder in test root
78 // vfmt off
79 structure: [
80 os.join_path('examples', 'ex1'), // Empty dir
81 os.join_path('examples', 'ex2'), // Two files
82 os.join_path('examples', 'ex2', 'ex2_0.v'),
83 os.join_path('examples', 'ex2', 'ex2_1.v'),
84 os.join_path('examples', 'ex3'), // One file
85 os.join_path('examples', 'ex3', 'ex3.v')
86 ]
87 // vfmt on
88 completes: {
89 'v run e': ['examples/']
90 'v run': ['examples/']
91 'v run ': ['examples/']
92 'v run examples/': ['ex1', 'ex2', 'ex3']
93 'v run examples/ex': ['examples/ex1/', 'examples/ex2/', 'examples/ex3/']
94 'v run examples/ex1': ['examples/ex1/']
95 'v run examples/ex1/': []
96 'v run examples/ex2/': ['ex2_0.v', 'ex2_1.v']
97 'v run examples/ex3/': ['examples/ex3/ex3.v']
98 'v run examples/ex3/ex3.v': ['examples/ex3/ex3.v']
99 'v examp': ['examples/']
100 'v examples/f': []
101 'v examples/': ['ex1', 'ex2', 'ex3']
102 'v examples/ex': ['examples/ex1/', 'examples/ex2/', 'examples/ex3/']
103 'v examples/ex1': ['examples/ex1/']
104 'v examples/ex1/': []
105 'v examples/ex2/': ['ex2_0.v', 'ex2_1.v']
106 'v examples/ex3/': ['examples/ex3/ex3.v']
107 'v examples/ex3/ex3.v': ['examples/ex3/ex3.v']
108 }
109 },
110 CompleteTestCase{
111 // Tests with two sub-folder in test root
112 // vfmt off
113 structure: [
114 os.join_path('sub0', 'ex1'), // Empty dir
115 os.join_path('sub0', 'ex2'), // Two files
116 os.join_path('sub0', 'ex2', 'ex2_0.v'),
117 os.join_path('sub0', 'ex2', 'ex2_1.v'),
118 os.join_path('sub0', 'ex3'), // One file
119 os.join_path('sub0', 'ex3', 'ex3.v'),
120 os.join_path('sub1', 'vex1'),
121 os.join_path('sub1', 'vex2'),
122 os.join_path('sub1', 'vex3'),
123 os.join_path('sub1', 'vex3', 'vex3.v')
124 ]
125 // vfmt on
126 completes: {
127 // sub0
128 'v run ./': ['sub0/', 'sub1/']
129 'v run ./s': ['./sub0/', './sub1/']
130 'v run': ['sub0/', 'sub1/']
131 'v run ': ['sub0/', 'sub1/']
132 'v run sub0/': ['ex1', 'ex2', 'ex3']
133 'v run sub0/ex': ['sub0/ex1/', 'sub0/ex2/', 'sub0/ex3/']
134 'v run sub0/ex1': ['sub0/ex1/']
135 'v run sub0/ex1/': []
136 'v run sub0/ex2/': ['ex2_0.v', 'ex2_1.v']
137 'v run sub0/ex3/': ['sub0/ex3/ex3.v']
138 'v run sub0/ex3/ex3.v': ['sub0/ex3/ex3.v']
139 'v su': ['sub0/', 'sub1/']
140 'v sub': ['sub0/', 'sub1/']
141 'v sub0/f': []
142 'v sub0/': ['ex1', 'ex2', 'ex3']
143 'v sub0/ex': ['sub0/ex1/', 'sub0/ex2/', 'sub0/ex3/']
144 'v sub0/ex1': ['sub0/ex1/']
145 'v sub0/ex1/': []
146 'v sub0/ex2/': ['ex2_0.v', 'ex2_1.v']
147 'v sub0/ex3/': ['sub0/ex3/ex3.v']
148 'v sub0/ex3/ex3.v': ['sub0/ex3/ex3.v']
149 // sub1
150 'v run sub1/': ['vex1', 'vex2', 'vex3']
151 'v sub1/vex1/': []
152 'v sub1/vex2/': []
153 'v sub1/vex3/': ['sub1/vex3/vex3.v']
154 }
155 },
156]
157
158fn run_individual_test(case CompleteTestCase) ! {
159 // Clean plate
160 os.rmdir_all(tfolder) or {}
161 os.mkdir_all(tfolder) or {}
162 // Work relative to the test dir
163 os.chdir(tfolder) or { panic(err) }
164 for relative_path in case.structure {
165 path := os.join_path(tfolder, relative_path)
166 rel_parts := relative_path.split(os.path_separator)
167 if rel_parts.last().contains('.') {
168 // Make the containing dir
169 os.mkdir_all(os.dir(path)) or { panic(err) }
170 // Create empty file
171 mut f := os.create(path) or { panic(err) }
172 f.close()
173 } else {
174 os.mkdir_all(path) or { panic(err) }
175 }
176 }
177 for complete, expected in case.completes {
178 mut pre_strip := ''
179 mut post_strip := ''
180 mut complete_command := '${vexe} complete'
181 match case.shell {
182 .bash {
183 pre_strip = "COMPREPLY+=('"
184 post_strip = "')"
185 complete_command += ' bash'
186 }
187 .fish {
188 complete_command += ' fish'
189 }
190 .zsh {
191 pre_strip = 'compadd -U -S"" -- \''
192 post_strip = "';"
193 complete_command += ' zsh'
194 }
195 .powershell {
196 complete_command += ' powershell'
197 }
198 }
199
200 mut normalized_complete := complete
201 if case.shell == .powershell {
202 normalized_complete = normalized_complete.replace('/', '\\')
203 }
204 complete_command += ' ${normalized_complete}'
205 res := os.execute('${complete_command}')
206 mut lines := res.output.split('\n')
207 for mut line in lines {
208 if case.shell == .powershell {
209 line = line.replace('\r', '')
210 line = line.all_after('.\\')
211 }
212 line = line.trim_string_left(pre_strip).trim_string_right(post_strip)
213 }
214 lines = lines.filter(it != '')
215 lines.sort()
216 mut sorted_expected := expected.clone()
217 if case.shell == .powershell {
218 sorted_expected = sorted_expected.map(fn (path string) string {
219 mut normalized_path := path.replace('/', '\\')
220 normalized_path = normalized_path.all_after('.\\')
221 return normalized_path
222 })
223 }
224 sorted_expected.sort()
225 // eprintln('${complete} ${lines} vs ${sorted_expected}') // kept for easier debugging
226
227 assert lines.len == sorted_expected.len
228 for i, line in lines {
229 assert line == sorted_expected[i]
230 }
231 }
232}
233
234fn test_all_complete_cases() {
235 for case in test_cases {
236 run_individual_test(case)!
237 }
238}
239