potřeby
Problém vytváření testů při
nejasném nebo měnícím se zadání
Testování je jen tak dobré, jak dobře jsou navržené
samotné testované situace
⇒ nebezpečí falešného bezpečí/sebevědomí
Některé situace se špatně testují, např.:
bussiness/userpotřebám
V=foo cmd1 p1 p2 … | V=bar cmd2 …
(exit 1) | (exit 2) | (exit 0)getent passwd user | grep /bash$getent passwd user | grep /bash$ | cut -d: -f7echo $?
0
declare -a PIPESTATUS=([0]="1" [1]="2" [2]="0")
(exit 1) | (exit 2) | (exit 0)getent passwd user | grep /bash$getent passwd user | grep /bash$ | cut -d: -f7set -o pipefail; !! ; echo $?
2
echo $(exit 2); echo $?
0var=$(exit 2); echo $?
2
cmd >out 2>errcmd >out 2>&1 out=$( cmd )\0) !
out=$( printf '%s\n\n' a b c )declare -- out=$'a\n\nb\n\nc'
out=$( printf '%s\n\n' a b c; echo . )declare -- out=$'a\n\nb\n\nc\n\n.'out=${out%.}declare -- out=$'a\n\nb\n\nc\n\n'
printf -v out 'a\0b\n\n'declare -- out="a"
out=$( printf 'a\0b\n\n' | base64 )declare -- out="YQBiCgo="base64 -d <<<"$out" | od -c0000000 a \0 b \n \n0000005
declare -p FOO-bash: declare: FOO: not foundtest -v FOO; echo $?1
printf '%s | %q' "$IFS" "$IFS" "${IFS@Q}" | $' \t\n' | $' \t\n'
echo "${BASH_VERSINFO@a}"ar
declare -ar BASH_VERSINFO=([0]="5" [1]="3" [2]="9" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")
$#$n, ${n}
$0 — jméno skriptu$1 … $9 — parametry${10} … — parametryshift nstatcat, od, stringsfindstatstat -c "%s" /etc/issue34cat, od, stringsfindstatcat, od, stringscat -A /etc/issueDebian GNU/Linux forky/sid \n \l$$od -c /etc/issue0000000 D e b i a n G N U / L i n u x0000020 f o r k y / s i d \ n \ l0000040 \n \n0000042strings /usr/lib/x86_64-linux-gnu/libm.so/* GNU ld scriptOUTPUT_FORMAT(elf64-x86-64)GROUP ( /usr/lib/x86_64-linux-gnu/libm.so.6 AS_NEEDED ( /usr/lib/x86_64-linux-gnu/libmvec.so.1 ) )findstatcat, od, stringsfindfind cesty… predikáty…find / \ \( \ \( -path /home -o -path /run -o -path /mnt \) \ -prune \ \) -o \( \ \! -type l \ -size +0 \ -writable \ -printf '%y %m %s\t%p\n' \ \) 2>/dev/nulld 3775 4096 /usr/share/ppd/customd 1777 4096 /var/tmpd 755 4096 /var/tmp/flatpak-cache-B2V7U3d 1777 9700 /tmpf 600 49478 /tmp/.com.google.Chrome.k8zck4f 664 68 /tmp/sumf 664 15 /tmp/f2f 664 12 /tmp/f1ps, pgrep, lsofping, ss, netstat, nc, curltimeoutps, pgrep, lsofping, ss, netstat, nc, curltimeouttimeout 5 bash -c 'while sleep 1; do date +%T; done'13:15:0113:15:0213:15:0313:15:04cmd -o -O optarg arg1 arg2 arg3$0 $1 $2 $3 $4 $5 $6 $#=6
cmd -o -O optarg arg1 arg2 arg3$0 $1 $2 $3 $4 $5 $6 $#=6
set -- -o -O optarg arg1 arg2 arg3params=( -o -O optarg arg1 arg2 arg3 )cmd "${params[@]}"
cmd <filecmd <<HERE
$PWD
$(date +%Y)
\\
HERE
/tmp
2026
\
cmd <<'HERE'
$PWD
$(date +%Y)
\\
HERE
$PWD
$(date +%Y)
\\
cmd <<<"one string"test a [[[ expr ]](( expr ))test a [-lt -gt -eq …-z -n = != < >-e -f -s -d -t -r -O …! -a -o -v -o …test -f file -a \( -O file -o -w file \)
[ -f file -a \( -O file -o -w file \) ]
[[ expr ]](( expr ))test a [[[ expr ]]===~&& ||[[ -f file && ( -O file || -w file ) ]]
[[ $var == foo* || $var =~ [0-9]+ ]]
(( expr ))test a [[[ expr ]](( expr ))0/0x/base#…)i=009; (( i=10#$i, j--, k=i+j, k>0 ))
/bin/test a /bin/[grepcmp, diff, comm, sha*sum-G BRE -E ERE -P perl -F fixed
grep "$RE"grep -e "$RE1" -e "$RE2"grep -f regex_file
-icase insensitive-v,-w,-xvice-versa, word/exact match-q,-squiet, silent-m 1max countsha*sum
test kontrolního součtu
cmp
binární porovnávání obsahu
comm
společné řádky (množinové porovnání)
diff
rozdíly/změny dvou verzí
sha*sum
test kontrolního součtu
sha256sum f1 f2e3b0c44298fc1…495991b7852b855 f1e3b0c44298fc1…495991b7852b855 f2cmd | sha256sum >sumcmd | sha256sum -c --status sumcmp
binární porovnávání obsahu
comm
společné řádky (množinové porovnání)
diff
rozdíly/změny dvou verzí
sha*sum
test kontrolního součtu
cmp
binární porovnávání obsahu
cmp f1 f2f1 f2 differ: char 11, line 1cmd | cmp -s - filecomm
společné řádky (množinové porovnání)
diff
rozdíly/změny dvou verzí
sha*sum
test kontrolního součtu
cmp
binární porovnávání obsahu
comm
společné řádky (množinové porovnání)
printf '%s\n' a b c d e f >f1printf '%s\n' a bb c e ee gg >f2comm f1 f2abbbcdeeefggcomm -12 f1 f2acediff
rozdíly/změny dvou verzí
sha*sum
test kontrolního součtu
cmp
binární porovnávání obsahu
comm
společné řádky (množinové porovnání)
diff
rozdíly/změny dvou verzí
diff f1 f22c2< b---> bb4d3< d6c5,6< f---> ee> ggdiff -u f1 f2--- f1 …+++ f2 …@@ -1,6 +1,6 @@ a-b+bb c-d e-f+ee+ggmkdir "$BASE"cd "$BASE"touch "$LOG_FILE"[[ -d $BASE ]][[ $PWD == $BASE ]][[ -f $LOG_FILE ]][[ -f $BASE/$LOG_FILE ]]mkdir "$BASE"cd "$BASE"touch "$LOG_FILE"mkdir -p "$BASE">> "$BASE/$LOG_FILE"export BASE='/tmp/readonly'export LOG_FILE='access.log'PERM='u-wx'mkdir "$BASE"; chmod "$PERM" "$BASE"./script(( $? != 0 ))mkdir "$BASE" && touch "$BASE/$LOG_FILE"export BASE='logs'export LOG_FILE='access.log'./script(( $? == 0 ))[[ -f $BASE/$LOG_FILE ]]✔️ true✔️ trueexport BASE='logs'LOG_FILE='my special log'./script(( $? == 0 ))[[ -f $BASE/$LOG_FILE ]]❌ false❌ falsemkdir "$BASE" && touch "$BASE/$LOG_FILE"TMP=$( mktemp -d ) export BASE=$TMP/logsexport LOG_FILE='access.log'./script(( $? == 0 ))[[ -f $BASE/$LOG_FILE ]] rm -rf -- "$TMP"docker, podmanDockerfile (co)docker-compose.yml (jak)
podman build -t dev .FROM debian:bookworm-slimRUN apt-get update && apt-get install -y curl jq …WORKDIR /workspaceCMD ["/bin/bash"]podman build -t dev .FROM debian:bookworm-slimRUN apt-get update && apt-get install -y curl jq …WORKDIR /workspaceCMD ["/bin/bash"]podman build -t dev .FROM debian:bookworm-slimRUN apt-get update && apt-get install -y curl jq …RUN groupadd -g 1000 tester \
&& useradd -u 1000 -g tester -s /bin/bash -m testerWORKDIR /workspaceRUN chown -R tester:tester /workspaceUSER testerCMD ["/bin/bash"]podman build -t dev .FROM debian:bookworm-slimRUN apt-get update && apt-get install -y curl jq …ARG U=1000ARG G=1000RUN groupadd -g $G tester \
&& useradd -u $U -g tester -s /bin/bash -m testerWORKDIR /workspaceRUN chown -R tester:tester /workspaceUSER testerCMD ["/bin/bash"]podman build \ --build-arg U=$(id -u) \ --build-arg G=$(id -g) \ -t dev .
podman run -it --rm dev--userns=keep-id-v "$PWD:/workspace"-v "$PWD:/workspace:O"podman run -it --rm dev envPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:…container=podmanTERM=xtermHOME=/home/testerHOSTNAME=3898f4a36c14podman run -it --rm \ --userns=keep-id \ -v "$PWD:/workspace:O" \ dev ./scriptdocker-compose.ymlservices: dev: build: . image: dev userns_mode: "keep-id" volumes: - .:/workspace:Opodman-compose buildpodman-compose build --build-arg U=$(id -u) --build-arg G=$(id -g)podman-compose run --rm devsleep nTS=$( date +%s ); date -d @$TStimeouttest-1#!/usr/bin/env bashexport BASE=logsexport LOG_FILE=access.log ./scriptpodman-compose run --rm dev ./test-1
test-2
#!/usr/bin/env bash
export BASE=/logsexport LOG_FILE=access.log ./scriptpodman-compose run --rm dev ./test-2mkdir: cannot create directory '/logs': Permission denied
#!/usr/bin/env bashexport BASE=logsexport LOG_FILE=access.log if ./script >/tmp/out 2>/tmp/err; then echo "$0: OK" else echo "$0: FAILED"fipodman-compose run --rm dev ./test-1./test-1: OK
podman-compose run --rm dev ./test-2./test-2: FAILED
#!/usr/bin/env bashexport BASE=logsexport LOG_FILE=access.logexp_EC=0 ./script >/tmp/out 2>/tmp/errEC=$? r=FAILED(( EC == exp_EC )) && r=OKecho "${0##*/}: $r"for t in test-*; do podman-compose run --rm dev ./$t; donetest-1: OKtest-2: OK#!/usr/bin/env bashexport BASE=logsexport LOG_FILE=access.logexp_EC=0exp_file=0 ./script >/tmp/out 2>/tmp/errEC=$? r=FAILEDd='exit code'(( EC == exp_EC )) && r=OKecho "${0##*/}: $d: $r" r=FAILEDd='log file'[[ -f $BASE/$LOG_FILE ]](( $? == exp_file )) && r=OKecho "${0##*/}: $d: $r"!!test-1: exit code: OKtest-1: log file: OKtest-2: exit code: OKtest-2: log file: OK#!/usr/bin/env bashexport BASE=/logsexport LOG_FILE=access.logexp_EC=1exp_file=1cat >/tmp/exp_err <<ERRmkdir: cannot create directory '$BASE': Permission deniedERR ./script >/tmp/out 2>/tmp/errEC=$? ... r=FAILEDd='error output'cmp -s /tmp/err /tmp/exp_err && r=OKecho "${0##*/}: $d: $r"#!/usr/bin/env bashexport BASE=/logsexport LOG_FILE=access.logexp_EC=1exp_file=1cat >/tmp/exp_err <<ERRmkdir: cannot create directory '$BASE': Permission deniedERR res() { printf '%s: %-15s %s\n' "${0##*/}" "$d:" "$r"; } equals() { r=❌; (($1==$2)) && r=✔️; res; } is_file() { r=❌; [[ -f $1 ]]; (($?==$2)) && r=✔️; res; } compare() { r=❌; cmp -s "$1" "$2" && r=✔️; res; } ./script >/tmp/out 2>/tmp/errEC=$? d='exit code' ; equals "$EC" "$exp_EC"d='log file' ; is_file "$BASE/$LOG_FILE" "$exp_file"d='error output'; compare /tmp/err /tmp/exp_errtest.libres() { printf '%s: %-15s %s\n' "${0##*/}" "$d:" "$r"; } equals() { r=❌; (($1==$2)) && r=✔️; res; } is_file() { r=❌; [[ -f $1 ]]; (($?==$2)) && r=✔️; res; } compare() { r=❌; cmp -s "$1" "$2" && r=✔️; res; } printf '%s: %s\n' "${0##*/}" "$desc""$script_file" >/tmp/out 2>/tmp/errEC=$? d='exit code' ; equals "$EC" "$exp_EC"d='log file' ; is_file "$BASE/$LOG_FILE" "$exp_file"d='error output'; compare /tmp/err /tmp/exp_errtest-2#!/usr/bin/env bashscript_file=./scriptdesc='Read-only directory'export BASE=/test-direxport LOG_FILE=access.logexp_EC=1exp_file=1cat >/tmp/exp_err <<ERRmkdir: cannot create directory '$BASE': Permission deniedERR source ./test.libfor t in test-*; do podman-compose run --rm dev ./$t; donetest-1: Basic testtest-1: exit code: ✔️test-1: log file: ✔️test-1: error output: ✔️test-2: Read-only directorytest-2: exit code: ✔️test-2: log file: ✔️test-2: error output: ✔️#!/usr/bin/env bats bats_require_minimum_version 1.5.0 load '/usr/lib/bats/bats-support/load'load '/usr/lib/bats/bats-assert/load' @test "Accessible BASE dir" { export BASE=test-dir export LOG_FILE=access.log run --separate-stderr ./script assert_success assert_equal "$stderr" "" [[ -f $BASE/$LOG_FILE ]]} @test "Inaccessible BASE dir" { export BASE=/test-dir export LOG_FILE=access.log run --separate-stderr ./script assert_failure assert_equal "$stderr" "mkdir: cannot create directory '$BASE': Permission denied" [[ ! -f $BASE/$LOG_FILE ]]} ./test.batstest.bats ✓ Accessible BASE dir ✓ Inaccessible BASE dir2 tests, 0 failuresalias get_data='echo "{\"id\":0,\"val\":\"mock\"}"'get_data | jq .{ "id": 0, "val": "mock"}get_data | jq -r .valmockget_data() { echo '{"id":0,"val":"mock"}'; }'get_data | jq -r .valmockget_data
#!/usr/bin/env bashcat <<'DATA'{ "id":0, "val":"mock"}DATAchmod +x get_data./get_data | jq -r .valmockalias get_data=~+/get_dataget_data | jq -r .valmockget_data
#!/usr/bin/env bashcat <<'DATA'Content-Type: application/json{ "id":0, "val":"mock"}DATAchmod +x get_datamkdir cgi-binmv get_data cgi-binpython3 -m http.server --cgi 8888curl localhost:8888/cgi-bin/get_data | jq -r .valmockgit clone https://gitlab.com/lukasbarinka/tdd.git
. ps1-ec. ps1-color
PS1='\w $?↗ '~ 0 $ PS1='\[\033[0;$(($?==0?32:31))m\]\w $?↗ \[\033[0m\]'~ 0 $ false~ 0 $ true~ 0 $ ./date ./date2date;date stejné časy?while :; do d1=$(date) d2=$(date) [[ $d1 != $d2 ]] && echo -n !done./date ./date2date;date stejné časy?while :; do date >/tmp/d1 date >/tmp/d2 cmp -s /tmp/d1 /tmp/d2 || echo -n !done🗁 list/00 🗋 data 🗋 white 🗋 blacknumber vypisující desetinná čísladatawhiteblack🗁 list/01 ./check ./check2 ./check3comm pracuje nad seřazenými souborysort data >/tmp/data.ssort white >/tmp/white.ssort black >/tmp/black.ssort white black >/tmp/all.scomm /tmp/white.s /tmp/black.swhite a black disjunktní?comm -12 /tmp/white.s /tmp/black.scomm -3 /tmp/data.s /tmp/all.s🗁 list/02 🗋 regex ./testregex[0-9]*grep -Ex -f regex data | diff - whitegrep -vEx -f regex data | diff - blackdiff prázdný🗁 list/03 🗋 regex ./test[+-]?[0-9]*+[+-]?[0-9]+*\.[0-9]+Skript maxint vypíše nejvyšší zadané celé číslo.
| Args. | StdOut | StdErr | EC |
2 1 | 2 | | 0 |
2 2 | 2 | | 0 |
11 9 | 11 | | 0 |
9 09 | 09 | | 0 |
2 | 2 | | 0 |
-0 | -0 | | 0 |
2 3 1 | 3 | | 0 |
1 -1 | 1 | | 0 |
| Args. | StdOut | StdErr | EC |
| | Args | 2 |
foo | | NaN | 1 |
1foo | | NaN | 1 |
1 foo | 1 | NaN | 1 |
1 2.5 3 | 3 | NaN | 1 |
🗁 args/01 🗋 script 🗋 test-01
script
echo '#!/usr/bin/env bash' >scriptchmod +x script./scripttest-01
#!/usr/bin/env bash# args: 2 1# exp_out: 2 out=$( ./script 2 1 ) r=FAILED[[ $out == 2 ]] && r=OKecho "$0: $r"🗁 args/01 🗋 script 🗋 test-01
script#!/usr/bin/env bash./test-01./test-01: FAILED🗁 args/02 🗋 script 🗋 test-01
script#!/usr/bin/env bashprintf '%d\n' "$@" | sort | tail -n 1./test-01./test-01: OK🗁 args/03 🗋 script 🗋 test-01 🗋 test-02 ./run
test-02#!/usr/bin/env bash# args: 2 2# exp_out: 2 out=$( ./script 2 2 ) r=FAILED[[ $out == 2 ]] && r=OKecho "$0: $r"for t in test-*; do ./$t; done./test-01: OK./test-02: OK🗁 args/04 🗋 script 🗋 test-01 🗋 test-02 🗋 test-03 ./run
test-03#!/usr/bin/env bash# args: 11 9# exp_out: 11 out=$( ./script 11 9 ) r=FAILED[[ $out == 11 ]] && r=OKecho "$0: $r"for t in test-*; do ./$t; done./test-01: OK./test-02: OK./test-02: FAILED🗁 args/05 🗋 script 🗋 test-01 🗋 test-02 🗋 test-03 ./run
test-03#!/usr/bin/env bashargs=( 11 9 )exp_out=11 out=$( ./script "${args[@]}" ) r=FAILED[[ $out == "$exp_out" ]] && r=OKecho "$0: $r"for t in test-*; do ./$t; done./test-01: OK./test-02: OK./test-02: FAILED🗁 args/06 🗋 script 🗋 test 🗋 test-01 🗋 test-02 🗋 test-03 ./run
test-03#!/usr/bin/env bashargs=( 11 9 )exp_out=11 source ./testtestout=$( ./script "${args[@]}" ) r=FAILED[[ $out == "$exp_out" ]] && r=OKecho "$0: $r"for t in test-*; do ./$t; done./test-01: OK./test-02: OK./test-02: FAILED🗁 args/07 🗋 script 🗋 test 🗋 test-01 🗋 test-02 🗋 test-03 ./run
test-03args=( 11 9 )exp_out=11test#!/usr/bin/env bashsource "./$1" || exit 2 out=$( ./script "${args[@]}" ) r=FAILED[[ $out == "$exp_out" ]] && r=OKecho "$0: $r"for t in test-*; do ./test "$t"; done./test-01: OK./test-02: OK./test-02: FAILED🗁 args/08 🗋 data 🗋 script ./test
test#!/usr/bin/env bashIFS='|'sed '/^ *#/d;s/ *|/|/g;s/| */|/g' data \| while read -r a exp_out exp_err exp_EC; do IFS=" " read -ra args <<<"$a" out=$( ./script "${args[@]}" 2>/dev/null ) r=FAILED [[ $out == "$exp_out" ]] && r=OKecho "$0: $r" printf '%-10s ⇒ %-5s : %-5s %s\n' \ "${args[*]}" ".$exp_out." ".$out." "$r" IFS='|'done./test2 1 ⇒ .2. : .2. OK2 2 ⇒ .2. : .2. OK11 9 ⇒ .11. : .9. FAILED9 09 ⇒ .09. : .9. FAILED2 ⇒ .2. : .2. OK-0 ⇒ .-0. : .0. FAILED2 3 1 ⇒ .3. : .3. OK1 -1 ⇒ .1. : .1. OK ⇒ .. : .0. FAILEDfoo ⇒ .. : .0. FAILED1fo ⇒ .. : .1. FAILED1 foo ⇒ .1. : .1. OK1 2.5 3 ⇒ .3. : .3. OK🗁 args/09 🗋 data 🗋 script ./test
script#!/usr/bin/env bashprintf '%ds\n' "$@" | sort | tail -n 1./test2 1 ⇒ .2. : .2. OK2 2 ⇒ .2. : .2. OK11 9 ⇒ .11. : .9. FAILED9 09 ⇒ .09. : .9. FAILED2 ⇒ .2. : .2. OK-0 ⇒ .-0. : .0. FAILED2 3 1 ⇒ .3. : .3. OK1 -1 ⇒ .1. : .1. OK ⇒ .. : .0. FAILEDfoo ⇒ .. : .0. FAILED1fo ⇒ .. : .1. FAILED1 foo ⇒ .1. : .1. OK1 2.5 3 ⇒ .3. : .3. OK./test2 1 ⇒ .2. : .2. OK2 2 ⇒ .2. : .2. OK11 9 ⇒ .11. : .9. FAILED9 09 ⇒ .09. : .9. FAILED2 ⇒ .2. : .2. OK-0 ⇒ .-0. : .-0. OK2 3 1 ⇒ .3. : .3. OK1 -1 ⇒ .1. : .1. OK ⇒ .. : .. OKfoo ⇒ .. : .foo. FAILED1fo ⇒ .. : .1fo. FAILED1 foo ⇒ .1. : .1. OK1 2.5 3 ⇒ .3. : .3. OK🗁 args/10 🗋 data 🗋 script ./test
script#!/usr/bin/env bashprintf '%s\n' "$@" | sort -n | tail -n 1./test2 1 ⇒ .2. : .2. OK2 2 ⇒ .2. : .2. OK11 9 ⇒ .11. : .9. FAILED9 09 ⇒ .09. : .9. FAILED2 ⇒ .2. : .2. OK-0 ⇒ .-0. : .-0. OK2 3 1 ⇒ .3. : .3. OK1 -1 ⇒ .1. : .1. OK ⇒ .. : .. OKfoo ⇒ .. : .foo. FAILED1fo ⇒ .. : .1fo. FAILED1 foo ⇒ .1. : .1. OK1 2.5 3 ⇒ .3. : .3. OK./test2 1 ⇒ .2. : .2. OK2 2 ⇒ .2. : .2. OK11 9 ⇒ .11. : .11. OK9 09 ⇒ .09. : .9. FAILED2 ⇒ .2. : .2. OK-0 ⇒ .-0. : .-0. OK2 3 1 ⇒ .3. : .3. OK1 -1 ⇒ .1. : .1. OK ⇒ .. : .. OKfoo ⇒ .. : .foo. FAILED1fo ⇒ .. : .1fo. FAILED1 foo ⇒ .1. : .1. OK1 2.5 3 ⇒ .3. : .3. OK🗁 args/11 🗋 data 🗋 script ./test
script#!/usr/bin/env bashprintf '%s\n' "$@" | sort -ns | tail -n 1./test2 1 ⇒ .2. : .2. OK2 2 ⇒ .2. : .2. OK11 9 ⇒ .11. : .11. OK9 09 ⇒ .09. : .9. FAILED2 ⇒ .2. : .2. OK-0 ⇒ .-0. : .-0. OK2 3 1 ⇒ .3. : .3. OK1 -1 ⇒ .1. : .1. OK ⇒ .. : .. OKfoo ⇒ .. : .foo. FAILED1fo ⇒ .. : .1fo. FAILED1 foo ⇒ .1. : .1. OK1 2.5 3 ⇒ .3. : .3. OK./test2 1 ⇒ .2. : .2. OK2 2 ⇒ .2. : .2. OK11 9 ⇒ .11. : .11. OK9 09 ⇒ .09. : .09. OK2 ⇒ .2. : .2. OK-0 ⇒ .-0. : .-0. OK2 3 1 ⇒ .3. : .3. OK1 -1 ⇒ .1. : .1. OK ⇒ .. : .. OKfoo ⇒ .. : .foo. FAILED1fo ⇒ .. : .1fo. FAILED1 foo ⇒ .1. : .1. OK1 2.5 3 ⇒ .3. : .3. OK🗁 args/12 🗋 data 🗋 script ./test
test⫶out=$( ./script "${args[@]}" 2>/dev/null/tmp/err )EC=$?err=$( < /tmp/err ) r_EC=FAILED[[ $EC == "$exp_EC" ]] && r_EC=OKr_out=FAILED[[ $out == "$exp_out" ]] && r_out=OKr_err=FAILED[[ $err == "$exp_err" ]] && r_err=OK printf '%-10s ⇒ %-5s : %-5s %s| %-6s : %-6s %-6s | %d %d %-6s\n' \ "${args[*]}" ".$exp_out." ".$out." "$r_out" \ ".$exp_err." ".$err." "$r_err" \ "$exp_EC" "$EC" "$r_EC"⫶./test2 1 ⇒ .2. : .2. OK | .. : .. OK | 0 0 OK 2 2 ⇒ .2. : .2. OK | .. : .. OK | 0 0 OK 11 9 ⇒ .11. : .11. OK | .. : .. OK | 0 0 OK 9 09 ⇒ .09. : .09. OK | .. : .. OK | 0 0 OK 2 ⇒ .2. : .2. OK | .. : .. OK | 0 0 OK -0 ⇒ .-0. : .-0. OK | .. : .. OK | 0 0 OK 2 3 1 ⇒ .3. : .3. OK | .. : .. OK | 0 0 OK 1 -1 ⇒ .1. : .1. OK | .. : .. OK | 0 0 OK ⇒ .. : .. OK | .Args. : .. FAILED | 2 0 FAILEDfoo ⇒ .. : .foo. FAILED | .NaN. : .. FAILED | 1 0 FAILED1fo ⇒ .. : .1fo. FAILED | .NaN. : .. FAILED | 1 0 FAILED1 foo ⇒ .1. : .1. OK | .NaN. : .. FAILED | 1 0 FAILED1 2.5 3 ⇒ .3. : .3. OK | .NaN. : .. FAILED | 1 0 FAILED🗁 args/13 🗋 data 🗋 script ./test
#!/usr/bin/env bashargs=()err=0 if (( $# == 0 )); then echo "Args" >&2 exit 2fi for arg; do if [[ $arg =~ ^-?[0-9]+$ ]]; then args+=( "$arg" ) elif (( err == 0 )); then echo "NaN" >&2 err=1 fidone printf '%s\n' "${args[@]}" | sort -ns | tail -n 1 exit $err./test2 1 ⇒ .2. : .2. OK | .. : .. OK | 0 0 OK 2 2 ⇒ .2. : .2. OK | .. : .. OK | 0 0 OK 11 9 ⇒ .11. : .11. OK | .. : .. OK | 0 0 OK 9 09 ⇒ .09. : .09. OK | .. : .. OK | 0 0 OK 2 ⇒ .2. : .2. OK | .. : .. OK | 0 0 OK -0 ⇒ .-0. : .-0. OK | .. : .. OK | 0 0 OK 2 3 1 ⇒ .3. : .3. OK | .. : .. OK | 0 0 OK 1 -1 ⇒ .1. : .1. OK | .. : .. OK | 0 0 OK ⇒ .. : .. OK | .Args. : .Args. OK | 2 2 OK foo ⇒ .. : .. OK | .NaN. : .NaN. OK | 1 1 OK 1fo ⇒ .. : .. OK | .NaN. : .NaN. OK | 1 1 OK 1 foo ⇒ .1. : .1. OK | .NaN. : .NaN. OK | 1 1 OK 1 2.5 3 ⇒ .3. : .3. OK | .NaN. : .NaN. OK | 1 1 OK 🗁 file/00 🗋 Dockerfile 🗋 docker-compose.ymlbackup vytvoří adresář …dev
Dockerfiledocker-compose.yml🗁 file/01 ./build ./runpodman-compose build \ --build-arg U=$(id -u) --build-arg G=$(id -g)podman-compose run --rm devFROM debian:bookworm-slimARG U=1000ARG G=1000RUN groupadd -g $G tester \ && useradd -u $U -g tester -s /bin/bash -m testerWORKDIR /workspaceRUN chown -R tester:tester /workspaceUSER testerCMD ["/bin/bash"]services: dev: build: . image: dev userns_mode: "keep-id" volumes: - .:/workspace:O🗁 file/02 🗋 test-01 🗋 test-02 🗋 test-03 ./run#!/usr/bin/env bash echo "❔ Workspace writable"podman-compose run --rm dev ./test-01if [[ ! -d testdir ]]; then echo " ✅ Overlay works"else echo " ❎ Overlay does not work"fi echo "❔ Root directory read-only"podman-compose run --rm dev ./test-02 echo "❔ Unprivileged user"podman-compose run --rm dev ./test-03 ./run#!/usr/bin/env bashmkdir testdir 2>/dev/nullif [[ -d testdir ]]; then echo " ✅ Directory created"else echo " ❎ Directory not created"fi#!/usr/bin/env bashmkdir /testdir 2>/dev/nullif [[ ! -d /testdir ]]; then echo " ✅ Directory not created"else echo " ❎ Directory created"fi#!/usr/bin/env bashif (( $(id -u) != 0 )); then echo " ✅ UID != 0"else echo " ❎ UID == 0"fi