Skip to content

Commit

Permalink
src: kwio: Adds load_module_text to kwio.sh
Browse files Browse the repository at this point in the history
load_module_text is a function that creates a dictionary from a
.txt file following a particular syntax, as follows:
[key]:
text
The created dictionary is accessed by ${module_text_dictionary[key]}.
This is useful to store long strings outside of the code.
Adds a little test suite for this function in kwio_test,
and a couple test samples in tests/samples.

Co-authored-by: Miguel de Mello Carpi <miguelmello@usp.br>
Co-authored-by: Lourenço Henrique Moinheiro Martins Sborz Bogo <louhmmsb@usp.br>
Signed-off-by: Rodrigo Siqueira <siqueirajordao@riseup.net>
Signed-off-by: Eduardo Brancher Urenha <eduardo.urenha@usp.br>
  • Loading branch information
3 people authored and rodrigosiqueira committed Jan 22, 2022
1 parent 8076ae1 commit fa872ad
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/kwio.sh
Expand Up @@ -172,3 +172,88 @@ function ask_with_default()

printf '%s\n' "$response"
}

# Load text from a file into a dictionary. The file that will be read must have
# a key before a text body to name that particular text as part of the key, for
# example:
#
# [KEY]:
# text
#
# [KEY] must be non-empty, alphanumeric and between square brackets followed by
# a colon. The global array string_file can then be queried by key as in
# ${string_file[<key>]} to obtain the string. <key> should be named according
# to its respective module for compatibility. That is, if we have modules A and
# B, name A's keys as [KEY_A] and B's keys as [KEY_B]. This makes it so the
# module's keys are compatible with each other
#
# @text_file_to_be_loaded_path The full path of the text file to be loaded as
# the first argument.
#
# Return:
# SUCCESS : In case of success.
# EKEYREJECTED : If an invalid key is found, prints the line with a bad key.
# ENOKEY : If a key is not found.
# ENOENT : If @text_file_to_be_loaded_path is invalid, or is not a text file.
# ENODATA : If the file given in @text_file_to_be_loaded_path is empty.
function load_module_text()
{
local text_file_to_be_loaded_path="$1"
local key=''
local line_counter=0
local error=0 # SUCCESS
local key_set=0
local first_line=0

# Associative array to read strings from files
unset module_text_dictionary
declare -gA module_text_dictionary

if [[ ! -f "$text_file_to_be_loaded_path" ]]; then
complain "[ERROR]:$text_file_to_be_loaded_path: Does not exist or is not a text file."
return 2 # ENOENT
fi

if [[ ! -s "$text_file_to_be_loaded_path" ]]; then
complain "[ERROR]:$text_file_to_be_loaded_path: File is empty."
return 61 # ENODATA
fi

while read -r line; do
((line_counter++))
# Match [VALUE]:
if [[ "$line" =~ ^\[(.*)\]:$ ]]; then
key=''
# Match to check if VALUE is composed of alphanumeric and underscores only
[[ "${BASH_REMATCH[1]}" =~ (^[A-Za-z0-9_][A-Za-z0-9_]*$) ]] && key="${BASH_REMATCH[1]}"
if [[ -z "$key" ]]; then
error=129 # EKEYREJECTED
complain "[ERROR]:$text_file_to_be_loaded_path:$line_counter: Keys should be alphanum chars."
continue
fi

if [[ -n "${module_text_dictionary[$key]}" ]]; then
warning "[WARNING]:$text_file_to_be_loaded_path:$line_counter: Overwriting '$key' key."
fi

key_set=1
first_line=1
module_text_dictionary["$key"]=''
# If we are inside a text block, collect the current line
elif [[ -n "$key" ]]; then
if [[ "$first_line" -eq 1 ]]; then
first_line=0
else
module_text_dictionary["$key"]+=$'\n'
fi
module_text_dictionary["$key"]+="$line"
fi
done < "$text_file_to_be_loaded_path"

if [[ "$key_set" -eq 0 ]]; then
error=126 # ENOKEY
complain "[ERROR]:$text_file_to_be_loaded_path: No key found."
fi

return "$error"
}
82 changes: 82 additions & 0 deletions tests/kwio_test.sh
Expand Up @@ -10,6 +10,8 @@ include './src/kwlib.sh'
# the function will return before the background commands finish.

declare -A configurations
declare -g load_module_text_path="$PWD/tests/samples/load_module_text_test_samples/"

sound_file="$PWD/tests/.kwio_test_aux/sound.file"
visual_file="$PWD/tests/.kwio_test_aux/visual.file"

Expand Down Expand Up @@ -237,4 +239,84 @@ function test_ask_yN()
assert_equals_helper "$assert_equals_message" "$LINENO" '0' "$output"
}

