Browse Source

DEV-3951-calculator (#1706)

* feat(calculator): add new exercise to scripting piscine

* test(calculator): fix swapped exit codes for error handling

* docs(calculator): clarify function behavior for errors

* test(calculator): update error message for invalid number

* docs(calculator): add explicit case statement requirement

improve references section style
add case and getent examples

* fix(calculator): remove getent info in the subject

* chore(calculator): make the solution executable

* test(calculator): add check for case usage

* test(calculator): fix case statement usage check on wrong file

* fix(calculator): remove script added by error

revert changes committed by mistake on Dockerfile and entrypoint.sh

* style(calculator): add newline at end of file
pull/1739/head
Michele 2 years ago committed by GitHub
parent
commit
dc8002d92e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 86
      sh/tests/calculator_test.sh
  2. 66
      sh/tests/solutions/calculator.sh
  3. 96
      subjects/devops/calculator/README.md

86
sh/tests/calculator_test.sh

@ -0,0 +1,86 @@
#!/usr/bin/env bash
# set -euo pipefail
IFS='
'
script_dirS=$(cd -P "$(dirname "$BASH_SOURCE")" &>/dev/null && pwd)
challenge() {
submitted="./calculator.sh $@
"
expected="./calculator.sh $@
"
submitted+=$(2>&1 bash "$script_dirS"/student/calculator.sh "$@")
submitted+="
exit status: $?"
expected+=$(2>&1 bash "$script_dirS"/solutions/calculator.sh "$@")
expected+="
exit status: $?"
diff -U 1 <(echo "$submitted") <(echo "$expected")
if [ $? != 0 ]
then
exit 1
fi
}
# Check if student uses case statement
if [[ $(cat "$script_dirS"/student/calculator.sh | grep case | wc -l) -eq 0 ]]
then
echo "Error: the use of case statement is mandatory"
exit 1
fi
# Valid inputs
challenge "15" "+" "10"
challenge "15" "-" "10"
challenge "15" "/" "10"
challenge "15" "*" "10"
challenge "3491" "+" "-67"
challenge "3491" "-" "-67"
challenge "3491" "/" "-67"
challenge "3491" "*" "-67"
challenge "-3491" "+" "-67"
challenge "-3491" "-" "-67"
challenge "-3491" "/" "-67"
challenge "-3491" "*" "-67"
# Invalid inputs
challenge
challenge "-3491" "*" "-67" "10" "12"
challenge "20" "/" "0"
challenge "20" "@" "10"
challenge "10" "*" "67invalid"
# Test operators functions
source $script_dirS"/student/calculator.sh" 10 + 10 >/dev/null 2>&1
if [ $(do_add 11 14) != 25 ]
then
echo "error in function do_add"
exit 1
fi
if [ $(do_sub 11 14) != -3 ]
then
echo "error in function do_sub"
exit 1
fi
if [ $(do_mult 3 5) != 15 ]
then
echo "error in function do_mult"
exit 1
fi
if [ $(do_divide 50 5) != 10 ]
then
echo "error in function do_divide"
exit 1
fi

66
sh/tests/solutions/calculator.sh

@ -0,0 +1,66 @@
#!/usr/bin/env bash
# Unofficial Bash Strict Mode
set -euo pipefail
IFS='
'
number='^-?[0-9]+$'
do_add () {
echo $(($1 + $2))
}
do_sub () {
echo $(($1 - $2))
}
do_mult () {
echo $(($1 * $2))
}
do_divide () {
echo $(($1 / $2))
}
if [ $# != 3 ]
then
>&2 echo "Error: expect 3 arguments"
exit 1
elif ! [[ $1 =~ $number && $3 =~ $number ]]
then
>&2 echo "Error: invalid number"
exit 4
else
case $2 in
"+")
echo $(do_add $1 $3)
;;
"-")
echo $(do_sub $1 $3)
;;
"*")
echo $(do_mult $1 $3)
;;
"/")
if [ $3 == 0 ]
then
>&2 echo "Error: division by 0"
exit 2
fi
echo $(do_divide $1 $3)
;;
*)
>&2 echo "Error: invalid operator"
exit 3
;;
esac
fi

96
subjects/devops/calculator/README.md

@ -0,0 +1,96 @@
## Calculator
### Instructions
In this exercise you will make a script `calculator.sh` that will take 3 arguments, calculate the result and print it on the standard output.
- The first argument and the third argument will be numbers.
- The second argument will be the operator.
Each operator should have its own function named as follow:
- `+`: `do_add()`.
- `-`: `do_sub()`.
- `*`: `do_mult()`.
- `/`: `do_divide()`.
Each function will receive two arguments, the left number and the right number, and return the result of the operation.
The functions assume that the input is valid, so the input must be checked before calling the functions.
To choose which function to call you must use the `case` statement.
> The functions will also be tested individually, so it is important to name each function exactly as above, the behavior of the functions have to match the exercise instructions.
### Usage
```console
$ ./calculator.sh 20 "*" 3
60
$ ./calculator.sh 20 / 20
1
$ ./calculator.sh -1 - 10
-11
$
```
### Error handling
All errors will print a specific message on **stderr** (ending with a newline) and returns a specific non-zero value:
- Wrong number of arguments: `"Error: expect 3 arguments"`, returns `1`.
- Division by 0: `"Error: division by 0"`, exit with `2`.
- Invalid operator: `"Error: invalid operator"`, exit with `3`.
- Invalid number(s): `"Error: invalid number"`, exit with `4`.
> Negative numbers are also a valid input.
### Hints
- `case` statement example:
```sh
# Check the first argument given to a script
case $1 in
"left")
echo "We will turn left"
;;
"right")
echo "We will turn right"
;;
"top")
echo "We will turn top"
;;
"bottom")
echo "We will turn bottom"
;;
# Any other case
*)
# This is printed in stderr
>&2 echo "Error: invalid argument"
exit 2
;;
esac
```
- Example of a function taking two arguments and returning a value by printing it.
The behavior of this function is the same than the one expected for the operators functions you will create:
```sh
print_full_name () {
name=$1
surname=$2
echo $name $surname
}
print_full_name "Gene" "Mallamar"
```
> Google and Man will be your friends!
### References
- [Bash functions](https://linuxize.com/post/bash-functions/)
- [Test if a variable is a number](https://stackoverflow.com/questions/806906/how-do-i-test-if-a-variable-is-a-number-in-bash)
- [Print on standard error](https://stackoverflow.com/questions/2990414/echo-that-outputs-to-stderr)
- [Case statement](https://linuxize.com/post/bash-case-statement/)
Loading…
Cancel
Save