#!/bin/bash

fail() {
  rm -fv "$CHECKPT"
  echo FAIL: "$1" unexpected exit code "$2"
  echo Log N/A
  exit 1
}

# Determine location of binaries

# Disabling SC2128, more context here -> https://stackoverflow.com/questions/35006457/choosing-between-0-and-bash-source
#shellcheck disable=SC2128
UNIT_TEST=$(dirname -- "$BASH_SOURCE")
BUILD=$(dirname -- "$UNIT_TEST")
BIN=$BUILD/bin

# Specify test details

WKSP=test_fd_wksp_ctl.wksp
PAGE_CNT=1
PAGE_SZ=gigantic
CPU_IDX=0
MODE=0600

CHECKPT=test_fd_wksp_ctl.checkpt
INFO="The quick brown fox jumps over the lazy dog"

# Disable the permanent log

FD_LOG_PATH=""
export FD_LOG_PATH

# Try to clean up any leftovers from previous runs (including same name on multiple pages)

"$BIN"/fd_wksp_ctl delete "$WKSP" delete "$WKSP" delete "$WKSP" > /dev/null 2>&1
rm -fv "$CHECKPT"

echo Testing no-op

"$BIN"/fd_wksp_ctl || fail no-op $?

echo Testing unknown

"$BIN"/fd_wksp_ctl unknown && fail unknown $?

echo Testing help

"$BIN"/fd_wksp_ctl help || fail help $?

echo Testing tag

"$BIN"/fd_wksp_ctl tag   && fail tag $?
"$BIN"/fd_wksp_ctl tag 1 || fail tag $?

echo Testing new

"$BIN"/fd_wksp_ctl new                                                && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"                                        && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT"                         && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ                && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ $CPU_IDX       && fail new $?
"$BIN"/fd_wksp_ctl new bad/name   "$PAGE_CNT" $PAGE_SZ $CPU_IDX $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    0           $PAGE_SZ $CPU_IDX $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" bad_sz   $CPU_IDX $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ -1       $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ ""       $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "q"      $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "0q1"    $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "0-"     $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "0-q"    $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "1-0"    $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "q-10/2" $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "0q10/2" $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "0-q/2"  $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "0-10%2" $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "0-10/"  $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "0-10/q" $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "10-0/2" $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ "0;1"    $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ 0-1024   $MODE && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ $CPU_IDX -1    && fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ $CPU_IDX $MODE || fail new $?
"$BIN"/fd_wksp_ctl new "$WKSP"    "$PAGE_CNT" $PAGE_SZ $CPU_IDX $MODE && fail new $?

echo Testing alloc

"$BIN"/fd_wksp_ctl alloc                                          && fail alloc $?
"$BIN"/fd_wksp_ctl alloc "$WKSP"                                  && fail alloc $?
"$BIN"/fd_wksp_ctl alloc "$WKSP"  4096                            && fail alloc $?
"$BIN"/fd_wksp_ctl alloc bad/name 4096 2097152                    && fail alloc $?
"$BIN"/fd_wksp_ctl alloc "$WKSP"  -1   2097152                    && fail alloc $?
"$BIN"/fd_wksp_ctl alloc "$WKSP"  4096 -1                         && fail alloc $?

GADDR=$("$BIN"/fd_wksp_ctl alloc "$WKSP" 4096 2097152 || fail alloc $?)

GADDR1=$("$BIN"/fd_wksp_ctl tag 1234 alloc "$WKSP" 4096 4096 || fail alloc $?)
GADDR2=$("$BIN"/fd_wksp_ctl tag 1234 alloc "$WKSP" 4096 4096 || fail alloc $?)
GADDR3=$("$BIN"/fd_wksp_ctl tag 2345 alloc "$WKSP" 4096 4096 || fail alloc $?)

SUPPORTED_STYLES=$("$BIN"/fd_wksp_ctl supported-styles || fail supported-styles $?)

