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 run pwd. It should output /etc.
18. The cd command should work with no arguments
Run cd and then run pwd. 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. Run echo $0 ($? is the environment variable that contains the exit code of the last command) and you should see 0, representing an exit code of 0.
21. The exit command should exit with an argument
Run exit 123. The shell should exit. Run echo $0 ($? is the environment variable that contains the exit code of the last command) and you should see 123, representing an exit code of 123.
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