package release import ( "context" "errors" "strings" "testing" ) type taggedWorkerStore struct { WorkerControlStore readTag, writeTag *string } func (s taggedWorkerStore) Get(ctx context.Context, key string) ([]byte, string, error) { raw, tag, err := s.WorkerControlStore.Get(ctx, key) if s.readTag != nil { tag = *s.readTag } return raw, tag, err } func (s taggedWorkerStore) Put(ctx context.Context, key string, raw []byte, etag string) (string, error) { tag, err := s.WorkerControlStore.Put(ctx, key, raw, etag) if s.writeTag != nil { tag = *s.writeTag } return tag, err } func TestWorkerAssignmentBoundsEveryReturnedETag(t *testing.T) { for _, length := range []int{0, maxWorkerControlETagBytes, maxWorkerControlETagBytes + 1} { priv, pub := testKeys(t) sg := RootSigner(priv) ctx := t.Context() store := NewDirStore(t.TempDir()) initial := workerTestAssignment() snap, err := CreateWorkerAssignment(ctx, store, sg, initial) if err != nil { t.Fatal(err) } tag := strings.Repeat("a", length) bad := taggedWorkerStore{WorkerControlStore: store, readTag: &tag} _, err = ReadWorkerAssignment(ctx, bad, pub, initial.Identity) if (length == maxWorkerControlETagBytes) != (err == nil) { t.Fatalf("read length %d: %v", length, err) } snap.etag = tag if _, err := snap.State(pub); (length == maxWorkerControlETagBytes) != (err == nil) { t.Fatalf("snapshot length %d: %v", length, err) } if length == maxWorkerControlETagBytes { continue } counted := &countedWorkerStore{WorkerControlStore: store} after := initial after.Revision++ after.Disabled = true if _, err := AdvanceWorkerAssignment(ctx, counted, sg, snap, after); !errors.Is(err, ErrWorkerControl) { t.Fatal("invalid snapshot sent to store", err) } if counted.puts.Load() != 0 { t.Fatal("invalid ETag reached conditional write") } } } func TestWorkerAssignmentInvalidWriteETagIsUncertain(t *testing.T) { for _, create := range []bool{false, true} { priv, pub := testKeys(t) sg := RootSigner(priv) ctx := t.Context() store := NewDirStore(t.TempDir()) initial := workerTestAssignment() tag := strings.Repeat("a", maxWorkerControlETagBytes+1) bad := taggedWorkerStore{WorkerControlStore: store, writeTag: &tag} expected := initial var err error if create { _, err = CreateWorkerAssignment(ctx, bad, sg, initial) } else { before, e := CreateWorkerAssignment(ctx, store, sg, initial) if e != nil { t.Fatal(e) } expected.Revision++ expected.Disabled = true _, err = AdvanceWorkerAssignment(ctx, bad, sg, before, expected) } if !errors.Is(err, ErrWorkerControl) { t.Fatal("invalid write ETag accepted", err) } recovered, e := ReadWorkerAssignment(ctx, store, pub, initial.Identity) if e != nil { t.Fatal(e) } got, e := recovered.State(pub) if e != nil || got.Revision != expected.Revision || got.Disabled != expected.Disabled { t.Fatal("uncertain write was lost", e) } } } func TestWorkerAssignmentEnabledNoSlotChangeNeverWrites(t *testing.T) { priv, _ := testKeys(t) sg := RootSigner(priv) store := &countedWorkerStore{WorkerControlStore: NewDirStore(t.TempDir())} state := workerTestAssignment() before, err := CreateWorkerAssignment(t.Context(), store, sg, state) if err != nil { t.Fatal(err) } writes := store.puts.Load() state.Revision++ if _, err := AdvanceWorkerAssignment(t.Context(), store, sg, before, state); !errors.Is(err, ErrWorkerControl) { t.Fatal("enabled no-op accepted", err) } if store.puts.Load() != writes { t.Fatal("enabled no-op reached storage") } }