Playing Around With Code

I’ve decided that this is too important to postpone, so I’m actually playing around with code. I’m trying to leverage as much of the code that is already there, though, so I’ve changed the format of the XML concurrency definition a bit:







I’m using the <threadcheck:def> node to designate a concurrency definition. It differs from <threadcheck> and other configuration file nodes, but makes it still apparent that these definitions are part of the Thread Checker. I guess I could have moved a lot more around, but this seems to be the easiest option to create mutually compatible and interchangeable XML files.

I think I’ll also name the annotation first, with the limitation that each definition can only have one annotation, and then list the methods and classes as individual tags, with their names stored in attributes.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

A Whole Week With a Wicked Cough

Edit: I should probably warn you that this post contains some rather gross details about the virus infection I seem to have now. If you don’t like to read about snot and vomit, please don’t continue to read.

By now, I’ve spent a whole week with a really bad cough. It started last Tuesday morning. I felt congested and had trouble breathing. By the end of the day, I was coughing up phlegm, but the phlegm was so thick, it didn’t really get all the way up to my mouth.

On Wednesday, my girlfriend brought me some Robotussin, and of course that helped. I also forced myself to stay hydrated better, but the cough was still nearly incapacitating, especially socially, since people typically don’t enjoy getting spat at. On Thursday, I decided that the cough was coming from so deep in my lung, especially since my rib pain had returned (diagnosed as costochondritis, inflamed rib cartilage, in November 2006 after a similar illness), I didn’t actually want to inhibit coughing, I want to encourage it and try to make the phlegm thinner. So I got a bottle of Mucinex. That, and massive quantities of Gatorade (close to 1.5 gallons) seemed to help a bit. The mucus is thinner, it is productive, although because I stopped taking Robotussin, I cough more often. Thursday night, I was still happy, because my phlegm was clear.

When on Friday morning my phlegm had turned the color of dark mustard, or “pale goldenrod” as House would say, I decided to call Health Services and ask for an appointment. I expected one on Monday or Tuesday, but there was a 4 PM available on Friday. Great. Now I just literally had to hang in there until that late.

I went to the compulsary COMP 600 seminar (which I would have skipped, had it not been for the doctor’s appointment), I was one of only three people in COMP 312, the class I hang out in. I wrote a little on my thesis, and then it was 4 PM.

I breezed right past the people waiting in line. That was nice. The nurse asked a bunch of questions and awkwardly typed them into their still new notebooks. She measured my body temperature after I had said I didn’t believe I had a fever but I did have chills. No fever. I don’t think I’ve had a fever in 15 years. To not spite the odds, I’m buying one now, though.

Then Dr. Jenkins came in and seemed to be a bit in a Friday-late-afternoon-mood, but who can blame him. He’s a great guy and I think he’s one of the best doctors I’ve known when it comes to sports injuries. I repeated my symptoms — sinus congestion, headache, postnasal drip, sore throat, trouble breathing, really thick phlegm, and the recurrence of the costochondritis — and he looked in my mouth, ears and nose, and felt the lymph nodes in my neck. He listened to my lungs from the back, and all seemed clear. He declared it’s a viral infect, there’s nothing I can do, I should just continue taking what I’ve been taking — Mucinex (guaifenesin). And if I want, I can add Robotussin (dextromethorphan), a cough suppressant, because studies have shown no negative impact. On the other hand, I’ve been told not to suppress the cough, and even to spit the phlegm out instead of swallowing it.

This morning I felt like crap again. The mornings and evenings are really bad. Later in the day, it wasn’t so bad. I think it has to do with hydration. Because of the Mucinex, I’m shooting for about 1.5 gallons of Gatorade a day. It does its part in making the phlegm thinner. When I haven’t had any fluids after sleeping, of course the symptoms are worse. This week, on several occasions I have coughed so hard, I made myself vomit — please understand, this had nothing to do with nausea or dizziness. It was just the pressure of the cough. It’s really disgusting and I’m sick of it.

The strange thing is that I had something similar in November 2005, and occasionally during almost the
last year and a half since then. Back then, I went to a doctor after my sputum turned yellow and was diagnosed with a viral infection and not treated, because there was no treatment for viral infections. While in the last year, I was usually able to function quite normally, and even bike at a relatively high performance, I’ve always had the feeling that I never quite recovered. I could usually get by just by not inhaling all that deep, but the fact that inhaling deep sends me, an absolute non-smoker, into a coughing fit and the rib pain located only on the right side of the sternum are still troubling for me.

Now that I have this harsh cough again, and while it has gotten better, no real end is in sight, I’m beginning to feel like I’m being undertreated, or treated in the wrong way: My sputum was and is yellow and the rib pain has returned, and to me, that sounds to me like a bacterial infection. My entire medical history points towards bacterial infections, I’ve very frequently had bacterial bronchitis. I’m against over-prescribing antibiotics, so I didn’t argue, but I’m not sure I’m being treated correctly.

I’m feeling slightly better now, especially during the day, but the mornings are still terrible and the evenings are bad. I also feel disgusting because I’m spewing mucus everywhere. My girlfriend also seems to have caught something, and we’re waking each other up with our coughs.

I think if this problem lingers on again for a few weeks, I am going to get a second opinion and get a chest X-ray. I believe I know my body pretty well, and most of the time, I know what I have, and even what I will get prescribed, before I visit the doctor. During my last three clinic visits, I predicted the correct eye drops I’d get, I self-diagnosed a rotator cuff injury in my right shoulder down to the exact muscle, and I narrowed down the rib pain to either costochondritis or pleurisy. I often get the impression that doctors don’t guess much better than I do. And no, I don’t think I’m a hypochondriac, I just try to inform myself about stuff I do have, and every one of my problems has been confirmed by a medical professional, even though the diagnosis may sometimes differ (viral vs. bacterial) Sure, there’s the “Butterfly effect” and maybe my suspicions get confirmed exactly because I inform myself, but I don’t think I’m Munchhausen either. ;-)

So, let’s hope that this goes away soon. I may have to go to Rice Health Services some time next week, maybe I can get a second opinion from Dr. Ware already, just by directing her how to use her stethoscope. If she can’t give me anything better, then I guess I’ll have to go to a hospital and maybe get a lateral X-ray image or an ultrasound of my lower right lung, and spend some money.

I hate hospitals and spending money…

Share
Posted in MS Thesis, Ramblings, Uncategorized | Leave a comment

Print This Post Print This Post  

Concurrency Delineation

