ci / Protobuf (push) Successful in 18s
ci / Web (lint, test, audit, build) (push) Successful in 1m16s
ci / Shell and licence headers (push) Successful in 20s
ci / Release build (dry run) (push) Successful in 2m9s
ci / Go (lint, test, vuln) (push) Successful in 4m19s
ci / End-to-end (server, agents, BIND, Kea) (push) Successful in 1m49s
ci / Development environment (compose) (push) Successful in 12s
ci / Integration (real BIND and Kea) (push) Successful in 5m12s
Docker Hub timed out on the shared runner; pulls now retry and fall back to a local image. The e2e scripts were committed without the executable bit. The truncation test checked letters that the marker itself contains. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
75 lines
2.2 KiB
Go
75 lines
2.2 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package command
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestMissingProgram(t *testing.T) {
|
|
_, err := Exec{Timeout: time.Second}.Run(context.Background(), "ddi-no-such-program-xyz", "-v")
|
|
var ce *Error
|
|
if !errors.As(err, &ce) || !IsNotFound(err) {
|
|
t.Fatalf("err = %v, want *Error wrapping exec.ErrNotFound", err)
|
|
}
|
|
if !strings.Contains(err.Error(), "ddi-no-such-program-xyz -v") {
|
|
t.Errorf("error does not name the command: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestFailingProgramQuotesOutput(t *testing.T) {
|
|
sh, err := exec.LookPath("sh")
|
|
if err != nil {
|
|
t.Skip("sh not available")
|
|
}
|
|
out, err := Exec{Timeout: 10 * time.Second}.Run(context.Background(), sh, "-c", "echo out; echo err >&2; exit 3")
|
|
if err == nil {
|
|
t.Fatal("expected an error")
|
|
}
|
|
if !strings.Contains(string(out), "out") || !strings.Contains(string(out), "err") {
|
|
t.Errorf("output = %q", out)
|
|
}
|
|
if !strings.Contains(err.Error(), "exit status 3") || !strings.Contains(err.Error(), "err") {
|
|
t.Errorf("error = %v", err)
|
|
}
|
|
}
|
|
|
|
func TestTimeout(t *testing.T) {
|
|
sh, err := exec.LookPath("sh")
|
|
if err != nil {
|
|
t.Skip("sh not available")
|
|
}
|
|
start := time.Now()
|
|
_, err = Exec{Timeout: 200 * time.Millisecond}.Run(context.Background(), sh, "-c", "sleep 10")
|
|
if !errors.Is(err, context.DeadlineExceeded) {
|
|
t.Fatalf("err = %v, want deadline exceeded", err)
|
|
}
|
|
if time.Since(start) > 8*time.Second {
|
|
t.Error("timeout did not stop the program")
|
|
}
|
|
}
|
|
|
|
func TestExcerptAndLimit(t *testing.T) {
|
|
long := strings.Repeat("a", MaxErrorOutput) + "END"
|
|
ex := Excerpt([]byte(long))
|
|
if !strings.HasPrefix(ex, "...") || !strings.HasSuffix(ex, "END") || len(ex) != MaxErrorOutput+3 {
|
|
t.Errorf("excerpt has length %d, prefix %q", len(ex), ex[:5])
|
|
}
|
|
var l limitedBuffer
|
|
_, _ = l.Write([]byte(strings.Repeat("b", MaxCapture-1)))
|
|
_, _ = l.Write([]byte("cc"))
|
|
_, _ = l.Write([]byte("dd"))
|
|
b := l.Bytes()
|
|
// Only the captured part counts: the marker itself contains letters.
|
|
kept := string(b[:MaxCapture])
|
|
if !strings.HasSuffix(string(b), "\n[output truncated]") || len(b) != MaxCapture+len("\n[output truncated]") ||
|
|
strings.Count(kept, "c") != 1 || strings.Contains(kept, "d") {
|
|
t.Errorf("limited buffer kept %d bytes", len(b))
|
|
}
|
|
}
|