v

Зеркало из https://github.com/vlang/v
Форк
0
/
vtest-all.v 
551 строка · 17.1 Кб
1
module main
2

3
import os
4
import term
5
import time
6

7
const vexe_path = os.getenv('VEXE')
8

9
const vroot = os.dir(vexe_path)
10

11
const vexe = os.quoted_path(vexe_path)
12

13
const args_string = os.args[1..].join(' ')
14

15
const vargs = args_string.all_before('test-all')
16

17
const vtest_nocleanup = os.getenv('VTEST_NOCLEANUP').bool()
18

19
const hw_native_no_builtin_size_limit = 300
20

21
const l2w_crosscc = os.find_abs_path_of_executable('x86_64-w64-mingw32-gcc-win32') or { '' }
22

23
const clang_path = os.find_abs_path_of_executable('clang') or { '' }
24

25
fn main() {
26
	mut commands := get_all_commands()
27
	// summary
28
	sw := time.new_stopwatch()
29
	for mut cmd in commands {
30
		cmd.run()
31
	}
32
	spent := sw.elapsed().milliseconds()
33
	oks := commands.filter(it.ecode == 0)
34
	fails := commands.filter(it.ecode != 0)
35
	flush_stdout()
36
	println('')
37
	println(term.header_left(term_highlight('Summary of `v test-all`:'), '-'))
38
	println(term_highlight('Total runtime: ${spent} ms'))
39
	for ocmd in oks {
40
		msg := if ocmd.okmsg != '' { ocmd.okmsg } else { ocmd.line }
41
		println(term.colorize(term.green, '>          OK: ${msg} '))
42
	}
43
	for fcmd in fails {
44
		msg := if fcmd.errmsg != '' { fcmd.errmsg } else { fcmd.line }
45
		println(term.failed('>      Failed:') + ' ${msg}')
46
	}
47
	flush_stdout()
48
	if fails.len > 0 {
49
		exit(1)
50
	}
51
}
52

53
enum RunCommandKind {
54
	system
55
	execute
56
}
57

58
const expect_nothing = '<nothing>'
59

60
const starts_with_nothing = '<nothing>'
61

62
const ends_with_nothing = '<nothing>'
63

64
const contains_nothing = '<nothing>'
65

66
type FnCheck = fn () !
67

68
struct Command {
69
mut:
70
	line        string
71
	label       string // when set, the label will be printed *before* cmd.line is executed
72
	ecode       int
73
	okmsg       string
74
	errmsg      string
75
	rmfile      string
76
	runcmd      RunCommandKind = .system
77
	expect      string         = expect_nothing
78
	starts_with string         = starts_with_nothing
79
	ends_with   string         = ends_with_nothing
80
	contains    string         = contains_nothing
81
	output      string
82
	before_cb   FnCheck = unsafe { nil }
83
	after_cb    FnCheck = unsafe { nil }
84
}
85

