Skip to content

Commit

Permalink
Minor release 0.3.0
Browse files Browse the repository at this point in the history
Signed-off-by: Torsten Long <[email protected]>
  • Loading branch information
razziel89 committed Jan 15, 2024
1 parent 228e4da commit 7cb86c9
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 29 deletions.
22 changes: 14 additions & 8 deletions .github/workflows/test-lint-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,29 +66,35 @@ jobs:
chmod +x shfmt
sudo mv shfmt /usr/local/bin/shfmt
- name: Install prettier
- name: Install NVM
run: |
curl -sSfL -o install_nvm.sh https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh
curl -sSfL -o install_nvm.sh "${BASE_URL}/${NVM_VERSION}/install.sh"
echo "${NVMINSTALL_SHA256} install_nvm.sh" | sha256sum --check
bash install_nvm.sh
env:
NVM_VERSION: v0.39.5
NVMINSTALL_SHA256: 69da4f89f430cd5d6e591c2ccfa2e9e3ad55564ba60f651f00da85e04010c640
BASE_URL: "https://raw.githubusercontent.com/nvm-sh/nvm"

- name: Install prettier
run: |
source "${HOME}/.nvm/nvm.sh"
nvm install "${NODE_VERSION}"
dirname "$(which npm)" >> "${GITHUB_PATH}"
npm install -g prettier
dirname "$(which prettier)" >> "${GITHUB_PATH}"
env:
NODE_VERSION: "20"
NVM_VERSION: v0.39.5
NVMINSTALL_SHA256: 69da4f89f430cd5d6e591c2ccfa2e9e3ad55564ba60f651f00da85e04010c640

- name: Install mdslw
run: |
curl -sSfL -o mdslw https://github.com/razziel89/mdslw/releases/download/${MDSLW_VERSION}/mdslw_x86_64-unknown-linux-musl
curl -sSfL -o mdslw "${BASE_URL}/${MDSLW_VERSION}/mdslw_x86_64-unknown-linux-musl"
echo "${MDSLW_SHA256} mdslw" | sha256sum --check
chmod +x mdslw
sudo mv mdslw /usr/local/bin
env:
MDSLW_VERSION: 0.5.5
MDSLW_SHA256: 04d944b8e9596b82b7511c29bbf5ff10ab3ca707772d6a3164acb087a7e3f02e
MDSLW_VERSION: 0.6.1
MDSLW_SHA256: 20814371ec7c1801b995aa2e506a71ea1a3b23a4affa977ca75b02ad3dd5c562
BASE_URL: "https://github.com/razziel89/mdslw/releases/download"

- uses: actions/checkout@v3
with:
Expand Down
44 changes: 36 additions & 8 deletions bin/mock_exe.sh
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,37 @@ _match_spec() {
done < <(base64 --decode <<< "${full_spec}") && wait $!
}

