Lab4 Part B: Testing CS3650 File System
Section 1: How to write tests for fs3650
For lab4 part B, you will need to write a series of tests to find bugs in (a) your code, and (b) a buggy solution we give you.
For this part we’ll give you two executables - lab4-bug.x86_64
and lab4-bug.aarch64
. If you’re not sure which CPU you have, try them both - you’ll get an exec format error on the wrong one.
To get buggy fs3650 executables, use the following commands:
$ cd ~/lab4
// if you're using ARM CPUs
$ wget https://www.khoury.northeastern.edu/~pjd/lab4-bug.aarch64
// if you're using X86 CPUs
$ wget https://www.khoury.northeastern.edu/~pjd/lab4-bug.x86_64
$ chmod +x lab4-bug.*
Testing buggy fs
To mount buggy fs:
// from lab4 part A, you should have file "test.img" and directory "fs"
$ ./lab4-bug.aarch64 -bug <bug_num> -image test.img fs
where the bug number (bug_num
) can be between 1 and 14 - each bug number results in a different pattern of one or more of the following errors:
- one or more (or all) directory entries may be missing from some directories
getattr
on some files or directories may report incorrect or invalid modes- reads may the correct length, but all zero bytes
- reads may return extra bytes at the end of the file
- reads may be garbled because of one of several common mistakes handling blocks and offset
Specifying a bug number outside of 1..14 (or no -bug
argument at all) should result in correct operation.
Targets and tools
You’ll want to test the following:
- directory contents
- file and directory attributes
- file contents, using different read lengths
To do that we’ll use the following commands:
ls
, or better yet(cd directory; echo *)
stat
cksum
dd
Expected test outputs
For our grading script to work, your script needs to:
- exit normally (without printing anything) if no bugs are found
exit 1
if an error is found, printing a description of the error first:echo DIRNAMES $dir
if$dir
is missing (or has extra) names in itecho CKSUM $file
if$file
has the wrong checksumecho MODE $path
if$path
has the wrong mode
Note that you need to print exactly one line, with DIRNAMES, CKSUM, or MODE followed by the path of the offending file or directory, and exit with the value 1.
Note that some of the “bug modes” will fail lots of different tests, and you may get different results from another student if you do your tests in a different order. That’s OK - we’ll check against a list of possible errors for each bug mode.
Section 2: Ground truth
To check what goes wrong for the buggy fs, you need the ground truth of the working fs3650 instance (i.e., test.img
). You can get all the information you need from the output of this command:
$ python3 print-disk.py test.img
however we’ll provide tables of the information below. You can also run lab4-bug
without the -bug
option.
Directory contents
Here are the directory contents - note that one of them is empty:
fs/ : dir dir1 dir2 dir-with-long-name file.1 file.2
fs/dir : file1 file2 file3
fs/dir1 : long-file-name subdir
fs/dir1/subdir :
fs/dir-with-long-name : 2nd-file-with-long-name
fs/dir2 : twenty-six--character-name twenty-seven-character-name
File attributes
You should check the mode and size of each file and directory. You can do that with the stat
command, using the following format string - %s
is size in bytes, and %f
is mode (unfortunately in hex):
$ stat -c '%f %s' filename
The following table has the correct values for each file in test.img, with the mode field in hex:
# name permissions size
fs/ 41ff 4096
fs/dir 41ff 4096
fs/dir/file1 81ff 100
fs/dir/file2 81ed 1200
fs/dir/file3 81ff 10111
fs/dir1 41ed 4096
fs/dir1/long-file-name 81ff 1025
fs/dir1/subdir 41ed 4096
fs/file.1 81ff 900
fs/dir-with-long-name 41ed 4096
fs/dir-with-long-name/2nd-file-with-long-name 81ff 200
fs/dir2 41ed 4096
fs/dir2/twenty-seven-character-name 81ff 100
fs/dir2/twenty-six--character-name 81ff 100
fs/file.2 81a0 2000
File contents
First we check the file contents using the cksum
utility, which reads in 4KB blocks, and prints out two numbers - a checksum and the length in bytes.
updated (03/29) (see also this piazza post.) Here are the checksums of all the files:
# file cksum
fs/dir/file1 3405207784 100
fs/dir/file2 2363425951 1200
fs/dir/file3 4010891928 10111
fs/dir1/long-file-name 2473152292 1025
fs/file.1 3660301625 900
fs/dir-with-long-name/2nd-file-with-long-name 1100315716 200
fs/dir2/twenty-seven-character-name 3615276204 100
fs/dir2/twenty-six--character-name 1609569549 100
fs/file.2 80949033 2000
Note that when you read the file normally (via cat
or cksum
) it will generate 4KB reads to fs_read
. You’ll want to test smaller and larger read sizes, using the dd
command - you should get the same checksums.
// read 97 bytes at a time:
$ dd if=fs/dir/file1 bs=97 status=none | cksum
// read 5000 bytes at a time:
$ dd if=fs/dir/file3 bs=5000 status=none | cksum
(“if” = input file, “bs” = block size, “status=none” = don’t print lots of status messages. Don’t blame us for dd
having the most obscure command syntax of any Unix utility…)
Section 3: Putting everything together: a script
Finally, you will need to put your test cases into a script. If you are good with shell scripting, feel free to implement a short, pretty script.
However, there’s nothing wrong with basically writing down a list of commands you could type at the terminal. Note that name=$(cmd)
sets the variable $name
to the output of cmd
, and variables (and other $
expressions) are expanded inside of double quotes (but not single quotes).
// [updated 03/29: see "Testing directory contents" below]
// names="$(cd fs/dir; echo *)"
// if [ "$names" != "file1 file2 file3" ] ; then
// echo DIRNAMES fs/dir
// exit 1
// fi
s="$(cksum fs/file.1)"
if [ "$s" != "3660301625 900 fs/file.1" ] ; then
echo CKSUM fs/file.1
exit 1
fi
m="$(stat -c '%f %s' fs/dir1)"
if [ "$m" != "41ed 4096" ] ; then
echo MODE fs/dir1
fi
x="$(dd if=fs/file.1 bs=300 status=none | cksum)
if [ "$x" != "3660301625 900" ] ; then
echo CKSUM fs/file.1
exit 1
fi
and so on. (note that cksum
prints the filename if you provide it as an argument, but doesn’t if it’s checksumming standard input)
Testing directory contents updated (03/29) (see also this piazza post.)
Getting a list of names in a directory that you can compare in an if
statement is a bit tricky. If you use ls
, then they’re on separate lines, and the resulting string won’t compare equal to the same list of names separated by spaces. If you use echo *
then the order of the names isn’t defined. (ls
is guaranteed to sort the filenames unless you give it weird options)
The following code will give you a variable containing (a) all the names in a directory, (b) sorted in alphabetical order, (c) separated by single spaces. Note that neither line has any double quotes - adding quotes will mess this up.
names=$(ls $dir)
names=$(echo $names)
Note that one line in the table you were given didn’t give the names in alphabetical order - it should be:
fs/dir2 twenty-seven-character-name twenty-six--character-name
Exercise 5 Testing buggy fs3650.
- Write a shell script to test different bug numbers (1..14).
- Name your script:
fstest.sh
. (The autograder will runfstest.sh
for grading.)$ cd ~/lab4/ $ touch fstest.sh // create your script $ git add fstest.sh // add it to git // use your favorite editor to edit fstest.sh ... $ chmod +x fstest.sh // set fstest.sh to be runnable
- You should also test your implementation:
$ make mount // mount your fs3650 from Part A $ ./fstest.sh // test on your own fs3650
Finally, submit your Lab4 part B
Submitting consists of three steps:
- Executing this checklist:
- Make sure you have added (
git add
)fstest.sh
that you created. - Note please create a
slack_b.txt
and$ git add slack_b.txt
. - Fill in
~/lab4/slack_b.txt
with (1) your name, (2) your NUID, (3) slack hours you used, and (4) acknowledgements.
- Make sure you have added (
- Push your code to GitHub:
$ cd ~/lab4 $ git commit -am 'submit lab4 part b' $ git push origin Counting objects: ... .... To ssh://github.com/NEU-CS3650-labs/lab4-<username>.git 7337116..ceed758 main -> main
- Actually submit your lab via Gradescope:
- Navigate to https://www.gradescope.com/ and click on log in.
- Select login with “School Credentials” and select “Northeastern University”.
- Enter Northeastern SSO login information and you should be able to log in to your gradescope account.
- Now, on Canvas, go to the CS3650 course and click on “Gradescope 1.3” from the left navigation bar. You will then be asked to accept the course invitation after which you can access the course on Gradescope.
- On Gradescope, select the lab/assignment you wish to submit and click on “Upload Submission”.
- You will then be asked to upload a zip file consisting of the files that the lab/assignment specifies.
Note: you can either zip all the files within your lab folder, or zip your lab folder; its name must start with “lab4-“ (this is supposed to be your GitHub repo name,lab4-<username>
). If you zip a folder named, for example, “mysubmit”, then Gradescope will complain about it and your submission might not work. - After uploading the zip file, the autograder will evaluate your submission and provide a score for it.
- After the manual grading process is performed by the TAs, your final score for the lab/assignment will be released.
This completes the lab4 part B.
Acknowledgments
This lab is created by Peter Desnoyers.