86
fn get_all_commands() []Command {
87
	mut res := []Command{}
88
	res << Command{
89
		line:   '${vexe} examples/hello_world.v'
90
		okmsg:  'V can compile hello world.'
91
		rmfile: 'examples/hello_world'
92
	}
93
	$if linux {
94
		if l2w_crosscc != '' {
95
			res << Command{
96
				line:   '${vexe} -os windows examples/hello_world.v'
97
				okmsg:  'V cross compiles hello_world.v on linux, to a windows .exe file'
98
				rmfile: 'examples/hello_world.exe'
99
			}
100
		} else {
101
			eprintln('Testing cross compilation from linux to windows needs x86_64-w64-mingw32-gcc-win32. Skipping hello_world.exe test.')
102
		}
103
	}
104
	res << Command{
105
		line:   '${vexe} -o hhww.c examples/hello_world.v'
106
		okmsg:  'V can output a .c file, without compiling further.'
107
		rmfile: 'hhww.c'
108
	}
109
	res << Command{
110
		line:   '${vexe} -skip-unused examples/hello_world.v'
111
		okmsg:  'V can compile hello world with -skip-unused.'
112
		rmfile: 'examples/hello_world'
113
	}
114
	res << Command{
115
		line:  '${vexe} -skip-unused test vlib/builtin'
116
		okmsg: 'V can test vlib/builtin with -skip-unused'
117
	}
118
	res << Command{
119
		line:   '${vexe} -skip-unused -profile - examples/hello_world.v'
120
		okmsg:  'V can compile hello world with both -skip-unused and -profile .'
121
		rmfile: 'examples/hello_world'
122
	}
123
	res << Command{
124
		line:   '${vexe} -e "print(84/2)"'
125
		okmsg:  'V can run code given after `-e`'
126
		runcmd: .execute
127
		expect: '42'
128
	}
129
	res << Command{
130
		line:   '${vexe} -e "import os; import math; print(os.args#[1..]) print(math.sin(math.pi/2).str())" arg1 arg2'
131
		okmsg:  'V can run code with `-e`, that use semicolons and several imports, and that accepts CLI parameters.'
132
		runcmd: .execute
133
		expect: "['arg1', 'arg2']1.0"
134
	}
135
	res << Command{
136
		line:     '${vexe} -o calling_c.exe run examples/call_c_from_v/main.c.v'
137
		okmsg:    'V can run main.c.v files'
138
		runcmd:   .execute
139
		contains: 'V can call C functions like `puts` too.'
140
	}
141
	$if linux || macos {
142
		res << Command{
143
			line:   '${vexe} run examples/hello_world.v'
144
			okmsg:  'V can run hello world.'
145
			runcmd: .execute
146
			expect: 'Hello, World!\n'
147
		}
148
		if clang_path != '' {
149
			res << Command{
150
				line:     '${vexe} -os freebsd -gc none examples/hello_world.v'
151
				okmsg:    'V cross compiles hello_world.v, to a FreeBSD executable'
152
				rmfile:   'examples/hello_world'
153
				after_cb: fn () ! {
154
					for file in ['examples/hello_world',
155
						os.join_path(os.vmodules_dir(), 'freebsdroot/usr/include/stdio.h')] {
156
						if !os.exists(file) {
157
							return error('>> file ${file} does not exist')
158
						}
159
					}
160
				}
161
			}
162
		} else {
163
			eprintln('Testing cross compilation to FreeBSD, needs clang.')
164
		}
165
		if os.getenv('V_CI_MUSL').len == 0 {
166
			for compiler_name in ['clang', 'gcc'] {
167
				if _ := os.find_abs_path_of_executable(compiler_name) {
168
					res << Command{
169
						line:   '${vexe} -cc ${compiler_name} -gc boehm run examples/hello_world.v'
170
						okmsg:  '`v -cc ${compiler_name} -gc boehm run examples/hello_world.v` works'
171
						runcmd: .execute
172
						expect: 'Hello, World!\n'
173
					}
174
				}
175
			}
176
		}
177
		res << Command{
178
			line:   '${vexe} interpret examples/hello_world.v'
179
			okmsg:  'V can interpret hello world.'
180
			runcmd: .execute
181
			expect: 'Hello, World!\n'
182
		}
183
		res << Command{
184
			line:        '${vexe} interpret examples/hanoi.v'
185
			okmsg:       'V can interpret hanoi.v'
186
			runcmd:      .execute
187
			starts_with: 'Disc 1 from A to C...\n'
188
			ends_with:   'Disc 1 from A to C...\n'
189
			contains:    'Disc 7 from A to C...\n'
190
		}
191
		res << Command{
192
			line:  '${vexe} -o - examples/hello_world.v | grep "#define V_COMMIT_HASH" > /dev/null'
193
			okmsg: 'V prints the generated source code to stdout with `-o -` .'
194
		}
195
		res << Command{
196
			line:  '${vexe} run examples/v_script.vsh > /dev/null'
197
			okmsg: 'V can run the .VSH script file examples/v_script.vsh'
198
		}
199
		// Note: -experimental is used here, just to suppress the warnings,
200
		// that are otherwise printed by the native backend,
201
		// until globals and hash statements *are implemented*:
202
		$if linux {
203
			res << Command{
204
				line:  '${vexe} -experimental -b native run examples/native/hello_world.v > /dev/null'
205
				okmsg: 'V compiles and runs examples/native/hello_world.v on the native backend for linux'
206
			}
207
			res << Command{
208
				line:     '${vexe} -no-builtin -experimental -b native examples/hello_world.v > /dev/null'
209
				okmsg:    'V compiles examples/hello_world.v on the native backend for linux with `-no-builtin` & the executable is <= ${hw_native_no_builtin_size_limit} bytes'
210
				rmfile:   'examples/hello_world'
211
				after_cb: fn () ! {
212
					file := 'examples/hello_world'
213
					if !os.exists(file) {
214
						return error('>> file ${file} does not exist')
215
					}
216
					if os.file_size(file) > hw_native_no_builtin_size_limit {
217
						return error('>> file ${file} bigger than ${hw_native_no_builtin_size_limit} bytes')
218
					}
219
				}
220
			}
221
		}
222
		// only compilation:
223
		res << Command{
224
			line:   '${vexe} -os linux -experimental -b native -o hw.linux examples/hello_world.v'
225
			okmsg:  'V compiles hello_world.v on the native backend for linux'
226
			rmfile: 'hw.linux'
227
		}
228
		res << Command{
229
			line:   '${vexe} -os macos -experimental -b native -o hw.macos examples/hello_world.v'
230
			okmsg:  'V compiles hello_world.v on the native backend for macos'
231
			rmfile: 'hw.macos'
232
		}
233
		$if windows {
234
			res << Command{
235
				line:   '${vexe} -os windows -experimental -b native -o hw.exe examples/hello_world.v'
236
				okmsg:  'V compiles hello_world.v on the native backend for windows'
237
				rmfile: 'hw.exe'
238
			}
239
		}
240
		//
241
		res << Command{
242
			line:   '${vexe} -b js -o hw.js examples/hello_world.v'
243
			okmsg:  'V compiles hello_world.v on the JS backend'
244
			rmfile: 'hw.js'
245
		}
246
		res << Command{
247
			line:   '${vexe} -skip-unused -b js -o hw_skip_unused.js examples/hello_world.v'
248
			okmsg:  'V compiles hello_world.v on the JS backend, with -skip-unused'
249
			rmfile: 'hw_skip_unused.js'
250
		}
251
		res << Command{
252
			line:   '${vexe} -skip-unused examples/2048'
253
			okmsg:  'V can compile 2048 with -skip-unused.'
254
			rmfile: 'examples/2048/2048'
255
		}
256
		if _ := os.find_abs_path_of_executable('emcc') {
257
			res << Command{
258
				line:   '${vexe} -os wasm32_emscripten examples/2048'
259
				okmsg:  'V can compile 2048 with -os wasm32_emscripten, using emcc.'
260
				rmfile: 'examples/2048/2048'
261
			}
262
		} else {
263
			println('> emcc not found, skipping `v -os wasm32_emscripten examples/2048`.')
264
		}
265
		res << Command{
266
			line:   '${vexe} -skip-unused  -live examples/hot_reload/bounce.v'
267
			okmsg:  'V can compile the hot code reloading bounce.v example with both: -skip-unused -live'
268
			rmfile: 'examples/hot_reload/bounce'
269
		}
270
	}
271
	res << Command{
272
		line:   '${vexe} -o vtmp cmd/v'
273
		okmsg:  'V can compile itself.'
274
		rmfile: 'vtmp'
275
	}
276
	res << Command{
277
		line:   '${vexe} -o vtmp_werror -cstrict cmd/v'
278
		okmsg:  'V can compile itself with -cstrict.'
279
		rmfile: 'vtmp_werror'
280
	}
281
	res << Command{
282
		line:   '${vexe} -o vtmp_autofree -autofree cmd/v'
283
		okmsg:  'V can compile itself with -autofree.'
284
		rmfile: 'vtmp_autofree'
285
	}
286
	res << Command{
287
		line:   '${vexe} -o vtmp_prealloc -prealloc cmd/v'
288
		okmsg:  'V can compile itself with -prealloc.'
289
		rmfile: 'vtmp_prealloc'
290
	}
291
	res << Command{
292
		line:   '${vexe} -o vtmp_unused -skip-unused cmd/v'
293
		okmsg:  'V can compile itself with -skip-unused.'
294
		rmfile: 'vtmp_unused'
295
	}
296
	$if linux {
297
		res << Command{
298
			line:   '${vexe} -cc gcc -keepc -freestanding -o bel vlib/os/bare/bare_example_linux.v'
299
			okmsg:  'V can compile with -freestanding on Linux with GCC.'
300
			rmfile: 'bel'
301
		}
302

303
		res << Command{
304
			line:   '${vexe} -cc gcc -keepc -freestanding -o str_array vlib/strconv/bare/str_array_example.v'
305
			okmsg:  'V can compile & allocate memory with -freestanding on Linux with GCC.'
306
			rmfile: 'str_array'
307
		}
308
	}
309
	////////////////////////////////////////////////////////////////////////
310
	// Test compilation of a shared library (.so, .dll. .dylib) with -shared:
311
	common_shared_flags := '-shared -skip-unused -d no_backtrace -o library examples/dynamic_library_loader/modules/library/library.v'
312
	$if macos {
313
		res << Command{
314
			line:   '${vexe} ${common_shared_flags}'
315
			okmsg:  'V compiles library.v with -shared on macos'
316
			rmfile: 'library.dylib'
317
		}
318
	}
319
	$if linux {
320
		res << Command{
321
			line:   '${vexe} ${common_shared_flags}'
322
			okmsg:  'V compiles library.v with -shared on linux'
323
			rmfile: 'library.so'
324
		}
325
	}
326
	// Test cross compilation to windows with -shared:
327
	$if linux {
328
		if l2w_crosscc != '' {
329
			res << Command{
330
				line:   '${vexe} -os windows ${common_shared_flags}'
331
				okmsg:  'V cross compiles library.v with -shared on linux, to a windows library.dll file'
332
				rmfile: 'library.dll'
333
			}
334
		} else {
335
			eprintln('Testing cross compilation from linux to windows needs x86_64-w64-mingw32-gcc-win32. Skipping library.dll test.')
336
		}
337
	}
338
	////////////////////////////////////////////////////////////////////////
339
	res << Command{
340
		line:  '${vexe} ${vargs} -progress test-cleancode'
341
		okmsg: 'All .v files are invariant when processed with `v fmt`'
342
	}
343
	res << Command{
344
		line:  '${vexe} ${vargs} -progress test-fmt'
345
		okmsg: 'All .v files can be processed with `v fmt`. Note: the result may not always be compilable, but `v fmt` should not crash.'
346
	}
347
	res << Command{
348
		line:  '${vexe} ${vargs} -progress test-self'
349
		okmsg: 'There are no _test.v file regressions.'
350
	}
351
	res << Command{
352
		line:  '${vexe} ${vargs} -progress -N -W build-tools'
353
		okmsg: 'All tools can be compiled.'
354
	}
355
	res << Command{
356
		line:  '${vexe} ${vargs} -progress -N -W build-examples'
357
		okmsg: 'All examples can be compiled.'
358
	}
359
	res << Command{
360
		line:  '${vexe} check-md -hide-warnings .'
361
		label: 'Check ```v ``` code examples and formatting of .MD files...'
362
		okmsg: 'All .md files look good.'
363
	}
364
	res << Command{
365
		line:  '${vexe} install nedpals.args'
366
		okmsg: '`v install` works.'
367
	}
368
	res << Command{
369
		okmsg:       'Running net.http with -d trace_http_request works.'
370
		line:        '${vexe} -d trace_http_request -e \'import net.http; x := http.fetch(url: "https://vpm.url4e.com/some/unknown/url")!; println(x.status_code)\''
371
		runcmd:      .execute
372
		starts_with: '> GET /some/unknown/url HTTP/1.1'
373
		contains:    'User-Agent: v.http'
374
		ends_with:   '404\n'
375
	}
376
	res << Command{
377
		okmsg:       'Running net.http with -d trace_http_response works.'
378
		line:        '${vexe} -d trace_http_response -e \'import net.http; x := http.fetch(url: "https://vpm.url4e.com/some/unknown/url")!; println(x.status_code)\''
379
		runcmd:      .execute
380
		starts_with: '< HTTP/1.1 404 Not Found'
381
		contains:    'Server: nginx'
382
		ends_with:   '404\n'
383
	}
384
	res << Command{
385
		line:   '${vexe} -usecache -cg examples/hello_world.v'
386
		okmsg:  '`v -usecache -cg` works.'
387
		rmfile: 'examples/hello_world'
388
	}
389
	// Note: test that a program that depends on thirdparty libraries with its
390
	// own #flags (tetris depends on gg, which uses sokol) can be compiled
391
	// with -usecache:
392
	res << Command{
393
		line:   '${vexe} -usecache examples/tetris/tetris.v'
394
		okmsg:  '`v -usecache` works.'
395
		rmfile: 'examples/tetris/tetris'
396
	}
397
	$if macos || linux {
398
		res << Command{
399
			line:   '${vexe} -o v.c cmd/v && cc -Werror v.c -lpthread -lm && rm -rf a.out'
400
			label:  'v.c should be buildable with no warnings...'
401
			okmsg:  'v.c can be compiled without warnings. This is good :)'
402
			rmfile: 'v.c'
403
		}
404
	}
405
	$if linux || macos {
406
		res << Command{
407
			line:   '${vexe} -gc none -no-retry-compilation -cc tcc -d use_openssl -showcc examples/veb/todo/main.v'
408
			okmsg:  'A simple veb app, compiles with `-gc none -no-retry-compilation -cc tcc -d use_openssl` on macos and linux'
409
			rmfile: 'examples/veb/todo/main'
410
		}
411
	}
412
	$if linux {
413
		res << Command{
414
			line:     '${vexe} vlib/v/tests/bench/bench_stbi_load.v && prlimit -v10485760 vlib/v/tests/bench/bench_stbi_load'
415
			okmsg:    'STBI load does not leak with GC on, when loading images multiple times (use < 10MB)'
416
			runcmd:   .execute
417
			contains: 'logo.png 1000 times.'
418
			rmfile:   'vlib/v/tests/bench/bench_stbi_load'
419
		}
420
	}
421
	$if !windows {
422
		res << Command{
423
			line:   '${vexe} -raw-vsh-tmp-prefix tmp vlib/v/tests/script_with_no_extension'
424
			okmsg:  'V can crun a script, that lacks a .vsh extension'
425
			runcmd: .execute
426
			expect: 'Test\n'
427
			rmfile: 'vlib/v/tests/tmp.script_with_no_extension'
428
		}
429

430
		res << Command{
431
			line:   '${vexe} -raw-vsh-tmp-prefix tmp run vlib/v/tests/script_with_no_extension'
432
			okmsg:  'V can run a script, that lacks a .vsh extension'
433
			runcmd: .execute
434
			expect: 'Test\n'
435
		}
436
	}
437
	return res
438
}
439

