From 73dc9aee9e9b8ce907dbfb3842a1e606ae0930de Mon Sep 17 00:00:00 2001 From: yukkop Date: Tue, 9 Dec 2025 03:47:27 +0000 Subject: [PATCH] feat(`package`): `hemar`: json_escape() --- package/hemar/.gitignore | 1 + package/hemar/grammar/antlr/GoodTry.g4 | 28 --- package/hemar/grammar/antlr/HemarLexer.g4 | 49 ---- package/hemar/grammar/antlr/HemarParser.g4 | 18 -- package/hemar/grammar/antlr/_Hemar.g4 | 149 ----------- package/hemar/grammar/antlr/default.nix | 36 --- package/hemar/parser/default.nix | 15 +- package/hemar/parser/hemar.sh | 235 ++++++++++-------- .../hemar/parser/src/plex/backend/env_var.sh | 70 ------ package/hemar/parser/src/plex/backend/file.sh | 50 ---- .../hemar/parser/src/plex/backend/yq-go.sh | 40 --- package/hemar/parser/src/plex/plex.sh | 21 -- package/hemar/parser/test.sh | 6 - .../parser/test/plex/env_backend_time.sh | 112 --------- package/hemar/parser/test/plex/jq_backend.sh | 19 -- .../hemar/parser/test/plex/jq_backend_time.sh | 128 ---------- test/package/hemar/default.nix | 2 +- test/package/hemar/lauch.sh | 2 - .../hemar/test/function-json-escape.sh | 126 ++++++++++ 19 files changed, 264 insertions(+), 843 deletions(-) create mode 100644 package/hemar/.gitignore delete mode 100644 package/hemar/grammar/antlr/GoodTry.g4 delete mode 100644 package/hemar/grammar/antlr/HemarLexer.g4 delete mode 100644 package/hemar/grammar/antlr/HemarParser.g4 delete mode 100644 package/hemar/grammar/antlr/_Hemar.g4 delete mode 100644 package/hemar/grammar/antlr/default.nix delete mode 100644 package/hemar/parser/src/plex/backend/env_var.sh delete mode 100644 package/hemar/parser/src/plex/backend/file.sh delete mode 100644 package/hemar/parser/src/plex/backend/yq-go.sh delete mode 100644 package/hemar/parser/src/plex/plex.sh delete mode 100644 package/hemar/parser/test.sh delete mode 100644 package/hemar/parser/test/plex/env_backend_time.sh delete mode 100644 package/hemar/parser/test/plex/jq_backend.sh delete mode 100644 package/hemar/parser/test/plex/jq_backend_time.sh create mode 100644 test/package/hemar/test/function-json-escape.sh diff --git a/package/hemar/.gitignore b/package/hemar/.gitignore new file mode 100644 index 0000000..0fbb5a8 --- /dev/null +++ b/package/hemar/.gitignore @@ -0,0 +1 @@ +SUMMARY.md \ No newline at end of file diff --git a/package/hemar/grammar/antlr/GoodTry.g4 b/package/hemar/grammar/antlr/GoodTry.g4 deleted file mode 100644 index 8db8c6c..0000000 --- a/package/hemar/grammar/antlr/GoodTry.g4 +++ /dev/null @@ -1,28 +0,0 @@ -grammar Hemar; - -// ----------------- parser rules ----------------- - -hemar: elements? EOF ; - -elements: element+ ; - -element - : segment - | interpoltion - ; - -segment : for elements? end ; - -for : 'for' 'in' ; - -end: 'end' ; - -interpoltion : 'mcha' ; - -OPEN : '{[' ; -CLOSE : ']}' ; - -WS : [ \t\n\r]+ -> skip ; -LEADING_TEXT : { getCharPositionInLine() == 0 }? (~'{'|'{'~'[')* OPEN -> skip; -MIDLE_TEXT : CLOSE (~'{'|'{'~'[')* OPEN -> skip; -ENDING_TEXT : CLOSE (~'{'|'{'~'[')* EOF -> skip ; diff --git a/package/hemar/grammar/antlr/HemarLexer.g4 b/package/hemar/grammar/antlr/HemarLexer.g4 deleted file mode 100644 index f7abdcc..0000000 --- a/package/hemar/grammar/antlr/HemarLexer.g4 +++ /dev/null @@ -1,49 +0,0 @@ -lexer grammar HemarLexer; - -// ---------- default mode: plain text ---------- - -// Everything that is not the start of "{[" is TEXT -TEXT - : ( ~'{' | '{' ~'[' )+ - ; - -// When we see "{[", emit LeftBrace and enter TAG mode -LeftBrace - : '{[' -> pushMode(TAG) - ; - -// skip whitespace in plain text if you want -SKIP_WS - : [ \t\r\n]+ -> skip - ; - -// ---------- TAG mode: inside {[ ... ]} ---------- - -mode TAG; - -fragment WS: [ \t\r\n] ; - -For : 'for'; -In : 'in'; -End : 'end'; - -// identifier inside tag -Path - : String - | String '.' Path - ; - -String - : ( ~[.\] \t\r\n] | ']' ~[}. \t\r\n] )+ - | '"' ( ~'"' | '\\' '"' )+ '"' - ; - -// closing "]}": emit RightBrace and go back to default mode -RightBrace - : ']}' -> popMode - ; - -// skip whitespace inside tag -SKIP_TAG_WS - : WS+ -> skip - ; diff --git a/package/hemar/grammar/antlr/HemarParser.g4 b/package/hemar/grammar/antlr/HemarParser.g4 deleted file mode 100644 index 319080c..0000000 --- a/package/hemar/grammar/antlr/HemarParser.g4 +++ /dev/null @@ -1,18 +0,0 @@ -parser grammar HemarParser; - -options { tokenVocab=HemarLexer; } - -hemar : element*? EOF ; - -element - : TEXT - | segment - | interpoltion - ; - -segment : for element*? end; - -for : LeftBrace For Path In Path RightBrace; -end : LeftBrace End RightBrace; - -interpoltion : LeftBrace Path RightBrace; diff --git a/package/hemar/grammar/antlr/_Hemar.g4 b/package/hemar/grammar/antlr/_Hemar.g4 deleted file mode 100644 index d7a7e5f..0000000 --- a/package/hemar/grammar/antlr/_Hemar.g4 +++ /dev/null @@ -1,149 +0,0 @@ -grammar Hemar; - -// ----------------- parser rules ----------------- - -hemar - : elements? EOF - ; - -elements - : element+ - ; - -element - : tag - | TEXT - ; - -// tag -tag - : OPEN path CLOSE - | OPEN loopStatement CLOSE - | OPEN includeHeader CLOSE - | OPEN 'end' CLOSE - | OPEN function CLOSE - | OPEN OPEN CLOSE // literal "{[" output - ; - -// loop tag: "for" string "in" path -loopStatement - : 'for' STRING 'in' path - ; - -// include tag: "include" path -includeHeader - : 'include' path - ; - -// function tag -function - : 'compute' language functionBody? // "compute" language body - | 'compute' '-' functionBody? // "compute" - body - ; - -language - : 'dash' - | 'plpgsql' - ; - -// everything up to (but not including) "]}" -// (raw body, including "{[" etc, at *token* level) -functionBody - : ( ~CLOSE )* - ; - -// path -path - : '.' - | segmentedPath - ; - -segmentedPath - : segment ('.' segment)* - ; - -segment - : STRING - | index - ; - -// index: \0 .. \9, \1.. \9\d*, and negative forms -index - : '\\' DIGIT - | '\\' ONENINE DIGITS? - | '\\' '-' DIGIT - | '\\' '-' ONENINE DIGITS? - ; - -// ----------------- lexer rules ----------------- - -OPEN : '{['; -CLOSE : ']}'; - -// text outside tags: anything except the "{[" sequence -TEXT - : TEXT_CHAR+ - ; - -/* - * Strings used in paths/loop variables: - * "..." with escapes similar to your spec. - */ -STRING - : '"' ( ESC | STRING_CHAR )* '"' - ; - -fragment STRING_CHAR - : ~["\\\r\n] - ; - -/* - * Escapes: - * . (literal dot) - * ]} (literal "]}") -- note this is two chars after '\' - * " \" - * \ \\ - * / \/ - * b f n r t - * uXXXX (hex) - * whitespace after backslash (your ws-in-escape) - */ -fragment ESC - : '\\' - ( - '.' - | ']}' - | '"' - | '\\' - | '/' - | 'b' - | 'f' - | 'n' - | 'r' - | 't' - | 'u' HEX HEX HEX HEX - | WS_CHAR - ) - ; - -// digits / hex -DIGITS : DIGIT+ ; -DIGIT : [0-9] ; -ONENINE: [1-9] ; -HEX : [0-9a-fA-F] ; - -// whitespace for normal lexing -WS - : [ \t\r\n]+ -> skip - ; - -// whitespace used inside escapes -fragment WS_CHAR - : [ \t\r\n] - ; - - -fragment TEXT_CHAR - : ~'{' // any except '{' - | '{' ~'[' // '{' only if not starting OPEN - ; diff --git a/package/hemar/grammar/antlr/default.nix b/package/hemar/grammar/antlr/default.nix deleted file mode 100644 index a3fcb89..0000000 --- a/package/hemar/grammar/antlr/default.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ stdenv, symlinkJoin, jre, antlr4, runtimeShell, jdk }: - -let - hemar-grammar = stdenv.mkDerivation { - pname = "hemar-grammar"; - version = "0.1.0"; - - src = ./.; # directory with Hemar.g4 - - nativeBuildInputs = [ - antlr4 - jdk - ]; - - buildPhase = '' - antlr4 HemarLexer.g4 HemarParser.g4 - javac *.java - ''; - - installPhase = '' - mkdir -p "$out/lib" "$out/bin" - cp *.class *.tokens "$out/lib" - - cat > "$out/bin/hemar-grammar" < bool is_ws() { @@ -187,15 +173,38 @@ buf_reset() { CURRENT_STAGE_BUFFER="$STAGE_BUFFER_1" } -STAGE_BUFFER_1="$(mktemp)" -CURRENT_STAGE_BUFFER=$STAGE_BUFFER_1 -trap 'rm -f "$STAGE_BUFFER_1"' EXIT INT HUP -log debug "stage buffer 1: ${WHITE}$STAGE_BUFFER_1" - # json_escape(value) -> str json_escape() { - # TODO: escape functionality - printf '%s' "${1}" | sed 's/"/\\"/g' + local input="${1}" + local output="" + local char hex + + while [ -n "$input" ]; do + char="${input%"${input#?}"}" # Get first character + input="${input#?}" # Remove first character + + hex=$(printf '%d' "'$char") + + case "$hex" in + 34) output="${output}\\\"" ;; # " + 92) output="${output}\\\\" ;; # \ + 10) output="${output}\\n" ;; # \n (newline) + 13) output="${output}\\r" ;; # \r (carriage return) + 9) output="${output}\\t" ;; # \t (tab) + 8) output="${output}\\b" ;; # \b (backspace) + 12) output="${output}\\f" ;; # \f (form feed) + *) + # NOTE(yukkop): escape control characters if they are not in the range 0x20-0x7E + if [ "$hex" -lt 32 ]; then + output="${output}\\u$(printf '%04x' "$hex")" + else + output="${output}${char}" + fi + ;; + esac + done + + printf '%s' "$output" } # finds close pattern and store the char to the stage buffers separating by spaces @@ -489,67 +498,93 @@ parse() { esac } -while [ $# -gt 0 ]; do - case $1 in - -c|--compact-output) - OUTPUT_ARGS="${OUTPUT_ARGS+$OUTPUT_ARGS }-I=0" - shift - ;; - --*|-*) - log error "argument $1 does not exists" - exit 9 - ;; - *) - log error "subcommand $1 does not exists" - exit 9 - ;; - esac -done -CHAR_N=1 -LINE_N=1 +if [ -z "${AS_LIBRARY+x}" ]; then + log notice "running" -while :; do - hex="$(dd bs=1 count=1 2>/dev/null | od -An -t u1)" + AST=$(mktemp) + AST_key='.' + trap 'rm -f "$AST"' EXIT INT HUP - [ -z "$hex" ] && { - break - } + yq -o j -i '.' "$AST" - # shellcheck disable=SC2059 - char="$(printf "\\$(printf '%03o' "$hex")")" + log debug "AST path: ${WHITE}${AST}" - # NOTE: if $char is empty, it because `dd` returned '\n' but `$(...)` - # removed it as trailing '\n', so I set $char as '\n' here - [ -z "$char" ] && { - LINE_N=$((LINE_N+1)) - char=' + # 0 - text + # 1 - deside tag type + # 2 - interpolation + # 3 - section + # 4 - include + # 5 - compute + STAGE=0 + + STAGE_BUFFER_1="$(mktemp)" + CURRENT_STAGE_BUFFER=$STAGE_BUFFER_1 + trap 'rm -f "$STAGE_BUFFER_1"' EXIT INT HUP + log debug "stage buffer 1: ${WHITE}$STAGE_BUFFER_1" + + while [ $# -gt 0 ]; do + case $1 in + -c|--compact-output) + OUTPUT_ARGS="${OUTPUT_ARGS+$OUTPUT_ARGS }-I=0" + shift + ;; + --*|-*) + log error "argument $1 does not exists" + exit 9 + ;; + *) + log error "subcommand $1 does not exists" + exit 9 + ;; + esac + done + + CHAR_N=1 + LINE_N=1 + + while :; do + hex="$(dd bs=1 count=1 2>/dev/null | od -An -t u1)" + + [ -z "$hex" ] && { + break + } + + # shellcheck disable=SC2059 + char="$(printf "\\$(printf '%03o' "$hex")")" + + # NOTE: if $char is empty, it because `dd` returned '\n' but `$(...)` + # removed it as trailing '\n', so I set $char as '\n' here + [ -z "$char" ] && { + LINE_N=$((LINE_N+1)) + char=' ' - } + } - log trace "char: $WHITE$char" + log trace "char: $WHITE$char" - parse "${char:?}" + parse "${char:?}" - CHAR_N=$((CHAR_N+1)) -done + CHAR_N=$((CHAR_N+1)) + done -log debug 'finishing' + log debug 'finishing' -# finish TEXT tag if file ends on it -if [ "$STAGE" -eq 0 ]; then - if [ "${open_tag_flag+x}" ]; then - unset open_tag_flag - printf '{' >> "$STAGE_BUFFER_1" - fi + # finish TEXT tag if file ends on it + if [ "$STAGE" -eq 0 ]; then + if [ "${open_tag_flag+x}" ]; then + unset open_tag_flag + printf '{' >> "$STAGE_BUFFER_1" + fi - buf=$(cat "$STAGE_BUFFER_1") - yq -o j -i "$AST_key += [{ - \"type\": \"text\", - \"value\": \"$(json_escape "$buf")\" - }]" "$AST" -fi + buf=$(cat "$STAGE_BUFFER_1") + yq -o j -i "$AST_key += [{ + \"type\": \"text\", + \"value\": \"$(json_escape "$buf")\" + }]" "$AST" + fi -# return the output -# shellcheck disable=SC2086 -yq ${OUTPUT_ARGS:-} -o j "$AST" + # return the output + # shellcheck disable=SC2086 + yq ${OUTPUT_ARGS:-} -o j "$AST" +fi \ No newline at end of file diff --git a/package/hemar/parser/src/plex/backend/env_var.sh b/package/hemar/parser/src/plex/backend/env_var.sh deleted file mode 100644 index 118609b..0000000 --- a/package/hemar/parser/src/plex/backend/env_var.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/dash - -plex_set() { - local structname key val regex base esc_key regex esc temp - structname=$1 key=$2 val=$3 - - # construct regex for ancestors - regex="^$key=" - - base=$key - while expr "$base" : '.*\.' >/dev/null; do - base=$(printf '%s\n' "$base" | sed 's/\.[^.]*$//') - esc=$(printf '%s\n' "$base" | sed 's/\./\\./g') - regex="$regex|^$esc=" - done - - # add descendants - esc_key="$(printf '%s\n' "$key" | sed 's/\./\\./g')" - regex="$regex|^${esc_key}\." - - # remove old - # =$(printf '%s\n' "$" | grep -v -E "$regex") - temp="$(eval "printf '%s\\n' \"\$$structname\"" | grep -v -E "$regex")" - eval "$structname=\"\$temp\"" - - # add new - eval "$structname=\$(printf '%s\\n%s=%s\\n' \"\$$structname\" \"\$key\" \"\$val\")" -} - -plex_child() { - local structname prefix - structname=$1 prefix=$2 - - eval printf '%s\\n' \"\$"$structname"\" \ - | grep "^$prefix\." \ - | sed "s|^$prefix\.||" -} - -plex_val() { - local structname key - structname=$1 key=$2 - eval printf '%s\n' \"\$"$structname"\" | grep "^$key=" | cut -d= -f2- -} - -plex_fetch() { - local structname key - structname=$1 key=$2 - if eval printf '%s\\n' \"\$"$structname"\" | grep -q "^$key="; then - eval printf '%s\\n' \"\$"$structname"\" | grep "^$key=" | cut -d= -f2- - else - eval printf '%s\\n' \"\$"$structname"\" | grep "^$key\." | sed "s|^$key\.||" - fi -} - -plex_push() { - local structname prefix val max idx newidx kv - structname=${1:?} - prefix=${2:?} - val=${3:?} - - # find max index - max=0 - for kv in $(plex_fetch "$structname" "$prefix"); do - idx=${kv%%=*} - [ "$idx" -gt "$max" ] 2>/dev/null && max=$idx - done - - newidx=$((max + 1)) - plex_set "$structname" "$prefix.$newidx" "$val" -} diff --git a/package/hemar/parser/src/plex/backend/file.sh b/package/hemar/parser/src/plex/backend/file.sh deleted file mode 100644 index 1404dc6..0000000 --- a/package/hemar/parser/src/plex/backend/file.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/dash - -PLEX_TEMP="$(mktemp -d)" - -#plex_set(name, key, value) -plex_set() { - local plexfile key val regex base esc_key esc - plexfile="${PLEX_TEMP:?}${1:?}" key="${2:?}" val="${3:?}" - - find PLEX_ -} - -plex_child() { - local plexfile key - plexfile="${PLEX_TEMP:?}${1:?}" key="${2:?}" - - grep "^$key\." "" | sed "s|^$key\.||" -} - -plex_val() { - local plexfile key - plexfile="${PLEX_TEMP:?}${1:?}" key="${2:?}" - grep "^$key=" | cut -d= -f2- "$plexfile" -} - -plex_fetch() { - local plexfile key temp - plexfile="${PLEX_TEMP:?}${1:?}" key="${2:?}" - - if temp="$(grep "^$key=" | cut -d= -f2- "$plexfile")"; then - printf '%s' "$temp" - else - grep "^$key\." "" | sed "s|^$key\.||" - fi -} - -plex_push() { - local plex prefix val max idx newidx kv - plex="${1:?}" prefix="${2:?}" val="${3:?}" - - # find max index - max=0 - for kv in $(plex_fetch "$plex" "$prefix"); do - idx=${kv%%=*} - [ "$idx" -gt "$max" ] 2>/dev/null && max=$idx - done - - newidx=$((max + 1)) - plex_set "$plex" "$prefix.$newidx" "$val" -} diff --git a/package/hemar/parser/src/plex/backend/yq-go.sh b/package/hemar/parser/src/plex/backend/yq-go.sh deleted file mode 100644 index 6787b4e..0000000 --- a/package/hemar/parser/src/plex/backend/yq-go.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/dash - -PLEX_TEMP="$(mktemp -d)" -trap 'rm -rf $PLEX_TEMP' EXIT - -#plex_set(name, key, value) -plex_set() { - local plexfile key val - plexfile="${PLEX_TEMP:?}/${1:?}.json" key="${2:?}" val="${3:?}" - - touch "$plexfile" - - yq -i ".$key = \"$val\"" "$plexfile" -} - -#plex_child(name, key) -plex_child() { - plex_fetch "${1:?}" "${2:?}" -} - -#plex_val(name, key) -plex_val() { - plex_fetch "${1:?}" "${2:?}" -} - -#plex_val(name, key) -plex_fetch() { - local plexfile key - plexfile="${PLEX_TEMP:?}/${1:?}.json" key="${2:?}" - - yq -r ".$key" "$plexfile" -} - -#plex_push(name, prefix, val) -plex_push() { - local plexfile prefix val - plexfile="${PLEX_TEMP:?}/${1:?}.json" prefix="${2:?}" val="${3:?}" - - yq -i ".$prefix += [\"$val\"]" "$plexfile" -} diff --git a/package/hemar/parser/src/plex/plex.sh b/package/hemar/parser/src/plex/plex.sh deleted file mode 100644 index 01919a0..0000000 --- a/package/hemar/parser/src/plex/plex.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/dash - -init_plex() { - local backend - backend=${1:?} - - case "$backend" in - env) - . ${WORKSPACE}/src/plex/backend/env_var.sh - ;; - file) - . ${WORKSPACE}/src/plex/backend/file.sh - ;; - yq-go) - . ${WORKSPACE}/src/plex/backend/yq-go.sh - ;; - *) - exit 1 - ;; - esac -} diff --git a/package/hemar/parser/test.sh b/package/hemar/parser/test.sh deleted file mode 100644 index 317839f..0000000 --- a/package/hemar/parser/test.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/dash - -# shellcheck disable=SC1091 -#. "${WORKSPACE:?}/test/plex/jq_backend_time.sh" -#. "${WORKSPACE:?}/test/plex/env_backend_time.sh" -. "${WORKSPACE:?}/test/plex/jq_backend.sh" diff --git a/package/hemar/parser/test/plex/env_backend_time.sh b/package/hemar/parser/test/plex/env_backend_time.sh deleted file mode 100644 index 1c2666f..0000000 --- a/package/hemar/parser/test/plex/env_backend_time.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/dash - -. "${WORKSPACE:?}/src/plex/plex.sh" -init_plex env - -MY_STRUCT='' - -math() { - awk "BEGIN {print $1}" -} - -elapsed() { - local task time count decrease avg - task=$1 - time=$2 - count=$3 - decrease=${4:-0} - avg=$(math "$time/$count-$decrease") - - printf '\n[%s]\nelapsed %s seconds\n%s per second\n' \ - "$task" "$avg" "$(math "1/$avg")" >&2 - printf '%s' "$avg" -} - -set_word_length() { - local length - length=${1:?} - - # shellcheck disable=SC2183 - __WORD_OFFSET_PATERN="$(printf '%*s' "$length" | tr ' ' '?')" -} - -UNIQ_8_WORDS_COUNT=1000 -DEFAULT_WORD_LENGTH=8 -set_word_length "$DEFAULT_WORD_LENGTH" - -randomword() { - local length - length=${1:-$DEFAULT_WORD_LENGTH} - LC_ALL=C tr -dc 'A-Za-z0-9' /dev/null -} - -DEFAULT_TRIES=1000 -ACCURATE_TRIES=10000 -SUPPER_ACCURATE_TRIES=100000 - -WORD_CREATE_ACCURACY="$ACCURATE_TRIES" -BENCH_ACCURACY="$DEFAULT_TRIES" - -count="$WORD_CREATE_ACCURACY" -set_word_length 8 -i=0 -start=$(date +%s) -while [ "$i" -lt "${count:?}" ]; do - new_word >/dev/null - i=$((i + 1)) -done -end=$(date +%s) -wordtime=$(elapsed 'Word creation' "$((end - start))" "$count") - -bench_set 'Set element with depth 1 length 8' 1 "$BENCH_ACCURACY" "$wordtime" -bench_set 'Set element with depth 2 length 8' 2 "$BENCH_ACCURACY" "$wordtime" -bench_set 'Set element with depth 3 length 8' 3 "$BENCH_ACCURACY" "$wordtime" - -count="$WORD_CREATE_ACCURACY" -set_word_length 2 -i=0 -start=$(date +%s) -while [ "$i" -lt "${count:?}" ]; do - new_word >/dev/null - i=$((i + 1)) -done -end=$(date +%s) -wordtime=$(elapsed 'Word creation' "$((end - start))" "$count") - -bench_set 'Set element with depth 1 length 2' 1 "$BENCH_ACCURACY" "$wordtime" -bench_set 'Set element with depth 2 length 2' 2 "$BENCH_ACCURACY" "$wordtime" -bench_set 'Set element with depth 3 length 2' 3 "$BENCH_ACCURACY" "$wordtime" - diff --git a/package/hemar/parser/test/plex/jq_backend.sh b/package/hemar/parser/test/plex/jq_backend.sh deleted file mode 100644 index c4c02b3..0000000 --- a/package/hemar/parser/test/plex/jq_backend.sh +++ /dev/null @@ -1,19 +0,0 @@ -. "${WORKSPACE:?}/src/plex/plex.sh" -init_plex yq-go - -plex_set ZALUPA zalupa apulaz -log error "struct:\n$WHITE$(yq . "$PLEX_TEMP/ZALUPA.json")$NC" - -plex_set ZALUPA kek.zalupa apulaz - -log error "struct:\n$WHITE$(yq . "$PLEX_TEMP/ZALUPA.json")$NC" - -plex_set ZALUPA zalupa apulaz - -log error "struct:\n$WHITE$(yq . "$PLEX_TEMP/ZALUPA.json")$NC" - -plex_val ZALUPA zalupa - -plex_child ZALUPA kek - -plex_fetch ZALUPA kek diff --git a/package/hemar/parser/test/plex/jq_backend_time.sh b/package/hemar/parser/test/plex/jq_backend_time.sh deleted file mode 100644 index 02b83df..0000000 --- a/package/hemar/parser/test/plex/jq_backend_time.sh +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/dash - -# shellcheck disable=SC1091 -. "${WORKSPACE:?}/src/plex/plex.sh" -init_plex yq-go - -math() { - awk "BEGIN {print $1}" -} - -elapsed() { - local task time count decrease avg - task=$1 - time=$2 - count=$3 - decrease=${4:-0} - avg=$(math "$time/$count-$decrease") - - if [ "$time" -eq 0 ]; then - log info "\n[$WHITE${task}$NC]\ninstant\n" - else - log info "\n[$WHITE${task}$NC]\nelapsed $WHITE${avg}$NC seconds\n$WHITE$(math "1/$avg")$NC per second\n" - fi - printf '%s' "$avg" -} - -set_word_length() { - local length - length=${1:?} - - # shellcheck disable=SC2183 - __WORD_OFFSET_PATERN="$(printf '%*s' "$length" | tr ' ' '?')" -} - -UNIQ_8_WORDS_COUNT=1000 -DEFAULT_WORD_LENGTH=8 -set_word_length "$DEFAULT_WORD_LENGTH" - -randomword() { - local length - length=${1:-$DEFAULT_WORD_LENGTH} - LC_ALL=C tr -dc 'A-Za-z0-9' /dev/null -} - -DEFAULT_TRIES=1000 -ACCURATE_TRIES=10000 -SUPPER_ACCURATE_TRIES=100000 - -WORD_CREATE_ACCURACY="$SUPPER_ACCURATE_TRIES" -BENCH_ACCURACY="$DEFAULT_TRIES" - -count="$WORD_CREATE_ACCURACY" -set_word_length 8 -i=0 -start=$(date +%s) -while [ "$i" -lt "${count:?}" ]; do - new_word >/dev/null - i=$((i + 1)) -done -end=$(date +%s) -time=$((end - start)) -log debug "word creation time: $time" -wordtime=$(elapsed 'Word creation' "$time" "$count") - -bench_set 'Set element with depth 1 length 8' 1 "$BENCH_ACCURACY" "$wordtime" -bench_set 'Set element with depth 2 length 8' 2 "$BENCH_ACCURACY" "$wordtime" -bench_set 'Set element with depth 3 length 8' 3 "$BENCH_ACCURACY" "$wordtime" - -log notice - - -count="$WORD_CREATE_ACCURACY" -set_word_length 2 -i=0 -start=$(date +%s) -while [ "$i" -lt "${count:?}" ]; do - new_word >/dev/null - i=$((i + 1)) -done -end=$(date +%s) -wordtime=$(elapsed 'Word creation' "$((end - start))" "$count") - -bench_set 'Set element with depth 1 length 2' 1 "$BENCH_ACCURACY" "$wordtime" -bench_set 'Set element with depth 2 length 2' 2 "$BENCH_ACCURACY" "$wordtime" -bench_set 'Set element with depth 3 length 2' 3 "$BENCH_ACCURACY" "$wordtime" diff --git a/test/package/hemar/default.nix b/test/package/hemar/default.nix index 1710fbf..9442637 100644 --- a/test/package/hemar/default.nix +++ b/test/package/hemar/default.nix @@ -35,7 +35,7 @@ mkPgTest = testName: testDrv: pkgs.runCommand "hemar-test-${testName}" { nativeBuildInputs = [ pkgs.coreutils pkgs.gnugrep pkgs.gnused ]; - buildInputs = [ hemar pkgs.yq-go ]; + buildInputs = [ hemar pkgs.yq-go pkgs.which ]; } '' ${builtins.readFile self.legacyPackages.${system}.helpers.posix-shell.log} test=${testDrv} diff --git a/test/package/hemar/lauch.sh b/test/package/hemar/lauch.sh index 0bd2ed2..107c0f0 100644 --- a/test/package/hemar/lauch.sh +++ b/test/package/hemar/lauch.sh @@ -17,8 +17,6 @@ json_diff() { # run test mkdir './test' -# shellcheck disable=SC2154 cp -r "$test"/* './test/' -# shellcheck disable=SC2164 cd './test' . './run.sh' diff --git a/test/package/hemar/test/function-json-escape.sh b/test/package/hemar/test/function-json-escape.sh new file mode 100644 index 0000000..a6e8b68 --- /dev/null +++ b/test/package/hemar/test/function-json-escape.sh @@ -0,0 +1,126 @@ +# shellcheck disable=SC2034 +AS_LIBRARY=1 +# shellcheck disable=SC1090 +. "$(which hemar)" + +log notice "test case: ${WHITE}double quote escaping" +input='text with "quotes"' +if ! answer=$(json_escape "$input"); then + log error "test failed: ${WHITE}error during json_escape call" + exit 1 +fi + +expected='text with \"quotes\"' +if [ "$answer" != "$expected" ]; then + log error "test failed: ${WHITE}wrong answer. Expected: $expected, Got: $answer" + exit 1 +fi + +log notice "test case: ${WHITE}backslash escaping" +input='text with \backslash' +if ! answer=$(json_escape "$input"); then + log error "test failed: ${WHITE}error during json_escape call" + exit 1 +fi + +expected='text with \\backslash' +if [ "$answer" != "$expected" ]; then + log error "test failed: ${WHITE}wrong answer. Expected: $expected, Got: $answer" + exit 1 +fi + +log notice "test case: ${WHITE}newline escaping" +input="line1 +line2" +if ! answer=$(json_escape "$input"); then + log error "test failed: ${WHITE}error during json_escape call" + exit 1 +fi + +expected='line1\nline2' +if [ "$answer" != "$expected" ]; then + log error "test failed: ${WHITE}wrong answer. Expected: $expected, Got: $answer" + exit 1 +fi + +log notice "test case: ${WHITE}carriage return escaping" +input=$(printf 'line1\rline2') +if ! answer=$(json_escape "$input"); then + log error "test failed: ${WHITE}error during json_escape call" + exit 1 +fi + +expected='line1\rline2' +if [ "$answer" != "$expected" ]; then + log error "test failed: ${WHITE}wrong answer. Expected: $expected, Got: $answer" + exit 1 +fi + +log notice "test case: ${WHITE}tab escaping" +input="text with tabs" +if ! answer=$(json_escape "$input"); then + log error "test failed: ${WHITE}error during json_escape call" + exit 1 +fi + +expected='text\twith\ttabs' +if [ "$answer" != "$expected" ]; then + log error "test failed: ${WHITE}wrong answer. Expected: $expected, Got: $answer" + exit 1 +fi + +log notice "test case: ${WHITE}control character escaping" +# NOTE: Test with a control character (bell, 0x07) +input=$(printf 'text\007with\007control') +if ! answer=$(json_escape "$input"); then + log error "test failed: ${WHITE}error during json_escape call" + exit 1 +fi + +# NOTE: Control character should be escaped as \u0007 +expected='text\u0007with\u0007control' +if [ "$answer" != "$expected" ]; then + log error "test failed: ${WHITE}wrong answer. Expected: $expected, Got: $answer" + exit 1 +fi + +log notice "test case: ${WHITE}complex string with multiple special chars" +input='text with "quotes" and \backslashes +and newlines and tabs' +if ! answer=$(json_escape "$input"); then + log error "test failed: ${WHITE}error during json_escape call" + exit 1 +fi + +expected='text with \"quotes\" and \\backslashes\nand newlines\tand tabs' +if [ "$answer" != "$expected" ]; then + log error "test failed: ${WHITE}wrong answer. Expected: $expected, Got: $answer" + exit 1 +fi + +log notice "test case: ${WHITE}empty string" +input='' +if ! answer=$(json_escape "$input"); then + log error "test failed: ${WHITE}error during json_escape call" + exit 1 +fi + +if [ -n "$answer" ]; then + log error "test failed: ${WHITE}empty string should produce empty output" + exit 1 +fi + +log notice "test case: ${WHITE}plain text (no escaping needed)" +input='plain text without special chars' +if ! answer=$(json_escape "$input"); then + log error "test failed: ${WHITE}error during json_escape call" + exit 1 +fi + +if [ "$answer" != "$input" ]; then + log error "test failed: ${WHITE}plain text should remain unchanged. Expected: $input, Got: $answer" + exit 1 +fi + +log notice "test passed" +