Tripoli


Disclaimer: Tripoli is a prototype. It was easy to put in the features that it has; it will be much harder to add/change anything from here. It also has some bugs. Use at your own risk!

About Tripoli

Tripoli is a prototype of a tool to help programmers quickly narrow down where a bug is by looking at which code was executed in one run but not another.

More jargonly, it is a differential code coverage tool implemented as an Eclipse plug-in and based on EclEmma, which in turn is based on Emma.

For example, if you wanted to figure out which code handles changing the colour of a square, you would do two runs. Tripoli would log which methods were executed in both runs, and tell you which were executed in the first run but not the second.

Both runs would run initialization code, code for creating a square, code for creating the colour picker dialog, and code to handle colour selections. However, only the first ("fat") run would run the code to actually colour the square. Tripoli would then tell you about only that square-colouring code.

Tripoli has two ways of teling you. First, it colours the code in your Eclipse source editors. Executable code that was executed only in the first ("fat") run is highlighted in green, while all other code is highlighted in red, as seen in this picture:

It also shows a view listing all the methods that were executed in the first run but not the second, as seen in this picture:

How to install Tripoli

If you already have EclEmma installed in your Eclipse, you will need to remove it, and also clean out any emma.jars that are hiding in various corners of your system. They conflict with Tripoli. Once you have no EclEmma in your system:

How to run Tripoli

To do a diff of two runs, you need to get code coverage information twice and "subtract" the second from the first. This means that your first run needs to be your "fat" run (the run with more code, e.g. ABCDEF), and the second needs to be your "skinny" run (the run with less code, e.g. ABCD).

To do a coverage run, find the Run Coverage button () in the toolbar, to the left of the regular Run () and Run as Debug buttons.

Press the Run Coverage button, and do your "fat" run. Quit, and you should see the Coverage View appear:

Press the Run Coverage button again. Do your "skinny" run and quit the application.

Now that you have your "fat" and "skinny" runs done, you need to diff them. Find the Coverage View, and find the "Diff Sessions" button () in the Coverage View toolbar. Press it.

Congratulations, you now have a Tripoli diff! Lines of code that were in the "fat" run but not the "skinny" run will be green, and all other executable lines will be (well, should be) red.

The coverage information from a run is called a "session". The Coverage View lets you look at information from one session. The Coverage View lists all the classes and methods that were executed in the region of interest. (For non-diff sessions, that of course means the all the lines that executed in the run, not just the diff.) You can change which session you look at via the Select Session toolbar button ().

Don't worry too much about what is in the code coverage percentage column for diff sessions. Those are probably wrong -- I haven't worried about making them be sensible or meaningful. Only worry about whether a method is in the Coverage View list or not. If you want more information, you can read up on the EclEmma documentation. (Just remember that everywhere where the EclEmma documentation says "merge", think "diff".)

Warnings!

The order of your runs matters!
Tripoli effectively subtracts the second coverage run from the first coverage run, so the "fat" run always has to be first and the "skinny" run second. EclEmma is not commutative.

Red is ambiguous!
When looking at a Tripoli diff run, red is ambiguous. Lines that are red include:
  • lines that weren't executed in either the fat or the skinny run
  • lines that were executed in both the fat or the skinny run
  • lines that were only executed in the skinny run
If you really need to know why a line is red (i.e., which of those three conditions it satisfied), you can look at the fat and skinny runs individually by changing the coverage session via the Select Session button () in the Coverage View toolbar.

Don't try to diff more than two sessions!
I am not completely sure what the results mean, but I suspect it is not likely to be what you want.

How to run Triopoli effectively

