Link Search Menu Expand Document

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:

  1. exit normally (without printing anything) if no bugs are found
  2. 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 it
    • echo CKSUM $file if $file has the wrong checksum
    • echo 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 run fstest.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:

  1. 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.
  2. 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
    
  3. 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.