Search code examples
linuxvisual-studio-codedebuggingrustgdb

How to debug a Rust Integration Test using VSCode + cppdbg


I want to debug a Rust integration test in VSCode using gdb (much better enum support than lldb). I used to use lldb using the fantastic CodeLLDB plugin, where my configuration in launch.json looked like this:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "lldb",
            "request": "launch",
            "name": "run integration test",
            "sourceLanguages": ["rust"],
            "cargo": {
                "args": [
                    "test",
                    "--package=name_of_my_package",
                    "--no-run",
                    "--tests",
                ],
                "filter": {
                    "kind": "test"
                }
            },
            "args": [
                "--exact",
                "--nocapture",
                "name_of_my_test",
            ],
            "cwd": "${workspaceFolder}",
        },
    ],
}

For using gdb, I assume that I would have to use the cpptools extension instead (debug type "cppdbg"), which does not support the "cargo" directive.

How can I create an equivalent configuration to the one above for cpptools?

(or some other extension supporting gdb)

The main problem seems to be getting the correct path of the test binary, which contains a nondeterministic hash. I found nothing better than this question, which is quite old, windows specific, and doesn't have any satisfactory answer. Is there a better solution for this by now?

Worst case, I would not even be opposed to some kind of hack using tasks.json to move/symlink the binary to a deterministic location.


Solution

  • I figured out a hacky way to do it using the tasks.json mechanism I alluded to. This requires jq and xargs on the PATH. The set -o pipefail; can be removed if not supported, at the cost of potentially running an outdated binary.

    If anybody has a better way, I would gladly accept their answer over this.

    my_package_name and my_test_name obviously have to be adjusted.


    tasks.json:

    {
        "version": "2.0.0",
        "tasks": [
            {
                "label": "build_integration_test",
                "type": "shell",
                "command": "set -o pipefail; cargo test --package=my_package_name --no-run --tests --message-format=json | jq -r 'first(select(.executable != null and .target.kind == [\"test\"])) | .executable' | xargs -I@ ln -fs @ ${workspaceFolder}/target/debug/integration_test_bin",
                "group": "build",
                "presentation": {
                    "reveal": "silent"
                },
                "options": {
                    "cwd": "${workspaceFolder}"
                },
            }
        ]
    }
    
    

    launch.json:

    {
        "version": "0.2.0",
        "configurations": [
         {
                "type": "cppdbg",
                "request": "launch",
                "name": "debug integration test (cppdbg)",
                "preLaunchTask": "build_integration_test",
                "program": "${workspaceFolder}/target/debug/integration_test_bin",
                "args": [  
                    "--exact",
                    "--nocapture",
                    "my_test_name"
                ],
                "cwd": "${workspaceFolder}",
            },
        ],
    }