Experience helps in figuring out what to do in your "skinny" run. (The "fat" run is usually easy -- usually it's just whatever you do to reproduce the problem.) Here is what I have learned so far:

Do as much as possible in the skinny run. Because of how we mentally group actions, it is easy to forget a step that should go in the skinny run. If you want to see what code colours a square, you might be tempted in your "skinny" run to only create the square, then quit. To you, the colour picker dialog is part of colouring the square, but there is a lot of code associated with displaying the colour picker dialog. Unless you display the colour picker dialog, all the colour picker dialog methods will show up in your diff.

In general:

Don't be afraid of doing extra things in your skinny run. Things that are in the skinny run but not in the fat run won't show up in the diff. While you have to be careful that you don't accidentally do anything that is related to the problem area, you can do unrelated things all day long. For example, suppose there was a problem with changing the width of a line via a menu action. In your skinny, for your first try, you might select the line, highlight the menu action for changing the width, slide off the menu item, and then quit. If you then see a bunch of things related to "Undo" in the diff, you might guess that those are generic to all actions, not just to changing the width. In that case, you might want to do a skinny run where you do everything as before, except that before you quit, you change the colour of the line via a menu action. You will probably get a more precise diff that way.

Don't be afraid to try a few different diffs. It is frequently faster to redo a diff than to examine a lot methods, so if you get a lot of methods, try doing something a little different on your skinny run. You might get a more precise diff. And if you don't, you can always go back to the previous diff.

Instead of omitting a step in your skinny run, you can try doing something different. For example, instead of omitting the step where you change the width of a line, try changing the colour instead.

FAQ

Why doesn't Tripoli work for me?
I have done really minimal testing. I run on Linux, and have tried it on Eclipse 3.2 and 3.3.1. I've also done limited testing on Windows Eclipse 3.2. I have no idea if it will work on anything else.

If it is so raw and untested, why are you releasing it now?
Because I'm planning on blogging about the research I just did using Tripoli, and don't want to answer a bunch of email messages that all ask, "Can I try it?" Also, it would be a lot of work -- far, far more than I have alrady put in -- to take it to the next level.

Why do you say it would be a lot of work to improve Tripoli?
First, Tripoli is built on top of Emma, which is built on top of EMMA, and EMMA is not supported. Any changes I want to make to EMMA, I'll have to do myself. Second, EMMA 1.2 is designed somewhat monolithically -- you start it and you get back a session. There's no starting and stopping logging during execution, and I'd like to be able to set "start logging" and "stop logging breakpoints". Third, EclEmma and EMMA really are structured around single sessions, which have one bit of information about lines (hit/not hit). I would need to do a lot of heavy thinking to figure out how to best handle paired sessions. Fourth, I repurposed EclEmma/EMMA's merge function for the diff. It's easy to rewrite EMMA's merge function to allow either merging or diffing based on a boolean that's passed in, but the place in EclEmma that knows if it is a merge or diff has poor communication to the place that does the merge. (NB: I'm sure at least one of the things I said here was wrong (from being uninformed), but I don't know which one, and I bet only one is wrong.)

What did your research show?
With only a slight bit of hand-waving, that Tripoli was really useful. See my technical report for the gory details.

Why is it called Tripoli?
It is an enhanced EclEmma, so EEE, or "triple-E", which, in Canadian English, sounds like "Tripoli".

Why do I have to remove emma.jar from everywhere? What is that file?
EclEmma is built on top of EMMA, which is an IDE-agnostic code coverage tool. I had to make a few changes to EMMA, which are reflected in emma.jar. If you aren't careful about cleaning out the old emma.jar files, Eclipse can use an older copy of emma.jar, which will not give you the results you want.

What changes did you make to EMMA?
I changed the "merge" function to do a "diff" instead. I changed about three lines of code in CoverageData.jar.

I want to do both merging and diffing! Why can't I do both?
Sorry, by the way that EclEmma is written, it was easy to do one or the other but not both. I might fix that someday, but not for quite a while, if at all.

I don't like the the red and the green source line colouring! Can I change the colours?
Yes, you can. See the EclEmma documentation (under Highlighting Preferences).

Why aren't the definition lines of methods or comments ever coloured?
EclEmma does its counting during execution. The definition lines of methods (which look like public int foo(int bar)) don't make it into the bytecode as distinct entities, so they don't get counted. Comments don't make into the bytecode at all, so they don't get coloured either.

Sometimes none of the lines in a file are coloured! Why not?
Sometimes, none of the lines of code in a file will be coloured. This will happen if you modified the code in between the fat and skinny runs. (If you really care about why, email me. Otherwise, just accept it -- explaining it seems to confuse people.) It also happens randomly sometimes. Sometimes there is just a second or two delay before it gets coloured; sometimes it does't ever colour. This is a known bug, but I have no idea what the problem is, and am not sure if it is a Tripoli problem or an EclEmma problem. Sorry. (Remember, this is a prototype!)

What does it mean if a line is coloured yellow?
It means that it is partially executed. See the fine EclEmma documentation on line colouring.


Kaitlin Duck Sherwood