Configuration to run golang tests under GDB
Native dlv is not supported on all platforms, but gdb has pretty decent go support that works for most cases.
Here is my snippet that allowed me to debug go test file with a simple C-x C-a d on OpenBSD:
;; .dir-locals.el
((nil . ((dape-configs . ((go-test
modes (go-mode go-ts-mode)
command "gdb"
command-args ("--interpreter=dap")
command-cwd (file-name-directory (buffer-file-name))
compile "go test -c -o /tmp/test.bin -gcflags '-N -l'"
:request "launch"
:program "/tmp/test.bin"
:args []
:stopAtBeginningOfMainSubprogram nil))))))
This probably can benefit from more massaging, but is it something you'd be keen on adding to the release? @svaante
Hey something like this could be fine to add, I am not the biggest fan of assuming "/tmp". Maybe one could use (temporary-file-directory) instead.
Would you mind explaining the need for -gcflags?
And how hard would it be to extend the configuration be able to configure the test selection?
Example for how it's done with dlv:
...
:args
(lambda ()
(require 'which-func)
(if-let* ((file-name (buffer-file-name))
((string-suffix-p "_test.go" file-name))
(fn-name (which-function)))
`["-test.run"
,(substring-no-properties (concat "^" fn-name "$"))]
[]))))
...
Maybe one could use
(temporary-file-directory)instead.
Yes. I think it should be used. Hardcoding /tmp is enough for a proof of concept, but not as a way forward.
Would you mind explaining the need for
-gcflags?
Debugging optimized code prevents GDB from showing local variables consistently, so I disabled optimizations. There might be more issues that I haven't seen yet.
I'm not 100% sure if this is really necessary, as I can reliabily print local vars from console, but they are not shown in the Local window. Disabling optimizations fixes all glitches.
And how hard would it be to extend the configuration be able to configure the test selection?
The code from dlv should work as out of the box as GDB runs the same test runner binary with the same runtime arguments. The only difference is that dlv compiles the test for you, whle when using gdb I need to compile test runner by hand.
dlv also places binary in /tmp, but I think it randomizes the executable name a bit better.
@svaante what do you think about that?
(require 'which-func)
(defun dape-go-test-name ()
(if-let* ((file-name (buffer-file-name))
((string-suffix-p "_test.go" file-name))
(fn-name (which-function)))
`["-test.run" ,(concat "^" (car (split-string (substring-no-properties fn-name))) "$")]
[]))
(defun dape-go-test-binary-name ()
(concat (temporary-file-directory) "__test.bin"))
(defun dape-go-binary-name ()
(concat (temporary-file-directory) "__prog.bin"))
;; .dir-locals.el
((nil . ((dape-configs . ((go-gdb-test
modes (go-mode go-ts-mode)
command "gdb"
command-args ("--interpreter=dap")
command-cwd (lambda () (file-name-directory (buffer-file-name)))
compile (lambda () (format "go test -c -o %s -gcflags '-N -l'" (dape-go-test-binary-name)))
:request "launch"
:program dape-go-test-binary-name
:args []
:stopAtBeginningOfMainSubprogram nil)
(go-gdb
modes (go-mode go-ts-mode)
command "gdb"
command-args ("--interpreter=dap")
command-cwd dape-command-cwd
compile (lambda () (format "go build -o %s -gcflags '-N -l'" (dape-go-binary-name)))
:request "launch"
:program dape-go-binary-name
:args []
:stopAtBeginningOfMainSubprogram nil))))))
Sorry for taking such a long time to respond. but this looks great. I have some small pointers, which would be easier to address in an PR.
Would you mind opening up an PR? For this big change an copyright assignment with FSF is needed (see Contribute in the Readme)