Skip to content

Commit 24b1808

Browse files
committed
tests: Fix some issues with build output
Before this change `RunTest` may return before all messages are processed. This also moves a lot of the logic around to better separate responsibilities and provide a more flexible interface that is, hopefully, easier to reason about. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
1 parent 621a944 commit 24b1808

File tree

5 files changed

+198
-98
lines changed

5 files changed

+198
-98
lines changed

test/gomod_git_auth_test.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ import (
1414
"strconv"
1515
"testing"
1616

17+
"github.com/moby/buildkit/client/llb"
18+
gwclient "github.com/moby/buildkit/frontend/gateway/client"
19+
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
1720
"github.com/project-dalec/dalec"
1821
"github.com/project-dalec/dalec/test/cmd/git_repo/passwd"
1922
gitservices "github.com/project-dalec/dalec/test/git_services"
2023
"github.com/project-dalec/dalec/test/testenv"
21-
"github.com/moby/buildkit/client/llb"
22-
gwclient "github.com/moby/buildkit/frontend/gateway/client"
23-
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
2424
"golang.org/x/crypto/ssh"
2525
"golang.org/x/crypto/ssh/agent"
2626
)
@@ -109,7 +109,8 @@ go {{ .ModFileGoVersion }}
109109

110110
t.Run("HTTP", func(t *testing.T) {
111111
t.Parallel()
112-
netHostBuildxEnv.RunTestOptsFirst(ctx, t, []testenv.TestRunnerOpt{
112+
113+
opts := []testenv.TestRunnerOpt{
113114
// This gives buildkit access to a secret with the name
114115
// `secretName` and the value `passwd.Password`. On the worker that
115116
// fetches the gomod dependencies, a file will be mounted at the
@@ -120,7 +121,9 @@ go {{ .ModFileGoVersion }}
120121
// requests. It is necessary but not sufficient for the buildx
121122
// instance to have host networking enabled.
122123
testenv.WithHostNetworking,
123-
}, func(ctx context.Context, client gwclient.Client) {
124+
}
125+
126+
netHostBuildxEnv.RunTest(ctx, t, func(ctx context.Context, client gwclient.Client) {
124127
// This MUST be called at the start of each test. Because we
125128
// persist the go mod cache between runs, the git tag of the
126129
// private go module needs to be unique. Within a single run of the
@@ -167,7 +170,7 @@ go {{ .ModFileGoVersion }}
167170

168171
filename := calculateFilename(ctx, t, attr, res)
169172
checkFile(ctx, t, filename, res, []byte("bar\n"))
170-
})
173+
}, opts...)
171174
})
172175

173176
t.Run("SSH", func(t *testing.T) {
@@ -182,12 +185,13 @@ go {{ .ModFileGoVersion }}
182185
pubkey, privkey := generateKeyPair(t)
183186
agentErrChan := startSSHAgent(t, privkey, sockaddr)
184187

185-
netHostBuildxEnv.RunTestOptsFirst(ctx, t, []testenv.TestRunnerOpt{
188+
opts := []testenv.TestRunnerOpt{
186189
// This tells buildkit to forward the SSH Agent socket, giving the
187190
// gomod generator worker access to the private key
188191
testenv.WithSSHSocket(sshID, sockaddr),
189192
testenv.WithHostNetworking,
190-
}, func(ctx context.Context, client gwclient.Client) {
193+
}
194+
netHostBuildxEnv.RunTest(ctx, t, func(ctx context.Context, client gwclient.Client) {
191195
// This MUST be called at the start of each test. Because we
192196
// persist the go mod cache between runs, the git tag of the
193197
// private go module needs to be unique. Within a single run of the
@@ -245,7 +249,7 @@ go {{ .ModFileGoVersion }}
245249

246250
filename := calculateFilename(ctx, t, attr, res)
247251
checkFile(ctx, t, filename, res, []byte("bar\n"))
248-
})
252+
}, opts...)
249253
})
250254
}
251255

