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> $'
! !