tests/GDBDebuggerTestsR.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Thu, 15 Feb 2018 08:46:03 +0000
changeset 103 56bf65352505
parent 101 d8fee2af20b2
child 104 4add55336dfe
permissions -rw-r--r--
Variable objects: preserve the identity of `GDBFrame` and `GDBVariable` objects ...across running / stopped cycle. This means that if given frame remains on the stack between top stops of a program, the `GDBFrame` instance that represents it would be the same (identical).

"
jv:libgdbs - GNU Debugger Interface Library
Copyright (C) 2015-now Jan Vrany

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License. 

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
"
"{ Package: 'jv:libgdbs/tests' }"

"{ NameSpace: Smalltalk }"

GDBDebuggerTestCase subclass:#GDBDebuggerTestsR
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	category:'GDB-Core-Tests'
!

!GDBDebuggerTestsR class methodsFor:'documentation'!

copyright
"
jv:libgdbs - GNU Debugger Interface Library
Copyright (C) 2015-now Jan Vrany

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License. 

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
"
!

documentation
"
    Tests for GDBDebugger (using real test programs)         

    [author:]
        Jan Vrany <jan.vrany@fit.cvut.cz>

    [instance variables:]

    [class variables:]

    [see also:]

"
! !

!GDBDebuggerTestsR class methodsFor:'accessing'!

resources
    ^ Array with: GDBDebuggeesResource

    "Created: / 28-02-2015 / 00:45:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!GDBDebuggerTestsR methodsFor:'tests - basic'!

test_02
    | inferior1 thread1 frame1 frame2 |

    debugger := GDBDebugger new.
    self assert: debugger isConnected.

    debugger executable: GDBDebuggeesResource current binaryFactorial1.
    debugger send: 'b factorial'.

    debugger send: 'r' andWaitFor: GDBStoppedEvent.

    self assert: debugger inferiors size == 1.
    inferior1 := debugger inferiors anElement.
    "/ Windows (starting with Windows 10) introduced a new
    "/ multi-threaded program loader so it can load .dll
    "/ faster, supposedly. Therefore there may be couple other
    "/ threads. Hence in windows, only assert that there is
    "/ at least on thread.
    OperatingSystem isMSWINDOWSlike ifTrue:[
        self assert: inferior1 threads notEmpty.
    ] ifFalse:[ 
        self assert: inferior1 threads size == 1
    ].
    thread1 := inferior1 threads anElement.
    self assert: thread1 stack size == 2.
    self assert: thread1 status isStopped.
    frame1 := thread1 stack first.
    frame2 := thread1 stack second.
    self assert: frame1 variables size == 1.
    self assert: frame1 variables first name = 'i'.
    self assert: frame1 variables first value = '5'.


    self assert: frame2 variables size == 4.
    self assert: frame2 variables first name = 'argc'.
    self assert: frame2 variables second name = 'argv'.
    self assert: frame2 variables third name = 'i'.
    self assert: frame2 variables fourth name = 'f'.

    debugger send: 'd'.
    debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.

    self assert: thread1 isDead.

    debugger send: 'quit' andWait: false.

    "Created: / 28-02-2015 / 00:55:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-07-2017 / 13:55:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 19-01-2018 / 09:23:24 / jv"
!

