Renamed config.sh to cfg.sh to match function name

Fixed code-breaking bugs for cfg.sh for all base functions (i.e not dispatcher functions)
Added test file for cfg function for all base functions (i.e not dispatcher functions)
This commit is contained in:
ayakael 2018-01-11 10:09:00 -09:00
parent 8e5a75dd47
commit d20bc4e986
No known key found for this signature in database
GPG key ID: 575626A4AE5F4026
3 changed files with 342 additions and 169 deletions

190
lib/cfg.sh Normal file
View file

@ -0,0 +1,190 @@
#!/bin/bash
# doc cfg {
#
# NAME
# cfg
#
# DESCRIPTION
# Reads and writes config files delimited by tabs, like fstab, using awk.
#
# USAGE
# _cfg <command> <arg>
#
# COMMANDS
# set-file <path/to/file>
# Sets path to file
#
# create <column-names>
# Creates config file and assigns <column-names>.
#
# print <column-name> <row-no>
# Prints value from <column-name> and <row-no>.
#
# change <column-name> <row-no> <value>
# Assigns new <value> to <column-name> and <row-no>.
#
# drop <row|column} {no|name}
# Drops <row-no> or <column-name>.
#
# insert <value-for-col1> <value-for-col2> <...>
# Inserts new row with a value per column. Number of arguments must match number of columns.
#
# query <conditional>
# Queries which <row-no(s)> fits the <conditional>.
#
#
# CONDITIONALS
#
#
#
# EXIT VALUES
# 0 Success
# 1 Syntax or usage error
# 2 File not found
# 3 File already present
# 4 Row or column not found
# 5 Row or column already has value
#
# }
_cfg_column_to_nf() {
# Argument parser and sanity check
[[ -z ${1+x} ]] && { _msg ECHO "_cfg_column_to_nf(): Expected column name"; return 1; }
local COLUMN=${1}
# Queries list of columns
local columnList=(all $(awk 'BEGIN {FS="\t"; OFS="\t"}; {if (NR == 1 ) {print $0}}' ${_CFG_PATH}))
# Checks if queried ${COLUMN} exists
if ! _if_array_contains ${COLUMN} ${columnList[@]}; then
_msg ECHO "_cfg_column_to_nf(): Column does not exist"
return 1
else
# Finds what NF is associated with ${COLUMN}
local COUNT=0
for column in ${columnList[@]}; do
[[ "${COLUMN}" == "${column}" ]] && echo "${COUNT}"
local COUNT=$(( ${COUNT} + 1 ))
done
return 0
fi
}
_cfg_set_file() {
# Argument parser and sanity check
[[ $# != 1 ]] && { _msg ECHO "_cfg_set_file(): Expected 1 argument"; return 1; }
# Sets _CFG_PATH globally
_CFG_PATH="${1}"
_CFG_TMP_PATH="$(sed 's|\(.*\)\/|\1/.|' <<<"${_CFG_PATH}")"
}
_cfg_create() {
# Argument parser and sanity check
[[ -z ${1+x} ]] && { _msg ECHO "_cfg_create(): Expected argument"; return 1; }
local colList=(${@})
# Creates config file
printf "%s\t" ${colList[@]} | awk 'BEGIN{OFS="\t";} {printf "%s\n",$0}' >> ${_CFG_PATH}
}
_cfg_print() {
# Argument parser and sanity check
[[ $# != 2 ]] && { _msg ECHO "_cfg_print(): Expected 2 arguments"; return 1; }
local COLUMN=${1}
local ROW=${2}
# Prints row of ${_CFG_PATH}
awk 'BEGIN {OFS="\t"}; {if (NR == '${ROW}') {print $'$(_cfg_column_to_nf ${COLUMN})'}}' "${_CFG_PATH}"
}
_cfg_change() {
# Argument parser and sanity check
[[ $# != 3 ]] && { _msg ECHO "_cfg_change(): Expected 3 arguments"; return 1; }
local COLUMN=${1}
local ROW=${2}
local VALUE=${3}
local COLUMN_NO=$(_cfg_column_to_nf ${COLUMN})
_if_is_integer ${ROW} || { _msg ECHO "_cfg_change(): Expected integer"; return 1; }
[[ ${ROW} > $(awk 'BEGIN{FS="\t"; OFS="\t"}; {print NR}' ${_CFG_PATH} | wc -l) ]] && { _msg ECHO "_cfg_change(): Row ${ROW} does not exist"; return 1; }
# Writes new version of file
awk 'BEGIN {OFS="\t"}; {if (NR == '${ROW}') {$'${COLUMN_NO}'="'${VALUE}'"} {print $0}}' "${_CFG_PATH}" > ${_CFG_TMP_PATH} && mv ${_CFG_TMP_PATH} ${_CFG_PATH}
}
_cfg_drop() {
# Argument parser and sanity check
[[ $# != 2 ]] && { _msg ECHO "_cfg_drop(): Expected 2 arguments"; return 1; }
local SUBCMD=${1}; shift
[[ ! $(_if_array_contains ${SUBCMD} row column) ]] && { _msg ECHO "_cfg_drop(): Expected 'row' or 'column' as subcommand"; return 1; }
# Dispatcher
eval _cfg_drop_${SUBCMD} ${1}
}
_cfg_drop_row() {
# Argument parser and sanity check
local ROW=${1}
[[ ${ROW} > $(awk 'BEGIN {FS="\t"; OFS="\t"}; {print NR}' ${_CFG_PATH} | wc -l) ]] && { _msg ECHO "_cfg_drop_row(): Row ${ROW} does not exist"; return 1; }
# Writes new version of file
awk 'BEGIN {OFS="\t"}; {if (NR != '${ROW}') {print $0}}' ${_CFG_PATH} > ${_CFG_TMP_PATH} && mv ${_CFG_TMP_PATH} ${_CFG_PATH}
}
_cfg_drop_column() {
local COLUMN=${1}
local NF=$(_cfg_column_to_nf "${COLUMN}")
# Writes new version of file
awk 'BEGIN {OFS="\t"}; {$'${NF}'=""; print $0}' ${_CFG_PATH} > ${_CFG_TMP_PATH} && mv ${_CFG_TMP_PATH} ${_CFG_PATH}
}
_cfg_insert() {
# Argument parser and sanity check
[[ $# != 2 ]] && { _msg ECHO "_cfg_insert(): Expected 2 arguments"; return 1; }
local SUBCMD=${1}; shift
[[ ! $(_if_array_contains ${SUBCMD} row column) ]] && { _msg ECHO "_cfg_insert(): Expected 'row' or 'column' as subcommand"; return 1; }
# Dispatcher
eval _cfg_insert_${SUBCMD} ${1}
}
_cfg_insert_column() {
# Argument parser and sanity check
local VALUE=${1}
local NX_COLUMN=$(( $(awk 'BEGIN{OFS="\t"}; {if (NR == 1) {print NF}}' ${_CFG_PATH}) + 1 ))
# Write new version of header into file
awk 'BEGIN {OFS="\t"}; {if (NR == 1) {$'${NX_COLUMN}'="'${VALUE}'"} {print $0}}' "${_CFG_PATH}" > ${_CFG_TMP_PATH} && mv ${_CFG_TMP_PATH} ${_CFG_PATH}
}
_cfg_insert_row() {
# Argument parser and sanity check
local valueList=(${@})
local COLUMN_NO=$(awk 'BEGIN{OFS="\t"}; {if (NR == 1) {print NF}}' ${_CFG_PATH})
[[ "${#valueList[@]}" != "${COLUMN_NO}" ]] && { _msg ECHO "_cfg_insert_row(): Number of arguments must be equal to ${COLUMN_NO}"; return 1; }
# Write row into file
printf "%s\t" ${valueList[@]} | awk 'BEGIN{OFS="\t";} {printf "%s\n",$0}' >> ${_CFG_PATH}
}
_cfg_query() {
# Argument parser and sanity check
local CONDITION="${1}"
awk 'BEGIN {FS="\t"; OFS="\t"}; {if ('${CONDITION}') {print NR}}' "${_CFG_PATH}"
}
_cfg() {
# Sanity check and command parser
[[ -z ${1+x} ]] && { _msg ECHO "_cfg(): Expected command"; return 1; }
local cmdList="(set-file create print change drop insert query)"
local CMD=${1}; shift
[[ ! $(_if_array_contains ${CMD} ${cmdList[@]}) ]] && { _msg ECHO "_cfg(): Command specified not valid"; return 1; }
# Dispatcher
eval _cfg_$(sed 's|-|_|' <<<"${CMD}") ${@}
}

View file

@ -1,169 +0,0 @@
#/bin/bash
# doc cfg {
#
# NAME
# cfg
#
# DESCRIPTION
# Reads and writes config files delimited by tabs, like fstab, using awk.
#
# USAGE
# _cfg <command> <arg>
#
# COMMANDS
# set-file <path/to/file>
# Sets path to file
#
# create <column-names>
# Creates config file and assigns <column-names>.
#
# print <column-name> <row-no>
# Prints value from <column-name> and <row-no>.
#
# change <column-name> <row-no> <value>
# Assigns new <value> to <column-name> and <row-no>.
#
# drop <row|column} {no|name}
# Drops <row-no> or <column-name>.
#
# insert <value-for-col1> <value-for-col2> <...>
# Inserts new row with a value per column. Number of arguments must match number of columns.
#
# query <conditional>
# Queries which <row-no(s)> fits the <conditional>.
#
#
# CONDITIONALS
#
#
#
# EXIT VALUES
# 0 Success
# 1 Syntax or usage error
# 2 File not found
# 3 File already present
# 4 Row or column not found
# 5 Row or column already has value
#
# }
_cfg() {
# Sanity check and command parser
[[ ! -z ${1+x} ]] && {_msg ECHO "_cfg(): Expected command"; return 1}
local cmdList="(set-file create print change drop insert query)"
local CMD=${1}; shift
[[ ! _if_array_contains ${CMD} ${cmdList[@]} ]] && {_msg ECHO "_cfg(): Command specified not valid; return 1"}
# Dispatcher
_cfg_$(sed 's|-|_|' <<<"${CMD}") ${@}
}
_cfg_column_to_nf() {
# Argument parser and sanity check
[[ ! -z ${1+x} ]] && {_msg ECHO "_cfg(): Expected column name"; return 1}
local COLUMN=${1}
# Queries list of columns
local columnList=(all $(awk 'BEGIN {FS="\t"; OFS="\t"}; {if (NR = 0) {print '${0}'}}' ${_CFG_PATH}))
# Checks if queried ${COLUMN} exists
if [ if ! _if_array_contains ${COLUMN} ${columnList[@]} ]; then
_msg ECHO "_cfg_column_to_nf(): Column does not exist"
return 1
else
# Finds what NF is associated with ${COLUMN}
local COUNT=0
for column ${columnList[@]}; do
[[ "${COLUMN}" == "${column}" ]] && echo "${COUNT}"
local COUNT=$(( ${COUNT} + 1 ))
return 0
done
fi
}
_cfg_set_file() {
# Argument parser and sanity check
[[ $# != 1 ]] && {_msg ECHO "_cfg_set_file(): Expected 1 argument"; return 1}
# Sets _CFG_PATH globally
_CFG_PATH="${1}"
_CFG_TMP_PATH="$(sed 's|\(.*\)\/|\1/.|' <<<"${CFG_PATH}")"
}
_cfg_create() {
# Argument parser and sanity check
[[ ! -z ${1+x} ]] && {_msg ECHO "_cfg_create(): Expected argument"; return 1}
local colList=(${@})
# Creates config file
printf "%s\t" ${colList[@]} >> ${_CFG_PATH}
}
_cfg_print() {
# Argument parser and sanity check
[[ $# != 2 ]] && {_msg ECHO "_cfg_print(): Expected 2 arguments"; return 1}
local COLUMN=${1}
local ROW=${2}
# Prints row of ${_CFG_PATH}
awk 'BEGIN {FS="\t"; OFS="\t"}; {if (NR='${ROW}') {print $'$(_cfg_column_to_nf ${COLUMN})'}}' "${_CFG_PATH}"
}
_cfg_change() {
# Argument parser and sanity check
[[ $# != 3 ]] && {_msg ECHO "_cfg_change(): Expected 3 arguments"; return 1}
local COLUMN=${1}
local ROW=${2}
local VALUE=${3}
[[ ! _if_is_integer ${ROW} ]] && {_msg ECHO "_cfg_change(): Expected integer; return 1"}
# Writes new version of file
awk 'BEGIN {OFS="\t"}; {if (NR == '${ROW}') {$'$(_cfg_column_to_nf ${COLUMN})'='${VALUE}'} {print $0}}' "${_CFG_PATH}" > ${_CFG_TMP_PATH} && mv ${_CFG_TMP_PATH} ${_CFG_PATH}
}
_cfg_drop() {
# Argument parser and sanity check
[[ -z $# != 2 ]] && {_msg ECHO "_cfg_drop(): Expected 2 arguments"; return 1}
local SUBCMD=${1}; shift
[[ ! _if_array_contains ${SUBCMD} row column ]] && {_msg ECHO "_cfg_drop(): Expected 'row' or 'column' as subcommand"; return 1}
# Dispatcher
_cfg_drop_${SUBCMD} ${1}
}
_cfg_drop_row() {
# Argument parser and sanity check
local ROW=${1}
[[ ${ROW} -mt $(awk 'BEGIN {FS="\t"; OFS="\t"}; {print NR}' ${_CFG_PATH}) ]] && {_msg ECHO "_cfg_drop_row(): Row number higher than available"}
# Writes new version of file
awk 'BEGIN {OFS="\t"}; {if (NR == '${ROW}') {$0="\b") {print $0}}' ${_CFG_PATH} > ${_CFG_TMP_PATH} && mv ${_CFG_TMP_PATH} ${_CFG_PATH}
}
_cfg_drop_column() {
local COLUMN=${1}
local NF=$(_cfg_column_to_nf "${COLUMN}")
# Writes new version of file
awk 'BEGIN {OFS="\t"}; {$'${NF}'="\b"; print &0}' ${_CFG_PATH} > ${_CFG_TMP_PATH} && mv ${_CFG_TMP_PATH} ${_CFG_PATH}
}
_cfg_insert() {
# Argument parser and sanity check
local valueList=(${@})
local COLUMN_NO=$(awk 'BEGIN{OFS="\t"}; {if (NR == 1) {print NF}}' ${_CFG_PATH})
[[ "${#valueList[@]}" =! "${COLUMN_NO}" ]] && {_msg ECHO "_cfg_insert(): Number of arguments must be equal to ${COLUMN_NO}"; return 1}
# Write row into file
printf "%s\t" ${valueList[@]} >> ${_CFG_PATH}
}
_cfg_query() {
# Argument parser and sanity check
local CONDITION=${1}
awk 'BEGIN {FS="\t"; OFS="\t"}; {if ('${CONDITION}') {print NR}}' "{_CFG_PATH}"
}

152
test/test-cfg.sh Normal file
View file

@ -0,0 +1,152 @@
#!/bin/bash
source ../lib/if.sh
source ../lib/ansi.sh
source ../lib/msg.sh
source ../lib/cfg.sh
TMP=/tmp
testcolList=(COL1 COL2 COL3 COL4 COL5)
# cfg test
bail() {
cat ${TMP}/test.cfg
rm ${TMP}/test.cfg
exit 1
}
_test_cfg_set_file() {
_msg EXEC "Testing _cfg_set_file()"
_cfg_set_file ${TMP}/test.cfg
[[ "${_CFG_PATH}" != "${TMP}/test.cfg" ]] && { _msg FAIL "_test_cfg_set_file(): \${_CFG_PATH} is '${_CFG_PATH}' rather than the expected '${TMP}/test.cfg'"; }
[[ "${_CFG_TMP_PATH}" != "${TMP}/.test.cfg" ]] && { _msg FAIL "_test_cfg_set_file(): \${_CFG_TMP_PATH} is '${_CFG_TMP_PATH}' rather than the expected '${TMP}/.test.cfg"; }
_msg OK
}
_test_cfg_create() {
_msg EXEC "Testing _cfg_create()"
local CMD="_cfg_create ${testcolList[@]}"
eval ${CMD} >${STDERR} 2>&1 || { _msg FAIL "_test_cfg_create(): Error in function execution"; }
local FC_OUTPUT="$(cat ${TMP}/test.cfg)"
local EX_OUTPUT="$(printf '%s\t' ${testcolList[@]})"
[[ "${FC_OUTPUT}" != "${EX_OUTPUT}" ]] && { _msg FAIL "_test_cfg_create(): Output '${FC_OUTPUT}' expected to be '${EX_OUTPUT}'"; }
_msg OK
}
_test_cfg_column_to_nf() {
_msg EXEC "Testing _cfg_column_to_nf()"
local argList=(all ${testcolList[@]})
_cfg_column_to_nf ${argList[1]} >${STDERR} 2>&1 || { _msg FAIL "test_cfg_column_to_nf(): Error in function execution"; }
for no in {0..5}; do
local FC_OUTPUT="$(_cfg_column_to_nf ${argList[${no}]})"
local EX_OUTPUT="${no}"
[[ ${FC_OUTPUT} -ne ${EX_OUTPUT} ]] && { _msg FAIL "_test_cfg_column_to_nf(): Output '${FC_OUTPUT}' expected to be '${EX_OUTPUT}'"; }
done
_msg OK
}
_test_cfg_print() {
_msg EXEC "Testing _cfg_print()"
local argList=(all 1)
local CMD="_cfg_print ${argList[@]}"
eval ${CMD} >${STDERR} 2>&1 || { _msg FAIL "_test_cfg_print(): Error in function execution"; }
local FC_OUTPUT="$(eval ${CMD})"
local EX_OUTPUT="$(printf '%s\t' ${testcolList[@]})"
[[ "${FC_OUTPUT}" != "${EX_OUTPUT}" ]] && { _msg FAIL "_test_cfg_print(): Output '${FC_OUTPUT}' expected to be '${EX_OUTPUT}'"; }
_msg OK
}
_test_cfg_insert_row() {
_msg EXEC "Testing _cfg_insert_row()"
local argList=(EL1 EL2 EL3 EL4 EL5)
local CMD="_cfg_insert_row ${argList[@]}"
eval ${CMD} >${STDERR} 2>&1 || { _msg FAIL "_test_cfg_insert_row(): Error in function execution"; }
local FC_OUTPUT="$(_cfg_print all 2)"
local EX_OUTPUT="$(printf '%s\t' ${argList[@]})"
[[ "${FC_OUTPUT}" != "${EX_OUTPUT}" ]] && { _msg FAIL "_test_cfg_insert_row(): Output '${FC_OUTPUT}' expected to be '${EX_OUTPUT}'"; }
awk 'BEGIN {OFS="\t"}; {if (NR != 2) {print $0}}' ${_CFG_PATH} > ${_CFG_TMP_PATH} && mv ${_CFG_TMP_PATH} ${_CFG_PATH}
_msg OK
}
_test_cfg_insert_column() {
_msg EXEC "Testing _cfg_insert_column()"
local argList=(COL6)
local CMD="_cfg_insert_column ${argList[@]}"
eval ${CMD} >${STDERR} 2>&1 || { _msg FAIL "_test_cfg_insert_column(): Error in function execution"; }
local fcoutputList=($(_cfg_print all 1))
local exoutputList=(${testcolList[@]} COL6)
[[ "${fcoutputList[@]}" != "${exoutputList[@]}" ]] && { _msg FAIL "_test_cfg_insert_column(): Output '${fcoutputList[@]}' expected to be '${exoutputList[@]}'"; }
awk 'BEGIN {OFS="\t"}; {$6=""; print $0}' ${_CFG_PATH} > ${_CFG_TMP_PATH} && mv ${_CFG_TMP_PATH} ${_CFG_PATH}
_msg OK
}
_test_cfg_change() {
_msg EXEC "Testing _cfg_change()"
_cfg_insert_row ${testcolList[@]}
local argList=(COL1 2 EL1_CH)
local CMD="_cfg_change ${argList[@]}"
eval ${CMD} >${STDERR} 2>&1 || { _msg FAIL "_test_cfg_change(): Error in function execution"; }
local FC_OUTPUT="$(_cfg_print COL1 2)"
local EX_OUTPUT="EL1_CH"
[[ "${FC_OUTPUT}" != "${EX_OUTPUT}" ]] && { _msg FAIL "_test_cfg_change(): Output '${FC_OUTPUT}' expected to be '${EX_OUTPUT}'"; }
_cfg_drop_row 2
_msg OK
}
_test_cfg_drop_row() {
_msg EXEC "Testing _cfg_drop_row()"
_cfg_insert_row ${testcolList[@]}
local argList=(2)
local CMD="_cfg_drop_row ${argList[@]}"
eval ${CMD} >${STDERR} 2>&1 || { _msg FAIL "_test_cfg_drop_row(): Error in function execution"; }
FC_OUTPUT="$(awk '{print NR}' ${TMP}/test.cfg | wc -l)"
EX_OUTPUT=1
[[ ${FC_OUTPUT} != ${EX_OUTPUT} ]] && { _msg FAIL "_test_cfg_drop_row(): Output '${FC_OUTPUT}' expected to be ${EX_OUTPUT}'"; }
_msg OK
}
_test_cfg_drop_column() {
_msg EXEC "Testing _cfg_drop_column()"
_cfg_insert_column "COL6"
local argList="COL6"
local CMD="_cfg_drop_column ${argList[@]}"
eval ${CMD} >${STDERR} 2>&1 || { _msg FAIL "_test_cfg_drop_column(): Error in function execution"; }
FC_OUTPUT="$(printf '%s ' $(awk 'BEGIN{OFS="\t"}; {if (NR == 1) {print $0}}' ${_CFG_PATH}))"
EX_OUTPUT="$(printf '%s ' ${testcolList[@]})"
[[ "${FC_OUTPUT}" != "${EX_OUTPUT}" ]] && { _msg FAIL "_test_cfg_drop_column(): Output '${FC_OUTPUT}' expected to be '${EX_OUTPUT}'"; }
_msg OK
}
_test_cfg_query() {
_msg EXEC "Testing _cfg_query"
_cfg_insert_row "EL1 EL2 EL3 EL4 EL5"
_cfg_insert_row "EL6 EL7 EL8 EL9 EL10"
local ARG="\$1==\"EL6\""
local CMD="_cfg_query '${ARG}'"
eval ${CMD} >${STDERR} 2>&1 || { _msg FAIL "_test_cfg_query(): Error in function execution"; }
FC_OUTPUT=$(eval ${CMD})
EX_OUTPUT=3
[[ "${FC_OUTPUT}" != "${EX_OUTPUT}" ]] && { _msg FAIL "_test_cfg_query(): Output '${FC_OUTPUT}' expected to be '${EX_OUTPUT}'"; }
awk 'BEGIN {OFS="\t"}; {if (NR == 1) {print $0}}' ${_CFG_PATH} > ${_CFG_TMP_PATH} && mv ${_CFG_TMP_PATH} ${_CFG_PATH}
_msg OK
}
testList=(cfg_set_file cfg_create cfg_column_to_nf cfg_print cfg_query cfg_insert_row cfg_insert_column cfg_drop_row cfg_drop_column cfg_change)
_msg ECHO "cfg function test suite started"
for test in ${testList[@]}; do
eval _test_${test}
done
rm ${TMP}/test.cfg
_msg ECHO "cfg function test suite ended"