2024-05-27-Testing and Debugging
Test
Idea:
Testing is to find bugs in the code -> The corner cases should be good testing examples
Black Box Testing:
- The tester considers only the expected behavior of the function—not any implementation details—to devise test cases
- Advantages:
- One advantage is that if you have a comprehensive test-suite written before you start, you are unlikely to skimp on testing after you implement your code
- By thinking about your corner cases in advance, you are less likely to make mistakes in developing and implementing your algorithm
Tips:
- Test every corner cases
- Test every error condition
- Test more or less cases
- Examine the datatype
- Test boundary cases
White box tests:
- Statement coverage:
Test whether each statement is executed - Decision coverage:
All possible outcomes are execrised. Cover every edge in the control flow graph. - Path coverage:
Span all possible valid paths through the control flow graph
Generating test case:
- Based on the algorithms to generate large amount of test cases randomly
- Verify: You can improve the confidence by testing the property of your program instead of directly proving your programs.
Assert:
There are some invariants during execution. So we can use some assert statement to check whether they can pertain their property or boolean true value. If they dieobey their property, the program will crash down and print the error message.
Debugging
Scientific method:
- Observe a phenomenon ->
- Raise a quetion ->
- Recursively gather information(assisted by debugger) ->
- Form a hypothesis(testable and actionable) ->
- Verify the hypothesis(Construct testcases; Inspect the internal state; Add asserts; Code inspection)
Intro to GDB
- Process:
- compile codes with debugging symbols:
gcc -ggdb3
- run gdb inside emacs (ESC x or ALT x)
- compile codes with debugging symbols:
- Basic commands in GDB:
- start:
runs the program and stops when execution enters main - run:
runs the program - step:
move forward by a line(go into the function called current line) - next:
advance the program one line of code, but will execute the entire function call - print:
evaluates the expression and prints the results
print multiple elements from an array: eg.p arr[0]@length
print will assign the value you want to print to the internal variables named $-
Notice: up and down can switch between different stack frames to see different variables - display:
display the expression’s value every time gdb stops and display a prompt - backtrace: lists all of the stack frames
- up and down:
switch between different stack frames.
Especiallly useful when the program stops in a failed assert, you can use up to return to the previous stack frames - info:
get information about various aspects of the program. - break:
- set a breakpoint
eg.break function: line
-
Conditional break points:
break 7 if i==25000
or you also usecond
to add conditions
cond <break point number> <condition>
- info breakpoints(i b): check the current states of break points
-
clear <name>
can clear the break points
- set a breakpoint
- until and finish:
- until: causes a loop to execute until it finishes
- finish: causes execution until the current function returns
- watch:
set watch points that can have gdb stop when the value of a particular expression changes
Particular useful when examining coping pointer-related problems, if you worry the pointer is a local variable, you can watch the internal variables in gdb
- start:
- Signals:
- SIGSEGV:
Indicates a segmentation fault and gdb will stop on the line that this fault happens - SIGABRT:
Happens when the program calls abort() or fails an assert - SIGINT:
Happens when the program is interrupted.(eg. the user presses Control-c)
- SIGSEGV: