You've already forked agentic-coding-workflow
bugfix
This commit is contained in:
@@ -6,8 +6,17 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/yan1h/agent-coding-workflow/internal/infra/errs"
|
||||
)
|
||||
|
||||
func requireCode(t *testing.T, err error, want errs.Code) {
|
||||
t.Helper()
|
||||
ae, ok := errs.As(err)
|
||||
require.True(t, ok, "expected *errs.AppError, got %T", err)
|
||||
require.Equal(t, want, ae.Code)
|
||||
}
|
||||
|
||||
func newWtSvc(t *testing.T) (*worktreeService, *fakeRepo, *fakePA, *fakeGit, uuid.UUID) {
|
||||
t.Helper()
|
||||
pa := &fakePA{pid: uuid.New(), canRead: true, canWrite: true}
|
||||
@@ -81,3 +90,55 @@ func TestWorktreeService_Delete_BlockedWhenActive(t *testing.T) {
|
||||
err = svc.Delete(context.Background(), caller, wt.ID)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
// Bug #5: Delete 的 check-and-transition 必须在锁下原子完成。即使 worktree 处于
|
||||
// active(被持有),Delete 也必须在事务内(GetWorktreeByIDForUpdate)发现并拒绝,
|
||||
// 返回 CodeWorktreeAlreadyActive,且不触碰磁盘 / 不删行。
|
||||
func TestWorktreeService_Delete_AtomicGuard_RefusesActive(t *testing.T) {
|
||||
t.Parallel()
|
||||
svc, repo, _, gitr, wsID := newWtSvc(t)
|
||||
caller := Caller{UserID: uuid.New()}
|
||||
wt, err := svc.Create(context.Background(), caller, wsID, CreateWorktreeInput{Branch: "feat-g"})
|
||||
require.NoError(t, err)
|
||||
_, err = svc.Acquire(context.Background(), caller, wt.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = svc.Delete(context.Background(), caller, wt.ID)
|
||||
require.Error(t, err)
|
||||
requireCode(t, err, errs.CodeWorktreeAlreadyActive)
|
||||
// 磁盘未被触碰,行仍存在且保持 active。
|
||||
require.Empty(t, gitr.removed)
|
||||
got, err := repo.GetWorktreeByID(context.Background(), wt.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, WorktreeStatusActive, got.Status)
|
||||
}
|
||||
|
||||
// Bug #6: Acquire 必须做 project 鉴权。无 write 权限的 caller 不得锁定 worktree。
|
||||
func TestWorktreeService_Acquire_DeniedWithoutWriteAccess(t *testing.T) {
|
||||
t.Parallel()
|
||||
svc, _, pa, _, wsID := newWtSvc(t)
|
||||
caller := Caller{UserID: uuid.New()}
|
||||
wt, err := svc.Create(context.Background(), caller, wsID, CreateWorktreeInput{Branch: "feat-a"})
|
||||
require.NoError(t, err)
|
||||
|
||||
pa.canWrite = false
|
||||
_, err = svc.Acquire(context.Background(), caller, wt.ID)
|
||||
require.Error(t, err)
|
||||
requireCode(t, err, errs.CodeForbidden)
|
||||
}
|
||||
|
||||
// Bug #6: Release 同样必须做 project 鉴权(在 holder-match 之前)。
|
||||
func TestWorktreeService_Release_DeniedWithoutWriteAccess(t *testing.T) {
|
||||
t.Parallel()
|
||||
svc, _, pa, _, wsID := newWtSvc(t)
|
||||
caller := Caller{UserID: uuid.New()}
|
||||
wt, err := svc.Create(context.Background(), caller, wsID, CreateWorktreeInput{Branch: "feat-rr"})
|
||||
require.NoError(t, err)
|
||||
_, err = svc.Acquire(context.Background(), caller, wt.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
pa.canWrite = false
|
||||
_, err = svc.Release(context.Background(), caller, wt.ID)
|
||||
require.Error(t, err)
|
||||
requireCode(t, err, errs.CodeForbidden)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user