Files
2026-07-20 04:45:05 +00:00

69 lines
2.1 KiB
Go

//go:build linux && agentcompat
package agent
import (
"context"
"errors"
"syscall"
"testing"
"time"
processharness "github.com/nezhahq/nezha/integration/agentcompat/internal/process"
"github.com/stretchr/testify/require"
)
func TestAgent_StartExposesFinalizerWhenPreparedConsumerSurvivesRollback(t *testing.T) {
prepared, err := PrepareBinary(t.Context(), testAgentSourceDir(t))
require.NoError(t, err)
trackingErr := errors.New("injected failed-start PID tracking error")
var supervisor *processharness.Supervisor
instance, startErr := Start(t.Context(), AgentStartConfig{
PreparedBinary: prepared,
Endpoint: "127.0.0.1:1",
UUID: "00000000-0000-0000-0000-000000000200",
newSupervisor: func(ctx context.Context, spec processharness.Spec) *processharness.Supervisor {
supervisor = processharness.NewSupervisor(ctx, spec)
cancelledContext, cancel := context.WithCancel(ctx)
cancel()
_ = supervisor.Stop(cancelledContext)
require.NoError(t, supervisor.Stop(t.Context()))
return supervisor
},
trackPID: func(int) error { return trackingErr },
})
require.Nil(t, instance)
require.ErrorIs(t, startErr, trackingErr)
require.NotNil(t, supervisor)
pid := supervisor.PID()
processGroupID := supervisor.ProcessGroupID()
t.Cleanup(func() {
_ = syscall.Kill(-processGroupID, syscall.SIGKILL)
select {
case <-supervisor.Exited():
case <-time.After(5 * time.Second):
}
_ = prepared.Close()
})
require.NoError(t, syscall.Kill(-processGroupID, 0))
var startFailure *AgentStartError
require.ErrorAs(t, startErr, &startFailure)
closeErr := prepared.Close()
var usageErr *PreparedBinaryUsageError
require.ErrorAs(t, closeErr, &usageErr)
require.Equal(t, "has active consumers", usageErr.Reason)
require.NoError(t, syscall.Kill(-processGroupID, syscall.SIGKILL))
select {
case <-supervisor.Exited():
case <-time.After(5 * time.Second):
t.Fatalf("failed-start consumer PID %d was not reaped", pid)
}
require.ErrorIs(t, syscall.Kill(-processGroupID, 0), syscall.ESRCH)
require.NoError(t, startFailure.Finalize(t.Context()))
require.NoError(t, startFailure.Finalize(t.Context()))
require.NoError(t, prepared.Close())
}