Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit 23c2dbd

Browse files
committed
fix/internal/grpc: retry: add requires-network tag to BUILD.bazel
1 parent c1ff60f commit 23c2dbd

12 files changed

Lines changed: 1761 additions & 5 deletions

internal/grpc/retry/BUILD.bazel

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,12 @@ go_test(
3434
"retry_test.go",
3535
],
3636
embed = [":retry"],
37-
flaky = True,
3837
tags = [
3938
TAG_PLATFORM_SOURCE,
40-
"manual",
39+
"requires-network",
4140
],
4241
deps = [
43-
"@com_github_grpc_ecosystem_go_grpc_middleware_v2//testing/testpb",
42+
"//internal/grpc/retry/testpb",
4443
"@com_github_sourcegraph_log//:log",
4544
"@com_github_sourcegraph_log//logtest",
4645
"@com_github_stretchr_testify//assert",

internal/grpc/retry/examples_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import (
88
"io"
99
"time"
1010

11-
"github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb"
1211
logger "github.com/sourcegraph/log"
1312
"google.golang.org/grpc"
1413
"google.golang.org/grpc/codes"
14+
15+
"github.com/sourcegraph/sourcegraph/internal/grpc/retry/testpb"
1516
)
1617

1718
var cc *grpc.ClientConn

internal/grpc/retry/retry_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ import (
1010
"testing"
1111
"time"
1212

13-
"github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb"
1413
"github.com/sourcegraph/log/logtest"
1514
"github.com/stretchr/testify/assert"
1615
"github.com/stretchr/testify/require"
1716
"github.com/stretchr/testify/suite"
1817
"google.golang.org/grpc"
1918
"google.golang.org/grpc/codes"
2019
"google.golang.org/grpc/status"
20+
21+
"github.com/sourcegraph/sourcegraph/internal/grpc/retry/testpb"
2122
)
2223

2324
var (
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
load("@io_bazel_rules_go//go:def.bzl", "go_library")
2+
load("//dev:go_defs.bzl", "go_test")
3+
4+
go_library(
5+
name = "testpb",
6+
srcs = [
7+
"interceptor_suite.go",
8+
"pingservice.go",
9+
"test.manual_validator.pb.go",
10+
"test.pb.go",
11+
"test_grpc.pb.go",
12+
],
13+
importpath = "github.com/sourcegraph/sourcegraph/internal/grpc/retry/testpb",
14+
visibility = ["//:__subpackages__"],
15+
deps = [
16+
"@com_github_stretchr_testify//require",
17+
"@com_github_stretchr_testify//suite",
18+
"@org_golang_google_grpc//:go_default_library",
19+
"@org_golang_google_grpc//codes",
20+
"@org_golang_google_grpc//credentials",
21+
"@org_golang_google_grpc//credentials/insecure",
22+
"@org_golang_google_grpc//status",
23+
"@org_golang_google_protobuf//reflect/protoreflect",
24+
"@org_golang_google_protobuf//runtime/protoimpl",
25+
],
26+
)
27+
28+
go_test(
29+
name = "testpb_test",
30+
srcs = ["pingservice_test.go"],
31+
embed = [":testpb"],
32+
deps = [
33+
"@com_github_stretchr_testify//require",
34+
"@org_golang_google_grpc//:go_default_library",
35+
"@org_golang_google_grpc//codes",
36+
"@org_golang_google_grpc//credentials/insecure",
37+
"@org_golang_google_grpc//status",
38+
],
39+
)
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
// Copyright (c) The go-grpc-middleware Authors.
2+
// Licensed under the Apache License 2.0.
3+
4+
package testpb
5+
6+
import (
7+
"context"
8+
"crypto/rand"
9+
"crypto/rsa"
10+
"crypto/tls"
11+
"crypto/x509"
12+
"crypto/x509/pkix"
13+
"encoding/pem"
14+
"flag"
15+
"math/big"
16+
"net"
17+
"sync"
18+
"time"
19+
20+
"github.com/stretchr/testify/require"
21+
"github.com/stretchr/testify/suite"
22+
"google.golang.org/grpc"
23+
"google.golang.org/grpc/credentials"
24+
"google.golang.org/grpc/credentials/insecure"
25+
)
26+
27+
var (
28+
flagTls = flag.Bool("use_tls", true, "whether all gRPC middleware tests should use tls")
29+
30+
certPEM []byte
31+
keyPEM []byte
32+
)
33+
34+
// InterceptorTestSuite is a testify/Suite that starts a gRPC PingService server and a client.
35+
type InterceptorTestSuite struct {
36+
suite.Suite
37+
38+
TestService TestServiceServer
39+
ServerOpts []grpc.ServerOption
40+
ClientOpts []grpc.DialOption
41+
42+
serverAddr string
43+
ServerListener net.Listener
44+
Server *grpc.Server
45+
clientConn *grpc.ClientConn
46+
Client TestServiceClient
47+
48+
restartServerWithDelayedStart chan time.Duration
49+
serverRunning chan bool
50+
51+
cancels []context.CancelFunc
52+
}
53+
54+
func (s *InterceptorTestSuite) SetupSuite() {
55+
s.restartServerWithDelayedStart = make(chan time.Duration)
56+
s.serverRunning = make(chan bool)
57+
58+
s.serverAddr = "127.0.0.1:0"
59+
var err error
60+
certPEM, keyPEM, err = generateCertAndKey([]string{"localhost", "example.com"})
61+
require.NoError(s.T(), err, "unable to generate test certificate/key")
62+
63+
go func() {
64+
for {
65+
var err error
66+
s.ServerListener, err = net.Listen("tcp", s.serverAddr)
67+
require.NoError(s.T(), err, "must be able to allocate a port for serverListener")
68+
s.serverAddr = s.ServerListener.Addr().String()
69+
if *flagTls {
70+
cert, err := tls.X509KeyPair(certPEM, keyPEM)
71+
require.NoError(s.T(), err, "unable to load test TLS certificate")
72+
creds := credentials.NewServerTLSFromCert(&cert)
73+
s.ServerOpts = append(s.ServerOpts, grpc.Creds(creds))
74+
}
75+
// This is the point where we hook up the interceptor.
76+
s.Server = grpc.NewServer(s.ServerOpts...)
77+
// Create a service if the instantiator hasn't provided one.
78+
if s.TestService == nil {
79+
s.TestService = &TestPingService{}
80+
}
81+
RegisterTestServiceServer(s.Server, s.TestService)
82+
83+
w := sync.WaitGroup{}
84+
w.Add(1)
85+
go func() {
86+
_ = s.Server.Serve(s.ServerListener)
87+
w.Done()
88+
}()
89+
if s.Client == nil {
90+
s.Client = s.NewClient(s.ClientOpts...)
91+
}
92+
93+
s.serverRunning <- true
94+
95+
d := <-s.restartServerWithDelayedStart
96+
s.Server.Stop()
97+
time.Sleep(d)
98+
w.Wait()
99+
}
100+
}()
101+
102+
select {
103+
case <-s.serverRunning:
104+
case <-time.After(2 * time.Second):
105+
s.T().Fatal("server failed to start before deadline")
106+
}
107+
}
108+
109+
func (s *InterceptorTestSuite) RestartServer(delayedStart time.Duration) <-chan bool {
110+
s.restartServerWithDelayedStart <- delayedStart
111+
time.Sleep(10 * time.Millisecond)
112+
return s.serverRunning
113+
}
114+
115+
func (s *InterceptorTestSuite) NewClient(dialOpts ...grpc.DialOption) TestServiceClient {
116+
newDialOpts := append(dialOpts, grpc.WithBlock())
117+
var err error
118+
if *flagTls {
119+
cp := x509.NewCertPool()
120+
if !cp.AppendCertsFromPEM(certPEM) {
121+
s.T().Fatal("failed to append certificate")
122+
}
123+
creds := credentials.NewTLS(&tls.Config{ServerName: "localhost", RootCAs: cp})
124+
newDialOpts = append(newDialOpts, grpc.WithTransportCredentials(creds))
125+
} else {
126+
newDialOpts = append(newDialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
127+
}
128+
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
129+
defer cancel()
130+
s.clientConn, err = grpc.DialContext(ctx, s.ServerAddr(), newDialOpts...)
131+
require.NoError(s.T(), err, "must not error on client Dial")
132+
return NewTestServiceClient(s.clientConn)
133+
}
134+
135+
func (s *InterceptorTestSuite) ServerAddr() string {
136+
return s.serverAddr
137+
}
138+
139+
type ctxTestNumber struct{}
140+
141+
var (
142+
ctxTestNumberKey = &ctxTestNumber{}
143+
zero = 0
144+
)
145+
146+
func ExtractCtxTestNumber(ctx context.Context) *int {
147+
if v, ok := ctx.Value(ctxTestNumberKey).(*int); ok {
148+
return v
149+
}
150+
return &zero
151+
}
152+
153+
// UnaryServerInterceptor returns a new unary server interceptors that adds query information logging.
154+
func UnaryServerInterceptor() grpc.UnaryServerInterceptor {
155+
return func(ctx context.Context, req any, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
156+
// newCtx := newContext(ctx, log, opts)
157+
newCtx := ctx
158+
resp, err := handler(newCtx, req)
159+
return resp, err
160+
}
161+
}
162+
163+
func (s *InterceptorTestSuite) SimpleCtx() context.Context {
164+
ctx, cancel := context.WithTimeout(context.TODO(), 2*time.Second)
165+
ctx = context.WithValue(ctx, ctxTestNumberKey, 1)
166+
s.cancels = append(s.cancels, cancel)
167+
return ctx
168+
}
169+
170+
func (s *InterceptorTestSuite) DeadlineCtx(deadline time.Time) context.Context {
171+
ctx, cancel := context.WithDeadline(context.TODO(), deadline)
172+
s.cancels = append(s.cancels, cancel)
173+
return ctx
174+
}
175+
176+
func (s *InterceptorTestSuite) TearDownSuite() {
177+
time.Sleep(10 * time.Millisecond)
178+
if s.ServerListener != nil {
179+
s.Server.GracefulStop()
180+
s.T().Logf("stopped grpc.Server at: %v", s.ServerAddr())
181+
_ = s.ServerListener.Close()
182+
}
183+
if s.clientConn != nil {
184+
_ = s.clientConn.Close()
185+
}
186+
for _, c := range s.cancels {
187+
c()
188+
}
189+
}
190+
191+
// generateCertAndKey copied from https://github.com/johanbrandhorst/certify/blob/master/issuers/vault/vault_suite_test.go#L255
192+
// with minor modifications.
193+
func generateCertAndKey(san []string) ([]byte, []byte, error) {
194+
priv, err := rsa.GenerateKey(rand.Reader, 2048)
195+
if err != nil {
196+
return nil, nil, err
197+
}
198+
notBefore := time.Now()
199+
notAfter := notBefore.Add(time.Hour)
200+
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
201+
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
202+
if err != nil {
203+
return nil, nil, err
204+
}
205+
template := x509.Certificate{
206+
SerialNumber: serialNumber,
207+
Subject: pkix.Name{
208+
CommonName: "example.com",
209+
},
210+
NotBefore: notBefore,
211+
NotAfter: notAfter,
212+
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
213+
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
214+
BasicConstraintsValid: true,
215+
DNSNames: san,
216+
}
217+
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv)
218+
if err != nil {
219+
return nil, nil, err
220+
}
221+
certOut := pem.EncodeToMemory(&pem.Block{
222+
Type: "CERTIFICATE",
223+
Bytes: derBytes,
224+
})
225+
keyOut := pem.EncodeToMemory(&pem.Block{
226+
Type: "RSA PRIVATE KEY",
227+
Bytes: x509.MarshalPKCS1PrivateKey(priv),
228+
})
229+
230+
return certOut, keyOut, nil
231+
}

0 commit comments

Comments
 (0)