function test_load_module_text_good_files()
{
local multiple_line_str

load_module_text "$load_module_text_path/file_correct"
assertEquals 'Should work without any errors.' 0 "$?"

assertEquals 'Key1' 'Hello, there! How are you? I hope you are enjoying reading this test suit!' "${module_text_dictionary[key1]}"
assertEquals 'Key2' 'Hey, you still there? []' "${module_text_dictionary[key2]}"

multiple_line_str=$'This should work with multiple lines.\nLine 1\nLine 2\nLine 3\nLine 4\nLine 5'
assertEquals 'Key3' "$multiple_line_str" "${module_text_dictionary[key3]}"

assertEquals 'Key4' 'done.' "${module_text_dictionary[key4]}"
assertEquals 'Key5' '' "${module_text_dictionary[key5]}"

multiple_line_str=$'\n\n\n\n\nThe one above should have an empty value.\n'
assertEquals 'Key6' "$multiple_line_str" "${module_text_dictionary[key6]}"

multiple_line_str=$'\nThis value should be ok\n'
assertEquals 'Key7' "$multiple_line_str" "${module_text_dictionary[key7]}"
}

function test_load_module_text_bad_keys()
{
local expected
local output

declare -a expected_sequence=(
"[ERROR]:$load_module_text_path/file_wrong_key:7: Keys should be alphanum chars."
"[ERROR]:$load_module_text_path/file_wrong_key:10: Keys should be alphanum chars."
"[ERROR]:$load_module_text_path/file_wrong_key:13: Keys should be alphanum chars."
"[ERROR]:$load_module_text_path/file_wrong_key:16: Keys should be alphanum chars."
"[ERROR]:$load_module_text_path/file_wrong_key:19: Keys should be alphanum chars."
)

output=$(load_module_text "$load_module_text_path/file_wrong_key")
assertEquals 'This file has invalid keys, this should return multiple errors.' 129 "$?"

compare_command_sequence 'expected_sequence' "$output" "$LINENO"
}

function test_load_module_text_invalid_files()
{
local expected
local output

expected="[ERROR]:$load_module_text_path/file_without_key: No key found."
output=$(load_module_text "$load_module_text_path/file_without_key")
assertEquals "[$LINENO]: This file has no keys, this should return an error." 126 "$?"
assertEquals "[$LINENO]: The ERROR message is not consistent with the error code or is incomplete." "$expected" "$output"

expected="[ERROR]:$load_module_text_path/file_empty: File is empty."
output=$(load_module_text "$load_module_text_path/file_empty")
assertEquals "[$LINENO]: This file is empty, this should return an error." 61 "$?"
assertEquals "[$LINENO]: The ERROR message is not consistent with the error code or is incomplete." "$expected" "$output"
}

function test_load_module_text_no_files()
{
local expected
local output

expected="[ERROR]:$load_module_text_path/file_does_not_exist_(do not create): Does not exist or is not a text file."
output=$(load_module_text "$load_module_text_path/file_does_not_exist_(do not create)")
assertEquals "[$LINENO]: This file does not exist, this should return an error." 2 "$?"
assertEquals "[$LINENO]: The ERROR message is not consistent with the error code or is incomplete." "$expected" "$output"
}

function test_load_module_text_repeated_keys()
{
local expected
local output

expected="[WARNING]:$load_module_text_path/file_repeated_keys:9: Overwriting 'Sagan' key."
output=$(load_module_text "$load_module_text_path/file_repeated_keys")
assertEquals "[$LINENO]: Although we received warnings, the function should exit with SUCCESS" 0 "$?"
assertEquals "[$LINENO]: The ERROR message is not consistent with the error code or is incomplete." "$expected" "$output"
}

invoke_shunit
26 changes: 26 additions & 0 deletions tests/samples/load_module_text_test_samples/file_correct
@@ -0,0 +1,26 @@
[key1]:
Hello, there! How are you? I hope you are enjoying reading this test suit!
[key2]:
Hey, you still there? []
[key3]:
This should work with multiple lines.
Line 1
Line 2
Line 3
Line 4
Line 5
[key4]:
done.
[key5]:
[key6]:





The one above should have an empty value.

[key7]:

This value should be ok

Empty file.
11 changes: 11 additions & 0 deletions tests/samples/load_module_text_test_samples/file_repeated_keys
@@ -0,0 +1,11 @@
[Sagan]:
If you wish
to
make an
apple pie
from scratch
you must first invent the Universe.

[Sagan]:
Extraordinary claims require
extraordinary evidence.
@@ -0,0 +1 @@
[this]: This file has text, but does not have a key.
20 changes: 20 additions & 0 deletions tests/samples/load_module_text_test_samples/file_wrong_key
@@ -0,0 +1,20 @@
[key]:
This key is fine.

[k1y3]:
This is also fine.

[~???????????????\\\\\\]:
This should give an error.

[So, how are you]:
This should not work.

[]]:
This also should not work.

[[]:
Neither this.

[[]]:
Neither this.

0 comments on commit fa872ad

Please sign in to comment.