for STYLE in $SUPPORTED_STYLES; do
  echo Testing with checkpt style "$STYLE"

  echo Testing checkpt

  "$BIN"/fd_wksp_ctl checkpt                                              && fail checkpt $?
  "$BIN"/fd_wksp_ctl checkpt "$WKSP"                                      && fail checkpt $?
  "$BIN"/fd_wksp_ctl checkpt "$WKSP"  "$CHECKPT"                          && fail checkpt $?
  "$BIN"/fd_wksp_ctl checkpt "$WKSP"  "$CHECKPT" "$MODE"                  && fail checkpt $?
  "$BIN"/fd_wksp_ctl checkpt "$WKSP"  "$CHECKPT" "$MODE" "$STYLE"         && fail checkpt $?
  "$BIN"/fd_wksp_ctl checkpt bad/name "$CHECKPT" "$MODE" "$STYLE" "$INFO" && fail checkpt $?
  "$BIN"/fd_wksp_ctl checkpt "$WKSP"  "$CHECKPT" -1      "$STYLE" "$INFO" && fail checkpt $?
  "$BIN"/fd_wksp_ctl checkpt "$WKSP"  "$CHECKPT" "$MODE" -1       "$INFO" && fail checkpt $?
  "$BIN"/fd_wksp_ctl checkpt "$WKSP"  "$CHECKPT" "$MODE" "$STYLE" "$INFO" || fail checkpt $?
  "$BIN"/fd_wksp_ctl checkpt "$WKSP"  "$CHECKPT" "$MODE" "$STYLE" "$INFO" && fail checkpt $?

  echo Testing checkpt-query

  "$BIN"/fd_wksp_ctl checkpt-query              && fail checkpt-query $?
  "$BIN"/fd_wksp_ctl checkpt-query "$CHECKPT"   && fail checkpt-query $?
  "$BIN"/fd_wksp_ctl checkpt-query "$CHECKPT" 0 \
                     checkpt-query "$CHECKPT" 1 \
                     checkpt-query "$CHECKPT" 2 \
                     checkpt-query "$CHECKPT" 3 \
                     checkpt-query "$CHECKPT" 4 \
                     checkpt-query "$CHECKPT" 5 || fail checkpt-query $?

  echo Testing info

  "$BIN"/fd_wksp_ctl info         && fail info $?
  "$BIN"/fd_wksp_ctl info "$WKSP" && fail info $?
  "$BIN"/fd_wksp_ctl info bad     1234 \
                     info "$WKSP"    0 \
                     info "$WKSP" 4096 \
                     info "$WKSP"    2 \
                     info "$WKSP" 1234 \
                     info "$WKSP" 2345 \
                     info "$WKSP" 1234 \
  || fail info $? # Yes ... a fail here is success from cmd exec POV (fail is logged)

  echo Testing memset

  "$BIN"/fd_wksp_ctl memset              && fail memset $?
  "$BIN"/fd_wksp_ctl memset "$GADDR"     && fail memset $?
  "$BIN"/fd_wksp_ctl memset bad/name 0   || fail memset $? # Yes ... a fail here is success from cmd exec POV (fail is logged)
  "$BIN"/fd_wksp_ctl memset "$GADDR" 0   || fail memset $?

  echo Testing check

  "$BIN"/fd_wksp_ctl check            && fail check $?
  "$BIN"/fd_wksp_ctl check bad/name   && fail check $?
  "$BIN"/fd_wksp_ctl check "$WKSP"    || fail check $?

  echo Testing verify

  "$BIN"/fd_wksp_ctl verify            && fail verify $?
  "$BIN"/fd_wksp_ctl verify bad/name   && fail verify $?
  "$BIN"/fd_wksp_ctl verify "$WKSP"    || fail verify $?

  echo Testing rebuild

  "$BIN"/fd_wksp_ctl rebuild              && fail rebuild $?
  "$BIN"/fd_wksp_ctl rebuild "$WKSP"      && fail rebuild $?
  "$BIN"/fd_wksp_ctl rebuild bad/name -   && fail rebuild $?
  "$BIN"/fd_wksp_ctl rebuild "$WKSP"  -   \
                     rebuild "$WKSP"  123 \
  || fail rebuild $?

  echo Testing usage

  "$BIN"/fd_wksp_ctl usage               && fail usage $?
  "$BIN"/fd_wksp_ctl usage bad/name      && fail usage $?
  "$BIN"/fd_wksp_ctl usage bad/name      1 \
                     usage "$WKSP"       1 \
                     usage "$WKSP"    1234 \
                     usage "$WKSP"    2345 \
  || fail usage $?

  echo Testing query

  "$BIN"/fd_wksp_ctl query          && fail query $?
  "$BIN"/fd_wksp_ctl query bad/name && fail query $?
  "$BIN"/fd_wksp_ctl query "$WKSP"  || fail query $?

  echo Testing tag-query

  "$BIN"/fd_wksp_ctl tag-query          && fail tag-query $?
  "$BIN"/fd_wksp_ctl tag-query bad/name \
                     tag-query "$GADDR"   \
                     tag-query "$GADDR1"  \
                     tag-query "$GADDR2"  \
                     tag-query "$GADDR3"  \
  || fail tag-query $? # Yes ... a fail here is success from cmd exec POV (fail is logged)

  echo Testing tag-free

  "$BIN"/fd_wksp_ctl tag-free         && fail tag-free $?
  "$BIN"/fd_wksp_ctl tag-free "$WKSP" && fail tag-free $?
  "$BIN"/fd_wksp_ctl tag-free bad     1234 \
                     tag-free "$WKSP"    0 \
                     tag-free "$WKSP" 4096 \
                     tag-free "$WKSP"    2 \
                     tag-free "$WKSP" 1234 \
                     tag-free "$WKSP" 2345 \
                     tag-free "$WKSP" 1234 \
  || fail tag-free $? # Yes ... a fail here is success from cmd exec POV (fail is logged)

  echo Testing free

  "$BIN"/fd_wksp_ctl free          && fail free $?
  "$BIN"/fd_wksp_ctl free bad/name || fail free $? # Yes ... a fail here is success from cmd exec POV (fail is logged)
  "$BIN"/fd_wksp_ctl free "$GADDR" || fail free $?
  "$BIN"/fd_wksp_ctl free "$GADDR" || fail free $? # Yes ... a fail here is success from cmd exec POV (fail is logged)

  echo Testing reset

  "$BIN"/fd_wksp_ctl reset          && fail reset $?
  "$BIN"/fd_wksp_ctl reset bad/name && fail reset $?
  "$BIN"/fd_wksp_ctl reset "$WKSP"  || fail reset $?

  echo Testing restore

  "$BIN"/fd_wksp_ctl restore                         && fail restore $?
  "$BIN"/fd_wksp_ctl restore "$WKSP"                 && fail restore $?
  "$BIN"/fd_wksp_ctl restore "$WKSP"  "$CHECKPT"     && fail restore $?
  "$BIN"/fd_wksp_ctl restore bad/name "$CHECKPT"     && fail restore $?
  "$BIN"/fd_wksp_ctl restore "$WKSP"  "$CHECKPT" -   query "$WKSP" check "$WKSP" \
                     restore "$WKSP"  "$CHECKPT" 123 query "$WKSP" check "$WKSP" \
                     restore "$WKSP"  "$CHECKPT" 123 query "$WKSP" check "$WKSP" \
                     restore "$WKSP"  "$CHECKPT" 234 query "$WKSP" check "$WKSP" \
  || fail restore $?

  rm -fv "$CHECKPT"

  # Test checkpt empty wksp, query empty checkpt, restore empty to empty,
  # restore non-empty to empty

  "$BIN"/fd_wksp_ctl reset         "$WKSP"                                          \
                     checkpt       "$WKSP" "$CHECKPT" "$MODE" "$STYLE" "$INFO"      \
                     checkpt-query "$CHECKPT" 2                                     \
                     restore       "$WKSP" "$CHECKPT" - query "$WKSP" check "$WKSP" \
                     alloc         "$WKSP" 1 1          query "$WKSP" check "$WKSP" \
                     restore       "$WKSP" "$CHECKPT" - query "$WKSP" check "$WKSP" \
  || fail reset $?
  rm -fv "$CHECKPT"
