Skip to content

Commit

Permalink
cmd: alpha test peers tests (#3039)
Browse files Browse the repository at this point in the history
Continuation of the epic for `alpha test` command.

In this PR are included:
- Start of TCP libp2p node.
- Connection to other peer nodes (using hash of the ENRs as an ID for the relay).
- Launching 3 ping tests towards peers:
  - Ping - regular ping done only once. It blocks the rest of the peer tests. We assume that if we cannot successfully ping a peer, there is no reason to execute any other tests against that peer.
  - PingMeasure - regular ping done only once, measuring the RTT. RTT is considered either good, average or bad.
  - PingLoad - continuous pings, spawning each second a new go routine doing pings, measuring the RTT of each one of them. The RTT is considered either good, average or bad. Worst observed RTT is picked as a resulting value.
- Keeping the TCP node alive (configurable by a flag), in order other peers to be able to conduct tests on their end.

N.B.: There are some hardcoded values that are subject to change:
- Threshold for good/average/bad for PingMeasure test (currently set to 200/500ms);
- Threshold for good/average/bad for PingLoad test (currently set to 200/500ms);
- Await time between ping attempts in Ping test, when peer is not reachable (currently set to 3s);
- Await time between pings in PingLoad test per go routine (currently set to random value between 0 and 100ms);

Not in scope of this PR:
- Tests against self
- More elaborate tests towards peers - direct/indirect connections, packet loss, etc.

category: feature
ticket: #2997
  • Loading branch information
KaloyanTanev authored Apr 19, 2024
1 parent ff6a69b commit 21d34cc
Show file tree
Hide file tree
Showing 7 changed files with 538 additions and 271 deletions.
42 changes: 39 additions & 3 deletions cmd/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,27 @@
package cmd

import (
"context"
"fmt"
"io"
"os"
"os/signal"
"sort"
"strings"
"syscall"
"time"

"github.com/pelletier/go-toml/v2"
"github.com/spf13/cobra"

"github.com/obolnetwork/charon/app/errors"
"github.com/obolnetwork/charon/app/log"
)

var (
errTimeoutInterrupted = testResultError{errors.New("timeout/interrupted")}
errNotImplemented = testResultError{errors.New("not implemented")}
errNoTicker = testResultError{errors.New("no ticker")}
)

type testConfig struct {
Expand Down Expand Up @@ -73,12 +83,25 @@ const (
categoryScoreC categoryScore = "C"
)

// toml fails on marshaling errors to string, so we wrap the errors and add custom marshal
type testResultError struct{ error }

type testResult struct {
Name string
Verdict testVerdict
Measurement string
Suggestion string
Error string
Error testResultError
}

func (s *testResultError) UnmarshalText(data []byte) error {
s.error = errors.New(string(data))
return nil
}

// MarshalText implements encoding.TextMarshaler
func (s testResultError) MarshalText() ([]byte, error) {
return []byte(s.Error()), nil
}

type testCaseName struct {
Expand Down Expand Up @@ -160,8 +183,8 @@ func writeResultToWriter(res testCategoryResult, w io.Writer) error {
suggestions = append(suggestions, singleTestRes.Suggestion)
}

if singleTestRes.Error != "" {
testOutput += " - " + singleTestRes.Error
if singleTestRes.Error.error != nil {
testOutput += " - " + singleTestRes.Error.Error()
}
lines = append(lines, testOutput)
}
Expand Down Expand Up @@ -231,3 +254,16 @@ func sortTests(tests []testCaseName) {
return tests[i].order < tests[j].order
})
}

func blockAndWait(ctx context.Context, awaitTime time.Duration) {
notifyCtx, cancelNotifyCtx := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)
defer cancelNotifyCtx()
keepAliveCtx, cancelKeepAliveCtx := context.WithTimeout(ctx, awaitTime)
defer cancelKeepAliveCtx()
select {
case <-keepAliveCtx.Done():
log.Info(ctx, "Await time reached or interrupted")
case <-notifyCtx.Done():
log.Info(ctx, "Forcefully stopped")
}
}
27 changes: 8 additions & 19 deletions cmd/testbeacon.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package cmd
import (
"context"
"io"
"sort"
"time"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -60,9 +59,6 @@ func runTestBeacon(ctx context.Context, w io.Writer, cfg testBeaconConfig) (err
return errors.New("test case not supported")
}
sortTests(queuedTests)
sort.Slice(queuedTests, func(i, j int) bool {
return queuedTests[i].order < queuedTests[j].order
})

parentCtx := ctx
if parentCtx == nil {
Expand All @@ -71,24 +67,17 @@ func runTestBeacon(ctx context.Context, w io.Writer, cfg testBeaconConfig) (err
timeoutCtx, cancel := context.WithTimeout(parentCtx, cfg.Timeout)
defer cancel()

ch := make(chan map[string][]testResult)
resultsCh := make(chan map[string][]testResult)
testResults := make(map[string][]testResult)
startTime := time.Now()
finished := false

// run test suite for all beacon nodes
go testAllBeacons(timeoutCtx, queuedTests, testCases, cfg, ch)
go testAllBeacons(timeoutCtx, queuedTests, testCases, cfg, resultsCh)

for !finished {
select {
case <-ctx.Done():
finished = true
case result, ok := <-ch:
if !ok {
finished = true
}
maps.Copy(testResults, result)
}
for result := range resultsCh {
maps.Copy(testResults, result)
}

execTime := Duration{time.Since(startTime)}

// use highest score as score of all
Expand Down Expand Up @@ -163,7 +152,7 @@ func testSingleBeacon(ctx context.Context, queuedTestCases []testCaseName, allTe
select {
case <-ctx.Done():
name = queuedTestCases[testCounter].name
res = append(res, testResult{Name: name, Verdict: testVerdictFail, Error: "timeout"})
res = append(res, testResult{Name: name, Verdict: testVerdictFail, Error: errTimeoutInterrupted})
finished = true
case result, ok := <-ch:
if !ok {
Expand Down Expand Up @@ -200,7 +189,7 @@ func beaconPing(ctx context.Context, _ *testBeaconConfig, _ string) testResult {
default:
return testResult{
Verdict: testVerdictFail,
Error: errors.New("ping not implemented").Error(),
Error: errNotImplemented,
}
}
}
20 changes: 10 additions & 10 deletions cmd/testbeacon_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ func TestBeaconTest(t *testing.T) {
},
expected: testCategoryResult{
Targets: map[string][]testResult{
"beacon-endpoint-1": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: "ping not implemented"}},
"beacon-endpoint-2": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: "ping not implemented"}},
"beacon-endpoint-1": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}},
"beacon-endpoint-2": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}},
},
},
expectedErr: "",
Expand All @@ -56,8 +56,8 @@ func TestBeaconTest(t *testing.T) {
},
expected: testCategoryResult{
Targets: map[string][]testResult{
"beacon-endpoint-1": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: "timeout"}},
"beacon-endpoint-2": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: "timeout"}},
"beacon-endpoint-1": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errTimeoutInterrupted}},
"beacon-endpoint-2": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errTimeoutInterrupted}},
},
},
expectedErr: "",
Expand All @@ -75,8 +75,8 @@ func TestBeaconTest(t *testing.T) {
},
expected: testCategoryResult{
Targets: map[string][]testResult{
"beacon-endpoint-1": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: "ping not implemented"}},
"beacon-endpoint-2": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: "ping not implemented"}},
"beacon-endpoint-1": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}},
"beacon-endpoint-2": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}},
},
},
expectedErr: "",
Expand Down Expand Up @@ -108,8 +108,8 @@ func TestBeaconTest(t *testing.T) {
},
expected: testCategoryResult{
Targets: map[string][]testResult{
"beacon-endpoint-1": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: "ping not implemented"}},
"beacon-endpoint-2": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: "ping not implemented"}},
"beacon-endpoint-1": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}},
"beacon-endpoint-2": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}},
},
},
expectedErr: "",
Expand All @@ -129,8 +129,8 @@ func TestBeaconTest(t *testing.T) {
expected: testCategoryResult{
CategoryName: "beacon",
Targets: map[string][]testResult{
"beacon-endpoint-1": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: "ping not implemented"}},
"beacon-endpoint-2": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: "ping not implemented"}},
"beacon-endpoint-1": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}},
"beacon-endpoint-2": {{Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}},
},
Score: categoryScoreC,
},
Expand Down
Loading

0 comments on commit 21d34cc

Please sign in to comment.