mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 09:40:12 +00:00
81 lines
2.3 KiB
Go
81 lines
2.3 KiB
Go
//go:build linux
|
|
|
|
package scenario
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
func TestHeldSessionAdapterCanceledWaiterRetainsCleanupForLaterCaller(t *testing.T) {
|
|
cleanupStarted := make(chan struct{})
|
|
cleanupRelease := make(chan struct{})
|
|
cleanupErr := errors.New("cleanup failed")
|
|
var cleanupCount atomic.Int32
|
|
lifecycle := heldTestLifecycle(t, "")
|
|
adapter := &heldSessionAdapter{
|
|
lifecycle: lifecycle,
|
|
cleanup: func(cleanupContext context.Context) error {
|
|
cleanupCount.Add(1)
|
|
if err := cleanupContext.Err(); err != nil {
|
|
t.Errorf("cleanup context canceled before release: %v", err)
|
|
}
|
|
close(cleanupStarted)
|
|
<-cleanupRelease
|
|
return cleanupErr
|
|
},
|
|
}
|
|
canceled, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
firstResult := make(chan error, 1)
|
|
go func() { firstResult <- adapter.Close(canceled) }()
|
|
<-cleanupStarted
|
|
if err := <-firstResult; !errors.Is(err, context.Canceled) {
|
|
t.Fatalf("canceled Close error = %v", err)
|
|
}
|
|
close(cleanupRelease)
|
|
if err := adapter.Close(context.Background()); !errors.Is(err, cleanupErr) {
|
|
t.Fatalf("later Close error = %v", err)
|
|
}
|
|
if count := cleanupCount.Load(); count != 1 {
|
|
t.Fatalf("cleanup invocation count = %d, want 1", count)
|
|
}
|
|
}
|
|
|
|
type heldSessionAdapter struct {
|
|
lifecycle *heldSessionLifecycle
|
|
cleanup func(context.Context) error
|
|
}
|
|
|
|
func (adapter *heldSessionAdapter) Plan() StressSessionPlan { return adapter.lifecycle.Plan() }
|
|
|
|
func (adapter *heldSessionAdapter) WaitLive(ctx context.Context) error {
|
|
return adapter.lifecycle.WaitLive(ctx)
|
|
}
|
|
|
|
func (adapter *heldSessionAdapter) IOStreamID() (string, bool) { return adapter.lifecycle.IOStreamID() }
|
|
|
|
func (adapter *heldSessionAdapter) WaitClosed(ctx context.Context) error {
|
|
return adapter.lifecycle.WaitClosed(ctx)
|
|
}
|
|
|
|
func (adapter *heldSessionAdapter) Done() <-chan struct{} { return adapter.lifecycle.Done() }
|
|
func (adapter *heldSessionAdapter) CloseResult() error { return adapter.lifecycle.CloseResult() }
|
|
|
|
func (adapter *heldSessionAdapter) Close(ctx context.Context) error {
|
|
owner, won := adapter.lifecycle.beginClose()
|
|
if !won {
|
|
return adapter.lifecycle.WaitClosed(ctx)
|
|
}
|
|
go func() {
|
|
cleanupContext, cancel := owner.cleanupContext()
|
|
defer cancel()
|
|
owner.markClosed(adapter.cleanup(cleanupContext))
|
|
}()
|
|
return adapter.lifecycle.WaitClosed(ctx)
|
|
}
|
|
|
|
var _ heldSession = (*heldSessionAdapter)(nil)
|