There are two options:
- You can start entire
V E G Aandtendermintand fire instructions at your node and debug the results. - You can attach the
dlvdebugger to the integration tests.
For both you'll need to
- Read and follow instructions in
GETTING_STARTED.mdfirst. - Install
dlvif you've not already done so. InVSCodeyou can do this by launching the "Command Palette" and runningGo: Install/Update Tools, selectdlv, press OK.
Once you have successfully installed V E G A with tendermint these are the steps to let you debug.
-
Build the debug version (with optimisations disabled) of all the binaries with:
DEBUGVEGA=yes make build
If you're on a Mac
make buildwill fail. This is because Mac OS isn't updatingbashbeyond version 3.x (something to do with GPL). The easiest solution is to install a recentbashe.g. withhttps://brew.sh/and then either run the above in the newbashinstance or add your new bash to/etc/shellsand then dochshto change your default shell. -
Use "Command Palette" to run
Debug: Open launch.json. If you didn't already have alaunch.jsonfile, this will create one with the below default configuration which can be used to debug the current package. Enter the following intolaunch.json(which will be by default created insidevega/.vscode/):{ "version": "0.2.0", "configurations": [ { "name": "Debug V E G A", "type": "go", "request": "attach", "mode": "remote", "remotePath": "/path/to/vega", // trading-core "port": 2345, "host": "127.0.0.1", "showLog":true, "trace":"log" } ] }Edit the
"remotePath"appropriately to reflect where your trading-core source code lives. -
Now open ideally two terminal windows. In the first one launch
tendermintas you normally would. To hard-reset the chain and start from scratch usetendermint unsafe_reset_all && tendermint init && tendermint node 2>./tendermint.stderr.out 1>./tendermint.stdout.out
Now launch the
dlvdebugger withV E G Aby runningdlv exec /path/to/vega/cmd/vega/vega-dbg --headless --listen=:2345 --log --api-version=2 -- nodeagain replacing the path to match where your git copy of trading core lives. If all went well you'll see something like:
API server listening at: [::]:2345 2019-10-13T20:37:41+01:00 info layer=debugger launching process with args: [/path/to/vega/cmd/vega/vega-dbg node] debugserver-@(#)PROGRAM:LLDB PROJECT:lldb-1100.0.28..1 for x86_64. Got a connection, launched process /path/to/vega/cmd/vega/vega (pid = 35671). -
Finally in
VSCodeopen the Debug panel and run theDebug V E G Aconfiguration created in the 2nd step above. At this pointV E G Ashould be running. -
Test that
V E G Ais running as expected by e.g. visitinghttp://localhost:3003/statisticsor trying something in the GraphQL playground athttp://localhost:3004/. If all is well you should be able to create users, place orders etc. as normal. More to the point breakpoints, call stack and variables should be usable as normal inVSCode.
-
Build a debug version of the
godogtest harness: from the root of theV E G Acore repositoryDEBUGVEGA=yes go test -c ./integration/... -
Use "Command Palette" to run
Debug: Open launch.json. If you didn't already have alaunch.jsonfile, this will create one with the below default configuration which can be used to debug the current package. Enter the following intolaunch.json(which will be by default created insidevega/.vscode/):{ "version": "0.2.0", "configurations": [ { "name": "Debug Test", "type": "go", "request": "attach", "mode": "remote", "port": 2345, "host": "127.0.0.1", "showLog":true, "trace":"log" } ] } -
Stick a breakpoint somewhere in the code that you know will be triggered by your integration test (this clearly has to be in a
.gofile, not.feature). -
Launch the feature test you care about (in the example below it's
2668-price-monitoring.feature)dlv exec ./integration.test --headless --listen=:2345 --log --api-version=2 -- -godog.format=pretty -- $(pwd)/integration/features/2668-price-monitoring.feature
The
godogtest harness is now running insidedlvand it has launched the integration test you chose. -
Finally in
VSCodeopen the Debug panel and run theDebug Test.
Prerequisites: Vim version >= 8.0 and the vim-go plug-in.
A debug binary can be built using the go test -c command, which works in the same way go build would. Some compiler optimisations, however, can mess up the output when trying to print certain variables (e.g. slices being passed appearing empty, or containing seemingly garbage values).
To disable any and all compiler optimisations we might encounter, simply add the gcflags="ALL=-N -l" option.
To build the vega binary for debugging, then:
go test -c -gcflags="ALL=-N -l" ./cmd/vegaTo build a binary to step through integration tests, simply run
go test -c -gcflags="ALL=-N -l" ./core/integrationThe output will be a binary called either vega.test or integration.test.
As-is, you can use the compiled binary to step through the code in dlv. Setting breakpoints using things like b core/execution/market.go:2107 is quite tedious, though, and only shows you a few lines of code around the breakpoint. Having the ability to set breakpoints and check out variables in our editor is what we're after. To do that, we need to start dlv as a debug server, so we can connect to it from inside Vim:
dlv exec --headless --api-version=2 --listen 127.0.0.1:9876 ./integration.test -- ./core/integration/featuresThe address and port to listen to is arbitrary, but in this particular example, we'll use 9876. In this example we're starting a debug session on the integration test binary. To debug vega.test, just replace integration.test with vega.test (obviously).
Passing in additional arguments/parameters is as easy as just appending -- to the command above and specifying the desired arguments and flags. To run integration tests with a specific tag, for example, the full command looks like this:
dlv exec --headless --api-version=2 --listen 127.0.0.1:9876 ./integration.test -- --godog.tags=LPWrong -- ./core/integration/featuresNow that dlv is running, we can open the code we want to step through in Vim, and connect to our debugger:
vim core/execution/market.goOnce in our editor, just enter the command :GoDebugConnect 127.0.0.1:9876
Debugger buffers will load as you've configured (default is the call stack top left, call stack, arguments, and registers bottom left, runtime and routine info bottom buffer). Open any file, jump to any line where you want to set a breakpoint, and run the :GoDebugBreakpoint (or :GoDebugBr) command.
To start executing the code, run :GoDebugContinue, and the test binary will run until a breakpoint is encountered. From that point on, you can use standard debugger commands (like :GoDebugStep, :GoDebugStepOut, and of course :GoDebugContinue). A full list of commands, what they do can be found by running :h :GoDebug.
The vim-go plug-in documentation also contains a list of default bindings (e.g. F9 for toggling a breakpoint, F5 for :GoDebugContinue), and detailed instructions on how to create your own bindings, how to customise your setup (:h go-debug-settings).
To stop debugging, run :GoDebugStop. This will close the debug buffers, and the dlv process will return.
Seeing what value a variable is set to is arguably the most common thing to do when debugging. Simply run :GoDebugPrint foo to see a full print-out of what a variable actually holds. Seeing as we're dealing with maps and arrays of objects quite a lot. It's important to note that dlv (and by extension vim-go debugging) does not restrict access to unexported fields, so things like :GoDebugPrint order.Price.u[0] work fine. :GoDebugPrint evaluates its argument as an expression, so things like :GoDebugPrint foo == 10 is valid.
Setting a variable to a different value is equally possible, but just like delve itself, this is limited to types like bool, float, int, and uint variants, and pointers. This can be useful when debugging functions that have some boolean argument (e.g. force is set to false, change to true by running :GoDebugSet force true).