I just contemplated one of the basic problems of concurrent programming: The “contours” of the concurrent program, the different threads, usually don’t conform to the “contours” of the object-oriented programming language. There may be one class, and a hierarchy underneath it, and a second class with its hierarchy, but threads can and often do cut completely across object-oriented boundaries. That’s why it’s so hard to separate things out and specify what should only be run in one thread.

My project can definitely help. However, I just realized that there might be a specialization of my work that can help even better: In addition to providing a class definition, like Java already does, and perhaps adding thread annotations to it, I can provide a concurrency definition that specifies what gets executed in what thread. It’s basically an inverted XML file that I have used so far.

The XML files so far were based on the packages and classes, just like class definitions. A concurrency definition would do it the other way around, it would be based on the invariants and list packages and classes.

Consider, for example, the following XML file from this post, which specifies simple invariants:









The concurrency definition as an XML file would look like this:









It merely lists all the invariants, and then the classes and methods that belong to it. That way, there should be a clear delineation between what is part of one thread (or rather: one invariant) and what isn’t. This would be in addition to the class definitions. Of course, internally, these XML files would be translated into the regular annotations.

I’m intrigued. The question now is whether I’m gonna interrupt my writing to program this.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Finished Digitizing Comments

I’ve finished entering the hand-written comments now — a total of 105, if I’m not mistaken — and am preparing to print them out again. Kind of ironic. But I think that’s the best way to remind me of them.

With the comments, I’m close to 110,000 words.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Digitizing Hand-Written Comments

Over the last few days I’ve been pretty much floored with what seems to be a viral infection. I was at first worried that it might be bacterial when I noticed a change of color, but Dr. Jenkins disagreed, and told me to continue to do what I’ve done the last five days: Lay low, drink lots of fluids, take some Robotussin and some Mutrinex. Grrreat. By down I’m really sick of oozing from so many places.

I’ve taken the time to re-read my entire blog and mark things that are important or need clarification. Printed out in 12 point font font, my blog is 159 pages long and contains roughly 104,000 words. I find that rather satisfactory and surprising. When I went through it, I found many things that I had forgotten, but that were important to mention, but also many open leads.

Today I tried to digitize the comments, i.e. add them to the blog, but it’s taking it’s time. Maybe I should have done it that way right away, but last Saturday, when I did most of the work, I didn’t want to take a laptop with me when I was eating my strawberries at the cafe.

I think it’ll take another day to get the remaining comments into the blog. But I’m just having trouble staying up for too long, working, and doing my every-day-chores like cleaning, shopping, and laundry. At least the last two are done for now. I think now I’ll watch a movie and fall asleep.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Another Small DrJava Bugfix

I committed another small DrJava bugfix, revision 4213, that corrects a problem with breakpoints: They were one off. I studied the recent changes and noticed that the method that was used to calculate the line number for the breakpoint had recently been switched from being 1-based to 0-based. I merely reversed the fix.

I did this fix while I was at the office, before the mandatory COMP 600 seminar on Friday at noon. I really only came to the office for the seminar and a doctor’s appointment at 4 PM. I wrote a little bit on my thesis, but not much, and sent out a few emails about COMP 312, a class in which I’m neither a student nor a TA.

The doctor said I have a viral infection, the chances that it’s bacterial are 1-to-100, even though my feelings and my history tell me it’s bacterial, because I observed a color change this morning. But hopefully the doctor is right: I’m strongly against the overprescription of antibiotics. I know my body pretty well. The doctor said getting guaifenesin as expectorant over-the-counter was a very good idea, and I have to agree, I think it helped. I’m coughing more, but more easily. I also try to keep extremely hydrated, chugging quarts of Gatorade, to thin down the mucus. I just had the feeling that I was coughing something up from extremely deep in my lungs, something that was supported by the return of the pain in my lower right ribs, near the sternum, something that was diagnosed as chostochondritis last fall (actually, that was one of my two choices before I went to see a doctor). Therefore I decided to discontinue taking dextromethorphan, because I didn’t want to suppress my cough. The doctor, however, told me that there’s no evidence that dextromethorphane inhibits the healing process by preventing coughs. So now I’m taking both; I keep them separate so I can dose them in a more targeted approach.

I feel like I’m getting better, but mornings and evenings are still very bad, and I have trouble sleeping. I hope this will be over soon. I’m tired of feeling like the Mississippi delta.

Share
Posted in DrJava, MS Thesis | Leave a comment

Print This Post Print This Post  

DrJava Relapse

Today I figured I should go to the group meeting again, and once I got to the office and the lab, I started playing around with YourKit again. It’s just such a great tool. What I was trying to figure out was how we could profile while running the entire unit test suite. My intuition tells me that this might more accurately show us some bottlenecks, rather than randomly using it as an application.

I found out that I can choose the Java executable that Ant will use to launch itself by setting the JAVACMD environment variable. Unfortunately, forked JUnit tests in the task aren’t launched that way, and right now our DrJava unit tests only work in forked mode. So I let that issue drop. I didn’t want to relapsed into working on DrJava too much anyway.

But then I did. Because we received a bug report that I judged as critical: [ 1679178 ] 100% CPU use when compiling. Under certain conditions — very reproducible, just had to use the attached project — the DrJava compiler would go into an infinite loop and consume all CPU power (of one core, at least).

I first used YourKit to diagnose the problem. There were an incredible number of calls to File.equals and String.indexOf… millions of them! That didn’t seem right. The culprit was the CompilerErrorModel._calculatePositions method: In a rare corner case, one that the original programmer had missed, the line number of the error received from javac would not match the line number information we had, in this case due to Windows/Unix line ending incompatibilities, and the error number was not incremented. Hence, the same error was processed infinitely.

I couldn’t really do anything about the wrong line endings, but at least I removed the infinite loop…

Share
Posted in DrJava | Leave a comment

Print This Post Print This Post  

Lots of Writing

The last week and a half, I’ve mainly spent writing. I’m working on my MS thesis, and of course, I’m running behind. I’m not sure if I can complete everything on time, but I’ve signed up for graduation this semester. Regardless of whether I’ll make it or not, that’s a good thing (except for my pocketbook; if I don’t graduate, I’ll pay a fine), because if I hadn’t signed up, I probably wouldn’t be writing right now with this much ferocity. I’m consciously trying to stay away from getting involved in other activities.