done

echo Testing delete

"$BIN"/fd_wksp_ctl delete          && fail delete $?
"$BIN"/fd_wksp_ctl delete bad/name && fail delete $?
"$BIN"/fd_wksp_ctl delete "$WKSP"  || fail delete $?

for STYLE in $SUPPORTED_STYLES; do
  echo Testing with style "$STYLE"

  echo Testing multi

  "$BIN"/fd_wksp_ctl new           "$WKSP" "$PAGE_CNT" $PAGE_SZ $CPU_IDX $MODE check "$WKSP" \
                     query         "$WKSP"                                     check "$WKSP" \
                     alloc         "$WKSP" 1 1                                 check "$WKSP" \
                     alloc         "$WKSP" 2 2                                 check "$WKSP" \
                     alloc         "$WKSP" 4 3                                 check "$WKSP" \
                     query         "$WKSP"                                     check "$WKSP" \
                     checkpt       "$WKSP" "$CHECKPT" "$MODE" "$STYLE" "$INFO" check "$WKSP" \
                     checkpt-query "$CHECKPT" 2                                check "$WKSP" \
                     reset         "$WKSP"                                     check "$WKSP" \
                     alloc         "$WKSP" 8 8                                 check "$WKSP" \
                     restore       "$WKSP" "$CHECKPT" -                        check "$WKSP" \
                     query         "$WKSP"                                     check "$WKSP" \
                     reset         "$WKSP"                                     check "$WKSP" \
                     query         "$WKSP"                                     check "$WKSP" \
                     delete        "$WKSP"                                                   \
  || fail multi $?
  rm -fv "$CHECKPT"
done

echo pass
echo Log N/A
exit 0