# Check whether the given process is a bats process. A bats process is a bash
# process with a script located in bats's libexec directory. If we are not
# being executed by bats at all, we consider all processes to be non-bats.
_is_bats_process() {
local process="$1"
if [[ -z ${BATS_LIBEXEC-} ]]; then
# Not using bats, process cannot be a bats one.
return 1
fi

local cmd_w_args
mapfile -t -d $'\0' cmd_w_args < "/proc/${process}/cmdline"
# The first entry in cmd_w_args would be "bash" and the second one the bats
# script if our parent process were a bats process. Such a bats script is in
# bats's libexec directory.
[[ ${#cmd_w_args[@]} -ge 2 ]] \
&& [[ ${cmd_w_args[0]} == "bash" &&
${cmd_w_args[1]} == "${BATS_LIBEXEC%%/}/"* ]]
}

_kill_parent() {
local parent="$1"

if [[ ${__SHELLMOCK__KILLPARENT-} -ne 1 ]]; then
return
# Do not kill the parent process if it is a bats process. If we did, bats
# would no longer be able to track the test.
if
[[ ${__SHELLMOCK__KILLPARENT-} -ne 1 ]] || _is_bats_process "${parent}"
then
return 0
fi

errecho "Killing parent process with information:"
# In case the `ps` command fails (e.g. because we mock it), don't fail this
# mock.
Expand All @@ -156,8 +181,10 @@ _kill_parent() {
find_matching_argspec() {
# Find arg specs for this command and determine whether a specification
# matches.
local cmd_b32="${1}"
shift
local outdir="${1}"
local cmd="${2}"
local cmd_b32="${3}"
shift 3

local env_var
while read -r env_var; do
Expand All @@ -172,7 +199,7 @@ find_matching_argspec() {
| grep -x "MOCK_ARGSPEC_BASE64_${cmd_b32}_[0-9][0-9]*" | sort -u
) && wait $!

errecho "SHELLMOCK: unexpected call to '$0 $*'"
errecho "SHELLMOCK: unexpected call '${cmd} $*'"
_kill_parent "${PPID}"
return 1
}
Expand Down Expand Up @@ -203,8 +230,9 @@ main() {
env_var_check
# Determine our name. This assumes that the first value in argv is the name of
# the command. This is almost always so.
local cmd_b32
cmd_b32="$(basename "$0" | base32 -w0 | tr "=" "_")"
local cmd cmd_b32 args
cmd="$(basename "$0")"
cmd_b32="$(base32 -w0 <<< "${cmd}" | tr "=" "_")"
local outdir
outdir="$(get_and_ensure_outdir "${cmd_b32}")"
declare -g STDERR="${outdir}/stderr"
Expand All @@ -214,7 +242,7 @@ main() {
# associated information to stdout and exit with the associated exit code. If
# it cannot be found, either exit with an error or kill the parent process.
local cmd_spec
cmd_spec="$(find_matching_argspec "${cmd_b32}" "$@")"
cmd_spec="$(find_matching_argspec "${outdir}" "${cmd}" "${cmd_b32}" "$@")"
provide_output "${cmd_spec}"
return_with_code "${cmd_spec}"
}
Expand Down
41 changes: 40 additions & 1 deletion docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ There are currently the following settings:

- `checkpath`
- `killparent`
- `ensure-assertions`

<!-- shellmock-helptext-end -->

Expand All @@ -429,7 +430,7 @@ However, the tested code can still make modifications to its `PATH`, which could
cause Shellmock's mocks to not be called.
Thus, every call to the `shellmock` command will check whether the `PATH`
variable has been changed since Shellmock was loaded via `load shellmock`.
An error will be written to standard error in case such a change is detected.
A warning will be written to standard error in case such a change is detected.

The default value is 1.
Use `shellmock global-config setval checkpath 0` to disable.
Expand Down Expand Up @@ -467,6 +468,44 @@ The default value is 1.
Use `shellmock global-config setval killparent 0` to disable.
Use `shellmock global-config getval killparent` to retrieve the current setting.

#### ensure-assertions

When creating and configuring a mock using Shellmock, you have to make sure to
assert that your configured mock has been used as expected via the `shellmock
assert` command.
Otherwise, you might not detect unexpected calls to your mock, or even the fact
that your mock has not even been used!
By default, Shellmock will fail a test that creates a mock without also running
corresponding assertions.
Take the following test as an example:

```bash
@test "without asserting expectations" {
shellmock new curl
shellmock config curl 0
# Not calling the curl mock here deliberately.
}
```

Without the `ensure-assertions` feature, the above test would succeed even
though the mock for `curl` had not even been called.
With the `ensure-assertions` feature enabled, which is the default, you will
receive an error output like this (some line breaks added to make it easier to
read):

```
✗ without asserting expectations
`@test "without asserting expectations" {' failed
ERROR: expectations for mock curl have not been asserted.
Consider adding 'shellmock assert expectations curl' to
the following test: without asserting expectations
```

The default value is 1.
Use `shellmock global-config setval ensure-assertions 0` to disable.
Use `shellmock global-config getval ensure-assertions` to retrieve the current
setting.

### calls

<!-- shellmock-helptext-start -->
Expand Down
12 changes: 8 additions & 4 deletions lib/command_global_config.bash
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,24 @@
# The global-config command that can be used to get and set some global options.
__shellmock__global-config() {
__shellmock_internal_pathcheck
__shellmock_internal_trapcheck

local subcmd="$1"
local arg="$2"
local val="${3-}"

local replacement="${arg//-/_}"
replacement="${replacement^^}"

case ${subcmd} in
setval)
case ${arg} in
checkpath | killparent)
checkpath | killparent | ensure-assertions)
if [[ -z ${val-} ]]; then
echo >&2 "Value argument to setval must not be empty."
return 1
fi
local varname="__SHELLMOCK__${arg^^}"
local varname="__SHELLMOCK__${replacement}"
declare -gx "${varname}=${val}"
;;
*)
Expand All @@ -43,8 +47,8 @@ __shellmock__global-config() {
;;
getval)
case ${arg} in
checkpath | killparent)
local varname="__SHELLMOCK__${arg^^}"
checkpath | killparent | ensure-assertions)
local varname="__SHELLMOCK__${replacement}"
echo "${!varname}"
;;
*)
Expand Down
8 changes: 7 additions & 1 deletion lib/mock_management.bash
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# or they could not be mocked with executables.
__shellmock__new() {
__shellmock_internal_pathcheck
__shellmock_internal_trapcheck

local cmd="$1"

Expand Down Expand Up @@ -64,6 +65,7 @@ __shellmock_assert_no_duplicate_argspecs() {
# code, as well as the desired argspecs.
__shellmock__config() {
__shellmock_internal_pathcheck
__shellmock_internal_trapcheck

# Fake output is read from stdin.
local cmd="$1"
Expand Down Expand Up @@ -152,6 +154,7 @@ __shellmock__config() {
# Assert whether the configured mocks have been called as expected.
__shellmock__assert() {
__shellmock_internal_pathcheck
__shellmock_internal_trapcheck

local assert_type="$1"
local cmd="$2"
Expand All @@ -164,6 +167,8 @@ __shellmock__assert() {
return 1
fi

touch "${__SHELLMOCK_EXPECTATIONS_DIR}/${cmd}"

case "${assert_type}" in
# Make sure that no calls were issued to the mock that we did not expect. By
# default, the mock will kill its parent process if an unexpected call
Expand Down Expand Up @@ -201,7 +206,7 @@ __shellmock__assert() {
mapfile -t actual_argspecs < <(
if [[ -d "${__SHELLMOCK_OUTPUT}/${cmd_b32}" ]]; then
find "${__SHELLMOCK_OUTPUT}/${cmd_b32}" -mindepth 2 -type f \
-name argspec -print0 | xargs -0 cat | sort -u
-name argspec -print0 | xargs -r -0 cat | sort -u
fi
) && wait $!

Expand Down Expand Up @@ -269,6 +274,7 @@ __shellmock_jsonify_array() {

__shellmock__calls() {
__shellmock_internal_pathcheck
__shellmock_internal_trapcheck

local cmd="$1"
local format="${2-"--plain"}"
Expand Down
Loading

0 comments on commit 7cb86c9

Please sign in to comment.