One Last Hurrah


Well, this is it -- my final blog post for DPS909. When I started this course, I was quite honestly dreading what was to come. I'd heard a lot from my colleagues -- even those with prior open-source development -- about how this was one of the hardest courses they have ever taken. I heard that I'd be devoting most of my week to completing the coursework, that the bugs I decided to work on would vanish or get taken by others at the last second, and so on and so forth.

Most terrifying, though, was the fact that I'd never touched an open-source project before. The thought of getting involved in a project like that was paralyzing, and I was dead certain that I was going to make a fool of myself.

And yet, in spite of all of this, I still signed up for DPS909 anyway.

The reason? I needed to beef up my resume.

My first co-op term was coming up, and I didn't have anything software development-related on my resume. Not great, considering I'd be looking for a job in software. Working with open-source projects was the only way I could see to rectify this and gain some experience, so despite all my misgivings, I enrolled in DPS909...

...And that was probably the best decision I've made.

At this point, those extra bullet points on my resume are secondary to all that I've learned. This course gave me the tools I needed to get started in open-source development, including the confidence to get involved. I've mentioned this in several past posts, but I am not a person with a great deal of self-esteem. While it's something I still struggle with to this day, I am much, much more confident than I was when the semester began, and I have my work in open-source to thank for that... And of course, by extension, DPS909, which was nowhere near as difficult as my colleagues led me to believe. It was challenging, but not impossible, and every obstacle brought with it new learning opportunities and knowledge.

Needless to say, my experience with this class has been very positive overall. I think that's enough sap for one day, though -- let's get to looking at what I've been doing this past week, yeah?

Yet Another Fix For Filer

I've mentioned this a couple times now, but the bug I chose to work on was for filer. Yes, this is the third time I've worked on this project in DPS909. I know. I just can't stay away.

Anyway, you can find the issue I was working on here. The gist of it was to refactor the way filer handles flags when opening files.  For those who haven't dealt with file systems before, this just means telling the system what you want to do with the file -- if you want to read it, write to it, append to it, create it, etc.  For filer, if you wanted to open a file with write permissions, the line of code would look something like this:
fs.open("/file.txt", "w");
Pretty simple, right?  First argument is the name of the file, second argument defines how the file gets opened/what it's prepared for.  There's also a third argument for the callback function, which is executed when fs.open finishes opening the file.  But we don't care about that for the purposes of this bug fix -- the only thing that actually matters here is that "w".

Originally, filer parsed the flags as a string -- so "w" or "w+" or "wx+", and so on.  There was no support for numbers, which is where my bug fix comes in.  Someone wanted to be able to pass something like 2 or Constants.fsConstants.O_WRONLY, both of which are just other ways of saying "w" in filer.

Refactoring things to use numbers instead of strings sounds like a pretty big task, but honestly it's not all that difficult.  You can see the specific changes I made by looking at my pull request, but this is the gist of what I did:
  1. Create a function to convert strings like "w" to numbers, which really ended up being one giant switch case.  The numbers I needed were already defined for me in the form of NodeJS' constants; all I did was return the appropriate constant for the appropriate flag.  In some cases, this meant using the bitwise | operator when there were multiple constants that applied.

    Lines like that looked a little something like this:
    case 'wx+': return Constants.fsConstants.O_WRONLY | Constants.fsConstants.O_RDONLY | Constants.fsConstants.O_CREAT | Constants.fsConstants.O_EXCL | Constants.fsConstants.O_TRUNC;
  2. Use that new function in the pre-existing open function (and anywhere else files could be opened).  This meant that no matter what happened, the flag would always be a number by the time it had to be used/validated/etc.
  3. Change any instances of flags as strings into numbers.  In other words, that meant changing if (flags == "w") to if (flags & Constants.fsConstants.O_WRONLY).  Note the bitwise & operator there.
  4. Refactor the function that validated the flags.
  5. Remove the old object that used to hold the flags when they were in the form of strings, along with associated variables.
  6. Create a new test to make sure that fs.open would work properly if passed a number.
Putting everything in a list like this makes it seem pretty easy... And honestly, it wasn't horribly difficult.  By which I mean, everything except for refactoring the validate_flags function was fairly easy, because oh boy, validate_flags did not want to cooperate.  It failed me on approximately 110 tests... Which I confirmed by removing any instance of the function and running the tests without it.  With validate_flags not in play, I only failed 8 tests -- all of which were related to, unsurprisingly, not validating the flags being passed to fs.open.

At this point, though, I was at a total loss for how to proceed.  How on earth was I going to go through 110 tests?  How on earth was I going to go through 110 tests without debugging tools?

Yeah, you heard me: no debugging tools.  At the time, I wasn't aware that you could run filer's tests manually and use the Chrome debugger to go through things.  At the time, I thought I'd need a miracle to fix all these bugs.

...Or just my professor's guidance.

My professor was the one who notified me of the bug, and offered to guide me through it as I needed the help.  After spending so much time fighting with Aseprite and desperately wishing I had a guide for that bug, I was very happy to have a mentor for this one.  By this point, my professor had actually helped me a few times before, too -- once with getting started and understanding what was required of this fix, and a second time when I wasn't sure what to do about some old objects in the code that were no longer used.

To be honest, I did feel a little guilty asking for help.  I didn't want to waste his time, especially with "dumb questions".  I know, I know, there's no such thing as a dumb question, but old habits die hard.

Fortunately, I am not so stubborn anymore that I will sit and suffer in silence (usually).  I reached out to my professor in class, and he sat down and patiently walked me through how to debug things using filer's manual tests and Chrome's debugger.

Armed with these new tools, fixing 110 failed tests seemed very manageable all of a sudden.  Yes, there were still a lot of failures, but at least I could actually debug things properly.  That, and there was no way all 110 tests were failing because of 110 separate bugs.  

(At least, I really hoped that wasn't the case.  I think I'd cry if I introduced that many bugs in one fell swoop.)

It took about an hour and a half of working to iron out all the issues in the code I'd written.  I was right about most of it being related to the validate_flags function, but there was another bug hiding in there too.  In JavaScript, the number 0 is considered "falsey".  This means that an if-statement that does something like this:

if (!flags) {...}

Will return false when flags has a value of 0.  This is unfortunate considering that 0 is the number that represents the "read" flag, which led to fs.open failing to open anything with said "read" flag.  To say that's an issue would be an understatement.  The obvious solution (to me, anyway) was to just add a condition to make it look like this:

if (!flags && flags != 0) {...}
Nice and easy!

From that point on, it was pretty smooth sailing.  I've already added some tests to filer, so adding yet another one wasn't difficult.  All that remains now is to wait for my code to be reviewed, and see what additional changes have to be made!

While this may be the end of DPS909, I don't think it will be the end of my open-source career.  I enjoy working with open-source, and you can bet I'm going to take this course's successor, DPS911, if my schedule allows for it.

Comments