Merge pull request #3709 from jsternberg/dap-loaded-source-path

dap: properly map source paths to client side paths
This commit is contained in:
Tõnis Tiigi
2026-03-10 18:08:19 -07:00
committed by GitHub
6 changed files with 182 additions and 76 deletions
+5 -6
View File
@@ -7,7 +7,6 @@ import (
"fmt"
"io"
"path"
"path/filepath"
"slices"
"strings"
"sync"
@@ -605,14 +604,14 @@ func (b *breakpointMap) Set(fname string, sbps []dap.SourceBreakpoint) (breakpoi
return breakpoints
}
func (b *breakpointMap) Intersect(ctx Context, src *pb.Source, ws string) map[digest.Digest]int {
func (b *breakpointMap) Intersect(ctx Context, src *pb.Source) map[digest.Digest]int {
b.mu.Lock()
defer b.mu.Unlock()
digests := make(map[digest.Digest]int)
for dgst, locs := range src.Locations {
if id := b.intersect(ctx, src, locs, ws); id > 0 {
if id := b.intersect(ctx, src, locs); id > 0 {
digests[digest.Digest(dgst)] = id
}
}
@@ -620,7 +619,7 @@ func (b *breakpointMap) Intersect(ctx Context, src *pb.Source, ws string) map[di
// Mark unverified breakpoints as failed at this point since we couldn't find an area
// in the source where they applied.
for _, info := range src.Infos {
fname := filepath.Join(ws, info.Filename)
fname := info.Filename
bps := b.getByPath(fname)
for _, bp := range bps {
@@ -640,7 +639,7 @@ func (b *breakpointMap) Intersect(ctx Context, src *pb.Source, ws string) map[di
return digests
}
func (b *breakpointMap) intersect(ctx Context, src *pb.Source, locs *pb.Locations, ws string) int {
func (b *breakpointMap) intersect(ctx Context, src *pb.Source, locs *pb.Locations) int {
overlaps := func(r *pb.Range, bp *dap.Breakpoint) bool {
if bp.Line < int(r.Start.Line) || bp.Line > int(r.End.Line) {
return false
@@ -661,7 +660,7 @@ func (b *breakpointMap) intersect(ctx Context, src *pb.Source, locs *pb.Location
r := loc.Ranges[0]
info := src.Infos[loc.SourceIndex]
fname := filepath.Join(ws, info.Filename)
fname := info.Filename
bps := b.getByPath(fname)
if len(bps) == 0 {
+2 -2
View File
@@ -187,12 +187,12 @@ func TestBreakpointMapIntersectVerified(t *testing.T) {
src := &pb.Source{
Locations: srcLocs,
Infos: []*pb.SourceInfo{
{Filename: filename},
{Filename: fpath},
},
}
ctx := newBreakpointTestContext(t)
digests := bm.Intersect(ctx, src, ws)
digests := bm.Intersect(ctx, src)
wantMatches := 0
for _, bc := range breakpointCases {
if bc.expectVerified {
+25 -16
View File
@@ -2,9 +2,9 @@ package dap
import (
"context"
"path"
"path/filepath"
"slices"
"strings"
"sync"
"github.com/docker/buildx/build"
@@ -31,10 +31,10 @@ type thread struct {
variables *variableReferences
// Inputs to the evaluate call.
c gateway.Client
ref gateway.Reference
meta map[string][]byte
sourcePath string
c gateway.Client
ref gateway.Reference
meta map[string][]byte
sourceInfoMap func(*pb.Source) *pb.Source
// LLB state for the evaluate call.
def *llb.Definition
@@ -107,14 +107,21 @@ func (t *thread) init(ctx Context, c gateway.Client, ref gateway.Reference, meta
t.c = c
t.ref = ref
t.meta = meta
t.sourceInfoMap = func(s *pb.Source) *pb.Source {
s = s.CloneVT()
for _, sinfo := range s.Infos {
// Map the filename from the source info from the frontend location to the
// client location.
fname := strings.Replace(sinfo.Filename, inputs.DockerfileMappingDst, inputs.DockerfileMappingSrc, 1)
// Combine the dockerfile directory with the context path to find the
// real base path. The frontend will report the base path as the filename.
dir := path.Dir(inputs.DockerfilePath)
if !path.IsAbs(dir) {
dir = path.Join(inputs.ContextPath, dir)
// Convert to an absolute path.
if abspath, err := filepath.Abs(fname); err == nil {
fname = abspath
}
sinfo.Filename = fname
}
return s
}
t.sourcePath = dir
if err := t.getLLBState(ctx); err != nil {
return err
@@ -252,7 +259,7 @@ func (t *thread) getStackFrame(dgst digest.Digest, next *step) *frame {
f.setNameFromMeta(meta)
}
if loc, ok := t.def.Source.Locations[string(dgst)]; ok {
f.fillLocation(t.def, loc, t.sourcePath, next)
f.fillLocation(t.def, loc, next)
}
t.frames[int32(f.Id)] = f
return f
@@ -296,7 +303,6 @@ func (t *thread) reset() {
t.c = nil
t.ref = nil
t.meta = nil
t.sourcePath = ""
t.ops = nil
}
@@ -462,9 +468,12 @@ func (t *thread) getLLBState(ctx Context) error {
return err
}
if t.sourceInfoMap != nil {
t.def.Source = t.sourceInfoMap(t.def.Source)
}
for _, src := range t.def.Source.Infos {
fname := filepath.Join(t.sourcePath, src.Filename)
t.sourceMap.Put(ctx, fname, src.Data)
t.sourceMap.Put(ctx, src.Filename, src.Data)
}
t.ops = make(map[digest.Digest]*pb.Op, len(t.def.Def))
@@ -483,7 +492,7 @@ func (t *thread) getLLBState(ctx Context) error {
}
func (t *thread) setBreakpoints(ctx Context) {
t.bps = t.breakpointMap.Intersect(ctx, t.def.Source, t.sourcePath)
t.bps = t.breakpointMap.Intersect(ctx, t.def.Source)
}
func (t *thread) seekNext(ctx Context, from *step, action stepType) (string, *step, map[string]gateway.Reference, error) {
+2 -2
View File
@@ -38,7 +38,7 @@ func (f *frame) setNameFromMeta(meta llb.OpMetadata) {
// TODO: should we infer the name from somewhere else?
}
func (f *frame) fillLocation(def *llb.Definition, loc *pb.Locations, ws string, next *step) {
func (f *frame) fillLocation(def *llb.Definition, loc *pb.Locations, next *step) {
for _, l := range loc.Locations {
for _, r := range l.Ranges {
if next != nil && f.Line != 0 {
@@ -57,7 +57,7 @@ func (f *frame) fillLocation(def *llb.Definition, loc *pb.Locations, ws string,
info := def.Source.Infos[l.SourceIndex]
f.Source = &dap.Source{
Name: path.Base(info.Filename),
Path: filepath.Join(ws, info.Filename),
Path: info.Filename,
}
// If we do not have a next operation, then we don't have
+49 -50
View File
@@ -107,7 +107,7 @@ COPY --from=base /etc/bar /bar
`)
dir := tmpdir(
t,
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
cmd := buildxCmd(sb, withDir(dir), withArgs("build", "--progress=quiet", "-f-", dir))
@@ -124,8 +124,8 @@ COPY foo /foo
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
dirDest := t.TempDir()
@@ -149,8 +149,8 @@ COPY foo /foo
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
dirDest := t.TempDir()
@@ -176,8 +176,8 @@ COPY foo /foo
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
dirDest := t.TempDir()
@@ -209,8 +209,8 @@ COPY foo /foo
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
dirDest := t.TempDir()
@@ -242,8 +242,8 @@ COPY foo /foo
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
dirDest := t.TempDir()
@@ -275,8 +275,8 @@ COPY foo /foo
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
dirDest := t.TempDir()
@@ -314,8 +314,8 @@ COPY --from=base /etc/bar /bar
`)
dir := tmpdir(
t,
fstest.CreateFile("build.Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("build.Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
out, err := buildCmd(sb, withDir(dir), withArgs(
@@ -359,7 +359,7 @@ COPY --from=base /etc/bar /bar
`)
dir := tmpdir(
t,
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
cmd := buildxCmd(sb, withDir(dir), withArgs("build", "--progress=quiet", "--metadata-file", filepath.Join(dir, "md.json"), "-f-", dir))
@@ -397,8 +397,8 @@ COPY foo /foo
`)
dir := tmpdir(
t,
fstest.CreateFile("build.Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("build.Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
dirDest := t.TempDir()
@@ -534,7 +534,7 @@ func testImageIDOutput(t *testing.T, sb integration.Sandbox) {
dockerfile := []byte(`FROM busybox:latest`)
dir := tmpdir(t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
targetDir := t.TempDir()
@@ -607,7 +607,7 @@ func testBuildMobyFromLocalImage(t *testing.T, sb integration.Sandbox) {
// build image
dockerfile := []byte(`FROM buildx-test:busybox`)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600))
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd = buildxCmd(
sb,
withArgs("build", "-q", "--output=type=cacheonly", dir),
@@ -626,7 +626,7 @@ func testBuildMobyFromLocalImage(t *testing.T, sb integration.Sandbox) {
FROM busybox:1.35
RUN busybox | head -1 | grep v1.36.1
`)
dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600))
dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd = buildxCmd(
sb,
withArgs("build", "-q", "--output=type=cacheonly", dir),
@@ -642,7 +642,7 @@ func testBuildDetailsLink(t *testing.T, sb integration.Sandbox) {
// build simple dockerfile
dockerfile := []byte(`FROM busybox:latest
RUN echo foo > /bar`)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600))
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd := buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir))
out, err := cmd.CombinedOutput()
require.NoError(t, err, string(out))
@@ -652,7 +652,7 @@ RUN echo foo > /bar`)
home, err := os.UserHomeDir() // TODO: sandbox should create a temp home dir and expose it through its interface
require.NoError(t, err)
dbDir := path.Join(home, ".docker", "desktop-build")
require.NoError(t, os.MkdirAll(dbDir, 0755))
require.NoError(t, os.MkdirAll(dbDir, 0o755))
dblaFile, err := os.Create(path.Join(dbDir, ".lastaccess"))
require.NoError(t, err)
defer func() {
@@ -671,7 +671,7 @@ RUN echo foo > /bar`)
// build erroneous dockerfile
dockerfile = []byte(`FROM busybox:latest
RUN exit 1`)
dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600))
dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir))
out, err = cmd.CombinedOutput()
require.Error(t, err, string(out))
@@ -802,8 +802,8 @@ func testBuildMultiPlatform(t *testing.T, sb integration.Sandbox) {
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
registry, err := sb.NewRegistry()
if errors.Is(err, integration.ErrRequirements) {
@@ -838,7 +838,7 @@ func testDockerHostGateway(t *testing.T, sb integration.Sandbox) {
FROM busybox
RUN ping -c 1 buildx.host-gateway-ip.local
`)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600))
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd := buildxCmd(sb, withArgs("build", "--add-host=buildx.host-gateway-ip.local:host-gateway", "--output=type=cacheonly", dir))
out, err := cmd.CombinedOutput()
if !isDockerWorker(sb) {
@@ -877,7 +877,7 @@ RUN ip a show eth0 | awk '/inet / {split($2, a, "/"); print a[1]}' > /ip-bridge.
RUN --network=host ip a show eth0 | awk '/inet / {split($2, a, "/"); print a[1]}' > /ip-host.txt
FROM scratch
COPY --from=build /ip*.txt /`)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600))
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd := buildxCmd(sb, withArgs("build", "--allow=network.host", fmt.Sprintf("--output=type=local,dest=%s", dir), dir))
cmd.Env = append(cmd.Env, "BUILDX_BUILDER="+builderName)
@@ -912,7 +912,7 @@ COPY --from=build /shmsize /
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
cmd := buildxCmd(sb, withArgs("build", "--shm-size=128m", fmt.Sprintf("--output=type=local,dest=%s", dir), dir))
@@ -933,7 +933,7 @@ COPY --from=build /ulimit /
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
cmd := buildxCmd(sb, withArgs("build", "--ulimit=nofile=1024:1024", fmt.Sprintf("--output=type=local,dest=%s", dir), dir))
@@ -1034,8 +1034,8 @@ func buildMetadataProvenanceMultiplatform(t *testing.T, sb integration.Sandbox,
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
registry, err := sb.NewRegistry()
@@ -1122,7 +1122,7 @@ COPy --from=base \
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
cmd := buildxCmd(
@@ -1258,8 +1258,8 @@ COPY --from=build /token /
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("tokenfile", []byte(token), 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("tokenfile", []byte(token), 0o600),
)
t.Run("env", func(t *testing.T) {
@@ -1347,7 +1347,7 @@ COPy --from=base \
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
cmd := buildxCmd(sb, withArgs("build", "--call=check,format=json", dir))
@@ -1382,7 +1382,7 @@ FROM second
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
cmd := buildxCmd(sb, withArgs("build", "--build-arg=BAR=678", "--target=target", "--call=outline,format=json", dir))
@@ -1423,7 +1423,7 @@ ARG FOO=bar
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
runOutline := func(args ...string) string {
@@ -1459,7 +1459,7 @@ FROM second AS binary
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
cmd := buildxCmd(sb, withArgs("build", "--call=targets,format=json", dir))
@@ -1501,7 +1501,7 @@ COPy --from=base \
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
cmd := buildxCmd(sb, withArgs("build", "--call=check,format=json", "--metadata-file", filepath.Join(dir, "md.json"), dir))
@@ -1537,7 +1537,7 @@ COPY Dockerfile .
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
cmd := buildxCmd(sb, withArgs("build", "--call=check", dir))
@@ -1556,7 +1556,7 @@ COPY Dockerfile .
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
cmd := buildxCmd(sb, withArgs("build", "--call=check", dir))
@@ -1575,7 +1575,7 @@ cOpy Dockerfile .
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
)
cmd := buildxCmd(sb, withArgs("build", "--call=check", dir))
@@ -1594,8 +1594,8 @@ cOpy Dockerfile .
`)
dir := tmpdir(
t,
fstest.CreateDir("subdir", 0700),
fstest.CreateFile("subdir/Dockerfile", dockerfile, 0600),
fstest.CreateDir("subdir", 0o700),
fstest.CreateFile("subdir/Dockerfile", dockerfile, 0o600),
)
dockerfilePath := filepath.Join(dir, "subdir", "Dockerfile")
@@ -1618,7 +1618,7 @@ RUN cat /etc/hosts | grep myhost | grep 1.2.3.4
RUN cat /etc/hosts | grep myhostmulti | grep 162.242.195.81
RUN cat /etc/hosts | grep myhostmulti | grep 162.242.195.82
`)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600))
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0o600))
cmd := buildxCmd(sb, withArgs("build",
"--add-host=myhost=1.2.3.4",
"--add-host=myhostmulti=162.242.195.81",
@@ -1649,10 +1649,9 @@ RUN cp /etc/foo /etc/bar
FROM scratch
COPY --from=base /etc/bar /bar
`)
dir := tmpdir(
t,
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
dir := tmpdir(t,
fstest.CreateFile("Dockerfile", dockerfile, 0o600),
fstest.CreateFile("foo", []byte("foo"), 0o600),
)
return dir
}
+99
View File
@@ -11,6 +11,7 @@ import (
"testing"
"time"
"github.com/containerd/continuity/fs/fstest"
"github.com/docker/buildx/commands"
debug "github.com/docker/buildx/dap"
"github.com/docker/buildx/dap/common"
@@ -78,6 +79,7 @@ var dapBuildTests = []func(t *testing.T, sb integration.Sandbox){
testDapBuildStopOnEntry,
testDapBuildSetBreakpoints,
testDapBuildVerifiedBreakpoints,
testDapBuildLoadedSource,
testDapBuildStepIn,
testDapBuildStepNext,
testDapBuildStepOut,
@@ -258,6 +260,103 @@ func testDapBuildVerifiedBreakpoints(t *testing.T, sb integration.Sandbox) {
require.ErrorAs(t, done(true), &exitErr)
}
func testDapBuildLoadedSource(t *testing.T, sb integration.Sandbox) {
type test struct {
Name string
ContextPath string
DockerfilePath string
}
runTest := func(t *testing.T, tt test, abspath bool) string {
dockerfile := []byte(`
FROM busybox:latest AS base
COPY foo /etc/foo
RUN cp /etc/foo /etc/bar
FROM scratch
COPY --from=base /etc/bar /bar
`)
appliers := []fstest.Applier{}
if tt.ContextPath != "" {
appliers = append(appliers, fstest.CreateDir(tt.ContextPath, 0o700))
}
if tt.DockerfilePath != "" {
appliers = append(appliers, fstest.CreateDir(path.Join(tt.ContextPath, tt.DockerfilePath), 0o700))
}
appliers = append(appliers,
fstest.CreateFile(path.Join(tt.ContextPath, tt.DockerfilePath, "Dockerfile"), dockerfile, 0o600),
fstest.CreateFile(path.Join(tt.ContextPath, "foo"), []byte("foo"), 0o600),
)
dir := tmpdir(t, appliers...)
client, done, err := dapBuildCmd(t, sb, withDir(dir))
require.NoError(t, err)
var source *dap.Source
client.RegisterEvent("loadedSource", func(em dap.EventMessage) {
e := em.(*dap.LoadedSourceEvent)
source = &e.Body.Source
})
launchCfg := commands.LaunchConfig{
Config: common.Config{
StopOnEntry: true,
},
}
if abspath {
launchCfg.ContextPath = path.Join(dir, tt.ContextPath)
} else {
launchCfg.ContextPath = tt.ContextPath
}
launchCfg.Dockerfile = path.Join(launchCfg.ContextPath, tt.DockerfilePath, "Dockerfile")
doLaunch(t, client, launchCfg)
interruptCh := pollInterruptEvents(client)
stopped := waitForInterrupt[*dap.StoppedEvent](t, interruptCh)
require.NotNil(t, stopped)
expected := path.Join(dir, tt.ContextPath, tt.DockerfilePath, "Dockerfile")
require.NotNil(t, source)
require.Equal(t, expected, source.Path)
require.Equal(t, "Dockerfile", source.Name)
var exitErr *exec.ExitError
require.ErrorAs(t, done(true), &exitErr)
return dir
}
for _, tt := range []test{
{
Name: "base path",
ContextPath: ".",
},
{
Name: "nested context",
ContextPath: "nested",
},
{
Name: "nested dockerfile",
ContextPath: ".",
DockerfilePath: "nested",
},
{
Name: "both nested",
ContextPath: "nested",
DockerfilePath: "subdir",
},
} {
t.Run(tt.Name, func(t *testing.T) {
t.Run("absolute paths", func(t *testing.T) {
runTest(t, tt, true)
})
t.Run("relative paths", func(t *testing.T) {
runTest(t, tt, false)
})
})
}
}
func testDapBuildStepIn(t *testing.T, sb integration.Sandbox) {
dir := createTestProject(t)
client, done, err := dapBuildCmd(t, sb, withArgs(dir))