Right now, I’m averaging about four pages a day, but I don’t care too much about the wording and I frequently write something while realizing that it’s in the wrong spot. I’ve rearranged my thesis several times already. I also just added a chapter. That was a result of printing out this very blog and starting to go through it for important information. I knew keeping this blog would pay off. The blog printed as 270 pages. I kind of feel like that’s MS-worthy already, but of course the style of writing is much too informal.

Anyway, I’m still going through the blog, marking important passages. Right now, it’s a strictly analog process with a highlighter and a red ink pen, but I’m thinking about how I can digitize the effort. Maybe I’ll add comments.

I’ve been in touch with the JUnit people and have created a completely separate plugin for JUnit 4.x that performs exactly what my modified JUnit does, except that it needs to be optionally invoked using Junit 4.x’s @RunWith annotation. I don’t think this is philosophically the right thing to do, but practically it probably is: Otherwise, thousands of existing unit tests would break.

I also realized that there’s one very important part of a threading discipline for which I don’t provide any suitable predicate: Checking whether an object’s lock (monitor) is actually held. That’s probably one of the most common requirements, right after specifying a certain thread. I added code to do just that, and I abused a side-effect of Object.wait for that: If the object’s lock isn’t held, an IllegalMonitorStateException is thrown. If it is thrown, then I know the lock isn’t held. So I basically do the following:

/**
* Return true if the current thread owns the monitor of the object.
* If this method is directly used in a predicate annotation, then the object
* passed is "this".
* @param o object whose monitor should be checked; must be non-null
* @return true if the current thread owns the monitor (false if o is null)
*/
public static boolean checkMonitorOwned(Object o) {
if (o==null) return false;
boolean interrupted = true;
while(interrupted) {
try {
o.wait(10);
interrupted = false;
}
catch(InterruptedException e) { /* ignore */ }
catch(IllegalMonitorStateException e) { return false; }
}
return true;
}

I’m aware that this can quite severely change threading behavior because of the wait and the timeout of 10 milliseconds, but it should be quite clear by now that full-fledged predicate annotations can be quite dangerous. Anyway, this is a very important addition. The predicate annotations that go along with it (and that are available for download and immediate use now) are OnlySynchronizedThis (which requires the code to be synchronized on this), OnlySynchronizedField (which specifies an object by class and field name whose monitor must be held) and OnlySynchronizedField.ByName (which does the same, but specifies the class by name), and their complements NotSynchronizedThis, NotSynchronizedField and NotSynchronizedField.ByName, which all do exactly the opposite, respectively.

Oh, and I’ve also moved the small Perforce server with just one user, which I’m using as a backup and “time machine”, from the Windows 2003 Server that Dr. Wong has let me use for such a long time to the Linux box that Corky got me. I always wanted to move it to Linux because of the improved scripting capabilities, but I haven’t been able to get those to work yet. So while it may seem like I haven’t done very much recently, and I clearly haven’t written very much, that’s not true.

PS: I have the unfortunate obligation to say goodbye to another Rice friend, Andrew Ladd. He passed away after a long struggle with cancer. I greatly admire him. I can only say that, while he died, he has definitely won his struggle. Goodbye, Andrew. You’ll be missed, too.

Share
Posted in Concurrent Unit Testing, MS Thesis | Leave a comment

Print This Post Print This Post  

Slow-Downs in DrJava

On Friday, before and during COMP 312, the production programming class that drives a lot of the development of DrJava, we discussed the reasons for the apparent slowdown of DrJava. At the beginning, I quite randomly mentioned that the reduced model was in list form and therefore wasn’t set up to handle more complicated requests, such as what class the cursor was in. Naturally it wasn’t set up to do that, that wasn’t on the programmers’ minds when the code was written, and it performs quite well for syntax highlighting, the main purpose, and pretty much acceptably for indenting. I just thought out loud if Barnaby’s attempt to write a tree-shaped reduced model would help satisfy those more complicated queries.

Corky vigorously defended the list-shaped reduced model. I’m not quite sure why, because I wasn’t even attacking it. Then he mentioned the slowdowns of DrJava that he had noticed, compared to about a year ago. A year ago was approximately when I started making major changes to the DrJava codebase and adding features like “Go to File”, persistent breakpoints and bookmarks, “Open Javadoc”, a simple form of code completion, a clipboard history, and “Find All”, all things that I’m sure absolutely nobody wants to miss anymore. Most of these features were driven by my own desire to use DrJava on bigger projects, and I always found something missing; unfortunately, I’m quite sure most people don’t even know about all the things I implemented, even though I documented them quite thoroughly (the first documentation update in a year and a half).

At the same time I had to admit that Corky was right: Opening the DrJava project took about three times as long with a recent version than with a version from January 2006, so something was definitely going on, although I was pretty sure that my changes had nothing to do with it. Sure, many of my changes, especially “Find All”, were not implemented in the best way, but they were implemented solidly with what the DrJava source code gave me. I added a few parts with extremely high code reuse, like the “predictive input dialog” and regions, then I recombined these new things with what was already there. To make “Find All” work, I have to cycle through all documents that contained matches, and this is actually visible in the title bar; however, now there’s a very convenient “Find All” feature (kind of like grep), before there wasn’t, and my code doesn’t do anything that a manual search by repeatedly pressing “Find Next” wouldn’t have done. Well, it does… it highlights the matches, if desired.

I felt like I wanted to prove that my changes had absolutely nothing to do with the slowdown, so I started playing around with the YourKit Java Profiler, a new and fantastic toy that we may use free of charge for our open source project. Just before Corky left for the weekend, I was able to demonstrate that one of the slow parts of DrJava, “Go to Line”, was due to horrible code that abused the list-shaped reduced model: It set the cursor of the reduced model to the beginning, and then moved it, counting newlines. Setting the line seems like a simple setter that should have constant runtime, but this algorithm was actually executing linearly! I promised I would rewrite the code by using Swing information.

When I had done that, I did some more profiling and received puzzling information: While the actual “Go to Line” operation was faster, something else took absolutely forever afterwards; with the old code, it didn’t, probably because something was cached. After some more profiling, I identified that the getter used to update the current line number in the status bar was the culprit. It was written in the same way “Go to Line” was written, and this code was being executed every time the cursor was moved. Absolutely horrible code, and the cause was abuse of the reduced model.

I had never claimed that the reduced model was bad, but I had stated that it wasn’t suited for more complicated queries. Unknowingly we were making unnecessarily complicated queries for “Go to Line” and to find the current line number, we were abusing the reduced model, and totally killing our performance.