test/linux_target_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3202,6 +3202,7 @@ func testLinuxPackageTestsFail(ctx context.Context, t *testing.T, cfg testLinuxC
32023202
sr := newSolveRequest(withSpec(ctx, t, spec), withBuildTarget(target))
32033203
_, err := client.Solve(ctx, sr)
32043204
assert.Assert(t, err != nil)
3205+
t.Logf("Build Error: %v", err)
32053206
// exit code errors would be here rather than in the buid logs
32063207
if !tc.isBuildError {
32073208
return
@@ -3224,7 +3225,7 @@ func testLinuxPackageTestsFail(ctx context.Context, t *testing.T, cfg testLinuxC
32243225

32253226
if !bytes.Contains(dt, []byte(tc.err.Error())) {
32263227
t.Errorf("expected error not found in logs")
3227-
t.Logf("Expected error:\n\t%v", err)
3228+
t.Logf("Expected error:\n\t%v", tc.err)
32283229
t.Log()
32293230
t.Log("---- Solve logs ----\n" + string(dt))
32303231
}

test/main_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import (
1010
"testing"
1111
"time"
1212

13-
"github.com/project-dalec/dalec/test/fixtures"
14-
"github.com/project-dalec/dalec/test/testenv"
1513
"github.com/moby/buildkit/util/tracing/delegated"
1614
"github.com/moby/buildkit/util/tracing/detect"
15+
"github.com/project-dalec/dalec/test/fixtures"
16+
"github.com/project-dalec/dalec/test/testenv"
1717
"go.opentelemetry.io/otel"
1818
"go.opentelemetry.io/otel/propagation"
1919
"go.opentelemetry.io/otel/sdk/trace"

test/testenv/build.go

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
gwclient "github.com/moby/buildkit/frontend/gateway/client"
1919
"github.com/moby/buildkit/identity"
2020
"github.com/moby/buildkit/solver/pb"
21-
"github.com/moby/buildkit/util/progress/progressui"
2221
"github.com/pkg/errors"
2322
"go.opentelemetry.io/otel"
2423
"go.opentelemetry.io/otel/codes"
@@ -176,6 +175,51 @@ var logBufferPool = &sync.Pool{New: func() any {
176175
return bytes.NewBuffer(nil)
177176
}}
178177

178+
func outputStreamStatusFn(ctx context.Context, t *testing.T) (func(*client.SolveStatus), func()) {
179+
var (
180+
warnings []*client.VertexWarning
181+
errOnce sync.Once
182+
183+
done = make(chan struct{})
184+
w = getBuildOutputStream(ctx, t, done)
185+
)
186+
187+
fn := func(msg *client.SolveStatus) {
188+
for _, v := range msg.Warnings {
189+
warnings = append(warnings, v)
190+
}
191+
for _, l := range msg.Logs {
192+
if _, err := w.Write(l.Data); err != nil {
193+
errOnce.Do(func() {
194+
// Don't spam the logs with multiple errors
195+
t.Logf("error writing log data: %v", err)
196+
})
197+
}
198+
}
199+
}
200+
201+
return fn, func() {
202+
for _, v := range warnings {
203+
t.Logf("WARNING: %s", string(v.Short))
204+
}
205+
if closer, ok := w.(io.Closer); ok {
206+
closer.Close()
207+
}
208+
close(done)
209+
}
210+
}
211+
212+
func multiStatusFunc(fns ...func(*client.SolveStatus)) func(*client.SolveStatus) {
213+
return func(msg *client.SolveStatus) {
214+
for _, fn := range fns {
215+
if fn == nil {
216+
continue
217+
}
218+
fn(msg)
219+
}
220+
}
221+
}
222+
179223
func getBuildOutputStream(ctx context.Context, t *testing.T, done <-chan struct{}) io.Writer {
180224
t.Helper()
181225

@@ -226,47 +270,42 @@ func getBuildOutputStream(ctx context.Context, t *testing.T, done <-chan struct{
226270
return f
227271
}
228272

229-
func displaySolveStatus(ctx context.Context, t *testing.T) chan *client.SolveStatus {
230-
ch := make(chan *client.SolveStatus)
231-
done := make(chan struct{})
232-
233-
output := getBuildOutputStream(ctx, t, done)
234-
display, err := progressui.NewDisplay(output, progressui.AutoMode, progressui.WithPhase(t.Name()))
235-
if err != nil {
236-
t.Fatal(err)
237-
}
238-
239-
go func() {
240-
defer close(done)
241-
242-
_, err := display.UpdateFrom(ctx, ch)
243-
if err != nil {
244-
t.Log(err)
273+
func fowardToSolveStatusFn(ctx context.Context, ch <-chan *client.SolveStatus, fns ...func(*client.SolveStatus)) {
274+
f := multiStatusFunc(fns...)
275+
for {
276+
select {
277+
case <-ctx.Done():
278+
return
279+
case msg, ok := <-ch:
280+
if msg != nil {
281+
f(msg)
282+
continue
283+
}
284+
if !ok {
285+
return
286+
}
245287
}
246-
}()
247-
248-
return ch
288+
}
249289
}
250290

251291
// withProjectRoot adds the current project root as the build context for the solve request.
252-
func withProjectRoot(t *testing.T, opts *client.SolveOpt) {
253-
t.Helper()
254-
292+
func withProjectRoot(opts *client.SolveOpt) error {
255293
cwd, err := os.Getwd()
256294
if err != nil {
257-
t.Fatal(err)
295+
return err
258296
}
259297

260298
projectRoot, err := lookupProjectRoot(cwd)
261299
if err != nil {
262-
t.Fatal(err)
300+
return err
263301
}
264302

265303
if opts.LocalDirs == nil {
266304
opts.LocalDirs = make(map[string]string)
267305
}
268306
opts.LocalDirs[dockerui.DefaultLocalNameContext] = projectRoot
269307
opts.LocalDirs[dockerui.DefaultLocalNameDockerfile] = projectRoot
308+
return nil
270309
}
271310

272311
// lookupProjectRoot looks up the project root from the current working directory.

0 commit comments

Comments
 (0)