diff --git a/testing/endtoend/component_handler_test.go b/testing/endtoend/component_handler_test.go index 77838f787..2e265949a 100644 --- a/testing/endtoend/component_handler_test.go +++ b/testing/endtoend/component_handler_test.go @@ -2,6 +2,9 @@ package endtoend import ( "context" + "fmt" + "os" + "strconv" "testing" "time" @@ -220,6 +223,37 @@ func (c *componentHandler) required() []e2etypes.ComponentRunner { return requiredComponents } +func (c *componentHandler) printPIDs(logger func(string, ...interface{})) { + msg := "\nPID of components. Attach a debugger... if you dare!\n\n" + + msg = "This test PID: " + strconv.Itoa(os.Getpid()) + " (parent=" + strconv.Itoa(os.Getppid()) + ")\n" + + // Beacon chain nodes + msg += fmt.Sprintf("Beacon chain nodes: %v\n", PIDsFromMultiComponentRunner(c.beaconNodes)) + // Validator nodes + msg += fmt.Sprintf("Validators: %v\n", PIDsFromMultiComponentRunner(c.validatorNodes)) + // ETH1 nodes + msg += fmt.Sprintf("ETH1 nodes: %v\n", PIDsFromMultiComponentRunner(c.eth1Nodes)) + + logger(msg) +} + +func PIDsFromMultiComponentRunner(runner e2etypes.MultipleComponentRunners) []int { + var pids []int + + for i := 0; true; i++ { + c, err := runner.ComponentAtIndex(i) + if c == nil || err != nil { + break + } + p := c.UnderlyingProcess() + if p != nil { + pids = append(pids, p.Pid) + } + } + return pids +} + func appendDebugEndpoints(cfg *e2etypes.E2EConfig) { debug := []string{ "--enable-debug-rpc-endpoints", diff --git a/testing/endtoend/components/beacon_node.go b/testing/endtoend/components/beacon_node.go index 0e9e7e066..88f09900f 100644 --- a/testing/endtoend/components/beacon_node.go +++ b/testing/endtoend/components/beacon_node.go @@ -290,3 +290,7 @@ func (node *BeaconNode) Resume() error { func (node *BeaconNode) Stop() error { return node.cmd.Process.Kill() } + +func (node *BeaconNode) UnderlyingProcess() *os.Process { + return node.cmd.Process +} diff --git a/testing/endtoend/components/eth1/depositor.go b/testing/endtoend/components/eth1/depositor.go index c22483f5e..088aa2014 100644 --- a/testing/endtoend/components/eth1/depositor.go +++ b/testing/endtoend/components/eth1/depositor.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/big" + "os" "sync" "time" @@ -218,3 +219,7 @@ func (d *Depositor) contractDepositor() (*contracts.DepositContract, error) { } return d.cd, nil } + +func (d *Depositor) UnderlyingProcess() *os.Process { + return nil // No subprocess for this component. +} diff --git a/testing/endtoend/components/eth1/node.go b/testing/endtoend/components/eth1/node.go index b98cc7fd7..ae97015a7 100644 --- a/testing/endtoend/components/eth1/node.go +++ b/testing/endtoend/components/eth1/node.go @@ -151,3 +151,7 @@ func (node *Node) Resume() error { func (node *Node) Stop() error { return node.cmd.Process.Kill() } + +func (node *Node) UnderlyingProcess() *os.Process { + return node.cmd.Process +} diff --git a/testing/endtoend/components/lighthouse_validator.go b/testing/endtoend/components/lighthouse_validator.go index d949a2c06..3e8d217cf 100644 --- a/testing/endtoend/components/lighthouse_validator.go +++ b/testing/endtoend/components/lighthouse_validator.go @@ -19,6 +19,7 @@ import ( "github.com/prysmaticlabs/prysm/v3/runtime/interop" "github.com/prysmaticlabs/prysm/v3/testing/endtoend/helpers" e2e "github.com/prysmaticlabs/prysm/v3/testing/endtoend/params" + "github.com/prysmaticlabs/prysm/v3/testing/endtoend/types" e2etypes "github.com/prysmaticlabs/prysm/v3/testing/endtoend/types" "github.com/prysmaticlabs/prysm/v3/validator/keymanager" keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4" @@ -248,6 +249,8 @@ func (v *LighthouseValidatorNode) Stop() error { return v.cmd.Process.Kill() } +var _ types.ComponentRunner = &KeystoreGenerator{} + type KeystoreGenerator struct { started chan struct{} } @@ -362,3 +365,7 @@ func setupKeystores(valClientIdx, startIdx, numOfKeys int) (string, error) { } return testNetDir, nil } + +func (k *KeystoreGenerator) UnderlyingProcess() *os.Process { + return nil // No subprocess for this component. +} diff --git a/testing/endtoend/components/tracing_sink.go b/testing/endtoend/components/tracing_sink.go index 4da6e6b3e..f6c5b6de4 100644 --- a/testing/endtoend/components/tracing_sink.go +++ b/testing/endtoend/components/tracing_sink.go @@ -14,8 +14,11 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v3/testing/endtoend/helpers" e2e "github.com/prysmaticlabs/prysm/v3/testing/endtoend/params" + "github.com/prysmaticlabs/prysm/v3/testing/endtoend/types" ) +var _ types.ComponentRunner = &TracingSink{} + // TracingSink to capture HTTP requests from opentracing pushes. This is meant // to capture all opentracing spans from Prysm during an end-to-end test. Spans // are normally sent to a jaeger (https://www.jaegertracing.io/docs/1.25/getting-started/) @@ -146,3 +149,7 @@ func captureRequest(f io.Writer, r *http.Request) error { } return nil } + +func (ts *TracingSink) UnderlyingProcess() *os.Process { + return nil // No subprocess for this component. +} diff --git a/testing/endtoend/components/validator.go b/testing/endtoend/components/validator.go index 0e86b1bdc..3eb2e9cad 100644 --- a/testing/endtoend/components/validator.go +++ b/testing/endtoend/components/validator.go @@ -297,6 +297,10 @@ func (v *ValidatorNode) Stop() error { return v.cmd.Process.Kill() } +func (v *ValidatorNode) UnderlyingProcess() *os.Process { + return v.cmd.Process +} + func createProposerSettingsPath(pubkeys []string, validatorIndex int) (string, error) { testNetDir := e2e.TestParams.TestPath + fmt.Sprintf("/proposer-settings/validator_%d", validatorIndex) configPath := filepath.Join(testNetDir, "config.json") diff --git a/testing/endtoend/components/web3remotesigner.go b/testing/endtoend/components/web3remotesigner.go index 49b00ff2c..65c0e7c07 100644 --- a/testing/endtoend/components/web3remotesigner.go +++ b/testing/endtoend/components/web3remotesigner.go @@ -273,3 +273,7 @@ func (w *Web3RemoteSigner) createTestnetDir() (string, error) { return configPath, nil } + +func (w *Web3RemoteSigner) UnderlyingProcess() *os.Process { + return w.cmd.Process +} diff --git a/testing/endtoend/endtoend_test.go b/testing/endtoend/endtoend_test.go index d6ca906b5..046dcaae1 100644 --- a/testing/endtoend/endtoend_test.go +++ b/testing/endtoend/endtoend_test.go @@ -448,6 +448,8 @@ func (r *testRunner) defaultEndToEndRun() error { return errors.Wrap(err, "components take too long to start") } + r.comHandler.printPIDs(t.Logf) + // Since defer unwraps in LIFO order, parent context will be closed only after logs are written. defer helpers.LogOutput(t) if config.UsePprof { @@ -550,6 +552,8 @@ func (r *testRunner) scenarioRun() error { return errors.Wrap(err, "components take too long to start") } + r.comHandler.printPIDs(t.Logf) + // Since defer unwraps in LIFO order, parent context will be closed only after logs are written. defer helpers.LogOutput(t) if config.UsePprof { diff --git a/testing/endtoend/types/types.go b/testing/endtoend/types/types.go index 71c645bba..c1821f5e8 100644 --- a/testing/endtoend/types/types.go +++ b/testing/endtoend/types/types.go @@ -4,6 +4,7 @@ package types import ( "context" + "os" types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" "google.golang.org/grpc" @@ -101,6 +102,8 @@ type ComponentRunner interface { Resume() error // Stop stops a component. Stop() error + // UnderlyingProcess is the underlying process, once started. + UnderlyingProcess() *os.Process } type MultipleComponentRunners interface {