Showing posts with label bug squashing. Show all posts
Showing posts with label bug squashing. Show all posts

Thursday, July 5, 2012

Never start or shutdown a service in android.test.ServiceTestCase.setUp() or tearDown()

Setting up your service setUp() or stopping it in tearDown() will break your test-case. Most probably a NullPointerException will be thrown somewhere. Both errors happen independently, but have in essence the same cause: the internal state keeping of ServiceTestCase.

The class Service does not keep track of the service life-cycle state, i.e. whether the service has been created, started, or is about to be destroyed. That is why the ServiceTestCase defines a number of state variables for tracking the state: mServiceAttached, mServiceCreated, mServiceStarted, and mServiceBound. The problem lies with mServiceCreated. Let's check it out in detail.

Calling startService() in setUp()

Starting the service in setUp() might cause an error during testServiceTestCaseSetUpProperly()—and for that matter, during any other of your own tests.

In my case it was only testServiceTestCaseSetUpProperly() that failed with an error. It is the sole test-case defined by ServiceTestCase. Its purpose is to detect improperly configured tests. I does only one thing: calling setupService().

My service was still very rudimentary, resembling the local service example from the API docs of class Service. The test failed during the tearDown(). Per default, tearDown() shuts down the service. This includes invoking onDestroy() on the service. There occurred a NullPointerException. The implementation of my onDestroy() method is as follows:

@Override
public void onDestroy() {
    // Cancel the persistent notification.
    mNM.cancel(NOTIFICATION);
    // Tell the user we stopped.
    Toast.makeText(this, R.string.music_player_stopped, Toast.LENGTH_SHORT).show();
}

Surprisingly the variable mNM (of class NotificationManager) was null, though it was initialized properly in onCreate():

@Override
public void onCreate() {
    mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    // Display a notification about us starting.  We put an icon in the status bar.
    showNotification();
}

So, when did it went null again? Well, never! Due to calling startService(…) in setUp() it just never had been initialized! It was initialized once, all right. And that was during startService(…). But right after that, testServiceTestCaseSetUpProperly() called setupService(), which will create a new service instance, but will not start it—i.e. onCreate() will not be invoked upon it. So my precious—and initialized—service instance was silently exchanged against an uninitialized one. That alone would not be fatal, were not the state variable ServiceTestCase.mServiceCreated still set to true, thus signaling that onCreate() had been invoked on the service. And because of that, tearDown() will happily invoke onDestroy() upon a service instance whose onCreate() method never had been called. Smells a bit like a bug to me…

Calling shutdownService() in tearDown()

In the case of the shutdown the cause of the error is easy to pinpoint: ServiceTestCase.tearDown() also shuts down the service—and the API docs clearly say so. It is understandable that a second attempt will fail, finding its underlying service gone. Or is it? The error happens in ServiceTestCase.shutdownService(), in line 10 of the following listing:

protected void shutdownService() {
    if (mServiceStarted) {
        mService.stopSelf();
        mServiceStarted = false;
    } else if (mServiceBound) {
        mService.onUnbind(mServiceIntent);
        mServiceBound = false;
    }
    if (mServiceCreated) {
        mService.onDestroy();
    } 
}

The call to ServiceTestCase.tearDown() has just executed this very same code once and afterwards nullified the service instance. However, mServiceCreated is (again) still true, although the service is already destroyed. In fact, this status variable is never re-set to false anywhere in ServiceTestCase. Thus onDestoy() will be invoked on a null reference.

Conclusion

The moral is, never call startService(…) in setUp() and never shutdownService() in tearDown(). It would be nice however, if the official documentation would impress a little more upon that. Also, a little less unforgiving implementation seems possible. Basically that would mean to just re-set mServiceCreated to false in two or so places.

Tuesday, June 12, 2012

Backlight control causes hard reboot on Macbook Pro

Since installing Fedora on my aged first-generation Macbook Pro I was plagued by intermittent reboots. They mostly occurred during the boot process, while logging into KDE, and—less often— when the system was up and running. No need to mention this was a disaster and it pretty much cured me from using a file system that deems a fsck-tool of no great import.

At least for the latter crash-type, I was able to pin-point the culprit: it was the black-light control. Whenever KDE dimmed the panel there was a solid chance the system would reboot—no kernel panic, no stopping. Not even kdump would break its fall. Sure enough, disabling dimming would cure that.

Display dimming can be disabled in KDE's «Engery Saving Settings»

Now I am waiting for the next crash during reboot before blacklisting the «apple_bl» kernel driver. But maybe the Linux kernel 3.4 that ships with Fedora 17 has mended this issue already. Lets wait and see.

Wednesday, April 25, 2012

Update: Address field completion works in KMail git master

Yesterday I was still in doubt if KDE bug #259949 (which prevents KMail from suggesting recipients while typing) was indeed fixed in Git. But as of now I can confirm that it works:

Screenshot showing KMail addressline completion working.
KMail addressee completion as to come in KDE 4.9


This screen shot was taken on my notebook today. The notebook's 32bits installation seems to be less fragile than the 64bits version that runs on my workstation. On the latter Akonadi still refuses to start.

From what I gather the data is produced by directly querying Nepomuk.

(Note: this posting appeared originally on tumblr on the April 25th.)


p.s. Fedora updated KDE to 4.8.2 which also fixed the bug.

Till Adam reports KDE bug #259949 (address line completion) fixed

Tim Adams reported to the KDE Users mailing list that bug #259949 will be fixed in KDE release 4.9. This is good news indeed as this little nasty plagues a lot (all?) of KDE 4.8 users.

The unfortunate side of this news is that I picked exactly this bug for investigation myself. It was a great motivation for diving into the KDE platform. But then again, why not dissect it anyway? Plus,
two days ago my clone of the master branch of the KDE platform still exhibited the bug.
I will be back shortly with a report on how to set up and debug the KDE platform from sources.

(Note: this posting appeared originally on tumblr on the April 24th.)