By the time I left around 10 PM, I was relieved that my code actually had nothing to do with the slowdown, but I was a bit worried that my lucky guess about the reduced model made me sound “too right”. I was actually pretty worked up over this. I didn’t want to rub anyone’s nose in this, I just made a lucky guess, but I didn’t know how my statements and findings would be interpreted. I went to the lab to do some more profiling and perhaps fix the problems on Sunday, but Corky had already done all the work.

Today at the lab meeting, he lauded my good work profiling and how it helped him fix the problems, and said each and every member of the DrJava team should learn how to use YourKit. I agree, it’s a fantastic tool. I wrote a long email today that described what I had learned about it, but of course, knowing human nature (at least if it is anywhere close to my human nature), I doubt many people actually went through it and tried to use YourKit.

Here’s the email I sent out, just to share my small slice of knowledge with the world once more:

Hi,

I installed YourKit into the javaplt account on CSnet. Here are
instructions if you want to use it. Please note that this is for the
Linux environment on CSnet. For Windows and MacOS, or away from CSnet,
these steps don't apply.

1. The directory YourKit is in is /home/javaplt/packages/yjp-6.0.11
2. Please set the following environment variable, probably in your .bashrc file:

setenv LD_LIBRARY_PATH /home/javaplt/packages/yjp-6.0.11/bin/linux-x86-32

3. To start YourKit, run the following script from the command line:

/home/javaplt/packages/yjp-6.0.11/bin/yjp.sh &

The & at the end will make YourKit run in the background, i.e. you can
still use the same command line window you've been using.

The first time you start YourKit, it should ask you for your license
information as explained in the previous email.

4. You need to pass a special command line argument to your java
executable when you're running a program that you want to profile:
-agentlib:yjpagent

To make that easier to remember, I have written a script that passes
that arguments, and all the argument passed to the script, to java.
It's located in:

/home/javaplt/packages/yjp-6.0.11/bin/yjpjava

So if you want to use it to run a program that you would normally start with:

java MyClass

just use:

/home/javaplt/packages/yjp-6.0.11/bin/yjpjava MyClass

Here is a more complicated example to start DrJava. Instead of writing:

java -cp drjava-15.jar edu.rice.cs.drjava.DrJava

now write:

/home/javaplt/packages/yjp-6.0.11/bin/yjpjava -cp drjava-15.jar
edu.rice.cs.drjava.DrJava

You may want to include the bin directory in your path or make
symlinks to yjp.sh and yjpjava.

5. Note that even though YourKit is running AND you have started your
Java program now, the two aren't automatically linked. To do that,
click on "Connect to locally running profiled application..." in
YourKit's "Welcome" screen. That should open a new pane that displays
CPU and memory usage graphs.

6. When you actually want to record usage times and counts, press the
"Start CPU Profiling" button. That will open another pane. There are
two selections, "Sampling" and "Tracing", and as far as I know,
"Sampling" records times only and doesn't give you invocation counts
and call stacks, but is faster. "Tracing" is a lot slower but gives
you more information.

7. When you want to view the data, i.e. when you're done performing
the action you want to profile, press the "Capture Snapshot" button.
That will bring up a dialog that tells you the file name as which the
snapshot has been saved, and it asks you whether you want to open the
snapshot. You probably want to press "Open" if you want to look at the
data right now.

8. Note that taking a snapshot stops profiling, so if you want to
continue to profile, you need to press the "Start CPU Profiling"
button again.

9. On the page that displays CPU snapshot informations, there are lots
of ways to gather information. I haven't explored everything. I found
selecting "Method List" on the left the most useful. That will give
you a lsit of all methods that were called, and you can sort by name,
time, own time, and invocation count (if you used tracing). Time
includes time spent in calls to other methods, i.e. the time from
method entry to method exit. Own time is only the time spent in the
actual method, i.e. the time from method entry to method exit
EXCLUDING the time spent in other methods that were called.

Usually I found a very sharp break between the times, i.e. going from
40 seconds in some methods (that were probably in a call chain) to 5
seconds. My intuition tells me that the last method to have a lot of
time spent is one of the "hot spots". You should also look at the
invocation count: The program may spend a lot of time in a method, but
if it's called very often, that may not mean very much.

This should really only be a guide to get you started. I'm far from
being an expert in using YourKit, so please play with it and learn by
using it. If you find something useful, perhaps you can let the rest
of us know.

If there are any problems, please let me know. Please also take into
account that we only have licenses for development on DrJava; if we
need additional licenses for DrJava developers, let me know and I will
request them. If you want to get free licenses for other open source
projects, please contact the YourKit licensing people directly.

--Mathias

I really think DrJava is a lot better now than it was in January 2006. I enjoy using it. It has features it desperately needed for big-time development, such as developing DrJava in DrJava, our very mantra. Now that some of the problems that had nothing to do with my additions have been removed, it is even better.

Share
Posted in DrJava | Leave a comment

Print This Post Print This Post  

Goodbye, Ken Kennedy

I just found out that Dr. Ken Kennedy, University Professor at Rice University, died today.

Dr. Kennedy was one of the smartest, kindest men I have met, a true genius, and yet a soft-spoken, humble man. I feel blessed to have had a chance to learn from him.

Thank you, Dr. Kennedy, and goodbye. I will miss you.

Update

Here are two nice obituaries for Dr. Kennedy:

Dr. Kennedy’s funeral ceremony will be held Thursday, February 15 at 3 PM at First Presbyterian Church on Main Street. A reception will be held in Martel Hall on the first level of Duncan Hall and should begin about 4:30 PM.

A reception to celebrate the life of Dr. Kennedy is planned for Monday, February 19 at 3 PM in Duncan Hall DH 3092. Please come and share your fond memories of Dr. Kennedy. I wish he could make it, too.

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

You Know You’re Getting Old…

You know you’re getting old when your minor injuries don’t go away anymore before you acquire new ones. My shoulder rotator cuff injury from last November still hurts a bit, not much, but it’s definitely still there. Sometimes, especially now that it’s cold, I even still feel my back hurt, probably still from my accident in 2005. And every once in a while, like now and the last couple of days, I feel a numb spot on my left upper back, sometimes also on my right. My self-diagnosing skills tell me that might be a pinched nerve at C5. Probably also from the accident, or even from birth. I’m gonna go have that checked out some time soon, it’s just difficult to go because it’s not always there.

