Make run identities collision-resistant and outputs exclusive
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package debugbundle
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -11,17 +13,16 @@ import (
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
|
||||
)
|
||||
|
||||
const testBundleRunID = "run-42-00000000000000000000000000000001"
|
||||
|
||||
func TestAllocateCreatesRestrictiveSummaryAndTrace(t *testing.T) {
|
||||
parent := t.TempDir()
|
||||
fixed := time.Unix(0, 42).UTC()
|
||||
previous := utcNow
|
||||
utcNow = func() time.Time { return fixed }
|
||||
defer func() { utcNow = previous }()
|
||||
bundle, err := Allocate(parent)
|
||||
bundle, err := Allocate(parent, testBundleRunID, fixed)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if bundle.RunID() != "run-42" || bundle.SummaryRoot() != filepath.Join(bundle.Path(), "summary") || bundle.TraceRoot() != filepath.Join(bundle.Path(), "trace") {
|
||||
if bundle.RunID() != testBundleRunID || bundle.CreatedAt() != fixed || bundle.SummaryRoot() != filepath.Join(bundle.Path(), "summary") || bundle.TraceRoot() != filepath.Join(bundle.Path(), "trace") {
|
||||
t.Fatalf("bundle=%#v", bundle)
|
||||
}
|
||||
for _, path := range []string{bundle.Path(), bundle.SummaryRoot(), bundle.TraceRoot()} {
|
||||
@@ -44,45 +45,42 @@ func TestAllocateCreatesRestrictiveSummaryAndTrace(t *testing.T) {
|
||||
t.Fatalf("file mode=%#o", info.Mode().Perm())
|
||||
}
|
||||
}
|
||||
func TestAllocateRetriesAndDoesNotDeleteBundle(t *testing.T) {
|
||||
func TestAllocateRejectsExistingBundleWithoutChangingIt(t *testing.T) {
|
||||
parent := t.TempDir()
|
||||
fixed := time.Unix(0, 9).UTC()
|
||||
previous := utcNow
|
||||
defer func() { utcNow = previous }()
|
||||
calls := 0
|
||||
utcNow = func() time.Time { calls++; return fixed.Add(time.Duration(calls-1) * time.Nanosecond) }
|
||||
if err := os.Mkdir(filepath.Join(parent, "run-9"), 0o700); err != nil {
|
||||
bundlePath := filepath.Join(parent, testBundleRunID)
|
||||
if err := os.Mkdir(bundlePath, 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bundle, err := Allocate(parent)
|
||||
if err != nil {
|
||||
sentinelPath := filepath.Join(bundlePath, "sentinel")
|
||||
sentinel := []byte("existing bundle")
|
||||
if err := os.WriteFile(sentinelPath, sentinel, 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if bundle.RunID() != "run-10" {
|
||||
t.Fatalf("run id=%q", bundle.RunID())
|
||||
|
||||
if _, err := Allocate(parent, testBundleRunID, time.Unix(0, 42)); err == nil || !strings.Contains(err.Error(), "already exists") {
|
||||
t.Fatalf("Allocate() error = %v, want collision", err)
|
||||
}
|
||||
if _, err := os.Stat(bundle.Path()); err != nil {
|
||||
t.Fatal(err)
|
||||
if got, err := os.ReadFile(sentinelPath); err != nil || !bytes.Equal(got, sentinel) {
|
||||
t.Fatalf("sentinel = %q, %v", got, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocateReturnsErrorAfterRunIDCollisionsAreExhausted(t *testing.T) {
|
||||
parent := t.TempDir()
|
||||
fixed := time.Unix(0, 99).UTC()
|
||||
if err := os.Mkdir(filepath.Join(parent, "run-99"), 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
previous := utcNow
|
||||
utcNow = func() time.Time { return fixed }
|
||||
defer func() { utcNow = previous }()
|
||||
|
||||
if _, err := Allocate(parent); err == nil {
|
||||
t.Fatal("Allocate succeeded after exhausting run ID collisions")
|
||||
func TestAllocateRejectsUnsafeRunIDsBeforeCreatingParent(t *testing.T) {
|
||||
for _, runID := range []string{"", ".", "..", "../escape", `..\\escape`, "/absolute", " trailing "} {
|
||||
t.Run(runID, func(t *testing.T) {
|
||||
parent := filepath.Join(t.TempDir(), "debug")
|
||||
if _, err := Allocate(parent, runID, time.Time{}); err == nil {
|
||||
t.Fatalf("Allocate(%q) succeeded", runID)
|
||||
}
|
||||
if _, err := os.Stat(parent); !os.IsNotExist(err) {
|
||||
t.Fatalf("debug parent exists or stat failed: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSummaryWriterWritesEverySummaryArtifact(t *testing.T) {
|
||||
bundle, err := Allocate(t.TempDir())
|
||||
bundle, err := Allocate(t.TempDir(), testBundleRunID, time.Unix(0, 42))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -140,7 +138,7 @@ func TestSummaryWriterWritesEverySummaryArtifact(t *testing.T) {
|
||||
}
|
||||
}
|
||||
func TestSummaryWriterConfinesArtifacts(t *testing.T) {
|
||||
bundle, err := Allocate(t.TempDir())
|
||||
bundle, err := Allocate(t.TempDir(), testBundleRunID, time.Unix(0, 42))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user