Make REPL tests parallel too
parent
84438c0139
commit
64a9f43405
|
@ -8,6 +8,8 @@ import (
|
||||||
os
|
os
|
||||||
term
|
term
|
||||||
readline
|
readline
|
||||||
|
os.cmdline
|
||||||
|
filepath
|
||||||
)
|
)
|
||||||
|
|
||||||
struct Repl {
|
struct Repl {
|
||||||
|
@ -71,12 +73,13 @@ pub fn repl_help() {
|
||||||
')
|
')
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_repl() []string {
|
pub fn run_repl(workdir string, vrepl_prefix string) []string {
|
||||||
version := v_version()
|
version := v_version()
|
||||||
println(version)
|
println(version)
|
||||||
println('Use Ctrl-C or `exit` to exit')
|
println('Use Ctrl-C or `exit` to exit')
|
||||||
file := '.vrepl.v'
|
|
||||||
temp_file := '.vrepl_temp.v'
|
file := filepath.join( workdir, '.${vrepl_prefix}vrepl.v' )
|
||||||
|
temp_file := filepath.join( workdir, '.${vrepl_prefix}vrepl_temp.v')
|
||||||
mut prompt := '>>> '
|
mut prompt := '>>> '
|
||||||
defer {
|
defer {
|
||||||
os.rm(file)
|
os.rm(file)
|
||||||
|
@ -192,13 +195,19 @@ pub fn run_repl() []string {
|
||||||
fn print_output(s os.Result) {
|
fn print_output(s os.Result) {
|
||||||
lines := s.output.split('\n')
|
lines := s.output.split('\n')
|
||||||
for line in lines {
|
for line in lines {
|
||||||
if line.starts_with('.vrepl_temp.v') {
|
if line.contains('.vrepl_temp.v:') {
|
||||||
// Hide the temporary file name
|
// Hide the temporary file name
|
||||||
idx := line.index(' ') or {
|
sline := line.all_after('.vrepl_temp.v:')
|
||||||
println(line)
|
idx := sline.index(' ') or {
|
||||||
|
println(sline)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println(line[idx+1..])
|
println(sline[idx+1..])
|
||||||
|
} else if line.contains('.vrepl.v:') {
|
||||||
|
// Ensure that .vrepl.v: is at the start, ignore the path
|
||||||
|
// This is needed to have stable .repl tests.
|
||||||
|
idx := line.index('.vrepl.v:') or { return }
|
||||||
|
println(line[idx..])
|
||||||
} else {
|
} else {
|
||||||
println(line)
|
println(line)
|
||||||
}
|
}
|
||||||
|
@ -207,13 +216,20 @@ fn print_output(s os.Result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// Support for the parameters replfolder and replprefix is needed
|
||||||
|
// so that the repl can be launched in parallel by several different
|
||||||
|
// threads by the REPL test runner.
|
||||||
|
args := cmdline.after(os.args, ['repl'])
|
||||||
|
replfolder := os.realpath( cmdline.option(args, '-replfolder', '.') )
|
||||||
|
replprefix := cmdline.option(args, '-replprefix', 'noprefix.')
|
||||||
|
os.chdir( replfolder )
|
||||||
if !os.exists(os.getenv('VEXE')) {
|
if !os.exists(os.getenv('VEXE')) {
|
||||||
println('Usage:')
|
println('Usage:')
|
||||||
println(' VEXE=vexepath vrepl\n')
|
println(' VEXE=vexepath vrepl\n')
|
||||||
println(' ... where vexepath is the full path to the v executable file')
|
println(' ... where vexepath is the full path to the v executable file')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
run_repl()
|
run_repl( replfolder, replprefix )
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rerror(s string) {
|
pub fn rerror(s string) {
|
||||||
|
|
|
@ -3,6 +3,9 @@ module main
|
||||||
import os
|
import os
|
||||||
import compiler.tests.repl.runner
|
import compiler.tests.repl.runner
|
||||||
import benchmark
|
import benchmark
|
||||||
|
import runtime
|
||||||
|
import sync
|
||||||
|
import filepath
|
||||||
|
|
||||||
fn test_the_v_compiler_can_be_invoked() {
|
fn test_the_v_compiler_can_be_invoked() {
|
||||||
vexec := runner.full_path_to_v(5)
|
vexec := runner.full_path_to_v(5)
|
||||||
|
@ -23,21 +26,79 @@ fn test_the_v_compiler_can_be_invoked() {
|
||||||
assert r_error.output == '`nonexisting.v` does not exist'
|
assert r_error.output == '`nonexisting.v` does not exist'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Session {
|
||||||
|
mut:
|
||||||
|
options runner.RunnerOptions
|
||||||
|
bmark benchmark.Benchmark
|
||||||
|
ntask int
|
||||||
|
ntask_mtx &sync.Mutex
|
||||||
|
waitgroup &sync.WaitGroup
|
||||||
|
}
|
||||||
|
|
||||||
fn test_all_v_repl_files() {
|
fn test_all_v_repl_files() {
|
||||||
options := runner.new_options()
|
mut session := &Session{
|
||||||
mut bmark := benchmark.new_benchmark()
|
options: runner.new_options()
|
||||||
for file in options.files {
|
bmark: benchmark.new_benchmark()
|
||||||
bmark.step()
|
ntask: 0
|
||||||
fres := runner.run_repl_file(options.wd, options.vexec, file) or {
|
ntask_mtx: sync.new_mutex()
|
||||||
bmark.fail()
|
waitgroup: sync.new_waitgroup()
|
||||||
eprintln(bmark.step_message_fail(err))
|
}
|
||||||
|
|
||||||
|
// warmup, and ensure that the vrepl is compiled in single threaded mode if it does not exist
|
||||||
|
runner.run_repl_file(os.cachedir(), session.options.vexec, 'vlib/compiler/tests/repl/nothing.repl') or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
session.bmark.set_total_expected_steps( session.options.files.len )
|
||||||
|
mut ncpus := runtime.nr_cpus()
|
||||||
|
$if windows {
|
||||||
|
// See: https://docs.microsoft.com/en-us/cpp/build/reference/fs-force-synchronous-pdb-writes?view=vs-2019
|
||||||
|
ncpus = 1
|
||||||
|
}
|
||||||
|
session.waitgroup.add( ncpus )
|
||||||
|
for i:=0; i < ncpus; i++ {
|
||||||
|
go process_in_thread(session)
|
||||||
|
}
|
||||||
|
session.waitgroup.wait()
|
||||||
|
session.bmark.stop()
|
||||||
|
println(session.bmark.total_message('total time spent running REPL files'))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_in_thread( session mut Session ){
|
||||||
|
cdir := os.cachedir()
|
||||||
|
mut tls_bench := benchmark.new_benchmark()
|
||||||
|
tls_bench.set_total_expected_steps( session.bmark.nexpected_steps )
|
||||||
|
for {
|
||||||
|
session.ntask_mtx.lock()
|
||||||
|
session.ntask++
|
||||||
|
idx := session.ntask-1
|
||||||
|
session.ntask_mtx.unlock()
|
||||||
|
|
||||||
|
if idx >= session.options.files.len { break }
|
||||||
|
tls_bench.cstep = idx
|
||||||
|
|
||||||
|
tfolder := filepath.join( cdir, 'vrepl_tests_$idx')
|
||||||
|
if os.is_dir( tfolder ) {
|
||||||
|
os.rmdir_recursive( tfolder )
|
||||||
|
}
|
||||||
|
os.mkdir( tfolder ) or { panic(err) }
|
||||||
|
|
||||||
|
file := os.realpath( filepath.join( session.options.wd, session.options.files[ idx ] ) )
|
||||||
|
session.bmark.step()
|
||||||
|
tls_bench.step()
|
||||||
|
fres := runner.run_repl_file(tfolder, session.options.vexec, file) or {
|
||||||
|
session.bmark.fail()
|
||||||
|
tls_bench.fail()
|
||||||
|
os.rmdir_recursive( tfolder )
|
||||||
|
eprintln(tls_bench.step_message_fail(err))
|
||||||
assert false
|
assert false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bmark.ok()
|
session.bmark.ok()
|
||||||
println(bmark.step_message_ok(fres))
|
tls_bench.ok()
|
||||||
|
os.rmdir_recursive( tfolder )
|
||||||
|
println(tls_bench.step_message_ok(fres))
|
||||||
assert true
|
assert true
|
||||||
}
|
}
|
||||||
bmark.stop()
|
session.waitgroup.done()
|
||||||
println(bmark.total_message('total time spent running REPL files'))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
filepath
|
filepath
|
||||||
)
|
)
|
||||||
|
|
||||||
struct RunnerOptions {
|
pub struct RunnerOptions {
|
||||||
pub:
|
pub:
|
||||||
wd string
|
wd string
|
||||||
vexec string
|
vexec string
|
||||||
|
@ -22,12 +22,12 @@ pub fn full_path_to_v(dirs_in int) string {
|
||||||
for i := 0; i < dirs_in; i++ {
|
for i := 0; i < dirs_in; i++ {
|
||||||
path = filepath.dir(path)
|
path = filepath.dir(path)
|
||||||
}
|
}
|
||||||
vexec := path + os.path_separator + vname
|
vexec := filepath.join( path, vname )
|
||||||
/*
|
/*
|
||||||
args := os.args
|
args := os.args
|
||||||
vreal := os.realpath('v')
|
vreal := os.realpath('v')
|
||||||
myself := os.realpath( os.executable() )
|
myself := os.realpath( os.executable() )
|
||||||
wd := os.getwd() + os.path_separator
|
wd := os.getwd()
|
||||||
println('args are: $args')
|
println('args are: $args')
|
||||||
println('vreal : $vreal')
|
println('vreal : $vreal')
|
||||||
println('myself : $myself')
|
println('myself : $myself')
|
||||||
|
@ -56,16 +56,23 @@ pub fn run_repl_file(wd string, vexec string, file string) ?string {
|
||||||
input := content.all_before('===output===\n')
|
input := content.all_before('===output===\n')
|
||||||
output := content.all_after('===output===\n')
|
output := content.all_after('===output===\n')
|
||||||
|
|
||||||
input_temporary_filename := 'input_temporary_filename.txt'
|
fname := filepath.filename( file )
|
||||||
|
input_temporary_filename := os.realpath(filepath.join( wd, 'input_temporary_filename.txt'))
|
||||||
os.write_file(input_temporary_filename, input)
|
os.write_file(input_temporary_filename, input)
|
||||||
rcmd := '"$vexec" repl < $input_temporary_filename'
|
os.write_file( os.realpath(filepath.join( wd, 'original.txt' ) ), fcontent )
|
||||||
|
rcmd := '"$vexec" repl -replfolder "$wd" -replprefix "${fname}." < $input_temporary_filename'
|
||||||
r := os.exec(rcmd) or {
|
r := os.exec(rcmd) or {
|
||||||
os.rm(input_temporary_filename)
|
os.rm(input_temporary_filename)
|
||||||
return error('Could not execute: $rcmd')
|
return error('Could not execute: $rcmd')
|
||||||
}
|
}
|
||||||
os.rm(input_temporary_filename)
|
os.rm(input_temporary_filename)
|
||||||
|
|
||||||
result := r.output.replace('\r','').replace('>>> ', '').replace('>>>', '').replace('... ', '').all_after('Use Ctrl-C or `exit` to exit\n').replace(wd, '' )
|
result := r.output.replace('\r','')
|
||||||
|
.replace('>>> ', '')
|
||||||
|
.replace('>>>', '')
|
||||||
|
.replace('... ', '')
|
||||||
|
.all_after('Use Ctrl-C or `exit` to exit\n')
|
||||||
|
.replace(wd + os.path_separator, '' )
|
||||||
|
|
||||||
if result != output {
|
if result != output {
|
||||||
file_result := '${file}.result.txt'
|
file_result := '${file}.result.txt'
|
||||||
|
@ -120,7 +127,7 @@ $diff
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_options() RunnerOptions {
|
pub fn new_options() RunnerOptions {
|
||||||
wd := os.getwd() + os.path_separator
|
wd := os.getwd()
|
||||||
vexec := full_path_to_v(5)
|
vexec := full_path_to_v(5)
|
||||||
mut files := []string
|
mut files := []string
|
||||||
if os.args.len > 1 {
|
if os.args.len > 1 {
|
||||||
|
@ -136,7 +143,7 @@ pub fn new_options() RunnerOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_prod_options() RunnerOptions {
|
pub fn new_prod_options() RunnerOptions {
|
||||||
wd := os.getwd() + os.path_separator
|
wd := os.getwd()
|
||||||
vexec := full_path_to_v(4)
|
vexec := full_path_to_v(4)
|
||||||
mut files := []string
|
mut files := []string
|
||||||
if os.args.len > 1 {
|
if os.args.len > 1 {
|
||||||
|
|
Loading…
Reference in New Issue