Monday, August 12, 2013

A Recurring Lack of Assertiveness

We recently ran into a problem with jSuneido - when you loaded a certain customer's dumped database it would load successfully but then fail the consistency checks.

After looking at where and how it was failing (a negative size value), I figured the problem was probably that the database had a single table larger than 2 gb and I was using a 32 bit int to store the size of commits so it was wrapping around. Normally commits wouldn't be anywhere near that large, but when bulk loading each table is written as a single commit.

I felt pretty good about finding the problem so quickly and easily.

I put asserts into the code to confirm that this was the problem. But they didn't fail. Hmmm... maybe I put them in the wrong place. I added more asserts in other places. They still didn't fail.

So I fell back on the age old debugging method of inserting print's. Of course, it's a big database with a lot of tables so there was lots of output. I skimmed through it and couldn't find a table bigger than 2gb.

So much for finding the problem quickly and easily!

The next day, at home, I continued working on it, partly just trying to remember how the database code works! On the positive side, I updated some comments and diagrams while I was at it.

Eventually, I ended up full circle, finding that there was indeed a table bigger than 2gb and my original guess about the problem was correct! Argh! (I'd missed it when I skimmed through the prints.)

The problem was that I didn't have assert's enabled, which is why the asserts I added didn't fail. I've been burnt by this before - see Don't Forget to enable Java assert and Burnt by Java assert Again. You'd think I would learn.

Part of the problem is the way Eclipse works. You can set options on JRE's, but when you update to a new version of Java, then you have to remember to set the options again (which I had forgotten to do, both at work and at home). It's too bad there isn't a way to set options that are common to all JRE's.

You can also set options in Eclipse launch configurations, but I have a ton of them, and again (AFAIK) there isn't a way to set default options that are common to all launch configurations.

I thought I had good defenses in place for this. I have a test which confirms that assert is enabled. But I'm using Infinitest to run my tests automatically and it must enable asserts itself. So unless I run the test manually, it's useless for confirming that I have asserts enabled.

I also enable asserts programmatically in the start-up code. But while I was testing I was running specific classes and bypassing the start-up code.

I'm not sure what else I can do to defend against this. Any suggestions?

Thursday, August 01, 2013

Upgrading to Eclipse 4.3 Kepler

Another relatively smooth upgrade.

I downloaded the Eclipse IDE for Java Developers (rather than Standard) since I don't do any plugin development.

See Top 10 Eclipse Kepler Features

I did have one problem on Mac OS X - when you try to run Eclipse you get an error that it is "damaged and can't be opened". I'd run into this before. It's a known issue which, for some reason, the Eclipse developers have closed as "RESOLVED NOT_ECLIPSE" i.e. not their problem. However, as one of the commenters points out, other apps don't have this problem, so it's obviously something Eclipse is doing different if not technically "wrong". It's relatively easy to work around by doing:

xattr -d com.apple.quarantine Eclipse.app/

I imported my plug-ins from my previous Eclipse 4.2 Juno and they all came across without any problems. Even Mercurial still seems to be functional. Here's the list of plug-ins I'm currently using:
  • Bytecode Outline
  • EclEmma Java Code Coverage
  • Checkstyle
  • FindBugs
  • Infinitest
  • MercurialEclipse
  • Metrics plugin for Eclipse
The other problem I ran into is also a known issue - conflicts (giving SecurityException) between the hamcrest-core in the Eclipse copy of JUnit, and hamcrest-library that I'm adding for additional matchers. At first I thought it was because the new version of Eclipse came with a newer version of JUnit, so I upgraded my hamcrest-library to match. But that didn't solve the problem.

I knew I'd run into this before so I went to my blog to see how I'd resolved it. I found Eclipse Hamcrest Runaround and I Give Up but nothing about how I eventually got it to work. It's funny how my blogs have become my external memory and I'm unhappy if I forget to record something.

After searching the web and messing around I realized the easiest solution is just to remove the Eclipse JUnit from the build path and have my own junit, hamcrest-core, and hamcrest-library. That seems to solve the problem.

See also:
Although I don't feel like I'm usually recording much useful information, these upgrade posts are some of my most frequently visited. That may just be because they come up in searches.