I turned in all the forms for my Master’s candidacy. Now I just need to write and defend it… haha. I also improved my Concutest-JUnit some more, and now I think it finally does everything I want it to do without rewriting the Java runtime. But I when I applied it to DrJava, I got annoyed by Ant’s JUnit task: It was too verbose. Even when everything was successful, it generated too much output, so it was hard to find the problem. I decided to download Ant’s source and look how I could shut it up. I ended up writing a new "quiet" formatter (based on "brief") for the JUnit task. The modified source and binary distribution, as well as an archive with just the modified source files and a patch file based off Ant revision 503170k, can be downloaded from my personal homepage.

Now I’m going to a superbowl party. I don’t really know what I care less about, the superbowl or that Germany won the handball world cup. But it’s all about the people you’re with, and I’m with my girlfriend, so I’ll have a great time. I’m told I’m rooting for “da bears” ;-)

Share
Posted in Concurrent Unit Testing, Uncategorized | Leave a comment

Print This Post Print This Post  

Non-Determinism of “Forced Join” Check

Just like most of the ad-hoc dynamic tools I’m developing, the test to ensure “forced joins” does not guarantee that the test is actually correctly written: Threads can be spawned and the main thread does not join them again, but this goes undetected because every time the tests are run, the spawned threads coincidentally happened to terminate before the test ended. The test just catches a badly written test that does not join with spawned threads if this situation actually occurs.

How can I improve the framework’s ability to detect bad tests? How can I detect the lack of joins even if spawned threads always end before the test ends? I think I need to make the check bi-directional: In addition to making the main thread check if there are still spawned threads alive, spawned threads need to check that the main thread joined with them. The problem is that a spawned thread may die before the main thread reaches the join statement, which then just acts as a no-op, so I can’t perform this check at the time the thread dies, because it may be a premature indictment. Too bad, that would have been easy to do…

I guess I should change Thread.start so that it registers the thread in a list, change Thread.join to remove the thread from the list, and then check that the list is empty at the time the test ends. This, of course, doesn’t guarantee that all bad tests are spotted either: It could just coincidentally happen that in the schedule that is executed, the threads that don’t have a join statement aren’t started.

Another low-tech solution that’s not quite as thorough would be to delay thread death for a second or so, so it’s similar to the idea of inserting random delays at synchronization points. If a thread dies later than usual and there’s no join statement, it becomes more likely that the test ends before the thread is dead, and my current check would report the thread as still alive.

Without exhaustive static analysis or execution of all possible schedules, our original scheduled-replay approach, I can’t deterministically conclude that a test is actually successful and correctly written. I can only increase the likelihood that bad tests are caught.

I still believe doing this is worthwhile. The problem with both of these approaches is that I have to modify methods in the java.lang.Thread class. That’s easy for me to do, but it also means that the rt.jar file has to be changed (I may get away with just putting the changed Thread class file in a jar file and putting it at the front of the boot classpath, but there were some limitations to that; I’ll have to check if this is indeed possible), and Corky and I both wanted to limit the changes to JUnit to regular Java, without messing with the runtime. Since instrumenting the rt.jar file consumes both time and disk space, these improved “forced join” checks will probably be an optional enhancement.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

@After and Timeout

I have now changed the versions 4.1 and 4.2 of Concutest-JUnit so that, in the case of a timeout, @After methods are executed before the check for spawned auxiliary threads is done. This now allows the JUnit’s own TimeoutTest to run smoothly.

This test is a testament to the confused state that unit testing of concurrent programs currently is in. The original TimeoutTest starts a test that enters an infinite loop and therefore violates the timeout constraint set. The test fails, TimeoutTest registers the failure, and therefore declares itself to have been passed successfully. This is good, because it demonstrates that time limits for tests work. But in the background, the test with the infinite loop continues to run… and run… and run… and it never finishes. It in fact prevents the Java VM from terminating. And that’s considered a success? It’s ironic that TimeoutTest itself is an example of a badly written concurrent unit test, one that spawns a thread and declares success before the spawned thread has ended.

I have now modified the test to include an @After method that sets a flag and therefore causes the (not-so-infinite-anymore) loop to exit. Without this, my Concutest-JUnit would have declared the test a failure because it concluded before all its spawned threads had died.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Testing Order

I’ve been working a bit more on Concutest-JUnit. Even though I thought I was done, when I ran the tests on different machines, I was still getting errors. Clearly, there were timing problems. I think I got to the root of the problem: Sometimes the main thread continued before the test thread had written the uncaught exception to a field, so success was assumed. I switched the architecture of the “old” style to wait/notify as well.

Then I noticed that in some cases, I was calling notify too early. I called it before I actually threw the exception, so the same problem described above could occur. I rearranged the code everywhere, both in the “old” style and the “new” style portions. I did some refactoring too to improve code reuse.

Now I’m running into another problem: In the “old” 3.8.2-style, where methods are prefixed with “test“, I run the tearDown method before I check if threads are still alive. This allows tearDown to end the “infinite” loop in TimeoutTest. In the “new” 4.0-style code, methods tagged with the @After annotation, the equivalents to tearDown methods, aren’t run until after the check is made if threads are still alive (or more precisely: it’s not guaranteed that they are run before), so an @After method is not always able to kill the “infinite” loop.

What’s the right behavior here? Unfortunately, I’m thinking that tearDown and @After methods are still part of the test, as they perform necessary clean-up. So I guess I’ll have to do some pretty complicated restructuring in the “new” style portion of the code. Or maybe I’ll postpone that for now and accept that there’s a difference in the way “old” and “new” tests behave.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Fixed Concutest-JUnit Issues

I fixed the concurrency problems with Concutest-JUnit. The issues were pretty intricate. I changed the synchronization from a join scheme to a wait/notify scheme. The trickiest bit was getting InterruptedException for timeouts to work correctly: When the test was interrupted because of a timeout, the actual testing thread had to be interrupted as well.

Now I’m testing it with DrJava again. Unfortunately I still have to use the 3.8.2 version, since the 4.0 version isn’t entirely backward compatible, and with the 4.0 version there are a lot of needless RMI exceptions. I’m glad I added the “\_NOJOIN” extension.

The tests that fail so far are:

  • InteractionsModelTest
    • testInterpretCurrentInteractionWithIncompleteInput
  • InteractionsPaneTest
    • testPromptListClearedOnReset
  • IntegratedMasterSlaveTest
    • testItAll
    • testImmediateQuiet
  • ReaderWriterLockTest
    • testMultipleReaders
    • testMultipleWriters
    • testMultipleReadersAndWriters

