~aleteoryx/muditaos

74ae1a6589caaf2f822bec932476bbd4b4c12a94 — Marcin Smoczyński 4 years ago 6c32205
[EGD-7031] Remove UT deps to the production image

Remove dependency to the production image by creating separate sysroot
for test assets alongside with a test image Test.img.

Signed-off-by: Marcin Smoczyński <smoczynski.marcin@gmail.com>
48 files changed, 447 insertions(+), 285 deletions(-)

M CMakeLists.txt
A board/CMakeLists.txt
A board/linux/CMakeLists.txt
M board/linux/libiosyscalls/CMakeLists.txt
A board/linux/libiosyscalls/include/iosyscalls.h
M board/linux/libiosyscalls/include/iosyscalls.hpp
A board/linux/libiosyscalls/src/interface.cpp
A board/linux/libiosyscalls/src/iosyscalls-internal.hpp
M board/linux/libiosyscalls/src/iosyscalls.cpp
M board/linux/libiosyscalls/src/syscalls_posix.cpp
M board/linux/libiosyscalls/src/syscalls_posix_dirent.cpp
M board/linux/libiosyscalls/src/syscalls_scan_family.cpp
M board/linux/libiosyscalls/src/syscalls_stdio.cpp
M board/linux/libiosyscalls/version.txt
A board/rt1051/CMakeLists.txt
M cmake/modules/AddBootBin.cmake
A cmake/modules/Assets.cmake
M cmake/modules/DiskImage.cmake
M generate_image.sh
M image/CMakeLists.txt
M module-apps/application-calculator/tests/CMakeLists.txt
M module-db/tests/CMakeLists.txt
M module-db/tests/test-initializer/CMakeLists.txt
M module-gui/test/test-catch-text/CMakeLists.txt
M module-gui/test/test-catch/CMakeLists.txt
M module-gui/test/test-google/CMakeLists.txt
M module-platform/CMakeLists.txt
M module-platform/linux/CMakeLists.txt
M module-platform/linux/src/LinuxPlatform.cpp
M module-platform/linux/tests/CMakeLists.txt
M module-platform/linux/tests/genlfstestimg.sh
A module-platform/linux/tests/test-setup.hpp
M module-platform/linux/tests/unittest_disk_manager.cpp
M module-platform/linux/tests/unittest_filesystem_core.cpp
M module-platform/linux/tests/unittest_filesystem_dualmount.cpp
M module-platform/linux/tests/unittest_iosys.cpp
M module-services/service-db/test/CMakeLists.txt
M module-services/service-db/test/test-settings/CMakeLists.txt
M module-services/service-desktop/tests/CMakeLists.txt
M module-utils/board/CMakeLists.txt
M module-utils/i18n/tests/CMakeLists.txt
M module-utils/test/CMakeLists.txt
M module-utils/time/test/CMakeLists.txt
M module-vfs/CMakeLists.txt
M products/BellHybrid/CMakeLists.txt
M products/PurePhone/CMakeLists.txt
M test/CMakeLists.txt
A test/filesystem.cpp
M CMakeLists.txt => CMakeLists.txt +1 -3
@@ 111,9 111,7 @@ endif ()

add_subdirectory(third-party)

if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
    add_subdirectory(board/linux/libiosyscalls)
endif()
add_subdirectory(board)

add_subdirectory(source)
add_subdirectory(module-platform)

A board/CMakeLists.txt => board/CMakeLists.txt +2 -0
@@ 0,0 1,2 @@
add_library(board STATIC)
add_subdirectory(${PROJECT_TARGET_NAME})

A board/linux/CMakeLists.txt => board/linux/CMakeLists.txt +1 -0
@@ 0,0 1,1 @@
add_subdirectory(libiosyscalls)

M board/linux/libiosyscalls/CMakeLists.txt => board/linux/libiosyscalls/CMakeLists.txt +19 -11
@@ 3,16 3,6 @@ project(iosyscalls VERSION 1.0
	DESCRIPTION "linux syscalls wrapper to our VFS"
)


set(SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_stdio.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_scan_family.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_posix.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_posix_dirent.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/iosyscalls.cpp
)


set(INCLUDES
    "${CMAKE_CURRENT_SOURCE_DIR}/include"
    "${CMAKE_SOURCE_DIR}/module-os/board/linux"


@@ 22,8 12,26 @@ set(INCLUDES
    "${CMAKE_SOURCE_DIR}/module-vfs/include/internal"
)

add_library(${PROJECT_NAME} SHARED)

target_sources(
        ${PROJECT_NAME}

add_library(${PROJECT_NAME} SHARED ${SOURCES})
    PRIVATE
        src/interface.cpp
        src/iosyscalls-internal.hpp
        src/iosyscalls.cpp
        src/syscalls_posix_dirent.cpp
        src/syscalls_posix.cpp
        src/syscalls_real.hpp
        src/syscalls_scan_family.cpp
        src/syscalls_stdio.cpp

    PUBLIC
        include/debug.hpp
        include/iosyscalls.h
        include/iosyscalls.hpp
)

target_compile_options( ${PROJECT_NAME} PRIVATE "-Wno-nonnull-compare" )
get_target_property( target_options ${PROJECT_NAME} COMPILE_OPTIONS)

A board/linux/libiosyscalls/include/iosyscalls.h => board/linux/libiosyscalls/include/iosyscalls.h +7 -0
@@ 0,0 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

void iosyscalls_set_image_name(const char *newImageName);
void iosyscalls_set_sysroot(const char *newSysroot);

M board/linux/libiosyscalls/include/iosyscalls.hpp => board/linux/libiosyscalls/include/iosyscalls.hpp +3 -54
@@ 1,56 1,5 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include <stddef.h>
#include <stdio.h>
#include <purefs/vfs_subsystem.hpp>

struct __dirstream;

namespace vfsn::linux::internal
extern "C"
{
    bool redirect_to_image();
    bool is_image_handle(const FILE *fil);
    bool is_image_fd(int fd);
    bool redirect_to_image(const char *inpath);
    const char *npath_translate(const char *inpath, char *buffer);

    struct FILEX
    {
        int fd{0};
        int error{0};
        int ungetchar{-1};
    };

    int to_native_fd(int fd);
    int to_image_fd(int fd);

    FILEX *allocate_filex(int fd);
    bool is_filex(const void *fd);
    void remove_filex(FILEX *fil);

    void add_DIR_to_image_list(__dirstream *indir);
    void remove_DIR_from_image_list(__dirstream *indir);
    bool is_image_DIR(__dirstream *indir);

    template <class Base, typename T, typename... Args>
    auto invoke_fs(T Base::*lfs_fun, Args &&... args)
        -> decltype((static_cast<Base *>(nullptr)->*lfs_fun)(std::forward<Args>(args)...))
    {
        auto vfs = purefs::subsystem::vfs_core();
        if (!vfs) {
            errno = EIO;
            return -1;
        }
        auto ret = (vfs.get()->*lfs_fun)(std::forward<Args>(args)...);
        if (ret < 0) {
            errno = -ret;
            ret   = -1;
        }
        else {
            errno = 0;
        }
        return ret;
    }
} // namespace vfsn::linux::internal
#include "iosyscalls.h"
}

