diff --git a/linux/scripts/dist.sh b/linux/scripts/dist.sh index ea68b33a409..469cedbff05 100755 --- a/linux/scripts/dist.sh +++ b/linux/scripts/dist.sh @@ -39,8 +39,9 @@ dch keyman --newversion "${KEYMAN_VERSION}" --force-bad-version --nomultimaint # Create the tarball -# files and folders to include in the tarball -# shellcheck disable=2034 # to_exclude appears to be unused +# We always include these files which are the minimum files and +# folder required for Ubuntu/Debian packaging +# shellcheck disable=2034 # to_include appears to be unused to_include=( common/build.sh \ common/cpp \ @@ -60,18 +61,61 @@ to_include=( # files and subfolders to exclude from paths included in 'to_include', # i.e. the exceptions to 'to_include'. + # shellcheck disable=2034 # to_exclude appears to be unused to_exclude=( + build \ common/test/keyboards/baseline/kmcomp-*.zip \ - core/build \ - linux/build \ linux/builddebs \ linux/docs/help \ linux/keyman-config/keyman_config/version.py \ linux/keyman-config/buildtools/build-langtags.py \ - linux/keyman-system-service/build ) +if [[ -z "${create_origdist+x}" ]]; then + # If we build a full source tarball we include additional files + # so that it's possible to run `${KEYMAN_ROOT}/build.sh` on Linux + + # shellcheck disable=2034 # to_include appears to be unused + to_include+=( + common/tools/hextobin \ + common/web/keyman-version \ + common/web/langtags \ + common/web/types \ + common/windows/cpp \ + common/windows/include \ + developer/src/common/include \ + developer/src/common/web \ + developer/src/ext/json \ + developer/src/kmc \ + developer/src/kmc-analyze \ + developer/src/kmc-copy \ + developer/src/kmc-generate \ + developer/src/kmc-keyboard-info \ + developer/src/kmc-kmn \ + developer/src/kmc-ldml \ + developer/src/kmc-model \ + developer/src/kmc-model-info \ + developer/src/kmc-package \ + developer/src/kmcmplib \ + docs/minimum-versions.md.in + resources/build \ + resources/standards-data \ + ) + + # additional files and subfolders to exclude from paths included in 'to_include', + # i.e. the exceptions to 'to_include'. + # shellcheck disable=2034 # to_exclude appears to be unused + to_exclude+=( + *.exe \ + resources/build/history \ + resources/build/l10n \ + resources/build/mac \ + resources/build/win \ + resources/build/*.lua \ + ) +fi + # array to store list of --tar-ignore parameters generated from to_include and to_exclude. ignored_files=() @@ -109,7 +153,7 @@ cd "${BASEDIR}" # create orig.tar.gz if [[ ! -z "${create_origdist+x}" ]]; then - cd dist + cd "${KEYMAN_ROOT}/linux/dist" pkgvers="keyman-${KEYMAN_VERSION}" tar xfz keyman-"${KEYMAN_VERSION}".tar.gz mv -v keyman "${pkgvers}" 2>/dev/null || mv -v "$(find . -mindepth 1 -maxdepth 1 -type d)" "${pkgvers}" diff --git a/linux/scripts/package-build.inc.sh b/linux/scripts/package-build.inc.sh index f2597911deb..1a903fe3efd 100644 --- a/linux/scripts/package-build.inc.sh +++ b/linux/scripts/package-build.inc.sh @@ -91,78 +91,135 @@ function generate_tar_ignore_list() { local list_var="$4" local prefix="$5" local includes_array="${includes_var}[@]" + # shellcheck disable=SC2034 local includes=("${!includes_array}") local excludes_array="${excludes_var}[@]" local excludes=("${!excludes_array}") - local dir all_dirs found_match inc - - mapfile -t all_dirs < <(find "${directory}" -mindepth 1 -maxdepth 1 -type d | sort) - for dir in "${all_dirs[@]}"; do - found_match=false - for inc in "${includes[@]}"; do - if [[ "./${inc}" =~ ^${dir} ]]; then - found_match=true - if [[ "./${inc}" != "${dir}" ]]; then - # check subdirectories - generate_tar_ignore_list "${dir}" "${includes_var}" "${excludes_var}" "${list_var}" "${prefix}" - fi - # check if files/subdir in $dir are in excludes list - _generate_excludes_for_dir "${dir}" "${includes_var}" "${excludes_var}" "${list_var}" - break - fi - done - if ! ${found_match}; then - _add_to_list "${list_var}" "${dir}" + + # Loop through excludes and put all without path in single_excludes + local single_excludes=() + for item in "${excludes[@]}"; do + if [[ ${item} != */* ]]; then + single_excludes+=("${item}") fi done + + local ignore_list=() + _process_directory "${directory}" false + + for item in "${ignore_list[@]}"; do + eval "${list_var}+=(\"--tar-ignore=${item}\")" + done } -function _generate_excludes_for_dir() { +function _process_directory() { local directory="$1" - local includes_var="$2" - local excludes_var="$3" - local list_var="$4" - local includes_array="${includes_var}[@]" - local includes=("${!includes_array}") - local excludes_array="${excludes_var}[@]" - local excludes=("${!excludes_array}") - local file all_files excluded included is_match - - mapfile -t all_files < <(find "${directory}" -mindepth 1 -maxdepth 1 | sort) - is_match=false - for file in "${all_files[@]}"; do - for included in "${includes[@]}"; do - if [[ "${file}" == ./${included} ]]; then - is_match=true - break + local isParentIncluded="$2" + local all_items item + + mapfile -t all_items < <(find "${directory}" -mindepth 1 -maxdepth 1 | sort) + for item in "${all_items[@]}"; do + debug "Checking item: ${item}" + if _is_exact_match "includes" "${item}"; then + debug " Including (full match): ${item}" + if [[ -d "${item}" ]]; then + _process_directory "${item}" true fi - done - if ${is_match} ; then - if [[ "${file}" != ./${included} ]] && [[ -f "${file}" ]]; then - _add_to_list "${list_var}" "${file}" + elif _starts_with "includes" "${item}"; then + debug " Including (partial match): ${item}" + if [[ -d "${item}" ]]; then + _process_directory "${item}" "${isParentIncluded}" fi + elif _is_exact_match "excludes" "${item}"; then + debug " Excluding (full match): ${item}" + _add_to_list "${item}" + elif _ends_with "single_excludes" "${item}" || _is_wildcard_match "single_excludes" "${item}"; then + debug " Excluding (single exclude): ${item}" + _add_to_list "${item}" + elif [[ "${isParentIncluded}" == "false" ]]; then + debug " Excluding (not included): ${item}" + _add_to_list "${item}" else - for excluded in "${excludes[@]}"; do - if [[ "${file}" == ./${excluded} ]]; then - _add_to_list "${list_var}" "${file}" - break - elif [[ "./${excluded}" =~ ^${file} ]]; then - # check subdirectories - _generate_excludes_for_dir "${file}" "${includes_var}" "${excludes_var}" "${list_var}" - break - fi - done + debug " Including (parent included): ${item}" + if [[ -d "${item}" ]]; then + _process_directory "${item}" "${isParentIncluded}" + fi fi done } function _add_to_list() { - local list_var="$1" - local filename="$2" - - # Note: the files end up in subdirectories under `keyman` (or rather - # the directory name of $KEYMAN_ROOT), so we can - # include that when matching files and directories to ignore. - # shellcheck disable=SC2154 - eval "${list_var}+=(\"--tar-ignore=${prefix}/${filename#./}\")" + local item="$1" + ignore_list+=("${prefix}/${item#./}") +} + +# Returns true if one of the values in the $1 array equals ${file} ($2) +# Example: will return true for array=(path1/path2) file=./path1/path2 +function _is_exact_match() { + local array_var="$1" + local file="$2" + local array_name="${array_var}[@]" + local haystack=("${!array_name}") + local item + for item in "${haystack[@]}"; do + if [[ "./${item#./}" == "${file}" ]]; then + return 0 + fi + done + return 1 +} + +# Returns true if one of the values in the $1 array starts with ${file} ($2) +# Example: will return true for array=(path1/path2) file=./path1 +function _starts_with() { + local array_var="$1" + local file="$2" + local array_name="${array_var}[@]" + local array_values=("${!array_name}") + local array_item + for array_item in "${array_values[@]}"; do + if [[ "./${array_item#./}" == ${file}* ]]; then + return 0 + fi + done + return 1 +} + +# Returns true if ${file} ($2) ends with one of the values in the $1 array +# Example: will return true for array=(path2) file=./path1/path2 +function _ends_with() { + local array_var="$1" + local file="$2" + local array_name="${array_var}[@]" + local array_values=("${!array_name}") + local array_item + for array_item in "${array_values[@]}"; do + if [[ "${file}" == */${array_item#./} ]]; then + return 0 + fi + done + return 1 +} + +# Returns true if ${file} ($2) matches one of the values of the $1 array. +# These values may contain wildcards. +# Example: will return true for array=(*.sh) file=./path1/build.sh +function _is_wildcard_match() { + local array_var="$1" + local file="$2" + local array_name="${array_var}[@]" + local array_values=("${!array_name}") + local array_item + for array_item in "${array_values[@]}"; do + array_item=${array_item/./\\.} + if [[ "${file}" =~ /${array_item/\*/.\*}$ ]]; then + return 0 + fi + done + return 1 +} + +function debug() { + # echo "$@" + return 0 } diff --git a/linux/scripts/test/package-build.inc.tests.sh b/linux/scripts/test/package-build.inc.tests.sh index 145392658d5..eaad0d0650f 100755 --- a/linux/scripts/test/package-build.inc.tests.sh +++ b/linux/scripts/test/package-build.inc.tests.sh @@ -16,61 +16,105 @@ function setup_file() { # Create directory structure for testing # / # /subdir1 + # /build/foo # /build.sh # /README.md # /path1 + # /abc.build + # /build/foo # /build.sh # /README.md + # /x/z.txt + # /xy/z.txt # /path2 + # /build/foo # /build.sh # /path3 + # /build/foo # /build.sh # /subdir2 + # /build/foo # /build.sh # /path1 + # /build/foo # /subdir3 + # /build/foo # /build.sh # /path1 + # /build/foo # /path2 + # /build/foo # /path3 # /subdir4 + # /build/foo # /build.sh # /path1 # /build.sh # /path2 # /subpath1 + # /build/foo # /build.sh # /subpath2 + # /build/foo # /build.sh # /path3 # /build.sh + # /build.sh # subdir1/path2, subdir2, subdir4/path1, subdir4/path2/subpath1, # and subdir4/path3 will be ignored - mkdir -p "${temp_dir}/subdir1/path1" # include - touch "${temp_dir}/subdir1/build.sh" + # all build/ directories will be ignored with the exception of + # subdir3/build. + mkdir -p "${temp_dir}/subdir1/build" # exclude + touch "${temp_dir}/subdir1/build/foo" # exclude + mkdir -p "${temp_dir}/subdir1/path1/build" + touch "${temp_dir}/subdir1/path1/build/foo" # exclude + mkdir -p "${temp_dir}/subdir1/path1/x" + touch "${temp_dir}/subdir1/path1/x/z.txt" + mkdir -p "${temp_dir}/subdir1/path1/xy" + touch "${temp_dir}/subdir1/path1/xy/z.txt" + touch "${temp_dir}/subdir1/build.sh" # include touch "${temp_dir}/subdir1/README.md" # exclude + touch "${temp_dir}/subdir1/path1/abc.build" touch "${temp_dir}/subdir1/path1/build.sh" # include touch "${temp_dir}/subdir1/path1/README.md" # exclude - mkdir -p "${temp_dir}/subdir1/path2" # exclude - touch "${temp_dir}/subdir1/path2/build.sh" - mkdir -p "${temp_dir}/subdir1/path3" # include - touch "${temp_dir}/subdir1/path3/build.sh" - mkdir -p "${temp_dir}/subdir2/path1" # exclude + mkdir -p "${temp_dir}/subdir1/path2/build" + touch "${temp_dir}/subdir1/path2/build/foo" # exclude + touch "${temp_dir}/subdir1/path2/build.sh" # exclude + mkdir -p "${temp_dir}/subdir1/path3/build" + touch "${temp_dir}/subdir1/path2/build/foo" # exclude + touch "${temp_dir}/subdir1/path3/build.sh" # include + mkdir -p "${temp_dir}/subdir2/build" # exclude + touch "${temp_dir}/subdir2/build/foo" # exclude + mkdir -p "${temp_dir}/subdir2/path1/build" # exclude + touch "${temp_dir}/subdir2/path1/build/foo" # exclude touch "${temp_dir}/subdir2/build.sh" + mkdir -p "${temp_dir}/subdir3/build" # include + touch "${temp_dir}/subdir3/build/foo" # include mkdir -p "${temp_dir}/subdir3/path1" # include touch "${temp_dir}/subdir3/build.sh" + mkdir -p "${temp_dir}/subdir3/path1/build" # exclude + touch "${temp_dir}/subdir3/path1/build/foo" # exclude mkdir -p "${temp_dir}/subdir3/path2" # include + mkdir -p "${temp_dir}/subdir3/path2/build" # exclude + touch "${temp_dir}/subdir3/path2/build/foo" # exclude mkdir -p "${temp_dir}/subdir3/path3" # include + mkdir -p "${temp_dir}/subdir4/build" # exclude + touch "${temp_dir}/subdir4/build/foo" # exclude mkdir -p "${temp_dir}/subdir4/path1" # exclude touch "${temp_dir}/subdir4/build.sh" touch "${temp_dir}/subdir4/path1/build.sh" mkdir -p "${temp_dir}/subdir4/path2/subpath1" # exclude touch "${temp_dir}/subdir4/path2/subpath1/build.sh" + mkdir -p "${temp_dir}/subdir4/path2/subpath1/build" # exclude + touch "${temp_dir}/subdir4/path2/subpath1/build/foo" # exclude mkdir -p "${temp_dir}/subdir4/path2/subpath2" # include touch "${temp_dir}/subdir4/path2/subpath2/build.sh" + mkdir -p "${temp_dir}/subdir4/path2/subpath2/build" # exclude + touch "${temp_dir}/subdir4/path2/subpath2/build/foo" # exclude mkdir -p "${temp_dir}/subdir4/path3" # exclude touch "${temp_dir}/subdir4/path3/build.sh" touch "${temp_dir}/subdir4/path3/other.txt" + touch "${temp_dir}/build.sh" } function teardown_file() { @@ -89,9 +133,14 @@ function test__generate_tar_ignore_list__basic() { # Verify expected=( + --tar-ignore=test1/build.sh + --tar-ignore=test1/subdir1/build + --tar-ignore=test1/subdir1/build.sh --tar-ignore=test1/subdir1/path2 --tar-ignore=test1/subdir1/README.md --tar-ignore=test1/subdir2 + --tar-ignore=test1/subdir4/build + --tar-ignore=test1/subdir4/build.sh --tar-ignore=test1/subdir4/path1 --tar-ignore=test1/subdir4/path2/subpath1 --tar-ignore=test1/subdir4/path3 @@ -113,6 +162,9 @@ function test__generate_tar_ignore_list__path_wildcard_in_exclude() { # Verify expected=( + --tar-ignore=foo/build.sh # not in include + --tar-ignore=foo/subdir1/build # not in include + --tar-ignore=foo/subdir1/build.sh # not in include --tar-ignore=foo/subdir1/path1/README.md # in exclude --tar-ignore=foo/subdir1/path2 # not in include --tar-ignore=foo/subdir1/README.md # not in include @@ -136,10 +188,12 @@ function test__generate_tar_ignore_list__file_wildcard_in_exclude() { # Verify expected=( + --tar-ignore=keyman/build.sh # not in include + --tar-ignore=keyman/subdir1/build # not in include + --tar-ignore=keyman/subdir1/build.sh # not in include --tar-ignore=keyman/subdir1/path1/build.sh # in exclude --tar-ignore=keyman/subdir1/path2 # not in include --tar-ignore=keyman/subdir1/path3/build.sh # in exclude - --tar-ignore=keyman/subdir1/build.sh # not in include --tar-ignore=keyman/subdir1/README.md # not in include --tar-ignore=keyman/subdir2 # not in include --tar-ignore=keyman/subdir3/build.sh # in exclude @@ -162,13 +216,17 @@ function test__generate_tar_ignore_list__file_wildcard_in_include() { # Verify expected=( + --tar-ignore=xyz/build.sh # not in include + --tar-ignore=xyz/subdir1/build # not in include + --tar-ignore=xyz/subdir1/build.sh # not in include --tar-ignore=xyz/subdir1/path2 # not in include --tar-ignore=xyz/subdir1/README.md # in exclude --tar-ignore=xyz/subdir2 # not in include + --tar-ignore=xyz/subdir4/build # not in include + --tar-ignore=xyz/subdir4/build.sh # not in include --tar-ignore=xyz/subdir4/path1 # not in include --tar-ignore=xyz/subdir4/path2 # not in include --tar-ignore=xyz/subdir4/path3/other.txt # not in include - --tar-ignore=xyz/subdir4/path2/subpath1 # not necessary, but in exclude ) assert-equal "${ignored_files[*]}" "${expected[*]}" @@ -187,9 +245,14 @@ function test__generate_tar_ignore_list__path_wildcard_in_include() { # Verify expected=( + --tar-ignore=bar/build.sh # not in include + --tar-ignore=bar/subdir1/build # not in include + --tar-ignore=bar/subdir1/build.sh # not in include --tar-ignore=bar/subdir1/path2 # not in include --tar-ignore=bar/subdir1/README.md # not in include --tar-ignore=bar/subdir2 # not in include + --tar-ignore=bar/subdir4/build # not in include + --tar-ignore=bar/subdir4/build.sh # not in include --tar-ignore=bar/subdir4/path1 # not in include --tar-ignore=bar/subdir4/path2/subpath1 # not in include --tar-ignore=bar/subdir4/path3 # not in include @@ -210,15 +273,370 @@ function test__generate_tar_ignore_list__exclude_subsubdir() { # Verify expected=( - --tar-ignore=baz/subdir1 - --tar-ignore=baz/subdir2 - --tar-ignore=baz/subdir3 - --tar-ignore=baz/subdir4/path2/subpath2 + --tar-ignore=baz/build.sh # not in include + --tar-ignore=baz/subdir1 # not in include + --tar-ignore=baz/subdir2 # not in include + --tar-ignore=baz/subdir3 # not in include + --tar-ignore=baz/subdir4/path2/subpath2 # in exclude + ) + + assert-equal "${ignored_files[*]}" "${expected[*]}" +} + +function test__generate_tar_ignore_list__exclude_build_Dirs() { + to_include=(subdir1/path1 subdir1/path3 subdir3 subdir3/build subdir4/path2) + to_exclude=(subdir1/README.md subdir4/path2/subpath1 subdir4/path2/subpath3 build) + + cd "${temp_dir}" + ignored_files=() + + # Execute + generate_tar_ignore_list "./" to_include to_exclude ignored_files wildcard + + # Verify + expected=( + --tar-ignore=wildcard/build.sh # not in include + --tar-ignore=wildcard/subdir1/build # in exclude + --tar-ignore=wildcard/subdir1/build.sh # not in include + --tar-ignore=wildcard/subdir1/path1/build # in exclude + --tar-ignore=wildcard/subdir1/path2 # not in include + --tar-ignore=wildcard/subdir1/path3/build # in exclude + --tar-ignore=wildcard/subdir1/README.md # in exclude + --tar-ignore=wildcard/subdir2 # not in include + --tar-ignore=wildcard/subdir3/path1/build # in exclude + --tar-ignore=wildcard/subdir3/path2/build # in exclude + --tar-ignore=wildcard/subdir4/build # in exclude + --tar-ignore=wildcard/subdir4/build.sh # not in include + --tar-ignore=wildcard/subdir4/path1 # not in include + --tar-ignore=wildcard/subdir4/path2/subpath1 # in exclude + --tar-ignore=wildcard/subdir4/path2/subpath2/build # in exclude + --tar-ignore=wildcard/subdir4/path3 # not in include + ) + + assert-equal "${ignored_files[*]}" "${expected[*]}" +} + +function test__generate_tar_ignore_list__exclude_xy() { + to_include=(subdir1 subdir2 subdir3 subdir4) + to_exclude=(xy) + + cd "${temp_dir}" + ignored_files=() + + # Execute + generate_tar_ignore_list "./" to_include to_exclude ignored_files wildcard + + # Verify + expected=( + --tar-ignore=wildcard/build.sh # not in include + --tar-ignore=wildcard/subdir1/path1/xy # in exclude + ) + + assert-equal "${ignored_files[*]}" "${expected[*]}" +} + +function test__generate_tar_ignore_list__exclude_x_doesnot_exclude_xy() { + to_include=(subdir1 subdir2 subdir3 subdir4) + to_exclude=(x) + + cd "${temp_dir}" + ignored_files=() + + # Execute + generate_tar_ignore_list "./" to_include to_exclude ignored_files wildcard + + # Verify + expected=( + --tar-ignore=wildcard/build.sh # not in include + --tar-ignore=wildcard/subdir1/path1/x # in exclude ) assert-equal "${ignored_files[*]}" "${expected[*]}" } +function test__generate_tar_ignore_list__can_include_toplevel_files() { + to_include=(subdir1 subdir3 ./build.sh) + to_exclude=(*.sh) + + cd "${temp_dir}" + ignored_files=() + + # Execute + generate_tar_ignore_list "./" to_include to_exclude ignored_files top + + # Verify + expected=( + --tar-ignore=top/subdir1/build.sh # in exclude + --tar-ignore=top/subdir1/path1/build.sh # in exclude + --tar-ignore=top/subdir1/path2/build.sh # in exclude + --tar-ignore=top/subdir1/path3/build.sh # in exclude + --tar-ignore=top/subdir2 # not in include + --tar-ignore=top/subdir3/build.sh # in exclude + --tar-ignore=top/subdir4 # not in include + ) + + assert-equal "${ignored_files[*]}" "${expected[*]}" +} + +# Tests for _starts_with function +function test__starts_with__match_parent() { + # Setup + includes=(subdir1/path1 subdir3) + + # Verify + assert-true _starts_with includes ./subdir1 +} + +function test__starts_with__exact_match() { + # Setup + includes=(subdir1/path1 subdir3) + + # Verify + assert-true _starts_with includes ./subdir1/path1 +} + +function test__starts_with__exact_match_localdir() { + # Setup + includes=(./subdir1/path1 ./subdir3) + + # Verify + assert-true _starts_with includes ./subdir1/path1 +} + +function test__starts_with__no_match() { + # Setup + includes=(subdir1/path1 subdir3) + + # Verify + assert-false _starts_with includes ./subdir2 +} + +function test__starts_with__normalized_paths() { + # Setup + includes=(path1 path2) + + # Verify + assert-true _starts_with includes ./path1 +} + +function test__starts_with__subdir() { + # Setup + includes=(path1 path2) + + # Verify + assert-false _starts_with includes ./path1/subdir +} + +function test__starts_with__no_match_different_name() { + # Setup + includes=(path1 path2) + + # Verify + assert-false _starts_with includes ./path3 +} + +# Tests for _ends_with function +function test__ends_with__exact_filename_first() { + # Setup + local array=(README.md test.txt) + + # Verify + assert-true _ends_with array ./subdir/README.md +} + +function test__ends_with__exact_filename_second() { + # Setup + local array=(README.md test.txt) + + # Verify + assert-true _ends_with array ./path/to/test.txt +} + +function test__ends_with__not_matching_similar_extension() { + # Setup + local array=(README.md test.txt) + + # Verify + assert-false _ends_with array ./README.md.bak +} + +function test__ends_with__no_match_other_filename() { + # Setup + local array=(README.md test.txt) + + # Verify + assert-false _ends_with array ./other.txt +} + +# Tests for _is_exact_match function +function test__is_exact_match__full_path_first() { + # Setup + includes=(./subdir1/path1 subdir3) + + # Verify + assert-true _is_exact_match includes ./subdir1/path1 +} + +function test__is_exact_match__full_path_second() { + # Setup + includes=(./subdir1/path1 subdir3) + + # Verify + assert-true _is_exact_match includes ./subdir3 +} + +function test__is_exact_match__partial_path_no_match() { + # Setup + includes=(./subdir1/path1 subdir3) + + # Verify + assert-false _is_exact_match includes ./subdir1 +} + +function test__is_exact_match__sibling_path_no_match() { + # Setup + includes=(./subdir1/path1 subdir3) + + # Verify + assert-false _is_exact_match includes ./subdir1/path2 +} + +function test__is_exact_match__normalized_paths_first() { + # Setup + includes=(subdir1 subdir2) + + # Verify + assert-true _is_exact_match includes ./subdir1 +} + +function test__is_exact_match__normalized_paths_second() { + # Setup + includes=(subdir1 subdir2) + + # Verify + assert-true _is_exact_match includes ./subdir2 +} + +function test__is_exact_match__empty_array() { + # Setup + includes=() + + # Verify + assert-false _is_exact_match includes ./anything +} + +# Tests for _is_wildcard_match function +function test__is_wildcard_match__file() { + # Setup + local array=(sh) + + # Verify + assert-true _is_wildcard_match array ./config/sh +} + +function test__is_wildcard_match__dot_file() { + # Setup + local array=(sh) + + # Verify + assert-false _is_wildcard_match array ./config/.sh +} + +function test__is_wildcard_match__dot_files_nested() { + # Setup + local array=(.sh) + + # Verify + assert-true _is_wildcard_match array ./deeply/nested/build/.sh +} + +function test__is_wildcard_match__no_dot_prefix() { + # Setup + local array=(sh) + + # Verify + assert-false _is_wildcard_match array ./build.sh +} + +function test__is_wildcard_match__toplevel_file() { + # Setup + local array=(sh) + + # Verify + assert-true _is_wildcard_match array ./sh +} + +function test__is_wildcard_match__multiple_extensions_first() { + # Setup + local array=(tmp log) + + # Verify + assert-true _is_wildcard_match array ./path/tmp +} + +function test__is_wildcard_match__multiple_extensions_second() { + # Setup + local array=(tmp log) + + # Verify + assert-true _is_wildcard_match array ./path/log +} + +function test__is_wildcard_match__dot_in_wildcard_first() { + # Setup + local array=(.tmp .log) + + # Verify + assert-true _is_wildcard_match array ./path/.tmp +} + +function test__is_wildcard_match__dot_in_wildcard_second() { + # Setup + local array=(.tmp .log) + + # Verify + assert-true _is_wildcard_match array ./path/.log +} + +function test__is_wildcard_match__dot_in_wildcard_no_dotfile() { + # Setup + local array=(.tmp .log) + + # Verify + assert-false _is_wildcard_match array ./path/xtmp +} + +function test__is_wildcard_match__wildcard_match_dotfile() { + # Setup + local array=(\*.sh) + + # Verify + assert-true _is_wildcard_match array ./path/.sh +} + +function test__is_wildcard_match__wildcard_match_file() { + # Setup + local array=(\*.sh) + + # Verify + assert-true _is_wildcard_match array ./path/subdir/build.sh +} + +function test__is_wildcard_match__wildcard_no_matches_file() { + # Setup + local array=(\*.sh) + + # Verify + assert-false _is_wildcard_match array ./path/old +} + +function test__is_wildcard_match__wildcard_no_matches_path() { + # Setup + local array=(\*.sh) + + # Verify + assert-false _is_wildcard_match array ./path/build.sh/foo +} # shellcheck disable=2119 run_tests diff --git a/resources/build/test/testing-framework.inc.sh b/resources/build/test/testing-framework.inc.sh index 4465f57f95b..5a2449ead5e 100644 --- a/resources/build/test/testing-framework.inc.sh +++ b/resources/build/test/testing-framework.inc.sh @@ -77,6 +77,31 @@ assert-succeeded() { fi } +_callfunc() { + local command="$1" + shift + + "${command}" "$@" +} + +assert-true() { + # shellcheck disable=SC2310 + if ! _callfunc "$@"; then + messages+=("- Expected test to return true but it returned false + ") + ((test_failures++)) + fi +} + +assert-false() { + # shellcheck disable=SC2310 + if _callfunc "$@"; then + messages+=("- Expected test to return false but it returned true + ") + ((test_failures++)) + fi +} + # setup() will run before each test # can be overriden in test script setup() { diff --git a/resources/build/test/testing-framework.tests.sh b/resources/build/test/testing-framework.inc.tests.sh similarity index 74% rename from resources/build/test/testing-framework.tests.sh rename to resources/build/test/testing-framework.inc.tests.sh index 15d4597cba2..5a760a75bd6 100755 --- a/resources/build/test/testing-framework.tests.sh +++ b/resources/build/test/testing-framework.inc.tests.sh @@ -164,6 +164,74 @@ EOF assert-contains "${test_output_contents}" "PASS: test_succeeding1" } +# Helper functions for testing assert-true and assert-false +function returns_true() { + return 0 +} + +function returns_false() { + return 1 +} + +## Tests for assert-true function + +function test__assert_true__with_function_that_returns_true() { + # Execute and Verify - should pass + assert-true returns_true +} + +function test__assert_true__with_builtin_true() { + # Execute and Verify - should pass + assert-true true +} + +function test__assert_true__with_function_with_args_success() { + # Execute and Verify - file exists + assert-true test -f /etc/hostname +} + +function test__assert_true__increments_failure_on_false() { + # Setup + test_failures=0 + messages=() + + # Execute function that returns false + returns_false + local result=$? + + # Verify it failed + assert-equal "${result}" "1" +} + +## Tests for assert-false function + +function test__assert_false__with_function_that_returns_false() { + # Execute and Verify - should pass + assert-false returns_false +} + +function test__assert_false__with_builtin_false() { + # Execute and Verify - should pass + assert-false false +} + +function test__assert_false__with_function_with_args_success() { + # Execute and Verify - file does not exist + assert-false test -f /nonexistent/file/that/does/not/exist +} + +function test__assert_false__increments_failure_on_true() { + # Setup + test_failures=0 + messages=() + + # Execute function that returns true + returns_true + local result=$? + + # Verify it succeeded + assert-equal "${result}" "0" +} # shellcheck disable=SC2031 if [[ "${1:-}" != "--recursive" ]]; then