In the first two cases, the Concutest-JUnit error was “Thread Wait for Interactions to Exit Thread(edu.rice.cs.util.newjvm.AbstractMasterJVM$1) is still alive“. Since I couldn’t figure out how to change the behavior of DrJava quickly, I just added the “\_NOJOIN” extension.

For the next group of tests in IntegratedMasterSlaveTest, the error was “Thread Wait for SlaveJVM Exit Thread (edu.rice.cs.util.newjvm.AbstractMasterJVM$1) is still alive. Again, since I didn’t want to mess around too much with DrJava, I added “\_NOJOIN”.

For ReaderWriterLockTest I insert join() calls. The tests spawned threads, which would eventually end, but it wasn’t guaranteed that this would happen before the test ended. So I added really inconsequential join() calls.

So far, it looks like the DrJava unit tests are written pretty well. There aren’t very many flaws. One thing I plan to do, though, is to tear out the MultiThreadedTestCase that all concurrent threads ought to extend, and see what happens then, because I think that will be more like a typical testing situation.

Share
Posted in Concurrent Unit Testing, DrJava | Leave a comment

Print This Post Print This Post  

Fixing the MacBook

On Monday, I picked up the replacement hard drive for my MacBook. The technician swapped the hard drive out, so I didn’t have to mess around with all the screws on the notebook myself, but he said reinstalling MacOS and trying to recover data from the broken hard drive wasn’t covered by the warranty: I would have had to leave the MacBook at their shop, pay for it myself, and it wasn’t guaranteed they’d get anything off it at all. I decided to reinstall MacOS myself. I’d have to reinstall all the applications again, but I had a relatively new data backup, and all the really important stuff is in a small one-user Perforce repository anyway.

So I reinstalled MacOS and most of the applications, which I got done pretty quickly. By Monday night, most of the applications were there already. Strangely enough, there are a bunch of problems: The newest version of Quicksilver is crashing now, so I rolled back to an older version. Now it works, but it looks and behaves differently, and I can’t get it set up the way it used to be. iTerm, a terminal replacement, is also looking different, but after a lot of experimenting, it looks the same again now. Setting up Fink took forever, I don’t know why. I hooked the MacBook up using wired Ethernet, so I don’t think it was a bandwidth issue. I don’t recall it taking this long when I installed it the first time, and Cygwin, which is similar, doesn’t nearly take as long either. It literally worked for half a day on downloading, installing, compiling and configuring.

Then I restored my data backup… and got a bad surprise: When I had made it, I had just dragged all files over from the MacBook hard drive to my USB hard drive; apparently when I did that, it didn’t copy hidden files, those that begin with a dot, like .bashrc for example. That’s bad. I had to set up my entire Unix configuration again. But now, I think I’ve got it set up again.

Now I’m looking for a way to make a drive image, so that in the future I don’t have to install all applications by hand again. Unfortunately, I haven’t found a suitable equivalent to Norton Ghost yet, and when I experimented, the computer hung, and after I reset, the “drive header” of the brand new hard drive sustained “minor damage”. I’m really worried that it’s not actually the hard drive but something else, and that it’s crapping up the new drive again before I can create a good backup.

I also got the two mobile drive racks that I ordered: I found a good deal on a lower-quality Kingwin KF21-IPF. They have much smaller, less efficient fans, but they were also a lot cheaper, and I hope the big fans won’t be necessary. Now I put the 160 GB VECTOR\_MEDIA drive and the previously unused 20 GB drive into trays for the mobile rack. Unfortunately the rack does not support hot-swapping, for that it would have had to be SATA or USB, and that would have been much more expensive.

I’m using the 20 GB drive as an additional backup drive, so I’m moving the Ghost images onto it. At the same time, I’m copying my collected resources that I mirror on my web server so I can put them on DVD. The network is a big bottleneck right now. I really hope that by the end of the day, I’ll have finished the following tasks:

  • Existing Ghost images on portable hard drive
  • Backup of my web documents
  • Drive image of “vector”, on internal hard drive and portable hard drive
  • Drive image of the MacBook, on internal backup drive “scalar”and portable hard drive

I really wish there was a way to queue up copying tasks instead of letting them run in parallel, which is killing the network performance…

Update

Somehow the computer gods must be conspiring against me: Copying the web documents across the network, 200 minutes remaining; copying Ghost images, 12 minutes remaining. And I’m merely trying to restart the MacBook, but “FileVault is recovering excess disk space” and that’s been taking 30 minutes already. But I’m glad I had FileVault turned on; because of that I didn’t have to worry about the data on the broken hard drive. Hmm. 30 minutes… Is the drive broken again? Should I just turn off the power? Argh.

Update

Finally, the MacBook shut down, and I rebooted from the MacOS installation DVD. I only figured out how to do that last weekend, when I was trying to fix the hard drive by running the Apple Care DVD: You have to press ‘C’ and keep it pressed until the Apple logo appears. There are other keys too, it just took a long time to find them. I checked the integrity of the new MacBook hard drive, and then I tried creating a drive image on a portable USB hard drive. Thankfully the USB drive is accessible from within the Disk Utility on the MacOS installation DVD.

Copying the Ghost images to the other portable hard drive finished, so now I could create a fresh Ghost image of “vector”… if only I had finished copying the web documents. With less network congestion, the estimate now went down from 200 minutes to 40 minutes, but the estimates vary a lot depending on file size, and the web documents often are very small. I tried creating a ZIP archive of them, and copying them was a lot quicker, but there was a problem with the file size of the archive. Files larger than 2 GB create problems (see above). In retrospect, I should have just created a multi-volume ZIP archive.

Update

I don’t believe it. Disk Utility gave me an error message that the image file will be too large! Now I still have to figure out how I can make that MacBook drive image… Apple’s Disk Utility didn’t work, maybe Carbon Copy Cloner will do the trick. Please… please?

Update

I backed up the web documents and I made a fresh Ghost image of VECTOR\_C. I still have to copy it, and some other Ghost images, to a portable hard drive. The MacBook backup using Carbon Copy Cloner apparently is at 60 percent so far. That’ll still take some time, and then I need to test it.

Update

Carbon Copy Cloner ran out of space, and it doesn’t let me backup directly to the USB drive. SuperDuper! just doesn’t work. So right now I have no clue how I can make a drive image of the MacBook.

It’s amazing how much time all this installation and maintenance sucks up.

Update

In the end, I formatted my GigaBank portable hard drive as an HFS+ drive for the Mac, and that allowed Disk Utility to write the entire big image to the hard drive. Now I can’t read it on Windows (without special software), but that’s ok. I guess that’s why I have two portable drives.

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