440
fn (mut cmd Command) run() {
441
	// Changing the current directory is needed for some of the compiler tests,
442
	// vlib/v/tests/local_test.v and vlib/v/tests/repl/repl_test.v
443
	os.chdir(vroot) or {}
444
	if cmd.label != '' {
445
		println(term.header_left(cmd.label, '*'))
446
	}
447
	if cmd.before_cb != unsafe { nil } {
448
		cmd.before_cb() or {
449
			cmd.ecode = -1
450
			cmd.errmsg = '> before_cb callback for "${cmd.line}" ${term.failed('FAILED')}\n${err}'
451
			println(cmd.errmsg)
452
			return
453
		}
454
	}
455
	sw := time.new_stopwatch()
456
	if cmd.runcmd == .system {
457
		cmd.ecode = os.system(cmd.line)
458
		cmd.output = ''
459
	}
460
	if cmd.runcmd == .execute {
461
		res := os.execute(cmd.line)
462
		cmd.ecode = res.exit_code
463
		cmd.output = res.output
464
	}
465
	spent := sw.elapsed().milliseconds()
466
	if cmd.after_cb != unsafe { nil } {
467
		cmd.after_cb() or {
468
			cmd.ecode = -1
469
			cmd.errmsg = '> after_cb callback for "${cmd.line}" ${term.failed('FAILED')}\n${err}'
470
			println(cmd.errmsg)
471
			return
472
		}
473
	}
474

475
	mut is_failed := false
476
	mut is_failed_expected := false
477
	mut is_failed_starts_with := false
478
	mut is_failed_ends_with := false
479
	mut is_failed_contains := false
480
	if cmd.ecode != 0 {
481
		is_failed = true
482
	}
483
	if cmd.expect != expect_nothing {
484
		if cmd.output != cmd.expect {
485
			is_failed = true
486
			is_failed_expected = true
487
		}
488
	}
489
	if cmd.starts_with != starts_with_nothing {
490
		if !cmd.output.starts_with(cmd.starts_with) {
491
			is_failed = true
492
			is_failed_starts_with = true
493
		}
494
	}
495
	if cmd.ends_with != ends_with_nothing {
496
		if !cmd.output.ends_with(cmd.ends_with) {
497
			is_failed = true
498
			is_failed_ends_with = true
499
		}
500
	}
501
	if cmd.contains != contains_nothing {
502
		if !cmd.output.contains(cmd.contains) {
503
			is_failed = true
504
			is_failed_contains = true
505
		}
506
	}
507

508
	run_label := if is_failed { term.failed('FAILED') } else { term_highlight('OK') }
509
	println('> Running: "${cmd.line}" took: ${spent} ms ... ${run_label}')
510

511
	if is_failed && is_failed_expected {
512
		eprintln('> expected:\n${cmd.expect}')
513
		eprintln('>   output:\n${cmd.output}')
514
	}
515
	if is_failed && is_failed_starts_with {
516
		eprintln('> expected to start with:\n${cmd.starts_with}')
517
		eprintln('>                 output:\n${cmd.output#[..cmd.starts_with.len]}')
518
	}
519
	if is_failed && is_failed_ends_with {
520
		eprintln('> expected to end with:\n${cmd.ends_with}')
521
		eprintln('>               output:\n${cmd.output#[-cmd.starts_with.len..]}')
522
	}
523
	if is_failed && is_failed_contains {
524
		eprintln('> expected to contain:\n${cmd.contains}')
525
		eprintln('>              output:\n${cmd.output}')
526
	}
527
	if vtest_nocleanup {
528
		return
529
	}
530
	if cmd.rmfile != '' {
531
		mut file_existed := rm_existing(cmd.rmfile)
532
		if os.user_os() == 'windows' {
533
			file_existed = file_existed || rm_existing(cmd.rmfile + '.exe')
534
		}
535
		if !file_existed {
536
			eprintln('Expected file did not exist: ${cmd.rmfile}')
537
			cmd.ecode = 999
538
		}
539
	}
540
}
541

542
// try to remove a file, return if it existed before the removal attempt
543
fn rm_existing(path string) bool {
544
	existed := os.exists(path)
545
	os.rm(path) or {}
546
	return existed
547
}
548

549
fn term_highlight(s string) string {
550
	return term.colorize(term.yellow, term.colorize(term.bold, s))
551
}
552

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.