mukan-ignite/integration/exec.go
Mukan Erkin Törük c32551b6f7
Some checks failed
Docs Deploy / build_and_deploy (push) Has been cancelled
Generate Docs / cli (push) Has been cancelled
Generate Config Doc / cli (push) Has been cancelled
Go formatting / go-formatting (push) Has been cancelled
Check links / markdown-link-check (push) Has been cancelled
Integration / pre-test (push) Has been cancelled
Integration / test on (push) Has been cancelled
Integration / status (push) Has been cancelled
Lint / Lint Go code (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
refactor: replace all github.com upstream refs with git.cw.tr/mukan-network
2026-05-11 03:36:24 +03:00

111 lines
2.5 KiB
Go

package envtest
import (
"bytes"
"context"
"fmt"
"io"
"os"
"time"
"github.com/stretchr/testify/assert"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cmdrunner"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cmdrunner/step"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/errors"
)
type execOptions struct {
ctx context.Context
shouldErr, shouldRetry bool
stdout, stderr io.Writer
}
type ExecOption func(*execOptions)
// ExecShouldError sets the expectations of a command's execution to end with a failure.
func ExecShouldError() ExecOption {
return func(o *execOptions) {
o.shouldErr = true
}
}
// ExecCtx sets cancelation context for the execution.
func ExecCtx(ctx context.Context) ExecOption {
return func(o *execOptions) {
o.ctx = ctx
}
}
// ExecStdout captures stdout of an execution.
func ExecStdout(w io.Writer) ExecOption {
return func(o *execOptions) {
o.stdout = w
}
}
// ExecStderr captures stderr of an execution.
func ExecStderr(w io.Writer) ExecOption {
return func(o *execOptions) {
o.stderr = w
}
}
// ExecRetry retries command until it is successful before context is canceled.
func ExecRetry() ExecOption {
return func(o *execOptions) {
o.shouldRetry = true
}
}
// Exec executes a command step with options where msg describes the expectation from the test.
// unless calling with Must(), Exec() will not exit test runtime on failure.
func (e Env) Exec(msg string, steps step.Steps, options ...ExecOption) (ok bool) {
opts := &execOptions{
ctx: e.ctx,
stdout: io.Discard,
stderr: io.Discard,
}
for _, o := range options {
o(opts)
}
var (
stdout = &bytes.Buffer{}
stderr = &bytes.Buffer{}
)
copts := []cmdrunner.Option{
cmdrunner.DefaultStdout(io.MultiWriter(stdout, opts.stdout)),
cmdrunner.DefaultStderr(io.MultiWriter(stderr, opts.stderr)),
}
if HasTestVerboseFlag() {
fmt.Printf("Executing %d step(s) for %q\n", len(steps), msg)
copts = append(copts, cmdrunner.EnableDebug())
}
if IsCI {
copts = append(copts, cmdrunner.EndSignal(os.Kill))
}
err := cmdrunner.
New(copts...).
Run(opts.ctx, steps...)
if errors.Is(err, context.Canceled) {
err = nil
}
if err != nil {
fmt.Fprintln(os.Stderr, err)
if opts.shouldRetry && opts.ctx.Err() == nil {
time.Sleep(time.Second)
return e.Exec(msg, steps, options...)
}
}
if err != nil {
msg = fmt.Sprintf("%s\n\nLogs:\n\n%s\n\nError Logs:\n\n%s\n",
msg,
stdout.String(),
stderr.String())
}
if opts.shouldErr {
return assert.Error(e.t, err, msg)
}
return assert.NoError(e.t, err, msg)
}