diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 170d138..e41c513 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -14,7 +14,7 @@ jobs: - name: install meson run: apt-get -yq install meson - name: Install build dependencies - run: apt-get -yq install libusb-1.0-0-dev libspdlog-dev libfmt-dev libpango1.0-dev libcairo2-dev gcovr + run: apt-get -yq install libusb-1.0-0-dev libpango1.0-dev libcairo2-dev gcovr - name: get build environment versions run: | echo "=== Start meson version ===" @@ -32,29 +32,25 @@ jobs: echo "=== Start dependency package version ===" apt-cache policy libpango1.0-dev apt-cache policy libcairo2-dev - apt-cache policy libfmt-dev - apt-cache policy libspdlog-dev apt-cache policy libusb-1.0-0-dev echo "=== End dependency package version ===" - - name: setup builddir - run: meson setup builddir -Db_coverage=true - - name: run unit tests - run: ninja -C builddir test - - name: calculate coverage - run: ninja -C builddir coverage-text + - name: Build ptprnt debug + run: scripts/build.sh debug --coverage --test + - name: Generate coverage + run: scripts/generate_coverage.sh --text - name: Coverage report - run: cat ./builddir/meson-logs/coverage.txt - - name: build and test dist package - run: ninja -C builddir dist - - name: upload dist package + run: cat ./coverageReport/coverage.txt + - name: build release + run: scripts/build.sh release + - name: upload release binary uses: actions/upload-artifact@v3 with: name: ptprnt - path: ./builddir/meson-dist/* + path: ./builddir/ptprnt if-no-files-found: error - name: upload coverage report uses: actions/upload-artifact@v3 with: name: coverage.txt - path: ./builddir/meson-logs/coverage.txt + path: ./coverageReport/coverage.txt if-no-files-found: error diff --git a/.gitignore b/.gitignore index eb39252..8082033 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Folder -builddir/ +builddir*/ subprojects/* .cache/ coverageReport/ diff --git a/README.md b/README.md index 8126c1a..bbc93dc 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,21 @@ ptprnt --font "NotoMono Nerd Font" --fontsize 32 --text "🖶 ptprnt v0.2.0 🥰 ## Quick Start -**Install dependencies:** +## Quick Start + +**Binary dependencies** + +Arch Linux: +```bash +pacman -S pango cairo libusb +``` + +Debian/Ubuntu: +```bash +apt install libpangocairo-1.0-0 libusb-1.0-0 +``` + +**Build dependencies:** Arch Linux: ```bash @@ -23,12 +37,19 @@ pacman -S libusb spdlog pango cairo meson Debian/Ubuntu: ```bash -apt-get install libusb-1.0-0-dev libspdlog-dev libfmt-dev libpango1.0-dev libcairo2-dev meson +apt install libusb-1.0-0-dev libspdlog-dev libfmt-dev libpango1.0-dev libcairo2-dev meson ``` +Note: spdlog is built as a subproject and statically linked, so it's not required as a system dependency. + **Build and run:** Clone this repository first and enter the directory. Then build: ```bash +# Using the build script (recommended) +./scripts/build.sh release +builddir/ptprnt --help + +# Or manually with meson meson setup builddir ninja -C builddir builddir/ptprnt --help @@ -181,17 +202,50 @@ ptprnt \ This is a modern C++20 rewrite of [ptouch-print](https://git.familie-radermacher.ch/linux/ptouch-print.git). Credits to Dominic Rademacher for reverse engineering the USB protocol. +**Build script:** +```bash +# Release build (tests disabled for faster builds) +./scripts/build.sh release + +# Debug build (tests enabled) +./scripts/build.sh debug + +# Debug with tests +./scripts/build.sh debug --test + +# Debug with coverage +./scripts/build.sh debug --coverage + +# Clean all build directories +./scripts/build.sh clean + +# Show all options +./scripts/build.sh --help +``` + +**Note:** Tests are only built in debug mode to keep release builds fast and small. Release builds do not include test binaries or link against gtest/gmock. + **Running tests:** ```bash +# Using build script +./scripts/build.sh --test + +# Or manually ninja -C builddir test ``` **Coverage reports:** ```bash -meson setup builddir -Db_coverage=true -ninja -C builddir -ninja -C builddir test -ninja -C builddir coverage-text +# 1. Build with coverage enabled and run tests +./scripts/build.sh debug --coverage --test + +# 2. Generate coverage reports +./scripts/generate_coverage.sh # All formats (html, xml, text) +./scripts/generate_coverage.sh --html # HTML only +./scripts/generate_coverage.sh --text # Text only +./scripts/generate_coverage.sh --xml # XML only (for CI/CD) +./scripts/generate_coverage.sh --html --xml # HTML and XML + ``` ## License diff --git a/meson.build b/meson.build index 15a659b..25a6427 100644 --- a/meson.build +++ b/meson.build @@ -20,10 +20,16 @@ project( ) usb_dep = dependency('libusb-1.0') -log_dep = dependency('spdlog') -fmt_dep = dependency('fmt') pangocairo_dep = dependency('pangocairo') +# spdlog with std::format (C++20) - static library +spdlog_proj = subproject('spdlog', default_options: ['std_format=enabled', 'default_library=static', 'compile_library=true']) +log_dep = spdlog_proj.get_variable('spdlog_dep') + +if not log_dep.found() + error('spdlog not found, can not proceed') +endif + # CLI11 cli11_proj = subproject('cli11') cli11_dep = cli11_proj.get_variable('CLI11_dep') @@ -50,20 +56,27 @@ ptprnt_exe = executable( 'ptprnt', 'src/main.cpp', install: true, - dependencies: [usb_dep, log_dep, fmt_dep, pangocairo_dep, cli11_dep], + dependencies: [usb_dep, log_dep, pangocairo_dep, cli11_dep], include_directories: incdir, sources: [ptprnt_srcs], cpp_args: cpp_args, ) ### Unit tests +# Only build tests for debug builds or when explicitly enabled +build_tests = get_option('buildtype') == 'debug' or get_option('build_tests') -# GTest and GMock -gtest_proj = subproject('gtest') -gtest_dep = gtest_proj.get_variable('gtest_main_dep') -gmock_dep = gtest_proj.get_variable('gmock_main_dep') -if not gtest_dep.found() - error('MESON_SKIP_TEST: gtest not installed.') -endif +if build_tests + # GTest and GMock + gtest_proj = subproject('gtest') + gtest_dep = gtest_proj.get_variable('gtest_main_dep') + gmock_dep = gtest_proj.get_variable('gmock_main_dep') + if not gtest_dep.found() + error('MESON_SKIP_TEST: gtest not installed.') + endif -subdir('tests') \ No newline at end of file + subdir('tests') + message('Tests enabled (buildtype=' + get_option('buildtype') + ')') +else + message('Tests disabled (use debug build or -Dbuild_tests=true to enable)') +endif \ No newline at end of file diff --git a/meson_options.txt b/meson_options.txt index 9cc746f..586619d 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -2,3 +2,8 @@ option('usb_trace_only', type: 'boolean', value: false, description: 'Enable USB trace mode: log USB data without sending to device (saves label tape during debugging)') + +option('build_tests', + type: 'boolean', + value: false, + description: 'Build unit tests (automatically enabled for debug builds)') diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..ad269c7 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,162 @@ +#!/bin/bash + +# Build script for ptprnt - simplifies common build configurations +# Usage: ./scripts/build.sh [release|debug|clean] [options] + +set -e + +SCRIPT_PATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +PROJECT_ROOT="${SCRIPT_PATH}/.." + +# Color output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_usage() { + echo "Usage: $0 [build-type] [options]" + echo "" + echo "Build Types:" + echo " release Build optimized release version (default)" + echo " debug Build debug version with symbols" + echo " clean Clean build directories" + echo "" + echo "Options:" + echo " --coverage Enable coverage reporting (debug builds only)" + echo " --reconfigure Force reconfiguration" + echo " --test Run tests after building" + echo " -j N Use N parallel jobs (default: auto)" + echo "" + echo "Examples:" + echo " $0 # Build release" + echo " $0 debug --test # Build debug and run tests" + echo " $0 debug --coverage # Build debug with coverage" + echo " $0 clean # Clean all build directories" +} + +# Default values +BUILD_TYPE="release" +BUILDDIR="builddir" +COVERAGE=false +RECONFIGURE=false +RUN_TESTS=false +JOBS="" + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + release|debug|clean) + BUILD_TYPE="$1" + shift + ;; + --coverage) + COVERAGE=true + shift + ;; + --reconfigure) + RECONFIGURE=true + shift + ;; + --test) + RUN_TESTS=true + shift + ;; + -j) + JOBS="-j $2" + shift 2 + ;; + -h|--help) + print_usage + exit 0 + ;; + *) + echo -e "${RED}Error: Unknown option: $1${NC}" + print_usage + exit 1 + ;; + esac +done + +cd "${PROJECT_ROOT}" + +# Handle clean +if [[ "${BUILD_TYPE}" == "clean" ]]; then + echo -e "${YELLOW}Cleaning build directories...${NC}" + rm -rf builddir builddir-debug + echo -e "${GREEN}Clean complete!${NC}" + exit 0 +fi + +# Set build directory and options based on build type +if [[ "${BUILD_TYPE}" == "debug" ]]; then + BUILDDIR="builddir-debug" + MESON_OPTS="--buildtype=debug" + + if [[ "${COVERAGE}" == true ]]; then + MESON_OPTS="${MESON_OPTS} -Db_coverage=true" + echo -e "${BLUE}Building debug with coverage enabled${NC}" + else + echo -e "${BLUE}Building debug version${NC}" + fi +else + BUILDDIR="builddir" + MESON_OPTS="--buildtype=release" + + if [[ "${COVERAGE}" == true ]]; then + echo -e "${YELLOW}Warning: Coverage is only supported for debug builds, ignoring --coverage${NC}" + fi + + if [[ "${RUN_TESTS}" == true ]]; then + echo -e "${YELLOW}Warning: Tests are not built for release builds (use debug build for testing)${NC}" + RUN_TESTS=false + fi + + echo -e "${BLUE}Building release version (tests disabled)${NC}" +fi + +# Setup or reconfigure build directory +if [[ ! -d "${BUILDDIR}" ]] || [[ "${RECONFIGURE}" == true ]]; then + if [[ "${RECONFIGURE}" == true ]]; then + echo -e "${YELLOW}Reconfiguring build...${NC}" + meson setup "${BUILDDIR}" ${MESON_OPTS} --wipe --reconfigure + else + echo -e "${YELLOW}Setting up build directory...${NC}" + meson setup "${BUILDDIR}" ${MESON_OPTS} + fi +fi + +# Build +echo -e "${YELLOW}Building...${NC}" +ninja -C "${BUILDDIR}" ${JOBS} + +if [[ $? -eq 0 ]]; then + echo -e "${GREEN}Build successful!${NC}" + echo -e "Binary: ${BUILDDIR}/ptprnt" +else + echo -e "${RED}Build failed!${NC}" + exit 1 +fi + +# Run tests if requested +if [[ "${RUN_TESTS}" == true ]]; then + echo -e "${YELLOW}Running tests...${NC}" + ninja -C "${BUILDDIR}" test + + if [[ $? -eq 0 ]]; then + echo -e "${GREEN}All tests passed!${NC}" + else + echo -e "${RED}Tests failed!${NC}" + exit 1 + fi +fi + +# Show binary info +echo "" +echo -e "${BLUE}Build Information:${NC}" +echo " Build type: ${BUILD_TYPE}" +echo " Build dir: ${BUILDDIR}" +echo " Binary: $(ls -lh ${BUILDDIR}/ptprnt | awk '{print $5, $9}')" +echo "" +echo -e "${GREEN}Done!${NC}" diff --git a/scripts/generate_coverage.sh b/scripts/generate_coverage.sh index 9b4f4a7..c1fc9f6 100755 --- a/scripts/generate_coverage.sh +++ b/scripts/generate_coverage.sh @@ -1,29 +1,195 @@ #!/bin/bash +# Coverage report generator for ptprnt +# Usage: ./scripts/generate_coverage.sh [options] + +set -e + SCRIPT_PATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +PROJECT_ROOT="${SCRIPT_PATH}/.." + +# Output paths HTML_COV_PATH="coverageReport/html" XML_COV_PATH="coverageReport/xml" +TEXT_COV_PATH="coverageReport" HTML_START_FILE="index.html" -echo "Generating Coverage report for ptprnt" +# Color output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color -cd $SCRIPT_PATH/.. +# Default values - all formats enabled by default +GENERATE_HTML=false +GENERATE_XML=false +GENERATE_TEXT=false +BUILDDIR="builddir-debug" -ninja -C builddir -ninja -C builddir test +# Common gcovr options +GCOVR_OPTS="--filter src --root ." -mkdir -p ${HTML_COV_PATH} -gcovr --html --html-details --html-syntax-highlighting --filter src --output ${HTML_COV_PATH}/${HTML_START_FILE} +print_usage() { + echo "Usage: $0 [options]" + echo "" + echo "Coverage Report Generator - generates coverage reports from existing coverage data" + echo "" + echo "Prerequisites:" + echo " Build with coverage enabled first:" + echo " ./scripts/build.sh debug --coverage --test" + echo "" + echo "Format Options (if none specified, all formats are generated):" + echo " --html Generate HTML coverage report" + echo " --xml Generate XML coverage report (for CI/CD)" + echo " --text Generate text coverage report (terminal output)" + echo "" + echo "Build Options:" + echo " --builddir DIR Use custom build directory (default: builddir-debug)" + echo "" + echo "Other Options:" + echo " -h, --help Show this help message" + echo "" + echo "Examples:" + echo " $0 # Generate all formats (html, xml, text)" + echo " $0 --html # Generate only HTML report" + echo " $0 --html --text # Generate HTML and text reports" + echo " $0 --xml # Generate XML for CI/CD" + echo " $0 --builddir builddir # Use release build directory" +} -mkdir -p ${XML_COV_PATH} -gcovr --xml-pretty --filter src --output ${XML_COV_PATH}/cov.xml - -if [ $? ] -then - echo "Coverage report successful generated!" - echo "Open: file://${SCRIPT_PATH}/${HTML_COV_PATH}/${HTML_START_FILE}" -else - echo "Error generating coverage report!" +# Parse arguments +# If no format arguments provided, enable all +if [[ $# -eq 0 ]]; then + GENERATE_HTML=true + GENERATE_XML=true + GENERATE_TEXT=true fi -rm *.gcov \ No newline at end of file +while [[ $# -gt 0 ]]; do + case $1 in + --html) + GENERATE_HTML=true + shift + ;; + --xml) + GENERATE_XML=true + shift + ;; + --text) + GENERATE_TEXT=true + shift + ;; + --builddir) + BUILDDIR="$2" + shift 2 + ;; + -h|--help) + print_usage + exit 0 + ;; + *) + echo -e "${RED}Error: Unknown option: $1${NC}" + print_usage + exit 1 + ;; + esac +done + +# Check if any format was selected when arguments were provided +if [[ $GENERATE_HTML == false && $GENERATE_XML == false && $GENERATE_TEXT == false ]]; then + echo -e "${RED}Error: No output format specified. Use --html, --xml, and/or --text${NC}" + print_usage + exit 1 +fi + +cd "${PROJECT_ROOT}" + +# Check if build directory exists +if [[ ! -d "${BUILDDIR}" ]]; then + echo -e "${RED}Error: Build directory '${BUILDDIR}' does not exist${NC}" + echo "" + echo "Build with coverage enabled first:" + echo " ./scripts/build.sh debug --coverage --test" + exit 1 +fi + +# Check if coverage data exists by looking for .gcda files +if ! find "${BUILDDIR}" -name "*.gcda" -print -quit | grep -q .; then + echo -e "${RED}Error: No coverage data found in '${BUILDDIR}'${NC}" + echo "" + echo "Make sure you built with coverage enabled and ran the tests:" + echo " ./scripts/build.sh debug --coverage --test" + exit 1 +fi + +echo -e "${BLUE}Generating Coverage report for ptprnt${NC}" +echo "Build directory: ${BUILDDIR}" +echo "Formats: $(${GENERATE_HTML} && echo -n "html ")$(${GENERATE_XML} && echo -n "xml ")$(${GENERATE_TEXT} && echo -n "text")" +echo "" + +# Check if gcovr is available +if ! command -v gcovr &> /dev/null; then + echo -e "${RED}Error: gcovr is not installed${NC}" + exit 1 +fi + +if [[ "${GENERATE_HTML}" == true ]]; then + echo -e "${YELLOW}Generating HTML coverage report...${NC}" + mkdir -p "${HTML_COV_PATH}" + gcovr ${GCOVR_OPTS} \ + --html --html-details --html-syntax-highlighting \ + --output "${HTML_COV_PATH}/${HTML_START_FILE}" + + if [[ $? -eq 0 ]]; then + echo -e "${GREEN}✓ HTML report generated${NC}" + echo "" + echo -e "${BLUE}To view HTML report, open:${NC}" + echo " file://${SCRIPT_PATH}/../${HTML_COV_PATH}/${HTML_START_FILE}" + + else + echo -e "${RED}✗ HTML report failed${NC}" + fi +fi + +if [[ "${GENERATE_XML}" == true ]]; then + echo -e "${YELLOW}Generating XML coverage report...${NC}" + mkdir -p "${XML_COV_PATH}" + gcovr ${GCOVR_OPTS} \ + --xml-pretty \ + --output "${XML_COV_PATH}/cov.xml" + + if [[ $? -eq 0 ]]; then + echo -e "${GREEN}✓ XML report generated${NC}" + echo "" + echo -e "${BLUE}To view XML report, open:${NC}" + echo " file://${SCRIPT_PATH}/../${XML_COV_PATH}/cov.xml" + else + echo -e "${RED}✗ XML report failed${NC}" + fi +fi + +if [[ "${GENERATE_TEXT}" == true ]]; then + echo -e "${YELLOW}Generating text coverage report...${NC}" + mkdir -p "${TEXT_COV_PATH}" + + # Save to file + gcovr ${GCOVR_OPTS} --output "${TEXT_COV_PATH}/coverage.txt" + + if [[ $? -eq 0 ]]; then + echo -e "${GREEN}✓ Text report generated${NC}" + echo "" + echo -e "${BLUE}To view TXT report, open:${NC}" + echo "file://${SCRIPT_PATH}/../${TEXT_COV_PATH}/coverage.txt" + else + echo -e "${RED}✗ Text report failed${NC}" + fi +fi + +# Clean up gcov files +rm -f *.gcov 2>/dev/null + +# Summary +echo "" +echo -e "${GREEN}Coverage reports generated successfully!${NC}" +echo "" diff --git a/src/PtouchPrint.cpp b/src/PtouchPrint.cpp index f52ae59..24aae23 100644 --- a/src/PtouchPrint.cpp +++ b/src/PtouchPrint.cpp @@ -18,7 +18,8 @@ */ #include "PtouchPrint.hpp" -#include +#include +#include #include #include #include @@ -104,11 +105,11 @@ bool PtouchPrint::handleListDrivers() { auto driverFactory = std::make_unique(); auto drivers = driverFactory->listAllDrivers(); - fmt::print("Available printer drivers:\n"); + std::cout << "Available printer drivers:\n"; for (const auto& driver : drivers) { - fmt::print(" - {}\n", driver); + std::cout << std::format(" - {}\n", driver); } - fmt::print("\nUse with: -p or --printer \n"); + std::cout << "\nUse with: -p or --printer \n"; return true; } diff --git a/src/cli/CliParser.cpp b/src/cli/CliParser.cpp index b4c7342..3885539 100644 --- a/src/cli/CliParser.cpp +++ b/src/cli/CliParser.cpp @@ -19,7 +19,8 @@ #include "CliParser.hpp" -#include +#include +#include namespace ptprnt::cli { @@ -92,7 +93,7 @@ void CliParser::reorderCommandsByArgv(int argc, char** argv) { void CliParser::setupParser() { // Version callback auto printVersion = [this](std::size_t) { - fmt::print("ptprnt version: {}\n", mVersionString); + std::cout << std::format("ptprnt version: {}\n", mVersionString); throw CLI::CallForVersion(); }; diff --git a/src/graphics/Label.cpp b/src/graphics/Label.cpp index 3f68d58..5721eec 100644 --- a/src/graphics/Label.cpp +++ b/src/graphics/Label.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -274,7 +275,7 @@ bool Label::append(const ILabel& other, uint32_t spacingPx) { int newStride = mCairoWrapper->cairo_image_surface_get_stride(newSurface.get()); // Clear the new surface (set to transparent/white) - std::memset(newData, 0x00, newStride * height); + memset(newData, 0x00, newStride * height); // Copy current label data for (int y = 0; y < height; ++y) { diff --git a/subprojects/spdlog.wrap b/subprojects/spdlog.wrap new file mode 100644 index 0000000..9f16f71 --- /dev/null +++ b/subprojects/spdlog.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = spdlog-1.15.3 +source_url = https://github.com/gabime/spdlog/archive/refs/tags/v1.15.3.tar.gz +source_filename = spdlog-1.15.3.tar.gz +source_hash = 15a04e69c222eb6c01094b5c7ff8a249b36bb22788d72519646fb85feb267e67 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/spdlog_1.15.3-5/spdlog-1.15.3.tar.gz +patch_filename = spdlog_1.15.3-5_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/spdlog_1.15.3-5/get_patch +patch_hash = 5e0eaf0002ff589cd8dac58e1b38c297422e7a0404d7d47ff0d2e285ed18169c +wrapdb_version = 1.15.3-5 + +[provide] +dependency_names = spdlog \ No newline at end of file diff --git a/tests/meson.build b/tests/meson.build index 71e0ce7..5bffb57 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,51 +1,29 @@ -tests = [ - [ - 'bitmap_test', - 'bitmap_test_exe', - ['../src/graphics/Bitmap.cpp', 'bitmap_test/bitmap_test.cpp'], - ], - [ - 'monochrome_test', - 'monochrome_test_exe', - [ - '../src/graphics/Monochrome.cpp', - 'monochrome_test/monochrome_test.cpp', - ], - ], +# Consolidated test binary - all tests in one executable for faster linking + +test_sources = [ + # Test files + 'bitmap_test/bitmap_test.cpp', + 'monochrome_test/monochrome_test.cpp', + 'label_test/label_test.cpp', + + # Source files under test + '../src/graphics/Bitmap.cpp', + '../src/graphics/Monochrome.cpp', + '../src/graphics/Label.cpp', ] -foreach test : tests - test( - test.get(0), - executable( - test.get(1), - sources: test.get(2), - include_directories: incdir, - dependencies: [ - gtest_dep, - usb_dep, - log_dep, - pangocairo_dep, - cli11_dep, - ], - ), - ) -endforeach +test_exe = executable( + 'ptprnt_tests', + sources: test_sources, + include_directories: incdir, + dependencies: [ + gmock_dep, # GMock includes GTest + usb_dep, + log_dep, + pangocairo_dep, + cli11_dep, + ], +) -# Label test requires GMock for mocking Cairo/Pango -test( - 'label_test', - executable( - 'label_test_exe', - sources: ['../src/graphics/Label.cpp', 'label_test/label_test.cpp'], - include_directories: incdir, - dependencies: [ - gmock_dep, - gtest_dep, - usb_dep, - log_dep, - pangocairo_dep, - cli11_dep, - ], - ), -) \ No newline at end of file +# Single test that runs all test suites +test('all_tests', test_exe)