diff --git a/CONTRIBUTING b/CONTRIBUTING index 74e821e..267918b 100644 --- a/CONTRIBUTING +++ b/CONTRIBUTING @@ -99,9 +99,10 @@ their editor or terminal. For usage text and help messages, do not implement a -h option. Instead, print usage information when any erroneous option is specified. Follow the NetBSD -style guide for the usage text’s output format [1]. +style guide for the usage text’s output format [0]. -[1] +If committing a new utility, please include tests and documentation (see +tests/ and docs/) for the new tool. If committing a new source file, format the commit message following these guidelines: @@ -130,6 +131,7 @@ $ git commit -m 'tool(1): fix #42 & add feature x' Commit messages should be written in the present tense. +[0] -- This work © 2023–2024 by Emma Tebibyte is licensed under CC BY-SA 4.0. To view a copy of this license, visit diff --git a/Makefile b/Makefile index 5e2c70d..6e554a4 100644 --- a/Makefile +++ b/Makefile @@ -53,9 +53,9 @@ install: dist cp -r $(DESTDIR)/* / .PHONY: test -test: build /tmp/getopt +test: all build /tmp/getopt + tests/test.sh /tmp/getopt - tests/posix-compat.sh /tmp/getopt: src/libgetopt.rs $(RUSTC) --test -o /tmp/getopt src/libgetopt.rs diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..ee370b8 --- /dev/null +++ b/tests/README @@ -0,0 +1,60 @@ +The testing suite contains two main trees (plus translations for strings used in +the shell scripts): the Bonsai tree and the POSIX tree: + +. +├── bonsai +│   ├── test_env +│   ├── dj.sh +│   ├── false.sh +│   ├── fop.sh +│   ├── hru.sh +│   ├── intcmp.sh +│   ├── mm.sh +│   ├── strcmp.sh +│   └── true.sh +├── locales +│   ├── en_US.UTF-8 +│   └── tok +├── posix +│   ├── bin +│   │   ├── cat +│   │   ├── false +│   │   └── true +│   └── posix_env +├── README +└── test.sh + +The Bonsai tree tests the functionality of Harakit utilities for regressions and +other issues relating to compliance to our standards of practice. + +The POSIX tree tests the use of Harakit utilities in place of the standard usage +of POSIX utilities. These scripts test the ability of Harakit to comply to POSIX +standards using its native utilities in shell scripts as a compatibility shim. +Each shell script in the top directory should contain a set of tests for each +POSIX utility and be named for that utility. The bin directory should contain +a set of shim scripts which will be imported into the path as POSIX utilities. +Each test will compare the behavior of the shim script to the real utility on +the system. + +Currently, due to the limitations of POSIX shell quoting, a subset of argument +parsing is supported: arguments containing characters from POSIX’s Portable +Filename Character Set [0]. + +The bonsai/test_env and posix/posix_env files contain prerequisite shared +environments for each of the tests. These scripts both contain lines which set +the shell to write all commands run in them (-x) and to fail if any command +fails (-e). See set(1p) for more information. + +Both sets of tests also inherit the environment set by the test.sh script, which +sets the $BIN environment variable to the bin directory at the root of the +project for easy and idiomatic access to the built Harakit binaries. When +calling the POSIX test scripts, test.sh also sets the variable $realutil to be +the absolute path to the currently tested utility’s counterpart on the system. + +[0] + +-- +Copyright © 2024 Emma Tebibyte + +This work is licensed under CC BY-SA 4.0. To view a copy of this license, visit +. diff --git a/tests/bonsai/dj.sh b/tests/bonsai/dj.sh new file mode 100755 index 0000000..9919d60 --- /dev/null +++ b/tests/bonsai/dj.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# Copyright (c) 2024 DTB +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +. tests/bonsai/test_env + +! dj -h + +# Linux has a /dev/full pseudodevice useful for testing errors. +case "$(uname)" in +Linux) + dj -Hi /dev/zero -o /dev/full 2>&1 \ + | xargs -I out "$BIN"/strcmp '1+0 > 0+0; 1024 > 0' out + ;; +esac + +# Read nothing from /dev/null, write nothing to /dev/null. +dj -Hi /dev/null -o /dev/null 2>&1 \ + | xargs -I out "$BIN"/strcmp '0+0 > 0+0; 0 > 0' out + +# Test skipping stdin. +#dd count=1 bs=1024 /dev/null \ +# | dj -H -s 24 -o /dev/null 2>&1 \ +# | xargs -I out "$BIN"/strcmp '1+0 > 1+0; 1024 > 1000' out diff --git a/tests/bonsai/false.sh b/tests/bonsai/false.sh new file mode 100755 index 0000000..3ad0e94 --- /dev/null +++ b/tests/bonsai/false.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# Copyright (c) 2024 DTB +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +. tests/bonsai/test_env + +! false +! false -h diff --git a/tests/bonsai/fop.sh b/tests/bonsai/fop.sh new file mode 100755 index 0000000..2cb2533 --- /dev/null +++ b/tests/bonsai/fop.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +. tests/bonsai/test_env + +! fop -h + +"$BIN/strcmp" "$(printf 'test0␞test1␞test2\n' | fop 1 sed 's/1/4/g')" \ + 'test0␞test4␞test2' + +"$BIN/strcmp" "$(printf 'test0 test1 test2\n' | fop -d' ' 2 sed 's/2/4/g')" \ + 'test0 test1 test4' + +! printf 'test\n' | fop 1 cat +! printf 'test\n' | fop 'test' cat +! printf 'test\n' | fop -d'test' cat diff --git a/tests/bonsai/hru.sh b/tests/bonsai/hru.sh new file mode 100755 index 0000000..51bf7c1 --- /dev/null +++ b/tests/bonsai/hru.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +. tests/bonsai/test_env + +alias strcmp="$BIN/strcmp" +alias rpn="$BIN/rpn" + +strcmp "$(printf '1234\n' | hru)" '1.2 kB' +strcmp "$(printf '0\n' | hru)" '0 B' + +# doesn’t currently work but would be useful for testing for regressions +#n=1 +#while "$BIN/true"; do +# n="$(rpn "$n" 10 ×)" +# +# printf '%s\n' "$n" | hru || break +#done +#printf 'integer limit: ~%s\n' "$(rpn "$n" 10 ÷)" + +! printf '%s\n' '-1' | hru diff --git a/tests/bonsai/intcmp.sh b/tests/bonsai/intcmp.sh new file mode 100755 index 0000000..e3cdcb7 --- /dev/null +++ b/tests/bonsai/intcmp.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# Copyright (c) 2024 DTB +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +. tests/bonsai/test_env + +intcmp -e 3 3 3 +intcmp -g 3 2 1 +intcmp -l 1 2 3 +intcmp -ge 3 3 1 +intcmp -le 1 3 3 +intcmp -gl 1 2 3 +intcmp -egl 3 1 1 2 +! intcmp -e 1 2 3 +! intcmp -g 1 3 3 +! intcmp -l 3 3 1 +! intcmp -ge 1 2 3 +! intcmp -le 3 2 1 +! intcmp -gl 3 3 3 +! intcmp -egl foo diff --git a/tests/bonsai/mm.sh b/tests/bonsai/mm.sh new file mode 100755 index 0000000..43f3a1c --- /dev/null +++ b/tests/bonsai/mm.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +. tests/bonsai/test_env + +exec 3>&1 + +! mm -h + +# mm(1) will error if positional arguments are given without -i or -o +! mm argument + +# check if stderr is empty upon specifying -e +! "$BIN/strcmp" "$(printf 'test\n' | mm -i - -e 2>&1 1>&3)" '' diff --git a/tests/bonsai/npc.sh b/tests/bonsai/npc.sh new file mode 100755 index 0000000..aa66b4f --- /dev/null +++ b/tests/bonsai/npc.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# Copyright (c) 2024 DTB +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +. tests/bonsai/test_env + +! npc -h + +# arg parsing +npc -e /dev/null \ +# | xargs "$BIN"/intcmp -e 8 \ +# && i="$(printf '20 + %s\n' "$i" | bc)" +#done diff --git a/tests/bonsai/strcmp.sh b/tests/bonsai/strcmp.sh new file mode 100755 index 0000000..9d9024e --- /dev/null +++ b/tests/bonsai/strcmp.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# Copyright (c) 2024 DTB +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +. tests/bonsai/test_env + +strcmp equals equals +! strcmp inequals equals +strcmp - - +! strcmp -h +! strcmp nocmp diff --git a/tests/bonsai/test_env b/tests/bonsai/test_env new file mode 100644 index 0000000..aaf2b50 --- /dev/null +++ b/tests/bonsai/test_env @@ -0,0 +1,5 @@ +#!/bin/sh + +set -ex + +alias "$UTIL=$BIN/$UTIL" diff --git a/tests/bonsai/true.sh b/tests/bonsai/true.sh new file mode 100755 index 0000000..413d758 --- /dev/null +++ b/tests/bonsai/true.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# Copyright (c) 2024 DTB +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +. tests/bonsai/test_env + +true +true -h diff --git a/tests/locales/en_US.UTF-8 b/tests/locales/en_US.UTF-8 new file mode 100644 index 0000000..95e2efb --- /dev/null +++ b/tests/locales/en_US.UTF-8 @@ -0,0 +1,4 @@ +#!/bin/sh + +export RUN_ERR='Run this script in the root of the project' +export TEST_STR='Testing utility' diff --git a/tests/locales/tok b/tests/locales/tok new file mode 100644 index 0000000..7770742 --- /dev/null +++ b/tests/locales/tok @@ -0,0 +1,5 @@ +#!/bin/sh + +export RUN_ERR="ilo ni li ken ala pali lon ma ni. sina ken kepeken ona lon ma \ +sewi" +export TEST_STR='ilo pali' diff --git a/tests/posix-compat.sh b/tests/posix-compat.sh deleted file mode 100755 index 1e98d7b..0000000 --- a/tests/posix-compat.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2023–2024 Emma Tebibyte -# SPDX-License-Identifier: FSFAP -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice and this -# notice are preserved. This file is offered as-is, without any warranty. - -set -e - -if ! ls Makefile >/dev/null 2>&1 -then - printf '%s: Run this script in the root of the project.\n' "$0" 1>&2 - exit 1 -fi - -printf "Starting POSIX compatibility testing.\n" - -for utility in tests/posix/*; do - printf '%s: %s: Testing utility.\n' "$0" "$utility" - "$utility" - printf '\n' -done diff --git a/tests/posix/bin/cat b/tests/posix/bin/cat new file mode 100755 index 0000000..e123d7c --- /dev/null +++ b/tests/posix/bin/cat @@ -0,0 +1,22 @@ +#!/bin/sh +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +# Strictly POSIX-compliant cat(1) implementation. See cat(1p) + +for arg in "$@"; do + case "$arg" in + -u) args="$(printf '%s %s\n' "$args" "$arg")" ;; + *) args="$(printf -- '%s -i %s\n' "$args" "$arg")" ;; + esac +done + +# See IEEE Std 1003.1-2017 3.282 +# https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_282 +IFS=' ' + +mm $args diff --git a/tests/posix/bin/false b/tests/posix/bin/false new file mode 100755 index 0000000..62a10c9 --- /dev/null +++ b/tests/posix/bin/false @@ -0,0 +1,12 @@ +#!/bin/sh +# Copyright (c) 2024 DTB +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +# Strictly POSIX-compliant false(1) implementation. See false(1p) + +false "$@" diff --git a/tests/posix/bin/true b/tests/posix/bin/true new file mode 100755 index 0000000..aed1b86 --- /dev/null +++ b/tests/posix/bin/true @@ -0,0 +1,11 @@ +#!/bin/sh +# Copyright (c) 2024 DTB +# Copyright (c) 2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +# Strictly POSIX-compliant true(1) implementation. See true(1p) +true "$@" diff --git a/tests/posix/posix_env b/tests/posix/posix_env new file mode 100644 index 0000000..b436601 --- /dev/null +++ b/tests/posix/posix_env @@ -0,0 +1,5 @@ +#!/bin/sh + +set -ex + +PATH="$PWD/bin:$PATH" diff --git a/tests/test.sh b/tests/test.sh new file mode 100755 index 0000000..bc68c65 --- /dev/null +++ b/tests/test.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +# Copyright (c) 2023–2024 Emma Tebibyte +# SPDX-License-Identifier: FSFAP +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice and this +# notice are preserved. This file is offered as-is, without any warranty. + +set -e + +. "tests/locales/$LANG" + +export BIN=build/bin + +if ! ls Makefile >/dev/null 2>&1 +then + printf '%s: %s\n' "$0" "$RUN_ERR" 1>&2 + exit 1 +fi + +for script in tests/bonsai/*.sh; do + export UTIL="$(printf '%s\n' "$script" \ + | sed -e 's/\.sh//g' -e 's;tests\/bonsai\/;;g')" + + printf '%s: %s: %s\n' "$0" "$UTIL" "$TEST_STR" + "$script" + printf '\n' +done + +for test_util in tests/posix/*.sh; do + realutil="$(command -v "$(printf '%s\n' "$test" | sed 's/\.sh$//g')")" + export realutil + export PATH="$BIN:$PATH" + printf '%s: %s: %s\n' "$0" "$test" "$TEST_STR" + "$test_util" + printf '\n' +done