testing: support for internal module testing
parent
3a2c46a1ce
commit
1cd5fab21d
|
@ -506,24 +506,22 @@ pub fn (v mut V) generate_main() {
|
||||||
if v.table.main_exists() {
|
if v.table.main_exists() {
|
||||||
verror('test files cannot have function `main`')
|
verror('test files cannot have function `main`')
|
||||||
}
|
}
|
||||||
if !v.table.has_at_least_one_test_fn() {
|
test_fn_names := v.table.all_test_function_names()
|
||||||
|
if test_fn_names.len == 0 {
|
||||||
verror('test files need to have at least one test function')
|
verror('test files need to have at least one test function')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a C `main`, which calls every single test function
|
// Generate a C `main`, which calls every single test function
|
||||||
v.gen_main_start(false)
|
v.gen_main_start(false)
|
||||||
|
|
||||||
if v.pref.is_stats {
|
if v.pref.is_stats {
|
||||||
cgen.genln('BenchedTests bt = main__start_testing();')
|
cgen.genln('BenchedTests bt = main__start_testing();')
|
||||||
}
|
}
|
||||||
|
for tfname in test_fn_names {
|
||||||
for _, f in v.table.fns {
|
if v.pref.is_stats { cgen.genln('BenchedTests_testing_step_start(&bt, tos3("$tfname"));') }
|
||||||
if f.name.starts_with('main__test_') {
|
cgen.genln('$tfname ();')
|
||||||
if v.pref.is_stats {
|
|
||||||
cgen.genln('BenchedTests_testing_step_start(&bt, tos3("$f.name"));') }
|
|
||||||
cgen.genln('$f.name ();')
|
|
||||||
if v.pref.is_stats { cgen.genln('BenchedTests_testing_step_end(&bt);') }
|
if v.pref.is_stats { cgen.genln('BenchedTests_testing_step_end(&bt);') }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if v.pref.is_stats { cgen.genln('BenchedTests_end_testing(&bt);') }
|
if v.pref.is_stats { cgen.genln('BenchedTests_end_testing(&bt);') }
|
||||||
v.gen_main_end('return g_test_fails > 0')
|
v.gen_main_end('return g_test_fails > 0')
|
||||||
}
|
}
|
||||||
|
@ -766,17 +764,25 @@ pub fn (v &V) get_user_files() []string {
|
||||||
user_files << filepath.join(preludes_path,'tests_with_stats.v')
|
user_files << filepath.join(preludes_path,'tests_with_stats.v')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_test := dir.ends_with('_test.v')
|
||||||
|
mut is_internal_module_test := false
|
||||||
|
if is_test {
|
||||||
|
tcontent := os.read_file( dir ) or { panic('$dir does not exist') }
|
||||||
|
if tcontent.contains('module ') && !tcontent.contains('module main') {
|
||||||
|
is_internal_module_test = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if is_internal_module_test {
|
||||||
// v volt/slack_test.v: compile all .v files to get the environment
|
// v volt/slack_test.v: compile all .v files to get the environment
|
||||||
// I need to implement user packages! TODO
|
single_test_v_file := os.realpath(dir)
|
||||||
is_test_with_imports := dir.ends_with('_test.v') &&
|
if v.pref.is_verbose {
|
||||||
(dir.contains('${os.path_separator}volt') ||
|
v.log('> Compiling an internal module _test.v file $single_test_v_file .')
|
||||||
dir.contains('${os.path_separator}c2volt'))// TODO
|
v.log('> That brings in all other ordinary .v files in the same module too .')
|
||||||
if is_test_with_imports {
|
|
||||||
user_files << dir
|
|
||||||
if pos := dir.last_index(os.path_separator) {
|
|
||||||
dir = dir[..pos] + os.path_separator// TODO why is this needed
|
|
||||||
}
|
}
|
||||||
|
user_files << single_test_v_file
|
||||||
|
dir = os.basedir( single_test_v_file )
|
||||||
}
|
}
|
||||||
|
|
||||||
if dir.ends_with('.v') || dir.ends_with('.vsh') {
|
if dir.ends_with('.v') || dir.ends_with('.vsh') {
|
||||||
single_v_file := dir
|
single_v_file := dir
|
||||||
// Just compile one file and get parent dir
|
// Just compile one file and get parent dir
|
||||||
|
|
|
@ -19,7 +19,7 @@ fn cb_assertion_failed(filename string, line int, sourceline string, funcname st
|
||||||
else { true }
|
else { true }
|
||||||
}
|
}
|
||||||
final_filename := if use_relative_paths { filename } else { os.realpath( filename ) }
|
final_filename := if use_relative_paths { filename } else { os.realpath( filename ) }
|
||||||
final_funcname := funcname.replace('main__','')
|
final_funcname := funcname.replace('main__','').replace('__','.')
|
||||||
|
|
||||||
mut fail_message := 'FAILED assertion'
|
mut fail_message := 'FAILED assertion'
|
||||||
if color_on { fail_message = term.bold(term.red(fail_message)) }
|
if color_on { fail_message = term.bold(term.red(fail_message)) }
|
||||||
|
|
|
@ -34,7 +34,7 @@ fn start_testing() BenchedTests {
|
||||||
|
|
||||||
// Called before each test_ function, defined in file_test.v
|
// Called before each test_ function, defined in file_test.v
|
||||||
fn (b mut BenchedTests) testing_step_start(stepfunc string) {
|
fn (b mut BenchedTests) testing_step_start(stepfunc string) {
|
||||||
b.step_func_name = stepfunc.replace('main__','')
|
b.step_func_name = stepfunc.replace('main__','').replace('__','.')
|
||||||
b.oks = C.g_test_oks
|
b.oks = C.g_test_oks
|
||||||
b.fails = C.g_test_fails
|
b.fails = C.g_test_fails
|
||||||
b.bench.step()
|
b.bench.step()
|
||||||
|
|
|
@ -778,13 +778,14 @@ fn (t &Table) main_exists() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (t &Table) has_at_least_one_test_fn() bool {
|
fn (t &Table) all_test_function_names() []string {
|
||||||
|
mut res := []string
|
||||||
for _, f in t.fns {
|
for _, f in t.fns {
|
||||||
if f.name.starts_with('main__test_') {
|
if f.name.contains('__test_') {
|
||||||
return true
|
res << f.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (t &Table) find_const(name string) ?Var {
|
fn (t &Table) find_const(name string) ?Var {
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
module amodule
|
||||||
|
|
||||||
|
// This tests whether _test.v files can be *internal* to a
|
||||||
|
// module, and thus have access to its guts.
|
||||||
|
|
||||||
|
// NB: the function test_private_isub() is defined both here
|
||||||
|
// and inside internal_module_test.v . That is done on purpose,
|
||||||
|
// with the goal of ensuring that _test.v files are compiled
|
||||||
|
// *independently* from each other.
|
||||||
|
//
|
||||||
|
// _test.v files should *only* import all the other normal .v
|
||||||
|
// files from the same folder, NOT other _test.v files from it.
|
||||||
|
|
||||||
|
fn test_private_isub(){
|
||||||
|
assert private_isub(7,5) == 2
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
module amodule
|
||||||
|
|
||||||
|
// this tests whether _test.v files can be *internal*
|
||||||
|
// to a module, and thus have access to its guts.
|
||||||
|
|
||||||
|
fn test_iadd(){
|
||||||
|
assert iadd(10, 20) == 30
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_imul(){
|
||||||
|
assert imul(5,8) == 40
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_private_isub(){
|
||||||
|
assert private_isub(10,6) == 4
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
module amodule
|
||||||
|
|
||||||
|
pub fn iadd(x int, y int) int {
|
||||||
|
return x + y
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn imul(x int, y int) int {
|
||||||
|
return x * y
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
fn private_isub(x int, y int) int {
|
||||||
|
return x - y
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
module main
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import compiler.tests.repl.runner
|
import compiler.tests.repl.runner
|
||||||
import benchmark
|
import benchmark
|
||||||
|
|
Loading…
Reference in New Issue