diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..d60acb1 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,38 @@ +# https://docs.github.com/ja/repositories/releasing-projects-on-github/automatically-generated-release-notes +changelog: + categories: + - title: "💥 BREAKING CHANGES" + labels: + - BREAKING CHANGE + - title: "⬆️ Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)" + labels: + - build + - dependencies + - title: "👷 Changes to our CI configuration files and scripts (examples: CircleCi, SauceLabs)" + labels: + - ci + - title: "📝 Documentation only changes" + labels: + - docs + - title: "✨ A new feature" + labels: + - feat + - title: "🐛 A bug fix" + labels: + - fix + - title: "⚡️ A code change that improves performance" + labels: + - perf + - title: "♻️ A code change that neither fixes a bug nor adds a feature" + labels: + - refactor + - title: "✅ Adding missing tests or correcting existing tests" + labels: + - test + - title: "🚨 Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)" + labels: + - style + - title: "🧑💻 Changes to the build process or auxiliary tools and libraries such as documentation generation" + labels: + - chore + - "*" diff --git a/.github/workflows/sh-test.yml b/.github/workflows/sh-test.yml new file mode 100644 index 0000000..73a4227 --- /dev/null +++ b/.github/workflows/sh-test.yml @@ -0,0 +1,61 @@ +name: sh-test +# ~~~~~~~ +# https://github.com/kunitsucom/log.sh/workflows/sh-test/badge.svg +# ~~~~~~~ + +on: + push: + branches: + - main + paths-ignore: + - '.github/dependabot.yml' + - '.github/pull_request_template.md' + - '.github/release.yml' + - 'README.md' + pull_request: + paths-ignore: + - '.github/dependabot.yml' + - '.github/pull_request_template.md' + - '.github/release.yml' + - 'README.md' + workflow_dispatch: + inputs: {} + +# NOTE: 連続で commit & push した時に最新の commit 以外のワークフローをキャンセルする +concurrency: + group: ${{ github.workflow }}-${{ github.base_ref }}-${{ github.head_ref }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + id-token: write + contents: read + +env: + WORKDIR: . + +defaults: + run: + shell: bash + +jobs: + sh-test: # NOTE: for Branch protection rule `Status checks that are required.` + runs-on: ubuntu-latest # ref. https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on + steps: + - uses: actions/checkout@v3 + - name: DEBUG + run: | + cat <<'DEBUG_DOC' + == DEBUG ======================================================= + github.ref: ${{ github.ref }} + github.event_name: ${{ github.event_name }} + -- toJSON(github.event.inputs) --------------------------------- + ${{ toJSON(github.event.inputs) }} + -- toJSON(github) ---------------------------------------------- + ${{ toJSON(github) }} + ================================================================ + DEBUG_DOC + shell: bash + - name: Run test.sh + working-directory: ${{ env.WORKDIR }} + run: | + ${{ env.WORKDIR }}/test.sh diff --git a/LICENSE b/LICENSE index 4918655..a49f4fa 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2022 kunitsuinc + Copyright 2022 kunitsucom Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 40a2a23..a69d05c 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,33 @@ -# rec.sh - JSON logger for POSIX Shell Script +# log.sh - JSON logger for POSIX Shell Script -rec.sh is a lightweight and no dependencies JSON logger for POSIX Shell Script. +[![license](https://img.shields.io/github/license/kunitsucom/log.sh)](LICENSE) +[![workflow](https://github.com/kunitsucom/log.sh/workflows/sh-test/badge.svg)](https://github.com/kunitsucom/log.sh/tree/main) + +log.sh is a lightweight and no dependencies JSON logger for POSIX Shell Script. This logger has been minimized as much as possible for copy-and-paste portability, at the expense of readability. -**NOTE:** rec.sh only supports JSON with string values. JSON such as `{"number":123}` cannot be output. In the case of rec.sh, it will be `{"number":"123"}`. +**NOTE:** log.sh only supports JSON with string values. JSON such as `{"number":123}` cannot be output. In the case of log.sh, it will be `{"number":"123"}`. -**NOTE:** rec.sh cannot output any control characters other than `\n` `\r` `\t`. +**NOTE:** log.sh cannot output any control characters other than `\n` `\r` `\t`. ## HOW TO USE There are two ways. -### 1. Vendoring (Recommended) +### 1. Vendoring (recommended) -Copy the rec.sh functions in the shell script file ([`index.html`](/index.html)) and paste them where you want to use them. -(file name `index.html` may seem strange, but it's necessary for me to serve Shell Script file in GitHub Pages with as short URL *https://kunitsuinc.github.io/rec.sh/* as possible) +Copy the log.sh functions in the shell script file ([`index.html`](/index.html)) and paste them where you want to use them. +(file name `index.html` may seem strange, but it's necessary for me to serve Shell Script file in GitHub Pages with as short URL [`https://kunitsucom.github.io/log.sh/`](https://kunitsucom.github.io/log.sh/) as possible) ### 2. Use via HTTP You can load a shell script function via the Internet as follows: ```console -$ eval "$(curl -fLSs --tlsv1.2 https://kunitsuinc.github.io/rec.sh/)" +$ eval "$(curl -fLSs --tlsv1.2 https://kunitsucom.github.io/log.sh/)" -$ RecInfoJSON hello foo bar HOSTNAME ${HOSTNAME} +$ LogshInfoJSON hello foo bar HOSTNAME ${HOSTNAME} {"timestamp":"2021-11-26T08:02:08+09:00","severity":"INFO","caller":"-bash","message":"hello","foo":"bar","HOSTNAME":"localhost"} # <- NOTE: stderr $ # And so on... @@ -33,11 +36,11 @@ $ # And so on... ## Examples of usage ```console -$ # RecDefaultJSON, RecDebugJSON, RecInfoJSON, RecNoticeJSON, RecWarningJSON, RecErrorJSON, RecCriticalJSON, RecAlertJSON and RecEmergencyJSON -$ RecInfoJSON hello foo bar HOSTNAME ${HOSTNAME} ctrl "$(printf "\n\t\r")" cannot-tail-lf "$(printf "\t\r\n")" cannot-other-ctrl-chars "$(printf "\x01\x7F")" +$ # LogshDefaultJSON, LogshDebugJSON, LogshInfoJSON, LogshNoticeJSON, LogshWarningJSON, LogshErrorJSON, LogshCriticalJSON, LogshAlertJSON and LogshEmergencyJSON +$ LogshInfoJSON hello foo bar HOSTNAME ${HOSTNAME} ctrl "$(printf "\n\t\r")" cannot-tail-lf "$(printf "\t\r\n")" cannot-other-ctrl-chars "$(printf "\x01\x7F")" {"timestamp":"2021-11-26T08:02:08+09:00","severity":"INFO","caller":"-bash","message":"hello","foo":"bar","HOSTNAME":"localhost","ctrl":"\n\t\r","cannot-tail-lf":"\t\r","cannot-other-ctrl-chars":""} # <- NOTE: stderr -$ RecInfoJSON hello foo bar HOSTNAME ${HOSTNAME} ctrl "$(printf "\n\t\r")" cannot-tail-lf "$(printf "\t\r\n")" cannot-other-ctrl-chars "$(printf "\x01\x7F")" 2>&1 | jq . +$ LogshInfoJSON hello foo bar HOSTNAME ${HOSTNAME} ctrl "$(printf "\n\t\r")" cannot-tail-lf "$(printf "\t\r\n")" cannot-other-ctrl-chars "$(printf "\x01\x7F")" 2>&1 | jq . { "timestamp": "2021-11-26T08:02:34+09:00", "severity": "INFO", @@ -46,43 +49,43 @@ $ RecInfoJSON hello foo bar HOSTNAME ${HOSTNAME} ctrl "$(printf "\n\t\r")" canno "foo": "bar", "HOSTNAME": "localhost", "ctrl": "\n\t\r", - "cannot-tail-lf": "\t\r" # <- NOTE: rec.sh can't output field value tail '\n' - "cannot-other-ctrl-chars": "" # <- NOTE: rec.sh can't output other control characters + "cannot-tail-lf": "\t\r" # <- NOTE: log.sh can't output field value tail '\n' + "cannot-other-ctrl-chars": "" # <- NOTE: log.sh can't output other control characters } ``` ```console $ # Severity threshold -$ export REC_SEVERITY=0; RecDefaultJSON "output"; RecDebugJSON "output"; RecInfoJSON "output" +$ export LOGSH_LEVEL=0; LogshDefaultJSON "output"; LogshDebugJSON "output"; LogshInfoJSON "output" {"timestamp":"2021-11-28T10:28:24+09:00","severity":"DEFAULT","caller":"-bash","message":"output"} {"timestamp":"2021-11-28T10:28:24+09:00","severity":"DEBUG","caller":"-bash","message":"output"} {"timestamp":"2021-11-28T10:28:24+09:00","severity":"INFO","caller":"-bash","message":"output"} -$ export REC_SEVERITY=1; RecDefaultJSON "NO OUTPUT"; RecDebugJSON "output"; RecInfoJSON "output" +$ export LOGSH_LEVEL=1; LogshDefaultJSON "NO OUTPUT"; LogshDebugJSON "output"; LogshInfoJSON "output" {"timestamp":"2021-11-28T10:28:24+09:00","severity":"DEBUG","caller":"-bash","message":"output"} {"timestamp":"2021-11-28T10:28:24+09:00","severity":"INFO","caller":"-bash","message":"output"} -$ export REC_SEVERITY=101; RecDefaultJSON "NO OUTPUT"; RecDebugJSON "NO OUTPUT"; RecInfoJSON "output" +$ export LOGSH_LEVEL=101; LogshDefaultJSON "NO OUTPUT"; LogshDebugJSON "NO OUTPUT"; LogshInfoJSON "output" {"timestamp":"2021-11-28T10:28:24+09:00","severity":"INFO","caller":"-bash","message":"output"} $ # +------------------+------------------------+ -$ # | Function | REC_SEVERITY threshold | +$ # | Function | LOGSH_LEVEL threshold | $ # +------------------+------------------------+ -$ # | RecDefaultJSON | 0 | -$ # | RecDebugJSON | 100 | -$ # | RecInfoJSON | 200 | -$ # | RecNoticeJSON | 300 | -$ # | RecWarningJSON | 400 | -$ # | RecErrorJSON | 500 | -$ # | RecCriticalJSON | 600 | -$ # | RecAlertJSON | 700 | -$ # | RecEmergencyJSON | 800 | +$ # | LogshDefaultJSON | 0 | +$ # | LogshDebugJSON | 100 | +$ # | LogshInfoJSON | 200 | +$ # | LogshNoticeJSON | 300 | +$ # | LogshWarningJSON | 400 | +$ # | LogshErrorJSON | 500 | +$ # | LogshCriticalJSON | 600 | +$ # | LogshAlertJSON | 700 | +$ # | LogshEmergencyJSON | 800 | $ # +------------------+------------------------+ ``` ```console $ # Change timestamp timezone -$ TZ=UTC RecInfoJSON hello foo bar 2>&1 | jq . +$ TZ=UTC LogshInfoJSON hello foo bar 2>&1 | jq . { "timestamp": "2021-11-27T11:19:15+00:00", # <- NOTE: TZ=UTC "severity": "INFO", @@ -94,30 +97,30 @@ $ TZ=UTC RecInfoJSON hello foo bar 2>&1 | jq . ```console $ # Change field key name -$ export REC_TIMESTAMP_KEY=ts REC_SEVERITY_KEY=lv REC_CALLER_KEY=file REC_MESSAGE_KEY=msg -$ RecInfoJSON hello foo bar 2>&1 | jq . +$ export LOGSH_TIMESTAMP_KEY=ts LOGSH_LEVEL_KEY=lv LOGSH_CALLER_KEY=file LOGSH_MESSAGE_KEY=msg +$ LogshInfoJSON hello foo bar 2>&1 | jq . { - "ts": "2021-11-27T20:21:55+09:00", # <- NOTE: REC_TIMESTAMP_KEY - "lv": "INFO", # <- NOTE: REC_SEVERITY_KEY - "file": "-bash", # <- NOTE: REC_CALLER_KEY - "msg": "hello", # <- NOTE: REC_MESSAGE_KEY + "ts": "2021-11-27T20:21:55+09:00", # <- NOTE: LOGSH_TIMESTAMP_KEY + "lv": "INFO", # <- NOTE: LOGSH_LEVEL_KEY + "file": "-bash", # <- NOTE: LOGSH_CALLER_KEY + "msg": "hello", # <- NOTE: LOGSH_MESSAGE_KEY "foo": "bar" } ``` ```console -$ # RecExecJSON -$ RecExecJSON date +%F +$ # LogshExecJSON +$ LogshExecJSON date +%F {"timestamp":"2021-11-27T20:25:03+09:00","severity":"INFO","caller":"-bash","message":"$ date +%F"} # <- NOTE: stderr 2021-11-25 ``` ```console -$ # RecRunJSON -$ RecRunJSON sh -c "echo out; echo err 1>&2; exit 1" +$ # LogshRunJSON +$ LogshRunJSON sh -c "echo out; echo err 1>&2; exit 1" {"timestamp":"2021-11-27T20:25:27+09:00","severity":"INFO","caller":"-bash","message":"$ date +%F","command":"date +%F","stdout":"2021-11-27","stderr":"","return":"1"} # <- NOTE: stderr -$ RecRunJSON sh -c "echo out; echo err 1>&2; exit 1" 2>&1 | jq . +$ LogshRunJSON sh -c "echo out; echo err 1>&2; exit 1" 2>&1 | jq . { "timestamp": "2021-11-27T20:26:46+09:00", "severity": "INFO", @@ -134,5 +137,5 @@ $ RecRunJSON sh -c "echo out; echo err 1>&2; exit 1" 2>&1 | jq . The following tools are used for development. -- formatter ... https://github.com/mvdan/sh -- linter ... https://github.com/koalaman/shellcheck +- formatter ... [`github.com/mvdan/sh`](https://github.com/mvdan/sh) +- linter ... [`github.com/koalaman/shellcheck`](https://github.com/koalaman/shellcheck) diff --git a/benchmark.sh b/benchmark.sh index fa74fe0..921f32b 100755 --- a/benchmark.sh +++ b/benchmark.sh @@ -1,36 +1,6 @@ #!/usr/bin/env bash set -E -e -o pipefail -u -# shellcheck disable=SC1091 -. index.html - -export TZ=UTC REC_SEVERITY=0 REC_TIMESTAMP_KEY=timestamp REC_SEVERITY_KEY=severity REC_CALLER_KEY=caller REC_MESSAGE_KEY=message - -DisplayRuntimeInfo() { - cmd="uname -s -v -m" - if [ "$(uname -s)" = Linux ]; then - cmd="${cmd:?}; grep model.name /proc/cpuinfo | sort -u" - elif [ "$(uname -s)" = Darwin ]; then - cmd="${cmd:?}; sysctl -a machdep.cpu.brand_string" - fi - RecExec sh -c "${cmd:?}" - echo -} && DisplayRuntimeInfo - -BenchmarkRecDebugJSON_001() { - echo "BenchmarkRecDebugJSON_001" - printf %s 'RecDebugJSON(message only) * 100' - time : "$(for _ in $(seq 1 100); do RecDebugJSON "$(printf "\t\nA\t\nB\t\nC\t\n")"; done >/tmp/rec.sh_BenchmarkRecDebugJSON_001.log 2>&1)" - echo -} && BenchmarkRecDebugJSON_001 - -BenchmarkRecDebugJSON_002() { - echo "BenchmarkRecDebugJSON_002" - printf %s 'RecDebugJSON(with 1 field) * 100' - time : "$(for _ in $(seq 1 100); do RecDebugJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")"; done >/tmp/rec.sh_BenchmarkRecDebugJSON_002.log 2>&1)" - echo -} && BenchmarkRecDebugJSON_002 - # benchmark sample on commit 'init' # ------------------------------------------------------------------------------------------------- # $ docker run -it --rm -v "$(pwd -P)":"$(pwd -P)" -w "$(pwd -P)" --env-file <(env) ubuntu:20.04 ./benchmark.sh @@ -38,14 +8,14 @@ BenchmarkRecDebugJSON_002() { # Linux #1 SMP Sat Jul 3 21:51:47 UTC 2021 x86_64 # model name : Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz # -# BenchmarkRecDebug_001 -# RecDebug(message only) * 100 +# BenchmarkLogshDebug_001 +# LogshDebug(message only) * 100 # real 0m0.596s # user 0m0.397s # sys 0m0.556s # -# BenchmarkRecDebug_002 -# RecDebug(with 1 field) * 100 +# BenchmarkLogshDebug_002 +# LogshDebug(with 1 field) * 100 # real 0m0.878s # user 0m0.608s # sys 0m0.876s @@ -55,31 +25,83 @@ BenchmarkRecDebugJSON_002() { # Darwin Darwin Kernel Version 20.6.0: Mon Aug 30 06:12:21 PDT 2021; root:xnu-7195.141.6~3/RELEASE_X86_64 x86_64 # machdep.cpu.brand_string: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz # -# BenchmarkRecDebug_001 -# RecDebug(message only) * 100 +# BenchmarkLogshDebug_001 +# LogshDebug(message only) * 100 # real 0m3.694s # user 0m0.702s # sys 0m2.035s # -# BenchmarkRecDebug_002 -# RecDebug(with 1 field) * 100 +# BenchmarkLogshDebug_002 +# LogshDebug(with 1 field) * 100 # real 0m5.973s # user 0m1.154s # sys 0m3.422s # ------------------------------------------------------------------------------------------------- +# $ ./benchmark.sh # 2022-04-09T07:30:54+00:00 [ INFO] $ sh -c 'uname -s -v -m; sysctl -a machdep.cpu.brand_string' # Darwin Darwin Kernel Version 21.4.0: Fri Mar 18 00:45:05 PDT 2022; root:xnu-8020.101.4~15/RELEASE_X86_64 x86_64 # machdep.cpu.brand_string: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz # -# BenchmarkRecDebugJSON_001 -# RecDebugJSON(message only) * 100 +# BenchmarkLogshDebugJSON_001 +# LogshDebugJSON(message only) * 100 # real 0m1.890s # user 0m0.730s # sys 0m1.639s # -# BenchmarkRecDebugJSON_002 -# RecDebugJSON(with 1 field) * 100 +# BenchmarkLogshDebugJSON_002 +# LogshDebugJSON(with 1 field) * 100 # real 0m3.108s # user 0m1.219s # sys 0m2.855s # ------------------------------------------------------------------------------------------------- +# $ ./benchmark.sh +# 2023-08-26T19:23:55+00:00 [ INFO] $ sh -c 'uname -s -v -m; sysctl -a machdep.cpu.brand_string' +# Darwin Darwin Kernel Version 22.6.0: Wed Jul 5 22:22:05 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T6000 arm64 +# machdep.cpu.brand_string: Apple M1 Max +# +# BenchmarkLogshDebugJSON_001 +# LogshDebugJSON(message only) * 100 +# real 0m1.132s +# user 0m0.198s +# sys 0m0.748s +# +# BenchmarkLogshDebugJSON_002 +# LogshDebugJSON(with 1 field) * 100 +# real 0m1.800s +# user 0m0.320s +# sys 0m1.225s +# ------------------------------------------------------------------------------------------------- + +cd "$(dirname "$0")" + +# shellcheck disable=SC1091 +. ./index.html + +export TZ=UTC LOGSH_LEVEL=0 LOGSH_TIMESTAMP_KEY=timestamp LOGSH_LEVEL_KEY=severity LOGSH_CALLER_KEY=caller LOGSH_MESSAGE_KEY=message + +DisplayRuntimeInfo() { + LogshRun uname -s -v -m + __system=$(uname -s) + if [ "${__system:-}" = Linux ]; then + LogshRun sh -c "grep model.name /proc/cpuinfo | sort -u" + elif [ "${__system:-}" = Darwin ]; then + LogshRun sysctl -a machdep.cpu.brand_string + else + LogshWarning unknown system + fi + echo +} && DisplayRuntimeInfo + +BenchmarkLogshDebugJSON_001() { + echo "BenchmarkLogshDebugJSON_001" + printf %s 'LogshDebugJSON(message only) * 100' + time : "$(for _ in $(seq 1 100); do LogshDebugJSON "$(printf "\t\nA\t\nB\t\nC\t\n")"; done >/tmp/log.sh_BenchmarkLogshDebugJSON_001.log 2>&1)" + echo +} && BenchmarkLogshDebugJSON_001 + +BenchmarkLogshDebugJSON_002() { + echo "BenchmarkLogshDebugJSON_002" + printf %s 'LogshDebugJSON(with 1 field) * 100' + time : "$(for _ in $(seq 1 100); do LogshDebugJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")"; done >/tmp/log.sh_BenchmarkLogshDebugJSON_002.log 2>&1)" + echo +} && BenchmarkLogshDebugJSON_002 diff --git a/index.html b/index.html index 9ac89d6..a65093c 100644 --- a/index.html +++ b/index.html @@ -1,49 +1,53 @@ #!/bin/sh -cat >/dev/null <<'#https://kunitsuinc.github.io/rec.sh/' +# shellcheck disable=SC2317 +cat >/dev/null <<'#https://kunitsucom.github.io/log.sh/'
-#https://kunitsuinc.github.io/rec.sh/
+#https://kunitsucom.github.io/log.sh/
-# LISENCE: https://github.com/kunitsuinc/rec.sh/blob/HEAD/LICENSE
+# LISENCE: https://github.com/kunitsucom/log.sh/blob/HEAD/LICENSE
# Common
-if [ -t 2 ]; then REC_COLOR=true; else REC_COLOR=''; fi
-_recRFC3339() { date "+%Y-%m-%dT%H:%M:%S%z" | sed "s/\(..\)$/:\1/"; }
-_recCmd() { for a in "$@"; do if echo "${a:-}" | grep -Eq "[[:blank:]]"; then printf "'%s' " "${a:-}"; else printf "%s " "${a:-}"; fi; done | sed "s/ $//"; }
+if [ "${LOGSH_COLOR:-}" ] || [ -t 2 ] ; then LOGSH_COLOR=true; else LOGSH_COLOR=''; fi
+_logshRFC3339() { date "+%Y-%m-%dT%H:%M:%S%z" | sed "s/\(..\)$/:\1/"; }
+_logshCmd() { for a in "$@"; do if echo "${a:-}" | grep -Eq "[[:blank:]]"; then printf "'%s' " "${a:-}"; else printf "%s " "${a:-}"; fi; done | sed "s/ $//"; }
# Color
-RecDefault() { test " ${REC_SEVERITY:-0}" -gt 000 2>/dev/null || echo "$*" | awk "{print \"$(_recRFC3339) [${REC_COLOR:+\\033[0;35m} DEFAULT${REC_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
-RecDebug() { test " ${REC_SEVERITY:-0}" -gt 100 2>/dev/null || echo "$*" | awk "{print \"$(_recRFC3339) [${REC_COLOR:+\\033[0;34m} DEBUG${REC_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
-RecInfo() { test " ${REC_SEVERITY:-0}" -gt 200 2>/dev/null || echo "$*" | awk "{print \"$(_recRFC3339) [${REC_COLOR:+\\033[0;32m} INFO${REC_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
-RecNotice() { test " ${REC_SEVERITY:-0}" -gt 300 2>/dev/null || echo "$*" | awk "{print \"$(_recRFC3339) [${REC_COLOR:+\\033[0;36m} NOTICE${REC_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
-RecWarning() { test " ${REC_SEVERITY:-0}" -gt 400 2>/dev/null || echo "$*" | awk "{print \"$(_recRFC3339) [${REC_COLOR:+\\033[0;33m} WARNING${REC_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
-RecError() { test " ${REC_SEVERITY:-0}" -gt 500 2>/dev/null || echo "$*" | awk "{print \"$(_recRFC3339) [${REC_COLOR:+\\033[0;31m} ERROR${REC_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
-RecCritical() { test " ${REC_SEVERITY:-0}" -gt 600 2>/dev/null || echo "$*" | awk "{print \"$(_recRFC3339) [${REC_COLOR:+\\033[0;1;31m} CRITICAL${REC_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
-RecAlert() { test " ${REC_SEVERITY:-0}" -gt 700 2>/dev/null || echo "$*" | awk "{print \"$(_recRFC3339) [${REC_COLOR:+\\033[0;41m} ALERT${REC_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
-RecEmergency() { test "${REC_SEVERITY:-0}" -gt 800 2>/dev/null || echo "$*" | awk "{print \"$(_recRFC3339) [${REC_COLOR:+\\033[0;1;41m}EMERGENCY${REC_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
-RecExec() { RecInfo "$ $(_recCmd "$@")" && "$@"; }
-RecRun() { _dlm="####R#E#C#D#E#L#I#M#I#T#E#R####" && _all=$({ _out=$("$@") && _rtn=$? || _rtn=$? && printf "\n%s" "${_dlm:?}${_out:-}" && return "${_rtn:-0}"; } 2>&1) && _rtn=$? || _rtn=$? && _dlmno=$(echo "${_all:-}" | sed -n "/${_dlm:?}/=") && _cmd=$(_recCmd "$@") && _stdout=$(echo "${_all:-}" | tail -n +"${_dlmno:-1}" | sed "s/^${_dlm:?}//") && _stderr=$(echo "${_all:-}" | head -n "${_dlmno:-1}" | grep -v "^${_dlm:?}") && RecInfo "$ ${_cmd:-}" && { [ -z "${_stdout:-}" ] || RecInfo "${_stdout:?}"; } && { [ -z "${_stderr:-}" ] || RecWarning "${_stderr:?}"; } && return "${_rtn:-0}"; }
+LogshDefault() { test " ${LOGSH_LEVEL:-0}" -gt 000 || echo "$*" | awk "{print \"$(_logshRFC3339) [${LOGSH_COLOR:+\\033[0;35m} DEFAULT${LOGSH_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
+LogshDebug() { test " ${LOGSH_LEVEL:-0}" -gt 100 || echo "$*" | awk "{print \"$(_logshRFC3339) [${LOGSH_COLOR:+\\033[0;34m} DEBUG${LOGSH_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
+LogshInfo() { test " ${LOGSH_LEVEL:-0}" -gt 200 || echo "$*" | awk "{print \"$(_logshRFC3339) [${LOGSH_COLOR:+\\033[0;32m} INFO${LOGSH_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
+LogshNotice() { test " ${LOGSH_LEVEL:-0}" -gt 300 || echo "$*" | awk "{print \"$(_logshRFC3339) [${LOGSH_COLOR:+\\033[0;36m} NOTICE${LOGSH_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
+LogshWarn() { test " ${LOGSH_LEVEL:-0}" -gt 400 || echo "$*" | awk "{print \"$(_logshRFC3339) [${LOGSH_COLOR:+\\033[0;33m} WARN${LOGSH_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
+LogshWarning() { test " ${LOGSH_LEVEL:-0}" -gt 400 || echo "$*" | awk "{print \"$(_logshRFC3339) [${LOGSH_COLOR:+\\033[0;33m} WARNING${LOGSH_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
+LogshError() { test " ${LOGSH_LEVEL:-0}" -gt 500 || echo "$*" | awk "{print \"$(_logshRFC3339) [${LOGSH_COLOR:+\\033[0;31m} ERROR${LOGSH_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
+LogshCritical() { test " ${LOGSH_LEVEL:-0}" -gt 600 || echo "$*" | awk "{print \"$(_logshRFC3339) [${LOGSH_COLOR:+\\033[0;1;31m} CRITICAL${LOGSH_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
+LogshAlert() { test " ${LOGSH_LEVEL:-0}" -gt 700 || echo "$*" | awk "{print \"$(_logshRFC3339) [${LOGSH_COLOR:+\\033[0;41m} ALERT${LOGSH_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
+LogshEmergency() { test "${LOGSH_LEVEL:-0}" -gt 800 || echo "$*" | awk "{print \"$(_logshRFC3339) [${LOGSH_COLOR:+\\033[0;1;41m}EMERGENCY${LOGSH_COLOR:+\\033[0m}] \"\$0\"\"}" 1>&2; }
+LogshExec() { LogshInfo "$ $(_logshCmd "$@")" && "$@"; }
+LogshRun() { _dlm="####R#E#C#D#E#L#I#M#I#T#E#R####" && _all=$({ _out=$("$@") && _rtn=$? || _rtn=$? && printf "\n%s" "${_dlm:?}${_out:-}" && return "${_rtn:-0}"; } 2>&1) && _rtn=$? || _rtn=$? && _dlmno=$(echo "${_all:-}" | sed -n "/${_dlm:?}/=") && _cmd=$(_logshCmd "$@") && _stdout=$(echo "${_all:-}" | tail -n +"${_dlmno:-1}" | sed "s/^${_dlm:?}//") && _stderr=$(echo "${_all:-}" | head -n "${_dlmno:-1}" | grep -v "^${_dlm:?}") && LogshInfo "$ ${_cmd:-}" && LogshInfo "${_stdout:-}" && { [ -z "${_stderr:-}" ] || LogshWarning "${_stderr:?}"; } && return "${_rtn:-0}"; }
# export functions for bash
# shellcheck disable=SC3045
-echo "${SHELL-}" | grep -q "bash$" && export -f _recRFC3339 _recCmd RecDefault RecDebug RecInfo RecWarning RecError RecCritical RecAlert RecEmergency RecExec RecRun
+echo "${SHELL-}" | grep -q "/?bash" && export -f _logshRFC3339 _logshCmd LogshDefault LogshDebug LogshInfo LogshWarning LogshError LogshCritical LogshAlert LogshEmergency LogshExec LogshRun || true
-# LISENCE: https://github.com/kunitsuinc/rec.sh/blob/HEAD/LICENSE
+# LISENCE: https://github.com/kunitsucom/log.sh/blob/HEAD/LICENSE
# Common
-_recRFC3339() { date "+%Y-%m-%dT%H:%M:%S%z" | sed "s/\(..\)$/:\1/"; }
-_recCmd() { for a in "$@"; do if echo "${a:-}" | grep -Eq "[[:blank:]]"; then printf "'%s' " "${a:-}"; else printf "%s " "${a:-}"; fi; done | sed "s/ $//"; }
+_logshRFC3339() { date "+%Y-%m-%dT%H:%M:%S%z" | sed "s/\(..\)$/:\1/"; }
+_logshCmd() { for a in "$@"; do if echo "${a:-}" | grep -Eq "[[:blank:]]"; then printf "'%s' " "${a:-}"; else printf "%s " "${a:-}"; fi; done | sed "s/ $//"; }
# JSON
-_recEscape() { printf %s "${1:-}" | sed "s/\"/\\\"/g; s/\r/\\\r/g; s/\t/\\\t/g; s/$/\\\n/g" | tr -d "[:cntrl:]" | sed "s/\\\n$/\n/"; }
-_recJSON() { _svr="${1:?}" && _msg="$(_recEscape "${2:-}")" && unset _fld _val && shift 2 && for a in "$@"; do if [ "${_val:-}" ]; then _fld="${_fld:?}:\"$(_recEscape "${a:-}")\"" && unset _val && continue; fi && _fld="${_fld:-}${_fld:+,}\"${a:?"json key is not set"}\"" && _val=1; done && test $(($# % 2)) = 1 && _fld="${_fld:?}:\"\"" || true && printf "{%s}\n" "\"${REC_TIMESTAMP_KEY:-timestamp}\":\"$(_recRFC3339)\",\"${REC_SEVERITY_KEY:-severity}\":\"${_svr:?}\",\"${REC_CALLER_KEY:-caller}\":\"$0\",\"${REC_MESSAGE_KEY:-message}\":\"${_msg:-}\"${_fld:+,}${_fld:-}"; }
-RecDefaultJSON() { test " ${REC_SEVERITY:-0}" -gt 000 2>/dev/null || _recJSON DEFAULT "$@" 1>&2; }
-RecDebugJSON() { test " ${REC_SEVERITY:-0}" -gt 100 2>/dev/null || _recJSON DEBUG "$@" 1>&2; }
-RecInfoJSON() { test " ${REC_SEVERITY:-0}" -gt 200 2>/dev/null || _recJSON INFO "$@" 1>&2; }
-RecNoticeJSON() { test " ${REC_SEVERITY:-0}" -gt 300 2>/dev/null || _recJSON NOTICE "$@" 1>&2; }
-RecWarningJSON() { test " ${REC_SEVERITY:-0}" -gt 400 2>/dev/null || _recJSON WARNING "$@" 1>&2; }
-RecErrorJSON() { test " ${REC_SEVERITY:-0}" -gt 500 2>/dev/null || _recJSON ERROR "$@" 1>&2; }
-RecCriticalJSON() { test " ${REC_SEVERITY:-0}" -gt 600 2>/dev/null || _recJSON CRITICAL "$@" 1>&2; }
-RecAlertJSON() { test " ${REC_SEVERITY:-0}" -gt 700 2>/dev/null || _recJSON ALERT "$@" 1>&2; }
-RecEmergencyJSON() { test "${REC_SEVERITY:-0}" -gt 800 2>/dev/null || _recJSON EMERGENCY "$@" 1>&2; }
-RecExecJSON() { RecInfoJSON "$ $(_recCmd "$@")" && "$@"; }
-RecRunJSON() { _dlm='####R#E#C#D#E#L#I#M#I#T#E#R####' && _all=$({ _out=$("$@") && _rtn=$? || _rtn=$? && printf "\n%s" "${_dlm:?}${_out:-}" && return "${_rtn:-0}"; } 2>&1) && _rtn=$? || _rtn=$? && _dlmno=$(echo "${_all:-}" | sed -n "/${_dlm:?}/=") && _cmd=$(_recCmd "$@") && _stdout=$(echo "${_all:-}" | tail -n +"${_dlmno:-1}" | sed "s/^${_dlm:?}//") && _stderr=$(echo "${_all:-}" | head -n "${_dlmno:-1}" | grep -v "^${_dlm:?}") && RecInfoJSON "$ ${_cmd:-}" command "${_cmd:-}" stdout "${_stdout:-}" stderr "${_stderr:-}" return "${_rtn:-0}" && return "${_rtn:-0}"; }
+_logshEscape() { printf %s "${1:-}" | sed "s/\"/\\\"/g; s/\r/\\\r/g; s/\t/\\\t/g; s/$/\\\n/g" | tr -d "[:cntrl:]" | sed "s/\\\n$/\n/"; }
+# NOTE: shift 2 -> ${1+shift} && ${1+shift} ... avoid "shift: can't shift that many" error
+_logshJSON() { _svr="${1:?}" && _msg="$(_logshEscape "${2:-}")" && unset _fld _val && ${1+shift} && ${1+shift} && for a in "$@"; do if [ "${_val:-}" ]; then _fld="${_fld:?}:\"$(_logshEscape "${a:-}")\"" && unset _val && continue; fi && _fld="${_fld:-}${_fld:+,}\"${a:?"json key is not set"}\"" && _val=1; done && test $(($# % 2)) = 1 && _fld="${_fld:?}:\"\"" || true && printf "{%s}\n" "\"${LOGSH_TIMESTAMP_KEY:-timestamp}\":\"$(_logshRFC3339)\",\"${LOGSH_LEVEL_KEY:-severity}\":\"${_svr:?}\",\"${LOGSH_CALLER_KEY:-caller}\":\"$0\",\"${LOGSH_MESSAGE_KEY:-message}\":\"${_msg:-}\"${_fld:+,}${_fld:-}"; }
+LogshDefaultJSON() { test " ${LOGSH_LEVEL:-0}" -gt 000 2>/dev/null || _logshJSON DEFAULT "$@" 1>&2; }
+LogshDebugJSON() { test " ${LOGSH_LEVEL:-0}" -gt 100 2>/dev/null || _logshJSON DEBUG "$@" 1>&2; }
+LogshInfoJSON() { test " ${LOGSH_LEVEL:-0}" -gt 200 2>/dev/null || _logshJSON INFO "$@" 1>&2; }
+LogshNoticeJSON() { test " ${LOGSH_LEVEL:-0}" -gt 300 2>/dev/null || _logshJSON NOTICE "$@" 1>&2; }
+LogshWarnJSON() { test " ${LOGSH_LEVEL:-0}" -gt 400 2>/dev/null || _logshJSON WARN "$@" 1>&2; }
+LogshWarningJSON() { test " ${LOGSH_LEVEL:-0}" -gt 400 2>/dev/null || _logshJSON WARNING "$@" 1>&2; }
+LogshErrorJSON() { test " ${LOGSH_LEVEL:-0}" -gt 500 2>/dev/null || _logshJSON ERROR "$@" 1>&2; }
+LogshCriticalJSON() { test " ${LOGSH_LEVEL:-0}" -gt 600 2>/dev/null || _logshJSON CRITICAL "$@" 1>&2; }
+LogshAlertJSON() { test " ${LOGSH_LEVEL:-0}" -gt 700 2>/dev/null || _logshJSON ALERT "$@" 1>&2; }
+LogshEmergencyJSON() { test "${LOGSH_LEVEL:-0}" -gt 800 2>/dev/null || _logshJSON EMERGENCY "$@" 1>&2; }
+LogshExecJSON() { LogshInfoJSON "$ $(_logshCmd "$@")" && "$@"; }
+LogshRunJSON() { _dlm='####R#E#C#D#E#L#I#M#I#T#E#R####' && _all=$({ _out=$("$@") && _rtn=$? || _rtn=$? && printf "\n%s" "${_dlm:?}${_out:-}" && return "${_rtn:-0}"; } 2>&1) && _rtn=$? || _rtn=$? && _dlmno=$(echo "${_all:-}" | sed -n "/${_dlm:?}/=") && _cmd=$(_logshCmd "$@") && _stdout=$(echo "${_all:-}" | tail -n +"${_dlmno:-1}" | sed "s/^${_dlm:?}//") && _stderr=$(echo "${_all:-}" | head -n "${_dlmno:-1}" | grep -v "^${_dlm:?}") && LogshInfoJSON "$ ${_cmd:-}" command "${_cmd:-}" stdout "${_stdout:-}" stderr "${_stderr:-}" return "${_rtn:-0}" && return "${_rtn:-0}"; }
# export functions for bash
# shellcheck disable=SC3045
-echo "${SHELL-}" | grep -q "bash$" && export -f _recRFC3339 _recCmd _recEscape _recJSON RecDefaultJSON RecDebugJSON RecInfoJSON RecNoticeJSON RecWarningJSON RecErrorJSON RecCriticalJSON RecAlertJSON RecEmergencyJSON RecExecJSON RecRunJSON
+echo "${SHELL-}" | grep -q "/?bash" && export -f _logshRFC3339 _logshCmd _logshEscape _logshJSON LogshDefaultJSON LogshDebugJSON LogshInfoJSON LogshNoticeJSON LogshWarningJSON LogshErrorJSON LogshCriticalJSON LogshAlertJSON LogshEmergencyJSON LogshExecJSON LogshRunJSON || true
-# (C) 2022 kunitsuinc
+# (C) 2022 kunitsucom
diff --git a/log.sh b/log.sh
new file mode 120000
index 0000000..64233a9
--- /dev/null
+++ b/log.sh
@@ -0,0 +1 @@
+index.html
\ No newline at end of file
diff --git a/rec.sh b/rec.sh
index 64233a9..b0590a5 120000
--- a/rec.sh
+++ b/rec.sh
@@ -1 +1 @@
-index.html
\ No newline at end of file
+log.sh
\ No newline at end of file
diff --git a/test.sh b/test.sh
index 5544a7c..12f604d 100755
--- a/test.sh
+++ b/test.sh
@@ -1,305 +1,28 @@
#!/bin/sh
set -e -u
-# shellcheck disable=SC1091
-. index.html
-
-export TZ=UTC REC_SEVERITY=0 REC_TIMESTAMP_KEY=timestamp REC_SEVERITY_KEY=severity REC_CALLER_KEY=caller REC_MESSAGE_KEY=message
-
-#
-# RecDefaultJSON
-#
-
-TestRecDefaultJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=0
- if ! RecDefaultJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"DEFAULT","caller":"./test.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'; then
- echo "FAIL: TestRecDefaultJSON_001"
- return 1
- fi
- echo "PASS: TestRecDefaultJSON_001"
-} && TestRecDefaultJSON_001
-
-TestRecDefaultJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=1
- if [ "$(RecDefaultJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)" ]; then
- echo "FAIL: TestRecDefaultJSON_002"
- return 1
- fi
- echo "PASS: TestRecDefaultJSON_002"
-} && TestRecDefaultJSON_002
-
-#
-# RecDebugJSON
-#
-
-TestRecDebugJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=100
- if ! RecDebugJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"DEBUG","caller":"./test.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'; then
- echo "FAIL: TestRecDebugJSON_001"
- return 1
- fi
- echo "PASS: TestRecDebugJSON_001"
-} && TestRecDebugJSON_001
-
-TestRecDebugJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=101
- if [ "$(RecDebugJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)" ]; then
- echo "FAIL: TestRecDebugJSON_002"
- return 1
- fi
- echo "PASS: TestRecDebugJSON_002"
-} && TestRecDebugJSON_002
-
-#
-# RecInfoJSON
-#
-
-TestRecInfoJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=200
- if ! RecInfoJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"INFO","caller":"./test.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'; then
- echo "FAIL: TestRecInfoJSON_001"
- return 1
- fi
- echo "PASS: TestRecInfoJSON_001"
-} && TestRecInfoJSON_001
-
-TestRecInfoJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=201
- if [ "$(RecInfoJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)" ]; then
- echo "FAIL: TestRecInfoJSON_002"
- return 1
- fi
- echo "PASS: TestRecInfoJSON_002"
-} && TestRecInfoJSON_002
-
-#
-# RecNoticeJSON
-#
-
-TestRecNoticeJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=300
- if ! RecNoticeJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"NOTICE","caller":"./test.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'; then
- echo "FAIL: TestRecNoticeJSON_001"
- return 1
- fi
- echo "PASS: TestRecNoticeJSON_001"
-} && TestRecNoticeJSON_001
-
-TestRecNoticeJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=301
- if [ "$(RecNoticeJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)" ]; then
- echo "FAIL: TestRecNoticeJSON_002"
- return 1
- fi
- echo "PASS: TestRecNoticeJSON_002"
-} && TestRecNoticeJSON_002
-
-#
-# RecWarningJSON
-#
-
-TestRecWarningJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=400
- if ! RecWarningJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"WARNING","caller":"./test.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'; then
- echo "FAIL: TestRecWarningJSON_001"
- return 1
- fi
- echo "PASS: TestRecWarningJSON_001"
-} && TestRecWarningJSON_001
-
-TestRecWarningJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=401
- if [ "$(RecWarningJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)" ]; then
- echo "FAIL: TestRecWarningJSON_002"
- return 1
- fi
- echo "PASS: TestRecWarningJSON_002"
-} && TestRecWarningJSON_002
-
-#
-# RecErrorJSON
-#
-
-TestRecErrorJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=500
- if ! RecErrorJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"ERROR","caller":"./test.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'; then
- echo "FAIL: TestRecErrorJSON_001"
- return 1
- fi
- echo "PASS: TestRecErrorJSON_001"
-} && TestRecErrorJSON_001
-
-TestRecErrorJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=501
- if [ "$(RecErrorJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)" ]; then
- echo "FAIL: TestRecErrorJSON_002"
- return 1
- fi
- echo "PASS: TestRecErrorJSON_002"
-} && TestRecErrorJSON_002
+cd "$(dirname "$0")"
-#
-# RecCriticalJSON
-#
-
-TestRecCriticalJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=600
- if ! RecCriticalJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"CRITICAL","caller":"./test.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'; then
- echo "FAIL: TestRecCriticalJSON_001"
- return 1
- fi
- echo "PASS: TestRecCriticalJSON_001"
-} && TestRecCriticalJSON_001
-
-TestRecCriticalJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=601
- if [ "$(RecCriticalJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)" ]; then
- echo "FAIL: TestRecCriticalJSON_002"
- return 1
- fi
- echo "PASS: TestRecCriticalJSON_002"
-} && TestRecCriticalJSON_002
-
-#
-# RecAlertJSON
-#
-
-TestRecAlertJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=700
- if ! RecAlertJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"ALERT","caller":"./test.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'; then
- echo "FAIL: TestRecAlertJSON_001"
- return 1
- fi
- echo "PASS: TestRecAlertJSON_001"
-} && TestRecAlertJSON_001
-
-TestRecAlertJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=701
- if [ "$(RecAlertJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)" ]; then
- echo "FAIL: TestRecAlertJSON_002"
- return 1
- fi
- echo "PASS: TestRecAlertJSON_002"
-} && TestRecAlertJSON_002
-
-#
-# RecEmergencyJSON
-#
-
-TestRecEmergencyJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=800
- if ! RecEmergencyJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"EMERGENCY","caller":"./test.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'; then
- echo "FAIL: TestRecEmergencyJSON_001"
- return 1
- fi
- echo "PASS: TestRecEmergencyJSON_001"
-} && TestRecEmergencyJSON_001
-
-TestRecEmergencyJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=801
- if [ "$(RecEmergencyJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)" ]; then
- echo "FAIL: TestRecEmergencyJSON_002"
- return 1
- fi
- echo "PASS: TestRecEmergencyJSON_002"
-} && TestRecEmergencyJSON_002
-
-#
-# RecExecJSON
-#
-
-TestRecExecJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=100
- if ! RecExecJSON true 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"INFO","caller":"./test.sh","message":". true"}$'; then
- echo "FAIL: TestRecExecJSON_001"
- return 1
- fi
- echo "PASS: TestRecExecJSON_001"
-} && TestRecExecJSON_001
-
-TestRecExecJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=201
- if [ "$(RecExecJSON true 2>&1)" ]; then
- echo "FAIL: TestRecExecJSON_002"
- return 1
- fi
- echo "PASS: TestRecExecJSON_002"
-} && TestRecExecJSON_002
-
-#
-# RecRunJSON
-#
-
-TestRecRunJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=100
- if ! RecRunJSON date +%Y-%m-%d 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"INFO","caller":"./test.sh","message":". date .%Y-%m-%d","command":"date .%Y-%m-%d","stdout":"[0-9]+-[0-9]+-[0-9]+","stderr":"","return":"0"}$'; then
- echo "FAIL: TestRecRunJSON_001"
- return 1
- fi
- echo "PASS: TestRecRunJSON_001"
-} && TestRecRunJSON_001
-
-TestRecRunJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=201
- if [ "$(RecRunJSON date +%Y-%m-%d 2>&1)" ]; then
- echo "FAIL: TestRecRunJSON_002"
- return 1
- fi
- echo "PASS: TestRecRunJSON_002"
-} && TestRecRunJSON_002
-
-#
-# common
-#
-
-TestCommonRecJSON_001() {
- unset REC_SEVERITY
- export REC_SEVERITY=0
- if ! RecDefaultJSON 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"DEFAULT","caller":"./test.sh","message":""}$'; then
- echo "FAIL: TestCommonRecJSON_001"
- return 1
- fi
- echo "PASS: TestCommonRecJSON_001"
-} && TestCommonRecJSON_001
-
-TestCommonRecJSON_002() {
- unset REC_SEVERITY
- export REC_SEVERITY=0
- if ! RecDefaultJSON "" testKey 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"DEFAULT","caller":"./test.sh","message":"","testKey":""}$'; then
- echo "FAIL: TestCommonRecJSON_002"
- return 1
- fi
- echo "PASS: TestCommonRecJSON_002"
-} && TestCommonRecJSON_002
-
-TestCommonRecJSON_003() {
- unset REC_SEVERITY
- export REC_SEVERITY=0
- if ! RecDefaultJSON "" testKey testValue 2>&1 | grep -Eq '^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"DEFAULT","caller":"./test.sh","message":"","testKey":"testValue"}$'; then
- echo "FAIL: TestCommonRecJSON_003"
- return 1
- fi
- echo "PASS: TestCommonRecJSON_003"
-} && TestCommonRecJSON_003
+# shellcheck disable=SC1091
+. ./index.html
+
+export TZ=UTC LOGSH_COLOR=true LOGSH_LEVEL=0 LOGSH_TIMESTAMP_KEY=timestamp LOGSH_LEVEL_KEY=severity LOGSH_CALLER_KEY=caller LOGSH_MESSAGE_KEY=message
+
+err=0
+
+LogshInfo "RUN: $0"
+trap 'if [ ${err:-0} -gt 0 ]; then
+ LogshError "FAIL: $0"
+ exit ${err:-1}
+else
+ LogshInfo "PASS: $0"
+ exit 0
+fi
+' EXIT
+
+# local
+./testcases.sh || err=$((err+$?))
+# ubuntu:22.04 dash
+docker run --rm -v "$(pwd -P)":"$(pwd -P)" -w "$(pwd -P)" ubuntu:22.04 dash ./testcases.sh || err=$((err+$?))
+# ubuntu:22.04 bash
+docker run --rm -v "$(pwd -P)":"$(pwd -P)" -w "$(pwd -P)" ubuntu:22.04 bash ./testcases.sh || err=$((err+$?))
diff --git a/testcases.sh b/testcases.sh
new file mode 100755
index 0000000..cb418ff
--- /dev/null
+++ b/testcases.sh
@@ -0,0 +1,467 @@
+#!/bin/sh
+set -e -u
+
+cd "$(dirname "$0")"
+
+# shellcheck disable=SC1091
+. ./index.html
+
+export TZ=UTC LOGSH_COLOR=true LOGSH_LEVEL=0 LOGSH_TIMESTAMP_KEY=timestamp LOGSH_LEVEL_KEY=severity LOGSH_CALLER_KEY=caller LOGSH_MESSAGE_KEY=message
+
+err=0
+
+# begin log
+LogshRun uname -a
+# end log
+LogshInfo "RUN: $0"
+trap 'if [ ${err:-0} -gt 0 ]; then
+ LogshError "FAIL: $0"
+ exit ${err:-1}
+else
+ LogshInfo "PASS: $0"
+ exit 0
+fi
+' EXIT
+
+#
+# LogshDefault
+#
+
+TestLogshDefault_001() {
+ LogshInfo " RUN: TestLogshDefault_001"
+ export LOGSH_LEVEL=0
+ expect='^[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00 \[.*DEFAULT.*\] LOG$'
+ actual=$(LogshDefault "LOG" 2>&1)
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshDefault_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshDefault_001"
+} && TestLogshDefault_001 || err=$((err+$?))
+
+TestLogshDefault_002() {
+ LogshInfo " RUN: TestLogshDefault_002"
+ export LOGSH_LEVEL=1
+ actual=$(LogshDefault "LOG" 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshDefault_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshDefault_002"
+} && TestLogshDefault_002 || err=$((err+$?))
+
+#
+# LogshDefaultJSON
+#
+
+TestLogshDefaultJSON_001() {
+ LogshInfo " RUN: TestLogshDefaultJSON_001"
+ export LOGSH_LEVEL=0
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"DEFAULT","caller":".+/testcases.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'
+ actual=$(LogshDefaultJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshDefaultJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshDefaultJSON_001"
+} && TestLogshDefaultJSON_001 || err=$((err+$?))
+
+TestLogshDefaultJSON_002() {
+ LogshInfo " RUN: TestLogshDefaultJSON_002"
+ export LOGSH_LEVEL=1
+ actual=$(LogshDefaultJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshDefaultJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshDefaultJSON_002"
+} && TestLogshDefaultJSON_002 || err=$((err+$?))
+
+#
+# LogshDebugJSON
+#
+
+TestLogshDebugJSON_001() {
+ LogshInfo " RUN: TestLogshDebugJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=100
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"DEBUG","caller":".+/testcases.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'
+ actual=$(LogshDebugJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshDebugJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshDebugJSON_001"
+} && TestLogshDebugJSON_001 || err=$((err+$?))
+
+TestLogshDebugJSON_002() {
+ LogshInfo " RUN: TestLogshDebugJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=101
+ actual=$(LogshDebugJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshDebugJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshDebugJSON_002"
+} && TestLogshDebugJSON_002 || err=$((err+$?))
+
+#
+# LogshInfoJSON
+#
+
+TestLogshInfoJSON_001() {
+ LogshInfo " RUN: TestLogshInfoJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=200
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"INFO","caller":".+/testcases.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'
+ actual=$(LogshInfoJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshInfoJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshInfoJSON_001"
+} && TestLogshInfoJSON_001 || err=$((err+$?))
+
+TestLogshInfoJSON_002() {
+ LogshInfo " RUN: TestLogshInfoJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=201
+ actual=$(LogshInfoJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshInfoJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshInfoJSON_002"
+} && TestLogshInfoJSON_002 || err=$((err+$?))
+
+#
+# LogshNoticeJSON
+#
+
+TestLogshNoticeJSON_001() {
+ LogshInfo " RUN: TestLogshNoticeJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=300
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"NOTICE","caller":".+/testcases.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'
+ actual=$(LogshNoticeJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshNoticeJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshNoticeJSON_001"
+} && TestLogshNoticeJSON_001 || err=$((err+$?))
+
+TestLogshNoticeJSON_002() {
+ LogshInfo " RUN: TestLogshNoticeJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=301
+ actual=$(LogshNoticeJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshNoticeJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshNoticeJSON_002"
+} && TestLogshNoticeJSON_002 || err=$((err+$?))
+
+#
+# LogshWarningJSON
+#
+
+TestLogshWarningJSON_001() {
+ LogshInfo " RUN: TestLogshWarningJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=400
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"WARNING","caller":".+/testcases.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'
+ actual=$(LogshWarningJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshWarningJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshWarningJSON_001"
+} && TestLogshWarningJSON_001 || err=$((err+$?))
+
+TestLogshWarningJSON_002() {
+ LogshInfo " RUN: TestLogshWarningJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=401
+ actual=$(LogshWarningJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshWarningJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshWarningJSON_002"
+} && TestLogshWarningJSON_002 || err=$((err+$?))
+
+#
+# LogshErrorJSON
+#
+
+TestLogshErrorJSON_001() {
+ LogshInfo " RUN: TestLogshErrorJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=500
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"ERROR","caller":".+/testcases.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'
+ actual=$(LogshErrorJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshErrorJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshErrorJSON_001"
+} && TestLogshErrorJSON_001 || err=$((err+$?))
+
+TestLogshErrorJSON_002() {
+ LogshInfo " RUN: TestLogshErrorJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=501
+ actual=$(LogshErrorJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshErrorJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshErrorJSON_002"
+} && TestLogshErrorJSON_002 || err=$((err+$?))
+
+#
+# LogshCriticalJSON
+#
+
+TestLogshCriticalJSON_001() {
+ LogshInfo " RUN: TestLogshCriticalJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=600
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"CRITICAL","caller":".+/testcases.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'
+ actual=$(LogshCriticalJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshCriticalJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshCriticalJSON_001"
+} && TestLogshCriticalJSON_001 || err=$((err+$?))
+
+TestLogshCriticalJSON_002() {
+ LogshInfo " RUN: TestLogshCriticalJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=601
+ actual=$(LogshCriticalJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshCriticalJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshCriticalJSON_002"
+} && TestLogshCriticalJSON_002 || err=$((err+$?))
+
+#
+# LogshAlertJSON
+#
+
+TestLogshAlertJSON_001() {
+ LogshInfo " RUN: TestLogshAlertJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=700
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"ALERT","caller":".+/testcases.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'
+ actual=$(LogshAlertJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshAlertJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshAlertJSON_001"
+} && TestLogshAlertJSON_001 || err=$((err+$?))
+
+TestLogshAlertJSON_002() {
+ LogshInfo " RUN: TestLogshAlertJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=701
+ actual=$(LogshAlertJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshAlertJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshAlertJSON_002"
+} && TestLogshAlertJSON_002 || err=$((err+$?))
+
+#
+# LogshEmergencyJSON
+#
+
+TestLogshEmergencyJSON_001() {
+ LogshInfo " RUN: TestLogshEmergencyJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=800
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"EMERGENCY","caller":".+/testcases.sh","message":"\\t\\nA\\t\\nB\\t\\nC\\t","test":"\\t\\nA\\t\\nB\\t\\nC\\t"}$'
+ actual=$(LogshEmergencyJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshEmergencyJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshEmergencyJSON_001"
+} && TestLogshEmergencyJSON_001 || err=$((err+$?))
+
+TestLogshEmergencyJSON_002() {
+ LogshInfo " RUN: TestLogshEmergencyJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=801
+ actual=$(LogshEmergencyJSON "$(printf "\t\nA\t\nB\t\nC\t\n")" "test" "$(printf "\t\nA\t\nB\t\nC\t\n")" 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshEmergencyJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshEmergencyJSON_002"
+} && TestLogshEmergencyJSON_002 || err=$((err+$?))
+
+#
+# LogshExecJSON
+#
+
+TestLogshExecJSON_001() {
+ LogshInfo " RUN: TestLogshExecJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=100
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"INFO","caller":".+/testcases.sh","message":". true"}$'
+ actual=$(LogshExecJSON true 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshExecJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshExecJSON_001"
+} && TestLogshExecJSON_001 || err=$((err+$?))
+
+TestLogshExecJSON_002() {
+ LogshInfo " RUN: TestLogshExecJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=201
+ actual=$(LogshExecJSON true 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshExecJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshExecJSON_002"
+} && TestLogshExecJSON_002 || err=$((err+$?))
+
+#
+# LogshRunJSON
+#
+
+TestLogshRunJSON_001() {
+ LogshInfo " RUN: TestLogshRunJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=100
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"INFO","caller":".+/testcases.sh","message":". date .%Y-%m-%d","command":"date .%Y-%m-%d","stdout":"[0-9]+-[0-9]+-[0-9]+","stderr":"","return":"0"}$'
+ actual=$(LogshRunJSON date +%Y-%m-%d 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestLogshRunJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshRunJSON_001"
+} && TestLogshRunJSON_001 || err=$((err+$?))
+
+TestLogshRunJSON_002() {
+ LogshInfo " RUN: TestLogshRunJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=201
+ actual=$(LogshRunJSON date +%Y-%m-%d 2>&1)
+ unset LOGSH_LEVEL
+ if [ "${actual:-}" ]; then
+ LogshError " FAIL: TestLogshRunJSON_002"
+ return 1
+ fi
+ LogshInfo " PASS: TestLogshRunJSON_002"
+} && TestLogshRunJSON_002 || err=$((err+$?))
+
+#
+# common
+#
+
+TestCommonLogshJSON_001() {
+ LogshInfo " RUN: TestCommonLogshJSON_001"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=0
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"DEFAULT","caller":".+/testcases.sh","message":""}$'
+ actual=$(LogshDefaultJSON 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestCommonLogshJSON_001"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestCommonLogshJSON_001"
+} && TestCommonLogshJSON_001 || err=$((err+$?))
+
+TestCommonLogshJSON_002() {
+ LogshInfo " RUN: TestCommonLogshJSON_002"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=0
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"DEFAULT","caller":".+/testcases.sh","message":"","testKey":""}$'
+ actual=$(LogshDefaultJSON "" testKey 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestCommonLogshJSON_002"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestCommonLogshJSON_002"
+} && TestCommonLogshJSON_002 || err=$((err+$?))
+
+TestCommonLogshJSON_003() {
+ LogshInfo " RUN: TestCommonLogshJSON_003"
+ unset LOGSH_LEVEL
+ export LOGSH_LEVEL=0
+ expect='^{"timestamp":"[0-9]+-[0-9]+-[0-9]+T[0-9]+:[0-9]+:[0-9]+.00:00","severity":"DEFAULT","caller":".+/testcases.sh","message":"","testKey":"testValue"}$'
+ actual=$(LogshDefaultJSON "" testKey testValue 2>&1)
+ unset LOGSH_LEVEL
+ if ! printf "%s" "${actual-}" | grep -Eq "$(printf "%s" "${expect}")" ; then
+ LogshError " FAIL: TestCommonLogshJSON_003"
+ printf " expect: %s\n" "${expect}"
+ printf " actual: %s\n" "${actual-}"
+ return 1
+ fi
+ LogshInfo " PASS: TestCommonLogshJSON_003"
+} && TestCommonLogshJSON_003