A board/linux/libiosyscalls/src/interface.cpp => board/linux/libiosyscalls/src/interface.cpp +19 -0
@@ 0,0 1,19 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "iosyscalls-internal.hpp"

extern "C"
{
    namespace vfs = vfsn::linux::internal;

    void iosyscalls_set_sysroot(const char *newSysroot)
    {
        vfs::set_sysroot(newSysroot);
    }

    void iosyscalls_set_image_name(const char *newImageName)
    {
        vfs::set_image_path(newImageName);
    }
}

A board/linux/libiosyscalls/src/iosyscalls-internal.hpp => board/linux/libiosyscalls/src/iosyscalls-internal.hpp +58 -0
@@ 0,0 1,58 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include <stddef.h>
#include <stdio.h>
#include <purefs/vfs_subsystem.hpp>

struct __dirstream;

namespace vfsn::linux::internal
{
    void set_image_path(const char *newImageName);
    void set_sysroot(const char *newSysroot);
    bool redirect_to_image();
    bool is_image_handle(const FILE *fil);
    bool is_image_fd(int fd);
    bool redirect_to_image(const char *inpath);
    const char *npath_translate(const char *inpath, char *buffer);

    struct FILEX
    {
        int fd{0};
        int error{0};
        int ungetchar{-1};
    };

    int to_native_fd(int fd);
    int to_image_fd(int fd);

    FILEX *allocate_filex(int fd);
    bool is_filex(const void *fd);
    void remove_filex(FILEX *fil);

    void add_DIR_to_image_list(__dirstream *indir);
    void remove_DIR_from_image_list(__dirstream *indir);
    bool is_image_DIR(__dirstream *indir);

    template <class Base, typename T, typename... Args>
    auto invoke_fs(T Base::*lfs_fun, Args &&... args)
        -> decltype((static_cast<Base *>(nullptr)->*lfs_fun)(std::forward<Args>(args)...))
    {
        auto vfs = purefs::subsystem::vfs_core();
        if (!vfs) {
            errno = EIO;
            return -1;
        }
        auto ret = (vfs.get()->*lfs_fun)(std::forward<Args>(args)...);
        if (ret < 0) {
            errno = -ret;
            ret   = -1;
        }
        else {
            errno = 0;
        }
        return ret;
    }
} // namespace vfsn::linux::internal

M board/linux/libiosyscalls/src/iosyscalls.cpp => board/linux/libiosyscalls/src/iosyscalls.cpp +65 -30
@@ 1,45 1,55 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <iosyscalls.hpp>
#include <cstdlib>
#include <cstring>
#include <pthread.h>
#include <parallel_hashmap/phmap.h>
#include <stdio.h>
#include <dlfcn.h>
#include <stdarg.h>
#include "iosyscalls-internal.hpp"

#include <debug.hpp>
#include <parallel_hashmap/phmap.h>

#include <dirent.h>
#include <dlfcn.h>
#include <pthread.h>

#include <algorithm>

#include <cassert>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>

namespace
{
    constexpr auto ENV_NAME       = "IOSYSCALLS_REDIRECT_TO_IMAGE";
    constexpr auto FIRST_FILEDESC = 64'566'756;
    constexpr auto SYSROOT        = "sysroot";
    bool g_evaluated              = false;
    bool g_redirect               = false;

    constexpr const char *LINUX_PATHS[]{"/dev/",
                                        "/etc/",
                                        "/lib",
                                        "/usr/share",
                                        "/run/user",
                                        "/home",
                                        "/proc",
                                        "PurePhone.img",
                                        "MuditaOS.log",
                                        "/tmp",
                                        nullptr};
    constexpr const char *LINUX_PATHS[]{
        "/dev/", "/etc/", "/lib", "/usr/share", "/run/user", "/home", "/proc", "/tmp", "MuditaOS.log", nullptr};

    constexpr const char *IMAGE_PATHS[]{"/sys", "/mfgconf", "assets", "country-codes.db", "Luts.bin", nullptr};
    constexpr const char *IMAGE_PATHS[]{"/sys", "/mfgconf", "sys", "assets", "country-codes.db", "Luts.bin", nullptr};

    pthread_mutex_t g_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
    phmap::flat_hash_set<vfsn::linux::internal::FILEX *> g_fdlist;
    phmap::flat_hash_set<DIR *> g_dirlist;
    std::string imageFileName;
    std::string sysroot = SYSROOT;
} // namespace

namespace vfsn::linux::internal
{
    void set_sysroot(const char *newSysroot)
    {
        sysroot = newSysroot;
    }

    void set_image_path(const char *newImageName)
    {
        imageFileName = std::string(newImageName);
    }

