add initial test infrastructure

master
Daniel Kolesa 2021-04-13 02:49:38 +02:00
parent de4a0c65c7
commit c42e58b868
6 changed files with 191 additions and 1 deletions

View File

@ -136,11 +136,29 @@ cd build
args="" args=""
if [ -n "${cross}" ]; then if [ -n "${cross}" ]; then
if [ "${meson_system}" = "windows" ]; then
cat << EOF > meson-exewrapper
#!/bin/sh
export WINEDEBUG=-all
export WINEPREFIX="$(pwd)/.wine"
export DISPLAY=
wine "\$@"
EOF
else
cat << EOF > meson-exewrapper
#!/bin/sh
qemu-${qemu_cpu} -L /usr/${expected_triplet} "\$@"
EOF
fi
chmod +x meson-exewrapper
cat << EOF > crossfile cat << EOF > crossfile
[binaries] [binaries]
c = '${CC}' c = '${CC}'
cpp = '${CXX}' cpp = '${CXX}'
ar = '${AR}'
as = '${AS}'
strip = '${STRIP}' strip = '${STRIP}'
exe_wrapper = '$(pwd)/meson-exewrapper'
[host_machine] [host_machine]
system = '${meson_system}' system = '${meson_system}'
@ -154,7 +172,7 @@ if [ -n "$BUILDTYPE" ]; then
args="${args} --buildtype=$BUILDTYPE" args="${args} --buildtype=$BUILDTYPE"
fi fi
meson .. ${args} || exit 1 meson .. -Dtests_cross=true ${args} || exit 1
ninja all || exit 1 ninja all || exit 1
ninja test || exit 1 ninja test || exit 1
cd .. cd ..

View File

@ -47,10 +47,22 @@ if get_option('cpp_std') == 'none'
endif endif
endif endif
build_root = meson.current_build_dir()
subdir('include') subdir('include')
subdir('src') subdir('src')
subdir('tools') subdir('tools')
if meson.is_cross_build() and get_option('tests')
build_tests = get_option('tests_cross')
else
build_tests = get_option('tests')
endif
if build_tests
subdir('tests')
endif
pkg = import('pkgconfig') pkg = import('pkgconfig')
pkg.generate( pkg.generate(

View File

@ -9,3 +9,15 @@ option('linenoise',
value: 'auto', value: 'auto',
description: 'Use linenoise for the REPL' description: 'Use linenoise for the REPL'
) )
option('tests',
type: 'boolean',
value: 'true',
description: 'Whether to build tests'
)
option('tests_cross',
type: 'boolean',
value: 'false',
description: 'Whether to build tests when cross-compiling'
)

38
tests/meson.build 100644
View File

@ -0,0 +1,38 @@
lang_tests = [
# test_name test_file expected_fail
['simple example', 'simple', false],
]
lib_tests = [
]
test_runner = executable('runner',
['runner.cc'],
dependencies: libcubescript,
include_directories: libcubescript_includes,
cpp_args: extra_cxxflags,
install: false
)
penv = environment()
penv.append('PATH', join_paths(build_root, 'src'))
foreach tcase: lang_tests
test(tcase[0],
test_runner,
args: [join_paths(meson.current_source_dir(), tcase[1] + '.cube')],
should_fail: tcase[2],
env: penv
)
endforeach
foreach tcase: lib_tests
test_exe = executable(tcase[0],
[tcase[0] + '.cc'],
dependencies: libcubescript,
include_directories: libcubescript_includes,
cpp_args: extra_cxxflags,
instalL: false
)
test(tcase[0], tcase[0], should_fail: tcase[1], env: penv)
endforeach

89
tests/runner.cc 100644
View File

@ -0,0 +1,89 @@
/* a rudimentary test runner for cubescript files */
#include <cstdio>
#include <string>
#include <string_view>
#include <cubescript/cubescript.hh>
namespace cs = cubescript;
struct skip_test {};
static bool do_run_file(cs::state &cs, char const *fname) {
FILE *f = std::fopen(fname, "rb");
if (!f) {
return false;
}
std::fseek(f, 0, SEEK_END);
auto len = std::ftell(f);
std::fseek(f, 0, SEEK_SET);
auto buf = std::make_unique<char[]>(len + 1);
if (!buf) {
std::fclose(f);
return false;
}
if (std::fread(buf.get(), 1, len, f) != std::size_t(len)) {
std::fclose(f);
return false;
}
buf[len] = '\0';
cs.run(std::string_view{buf.get(), std::size_t(len)}, fname);
return true;
}
int main(int argc, char **argv) {
if (argc != 2) {
std::fprintf(stderr, "error: incorrect number of arguments\n");
}
cs::state gcs;
cs::std_init_all(gcs);
gcs.new_command("echo", "C", [](auto &s, auto args, auto &) {
std::printf("%s\n", args[0].get_string(s).view().data());
});
gcs.new_command("skip_test", "", [](auto &, auto, auto &) {
throw skip_test{};
});
/* takes a string so we can print it */
gcs.new_command("assert", "ssN", [](auto &s, auto args, auto &ret) {
auto val = args[0];
val.force_code(s);
if (!s.run(val.get_code()).get_bool()) {
if (args[2].get_integer() > 1) {
throw cs::error{
s, "assertion failed: [%s] (%s)",
args[0].get_string(s).data(), args[1].get_string(s).data()
};
} else {
throw cs::error{
s, "assertion failed: [%s]",
args[0].get_string(s).data()
};
}
}
ret = std::move(args[0]);
});
try {
do_run_file(gcs, argv[1]);
} catch (skip_test) {
return 77;
} catch (cs::error const &e) {
std::fprintf(stderr, "error: %s", e.what().data());
return 1;
} catch (...) {
std::fprintf(stderr, "error: unknown error");
return 1;
}
return 0;
}

21
tests/simple.cube 100644
View File

@ -0,0 +1,21 @@
// a simple test mainly to serve as an example
echo "hello world"
// addition
assert [= (+ 5 10) 15]
assert [!= (+ 4 5) 11]
// multiplication
assert [= (* 5 2) 10]
assert [!= (* 3 4) 13]
// string equality
assert [=s "hello world" "hello world"]
assert [!=s "hello world" "dlrow olleh"]
// simple loop
x = 5
loop i 3 [x = (* $x 2); echo $x]
assert [= $x 40]