fix(auth): close Windows remediation review findings
This commit is contained in:
@@ -308,6 +308,64 @@ func TestRestoreStagesArchiveAfterCheckpointAndRejectsMutation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type restoreLifecycleTestOutcome struct {
|
||||
result RestoreResult
|
||||
err error
|
||||
}
|
||||
|
||||
func releaseLifecycleStage(ctx context.Context, release chan<- struct{}, done <-chan restoreLifecycleTestOutcome) (restoreLifecycleTestOutcome, bool, error) {
|
||||
select {
|
||||
case outcome := <-done:
|
||||
return outcome, true, nil
|
||||
default:
|
||||
}
|
||||
select {
|
||||
case release <- struct{}{}:
|
||||
return restoreLifecycleTestOutcome{}, false, nil
|
||||
default:
|
||||
}
|
||||
|
||||
timer := time.NewTimer(2 * time.Second)
|
||||
defer timer.Stop()
|
||||
var ctxErr error
|
||||
select {
|
||||
case outcome := <-done:
|
||||
return outcome, true, nil
|
||||
case release <- struct{}{}:
|
||||
return restoreLifecycleTestOutcome{}, false, nil
|
||||
case <-ctx.Done():
|
||||
ctxErr = ctx.Err()
|
||||
ctx = nil
|
||||
case <-timer.C:
|
||||
if ctxErr != nil {
|
||||
return restoreLifecycleTestOutcome{}, false, ctxErr
|
||||
}
|
||||
return restoreLifecycleTestOutcome{}, false, errors.New("timed out releasing lifecycle stage")
|
||||
}
|
||||
select {
|
||||
case outcome := <-done:
|
||||
return outcome, true, nil
|
||||
case release <- struct{}{}:
|
||||
return restoreLifecycleTestOutcome{}, false, nil
|
||||
case <-timer.C:
|
||||
return restoreLifecycleTestOutcome{}, false, ctxErr
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseLifecycleStageReturnsPrematureWorkerOutcome(t *testing.T) {
|
||||
want := errors.New("worker ended before the next lifecycle stage")
|
||||
done := make(chan restoreLifecycleTestOutcome, 1)
|
||||
done <- restoreLifecycleTestOutcome{err: want}
|
||||
|
||||
got, terminal, err := releaseLifecycleStage(context.Background(), make(chan struct{}), done)
|
||||
if err != nil {
|
||||
t.Fatalf("releaseLifecycleStage() error = %v", err)
|
||||
}
|
||||
if !terminal || !errors.Is(got.err, want) {
|
||||
t.Fatalf("releaseLifecycleStage() = outcome %#v, terminal %t; want original worker error", got, terminal)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRestoreLifecycleLockExcludesCompetingTransactionsUntilTerminalCleanup(t *testing.T) {
|
||||
targetFailure := errors.New("target restore failed")
|
||||
recoveryFailure := errors.New("recovery restore failed")
|
||||
@@ -402,15 +460,15 @@ func TestRestoreLifecycleLockExcludesCompetingTransactionsUntilTerminalCleanup(t
|
||||
installationID: fixture.installationID,
|
||||
entries: []preflightArchiveEntry{{path: "configuration/operator.env", body: []byte("checkpoint")}},
|
||||
})
|
||||
stages := make(chan string)
|
||||
continueStage := make(chan struct{})
|
||||
stages := make(chan string, 1)
|
||||
continueStage := make(chan struct{}, 1)
|
||||
caller, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
gate := func(stage string) {
|
||||
stages <- stage
|
||||
<-continueStage
|
||||
}
|
||||
runner.beforeFinalMaintenanceRelease = func() { gate("final-barrier-release") }
|
||||
caller, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
deps := restoreTestDependencies(t, runner)
|
||||
deps.prepareRecovery = func(ctx context.Context, target config.Installation, _ string) (PreflightResult, error) {
|
||||
return Preflight(ctx, target, PreflightRequest{Archive: recoveryArchive, Confirm: true, AllowExternalSecrets: true}, permissivePreflightDependencies())
|
||||
@@ -426,32 +484,66 @@ func TestRestoreLifecycleLockExcludesCompetingTransactionsUntilTerminalCleanup(t
|
||||
}
|
||||
scenario.configure(&deps, runner, gate, cancel)
|
||||
|
||||
type outcome struct {
|
||||
result RestoreResult
|
||||
err error
|
||||
}
|
||||
done := make(chan outcome, 1)
|
||||
done := make(chan restoreLifecycleTestOutcome, 1)
|
||||
go func() {
|
||||
result, err := restoreWithDependencies(caller, installation, RestoreRequest{Archive: archive, Confirm: true}, deps)
|
||||
done <- outcome{result: result, err: err}
|
||||
done <- restoreLifecycleTestOutcome{result: result, err: err}
|
||||
}()
|
||||
|
||||
var failures []error
|
||||
for _, wantStage := range scenario.stages {
|
||||
var terminal *restoreLifecycleTestOutcome
|
||||
for stageIndex, wantStage := range scenario.stages {
|
||||
receivedStage := false
|
||||
select {
|
||||
case stage := <-stages:
|
||||
receivedStage = true
|
||||
if stage != wantStage {
|
||||
failures = append(failures, fmt.Errorf("lifecycle stage = %q, want %q", stage, wantStage))
|
||||
}
|
||||
case outcome := <-done:
|
||||
terminal = &outcome
|
||||
failures = append(failures, fmt.Errorf("restore ended before lifecycle stage %q: %w", wantStage, outcome.err))
|
||||
case <-time.After(2 * time.Second):
|
||||
failures = append(failures, fmt.Errorf("timed out waiting for lifecycle stage %q", wantStage))
|
||||
select {
|
||||
case outcome := <-done:
|
||||
terminal = &outcome
|
||||
failures = append(failures, fmt.Errorf("restore ended before lifecycle stage %q: %w", wantStage, outcome.err))
|
||||
default:
|
||||
failures = append(failures, fmt.Errorf("timed out waiting for lifecycle stage %q", wantStage))
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
if terminal != nil || !receivedStage {
|
||||
break
|
||||
}
|
||||
if err := competingRestoreAndBackupEntry(installation, archive, t); err != nil {
|
||||
failures = append(failures, fmt.Errorf("%s: %w", wantStage, err))
|
||||
}
|
||||
continueStage <- struct{}{}
|
||||
outcome, workerDone, err := releaseLifecycleStage(caller, continueStage, done)
|
||||
if err != nil {
|
||||
failures = append(failures, fmt.Errorf("release lifecycle stage %q: %w", wantStage, err))
|
||||
cancel()
|
||||
break
|
||||
}
|
||||
if workerDone {
|
||||
terminal = &outcome
|
||||
if stageIndex+1 < len(scenario.stages) {
|
||||
failures = append(failures, fmt.Errorf("restore ended before lifecycle stage %q: %w", scenario.stages[stageIndex+1], outcome.err))
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
var result restoreLifecycleTestOutcome
|
||||
if terminal != nil {
|
||||
result = *terminal
|
||||
} else {
|
||||
select {
|
||||
case result = <-done:
|
||||
case <-time.After(2 * time.Second):
|
||||
failures = append(failures, errors.New("timed out waiting for restore worker outcome"))
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
result := <-done
|
||||
for _, wantErr := range scenario.wantErrors {
|
||||
if !errors.Is(result.err, wantErr) {
|
||||
failures = append(failures, fmt.Errorf("restore error = %v, want %v", result.err, wantErr))
|
||||
|
||||
Reference in New Issue
Block a user