Home | Developer's corner | Knowledge base | Working documents | Documentation | Tutorials | Training | How do I | Frequently asked questions | Technical support |
Using odb, the command-line debugger
ODB is a command-line debugger of TTCN-3 test suites with command syntax similar to gdb. If you are already familiar with gdb, you will find it easy learning odb.
First, you need to make sure that OpenTTCN server daemon openttcnd is up and running. OpenTTCN server daemon is typically started using the ot start command from the command line prompt. If openttcnd is not running, odb would refuse to start.
To start odb from the command line, type:
C:\Demo>odb
You will see a command prompt of this kind:
OpenTTCN Debugger odb Windows Copyright 2007 OpenTTCN Oy All Rights Reserved Build date: Jun 21 2007 Built with OpenTTCN SDK 2.56.0.RC7 (odb)
From the odb command prompt, type:
(odb) help
This will print you the list of available commands. To get more help, type help more.
Let's imagine that we are debugging the following excerpt of TTCN-3 code (file main.ttcn):
1 module ModMain
2 {
3
4 type component CompType
5 {
6 var charstring compVar := "Supplied value #1";
7 }
8
9 function RecursiveFactorial(integer arg) return integer
10 {
11 if (arg < 0)
12 {
13 log("RecursiveFactorial(): invalid argument.");
14 setverdict(fail);
15 stop;
16 }
17 else if (arg == 0)
18 {
19 return 1;
20 }
21
22 var integer f := RecursiveFactorial(arg - 1);
23 return arg * f;
24 }
25
26 testcase TC_Recursive() runs on CompType
27 {
28 var integer n := 5;
29
30 log(RecursiveFactorial(n));
31 log(RecursiveFactorial(3));
32 log(RecursiveFactorial(2));
33 log(RecursiveFactorial(1));
34
35 setverdict(pass);
36 }
37
38 }
First, we need to compile main.ttcn into a precompiled test suite. OpenTTCN uses the concept of precompiled test suite representation that is similar to Java bytecode, except that it is stored in OpenTTCN system repository (database) rather than in a class or JAR file as it is done in Java. In fact, OpenTTCN virtual machine is similar to Java virtual machine: it works the same way.
To compile the file main.ttcn, from the command line prompt type:
C:\Demo>importer3 load MyExample main.ttcn
This is enough to get us started.
Now, from the odb prompt, let's attach to MyExample test session that was implicitly created when we compiled main.ttcn. This is done like this:
(odb) attach MyExample Attached to session MyExample.
Let's set the breakpoint for line 30 in main.ttcn:
(odb) b main.ttcn:30 Breakpoint 1 at file main.ttcn, line 30.
Now let's start running the test case TC_Recursive. From the command line prompt, type:
C:\Demo>tester run -f -l MyExample TC_Recursive
In the odb window you shall see the following:
(odb) Starting test case: TC_Recursive Breakpoint 1, TC_Recursive at main.ttcn:30 (mtc) (odb)
We have stopped right before executing line 30.
Now we can inspect values of local and component variables, as well as formal parameters visible in the currently selected stack frame of the currently selected test component (this time it is mtc). By default, innermost stack frame is selected every time when a break condition is reached. The p command will print variable values:
(odb) p n 5 (odb) p compVar "Supplied value #1"
Let us now step into RecursiveFactorial function call at line 30. This is done using the s command:
(odb) s Stepping into. Breaking into RecursiveFactorial at main.ttcn:11 (mtc) (odb)
We can now examine the call stack trace:
(odb) bt * #0 RecursiveFactorial at main.ttcn:11 #1 TC_Recursive at main.ttcn:30
Currently selected frame is marked with an asterisk. Having a frame selected defines a context in which variables are looked up by the p command. Component variables are invisible if the relevant function does not define a runs on clause. Another frame can be selected using the frame command. We would leave it as an exercise for the reader to figure out what is going on in the next batch of odb commands:
(odb) p arg 5 (odb) p n **ERROR** (odb) p compVar **ERROR** (odb) frame 1 Selected frame #1 (odb) bt #0 RecursiveFactorial at main.ttcn:11 * #1 TC_Recursive at main.ttcn:30 (odb) p arg **ERROR** (odb) p n 5 (odb) p compVar "Supplied value #1"
It is also possible to see the list of available test components using the ts command:
(odb) ts * 0 mtc in RecursiveFactorial at main.ttcn:11
Selected test component is marked with an asterisk in the list above. This time we have the only one test component, mtc, so there are no more test components in the list. If there were many of them, it would also be possible to switch between test components using the t command. Selected test component defines a context in which odb operations are performed.
Let us perform a sequence of steps that would bring us to calling RecursiveFactorial one more time, recursively:
(odb) n Stepping over. Breaking into RecursiveFactorial at main.ttcn:17 (mtc) (odb) n Stepping over. Breaking into RecursiveFactorial at main.ttcn:22 (mtc) (odb) s Stepping into. Breaking into RecursiveFactorial at main.ttcn:11 (mtc) (odb) bt * #0 RecursiveFactorial at main.ttcn:11 #1 RecursiveFactorial at main.ttcn:22 #2 TC_Recursive at main.ttcn:30 (odb) p arg 4
Note that the innermost frame #0 is selected and frame numbering has changed. Stack trace shows us that RecursiveFactorial has been called recursively second time. Now we want to step out of the current function call, that is, recursive call of RecursiveFactorial:
(odb) so Stepping out. Breaking into RecursiveFactorial at main.ttcn:23 (mtc) (odb) bt * #0 RecursiveFactorial at main.ttcn:23 #1 TC_Recursive at main.ttcn:30 (odb) p f 24
Several other nested calls of RecursiveFactorial obviously happened in between, so the result of evaluation of RecursiveFactorial(4) stored in the local variable f is 24.
Now if we step out of the last instance of RecursiveFactorial call back to TC_Recursive:
(odb) so Stepping out. Breaking into TC_Recursive at main.ttcn:31 (mtc) (odb) bt * #0 TC_Recursive at main.ttcn:31
As we can see, output of the command line window that runs the tester run command has been updated to show the log statement from line 30.
If we do not want to descend into evaluation of the RecursiveFactorial function, we can use the n command (alias for next, meaning 'step over'):
(odb) n Stepping over. Breaking into TC_Recursive at main.ttcn:32 (mtc)
Notice that the output of the tester run command line window has been updated one more time to display the output of another log statement on line 31.
Now let us let execution continue freely until next break condition is reached:
(odb) c Continuing. Execution finished.
As there were no more break conditions on our way to the end of the test case, test case has finished and pass verdict was assigned, as can be seen from the output of the tester run window.
Now we can exit odb using the q command. It is important that you exit odb properly, as proper exit unregisters odb from the session to which it was attached before. Keep in mind that you need to exit odb while openttcnd daemon is still running (i.e. before doing ot stop).
If your test case hangs for some reason and is not responding, under Windows you can use Ctrl-C in the tester run command line window to terminate test execution. Under Linux, the way to terminate a test case that does not respond would be opening another terminal window and typing tester term MySession there. In both cases, if odb was attached to that session, it should receive an “execution finished” notification.