Officially Nearly Done With New PC

I think I can say I’m pretty much done with the move to the new computer. The old “scalar”, or “tensor” as it should now be called, has been completely gutted now. Gutted and stuffed, kind off. I’ve removed all hard drives, but now I’ve had too many CD drives, so they had to be moved somewhere. Now “tensor” has no hard drives, but three whopping CD drives. At least one of them is even a CD writer, and one of them a DVD reader.

I’ve moved the two SATA hard drives that I’ve had in “tensor” into the new “scalar”, which now has three SATA hard drives and one SATA DVD writer. One PATA hard drive from “tensor” joined the two already in “vector”, so “vector” now also has three hard drives (albeit PATA) and a DVD writer (also PATA). I also took my original IntelliMouse Explorer (version 1) to work and took the mouse I bought for the office, an IntelliMouse Explorer 4.0, back home. Somehow the latest IntelliPoint software wouldn’t let me change the actions for the thumb buttons; they remained at “Back” and “Forward”, something I find pretty useless somehow.

One thing that I may still do is get a mobile rack. Now that I have removed the 2nd optical drive, I have an open 5.25″ slot, and if I put a mobile rack (the Kingwin KF-101-IPF seems to be a good one) in there and get two trays, I could actually use two hard drives: Whichever one I choose to normally hook up to it (probably VECTOR_MEDIA, 160 GB) and the puny 20 GB hard drive that I still have sitting around. And let’s face it: Over time, I’ll have more and more hard drives “sitting around”. The rack and two trays comes out to $41.56 at Directron, and I should still have $27 store credit from Directron’s assembly screw-up that I’d otherwise probably never use.

Now I’m reorganizing files on “vector”. That’s my media and web server. I’ve decided to give it separate drives for the media and the web documents. C:\ (C: is named VECTOR, 120 GB) will essentially remain the same, but C:\WebDocs will be moved to D:\WebDocs (D: is named VECTOR\_MISC, 80 GB). What used to be in D:\Music has now become E:\Music due to the shuffling of drives, so I’m copying that to E:\Music (E: is named VECTOR\_MEDIA, 160 GB). That fits well, since on “scalar”, E: is also my MEDIA partition. VECTOR\_MISC will contain the documents of the web server (yes, I’m running a small web server, but it’s really just an online collection of bookmarks and some documents I may want to access from anywhere), about 4.5 GB, and probably also some Ghost backup images, maybe 25 GB. That leaves over 40 GB for additional web space… What could I fill it with?

Some software is still missing or not working correctly on “scalar”. Somehow, my favorite, old, trusted image browsing software from 1999, ACDSee 3.0, only works for the administrator account. I’m not sure, but this may even be a limitation that’s part of the program; it’s pre-Win2k, after all. ACDSee also crashes when it tries to preview videos, and that’s pretty annoying. Nonetheless, I haven’t really found anything else I like. I also need to install TeX and Ghostscript, both particularly important for my thesis, and perhaps a few games (to make sure writing the thesis won’t be too easy… yeah, right). After that, I’ll make another Ghost image of “scalar”.

Hopefully my MacBook, “manifold”, will be fixed on Monday. Then I can do another round of installing there. I should really look out for a Mac version of Ghost. Maybe it even already works. I lost a couple of data files only, and if the MacBook hard drive is gone, then I lost a small DrJava refactoring in progress, but that’s it. My backup scheme is pretty solid, since all the important data is mirrored across many computers. But installing all the applications and getting the settings just right again, that’s what takes time.

Soon we’ve got to start cooking. Diana and I are joining some friends at a potluck. I’ll bring the camera ;)

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

Touch of Death

After I had finished adding my new code to JUnit 3.8.2 and therefore created Concutest-JUnit 3.8.2 (yeah, versions… soon there’s probably also going to be a 4.2 version, because the JUnit people sneakily released versions 4.1 and 4.2 without me noticing), I decided I needed to add tests to JUnit 3.8.2 as well. No problem so far. However, when I standardized the packages, I started getting JUnit test failures and errors in the tests concerning the concurrent portion of the JUnit 4.0 stuff, i.e. the stuff I added to the JUnit 4.0 annotation-style code. So far, I haven’t been able to isolate the problem or even figure out when it started occurring. It seems like it has been there right from the beginning, when I transferred it over from the 3.8.2 style I had originally integrated into the 4.0 library. JUnit is so confusing on the inside, and JUnit tests of JUnit are a category worse, particularly when they are concurrent.

Something that has touched me a lot more, though, was the apparent demise of the hard drive in my MacBook (pictures). On Friday morning, everything seemed ok. I powered the notebook down, biked to school, opened it up at the 600 seminar, it worked for a few seconds, but then I got the spinning beachball of death (so much more pleasant than “blue screen of death”, isn’t it?). I did a hard reset, and after that it wouldn’t recognize the hard drive anymore. I tried to boot with the Mac OS installation CD, but it doesn’t even say a hard drive exists. Fortunately, Corky got us AppleCare, so everything should be all right. I found that the nearest Apple Authorized Service Provider, MacTronics, is conveniently located almost on my way to work. I’ve called in, described the problem, morsed a few serial numbers across the wire, and the nice lady on the phone said she would try to pre-order a replacement 80 GB hard drive for Monday. On Monday I should come in between 1 PM and 3 PM.

Hopefully it’ll be an easy thing. I really don’t have much time for a lot of trial and error, I just got done fixing up my home machine. I guess I should be glad both machines didn’t break simultaneously. I had some work-on-progress data on the MacBook that wasn’t backed up, but not too much. Installing all the applications will be cumbersome again, because… guess what? I don’t have a Ghost image with all the apps and settings. I don’t even know if there is an equivalent program for the Mac.

I sorely miss the MacBook already after just one day. It’s just the perfect combination of Unix environment, solid keyboard, nice display, good looks, pretty UI, decent stability. I really do a lot of work on it. So, hopefully I’ll have it back on Monday.

Share
Posted in Concurrent Unit Testing, Uncategorized | Leave a comment

Print This Post Print This Post  

JUnit 3.8.1 Modified

I just quickly moved over the changes from my 4.0-based source to the JUnit 3.8.2 source. I found that, when being restricted to the Java 1.4 API, debugging information is a lot harder to get. I can’t find stack traces of the threads involved, for example.

When I ran the DrJava unit test suite with the modified version of JUnit 3.8.2, I got these results:

Testsuite: edu.rice.cs.drjava.model.GlobalModelJUnitTest
Tests run: 14, Failures: 1, Errors: 0, Time elapsed: 18.958 sec

Testcase: testJUnitAllWithErrors
(edu.rice.cs.drjava.model.GlobalModelJUnitTest):
FAILED
junit.framework.AssertionFailedError:
test case has one error reported expected:
<2> but was:<1>


Testsuite: edu.rice.cs.drjava.model.MultiThreadedTestCaseTest
Tests run: 1, Failures: 1, Errors: 0, Time elapsed: 0.011 sec

Testcase: testUncaught
(edu.rice.cs.drjava.model.MultiThreadedTestCaseTest):
FAILED
junit.framework.AssertionFailedError:
expected:<1> but was:<0>


Testsuite: edu.rice.cs.drjava.model.junit.JUnitErrorModelTest
Tests run: 4, Failures: 1, Errors: 1, Time elapsed: 6.293 sec

Testcase: testErrorsArrayInOrder
(edu.rice.cs.drjava.model.junit.JUnitErrorModelTest):
FAILED
junit.framework.AssertionFailedError:
the test results should have one error and one failure 1 expected:
<2> but was:<1>


Testcase: testVerifyErrorHandledCorrectly
(edu.rice.cs.drjava.model.junit.JUnitErrorModelTest):
Caused an ERROR
edu.rice.cs.util.UnexpectedException: java.lang.InterruptedException


Testsuite: edu.rice.cs.drjava.model.repl.InteractionsModelTest
Tests run: 10, Failures: 0, Errors: 1, Time elapsed: 1.486 sec

Testcase: testInterpretCurrentInteractionWithIncompleteInput
(edu.rice.cs.drjava.model.repl.InteractionsModelTest):
Caused an ERROR
junit.framework.TestCase$MultithreadedTestError:
The test did not perform a join on all spawned threads.


Testsuite: edu.rice.cs.drjava.ui.InteractionsPaneTest
Tests run: 14, Failures: 0, Errors: 1, Time elapsed: 4.876 sec

Testcase: testPromptListClearedOnReset
(edu.rice.cs.drjava.ui.InteractionsPaneTest):
Caused an ERROR
junit.framework.TestCase$MultithreadedTestError:
The test did not perform a join on all spawned threads.


Testsuite: edu.rice.cs.util.CompletionMonitorTest
Tests run: 2, Failures: 0, Errors: 1, Time elapsed: 0.061 sec

Testcase: testDegenerateSignal
(edu.rice.cs.util.CompletionMonitorTest):
Caused an ERROR
junit.framework.TestCase$MultithreadedTestError:
The test did not perform a join on all spawned threads.


Testsuite: edu.rice.cs.util.ReaderWriterLockTest
Tests run: 7, Failures: 0, Errors: 1, Time elapsed: 0.138 sec

Testcase: testMultipleReaders
(edu.rice.cs.util.ReaderWriterLockTest):
Caused an ERROR
junit.framework.TestCase$MultithreadedTestError:
The test did not perform a join on all spawned threads.

This already looks a lot better than the weird RMI “unmarshall” exceptions. It looks like we have three failed tests due to wrong counts, one due to an InterruptedException, and a whole four tests with bad join policies.

I’ll look at it more in the morning. I don’t really like this 3.8.2 system. It constrains me too much. I want something 5.0, with annotations, so I’ll have to see if I can rewrite DrJava or bring the missing files back to JUnit4.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Additions to JUnit

During the last few days, I continued to struggle with my Concutest-JUnit extensions. The JUnit code inside is an absolute mess; I’m probably stepping on someone’s toes right now, but the code is ugly, overly complex and unnecessarily convoluted, and it’s barely commented (except for important details like “Parts of this method were written at 2337 meters in the Hueffihuette, Kanton Uri”).

I added a @Test annotation parameter to disable the requirement to join with all spawned threads: @Test(forceThreadJoin=false) public void foo() { ... }. In JUnit3-style tests, you can now append the suffix "\_NOJOIN" to a method name to disable forced joins. With JUnit 3, the test above therefore has to be written as public void testFoo\_NOJOIN() { ... }.

I also extended my set of unit tests for the unit testing suite (that’s a rather weird concept, to unit test the unit testing library using the unit testing library being tested; I’m not sure that’s really sound). JUnit4 already includes parameters for timeouts, so I’m not sure if I’m going to add that to my library; it would also have to go into the method name, and that might really get hard to read: public void testFoo\_TIMEOUT30s\_NOJOIN() { ... }.

When I dropped my new Concutest-JUnit jar file into DrJava, I got a bunch of weird RMI exceptions, though. I expected some problems, but not that many. Of course, first I thought I must have done something wrong, and I could understand if changing the threading behavior of unit tests has some influence on RMI. I changed the tests that failed to use the "_NOJOIN" suffix and rewrote my JUnit extensions to use the original JUnit4 code in that case. But I was still getting the exceptions…

So I plugged in the unmodified JUnit4 library, ran the tests, and I was still getting the errors. So the problem was not related to my changes. When I looked closer, I found out that junit.runner.TestCaseClassLoader was deleted when JUnit went from version 3.8.2 to 4.0, and this is a class that DrJava depends on. So despite all claims, JUnit4 is not backward-compatible with previous versions.

I’m sure there is a way to make DrJava work just like before without TestCaseClassLoader, but I’m not familiar with the affected code, neither in DrJava nor in JUnit. Furthermore, Dan reminded me today that we can’t actually bundle JUnit4 with DrJava yet, because JUnit4 requires at least Java 5.0, and we are still supporting Java 1.4. That means for now I’ll also create a modified version of JUnit 3.8.2.

It’s freezing today (literally; I’m wearing three pairs pants concurrently, so far without any deadlocks), it’s almost 6 PM and already dark, so I’m going to bike home now. I’m going to create Concutest-JUnit3.8.2 when I’m at home, perhaps after dinner, or even after dinner and a nap. But that’s ok, I’ve done quite a bit today: Besides my JUnit work, I’ve made four DrJava commits, mainly bugfixes, but also a new “Copy System Properties” button in the “About” dialog to make it easier for users to supply us with important system information.

TTFN.

Update

When I got back from work, I found the SATA cable in my mailbox. Unfortunately, it angled in just the opposite direction. I was still able to route the cable and close the side panel of my new machine, though.

Share
Posted in Concurrent Unit Testing, DrJava | Leave a comment

Print This Post Print This Post