Testing, Debugging, and Verification TDA566/DIT082, LP2, HT2013

Exercises Week 3

Here are exercises for Week 3.
Bug Tracking

Go to the Bugzilla bugtracker of Mozilla and answer the following questions:

  1. How many bugs have been entered as new in the last three days?
  2. How many of those are critical or blocking?
  3. 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

  1. 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.


  2. 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?

    1. Write a version noRef.c of ref.c that avoids reference
    2. 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; }
  1. 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.


  2. 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.
  1. 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).


  2. 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.





Home | Course | Schedule | Exam | Exercises | Labs | Evaluation | Tools | Links Moa Johansson, Nov 14, 2012