Testing/Debugging

Q: I’m failing a test on the autograder, but it passes locally. What’s wrong?

A: See the questions below for how to run tests effectively.

Q: How do I see more output from runner.py?

A: Don’t forget the --verbose flag! Use it like so: python3 runner.py --verbose *path to desired .in*.

Q: I got a syntax error on a print statement when I ran the tester.

A: Make sure to use python3, not python!

Q: How do I see what my repository looked like at the end of a test?

A: Add the –keep flag right after –verbose and you should see a new directory for each time a test is run.

Q: runner.py doesn’t seem to be using the latest version of my code!

A: Make sure you ran javac gitlet/*.java!

Q: The autograder doesn’t provide files such as wug2.txt, wug3.txt, and blank-status2.inc! How can I swoop them locally?

A: This is intended - it’ll be a fun challenge to try to reverse engineer their contents based on the contents of the tests that reference them.

Q: How do I run integration tests in IntelliJ instead of the terminal?

To debug using runner.py, first do the following Go to Run->Edit Configurations. Click on the + in the top left corner of the pop-up window. Click on Remote. Feel free to put any name in the Name field. Click OK. Then run the script with the following command from the testing directory

python3 runner.py --debug --lib=PATHTOLIB TEST.in

PATHTOLIB is the relative path to the lib directory located within the library-su20 folder. For me ../su20-s\*\*\*/library-su20/lib and /Users/Zoe/su20-s\*\*\*/library-su20/lib both work. The second option is the path starting from the root directory of my computer (specified by the / in the beginning). This path might be different for you.

TEST.in is just the path to the integration test you would like to run (just like the original python script). On running the script, you will be presented with some instructions on how “debug” mode works. Please read the instructions carefully and we will now have a functioning IntelliJ debugger once again! Note, you can also use the --verbose, --keep, --tolerance, etc. with --debug at the same time if you would like.

Credit to Alex Kazorian for making this script! He’s a real homie :)

Q: Why do I keep getting compiler errors telling me some packages weren’t found?

A: If you have a windows computer, check that your path contains the 61b library files. In Windows Powershell as an Administrator you can execute the following two commands to fix it, if it is not there:

[System.Environment]::SetEnvironmentVariable('CLASSPATH', "$HOME\su20-s\*\*\*\library-su20\lib\*;.", [System.EnvironmentVariableTarget]::Machine)

[System.Environment]::SetEnvironmentVariable('PATH', "$Env:Path;$HOME\su20-s\*\*\*\library-su20\bin", [System.EnvironmentVariableTarget]::Machine)

Also, make sure you’re not using foreign imports in your code – these libraries won’t exist on the autograder.

Q: I am on Windows and unable to pass EC test 11 locally.

A: Due to a quirk with how the test is written compared to the spec, substituting File.separator in for / appropriately will result in a failure. Copy and paste the test from here (include a newline at the end btw) to get a platform-agnostic version that will pass on both Windows and non-Windows based systems.

Q: I’m getting weird characters when writing and reading a String to a file.

A: You’re probably serializing the String before writing it. You can just write the String directly to the file instead, and avoid any extra weirdness caused by the serialization.

Q: I’m failing a test on a line that says «<. What does that mean?

A: On the integration tests, «< is the expected end of a command. If the integration test is formatted like:

> command
Output.
<<<

This means that the test is expecting you to print “Output.” after running command. If instead the test says:

> command
<<<

It is expecting the command to finish without printing anything. You should double check that your command is printing/not printing the correct message and in the correct format (including whitespaces and newlines).

branch

Q: What does HEAD do? Do I always have to move it to point at the latest commit?

A: Kind of. Each branch should have a pointer to its own head commit. The global HEAD points to your current branch. In effect, the head is pointing to a commit (the one master is pointing to), but through the middleman of the branch. This makes it easy to switch between branches and every time you add a commit to a branch, the head is in effect automatically moved to the new commit, since it only pointed at the branch and not a commit specifically.

commit

Q: My commit ID (SHA-1 hash) keeps changing on me.

A: For this reason, my personal recommendation is to assign the ID as an instance variable within your commit class’s constructor after all other instance variables are assigned. Then, create a getter method for the ID, and use that throughout. There are certainly other ways to solve this, but this approach is a near-foolproof solution, so it’s my personal recommendation.

Q: How do I get the SHA-1 hash in the first place?

A: Note that any serializable object (think back to Lab 12) can be serialized via Utils.serialize, and then the result can be hashed using Utils.sha1. Commit objects should be serializable.

log

Q: What does the -0800/-0700 mean?

A: That’s the offset from UTC; for instance -0800 means 8 hours and 0 minutes behind UTC (corresponding to Pacific Standard Time) and -0700 means 7 hours and 0 minutes behind UTC (corresponding to Pacific Daylight Time - what the west coast is currently in). Depending on where you are, testing locally may result in different numbers, and this is perfectly fine.

Q: How do I format the date properly?

A: Take a look at SimpleDateFormat.

Q: Blank lines?!??!?!?!

A: Just include an additional blank line after each commit regardless of whether or not it’s the last one. Only one though, not two.

Q: My output looks identical to the autograder expected output; what’s up?

A: Make sure you lowercased “commit”, have three equal signs, uppercased “Date” and “Merge”, and have an additional blank line after each commit (so that there’s one blank line between commits and one after the last one). Check for any other slight differences, including with your date format.

find

Q: What commits do we look at?

A: All commits ever made.

merge

Q: My merge conflicts don’t match expected output.

A: Make sure you have the right number of signs and that you don’t forcibly append a newline before inserting those signs; if a file contains “hi wug!” with no newline at the end, and you merge it with conflicts, you should have “hi wug!=======” or “hi wug!»»»>”. See the spec for some more on line terminators.

Q: What does the untracked file check do?

A: The failure case There is an untracked file in the way; delete it or add it first is concerned with files that are untracked and would be overwritten. When you’re checking out a branch, you’re restoring all of the files contained in its head commit to the CWD, overwriting whatever contents the current versions of those files might have. If a file isn’t in that commit, it’s not in danger of being overwritten, so it’s not relevant to the error.

Miscellaneous

Q: COMPILER WARNING FOR UNCHECKED CAST / SERIALIZING GENERICS.

A: You can also create a new non-generic blank class that simply extends HashMap<String, String>, and work with objects of that type instead.

Q: Can I serialize the File object pointing to a blob and use that to get its contents?

A: No, the File object only stores the file path, so using it to get the contents would only give you the working directory version of the file. You want to serialize the byte array representing these contents, which can be obtained via Utils.readContents.

Q: I get a warning for a “confusing var-args” call, e.g. with Utils.writeContents.

A: TL;DR it’s safe to ignore them. Basically, with varargs in Java, the additional parameters are all wrapped in an array automatically. When calling varargs methods, Java lets you manually wrap the arguments inside of an array, and then Java will use that array directly. IntelliJ thinks that you’re intending to do this, but you’re actually just intending to pass in one additional parameter - a byte[] - rather than all the individual bytes by themselves. It turns out that since the byte[] is a primitive array, it doesn’t count as an Object[], and therefore the byte[] itself gets wrapped in an Object[], which is in fact what we want. IntelliJ basically thinks you aren’t doing what you want to, but you actually are.