    bool redirect_to_image()
    {
        if (!g_evaluated) {


@@ 52,33 62,58 @@ namespace vfsn::linux::internal

    bool redirect_to_image(const char *inpath)
    {
        if (!redirect_to_image())
        if (!redirect_to_image()) {
            return false;
        }

        for (auto path = LINUX_PATHS; *path; ++path)
            if (std::strstr(inpath, *path) == inpath)
        if (std::strstr(inpath, imageFileName.c_str()) == inpath) {
            return false;
        }

        for (auto path = LINUX_PATHS; *path; ++path) {
            if (std::strstr(inpath, *path) == inpath) {
                return false;
            }
        }

        return true;
    }

    const char *npath_translate(const char *inpath, char *buffer)
    {
        for (auto path = IMAGE_PATHS; *path; ++path)
        auto inputPath = std::string(inpath);

        for (auto path = IMAGE_PATHS; *path != 0; ++path) {
            if (std::strstr(inpath, *path) == inpath) {
                if (!std::strcmp(*path, "/mfgconf")) {
                    std::strncpy(buffer, "sys/", PATH_MAX);
                    std::strncpy(buffer + 3, inpath + 8, PATH_MAX - 3);
                std::string outpath;

                if (std::strcmp(*path, "/mfgconf") == 0) {
                    outpath = sysroot;
                    outpath += "/sys/";
                    outpath += inputPath;
                }
                else if (std::strcmp(*path, "sys") == 0) {
                    outpath = sysroot;
                    outpath += "/";
                    outpath += inputPath;
                }
                else if (*inpath == '/') {
                    std::strncpy(buffer, inpath + 1, PATH_MAX);
                    outpath = sysroot + inputPath;
                }
                else {
                    std::strncpy(buffer, "sys/current/", PATH_MAX);
                    std::strncpy(buffer + 12, inpath, PATH_MAX - 12);
                    outpath = sysroot;
                    outpath += "/sys/current/";
                    outpath += inputPath;
                }

                assert(outpath.size() < PATH_MAX);
                std::copy_n(std::begin(outpath), outpath.size(), buffer);
                buffer[outpath.size()] = '\0';

                return buffer;
            }
        }

        return inpath;
    }


M board/linux/libiosyscalls/src/syscalls_posix.cpp => board/linux/libiosyscalls/src/syscalls_posix.cpp +10 -10
@@ 1,19 1,19 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <iosyscalls.hpp>
#include "iosyscalls-internal.hpp"

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/mount.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <fcntl.h>
#include <errno.h>
#include <stdarg.h> // for va_*
#include <fcntl.h>
#include <limits.h> // for PATH_MAX
#include <poll.h>
#include <stdarg.h> // for va_*
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <unistd.h>

#include "syscalls_real.hpp"


M board/linux/libiosyscalls/src/syscalls_posix_dirent.cpp => board/linux/libiosyscalls/src/syscalls_posix_dirent.cpp +1 -1
@@ 1,7 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <iosyscalls.hpp>
#include "iosyscalls-internal.hpp"

#include <dirent.h>
#include <errno.h>

M board/linux/libiosyscalls/src/syscalls_scan_family.cpp => board/linux/libiosyscalls/src/syscalls_scan_family.cpp +5 -5
@@ 1,15 1,15 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "iosyscalls-internal.hpp"

#include "debug.hpp"
#include "syscalls_real.hpp"

#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <stdarg.h>
#include <iosyscalls.hpp>

#include "syscalls_real.hpp"

#include "debug.hpp"

namespace
{

M board/linux/libiosyscalls/src/syscalls_stdio.cpp => board/linux/libiosyscalls/src/syscalls_stdio.cpp +1 -1
@@ 1,7 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <iosyscalls.hpp>
#include "iosyscalls-internal.hpp"

#include <stdio.h>
#include <fcntl.h>

M board/linux/libiosyscalls/version.txt => board/linux/libiosyscalls/version.txt +4 -0
@@ 94,3 94,7 @@ GLIBC_2.33 {
                lstat64;
                fstat64;
};
IOSYSCALLS_1.0 {
        global:
                iosyscalls_*;
};

A board/rt1051/CMakeLists.txt => board/rt1051/CMakeLists.txt +0 -0
M cmake/modules/AddBootBin.cmake => cmake/modules/AddBootBin.cmake +0 -1
@@ 35,5 35,4 @@ function(add_boot_bin SOURCE_TARGET)
    message("Adding '${SOURCE_TARGET}-boot.bin' target")
    add_custom_target(${SOURCE_TARGET}-boot.bin
        DEPENDS ${BIN_FILE})
    set_target_properties(${SOURCE_TARGET}-boot.bin PROPERTIES BIN_FILE ${BIN_FILE})
endfunction()

A cmake/modules/Assets.cmake => cmake/modules/Assets.cmake +27 -0
@@ 0,0 1,27 @@
set(ASSETS_SOURCE_DIR ${CMAKE_SOURCE_DIR}/image)

macro(add_assets_target)

    set(_ASSETS_TARGET ${ARGV0})
    set(_ASSETS_SOURCE_DIR ${ARGV1})
    set(_ASSETS_DEST_DIR ${ARGV2})

    add_custom_target(
        ${_ASSETS_TARGET}
        COMMAND mkdir -p ${_ASSETS_DEST_DIR}
        COMMAND rsync -qravu --delete
            ${_ASSETS_SOURCE_DIR}/.boot.json*
            ${_ASSETS_SOURCE_DIR}/personalization.json
            ${_ASSETS_DEST_DIR}
        COMMAND rsync -qravu --delete
            ${_ASSETS_SOURCE_DIR}/assets
            ${_ASSETS_SOURCE_DIR}/Luts.bin
            ${_ASSETS_SOURCE_DIR}/country-codes.db
            ${_ASSETS_DEST_DIR}/current
        COMMAND rsync -qravu --delete
            ${_ASSETS_SOURCE_DIR}/user
            ${_ASSETS_DEST_DIR}
        COMMENT
            "Copying assets.. (${_ASSETS_TARGET})"
    )
endmacro()

M cmake/modules/DiskImage.cmake => cmake/modules/DiskImage.cmake +45 -20
@@ 1,32 1,57 @@
function(add_image SOURCE_TARGET)
    set(DISK_IMAGE_NAME ${SOURCE_TARGET}.img)
    set(DISK_IMAGE ${CMAKE_BINARY_DIR}/${DISK_IMAGE_NAME})
    set(BIN_FILE_TARGET ${SOURCE_TARGET}-boot.bin)
    get_target_property(BIN_FILE ${BIN_FILE_TARGET} BIN_FILE)

    if (${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
        SET(TARGET_DEP ${BIN_FILE} pureflash)
function(add_image)
    cmake_parse_arguments(
        _ARG
        ""
        "PRODUCT;SYSROOT;ASSETS"
        ""
        ${ARGN}
    )

    if(NOT ${PROJECT_TARGET_NAME} STREQUAL "linux")
        set(HAS_BOOTFILE YES)
        set(RUNS_ON_HARDWARE YES)
    endif()

    set(SCRIPT_PATH ${CMAKE_SOURCE_DIR}/generate_image.sh)

    set(DISK_IMAGE_NAME ${_ARG_PRODUCT}.img)
    set(DISK_IMAGE_PATH ${CMAKE_BINARY_DIR}/${DISK_IMAGE_NAME})

    if(HAS_BOOTFILE)
        set(BIN_FILE_TARGET ${_ARG_PRODUCT}-boot.bin)
        set(BIN_FILE_PATH ${CMAKE_BINARY_DIR}/sys/current/${_ARG_PRODUCT}-boot.bin)
    else()
        SET(TARGET_DEP ${SOURCE_TARGET})
        set(BIN_FILE_PATH "")
    endif()

    set(COMMAND_DEPENDS "genlittlefs")
    list(APPEND COMMNDS_DEPENDS ${SCRIPT_PATH})
    if(_ARG_ASSETS)
        list(APPEND COMMAND_DEPENDS ${_ARG_ASSETS})
    endif()
    if(RUNS_ON_HARDWARE)
        list(APPEND COMMAND_DEPENDS pureflash)
    endif()
    if(HAS_BOOTFILE)
        list(APPEND COMMAND_DEPENDS ${BIN_FILE_TARGET})
    endif()

    add_custom_command(
        OUTPUT ${DISK_IMAGE_NAME}
        DEPENDS genlittlefs
        DEPENDS assets
        DEPENDS ${BIN_FILE_TARGET}
        DEPENDS ${TARGET_DEP}
        DEPENDS ${CMAKE_SOURCE_DIR}/generate_image.sh
        COMMAND ${CMAKE_SOURCE_DIR}/generate_image.sh
        ${DISK_IMAGE}
        ${CMAKE_BINARY_DIR}
        "$<$<STREQUAL:${PROJECT_TARGET},TARGET_RT1051>:${BIN_FILE}>"
        DEPENDS ${COMMAND_DEPENDS}
        COMMAND
            ${SCRIPT_PATH}
            ${DISK_IMAGE_NAME}
            ${CMAKE_BINARY_DIR}/${_ARG_SYSROOT}
            "${BIN_FILE_PATH}"
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        COMMENT "Generate ${DISK_IMAGE_NAME}"
        )
    )

    message("Adding disk image target: ${DISK_IMAGE_NAME}")
    add_custom_target(${SOURCE_TARGET}-disk-img

    add_custom_target(${_ARG_PRODUCT}-disk-img
        DEPENDS ${DISK_IMAGE_NAME})

endfunction()


M generate_image.sh => generate_image.sh +11 -10
@@ 5,8 5,8 @@
usage() {
cat << ==usage
Usage: $(basename $0) image_path build_dir [boot.bin_file]
    image_path    - Destination image path name e.g. PurePhone.img
    build_dir     - PurePhone build dir e.g. build-rt1051-RelWithDebInfo
    image_path    - Destination image path name e.g., PurePhone.img
    sysroot       - product's system root e.g., build-rt1051-RelWithDebInfo/sysroot
    boot.bin_file - optional for linux image - name of the boot.bin file (for different targets)
==usage
}


@@ 18,11 18,11 @@ if [[ ( $# -ne 2 ) && ( $# -ne 3 ) ]]; then
fi

IMAGE_NAME=$(realpath $1)
BUILDDIR=$(realpath $2)
SYSROOT=$(realpath $2)
BIN_FILE=$3

if [ ! -d "$BUILDDIR" ]; then
	echo "Error! \${build_dir} (${BUILDDIR}) is not a directory"
if [ ! -d "$SYSROOT" ]; then
	echo "Error! ${SYSROOT} is not a directory"
	usage
	exit -1
fi


@@ 49,7 49,7 @@ if [ ! $MTOOLS_OK ]; then
	exit -1
fi

GENLFS=$(find $BUILDDIR -type f -iname genlittlefs -executable -print -quit)
GENLFS=$(realpath $(find $BUILDDIR -type f -iname genlittlefs -executable -print -quit))
if [ -z ${GENLFS} ]; then
    echo "Error: Unable to find genlilttlefs..."
    exit -1


@@ 82,11 82,11 @@ unit: sectors
PART1="$IMAGE_NAME@@$(($PART1_START * $DEVICE_BLK_SIZE))"
mformat -i "$PART1" -F -T $PART1_SIZE -M $DEVICE_BLK_SIZE -v MUDITAOS

if [ ! -d "$BUILDDIR/sys" ]; then
if [ ! -d "${SYSROOT}/sys" ]; then
	echo "Fatal! Image folder sys/ missing in build. Check build system."
	exit -1
fi
cd "$BUILDDIR"/sys
cd "${SYSROOT}/sys"

#Copy FAT data
CURRENT_DATA="assets country-codes.db Luts.bin"


@@ 97,7 97,7 @@ mmd -i "$PART1" ::/updates

for i in $CURRENT_DATA; do
	f="current/$i"
    if [ -f "$f" -o -d "$f" ]; then
	if [ -f "$f" -o -d "$f" ]; then
		mcopy -s -i "$PART1" $f ::/current/
	else
		echo "Error! Unable to copy item: $f"


@@ 106,7 106,7 @@ for i in $CURRENT_DATA; do
done

if [[ -n "${BIN_FILE}" && -f "${BIN_FILE}" ]]; then
    mcopy -v -s -i "$PART1" ${BIN_FILE} ::/current/boot.bin
	mcopy -v -s -i "$PART1" ${BIN_FILE} ::/current/boot.bin
else
	echo "Warning! Missing boot.bin"
	echo "(it's fine for a Linux build)"


@@ 116,6 116,7 @@ mcopy -s -i "$PART1" .boot.json ::
mcopy -s -i "$PART1" .boot.json.crc32 ::

#Littlefs generate image
echo $(pwd)
$GENLFS --image=$IMAGE_NAME --block_size=32768  --overwrite  --partition_num=3 -- user/*
$GENLFS --image=$IMAGE_NAME --block_size=4096  --overwrite  --partition_num=2


M image/CMakeLists.txt => image/CMakeLists.txt +5 -20
@@ 1,25 1,10 @@
include(Utils)
include(Assets)
include(Utils)

set(ASSETS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(ASSETS_DEST_DIR "${CMAKE_BINARY_DIR}/sys")
set(SYSROOT ${CMAKE_BINARY_DIR}/sysroot)
set(ASSETS_DEST_DIR ${SYSROOT}/sys)

add_custom_target(
    assets
    COMMAND rsync -ravu --delete
        ${ASSETS_SOURCE_DIR}/.boot.json*
        ${ASSETS_SOURCE_DIR}/personalization.json
        ${ASSETS_DEST_DIR}
    COMMAND rsync -ravu --delete
        ${ASSETS_SOURCE_DIR}/assets
        ${ASSETS_SOURCE_DIR}/Luts.bin
        ${ASSETS_SOURCE_DIR}/country-codes.db
        ${ASSETS_DEST_DIR}/current
    COMMAND rsync -ravu --delete
        ${ASSETS_SOURCE_DIR}/user
        ${ASSETS_DEST_DIR}
    COMMENT
        "Copying assets.."
    )
add_assets_target(assets ${ASSETS_SOURCE_DIR} ${ASSETS_DEST_DIR})

multicomp_install(
    FILES

M module-apps/application-calculator/tests/CMakeLists.txt => module-apps/application-calculator/tests/CMakeLists.txt +2 -9
@@ 1,8 1,4 @@
if (NOT IS_SYMLINK "${CMAKE_BINARY_DIR}/sys/user")
    file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/sys/user")
endif()

add_catch2_executable(
add_catch2_executable(
    NAME
        calculator
    SRCS


@@ 11,11 7,8 @@ add_catch2_executable(
        CalculatorUtility_tests.cpp
    LIBS
        application-calculator
        iosyscalls
        module-gui
        module-sys
    DEPS
        assets
    USE_FS
)

target_include_directories(catch2-calculator PRIVATE $<TARGET_PROPERTY:application-calculator,INCLUDE_DIRECTORIES>)

M module-db/tests/CMakeLists.txt => module-db/tests/CMakeLists.txt +1 -8
@@ 1,7 1,3 @@
if (NOT IS_SYMLINK "${CMAKE_BINARY_DIR}/sys/user")
    file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/sys/user")
endif()

add_catch2_executable(
    NAME
        db


@@ 34,11 30,8 @@ add_catch2_executable(
        
    LIBS
        module-sys
        iosyscalls
        module-db
        json::json
    DEPS
        assets
        PurePhone-disk-img
    USE_FS
)
add_subdirectory(test-initializer)

M module-db/tests/test-initializer/CMakeLists.txt => module-db/tests/test-initializer/CMakeLists.txt +2 -8
@@ 1,7 1,3 @@
if (NOT IS_SYMLINK "${CMAKE_BINARY_DIR}/sys/user")
    file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/sys/user")
endif()

add_catch2_executable(
    NAME
        db-initializer


@@ 11,9 7,7 @@ add_catch2_executable(
        
    LIBS
        module-sys
        iosyscalls
        module-db
    DEPS
        assets
        PurePhone-disk-img
    
    USE_FS
)

M module-gui/test/test-catch-text/CMakeLists.txt => module-gui/test/test-catch-text/CMakeLists.txt +1 -4
@@ 21,9 21,6 @@ add_catch2_executable(
                ../mock/
        LIBS
                module-sys
                iosyscalls
                module-gui
        DEPS
                assets
                PurePhone-disk-img
	USE_FS
)

M module-gui/test/test-catch/CMakeLists.txt => module-gui/test/test-catch/CMakeLists.txt +3 -6
@@ 10,15 10,12 @@ add_catch2_executable(
                test-gui-image.cpp
                ../mock/TestWindow.cpp
                ../mock/InitializedFontManager.cpp
        test-language-input-parser.cpp
        test-key-translator.cpp
                test-language-input-parser.cpp
                test-key-translator.cpp
        INCLUDE
                ..
        LIBS
                module-sys
                iosyscalls
                module-gui
        DEPS
                assets
                PurePhone-disk-img
	USE_FS
)

M module-gui/test/test-google/CMakeLists.txt => module-gui/test/test-google/CMakeLists.txt +1 -0
@@ 12,4 12,5 @@ add_gtest_executable(
        LIBS
                module-utils
                module-gui
        USE_FS
)

M module-platform/CMakeLists.txt => module-platform/CMakeLists.txt +7 -0
@@ 16,4 16,11 @@ target_sources(
        include/Platform.hpp
)

target_link_libraries(
        platform

    PRIVATE
        module-bsp
)

add_subdirectory(${PROJECT_TARGET_NAME})

M module-platform/linux/CMakeLists.txt => module-platform/linux/CMakeLists.txt +1 -0
@@ 21,6 21,7 @@ target_include_directories(
target_link_libraries(
        platform
    PRIVATE
        iosyscalls
        module-vfs
)


M module-platform/linux/src/LinuxPlatform.cpp => module-platform/linux/src/LinuxPlatform.cpp +3 -0
@@ 6,6 6,7 @@
#include "BlockDeviceFactory.hpp"

#include <bsp/bsp.hpp>
#include <iosyscalls.hpp>
#include <purefs/vfs_subsystem.hpp>

#include <exception>


@@ 36,6 37,8 @@ void LinuxPlatform::initFilesystem()
        throw std::runtime_error("Filesystem already initialized");
    }

    iosyscalls_set_image_name(imageName.c_str());

    auto blockDeviceFactory = std::make_unique<BlockDeviceFactory>(imageName);
    vfs                     = purefs::subsystem::initialize(std::move(blockDeviceFactory));


M module-platform/linux/tests/CMakeLists.txt => module-platform/linux/tests/CMakeLists.txt +9 -8
@@ 1,3 1,5 @@

set(TEST_SYSROOT ${CMAKE_BINARY_DIR}/test-sysroot)
add_custom_target("test_disk_image")
add_custom_command(
        PRE_BUILD


@@ 12,9 14,9 @@ add_catch2_executable(
        ${CMAKE_CURRENT_LIST_DIR}/unittest_disk_manager.cpp
    LIBS
        platform
        module-vfs
    DEPS
        test_disk_image
    USE_FS
)

add_catch2_executable(


@@ 24,14 26,15 @@ add_catch2_executable(
    LIBS
        platform
        module-vfs
    USE_FS
)

set(LITTLEFS_IMAGE "lfstest.img")
add_custom_target(
    ${LITTLEFS_IMAGE}
    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/genlfstestimg.sh 1G ${LITTLEFS_IMAGE}
    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/genlfstestimg.sh 1G ${LITTLEFS_IMAGE} ${TEST_SYSROOT}
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
    DEPENDS genlittlefs assets
    DEPENDS genlittlefs test-assets
)

add_catch2_executable(


@@ 40,9 43,9 @@ add_catch2_executable(
        ${CMAKE_CURRENT_LIST_DIR}/unittest_filesystem_littlefs.cpp
    LIBS
        platform
        module-vfs
    DEPS
        ${LITTLEFS_IMAGE}
    USE_FS
)

add_catch2_executable(


@@ 51,9 54,9 @@ add_catch2_executable(
        ${CMAKE_CURRENT_LIST_DIR}/unittest_filesystem_dualmount.cpp
    LIBS
        platform
        module-vfs
    DEPS
        ${LITTLEFS_IMAGE}
    USE_FS
)

# iosyscalls tests


@@ 65,10 68,8 @@ add_catch2_executable(
    LIBS
        module-sys
        module-vfs
        iosyscalls
        platform
    DEPS
        PurePhone-disk-img
    USE_FS
)

# prepare test assets

M module-platform/linux/tests/genlfstestimg.sh => module-platform/linux/tests/genlfstestimg.sh +9 -6
@@ 4,7 4,7 @@

usage() {
cat << ==usage
Usage: $(basename $0) [image_size] [image_file] [files]...
Usage: $(basename $0) [image_size] [image_file] [sysroot] [files]...
	image_size Target disk image size
	image_file Target image name
	files Files to include in the image


@@ 19,7 19,13 @@ if [ $# -lt 2 ]; then
fi
IMAGE_SIZE="$1"
IMAGE_FILE="$2"
shift 2
SYSROOT="$3"
shift 3

if [ ! -d "${SYSROOT}/sys" ]; then
	echo "Invalid sysroot: ${SYSROOT}"
	exit -1
fi

_REQ_CMDS="sfdisk truncate"
for cmd in $_REQ_CMDS; do


@@ 33,8 39,6 @@ truncate -s $IMAGE_SIZE $IMAGE_FILE
SECTOR_START=2048
SECTOR_END=$(( $(stat -c "%s" $IMAGE_FILE)/512 - $SECTOR_START))



sfdisk $IMAGE_FILE << ==sfdisk
label: dos
unit: sectors


@@ 42,5 46,4 @@ unit: sectors
/dev/sdz1 : start=$SECTOR_START, size=$SECTOR_END, type=9e
==sfdisk
pwd
./genlittlefs --image $IMAGE_FILE --block_size=32768  --overwrite  --partition_num 1 -- sys/.boot.json sys/current/assets/* module-platform/test_dir/*

./genlittlefs --image $IMAGE_FILE --block_size=32768  --overwrite  --partition_num 1 -- ${SYSROOT}/sys/.boot.json ${SYSROOT}/sys/current/assets/* module-platform/test_dir/*

A module-platform/linux/tests/test-setup.hpp => module-platform/linux/tests/test-setup.hpp +9 -0
@@ 0,0 1,9 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

namespace testing::vfs
{
    constexpr auto disk_image = "Test.img";
}

M module-platform/linux/tests/unittest_disk_manager.cpp => module-platform/linux/tests/unittest_disk_manager.cpp +8 -5
@@ 3,12 3,15 @@
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include <purefs/blkdev/disk_manager.hpp>

#include <platform/linux/DiskImage.hpp>

#include "test-setup.hpp"

#include <filesystem>

namespace
{
    constexpr auto disk_image          = "PurePhone.img";
    constexpr auto part_disk_image     = "test_disk.img";
    constexpr auto part_disk_image_ext = "test_disk_ext.img";
    constexpr auto part_disk_image_bad = "test_disk_bad.img";


@@ 19,7 22,7 @@ TEST_CASE("Registering and unregistering device")
{
    using namespace purefs;
    blkdev::disk_manager dm;
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm.register_device(disk, "emmc0") == 0);
    REQUIRE(dm.register_device(disk, "emmc0") == -EEXIST);


@@ 93,7 96,7 @@ TEST_CASE("RW boundary checking")
{
    using namespace purefs;
    blkdev::disk_manager dm;
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm.register_device(disk, "emmc0") == 0);
    const auto parts = dm.partitions("emmc0");


@@ 112,7 115,7 @@ TEST_CASE("Alternative partitions in the disk manager")
{
    using namespace purefs;
    blkdev::disk_manager dm;
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm.register_device(disk, "emmc0") == 0);
    const auto sect_size  = dm.get_info("emmc0", blkdev::info_type::sector_size);


@@ 291,7 294,7 @@ TEST_CASE("Disk sectors out of range for partition")
{
    using namespace purefs;
    blkdev::disk_manager dm;
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm.register_device(disk, "emmc1") == 0);
    const auto parts = dm.partitions("emmc1");

M module-platform/linux/tests/unittest_filesystem_core.cpp => module-platform/linux/tests/unittest_filesystem_core.cpp +17 -16
@@ 10,21 10,22 @@
#include <purefs/blkdev/disk_manager.hpp>
#include <purefs/fs/drivers/filesystem_vfat.hpp>
#include <purefs/vfs_subsystem.hpp>

#include <purefs/fs/thread_local_cwd.hpp>

#include "test-setup.hpp"

#include <tuple>

#include <sys/statvfs.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <tuple>

namespace
{
    constexpr auto disk_image = "PurePhone.img";
}

TEST_CASE("Corefs: Registering and unregistering block device")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);


@@ 58,7 59,7 @@ TEST_CASE("Corefs: Basic API test")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);


@@ 117,7 118,7 @@ TEST_CASE("Corefs: Create new file, write, read from it")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);


@@ 162,7 163,7 @@ TEST_CASE("Corefs: Register null filesystem")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);


@@ 173,7 174,7 @@ TEST_CASE("Corefs: Mount empty strings")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);


@@ 189,7 190,7 @@ TEST_CASE("Corefs: Write to not valid file descriptor")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);


@@ 211,7 212,7 @@ TEST_CASE("Corefs: Directory operations")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);


@@ 277,7 278,7 @@ TEST_CASE("Corefs: Read only filesystem")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    purefs::fs::filesystem fscore(dm);


@@ 314,7 315,7 @@ TEST_CASE("Corefs: Remount filesystem from RO to RW and to RO")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    auto fscore         = std::make_shared<purefs::fs::filesystem>(dm);


@@ 350,7 351,7 @@ TEST_CASE("Corefs: Autodetect filesystems")
{
    using namespace purefs;
    auto dm   = std::make_shared<blkdev::disk_manager>();
    auto disk = std::make_shared<blkdev::disk_image>(disk_image);
    auto disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    REQUIRE(disk);
    REQUIRE(dm->register_device(disk, "emmc0") == 0);
    auto fscore         = std::make_shared<purefs::fs::filesystem>(dm);

M module-platform/linux/tests/unittest_filesystem_dualmount.cpp => module-platform/linux/tests/unittest_filesystem_dualmount.cpp +6 -4
@@ 10,14 10,16 @@
#include <purefs/blkdev/disk_manager.hpp>
#include <purefs/fs/drivers/filesystem_vfat.hpp>
#include <purefs/fs/drivers/filesystem_littlefs.hpp>

#include "test-setup.hpp"

#include <sys/statvfs.h>
#include <sys/stat.h>
#include <fcntl.h>

namespace
{
    constexpr auto vfat_disk_image = "PurePhone.img";
    constexpr auto lfs_disk_image  = "lfstest.img";
    constexpr auto lfs_disk_image = "lfstest.img";

    auto prepare_filesystem(std::string_view vfat_dev_name, std::string_view lfs_dev_name)
        -> std::pair<std::unique_ptr<purefs::fs::filesystem>, std::shared_ptr<purefs::blkdev::disk_manager>>


@@ 25,7 27,7 @@ namespace
        using namespace purefs;

        auto dm        = std::make_shared<blkdev::disk_manager>();
        auto vfat_disk = std::make_shared<blkdev::disk_image>(vfat_disk_image);
        auto vfat_disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
        auto lfs_disk  = std::make_shared<blkdev::disk_image>(lfs_disk_image);

        if (dm->register_device(vfat_disk, vfat_dev_name) != 0) {


@@ 55,7 57,7 @@ TEST_CASE("dualmount: Basic mount")
    using namespace purefs;

    auto dm        = std::make_shared<blkdev::disk_manager>();
    auto vfat_disk = std::make_shared<blkdev::disk_image>(vfat_disk_image);
    auto vfat_disk = std::make_shared<blkdev::disk_image>(::testing::vfs::disk_image);
    auto lfs_disk  = std::make_shared<blkdev::disk_image>(lfs_disk_image);
    REQUIRE(vfat_disk);
    REQUIRE(lfs_disk);

M module-platform/linux/tests/unittest_iosys.cpp => module-platform/linux/tests/unittest_iosys.cpp +1 -1
@@ 10,7 10,7 @@

TEST_CASE("VFS linux support")
{
    auto platform = platform::linux::LinuxPlatform("PurePhone.img");
    auto platform = platform::linux::LinuxPlatform("Test.img");

    REQUIRE_NOTHROW(platform.init());


M module-services/service-db/test/CMakeLists.txt => module-services/service-db/test/CMakeLists.txt +1 -3
@@ 6,7 6,6 @@ add_catch2_executable(
            main.cpp
            test-service-db-api.cpp
            test-service-db-settings-messages.cpp
            #test-service-db-file_indexer.cpp
            test-service-db-quotes.cpp
            test-factory-settings.cpp
        LIBS


@@ 18,8 17,7 @@ add_catch2_executable(
            module-vfs
            service-audio
            service-cellular
        DEPS
            PurePhone-disk-img
        USE_FS
)

add_catch2_executable(

M module-services/service-db/test/test-settings/CMakeLists.txt => module-services/service-db/test/test-settings/CMakeLists.txt +0 -1
@@ 13,5 13,4 @@ add_catch2_executable(
            module-cellular
        DEPS
            module-sys
            PurePhone-disk-img
)

M module-services/service-desktop/tests/CMakeLists.txt => module-services/service-desktop/tests/CMakeLists.txt +17 -10
@@ 1,5 1,16 @@
file (COPY "${CMAKE_CURRENT_LIST_DIR}/muditaos-unittest.tar" DESTINATION "${CMAKE_BINARY_DIR}/sys/updates")
file (COPY "${CMAKE_CURRENT_LIST_DIR}/factory-test" DESTINATION "${CMAKE_BINARY_DIR}/sys")
file(
    COPY
        muditaos-unittest.tar
    DESTINATION
        ${TEST_ASSETS_DEST_DIR}/updates
)

file(
    COPY
        factory-test
    DESTINATION
        ${TEST_ASSETS_DEST_DIR}
)

add_catch2_executable(
    NAME


@@ 11,9 22,7 @@ add_catch2_executable(
        service-desktop
        module-utils
        module-apps
        iosyscalls
    DEPS
        PurePhone-disk-img
    USE_FS
)

add_catch2_executable(


@@ 26,8 35,7 @@ add_catch2_executable(
        service-desktop
        module-utils
        module-apps
        module-vfs
        iosyscalls
    USE_FS
)

add_catch2_executable(


@@ 40,6 48,5 @@ add_catch2_executable(
        service-desktop
        module-utils
        module-apps
        module-vfs
        iosyscalls
)
\ No newline at end of file
    USE_FS
)

M module-utils/board/CMakeLists.txt => module-utils/board/CMakeLists.txt +0 -2
@@ 1,5 1,3 @@
add_library(board STATIC)

if(${PROJECT_TARGET} STREQUAL "TARGET_Linux")
    target_sources(board
    PRIVATE

M module-utils/i18n/tests/CMakeLists.txt => module-utils/i18n/tests/CMakeLists.txt +1 -0
@@ 5,4 5,5 @@ add_catch2_executable(
        test_i18n.cpp
    LIBS
        i18n
    USE_FS
)

M module-utils/test/CMakeLists.txt => module-utils/test/CMakeLists.txt +0 -13
@@ 26,9 26,6 @@ add_catch2_executable(
        unittest_utils.cpp
    LIBS
        module-utils
        iosyscalls
    DEPS
        PurePhone-disk-img
)

# Log tests


@@ 50,13 47,3 @@ add_catch2_executable(
    LIBS
        module-utils
)

# ParserICS tests
#add_catch2_executable(
#    NAME
#        utils-parserIcs
#    SRCS
#        test_ParserICS.cpp
#    LIBS
#        module-utils
#)

M module-utils/time/test/CMakeLists.txt => module-utils/time/test/CMakeLists.txt +1 -3
@@ 25,7 25,5 @@ add_catch2_executable(
    LIBS
        time
        utf8
        iosyscalls
    DEPS
        PurePhone-disk-img
    USE_FS
)

M module-vfs/CMakeLists.txt => module-vfs/CMakeLists.txt +1 -1
@@ 96,7 96,7 @@ target_include_directories(module-vfs
)

target_link_libraries(module-vfs 
    PRIVATE 
    PRIVATE
        fatfs::fatfs
        json::json
        littlefs::littlefs

M products/BellHybrid/CMakeLists.txt => products/BellHybrid/CMakeLists.txt +5 -3
@@ 73,15 73,17 @@ endif()

set_source_files_properties(BellHybridMain.cpp PROPERTIES COMPILE_DEFINITIONS "${ENABLED_APPS_DEFINES}")


strip_executable(BellHybrid)


add_dependencies(BellHybrid version)

include(AddBootBin)
add_boot_bin(BellHybrid)
add_image(BellHybrid)
add_image(
    PRODUCT BellHybrid
    SYSROOT sysroot
    ASSETS  assets
)

include(AddHexTarget)
add_hex_target(BellHybrid)

M products/PurePhone/CMakeLists.txt => products/PurePhone/CMakeLists.txt +5 -1
@@ 91,7 91,11 @@ add_dependencies(PurePhone version)

include(AddBootBin)
add_boot_bin(PurePhone)
add_image(PurePhone)
add_image(
    PRODUCT PurePhone
    SYSROOT sysroot
    ASSETS  assets
)

include(AddHexTarget)
add_hex_target(PurePhone)

M test/CMakeLists.txt => test/CMakeLists.txt +35 -7
@@ 12,18 12,37 @@ define_property(
    FULL_DOCS "Add directory to a test entity to group tests defined in the directory and its subdirectories"
)

include(Assets)
include(Catch)
include(CMakeParseArguments)
include(DiskImage)
include(GoogleTest)
include(Catch)

add_custom_target(unittests)

set(ROOT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
set(TEST_ASSETS_DEST_DIR ${CMAKE_BINARY_DIR}/test-sysroot/sys)
set(TEST_ASSETS_DEST_DIR ${TEST_ASSETS_DEST_DIR} PARENT_SCOPE)

add_assets_target(test-assets ${ASSETS_SOURCE_DIR} ${TEST_ASSETS_DEST_DIR})
add_image(
    PRODUCT Test
    SYSROOT test-sysroot
    ASSETS  test-assets
)

macro(enable_test_filesystem)
    target_sources(${_TESTNAME} PRIVATE ${ROOT_TEST_DIR}/filesystem.cpp)
    list(APPEND _TEST_ARGS_LIBS iosyscalls)
    list(APPEND _TEST_ARGS_LIBS board)
    list(APPEND _TEST_ARGS_INCLUDE ${CMAKE_SOURCE_DIR}/module-vfs/include/user)
    list(APPEND _TEST_ARGS_DEPS Test-disk-img)
endmacro()

function(add_gtest_executable)
    cmake_parse_arguments(
        _TEST_ARGS
        ""
        "USE_FS"
        "NAME"
        "SRCS;INCLUDE;LIBS;DEFS;DEPS"
        ${ARGN}


@@ 51,6 70,11 @@ function(add_gtest_executable)
        target_sources(${_TESTNAME} PRIVATE ${ROOT_TEST_DIR}/mock-freertos-tls.cpp)
    endif (NOT ${ENABLE_TEST_LOGS})

    set(_TEST_LABELS "")
    if(_TEST_ARGS_USE_FS)
        enable_test_filesystem()
    endif()

    target_link_libraries(${_TESTNAME} PRIVATE gtest_main gmock log)
    foreach(lib ${_TEST_ARGS_LIBS})
        target_link_libraries(${_TESTNAME} PRIVATE ${lib})


@@ 74,7 98,6 @@ function(add_gtest_executable)
    add_dependencies(unittests ${_TESTNAME})
    add_dependencies(check ${_TESTNAME})

    set(_TEST_LABELS "")
    if(_TEST_ENTITY)
        add_dependencies(unittests-${_TEST_ENTITY} ${_TESTNAME})
        list(APPEND _TEST_LABELS ${_TEST_ENTITY})


@@ 86,13 109,13 @@ function(add_gtest_executable)
        TEST_LIST _TEST_LIST
    )

    set_tests_properties(${_TEST_LIST} PROPERTIES LABELS ${_TEST_ENTITY})
    set_tests_properties(${_TEST_LIST} PROPERTIES LABELS ${_TEST_LABELS})
endfunction()

function(add_catch2_executable)
    cmake_parse_arguments(
        _TEST_ARGS
        ""
        "USE_FS"
        "NAME"
        "SRCS;INCLUDE;LIBS;DEFS;DEPS"
        ${ARGN}


@@ 120,11 143,15 @@ function(add_catch2_executable)
        target_sources(${_TESTNAME} PRIVATE ${ROOT_TEST_DIR}/mock-freertos-tls.cpp)
    endif (NOT ${ENABLE_TEST_LOGS} AND NOT ${_TESTNAME} STREQUAL "catch2-utils-log")

    set(_TEST_LABELS "")
    if(_TEST_ARGS_USE_FS)
        enable_test_filesystem()
    endif()

    target_link_libraries(${_TESTNAME} PRIVATE Catch2::Catch2 log)
    foreach(lib ${_TEST_ARGS_LIBS})
        target_link_libraries(${_TESTNAME} PRIVATE ${lib})
    endforeach(lib)

    foreach(include ${_TEST_ARGS_INCLUDE})
        target_include_directories(${_TESTNAME} PRIVATE ${include})
    endforeach(include)


@@ 142,11 169,12 @@ function(add_catch2_executable)

    if(_TEST_ENTITY)
        add_dependencies(unittests-${_TEST_ENTITY} ${_TESTNAME})
        list(APPEND _TEST_LABELS ${_TEST_ENTITY})
    endif()

    catch_discover_tests(${_TESTNAME}
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
        PROPERTIES LABELS ${_TEST_ENTITY}
        PROPERTIES LABELS ${_TEST_LABELS}
    )
endfunction()


A test/filesystem.cpp => test/filesystem.cpp +17 -0
@@ 0,0 1,17 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <iosyscalls.hpp>

auto constexpr TESTS_SYSROOT = "test-sysroot";
auto constexpr IMAGE_NAME    = "Test.img";

void __attribute__((constructor)) setup_sysroot()
{
    iosyscalls_set_sysroot(TESTS_SYSROOT);
}

void __attribute__((constructor)) setup_disk_image()
{
    iosyscalls_set_image_name(IMAGE_NAME);
}