diff --git a/cmd/test.go b/cmd/test.go index bd7d0e3d5..1d057b0d1 100644 --- a/cmd/test.go +++ b/cmd/test.go @@ -87,11 +87,12 @@ const ( type testResultError struct{ error } type testResult struct { - Name string - Verdict testVerdict - Measurement string - Suggestion string - Error testResultError + Name string + Verdict testVerdict + Measurement string + Suggestion string + Error testResultError + IsAcceptable bool } func (s *testResultError) UnmarshalText(data []byte) error { @@ -101,6 +102,10 @@ func (s *testResultError) UnmarshalText(data []byte) error { // MarshalText implements encoding.TextMarshaler func (s testResultError) MarshalText() ([]byte, error) { + if s.error == nil { + return []byte{}, nil + } + return []byte(s.Error()), nil } @@ -214,12 +219,18 @@ func calculateScore(results []testResult) categoryScore { avg := 0 for _, t := range results { switch t.Verdict { - case testVerdictBad, testVerdictFail: + case testVerdictBad: return categoryScoreC case testVerdictGood: avg++ case testVerdictAvg: avg-- + case testVerdictFail: + if !t.IsAcceptable { + return categoryScoreC + } + + continue case testVerdictOk: continue } diff --git a/cmd/testpeers.go b/cmd/testpeers.go index 18106f6cd..d8d8f5296 100644 --- a/cmd/testpeers.go +++ b/cmd/testpeers.go @@ -10,6 +10,7 @@ import ( "io" "math" "math/rand" + "net" "slices" "strings" "time" @@ -99,7 +100,7 @@ func supportedPeerTestCases() map[testCaseName]testCasePeer { func supportedSelfTestCases() map[testCaseName]func(context.Context, *testPeersConfig) testResult { return map[testCaseName]func(context.Context, *testPeersConfig) testResult{ - {name: "natOpen", order: 1}: natOpenTest, + {name: "libp2pTCPPortOpenTest", order: 1}: libp2pTCPPortOpenTest, } } @@ -569,15 +570,49 @@ func peerPingLoadTest(ctx context.Context, conf *testPeersConfig, tcpNode host.H return testRes } -func natOpenTest(ctx context.Context, _ *testPeersConfig) testResult { - // TODO(kalo): implement real port check - select { - case <-ctx.Done(): - return testResult{Verdict: testVerdictFail} - default: - return testResult{ - Verdict: testVerdictFail, - Error: errNotImplemented, - } +func dialLibp2pTCPIP(ctx context.Context, address string) error { + d := net.Dialer{Timeout: time.Second} + conn, err := d.DialContext(ctx, "tcp", address) + if err != nil { + return errors.Wrap(err, "net dial") + } + defer conn.Close() + buf := new(strings.Builder) + _, err = io.CopyN(buf, conn, 19) + if err != nil { + return errors.Wrap(err, "io copy") + } + if !strings.Contains(buf.String(), "/multistream/1.0.0") { + return errors.New("multistream not found", z.Any("found", buf.String()), z.Any("address", address)) + } + + err = conn.Close() + if err != nil { + return errors.Wrap(err, "close conn") } + + return nil +} + +func libp2pTCPPortOpenTest(ctx context.Context, cfg *testPeersConfig) testResult { + testRes := testResult{Name: "Libp2pTCPPortOpen"} + + group, _ := errgroup.WithContext(ctx) + + for _, addr := range cfg.P2P.TCPAddrs { + addrVal := addr + group.Go(func() error { return dialLibp2pTCPIP(ctx, addrVal) }) + } + + err := group.Wait() + if err != nil { + testRes.Verdict = testVerdictFail + testRes.Error = testResultError{err} + + return testRes + } + + testRes.Verdict = testVerdictOk + + return testRes } diff --git a/cmd/testpeers_internal_test.go b/cmd/testpeers_internal_test.go index 3d1482c71..b33ad356e 100644 --- a/cmd/testpeers_internal_test.go +++ b/cmd/testpeers_internal_test.go @@ -51,7 +51,7 @@ func TestPeersTest(t *testing.T) { CategoryName: "peers", Targets: map[string][]testResult{ "self": { - {Name: "natOpen", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}, + {Name: "libp2pTCPPortOpenTest", Verdict: testVerdictOk, Measurement: "", Suggestion: "", Error: testResultError{nil}}, }, "frantic-colony - enr:-JG4QFI0llFYxSoTAHm24OrbgoVx77dL6Ehl1Ydys39JYoWcBhiHrRhtGXDTaygWNsEWFb1cL7a1Bk0klIdaNuXplKWGAYGv0Gt7gmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQL6bcis0tFXnbqG4KuywxT5BLhtmijPFApKCDJNl3mXFYN0Y3CCDhqDdWRwgg4u": { {Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errTimeoutInterrupted}, @@ -87,7 +87,7 @@ func TestPeersTest(t *testing.T) { CategoryName: "peers", Targets: map[string][]testResult{ "self": { - {Name: "natOpen", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}, + {Name: "libp2pTCPPortOpenTest", Verdict: testVerdictOk, Measurement: "", Suggestion: "", Error: testResultError{nil}}, }, "frantic-colony - enr:-JG4QFI0llFYxSoTAHm24OrbgoVx77dL6Ehl1Ydys39JYoWcBhiHrRhtGXDTaygWNsEWFb1cL7a1Bk0klIdaNuXplKWGAYGv0Gt7gmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQL6bcis0tFXnbqG4KuywxT5BLhtmijPFApKCDJNl3mXFYN0Y3CCDhqDdWRwgg4u": { {Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errTimeoutInterrupted}, @@ -175,7 +175,7 @@ func TestPeersTest(t *testing.T) { CategoryName: "peers", Targets: map[string][]testResult{ "self": { - {Name: "natOpen", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errNotImplemented}, + {Name: "libp2pTCPPortOpenTest", Verdict: testVerdictOk, Measurement: "", Suggestion: "", Error: testResultError{nil}}, }, "frantic-colony - enr:-JG4QFI0llFYxSoTAHm24OrbgoVx77dL6Ehl1Ydys39JYoWcBhiHrRhtGXDTaygWNsEWFb1cL7a1Bk0klIdaNuXplKWGAYGv0Gt7gmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQL6bcis0tFXnbqG4KuywxT5BLhtmijPFApKCDJNl3mXFYN0Y3CCDhqDdWRwgg4u": { {Name: "ping", Verdict: testVerdictFail, Measurement: "", Suggestion: "", Error: errTimeoutInterrupted},