Here are exercises for Week 3.
Bug Tracking
Go to the Bugzilla
bugtracker of Mozilla and answer the following questions:
- How many bugs have been entered as new in the last three days?
- How many of those are critical or blocking?
- How many bugs are present in the current version of the Firefox
web browser? Which of these is the worst problem? Which one would
you address first?
All answers come from properly querying the Bugzilla system. The considerations made on the worst problems are contextual to the bug itself, and when the parameters to define a bug seen in class are the same between two bugs, then considerations must be done also, for instance, on the number of users that can be affected by the bug, and other.
|
Isolating Units
- In
the Observer
Pattern, the observers typically need access to the Subject's state.
Thus, there is a dependency of the Subject on the Observers. Assume you
want to test the Subject in isolation, how would you do it?
One can break dependencies by creating an Observer class called for instance TestObserver whose notify method does nothing.
The subject to test will therefore have as its internal list of observers to notify just objects of kind TestObserver, which will do nothing. In this way the isolation is achieved.
Another way is to overwrite the registerObserver or set the observerCollection empty.
|
- Besides interfaces and abstract classes, there are other
possibilities to break dependencies. If you know about macros (C, C++)
or aspects: how could they be used?
- Write a version noRef.c of ref.c that avoids reference
- Use macro preprocessor to load different code while testing
// value of TEST from environment or call option
#if TEST == UNIT
# define REF "noRef.c "
#else
# define REF "ref.c"
#endif
...
// Here ref.c was originally located
#include REF
|
The following exercises make use of the Java files contained here. The archive contains two Eclipse projects that you can import in your workspace. You can use however any kind of IDE/editor/debugger of your choice.
|
Input Minimization
In the DD directory of the archive you downloaded there is an implementation of the DDmin algorithm seen in the lectures.
Apply this algorithm to the method
boolean geegg(String s)
in class Geegg. Assume this method returns true whenever the string s contains at
least two times the character 'e' or at least three times the
character 'g'. Apply the algorithm to the string "a-debugging-exam" to
find a minimal input that causes geegg() to return true.
Give all intermediate steps of the algorithm, not only the final
result!
Just examine the output of main in Geegg class to see how the algorithm evolves, and compare it with the definition of the DDmin algorithm.
|
Observing Execution
Look at the following Java method that is supposed to compute the
n-th Fibonacci number (in the directory Fib of the archive you downloaded ):
1 static int fib(int n) {
2 int f = 0;
3 int f0 = 1;
4 int f1 = 1;
5 while (n > 1) {
6 n--;
7 f = f0 +f1;
8 f0 = f1;
9 f1 = f; }
10 return f; }
- The program works fine with the exception of the first two numbers
(starting with 0 in Java indexing style). Use a debugger to follow the
execution and find out what is wrong.
Use a debugger as was shown during the exercise session. The problem lies in the initialization of f, which is overwritten in the loop.
|
- Assume we want to know which is the first Fibonacci number that is greater than 1000. How can we use the functionality of
debugger to determine this without changing the code?
Using a conditional breakpoint, at e.g. line 8, with condition f>1000.
|
Tracking Causes and Effects
Use the Fib.java class from above for this exercise.
- For each statement, determine the statement that are data- and
control-dependent on it.
You can refer to the example in the book Why Programs Fail. Chapter 7 (Deducing errors).
|
- Assume we are in the only loop execution of
fib(2) in
the statement of Line 9. Successively compute the backward-dependent
statements. Does this explain why the defect in this program shows
only for the first two Fibonacci numbers?
Indirectly, one can see that when executing within the loop, if one walks backwards the dependencies (control and data), the initialization of f at line 2 is not among the dependencies walked. This means that the cause of infection is removed since the bad initialization value is not propagated inside the loop. So there will not be a failure whenever the loop is entered, but there will be a failure if it is not entered, that is, when n=0 or n=1.
|
|