Assignment 5 Guidelines for Testing
Guidelines for assignment testing
Before you submit your assignment, be sure that you clean up your code and test the assignment.
Clean code
Avoid submitting sloppy code. It's a reflection on the quality of your work. Check that:
- The name of ALL team members appears in a comment at the top of the code as well as in a separate README file
- The code is nicely formatted and properly intented.
- You're not mixing spaces and tabs in your indentation.
-
Variable names make sense. If you have names like
temp1
,temp2
, change them. - If you use malloc to allocate memory, you should free it using free.
-
Your code is well commented. This does not mean that every line gets a comment but be sure to:
- Have a comment block in front of each function to explain what the function does.
- Explain each variable except for the most obvious ones (e.g., i as an iterator).
- Have blank lines between variables and code.
Testing
These are some of the basic tests that you should run on your program to ensure that it functions reasonably well.
- 1. Empty command #1
- Test: enter just a newline. All that should happen is that you should get another prompt.
- 2. Empty command #2
- Test: enter a bunch of spaces and tabs followed by a newline. All that should happen is that you should get another prompt.
- 3. Exit on end of file
- Enter a control D at the command prompt. The shell should exit cleanly (just like with the exit command.
- 4. A shell prompt for each line of input
- The shell should issue a prompt. The prompt should NOT terminate with a newline. That is, commands will be entered on the same line as the prompt.
- 5. No shell prompt if the standard input is not a terminal
-
Your shell should not print a prompt if the input is not a terminal. For example, if you run:
(echo echo abc;echo echo def;echo echo ghi)|./myshell
You should see something like
abc process 9584 exits with 0 def process 9585 exits with 0 ghi process 9586 exits with 0
- 6. The shell should run a simple command with arguments
-
If you run:
echo hello, world
You should see:
hello, world process 16589 exits with 0
- 7. The shell should print an exit code for each process that terminates.
-
If you run:
echo hello, world
You should see:
hello, world process 16589 exits with 0
- 8. Handle too many arguments gracefully
-
Your shell should warn of too many arguments on a command line and definitely not crash. This command, for example, should be handled gracefully:
echo a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z
- 9. Quotes should be handled properly
-
If you run:
echo "abc" "def" 'ghi' 'jkl'
You should get:
abc def ghi jkl process 9649 exits with 0
- 10. Spaces within quotes should be parsed correctly.
-
Download and compile echoargs.c (from the getopt tutorial). Run
./echoargs 'abc def ghi' "j k l"
You should get this output:
argc = 3 arg[0] = "./echo" arg[1] = "abc def ghi" arg[2] = "j k l"
- 11. Mismatched quotes should be detected and handled gracefully #1.
-
For example, running:
echo 'abc
might produce something like
error: mismatched quote
- 12. Mismatched quotes should be detected and handled gracefully #2.
-
For example, running:
echo 'abc"
might produce something like
error: mismatched quote
- 13. A command should work with a single pipe.
-
ls -laF /|tr a-z A-Z
should produce something like (partial output shown):
TOTAL 100 DRWXR-XR-X 23 ROOT ROOT 4096 FEB 25 07:02 ./ DRWXR-XR-X 23 ROOT ROOT 4096 FEB 25 07:02 ../ DRWXR-XR-X 2 ROOT ROOT 4096 FEB 23 10:20 BIN/ DRWXR-XR-X 3 ROOT ROOT 4096 MAR 3 06:59 BOOT/ DRWXR-XR-X 14 ROOT ROOT 4120 MAR 3 06:59 DEV/ DRWXR-XR-X 102 ROOT ROOT 4096 MAR 3 06:59 ETC/ DRWXR-XR-X 4 ROOT ROOT 4096 JUL 1 2014 HOME/ LRWXRWXRWX 1 ROOT ROOT 33 FEB 25 07:02 INITRD.IMG -> BOOT/INITRD.IMG-3.13.0-46-GENERIC LRWXRWXRWX 1 ROOT ROOT 33 JAN 13 06:49 INITRD.IMG.OLD -> BOOT/INITRD.IMG-3.13.0-44-GENERIC
- 14. A pipeline of three commands should work.
-
This pipeline of commands:
ls -alF / | grep bin | cat -n
should produce something like
process 10121 exits with 0 1 drwxr-xr-x 2 root root 4096 Feb 23 10:20 bin/ 2 drwxr-xr-x 2 root root 12288 Feb 27 07:21 sbin/ process 10122 exits with 0 process 10123 exits with 0
Note: for this assignment, you can print child exits whenever you get them and don't have to buffer them until all child processes have terminated.
- 15. A pipeline of more than three commands should work.
-
This command:
ls -alF / | grep bin | tr a-z 'A-Z' |rev|cat -n
might produce something like
process 10131 exits with 0 process 10132 exits with 0 process 10133 exits with 0 1 /NIB 02:01 32 BEF 6904 TOOR TOOR 2 X-RX-RXWRD 2 /NIBS 12:70 72 BEF 88221 TOOR TOOR 2 X-RX-RXWRD process 10134 exits with 0 process 10135 exits with 0
- 16. Pipes that pass a lot of data should work.
-
This command pipeline:
cat moby.txt |tr A-Z a-z|tr -C a-z '\n' |sed '/^$/d' |sort|uniq -c|sort -nr|sed 10q
Counts the number of unique words in Moby Dick (see the assignment writeup for an explanation of what is going on. You will need to download the file moby.txt.
Your output should look like:
14432 the 6609 of 6430 and 4736 a 4625 to 4172 in 3085 that 2530 his 2522 it ...
If your program seems to hang forever, chances are that you are not running the commands in your pipeline concurrently. Pipes maintain an in-memory buffer to hold their data. When that buffer is full, the program that writes to the pipe is blocked. With small amounts of data, you can get away with writing code that runs one program, waits for it to complete, runs the next one, waits for that to end, and so on. With large amounts of data, it becomes essential that the programs run concurrently so that the next command in the pipeline can read data form the previous one.
- 17. The cd command should work with one argument
-
Run
cd /etc
and then runpwd
. It should output/etc
. - 18. The cd command should work with no arguments
-
Run
cd
and then runpwd
. It should print your home directory. - 19. The cd command should barf when given more than one argument
-
Running the
cd
command with two or more arguments, such as:cd /etc /home
should produce an error message:
cd: too many arguments
- 20. The exit command should exit with no arguments
-
- Run
exit
. The shell should exit. Runecho $0
($? is the environment variable that contains the exit code of the last command) and you should see0
, representing an exit code of 0. - Run
- 21. The exit command should exit with an argument
-
- Run
exit 123
. The shell should exit. Runecho $0
($? is the environment variable that contains the exit code of the last command) and you should see123
, representing an exit code of 123. - Run
- 22. Check that the shell is able to accept at least 10 commands.
-
Run this in bash, replacing myshell with the name of your shell:
(typeset -i i;i=0;while [ $i -lt 10 ];do echo echo $i;i=i+1;done)|./myshell
You're sending the echo command repeatedly, with the argument being an incrementing sequence of digits. Your output should look like:
0 process 11319 exits with 0 1 process 11320 exits with 0 2 process 11321 exits with 0 3 process 11322 exits with 0 4 process 11323 exits with 0 5 process 11324 exits with 0 6 process 11325 exits with 0 7 process 11326 exits with 0 8 process 11327 exits with 0 9 process 11328 exits with 0
- 23. Check that the shell is able to accept at least 1000 commands.
-
Run this in bash, replacing myshell with the name of your shell:
(typeset -i i;i=0;while [ $i -lt 1000 ];do echo echo $i;i=i+1;done)|./myshell
You're doing the same thing but 1,000 times. Your output should look like (truncated here):
0 process 11331 exits with 0 1 process 11332 exits with 0 2 process 11333 exits with 0 ... 997 process 12328 exits with 0 998 process 12329 exits with 0 999 process 12330 exits with 0