test_03
    | inferior1 thread1 |

    self skipIf: OperatingSystem isMSWINDOWSlike  description: 'Skipped since we cannot interact with inferor on Windows (no TTY support)'.

    debugger := GDBDebugger new.
    self assert: debugger isConnected.

    debugger executable: GDBDebuggeesResource current binaryPressAnyKey.

    debugger send: (GDBMI_exec_run new).

    self assert: debugger inferiors size == 1.
    inferior1 := debugger inferiors anElement.
    self assert: inferior1 threads size == 1.
    thread1 := inferior1 threads anElement.
    self assert: thread1 isRunning.

    debugger send: (GDBMI_exec_interrupt new arguments: #('--all')) andWaitFor: GDBStoppedEvent.

    self assert: thread1 isRunning not.

    debugger inferiorStdin nextPutLine:'X'.  

    debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.

    debugger send: 'quit' andWait: false

    "Created: / 08-03-2015 / 07:42:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 01-06-2017 / 22:30:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-01-2018 / 14:53:19 / jv"
!

test_basic_01
    | timeToExit eventPumpProcess eventDispatchProcess|

    debugger := GDBDebugger new.
    timeToExit := 0.
    eventPumpProcess := (debugger instVarNamed: #connection) instVarNamed: #eventPumpProcess.
    eventDispatchProcess := (debugger instVarNamed: #connection) instVarNamed: #eventDispatchProcess.
    self assert: debugger isConnected.
    self assert: eventPumpProcess isDead not.
    self assert: eventDispatchProcess isDead not.
    debugger send: (GDBMI_gdb_exit new) andWait: false.      
    [ debugger isConnected and:[timeToExit < 2000] ] whileTrue:[
        Logger trace:'Still connected...'.
        Delay waitForMilliseconds: 200.  
        timeToExit := timeToExit + 200.
    ].
    self assert: timeToExit < 2000.
    self assert: debugger isConnected not.
    self assert: eventPumpProcess isDead.
    self assert: eventDispatchProcess isDead.

    "Created: / 24-06-2014 / 09:06:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 31-05-2017 / 22:42:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-01-2018 / 15:29:08 / jv"
!

test_breakpoints_01a
    |  |

    debugger := GDBDebugger new.
    self assert: debugger isConnected.

    debugger executable: GDBDebuggeesResource current binaryFactorial1.
    self assert: debugger breakpoints isEmpty.

    debugger send: 'b factorial'.
    self assert: debugger breakpoints size == 1.

    debugger send: 'r' andWaitFor: GDBStoppedEvent.
    self assert: debugger breakpoints size == 1.
    self assert: debugger breakpoints first func = 'factorial'.


    debugger send: 'del'.
    self assert: debugger breakpoints isEmpty.

    debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.
    self assert: debugger breakpoints isEmpty.

    debugger send: 'quit' andWait: false.

    "Created: / 07-07-2017 / 12:25:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_breakpoints_01b
    |  |

    debugger := GDBDebugger new.
    self assert: debugger isConnected.

    debugger executable: GDBDebuggeesResource current binaryFactorial1.
    self assert: debugger breakpoints isEmpty.

    debugger send: 'b factorial'.
    self assert: debugger breakpoints size == 1.

    debugger send: 'r' andWaitFor: GDBStoppedEvent.
    self assert: debugger breakpoints size == 1.
    self assert: debugger breakpoints first func = 'factorial'.


    debugger send: 'dis ', debugger breakpoints anElement number printString.
    self assert: debugger breakpoints size == 1.
    self assert: debugger breakpoints anElement enabled == false.

    debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.

    debugger send: 'quit' andWait: false.

    "Created: / 07-07-2017 / 12:27:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_breakpoints_01c
    |  |

    debugger := GDBDebugger new.
    self assert: debugger isConnected.

    debugger executable: GDBDebuggeesResource current binaryFactorial1.
    self assert: debugger breakpoints isEmpty.

    debugger send: 'b factorial'.
    self assert: debugger breakpoints size == 1.

    debugger send: 'r' andWaitFor: GDBStoppedEvent.
    self assert: debugger breakpoints size == 1.
    self assert: debugger breakpoints first func = 'factorial'.


    debugger breakpoints anElement enabled: false.
    self assert: debugger breakpoints size == 1.
    self assert: debugger breakpoints anElement enabled == false.

    debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.

    debugger send: 'quit' andWait: false.

    "Created: / 07-07-2017 / 12:34:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_breakpoints_03a

    self skipIf: OperatingSystem isMSWINDOWSlike  description: 'Skipped since we don;t have separate console TTY (no TTY support)'.

    debugger := GDBDebugger new.
    self assert: debugger isConnected.

    debugger executable: GDBDebuggeesResource current binaryFactorial1.
    self assert: debugger breakpoints isEmpty.

    debugger consoleInput nextPutLine: 'b factorial'.
    Delay waitForSeconds: 1.  
    self assert: debugger breakpoints size == 1.

    debugger send: 'r' andWaitFor: GDBStoppedEvent.
    self assert: debugger breakpoints size == 1.
    self assert: debugger breakpoints first func = 'factorial'.


    debugger consoleInput nextPutLine: 'del 1'.
    Delay waitForSeconds: 1.  
    self assert: debugger breakpoints isEmpty.

    debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.
    self assert: debugger breakpoints isEmpty.

    debugger send: 'quit' andWait: false.

    "Created: / 10-07-2017 / 22:05:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 11-07-2017 / 11:06:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-01-2018 / 14:57:37 / jv"
!

test_breakpoints_04a
    debugger := GDBDebugger new.
    self assert: debugger isConnected.

    debugger executable: GDBDebuggeesResource current binaryFactorial1.
    self assert: debugger breakpoints isEmpty.

    debugger send: 'b factorial'.
    self assert: debugger breakpoints size == 1.

    debugger breakpoints first script: 'printf "factorial\n"
disable ', debugger breakpoints first number asString.

    debugger send: 'r' andWaitFor: GDBStoppedEvent.
    self assert: debugger breakpoints size == 1.
    "/ We need to wait a until breakpoint-modifed
    "/ event is received.
    Delay waitForMilliseconds: 200.  
    self assert: debugger breakpoints first enabled == false.

    debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.

    debugger send: 'quit' andWait: false.

    "Created: / 11-07-2017 / 20:35:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (format): / 11-07-2017 / 23:31:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_stack_01
    "Tests that stack frames object are preserved amonh run/top cycles
     if they 're still valid"

    | stack1 stack2 |

    debugger := GDBDebugger new.
    self assert: debugger isConnected.
    debugger executable: GDBDebuggeesResource current binaryFactorial1.
    debugger send: 'b factorial'.
    debugger send: 'r' andWaitFor: GDBStoppedEvent.

    stack1 := debugger selectedInferior threads first stack.
    debugger send: 'c' andWaitFor: GDBStoppedEvent.
    stack2 := debugger selectedInferior threads first stack.
    self assert: stack1 size == 2.
    self assert: stack2 size == 3.
    self assert: stack1 first  == stack2 second.
    self assert: stack1 second == stack2 third.
    self assert: stack2 first line == 4.
    self assert: stack2 second line == 7.

    stack1 := debugger selectedInferior threads first stack.
    debugger send: 'c' andWaitFor: GDBStoppedEvent.
    stack2 := debugger selectedInferior threads first stack.
    self assert: stack1 size == 3.
    self assert: stack2 size == 4.
    self assert: stack1 first  == stack2 second.
    self assert: stack1 second == stack2 third.
    self assert: stack1 third == stack2 fourth.
    self assert: stack2 first line == 4.
    self assert: stack2 second line == 7.
    self assert: stack2 third line == 7.


    debugger send: 'd'.
    debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.
    debugger send: 'quit' andWait: false.

    "Created: / 30-01-2018 / 15:54:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 01-02-2018 / 21:04:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_variables_01
    | variables d |

    debugger := GDBDebugger new.
    debugger executable: GDBDebuggeesResource current binaryVariables.

    debugger send: 'b main'.
    debugger send: 'r' andWaitFor: GDBStoppedEvent.
    debugger send: 's' andWaitFor: GDBStoppedEvent.

    variables := debugger selectedInferior threads first stack first variables.

    self assert: variables size = 3. "/ argc, argv, d.
    self assert: variables first name = 'argc'.
    self assert: variables first varobj expression = 'argc'.

    self assert: variables second name = 'argv'.
    self assert: variables second varobj expression = 'argv'.

    self assert: variables third name = 'd'.
    self assert: variables third varobj expression = 'd'.

    d := variables third varobj.
    self assert: d hasChildren.
    self assert: d children size = 3.

    self assert: d children first hasChildren not.
    self assert: d children first children = #().
    self assert: d children first expression = 'i'.
    self assert: d children first value = '1'.

    self assert: d children third hasChildren.
    self assert: d children third children size = 2.
    self assert: d children third children first expression = 'as_i'.
    self assert: d children third children second expression = 'as_f'.

    self assert: d children third children first hasChildren.
    self assert: d children third children first children size = 2.
    self assert: d children third children first children first expression = 'a'.
    self assert: d children third children first children first value = '10'.
    self assert: d children third children first children second expression = 'b'.
    self assert: d children third children first children second value = '20'.
    
    debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.
    debugger send: 'quit' andWait: false.

    "Created: / 30-01-2018 / 10:27:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"


! !

!GDBDebuggerTestsR class methodsFor:'documentation'!

version_HG

    ^ '$Changeset: <not expanded> $'
! !