From 2a04de41acb7f61c03c7c362c55884aa4a5dc9a6 Mon Sep 17 00:00:00 2001 From: Emmanuel Valverde Ramos Date: Thu, 17 Oct 2024 18:51:11 +0200 Subject: [PATCH 1/6] Test that covers the source of a file and check the spies (#380) Co-authored-by: Chemaclass --- install.sh | 2 +- src/test_doubles.sh | 1 + tests/unit/console_results_test.sh | 1 - tests/unit/fixtures/fake_function_to_spy.sh | 5 +++ tests/unit/test_doubles_test.sh | 40 +++++++++++++++++++++ 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/unit/fixtures/fake_function_to_spy.sh diff --git a/install.sh b/install.sh index f158d959..ee328ecb 100755 --- a/install.sh +++ b/install.sh @@ -24,7 +24,7 @@ function build_and_install_beta() { exit 1 fi - git clone --depth 1 --no-tags $BASHUNIT_GIT_REPO temp_bashunit 2>/dev/null + git clone --depth 1 --no-tags "$BASHUNIT_GIT_REPO" temp_bashunit 2>/dev/null cd temp_bashunit ./build.sh >/dev/null local latest_commit=$(git rev-parse --short=7 HEAD) diff --git a/src/test_doubles.sh b/src/test_doubles.sh index c450fa16..a149e527 100644 --- a/src/test_doubles.sh +++ b/src/test_doubles.sh @@ -96,3 +96,4 @@ function assert_have_been_called_times() { state::add_assertions_passed } + diff --git a/tests/unit/console_results_test.sh b/tests/unit/console_results_test.sh index d1f99fe2..1cb6e5a5 100644 --- a/tests/unit/console_results_test.sh +++ b/tests/unit/console_results_test.sh @@ -297,7 +297,6 @@ function test_render_execution_time_on_osx_without_perl() { mock dependencies::has_perl mock_false _START_TIME=1727771758.0664479733 - EPOCHREALTIME=1727780556.4266040325 local render_result render_result=$( diff --git a/tests/unit/fixtures/fake_function_to_spy.sh b/tests/unit/fixtures/fake_function_to_spy.sh new file mode 100644 index 00000000..1c630364 --- /dev/null +++ b/tests/unit/fixtures/fake_function_to_spy.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +function function_to_be_spied_on(){ + echo "this function should be spy and not execute" +} diff --git a/tests/unit/test_doubles_test.sh b/tests/unit/test_doubles_test.sh index 9c9e489a..6e6748d3 100644 --- a/tests/unit/test_doubles_test.sh +++ b/tests/unit/test_doubles_test.sh @@ -65,3 +65,43 @@ function test_unsuccessful_spy_called_times() { "$(console_results::print_failed_test "Unsuccessful spy called times" "ps" "to has been called" "1 times")"\ "$(assert_have_been_called_times 1 ps)" } + +function test_successful_spy_with_source_function() { + # shellcheck source=/dev/null + source ./fixtures/fake_function_to_spy.sh + spy function_to_be_spied_on + + function_to_be_spied_on + + assert_have_been_called function_to_be_spied_on +} + +function test_unsuccessful_spy_with_source_function_have_been_called() { + # shellcheck source=/dev/null + source ./fixtures/fake_function_to_spy.sh + spy function_to_be_spied_on + + function_to_be_spied_on + function_to_be_spied_on + + assert_same\ + "$(console_results::print_failed_test \ + "Unsuccessful spy with source function have been called"\ + "function_to_be_spied_on" \ + "to has been called" \ + "1 times")"\ + "$(assert_have_been_called_times 1 function_to_be_spied_on)" +} + + +function test_successful_spy_called_times_with_source() { + # shellcheck source=/dev/null + source ./fixtures/fake_function_to_spy.sh + spy function_to_be_spied_on + + function_to_be_spied_on + function_to_be_spied_on + + assert_have_been_called_times 2 function_to_be_spied_on +} + From 90550ce66ae55b69cfd404d270998f2c0beabf15 Mon Sep 17 00:00:00 2001 From: Emmanuel Valverde Ramos Date: Thu, 17 Oct 2024 16:14:40 +0200 Subject: [PATCH 2/6] chore: add test that covers the source of a file and check that the spies work --- src/test_doubles.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test_doubles.sh b/src/test_doubles.sh index a149e527..c450fa16 100644 --- a/src/test_doubles.sh +++ b/src/test_doubles.sh @@ -96,4 +96,3 @@ function assert_have_been_called_times() { state::add_assertions_passed } - From 1a6d91586551be225100d8cc30e1723cde663bfd Mon Sep 17 00:00:00 2001 From: Emmanuel Valverde Ramos Date: Thu, 17 Oct 2024 18:21:10 +0200 Subject: [PATCH 3/6] style: fix editorconfig lenght --- tmp/temp.sh | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 tmp/temp.sh diff --git a/tmp/temp.sh b/tmp/temp.sh new file mode 100644 index 00000000..4f40f4e6 --- /dev/null +++ b/tmp/temp.sh @@ -0,0 +1,262 @@ +#!/bin/bash +# check_os.sh + +# shellcheck disable=SC2034 +_OS="Unknown" +_DISTRO="Unknown" + +function check_os::init() { + if check_os::is_linux; then + _OS="Linux" + if check_os::is_ubuntu; then + _DISTRO="Ubuntu" + elif check_os::is_alpine; then + _DISTRO="Alpine" + else + _DISTRO="Other" + fi + elif check_os::is_macos; then + _OS="OSX" + elif check_os::is_windows; then + _OS="Windows" + else + _OS="Unknown" + _DISTRO="Unknown" + fi +} + +function check_os::is_ubuntu() { + command -v apt > /dev/null +} + +function check_os::is_alpine() { + command -v apk > /dev/null +} + +function check_os::is_linux() { + [[ "$(uname)" == "Linux" ]] +} + +function check_os::is_macos() { + [[ "$(uname)" == "Darwin" ]] +} + +function check_os::is_windows() { + [[ "$(uname)" == *"MINGW"* ]] +} + +function check_os::is_busybox() { + + case "$_DISTRO" in + + "Alpine") + return 0 + ;; + *) + return 1 + ;; + esac +} + +check_os::init + +export _OS +export _DISTRO +export -f check_os::is_alpine +export -f check_os::is_busybox +export -f check_os::is_ubuntu + +# str.sh + +function str::rpad() { + local left_text="$1" + local right_word="$2" + local width_padding="${3:-$TERMINAL_WIDTH}" + # Subtract 1 more to account for the extra space + local padding=$((width_padding - ${#right_word} - 1)) + + # Remove ANSI escape sequences (non-visible characters) for length calculation + # shellcheck disable=SC2155 + local clean_left_text=$(echo -e "$left_text" | sed 's/\x1b\[[0-9;]*m//g') + + local is_truncated=false + # If the visible left text exceeds the padding, truncate it and add "..." + if [[ ${#clean_left_text} -gt $padding ]]; then + local truncation_length=$((padding - 3)) # Subtract 3 for "..." + clean_left_text="${clean_left_text:0:$truncation_length}" + is_truncated=true + fi + + # Rebuild the text with ANSI codes intact, preserving the truncation + local result_left_text="" + local i=0 + local j=0 + while [[ $i -lt ${#clean_left_text} && $j -lt ${#left_text} ]]; do + local char="${clean_left_text:$i:1}" + local original_char="${left_text:$j:1}" + + # If the current character is part of an ANSI sequence, skip it and copy it + if [[ "$original_char" == $'\x1b' ]]; then + while [[ "${left_text:$j:1}" != "m" && $j -lt ${#left_text} ]]; do + result_left_text+="${left_text:$j:1}" + ((j++)) + done + result_left_text+="${left_text:$j:1}" # Append the final 'm' + ((j++)) + elif [[ "$char" == "$original_char" ]]; then + # Match the actual character + result_left_text+="$char" + ((i++)) + ((j++)) + else + ((j++)) + fi + done + + local remaining_space + if $is_truncated ; then + result_left_text+="..." + # 1: due to a blank space + # 3: due to the appended ... + remaining_space=$((width_padding - ${#clean_left_text} - ${#right_word} - 1 - 3)) + else + # Copy any remaining characters after the truncation point + result_left_text+="${left_text:$j}" + remaining_space=$((width_padding - ${#clean_left_text} - ${#right_word} - 1)) + fi + + # Ensure the right word is placed exactly at the far right of the screen + # filling the remaining space with padding + if [[ $remaining_space -lt 0 ]]; then + remaining_space=0 + fi + + printf "%s%${remaining_space}s %s\n" "$result_left_text" "" "$right_word" +} + +# globals.sh +set -euo pipefail + +# This file provides a set of global functions to developers. + +function current_dir() { + dirname "${BASH_SOURCE[1]}" +} + +function current_filename() { + basename "${BASH_SOURCE[1]}" +} + +function caller_filename() { + dirname "${BASH_SOURCE[2]}" +} + +function caller_line() { + echo "${BASH_LINENO[1]}" +} + +function current_timestamp() { + date +"%Y-%m-%d %H:%M:%S" +} + +function is_command_available() { + command -v "$1" >/dev/null 2>&1 +} + +function random_str() { + local length=${1:-6} + local chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' + local str='' + for (( i=0; i> "$BASHUNIT_DEV_LOG" +} + +# dependencies.sh +set -euo pipefail + +function dependencies::has_perl() { + command -v perl >/dev/null 2>&1 +} + +function dependencies::has_powershell() { + command -v powershell > /dev/null 2>&1 +} + +function dependencies::has_adjtimex() { + command -v adjtimex >/dev/null 2>&1 +} + +function dependencies::has_bc() { + command -v bc >/dev/null 2>&1 +} + +function dependencies::has_awk() { + command -v awk >/dev/null 2>&1 +} + +function dependencies::has_git() { + command -v git >/dev/null 2>&1 +} + +function dependencies::has_curl() { + command -v curl >/dev/null 2>&1 +} + +function dependencies::has_wget() { + command -v wget >/dev/null 2>&1 +} + +# io.sh + +function io::download_to() { + local url="$1" + local output="$2" + if dependencies::has_curl; then + curl -L -J -o "$output" "$url" 2>/dev/null + elif dependencies::has_wget; then + wget -q -O "$output" "$url" 2>/dev/null + else + return 1 + fi +} + +# math.sh From ef61f1f40591829a99cd4d3704f58384cd6616f4 Mon Sep 17 00:00:00 2001 From: Emmanuel Valverde Ramos Date: Thu, 17 Oct 2024 18:53:33 +0200 Subject: [PATCH 4/6] chore: add test of spies failing to fix on main --- tests/functional/doubles_test.sh | 49 +++++++++++++++++++ tests/functional/fixtures/doubles_function.sh | 5 ++ tests/functional/fixtures/doubles_ps_output | 8 +++ tests/functional/fixtures/doubles_script.sh | 3 ++ ...t_mock_ps_when_executing_a_script.snapshot | 3 ++ ...when_executing_a_sourced_function.snapshot | 3 ++ 6 files changed, 71 insertions(+) create mode 100644 tests/functional/doubles_test.sh create mode 100644 tests/functional/fixtures/doubles_function.sh create mode 100644 tests/functional/fixtures/doubles_ps_output create mode 100644 tests/functional/fixtures/doubles_script.sh create mode 100644 tests/functional/snapshots/doubles_test_sh_.test_mock_ps_when_executing_a_script.snapshot create mode 100644 tests/functional/snapshots/doubles_test_sh_.test_mock_ps_when_executing_a_sourced_function.snapshot diff --git a/tests/functional/doubles_test.sh b/tests/functional/doubles_test.sh new file mode 100644 index 00000000..82780983 --- /dev/null +++ b/tests/functional/doubles_test.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +function test_mock_ps_when_executing_a_script() { + skip "The mock is not been able to cat the output of the cat" + return + mock ps cat ./tests/functional/fixtures/doubles_ps_output + + assert_match_snapshot "$(./tests/functional/fixtures/doubles_script.sh)" +} + +function test_mock_ps_when_executing_a_sourced_function() { + skip "The mock is not been able to cat the output of the cat" + return + source ./tests/functional/fixtures/doubles_function.sh + mock ps cat ./tests/functional/fixtures/doubles_ps_output + + assert_match_snapshot "$(top_mem)" +} + +function test_spy_commands_called_once_when_executing_a_script() { + skip "not working while executing commands outside a function" + return + + spy ps + spy awk + spy head + + ./tests/functional/fixtures/doubles_script.sh + + assert_have_been_called_times 1 ps + assert_have_been_called_times 1 awk + assert_have_been_called_times 1 head +} + +function test_spy_commands_called_once_when_executing_a_sourced_function() { + skip "The spies can not spy inside the scope of the function" + return + + source ./tests/functional/fixtures/doubles_function.sh + spy ps + spy awk + spy head + + top_mem + + assert_have_been_called_times 1 ps + assert_have_been_called_times 1 awk + assert_have_been_called_times 1 head +} diff --git a/tests/functional/fixtures/doubles_function.sh b/tests/functional/fixtures/doubles_function.sh new file mode 100644 index 00000000..34ced26e --- /dev/null +++ b/tests/functional/fixtures/doubles_function.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +function top_mem() { + ps -eo cmd,%mem --sort=-%mem | awk '$2 >= 1.0 {print $0}' | head -n 3 +} diff --git a/tests/functional/fixtures/doubles_ps_output b/tests/functional/fixtures/doubles_ps_output new file mode 100644 index 00000000..d2e071eb --- /dev/null +++ b/tests/functional/fixtures/doubles_ps_output @@ -0,0 +1,8 @@ +CMD %MEM +firefox 2.0 +Xorg 1.6 +jetbrains-toolbox 1.3 +vitepress 1.0 +bashunit 0.1 +bash 0.0 +ps 0.0 diff --git a/tests/functional/fixtures/doubles_script.sh b/tests/functional/fixtures/doubles_script.sh new file mode 100644 index 00000000..224ee384 --- /dev/null +++ b/tests/functional/fixtures/doubles_script.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +ps -eo cmd,%mem --sort=-%mem | awk '$2 >= 1.0 {print $0}' | head -n 3 diff --git a/tests/functional/snapshots/doubles_test_sh_.test_mock_ps_when_executing_a_script.snapshot b/tests/functional/snapshots/doubles_test_sh_.test_mock_ps_when_executing_a_script.snapshot new file mode 100644 index 00000000..77519f53 --- /dev/null +++ b/tests/functional/snapshots/doubles_test_sh_.test_mock_ps_when_executing_a_script.snapshot @@ -0,0 +1,3 @@ +firefox 2.0 +Xorg 1.6 +jetbrains-toolbox 1.3 diff --git a/tests/functional/snapshots/doubles_test_sh_.test_mock_ps_when_executing_a_sourced_function.snapshot b/tests/functional/snapshots/doubles_test_sh_.test_mock_ps_when_executing_a_sourced_function.snapshot new file mode 100644 index 00000000..77519f53 --- /dev/null +++ b/tests/functional/snapshots/doubles_test_sh_.test_mock_ps_when_executing_a_sourced_function.snapshot @@ -0,0 +1,3 @@ +firefox 2.0 +Xorg 1.6 +jetbrains-toolbox 1.3 From cb5fb1b153ad2248f29ef39acd247961c8e6b589 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Fri, 18 Oct 2024 14:46:12 +0200 Subject: [PATCH 5/6] feat: ignore tmp/ folder --- .gitignore | 1 + tmp/temp.sh | 262 ---------------------------------------------------- 2 files changed, 1 insertion(+), 262 deletions(-) delete mode 100644 tmp/temp.sh diff --git a/.gitignore b/.gitignore index f4c9adaf..bd5d5b84 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ report.html # internal local/ +tmp/ dev.log diff --git a/tmp/temp.sh b/tmp/temp.sh deleted file mode 100644 index 4f40f4e6..00000000 --- a/tmp/temp.sh +++ /dev/null @@ -1,262 +0,0 @@ -#!/bin/bash -# check_os.sh - -# shellcheck disable=SC2034 -_OS="Unknown" -_DISTRO="Unknown" - -function check_os::init() { - if check_os::is_linux; then - _OS="Linux" - if check_os::is_ubuntu; then - _DISTRO="Ubuntu" - elif check_os::is_alpine; then - _DISTRO="Alpine" - else - _DISTRO="Other" - fi - elif check_os::is_macos; then - _OS="OSX" - elif check_os::is_windows; then - _OS="Windows" - else - _OS="Unknown" - _DISTRO="Unknown" - fi -} - -function check_os::is_ubuntu() { - command -v apt > /dev/null -} - -function check_os::is_alpine() { - command -v apk > /dev/null -} - -function check_os::is_linux() { - [[ "$(uname)" == "Linux" ]] -} - -function check_os::is_macos() { - [[ "$(uname)" == "Darwin" ]] -} - -function check_os::is_windows() { - [[ "$(uname)" == *"MINGW"* ]] -} - -function check_os::is_busybox() { - - case "$_DISTRO" in - - "Alpine") - return 0 - ;; - *) - return 1 - ;; - esac -} - -check_os::init - -export _OS -export _DISTRO -export -f check_os::is_alpine -export -f check_os::is_busybox -export -f check_os::is_ubuntu - -# str.sh - -function str::rpad() { - local left_text="$1" - local right_word="$2" - local width_padding="${3:-$TERMINAL_WIDTH}" - # Subtract 1 more to account for the extra space - local padding=$((width_padding - ${#right_word} - 1)) - - # Remove ANSI escape sequences (non-visible characters) for length calculation - # shellcheck disable=SC2155 - local clean_left_text=$(echo -e "$left_text" | sed 's/\x1b\[[0-9;]*m//g') - - local is_truncated=false - # If the visible left text exceeds the padding, truncate it and add "..." - if [[ ${#clean_left_text} -gt $padding ]]; then - local truncation_length=$((padding - 3)) # Subtract 3 for "..." - clean_left_text="${clean_left_text:0:$truncation_length}" - is_truncated=true - fi - - # Rebuild the text with ANSI codes intact, preserving the truncation - local result_left_text="" - local i=0 - local j=0 - while [[ $i -lt ${#clean_left_text} && $j -lt ${#left_text} ]]; do - local char="${clean_left_text:$i:1}" - local original_char="${left_text:$j:1}" - - # If the current character is part of an ANSI sequence, skip it and copy it - if [[ "$original_char" == $'\x1b' ]]; then - while [[ "${left_text:$j:1}" != "m" && $j -lt ${#left_text} ]]; do - result_left_text+="${left_text:$j:1}" - ((j++)) - done - result_left_text+="${left_text:$j:1}" # Append the final 'm' - ((j++)) - elif [[ "$char" == "$original_char" ]]; then - # Match the actual character - result_left_text+="$char" - ((i++)) - ((j++)) - else - ((j++)) - fi - done - - local remaining_space - if $is_truncated ; then - result_left_text+="..." - # 1: due to a blank space - # 3: due to the appended ... - remaining_space=$((width_padding - ${#clean_left_text} - ${#right_word} - 1 - 3)) - else - # Copy any remaining characters after the truncation point - result_left_text+="${left_text:$j}" - remaining_space=$((width_padding - ${#clean_left_text} - ${#right_word} - 1)) - fi - - # Ensure the right word is placed exactly at the far right of the screen - # filling the remaining space with padding - if [[ $remaining_space -lt 0 ]]; then - remaining_space=0 - fi - - printf "%s%${remaining_space}s %s\n" "$result_left_text" "" "$right_word" -} - -# globals.sh -set -euo pipefail - -# This file provides a set of global functions to developers. - -function current_dir() { - dirname "${BASH_SOURCE[1]}" -} - -function current_filename() { - basename "${BASH_SOURCE[1]}" -} - -function caller_filename() { - dirname "${BASH_SOURCE[2]}" -} - -function caller_line() { - echo "${BASH_LINENO[1]}" -} - -function current_timestamp() { - date +"%Y-%m-%d %H:%M:%S" -} - -function is_command_available() { - command -v "$1" >/dev/null 2>&1 -} - -function random_str() { - local length=${1:-6} - local chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' - local str='' - for (( i=0; i> "$BASHUNIT_DEV_LOG" -} - -# dependencies.sh -set -euo pipefail - -function dependencies::has_perl() { - command -v perl >/dev/null 2>&1 -} - -function dependencies::has_powershell() { - command -v powershell > /dev/null 2>&1 -} - -function dependencies::has_adjtimex() { - command -v adjtimex >/dev/null 2>&1 -} - -function dependencies::has_bc() { - command -v bc >/dev/null 2>&1 -} - -function dependencies::has_awk() { - command -v awk >/dev/null 2>&1 -} - -function dependencies::has_git() { - command -v git >/dev/null 2>&1 -} - -function dependencies::has_curl() { - command -v curl >/dev/null 2>&1 -} - -function dependencies::has_wget() { - command -v wget >/dev/null 2>&1 -} - -# io.sh - -function io::download_to() { - local url="$1" - local output="$2" - if dependencies::has_curl; then - curl -L -J -o "$output" "$url" 2>/dev/null - elif dependencies::has_wget; then - wget -q -O "$output" "$url" 2>/dev/null - else - return 1 - fi -} - -# math.sh From 0ef406d657e22d8feea3b96e0c76c2ef85630d59 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Fri, 18 Oct 2024 14:55:56 +0200 Subject: [PATCH 6/6] test: remove failing tests/functional/doubles_test.sh as they are part of https://github.com/TypedDevs/bashunit/pull/232 --- tests/functional/doubles_test.sh | 49 ------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 tests/functional/doubles_test.sh diff --git a/tests/functional/doubles_test.sh b/tests/functional/doubles_test.sh deleted file mode 100644 index 82780983..00000000 --- a/tests/functional/doubles_test.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -function test_mock_ps_when_executing_a_script() { - skip "The mock is not been able to cat the output of the cat" - return - mock ps cat ./tests/functional/fixtures/doubles_ps_output - - assert_match_snapshot "$(./tests/functional/fixtures/doubles_script.sh)" -} - -function test_mock_ps_when_executing_a_sourced_function() { - skip "The mock is not been able to cat the output of the cat" - return - source ./tests/functional/fixtures/doubles_function.sh - mock ps cat ./tests/functional/fixtures/doubles_ps_output - - assert_match_snapshot "$(top_mem)" -} - -function test_spy_commands_called_once_when_executing_a_script() { - skip "not working while executing commands outside a function" - return - - spy ps - spy awk - spy head - - ./tests/functional/fixtures/doubles_script.sh - - assert_have_been_called_times 1 ps - assert_have_been_called_times 1 awk - assert_have_been_called_times 1 head -} - -function test_spy_commands_called_once_when_executing_a_sourced_function() { - skip "The spies can not spy inside the scope of the function" - return - - source ./tests/functional/fixtures/doubles_function.sh - spy ps - spy awk - spy head - - top_mem - - assert_have_been_called_times 1 ps - assert_have_been_called_times 1 awk - assert_have_been_called_times 1 head -}