Initial commit

This commit is contained in:
Donny
2019-04-22 20:46:32 +08:00
commit 49ab8aadd1
25441 changed files with 4055000 additions and 0 deletions

56
vendor/google.golang.org/grpc/test/BUILD.bazel.in generated vendored Normal file
View File

@@ -0,0 +1,56 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"rawConnWrapper.go",
"servertester.go",
],
importpath = "google.golang.org/grpc/test",
visibility = ["//visibility:public"],
deps = [
"@org_golang_x_net//http2:go_default_library",
"@org_golang_x_net//http2/hpack:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"channelz_test.go",
"end2end_test.go",
"gracefulstop_test.go",
],
embed = [":go_default_library"],
deps = [
"//:go_default_library",
"//balancer/grpclb:go_default_library",
"//balancer/roundrobin:go_default_library",
"//codes:go_default_library",
"//connectivity:go_default_library",
"//credentials:go_default_library",
"//encoding/gzip:go_default_library",
"//grpclog/glogger:go_default_library",
"//health:go_default_library",
"//health/grpc_health_v1:go_default_library",
"//internal:go_default_library",
"//internal/channelz:go_default_library",
"//internal/leakcheck:go_default_library",
"//keepalive:go_default_library",
"//metadata:go_default_library",
"//peer:go_default_library",
"//resolver:go_default_library",
"//resolver/manual:go_default_library",
"//resolver/passthrough:go_default_library",
"//stats:go_default_library",
"//status:go_default_library",
"//tap:go_default_library",
"//test/grpc_testing:go_default_library",
"//testdata:go_default_library",
"@com_github_golang_protobuf//proto:go_default_library",
"@io_bazel_rules_go//proto/wkt:any_go_proto",
"@org_golang_google_genproto//googleapis/rpc/status:go_default_library",
"@org_golang_x_net//context:go_default_library",
"@org_golang_x_net//http2:go_default_library",
],
)

190
vendor/google.golang.org/grpc/test/balancer_test.go generated vendored Normal file
View File

@@ -0,0 +1,190 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package test
import (
"context"
"reflect"
"testing"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/internal/leakcheck"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/resolver"
testpb "google.golang.org/grpc/test/grpc_testing"
"google.golang.org/grpc/testdata"
)
const testBalancerName = "testbalancer"
// testBalancer creates one subconn with the first address from resolved
// addresses.
//
// It's used to test options for NewSubConn are applies correctly.
type testBalancer struct {
cc balancer.ClientConn
sc balancer.SubConn
newSubConnOptions balancer.NewSubConnOptions
pickOptions []balancer.PickOptions
doneInfo []balancer.DoneInfo
}
func (b *testBalancer) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
b.cc = cc
return b
}
func (*testBalancer) Name() string {
return testBalancerName
}
func (b *testBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
// Only create a subconn at the first time.
if err == nil && b.sc == nil {
b.sc, err = b.cc.NewSubConn(addrs, b.newSubConnOptions)
if err != nil {
grpclog.Errorf("testBalancer: failed to NewSubConn: %v", err)
return
}
b.cc.UpdateBalancerState(connectivity.Connecting, &picker{sc: b.sc, bal: b})
b.sc.Connect()
}
}
func (b *testBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
grpclog.Infof("testBalancer: HandleSubConnStateChange: %p, %v", sc, s)
if b.sc != sc {
grpclog.Infof("testBalancer: ignored state change because sc is not recognized")
return
}
if s == connectivity.Shutdown {
b.sc = nil
return
}
switch s {
case connectivity.Ready, connectivity.Idle:
b.cc.UpdateBalancerState(s, &picker{sc: sc, bal: b})
case connectivity.Connecting:
b.cc.UpdateBalancerState(s, &picker{err: balancer.ErrNoSubConnAvailable, bal: b})
case connectivity.TransientFailure:
b.cc.UpdateBalancerState(s, &picker{err: balancer.ErrTransientFailure, bal: b})
}
}
func (b *testBalancer) Close() {
}
type picker struct {
err error
sc balancer.SubConn
bal *testBalancer
}
func (p *picker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
p.bal.pickOptions = append(p.bal.pickOptions, opts)
if p.err != nil {
return nil, nil, p.err
}
return p.sc, func(d balancer.DoneInfo) { p.bal.doneInfo = append(p.bal.doneInfo, d) }, nil
}
func TestCredsBundleFromBalancer(t *testing.T) {
balancer.Register(&testBalancer{
newSubConnOptions: balancer.NewSubConnOptions{
CredsBundle: &testCredsBundle{},
},
})
defer leakcheck.Check(t)
te := newTest(t, env{name: "creds-bundle", network: "tcp", balancer: ""})
te.tapHandle = authHandle
te.customDialOptions = []grpc.DialOption{
grpc.WithBalancerName(testBalancerName),
}
creds, err := credentials.NewServerTLSFromFile(testdata.Path("server1.pem"), testdata.Path("server1.key"))
if err != nil {
t.Fatalf("Failed to generate credentials %v", err)
}
te.customServerOptions = []grpc.ServerOption{
grpc.Creds(creds),
}
te.startServer(&testServer{})
defer te.tearDown()
cc := te.clientConn()
tc := testpb.NewTestServiceClient(cc)
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
t.Fatalf("Test failed. Reason: %v", err)
}
}
func TestPickAndDone(t *testing.T) {
defer leakcheck.Check(t)
for _, e := range listTestEnv() {
testPickAndDone(t, e)
}
}
func testPickAndDone(t *testing.T, e env) {
te := newTest(t, e)
b := &testBalancer{}
balancer.Register(b)
te.customDialOptions = []grpc.DialOption{
grpc.WithBalancerName(testBalancerName),
}
te.userAgent = failAppUA
te.startServer(&testServer{security: e.security})
defer te.tearDown()
cc := te.clientConn()
tc := testpb.NewTestServiceClient(cc)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
wantErr := detailedError
if _, err := tc.EmptyCall(ctx, &testpb.Empty{}); !reflect.DeepEqual(err, wantErr) {
t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want _, %v", err, wantErr)
}
md := metadata.Pairs("testMDKey", "testMDVal")
ctx = metadata.NewOutgoingContext(ctx, md)
if _, err := tc.UnaryCall(ctx, &testpb.SimpleRequest{}); err != nil {
t.Fatalf("TestService.UnaryCall(%v, _, _, _) = _, %v; want _, <nil>", ctx, err)
}
poWant := []balancer.PickOptions{
{FullMethodName: "/grpc.testing.TestService/EmptyCall"},
{FullMethodName: "/grpc.testing.TestService/UnaryCall", Header: md},
}
if !reflect.DeepEqual(b.pickOptions, poWant) {
t.Fatalf("b.pickOptions = %v; want %v", b.pickOptions, poWant)
}
if len(b.doneInfo) < 1 || !reflect.DeepEqual(b.doneInfo[0].Err, wantErr) {
t.Fatalf("b.doneInfo = %v; want b.doneInfo[0].Err = %v", b.doneInfo, wantErr)
}
if len(b.doneInfo) < 2 || !reflect.DeepEqual(b.doneInfo[1].Trailer, testTrailerMetadata) {
t.Fatalf("b.doneInfo = %v; want b.doneInfo[1].Trailer = %v", b.doneInfo, testTrailerMetadata)
}
}

View File

@@ -0,0 +1,14 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["bufconn.go"],
importpath = "google.golang.org/grpc/test/bufconn",
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["bufconn_test.go"],
embed = [":go_default_library"],
)

244
vendor/google.golang.org/grpc/test/bufconn/bufconn.go generated vendored Normal file
View File

@@ -0,0 +1,244 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package bufconn provides a net.Conn implemented by a buffer and related
// dialing and listening functionality.
package bufconn
import (
"fmt"
"io"
"net"
"sync"
"time"
)
// Listener implements a net.Listener that creates local, buffered net.Conns
// via its Accept and Dial method.
type Listener struct {
mu sync.Mutex
sz int
ch chan net.Conn
done chan struct{}
}
var errClosed = fmt.Errorf("Closed")
// Listen returns a Listener that can only be contacted by its own Dialers and
// creates buffered connections between the two.
func Listen(sz int) *Listener {
return &Listener{sz: sz, ch: make(chan net.Conn), done: make(chan struct{})}
}
// Accept blocks until Dial is called, then returns a net.Conn for the server
// half of the connection.
func (l *Listener) Accept() (net.Conn, error) {
select {
case <-l.done:
return nil, errClosed
case c := <-l.ch:
return c, nil
}
}
// Close stops the listener.
func (l *Listener) Close() error {
l.mu.Lock()
defer l.mu.Unlock()
select {
case <-l.done:
// Already closed.
break
default:
close(l.done)
}
return nil
}
// Addr reports the address of the listener.
func (l *Listener) Addr() net.Addr { return addr{} }
// Dial creates an in-memory full-duplex network connection, unblocks Accept by
// providing it the server half of the connection, and returns the client half
// of the connection.
func (l *Listener) Dial() (net.Conn, error) {
p1, p2 := newPipe(l.sz), newPipe(l.sz)
select {
case <-l.done:
return nil, errClosed
case l.ch <- &conn{p1, p2}:
return &conn{p2, p1}, nil
}
}
type pipe struct {
mu sync.Mutex
// buf contains the data in the pipe. It is a ring buffer of fixed capacity,
// with r and w pointing to the offset to read and write, respsectively.
//
// Data is read between [r, w) and written to [w, r), wrapping around the end
// of the slice if necessary.
//
// The buffer is empty if r == len(buf), otherwise if r == w, it is full.
//
// w and r are always in the range [0, cap(buf)) and [0, len(buf)].
buf []byte
w, r int
wwait sync.Cond
rwait sync.Cond
closed bool
writeClosed bool
}
func newPipe(sz int) *pipe {
p := &pipe{buf: make([]byte, 0, sz)}
p.wwait.L = &p.mu
p.rwait.L = &p.mu
return p
}
func (p *pipe) empty() bool {
return p.r == len(p.buf)
}
func (p *pipe) full() bool {
return p.r < len(p.buf) && p.r == p.w
}
func (p *pipe) Read(b []byte) (n int, err error) {
p.mu.Lock()
defer p.mu.Unlock()
// Block until p has data.
for {
if p.closed {
return 0, io.ErrClosedPipe
}
if !p.empty() {
break
}
if p.writeClosed {
return 0, io.EOF
}
p.rwait.Wait()
}
wasFull := p.full()
n = copy(b, p.buf[p.r:len(p.buf)])
p.r += n
if p.r == cap(p.buf) {
p.r = 0
p.buf = p.buf[:p.w]
}
// Signal a blocked writer, if any
if wasFull {
p.wwait.Signal()
}
return n, nil
}
func (p *pipe) Write(b []byte) (n int, err error) {
p.mu.Lock()
defer p.mu.Unlock()
if p.closed {
return 0, io.ErrClosedPipe
}
for len(b) > 0 {
// Block until p is not full.
for {
if p.closed || p.writeClosed {
return 0, io.ErrClosedPipe
}
if !p.full() {
break
}
p.wwait.Wait()
}
wasEmpty := p.empty()
end := cap(p.buf)
if p.w < p.r {
end = p.r
}
x := copy(p.buf[p.w:end], b)
b = b[x:]
n += x
p.w += x
if p.w > len(p.buf) {
p.buf = p.buf[:p.w]
}
if p.w == cap(p.buf) {
p.w = 0
}
// Signal a blocked reader, if any.
if wasEmpty {
p.rwait.Signal()
}
}
return n, nil
}
func (p *pipe) Close() error {
p.mu.Lock()
defer p.mu.Unlock()
p.closed = true
// Signal all blocked readers and writers to return an error.
p.rwait.Broadcast()
p.wwait.Broadcast()
return nil
}
func (p *pipe) closeWrite() error {
p.mu.Lock()
defer p.mu.Unlock()
p.writeClosed = true
// Signal all blocked readers and writers to return an error.
p.rwait.Broadcast()
p.wwait.Broadcast()
return nil
}
type conn struct {
io.Reader
io.Writer
}
func (c *conn) Close() error {
err1 := c.Reader.(*pipe).Close()
err2 := c.Writer.(*pipe).closeWrite()
if err1 != nil {
return err1
}
return err2
}
func (*conn) LocalAddr() net.Addr { return addr{} }
func (*conn) RemoteAddr() net.Addr { return addr{} }
func (c *conn) SetDeadline(t time.Time) error { return fmt.Errorf("unsupported") }
func (c *conn) SetReadDeadline(t time.Time) error { return fmt.Errorf("unsupported") }
func (c *conn) SetWriteDeadline(t time.Time) error { return fmt.Errorf("unsupported") }
type addr struct{}
func (addr) Network() string { return "bufconn" }
func (addr) String() string { return "bufconn" }

View File

@@ -0,0 +1,199 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package bufconn
import (
"fmt"
"io"
"net"
"reflect"
"testing"
"time"
)
func testRW(r io.Reader, w io.Writer) error {
for i := 0; i < 20; i++ {
d := make([]byte, i)
for j := 0; j < i; j++ {
d[j] = byte(i - j)
}
var rn int
var rerr error
b := make([]byte, i)
done := make(chan struct{})
go func() {
for rn < len(b) && rerr == nil {
var x int
x, rerr = r.Read(b[rn:])
rn += x
}
close(done)
}()
wn, werr := w.Write(d)
if wn != i || werr != nil {
return fmt.Errorf("%v: w.Write(%v) = %v, %v; want %v, nil", i, d, wn, werr, i)
}
select {
case <-done:
case <-time.After(500 * time.Millisecond):
return fmt.Errorf("%v: r.Read never returned", i)
}
if rn != i || rerr != nil {
return fmt.Errorf("%v: r.Read = %v, %v; want %v, nil", i, rn, rerr, i)
}
if !reflect.DeepEqual(b, d) {
return fmt.Errorf("%v: r.Read read %v; want %v", i, b, d)
}
}
return nil
}
func TestPipe(t *testing.T) {
p := newPipe(10)
if err := testRW(p, p); err != nil {
t.Fatalf(err.Error())
}
}
func TestPipeClose(t *testing.T) {
p := newPipe(10)
p.Close()
if _, err := p.Write(nil); err != io.ErrClosedPipe {
t.Fatalf("p.Write = _, %v; want _, %v", err, io.ErrClosedPipe)
}
if _, err := p.Read(nil); err != io.ErrClosedPipe {
t.Fatalf("p.Read = _, %v; want _, %v", err, io.ErrClosedPipe)
}
}
func TestConn(t *testing.T) {
p1, p2 := newPipe(10), newPipe(10)
c1, c2 := &conn{p1, p2}, &conn{p2, p1}
if err := testRW(c1, c2); err != nil {
t.Fatalf(err.Error())
}
if err := testRW(c2, c1); err != nil {
t.Fatalf(err.Error())
}
}
func TestConnCloseWithData(t *testing.T) {
lis := Listen(7)
errChan := make(chan error)
var lisConn net.Conn
go func() {
var err error
if lisConn, err = lis.Accept(); err != nil {
errChan <- err
}
close(errChan)
}()
dialConn, err := lis.Dial()
if err != nil {
t.Fatalf("Dial error: %v", err)
}
if err := <-errChan; err != nil {
t.Fatalf("Listen error: %v", err)
}
// Write some data on both sides of the connection.
n, err := dialConn.Write([]byte("hello"))
if n != 5 || err != nil {
t.Fatalf("dialConn.Write([]byte{\"hello\"}) = %v, %v; want 5, <nil>", n, err)
}
n, err = lisConn.Write([]byte("hello"))
if n != 5 || err != nil {
t.Fatalf("lisConn.Write([]byte{\"hello\"}) = %v, %v; want 5, <nil>", n, err)
}
// Close dial-side; writes from either side should fail.
dialConn.Close()
if _, err := lisConn.Write([]byte("hello")); err != io.ErrClosedPipe {
t.Fatalf("lisConn.Write() = _, <nil>; want _, <non-nil>")
}
if _, err := dialConn.Write([]byte("hello")); err != io.ErrClosedPipe {
t.Fatalf("dialConn.Write() = _, <nil>; want _, <non-nil>")
}
// Read from both sides; reads on lisConn should work, but dialConn should
// fail.
buf := make([]byte, 6)
if _, err := dialConn.Read(buf); err != io.ErrClosedPipe {
t.Fatalf("dialConn.Read(buf) = %v, %v; want _, io.ErrClosedPipe", n, err)
}
n, err = lisConn.Read(buf)
if n != 5 || err != nil {
t.Fatalf("lisConn.Read(buf) = %v, %v; want 5, <nil>", n, err)
}
}
func TestListener(t *testing.T) {
l := Listen(7)
var s net.Conn
var serr error
done := make(chan struct{})
go func() {
s, serr = l.Accept()
close(done)
}()
c, cerr := l.Dial()
<-done
if cerr != nil || serr != nil {
t.Fatalf("cerr = %v, serr = %v; want nil, nil", cerr, serr)
}
if err := testRW(c, s); err != nil {
t.Fatalf(err.Error())
}
if err := testRW(s, c); err != nil {
t.Fatalf(err.Error())
}
}
func TestCloseWhileDialing(t *testing.T) {
l := Listen(7)
var c net.Conn
var err error
done := make(chan struct{})
go func() {
c, err = l.Dial()
close(done)
}()
l.Close()
<-done
if c != nil || err != errClosed {
t.Fatalf("c, err = %v, %v; want nil, %v", c, err, errClosed)
}
}
func TestCloseWhileAccepting(t *testing.T) {
l := Listen(7)
var c net.Conn
var err error
done := make(chan struct{})
go func() {
c, err = l.Accept()
close(done)
}()
l.Close()
<-done
if c != nil || err != errClosed {
t.Fatalf("c, err = %v, %v; want nil, %v", c, err, errClosed)
}
}

View File

@@ -0,0 +1,100 @@
// +build go1.10,linux,!appengine
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// The test in this file should be run in an environment that has go1.10 or later,
// as the function SyscallConn() (required to get socket option) was
// introduced to net.TCPListener in go1.10.
package test
import (
"testing"
"time"
"google.golang.org/grpc/internal/channelz"
"google.golang.org/grpc/internal/leakcheck"
testpb "google.golang.org/grpc/test/grpc_testing"
)
func TestCZSocketMetricsSocketOption(t *testing.T) {
envs := []env{tcpClearRREnv, tcpTLSRREnv}
for _, e := range envs {
testCZSocketMetricsSocketOption(t, e)
}
}
func testCZSocketMetricsSocketOption(t *testing.T, e env) {
defer leakcheck.Check(t)
channelz.NewChannelzStorage()
te := newTest(t, e)
te.startServer(&testServer{security: e.security})
defer te.tearDown()
cc := te.clientConn()
tc := testpb.NewTestServiceClient(cc)
doSuccessfulUnaryCall(tc, t)
time.Sleep(10 * time.Millisecond)
ss, _ := channelz.GetServers(0)
if len(ss) != 1 {
t.Fatalf("There should be one server, not %d", len(ss))
}
if len(ss[0].ListenSockets) != 1 {
t.Fatalf("There should be one listen socket, not %d", len(ss[0].ListenSockets))
}
for id := range ss[0].ListenSockets {
sm := channelz.GetSocket(id)
if sm == nil || sm.SocketData == nil || sm.SocketData.SocketOptions == nil {
t.Fatalf("Unable to get server listen socket options")
}
}
ns, _ := channelz.GetServerSockets(ss[0].ID, 0)
if len(ns) != 1 {
t.Fatalf("There should be one server normal socket, not %d", len(ns))
}
if ns[0] == nil || ns[0].SocketData == nil || ns[0].SocketData.SocketOptions == nil {
t.Fatalf("Unable to get server normal socket options")
}
tchan, _ := channelz.GetTopChannels(0)
if len(tchan) != 1 {
t.Fatalf("There should only be one top channel, not %d", len(tchan))
}
if len(tchan[0].SubChans) != 1 {
t.Fatalf("There should only be one subchannel under top channel %d, not %d", tchan[0].ID, len(tchan[0].SubChans))
}
var id int64
for id = range tchan[0].SubChans {
break
}
sc := channelz.GetSubChannel(id)
if sc == nil {
t.Fatalf("There should only be one socket under subchannel %d, not 0", id)
}
if len(sc.Sockets) != 1 {
t.Fatalf("There should only be one socket under subchannel %d, not %d", sc.ID, len(sc.Sockets))
}
for id = range sc.Sockets {
break
}
skt := channelz.GetSocket(id)
if skt == nil || skt.SocketData == nil || skt.SocketData.SocketOptions == nil {
t.Fatalf("Unable to get client normal socket options")
}
}

1915
vendor/google.golang.org/grpc/test/channelz_test.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
proto_library(
name = "codec_perf_proto",
srcs = ["perf.proto"],
visibility = ["//visibility:public"],
)
go_proto_library(
name = "codec_perf_go_proto",
importpath = "google.golang.org/grpc/test/codec_perf",
proto = ":codec_perf_proto",
visibility = ["//visibility:public"],
)
go_library(
name = "go_default_library",
embed = [":codec_perf_go_proto"],
importpath = "google.golang.org/grpc/test/codec_perf",
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,75 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: codec_perf/perf.proto
package codec_perf
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// Buffer is a message that contains a body of bytes that is used to exercise
// encoding and decoding overheads.
type Buffer struct {
Body []byte `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Buffer) Reset() { *m = Buffer{} }
func (m *Buffer) String() string { return proto.CompactTextString(m) }
func (*Buffer) ProtoMessage() {}
func (*Buffer) Descriptor() ([]byte, []int) {
return fileDescriptor_perf_6cc81a33b24d08e7, []int{0}
}
func (m *Buffer) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Buffer.Unmarshal(m, b)
}
func (m *Buffer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Buffer.Marshal(b, m, deterministic)
}
func (dst *Buffer) XXX_Merge(src proto.Message) {
xxx_messageInfo_Buffer.Merge(dst, src)
}
func (m *Buffer) XXX_Size() int {
return xxx_messageInfo_Buffer.Size(m)
}
func (m *Buffer) XXX_DiscardUnknown() {
xxx_messageInfo_Buffer.DiscardUnknown(m)
}
var xxx_messageInfo_Buffer proto.InternalMessageInfo
func (m *Buffer) GetBody() []byte {
if m != nil {
return m.Body
}
return nil
}
func init() {
proto.RegisterType((*Buffer)(nil), "codec.perf.Buffer")
}
func init() { proto.RegisterFile("codec_perf/perf.proto", fileDescriptor_perf_6cc81a33b24d08e7) }
var fileDescriptor_perf_6cc81a33b24d08e7 = []byte{
// 83 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4d, 0xce, 0x4f, 0x49,
0x4d, 0x8e, 0x2f, 0x48, 0x2d, 0x4a, 0xd3, 0x07, 0x11, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42,
0x5c, 0x60, 0x61, 0x3d, 0x90, 0x88, 0x92, 0x0c, 0x17, 0x9b, 0x53, 0x69, 0x5a, 0x5a, 0x6a, 0x91,
0x90, 0x10, 0x17, 0x4b, 0x52, 0x7e, 0x4a, 0xa5, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x4f, 0x10, 0x98,
0x9d, 0xc4, 0x06, 0xd6, 0x60, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x5f, 0x4f, 0x3c, 0x49,
0x00, 0x00, 0x00,
}

View File

@@ -0,0 +1,25 @@
// Copyright 2017 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Messages used for performance tests that may not reference grpc directly for
// reasons of import cycles.
syntax = "proto3";
package codec.perf;
// Buffer is a message that contains a body of bytes that is used to exercise
// encoding and decoding overheads.
message Buffer {
bytes body = 1;
}

131
vendor/google.golang.org/grpc/test/creds_test.go generated vendored Normal file
View File

@@ -0,0 +1,131 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package test
// TODO(https://github.com/grpc/grpc-go/issues/2330): move all creds releated
// tests to this file.
import (
"context"
"testing"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/internal/leakcheck"
testpb "google.golang.org/grpc/test/grpc_testing"
"google.golang.org/grpc/testdata"
)
const (
bundlePerRPCOnly = "perRPCOnly"
bundleTLSOnly = "tlsOnly"
)
type testCredsBundle struct {
t *testing.T
mode string
}
func (c *testCredsBundle) TransportCredentials() credentials.TransportCredentials {
if c.mode == bundlePerRPCOnly {
return nil
}
creds, err := credentials.NewClientTLSFromFile(testdata.Path("ca.pem"), "x.test.youtube.com")
if err != nil {
c.t.Logf("Failed to load credentials: %v", err)
return nil
}
return creds
}
func (c *testCredsBundle) PerRPCCredentials() credentials.PerRPCCredentials {
if c.mode == bundleTLSOnly {
return nil
}
return testPerRPCCredentials{}
}
func (c *testCredsBundle) NewWithMode(mode string) (credentials.Bundle, error) {
return &testCredsBundle{mode: mode}, nil
}
func TestCredsBundleBoth(t *testing.T) {
defer leakcheck.Check(t)
te := newTest(t, env{name: "creds-bundle", network: "tcp", balancer: "v1", security: "empty"})
te.tapHandle = authHandle
te.customDialOptions = []grpc.DialOption{
grpc.WithCredentialsBundle(&testCredsBundle{t: t}),
}
creds, err := credentials.NewServerTLSFromFile(testdata.Path("server1.pem"), testdata.Path("server1.key"))
if err != nil {
t.Fatalf("Failed to generate credentials %v", err)
}
te.customServerOptions = []grpc.ServerOption{
grpc.Creds(creds),
}
te.startServer(&testServer{})
defer te.tearDown()
cc := te.clientConn()
tc := testpb.NewTestServiceClient(cc)
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
t.Fatalf("Test failed. Reason: %v", err)
}
}
func TestCredsBundleTransportCredentials(t *testing.T) {
defer leakcheck.Check(t)
te := newTest(t, env{name: "creds-bundle", network: "tcp", balancer: "v1", security: "empty"})
te.customDialOptions = []grpc.DialOption{
grpc.WithCredentialsBundle(&testCredsBundle{t: t, mode: bundleTLSOnly}),
}
creds, err := credentials.NewServerTLSFromFile(testdata.Path("server1.pem"), testdata.Path("server1.key"))
if err != nil {
t.Fatalf("Failed to generate credentials %v", err)
}
te.customServerOptions = []grpc.ServerOption{
grpc.Creds(creds),
}
te.startServer(&testServer{})
defer te.tearDown()
cc := te.clientConn()
tc := testpb.NewTestServiceClient(cc)
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
t.Fatalf("Test failed. Reason: %v", err)
}
}
func TestCredsBundlePerRPCCredentials(t *testing.T) {
defer leakcheck.Check(t)
te := newTest(t, env{name: "creds-bundle", network: "tcp", balancer: "v1", security: "empty"})
te.tapHandle = authHandle
te.customDialOptions = []grpc.DialOption{
grpc.WithCredentialsBundle(&testCredsBundle{t: t, mode: bundlePerRPCOnly}),
}
te.startServer(&testServer{})
defer te.tearDown()
cc := te.clientConn()
tc := testpb.NewTestServiceClient(cc)
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
t.Fatalf("Test failed. Reason: %v", err)
}
}

7201
vendor/google.golang.org/grpc/test/end2end_test.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

53
vendor/google.golang.org/grpc/test/go_vet/vet.go generated vendored Normal file
View File

@@ -0,0 +1,53 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// vet checks whether files that are supposed to be built on appengine running
// Go 1.10 or earlier import an unsupported package (e.g. "unsafe", "syscall").
package main
import (
"fmt"
"go/build"
"os"
)
func main() {
fail := false
b := build.Default
b.BuildTags = []string{"appengine", "appenginevm"}
argsWithoutProg := os.Args[1:]
for _, dir := range argsWithoutProg {
p, err := b.Import(".", dir, 0)
if _, ok := err.(*build.NoGoError); ok {
continue
} else if err != nil {
fmt.Printf("build.Import failed due to %v\n", err)
fail = true
continue
}
for _, pkg := range p.Imports {
if pkg == "syscall" || pkg == "unsafe" {
fmt.Printf("Package %s/%s importing %s package without appengine build tag is NOT ALLOWED!\n", p.Dir, p.Name, pkg)
fail = true
}
}
}
if fail {
os.Exit(1)
}
}

212
vendor/google.golang.org/grpc/test/gracefulstop_test.go generated vendored Normal file
View File

@@ -0,0 +1,212 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package test
import (
"context"
"fmt"
"io"
"net"
"sync"
"testing"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/internal/leakcheck"
testpb "google.golang.org/grpc/test/grpc_testing"
)
type delayListener struct {
net.Listener
closeCalled chan struct{}
acceptCalled chan struct{}
allowCloseCh chan struct{}
cc *delayConn
dialed bool
}
func (d *delayListener) Accept() (net.Conn, error) {
select {
case <-d.acceptCalled:
// On the second call, block until closed, then return an error.
<-d.closeCalled
<-d.allowCloseCh
return nil, fmt.Errorf("listener is closed")
default:
close(d.acceptCalled)
conn, err := d.Listener.Accept()
// Allow closing of listener only after accept.
// Note: Dial can return successfully, yet Accept
// might now have finished.
d.allowClose()
return conn, err
}
}
func (d *delayListener) allowClose() {
close(d.allowCloseCh)
}
func (d *delayListener) Close() error {
close(d.closeCalled)
go func() {
<-d.allowCloseCh
d.Listener.Close()
}()
return nil
}
func (d *delayListener) allowClientRead() {
d.cc.allowRead()
}
func (d *delayListener) Dial(to time.Duration) (net.Conn, error) {
if d.dialed {
// Only hand out one connection (net.Dial can return more even after the
// listener is closed). This is not thread-safe, but Dial should never be
// called concurrently in this environment.
return nil, fmt.Errorf("no more conns")
}
d.dialed = true
c, err := net.DialTimeout("tcp", d.Listener.Addr().String(), to)
if err != nil {
return nil, err
}
d.cc = &delayConn{Conn: c, blockRead: make(chan struct{})}
return d.cc, nil
}
type delayConn struct {
net.Conn
blockRead chan struct{}
}
func (d *delayConn) allowRead() {
close(d.blockRead)
}
func (d *delayConn) Read(b []byte) (n int, err error) {
<-d.blockRead
return d.Conn.Read(b)
}
func TestGracefulStop(t *testing.T) {
defer leakcheck.Check(t)
// This test ensures GracefulStop cannot race and break RPCs on new
// connections created after GracefulStop was called but before
// listener.Accept() returns a "closing" error.
//
// Steps of this test:
// 1. Start Server
// 2. GracefulStop() Server after listener's Accept is called, but don't
// allow Accept() to exit when Close() is called on it.
// 3. Create a new connection to the server after listener.Close() is called.
// Server will want to send a GoAway on the new conn, but we delay client
// reads until 5.
// 4. Send an RPC on the new connection.
// 5. Allow the client to read the GoAway. The RPC should complete
// successfully.
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("Error listenening: %v", err)
}
dlis := &delayListener{
Listener: lis,
acceptCalled: make(chan struct{}),
closeCalled: make(chan struct{}),
allowCloseCh: make(chan struct{}),
}
d := func(_ string, to time.Duration) (net.Conn, error) { return dlis.Dial(to) }
serverGotReq := make(chan struct{})
ss := &stubServer{
fullDuplexCall: func(stream testpb.TestService_FullDuplexCallServer) error {
close(serverGotReq)
_, err := stream.Recv()
if err != nil {
return err
}
return stream.Send(&testpb.StreamingOutputCallResponse{})
},
}
s := grpc.NewServer()
testpb.RegisterTestServiceServer(s, ss)
// 1. Start Server
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
s.Serve(dlis)
wg.Done()
}()
// 2. GracefulStop() Server after listener's Accept is called, but don't
// allow Accept() to exit when Close() is called on it.
<-dlis.acceptCalled
wg.Add(1)
go func() {
s.GracefulStop()
wg.Done()
}()
// 3. Create a new connection to the server after listener.Close() is called.
// Server will want to send a GoAway on the new conn, but we delay it
// until 5.
<-dlis.closeCalled // Block until GracefulStop calls dlis.Close()
// Now dial. The listener's Accept method will return a valid connection,
// even though GracefulStop has closed the listener.
ctx, dialCancel := context.WithTimeout(context.Background(), 5*time.Second)
defer dialCancel()
cc, err := grpc.DialContext(ctx, "", grpc.WithInsecure(), grpc.WithBlock(), grpc.WithDialer(d))
if err != nil {
t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err)
}
client := testpb.NewTestServiceClient(cc)
defer cc.Close()
// 4. Send an RPC on the new connection.
// The server would send a GOAWAY first, but we are delaying the server's
// writes for now until the client writes more than the preface.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
stream, err := client.FullDuplexCall(ctx)
if err != nil {
t.Fatalf("FullDuplexCall= _, %v; want _, <nil>", err)
}
go func() {
// 5. Allow the client to read the GoAway. The RPC should complete
// successfully.
<-serverGotReq
dlis.allowClientRead()
}()
if err := stream.Send(&testpb.StreamingOutputCallRequest{}); err != nil {
t.Fatalf("stream.Send(_) = %v, want <nil>", err)
}
if _, err := stream.Recv(); err != nil {
t.Fatalf("stream.Recv() = _, %v, want _, <nil>", err)
}
if _, err := stream.Recv(); err != io.EOF {
t.Fatalf("stream.Recv() = _, %v, want _, io.EOF", err)
}
// 5. happens above, then we finish the call.
cancel()
wg.Wait()
}

View File

@@ -0,0 +1,23 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
proto_library(
name = "grpc_testing_proto",
srcs = ["test.proto"],
visibility = ["//visibility:public"],
)
go_proto_library(
name = "grpc_testing_go_proto",
compilers = ["@io_bazel_rules_go//proto:go_grpc"],
importpath = "google.golang.org/grpc/test/grpc_testing",
proto = ":grpc_testing_proto",
visibility = ["//visibility:public"],
)
go_library(
name = "go_default_library",
embed = [":grpc_testing_go_proto"],
importpath = "google.golang.org/grpc/test/grpc_testing",
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,949 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: grpc_testing/test.proto
package grpc_testing
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// The type of payload that should be returned.
type PayloadType int32
const (
// Compressable text format.
PayloadType_COMPRESSABLE PayloadType = 0
// Uncompressable binary format.
PayloadType_UNCOMPRESSABLE PayloadType = 1
// Randomly chosen from all other formats defined in this enum.
PayloadType_RANDOM PayloadType = 2
)
var PayloadType_name = map[int32]string{
0: "COMPRESSABLE",
1: "UNCOMPRESSABLE",
2: "RANDOM",
}
var PayloadType_value = map[string]int32{
"COMPRESSABLE": 0,
"UNCOMPRESSABLE": 1,
"RANDOM": 2,
}
func (x PayloadType) String() string {
return proto.EnumName(PayloadType_name, int32(x))
}
func (PayloadType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_test_c9f6c5af4267cb88, []int{0}
}
type Empty struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Empty) Reset() { *m = Empty{} }
func (m *Empty) String() string { return proto.CompactTextString(m) }
func (*Empty) ProtoMessage() {}
func (*Empty) Descriptor() ([]byte, []int) {
return fileDescriptor_test_c9f6c5af4267cb88, []int{0}
}
func (m *Empty) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Empty.Unmarshal(m, b)
}
func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Empty.Marshal(b, m, deterministic)
}
func (dst *Empty) XXX_Merge(src proto.Message) {
xxx_messageInfo_Empty.Merge(dst, src)
}
func (m *Empty) XXX_Size() int {
return xxx_messageInfo_Empty.Size(m)
}
func (m *Empty) XXX_DiscardUnknown() {
xxx_messageInfo_Empty.DiscardUnknown(m)
}
var xxx_messageInfo_Empty proto.InternalMessageInfo
// A block of data, to simply increase gRPC message size.
type Payload struct {
// The type of data in body.
Type PayloadType `protobuf:"varint,1,opt,name=type,proto3,enum=grpc.testing.PayloadType" json:"type,omitempty"`
// Primary contents of payload.
Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Payload) Reset() { *m = Payload{} }
func (m *Payload) String() string { return proto.CompactTextString(m) }
func (*Payload) ProtoMessage() {}
func (*Payload) Descriptor() ([]byte, []int) {
return fileDescriptor_test_c9f6c5af4267cb88, []int{1}
}
func (m *Payload) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Payload.Unmarshal(m, b)
}
func (m *Payload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Payload.Marshal(b, m, deterministic)
}
func (dst *Payload) XXX_Merge(src proto.Message) {
xxx_messageInfo_Payload.Merge(dst, src)
}
func (m *Payload) XXX_Size() int {
return xxx_messageInfo_Payload.Size(m)
}
func (m *Payload) XXX_DiscardUnknown() {
xxx_messageInfo_Payload.DiscardUnknown(m)
}
var xxx_messageInfo_Payload proto.InternalMessageInfo
func (m *Payload) GetType() PayloadType {
if m != nil {
return m.Type
}
return PayloadType_COMPRESSABLE
}
func (m *Payload) GetBody() []byte {
if m != nil {
return m.Body
}
return nil
}
// Unary request.
type SimpleRequest struct {
// Desired payload type in the response from the server.
// If response_type is RANDOM, server randomly chooses one from other formats.
ResponseType PayloadType `protobuf:"varint,1,opt,name=response_type,json=responseType,proto3,enum=grpc.testing.PayloadType" json:"response_type,omitempty"`
// Desired payload size in the response from the server.
// If response_type is COMPRESSABLE, this denotes the size before compression.
ResponseSize int32 `protobuf:"varint,2,opt,name=response_size,json=responseSize,proto3" json:"response_size,omitempty"`
// Optional input payload sent along with the request.
Payload *Payload `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
// Whether SimpleResponse should include username.
FillUsername bool `protobuf:"varint,4,opt,name=fill_username,json=fillUsername,proto3" json:"fill_username,omitempty"`
// Whether SimpleResponse should include OAuth scope.
FillOauthScope bool `protobuf:"varint,5,opt,name=fill_oauth_scope,json=fillOauthScope,proto3" json:"fill_oauth_scope,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SimpleRequest) Reset() { *m = SimpleRequest{} }
func (m *SimpleRequest) String() string { return proto.CompactTextString(m) }
func (*SimpleRequest) ProtoMessage() {}
func (*SimpleRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_test_c9f6c5af4267cb88, []int{2}
}
func (m *SimpleRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SimpleRequest.Unmarshal(m, b)
}
func (m *SimpleRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SimpleRequest.Marshal(b, m, deterministic)
}
func (dst *SimpleRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_SimpleRequest.Merge(dst, src)
}
func (m *SimpleRequest) XXX_Size() int {
return xxx_messageInfo_SimpleRequest.Size(m)
}
func (m *SimpleRequest) XXX_DiscardUnknown() {
xxx_messageInfo_SimpleRequest.DiscardUnknown(m)
}
var xxx_messageInfo_SimpleRequest proto.InternalMessageInfo
func (m *SimpleRequest) GetResponseType() PayloadType {
if m != nil {
return m.ResponseType
}
return PayloadType_COMPRESSABLE
}
func (m *SimpleRequest) GetResponseSize() int32 {
if m != nil {
return m.ResponseSize
}
return 0
}
func (m *SimpleRequest) GetPayload() *Payload {
if m != nil {
return m.Payload
}
return nil
}
func (m *SimpleRequest) GetFillUsername() bool {
if m != nil {
return m.FillUsername
}
return false
}
func (m *SimpleRequest) GetFillOauthScope() bool {
if m != nil {
return m.FillOauthScope
}
return false
}
// Unary response, as configured by the request.
type SimpleResponse struct {
// Payload to increase message size.
Payload *Payload `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
// The user the request came from, for verifying authentication was
// successful when the client expected it.
Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
// OAuth scope.
OauthScope string `protobuf:"bytes,3,opt,name=oauth_scope,json=oauthScope,proto3" json:"oauth_scope,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SimpleResponse) Reset() { *m = SimpleResponse{} }
func (m *SimpleResponse) String() string { return proto.CompactTextString(m) }
func (*SimpleResponse) ProtoMessage() {}
func (*SimpleResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_test_c9f6c5af4267cb88, []int{3}
}
func (m *SimpleResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SimpleResponse.Unmarshal(m, b)
}
func (m *SimpleResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SimpleResponse.Marshal(b, m, deterministic)
}
func (dst *SimpleResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_SimpleResponse.Merge(dst, src)
}
func (m *SimpleResponse) XXX_Size() int {
return xxx_messageInfo_SimpleResponse.Size(m)
}
func (m *SimpleResponse) XXX_DiscardUnknown() {
xxx_messageInfo_SimpleResponse.DiscardUnknown(m)
}
var xxx_messageInfo_SimpleResponse proto.InternalMessageInfo
func (m *SimpleResponse) GetPayload() *Payload {
if m != nil {
return m.Payload
}
return nil
}
func (m *SimpleResponse) GetUsername() string {
if m != nil {
return m.Username
}
return ""
}
func (m *SimpleResponse) GetOauthScope() string {
if m != nil {
return m.OauthScope
}
return ""
}
// Client-streaming request.
type StreamingInputCallRequest struct {
// Optional input payload sent along with the request.
Payload *Payload `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StreamingInputCallRequest) Reset() { *m = StreamingInputCallRequest{} }
func (m *StreamingInputCallRequest) String() string { return proto.CompactTextString(m) }
func (*StreamingInputCallRequest) ProtoMessage() {}
func (*StreamingInputCallRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_test_c9f6c5af4267cb88, []int{4}
}
func (m *StreamingInputCallRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamingInputCallRequest.Unmarshal(m, b)
}
func (m *StreamingInputCallRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StreamingInputCallRequest.Marshal(b, m, deterministic)
}
func (dst *StreamingInputCallRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_StreamingInputCallRequest.Merge(dst, src)
}
func (m *StreamingInputCallRequest) XXX_Size() int {
return xxx_messageInfo_StreamingInputCallRequest.Size(m)
}
func (m *StreamingInputCallRequest) XXX_DiscardUnknown() {
xxx_messageInfo_StreamingInputCallRequest.DiscardUnknown(m)
}
var xxx_messageInfo_StreamingInputCallRequest proto.InternalMessageInfo
func (m *StreamingInputCallRequest) GetPayload() *Payload {
if m != nil {
return m.Payload
}
return nil
}
// Client-streaming response.
type StreamingInputCallResponse struct {
// Aggregated size of payloads received from the client.
AggregatedPayloadSize int32 `protobuf:"varint,1,opt,name=aggregated_payload_size,json=aggregatedPayloadSize,proto3" json:"aggregated_payload_size,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StreamingInputCallResponse) Reset() { *m = StreamingInputCallResponse{} }
func (m *StreamingInputCallResponse) String() string { return proto.CompactTextString(m) }
func (*StreamingInputCallResponse) ProtoMessage() {}
func (*StreamingInputCallResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_test_c9f6c5af4267cb88, []int{5}
}
func (m *StreamingInputCallResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamingInputCallResponse.Unmarshal(m, b)
}
func (m *StreamingInputCallResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StreamingInputCallResponse.Marshal(b, m, deterministic)
}
func (dst *StreamingInputCallResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_StreamingInputCallResponse.Merge(dst, src)
}
func (m *StreamingInputCallResponse) XXX_Size() int {
return xxx_messageInfo_StreamingInputCallResponse.Size(m)
}
func (m *StreamingInputCallResponse) XXX_DiscardUnknown() {
xxx_messageInfo_StreamingInputCallResponse.DiscardUnknown(m)
}
var xxx_messageInfo_StreamingInputCallResponse proto.InternalMessageInfo
func (m *StreamingInputCallResponse) GetAggregatedPayloadSize() int32 {
if m != nil {
return m.AggregatedPayloadSize
}
return 0
}
// Configuration for a particular response.
type ResponseParameters struct {
// Desired payload sizes in responses from the server.
// If response_type is COMPRESSABLE, this denotes the size before compression.
Size int32 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"`
// Desired interval between consecutive responses in the response stream in
// microseconds.
IntervalUs int32 `protobuf:"varint,2,opt,name=interval_us,json=intervalUs,proto3" json:"interval_us,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ResponseParameters) Reset() { *m = ResponseParameters{} }
func (m *ResponseParameters) String() string { return proto.CompactTextString(m) }
func (*ResponseParameters) ProtoMessage() {}
func (*ResponseParameters) Descriptor() ([]byte, []int) {
return fileDescriptor_test_c9f6c5af4267cb88, []int{6}
}
func (m *ResponseParameters) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ResponseParameters.Unmarshal(m, b)
}
func (m *ResponseParameters) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ResponseParameters.Marshal(b, m, deterministic)
}
func (dst *ResponseParameters) XXX_Merge(src proto.Message) {
xxx_messageInfo_ResponseParameters.Merge(dst, src)
}
func (m *ResponseParameters) XXX_Size() int {
return xxx_messageInfo_ResponseParameters.Size(m)
}
func (m *ResponseParameters) XXX_DiscardUnknown() {
xxx_messageInfo_ResponseParameters.DiscardUnknown(m)
}
var xxx_messageInfo_ResponseParameters proto.InternalMessageInfo
func (m *ResponseParameters) GetSize() int32 {
if m != nil {
return m.Size
}
return 0
}
func (m *ResponseParameters) GetIntervalUs() int32 {
if m != nil {
return m.IntervalUs
}
return 0
}
// Server-streaming request.
type StreamingOutputCallRequest struct {
// Desired payload type in the response from the server.
// If response_type is RANDOM, the payload from each response in the stream
// might be of different types. This is to simulate a mixed type of payload
// stream.
ResponseType PayloadType `protobuf:"varint,1,opt,name=response_type,json=responseType,proto3,enum=grpc.testing.PayloadType" json:"response_type,omitempty"`
// Configuration for each expected response message.
ResponseParameters []*ResponseParameters `protobuf:"bytes,2,rep,name=response_parameters,json=responseParameters,proto3" json:"response_parameters,omitempty"`
// Optional input payload sent along with the request.
Payload *Payload `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StreamingOutputCallRequest) Reset() { *m = StreamingOutputCallRequest{} }
func (m *StreamingOutputCallRequest) String() string { return proto.CompactTextString(m) }
func (*StreamingOutputCallRequest) ProtoMessage() {}
func (*StreamingOutputCallRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_test_c9f6c5af4267cb88, []int{7}
}
func (m *StreamingOutputCallRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamingOutputCallRequest.Unmarshal(m, b)
}
func (m *StreamingOutputCallRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StreamingOutputCallRequest.Marshal(b, m, deterministic)
}
func (dst *StreamingOutputCallRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_StreamingOutputCallRequest.Merge(dst, src)
}
func (m *StreamingOutputCallRequest) XXX_Size() int {
return xxx_messageInfo_StreamingOutputCallRequest.Size(m)
}
func (m *StreamingOutputCallRequest) XXX_DiscardUnknown() {
xxx_messageInfo_StreamingOutputCallRequest.DiscardUnknown(m)
}
var xxx_messageInfo_StreamingOutputCallRequest proto.InternalMessageInfo
func (m *StreamingOutputCallRequest) GetResponseType() PayloadType {
if m != nil {
return m.ResponseType
}
return PayloadType_COMPRESSABLE
}
func (m *StreamingOutputCallRequest) GetResponseParameters() []*ResponseParameters {
if m != nil {
return m.ResponseParameters
}
return nil
}
func (m *StreamingOutputCallRequest) GetPayload() *Payload {
if m != nil {
return m.Payload
}
return nil
}
// Server-streaming response, as configured by the request and parameters.
type StreamingOutputCallResponse struct {
// Payload to increase response size.
Payload *Payload `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StreamingOutputCallResponse) Reset() { *m = StreamingOutputCallResponse{} }
func (m *StreamingOutputCallResponse) String() string { return proto.CompactTextString(m) }
func (*StreamingOutputCallResponse) ProtoMessage() {}
func (*StreamingOutputCallResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_test_c9f6c5af4267cb88, []int{8}
}
func (m *StreamingOutputCallResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamingOutputCallResponse.Unmarshal(m, b)
}
func (m *StreamingOutputCallResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StreamingOutputCallResponse.Marshal(b, m, deterministic)
}
func (dst *StreamingOutputCallResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_StreamingOutputCallResponse.Merge(dst, src)
}
func (m *StreamingOutputCallResponse) XXX_Size() int {
return xxx_messageInfo_StreamingOutputCallResponse.Size(m)
}
func (m *StreamingOutputCallResponse) XXX_DiscardUnknown() {
xxx_messageInfo_StreamingOutputCallResponse.DiscardUnknown(m)
}
var xxx_messageInfo_StreamingOutputCallResponse proto.InternalMessageInfo
func (m *StreamingOutputCallResponse) GetPayload() *Payload {
if m != nil {
return m.Payload
}
return nil
}
func init() {
proto.RegisterType((*Empty)(nil), "grpc.testing.Empty")
proto.RegisterType((*Payload)(nil), "grpc.testing.Payload")
proto.RegisterType((*SimpleRequest)(nil), "grpc.testing.SimpleRequest")
proto.RegisterType((*SimpleResponse)(nil), "grpc.testing.SimpleResponse")
proto.RegisterType((*StreamingInputCallRequest)(nil), "grpc.testing.StreamingInputCallRequest")
proto.RegisterType((*StreamingInputCallResponse)(nil), "grpc.testing.StreamingInputCallResponse")
proto.RegisterType((*ResponseParameters)(nil), "grpc.testing.ResponseParameters")
proto.RegisterType((*StreamingOutputCallRequest)(nil), "grpc.testing.StreamingOutputCallRequest")
proto.RegisterType((*StreamingOutputCallResponse)(nil), "grpc.testing.StreamingOutputCallResponse")
proto.RegisterEnum("grpc.testing.PayloadType", PayloadType_name, PayloadType_value)
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// TestServiceClient is the client API for TestService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type TestServiceClient interface {
// One empty request followed by one empty response.
EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
// One request followed by one response.
// The server returns the client payload as-is.
UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error)
// One request followed by a sequence of responses (streamed download).
// The server returns the payload with client desired type and sizes.
StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error)
// A sequence of requests followed by one response (streamed upload).
// The server returns the aggregated size of client payload as the result.
StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error)
// A sequence of requests with each request served by the server immediately.
// As one request could lead to multiple responses, this interface
// demonstrates the idea of full duplexing.
FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error)
// A sequence of requests followed by a sequence of responses.
// The server buffers all the client requests and then serves them in order. A
// stream of responses are returned to the client when the server starts with
// first request.
HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error)
}
type testServiceClient struct {
cc *grpc.ClientConn
}
func NewTestServiceClient(cc *grpc.ClientConn) TestServiceClient {
return &testServiceClient{cc}
}
func (c *testServiceClient) EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/grpc.testing.TestService/EmptyCall", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *testServiceClient) UnaryCall(ctx context.Context, in *SimpleRequest, opts ...grpc.CallOption) (*SimpleResponse, error) {
out := new(SimpleResponse)
err := c.cc.Invoke(ctx, "/grpc.testing.TestService/UnaryCall", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *testServiceClient) StreamingOutputCall(ctx context.Context, in *StreamingOutputCallRequest, opts ...grpc.CallOption) (TestService_StreamingOutputCallClient, error) {
stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[0], "/grpc.testing.TestService/StreamingOutputCall", opts...)
if err != nil {
return nil, err
}
x := &testServiceStreamingOutputCallClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type TestService_StreamingOutputCallClient interface {
Recv() (*StreamingOutputCallResponse, error)
grpc.ClientStream
}
type testServiceStreamingOutputCallClient struct {
grpc.ClientStream
}
func (x *testServiceStreamingOutputCallClient) Recv() (*StreamingOutputCallResponse, error) {
m := new(StreamingOutputCallResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *testServiceClient) StreamingInputCall(ctx context.Context, opts ...grpc.CallOption) (TestService_StreamingInputCallClient, error) {
stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[1], "/grpc.testing.TestService/StreamingInputCall", opts...)
if err != nil {
return nil, err
}
x := &testServiceStreamingInputCallClient{stream}
return x, nil
}
type TestService_StreamingInputCallClient interface {
Send(*StreamingInputCallRequest) error
CloseAndRecv() (*StreamingInputCallResponse, error)
grpc.ClientStream
}
type testServiceStreamingInputCallClient struct {
grpc.ClientStream
}
func (x *testServiceStreamingInputCallClient) Send(m *StreamingInputCallRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *testServiceStreamingInputCallClient) CloseAndRecv() (*StreamingInputCallResponse, error) {
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
m := new(StreamingInputCallResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *testServiceClient) FullDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_FullDuplexCallClient, error) {
stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[2], "/grpc.testing.TestService/FullDuplexCall", opts...)
if err != nil {
return nil, err
}
x := &testServiceFullDuplexCallClient{stream}
return x, nil
}
type TestService_FullDuplexCallClient interface {
Send(*StreamingOutputCallRequest) error
Recv() (*StreamingOutputCallResponse, error)
grpc.ClientStream
}
type testServiceFullDuplexCallClient struct {
grpc.ClientStream
}
func (x *testServiceFullDuplexCallClient) Send(m *StreamingOutputCallRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *testServiceFullDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) {
m := new(StreamingOutputCallResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *testServiceClient) HalfDuplexCall(ctx context.Context, opts ...grpc.CallOption) (TestService_HalfDuplexCallClient, error) {
stream, err := c.cc.NewStream(ctx, &_TestService_serviceDesc.Streams[3], "/grpc.testing.TestService/HalfDuplexCall", opts...)
if err != nil {
return nil, err
}
x := &testServiceHalfDuplexCallClient{stream}
return x, nil
}
type TestService_HalfDuplexCallClient interface {
Send(*StreamingOutputCallRequest) error
Recv() (*StreamingOutputCallResponse, error)
grpc.ClientStream
}
type testServiceHalfDuplexCallClient struct {
grpc.ClientStream
}
func (x *testServiceHalfDuplexCallClient) Send(m *StreamingOutputCallRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *testServiceHalfDuplexCallClient) Recv() (*StreamingOutputCallResponse, error) {
m := new(StreamingOutputCallResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// TestServiceServer is the server API for TestService service.
type TestServiceServer interface {
// One empty request followed by one empty response.
EmptyCall(context.Context, *Empty) (*Empty, error)
// One request followed by one response.
// The server returns the client payload as-is.
UnaryCall(context.Context, *SimpleRequest) (*SimpleResponse, error)
// One request followed by a sequence of responses (streamed download).
// The server returns the payload with client desired type and sizes.
StreamingOutputCall(*StreamingOutputCallRequest, TestService_StreamingOutputCallServer) error
// A sequence of requests followed by one response (streamed upload).
// The server returns the aggregated size of client payload as the result.
StreamingInputCall(TestService_StreamingInputCallServer) error
// A sequence of requests with each request served by the server immediately.
// As one request could lead to multiple responses, this interface
// demonstrates the idea of full duplexing.
FullDuplexCall(TestService_FullDuplexCallServer) error
// A sequence of requests followed by a sequence of responses.
// The server buffers all the client requests and then serves them in order. A
// stream of responses are returned to the client when the server starts with
// first request.
HalfDuplexCall(TestService_HalfDuplexCallServer) error
}
func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) {
s.RegisterService(&_TestService_serviceDesc, srv)
}
func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TestServiceServer).EmptyCall(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpc.testing.TestService/EmptyCall",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TestServiceServer).EmptyCall(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _TestService_UnaryCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SimpleRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TestServiceServer).UnaryCall(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpc.testing.TestService/UnaryCall",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TestServiceServer).UnaryCall(ctx, req.(*SimpleRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TestService_StreamingOutputCall_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(StreamingOutputCallRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(TestServiceServer).StreamingOutputCall(m, &testServiceStreamingOutputCallServer{stream})
}
type TestService_StreamingOutputCallServer interface {
Send(*StreamingOutputCallResponse) error
grpc.ServerStream
}
type testServiceStreamingOutputCallServer struct {
grpc.ServerStream
}
func (x *testServiceStreamingOutputCallServer) Send(m *StreamingOutputCallResponse) error {
return x.ServerStream.SendMsg(m)
}
func _TestService_StreamingInputCall_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(TestServiceServer).StreamingInputCall(&testServiceStreamingInputCallServer{stream})
}
type TestService_StreamingInputCallServer interface {
SendAndClose(*StreamingInputCallResponse) error
Recv() (*StreamingInputCallRequest, error)
grpc.ServerStream
}
type testServiceStreamingInputCallServer struct {
grpc.ServerStream
}
func (x *testServiceStreamingInputCallServer) SendAndClose(m *StreamingInputCallResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *testServiceStreamingInputCallServer) Recv() (*StreamingInputCallRequest, error) {
m := new(StreamingInputCallRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func _TestService_FullDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(TestServiceServer).FullDuplexCall(&testServiceFullDuplexCallServer{stream})
}
type TestService_FullDuplexCallServer interface {
Send(*StreamingOutputCallResponse) error
Recv() (*StreamingOutputCallRequest, error)
grpc.ServerStream
}
type testServiceFullDuplexCallServer struct {
grpc.ServerStream
}
func (x *testServiceFullDuplexCallServer) Send(m *StreamingOutputCallResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *testServiceFullDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) {
m := new(StreamingOutputCallRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func _TestService_HalfDuplexCall_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(TestServiceServer).HalfDuplexCall(&testServiceHalfDuplexCallServer{stream})
}
type TestService_HalfDuplexCallServer interface {
Send(*StreamingOutputCallResponse) error
Recv() (*StreamingOutputCallRequest, error)
grpc.ServerStream
}
type testServiceHalfDuplexCallServer struct {
grpc.ServerStream
}
func (x *testServiceHalfDuplexCallServer) Send(m *StreamingOutputCallResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *testServiceHalfDuplexCallServer) Recv() (*StreamingOutputCallRequest, error) {
m := new(StreamingOutputCallRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
var _TestService_serviceDesc = grpc.ServiceDesc{
ServiceName: "grpc.testing.TestService",
HandlerType: (*TestServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "EmptyCall",
Handler: _TestService_EmptyCall_Handler,
},
{
MethodName: "UnaryCall",
Handler: _TestService_UnaryCall_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "StreamingOutputCall",
Handler: _TestService_StreamingOutputCall_Handler,
ServerStreams: true,
},
{
StreamName: "StreamingInputCall",
Handler: _TestService_StreamingInputCall_Handler,
ClientStreams: true,
},
{
StreamName: "FullDuplexCall",
Handler: _TestService_FullDuplexCall_Handler,
ServerStreams: true,
ClientStreams: true,
},
{
StreamName: "HalfDuplexCall",
Handler: _TestService_HalfDuplexCall_Handler,
ServerStreams: true,
ClientStreams: true,
},
},
Metadata: "grpc_testing/test.proto",
}
func init() { proto.RegisterFile("grpc_testing/test.proto", fileDescriptor_test_c9f6c5af4267cb88) }
var fileDescriptor_test_c9f6c5af4267cb88 = []byte{
// 587 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xdb, 0x6e, 0xd3, 0x40,
0x10, 0x65, 0xdb, 0xf4, 0x36, 0x49, 0xad, 0x68, 0xab, 0xaa, 0xae, 0x8b, 0x84, 0x65, 0x1e, 0x30,
0x48, 0xa4, 0x28, 0x08, 0x1e, 0x41, 0xa5, 0x17, 0x51, 0x29, 0x4d, 0x82, 0x9d, 0x3c, 0x47, 0xdb,
0x64, 0x6b, 0x2c, 0x39, 0xf6, 0xb2, 0x5e, 0x57, 0xa4, 0x0f, 0xfc, 0x18, 0x3f, 0xc3, 0x47, 0xf0,
0x01, 0x68, 0xd7, 0x76, 0xe2, 0x24, 0xae, 0x48, 0x41, 0xf0, 0x14, 0x7b, 0xe6, 0xcc, 0x99, 0x73,
0x3c, 0xb3, 0x1b, 0x38, 0xf0, 0x38, 0x1b, 0x0e, 0x04, 0x8d, 0x85, 0x1f, 0x7a, 0xc7, 0xf2, 0xb7,
0xc1, 0x78, 0x24, 0x22, 0x5c, 0x93, 0x89, 0x46, 0x96, 0xb0, 0xb6, 0x60, 0xe3, 0x7c, 0xcc, 0xc4,
0xc4, 0x6a, 0xc1, 0x56, 0x97, 0x4c, 0x82, 0x88, 0x8c, 0xf0, 0x4b, 0xa8, 0x88, 0x09, 0xa3, 0x3a,
0x32, 0x91, 0xad, 0x35, 0x0f, 0x1b, 0xc5, 0x82, 0x46, 0x06, 0xea, 0x4d, 0x18, 0x75, 0x14, 0x0c,
0x63, 0xa8, 0x5c, 0x47, 0xa3, 0x89, 0xbe, 0x66, 0x22, 0xbb, 0xe6, 0xa8, 0x67, 0xeb, 0x27, 0x82,
0x5d, 0xd7, 0x1f, 0xb3, 0x80, 0x3a, 0xf4, 0x4b, 0x42, 0x63, 0x81, 0xdf, 0xc1, 0x2e, 0xa7, 0x31,
0x8b, 0xc2, 0x98, 0x0e, 0x56, 0x63, 0xaf, 0xe5, 0x78, 0xf9, 0x86, 0x9f, 0x16, 0xea, 0x63, 0xff,
0x8e, 0xaa, 0x76, 0x1b, 0x33, 0x90, 0xeb, 0xdf, 0x51, 0x7c, 0x0c, 0x5b, 0x2c, 0x65, 0xd0, 0xd7,
0x4d, 0x64, 0x57, 0x9b, 0xfb, 0xa5, 0xf4, 0x4e, 0x8e, 0x92, 0xac, 0x37, 0x7e, 0x10, 0x0c, 0x92,
0x98, 0xf2, 0x90, 0x8c, 0xa9, 0x5e, 0x31, 0x91, 0xbd, 0xed, 0xd4, 0x64, 0xb0, 0x9f, 0xc5, 0xb0,
0x0d, 0x75, 0x05, 0x8a, 0x48, 0x22, 0x3e, 0x0f, 0xe2, 0x61, 0xc4, 0xa8, 0xbe, 0xa1, 0x70, 0x9a,
0x8c, 0x77, 0x64, 0xd8, 0x95, 0x51, 0xeb, 0x1b, 0x68, 0xb9, 0xeb, 0x54, 0x55, 0x51, 0x11, 0x5a,
0x49, 0x91, 0x01, 0xdb, 0x53, 0x31, 0xd2, 0xe2, 0x8e, 0x33, 0x7d, 0xc7, 0x4f, 0xa0, 0x5a, 0xd4,
0xb0, 0xae, 0xd2, 0x10, 0xcd, 0xfa, 0xb7, 0xe0, 0xd0, 0x15, 0x9c, 0x92, 0xb1, 0x1f, 0x7a, 0x97,
0x21, 0x4b, 0xc4, 0x29, 0x09, 0x82, 0x7c, 0x02, 0x0f, 0x95, 0x62, 0xf5, 0xc0, 0x28, 0x63, 0xcb,
0x9c, 0xbd, 0x85, 0x03, 0xe2, 0x79, 0x9c, 0x7a, 0x44, 0xd0, 0xd1, 0x20, 0xab, 0x49, 0x47, 0x83,
0xd4, 0x68, 0xf6, 0x67, 0xe9, 0x8c, 0x5a, 0xce, 0xc8, 0xba, 0x04, 0x9c, 0x73, 0x74, 0x09, 0x27,
0x63, 0x2a, 0x28, 0x8f, 0xe5, 0x12, 0x15, 0x4a, 0xd5, 0xb3, 0xb4, 0xeb, 0x87, 0x82, 0xf2, 0x5b,
0x22, 0x07, 0x94, 0x0d, 0x1c, 0xf2, 0x50, 0x3f, 0xb6, 0x7e, 0xa0, 0x82, 0xc2, 0x4e, 0x22, 0x16,
0x0c, 0xff, 0xed, 0xca, 0x7d, 0x82, 0xbd, 0x69, 0x3d, 0x9b, 0x4a, 0xd5, 0xd7, 0xcc, 0x75, 0xbb,
0xda, 0x34, 0xe7, 0x59, 0x96, 0x2d, 0x39, 0x98, 0x2f, 0xdb, 0x7c, 0xe8, 0x82, 0x5a, 0x6d, 0x38,
0x2a, 0x75, 0xf8, 0x87, 0xeb, 0xf5, 0xe2, 0x3d, 0x54, 0x0b, 0x86, 0x71, 0x1d, 0x6a, 0xa7, 0x9d,
0xab, 0xae, 0x73, 0xee, 0xba, 0x27, 0x1f, 0x5a, 0xe7, 0xf5, 0x47, 0x18, 0x83, 0xd6, 0x6f, 0xcf,
0xc5, 0x10, 0x06, 0xd8, 0x74, 0x4e, 0xda, 0x67, 0x9d, 0xab, 0xfa, 0x5a, 0xf3, 0x7b, 0x05, 0xaa,
0x3d, 0x1a, 0x0b, 0x97, 0xf2, 0x5b, 0x7f, 0x48, 0xf1, 0x1b, 0xd8, 0x51, 0x17, 0x88, 0x94, 0x85,
0xf7, 0xe6, 0xbb, 0xab, 0x84, 0x51, 0x16, 0xc4, 0x17, 0xb0, 0xd3, 0x0f, 0x09, 0x4f, 0xcb, 0x8e,
0xe6, 0x11, 0x73, 0x17, 0x87, 0xf1, 0xb8, 0x3c, 0x99, 0x7d, 0x80, 0x00, 0xf6, 0x4a, 0xbe, 0x0f,
0xb6, 0x17, 0x8a, 0xee, 0x5d, 0x12, 0xe3, 0xf9, 0x0a, 0xc8, 0xb4, 0xd7, 0x2b, 0x84, 0x7d, 0xc0,
0xcb, 0x27, 0x02, 0x3f, 0xbb, 0x87, 0x62, 0xf1, 0x04, 0x1a, 0xf6, 0xef, 0x81, 0x69, 0x2b, 0x5b,
0xb6, 0xd2, 0x2e, 0x92, 0x20, 0x38, 0x4b, 0x58, 0x40, 0xbf, 0xfe, 0x33, 0x4f, 0x36, 0x52, 0xae,
0xb4, 0x8f, 0x24, 0xb8, 0xf9, 0x0f, 0xad, 0xae, 0x37, 0xd5, 0x7f, 0xd0, 0xeb, 0x5f, 0x01, 0x00,
0x00, 0xff, 0xff, 0x07, 0xc7, 0x76, 0x69, 0x9e, 0x06, 0x00, 0x00,
}

View File

@@ -0,0 +1,154 @@
// Copyright 2017 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// An integration test service that covers all the method signature permutations
// of unary/streaming requests/responses.
syntax = "proto3";
package grpc.testing;
message Empty {}
// The type of payload that should be returned.
enum PayloadType {
// Compressable text format.
COMPRESSABLE = 0;
// Uncompressable binary format.
UNCOMPRESSABLE = 1;
// Randomly chosen from all other formats defined in this enum.
RANDOM = 2;
}
// A block of data, to simply increase gRPC message size.
message Payload {
// The type of data in body.
PayloadType type = 1;
// Primary contents of payload.
bytes body = 2;
}
// Unary request.
message SimpleRequest {
// Desired payload type in the response from the server.
// If response_type is RANDOM, server randomly chooses one from other formats.
PayloadType response_type = 1;
// Desired payload size in the response from the server.
// If response_type is COMPRESSABLE, this denotes the size before compression.
int32 response_size = 2;
// Optional input payload sent along with the request.
Payload payload = 3;
// Whether SimpleResponse should include username.
bool fill_username = 4;
// Whether SimpleResponse should include OAuth scope.
bool fill_oauth_scope = 5;
}
// Unary response, as configured by the request.
message SimpleResponse {
// Payload to increase message size.
Payload payload = 1;
// The user the request came from, for verifying authentication was
// successful when the client expected it.
string username = 2;
// OAuth scope.
string oauth_scope = 3;
}
// Client-streaming request.
message StreamingInputCallRequest {
// Optional input payload sent along with the request.
Payload payload = 1;
// Not expecting any payload from the response.
}
// Client-streaming response.
message StreamingInputCallResponse {
// Aggregated size of payloads received from the client.
int32 aggregated_payload_size = 1;
}
// Configuration for a particular response.
message ResponseParameters {
// Desired payload sizes in responses from the server.
// If response_type is COMPRESSABLE, this denotes the size before compression.
int32 size = 1;
// Desired interval between consecutive responses in the response stream in
// microseconds.
int32 interval_us = 2;
}
// Server-streaming request.
message StreamingOutputCallRequest {
// Desired payload type in the response from the server.
// If response_type is RANDOM, the payload from each response in the stream
// might be of different types. This is to simulate a mixed type of payload
// stream.
PayloadType response_type = 1;
// Configuration for each expected response message.
repeated ResponseParameters response_parameters = 2;
// Optional input payload sent along with the request.
Payload payload = 3;
}
// Server-streaming response, as configured by the request and parameters.
message StreamingOutputCallResponse {
// Payload to increase response size.
Payload payload = 1;
}
// A simple service to test the various types of RPCs and experiment with
// performance with various types of payload.
service TestService {
// One empty request followed by one empty response.
rpc EmptyCall(Empty) returns (Empty);
// One request followed by one response.
// The server returns the client payload as-is.
rpc UnaryCall(SimpleRequest) returns (SimpleResponse);
// One request followed by a sequence of responses (streamed download).
// The server returns the payload with client desired type and sizes.
rpc StreamingOutputCall(StreamingOutputCallRequest)
returns (stream StreamingOutputCallResponse);
// A sequence of requests followed by one response (streamed upload).
// The server returns the aggregated size of client payload as the result.
rpc StreamingInputCall(stream StreamingInputCallRequest)
returns (StreamingInputCallResponse);
// A sequence of requests with each request served by the server immediately.
// As one request could lead to multiple responses, this interface
// demonstrates the idea of full duplexing.
rpc FullDuplexCall(stream StreamingOutputCallRequest)
returns (stream StreamingOutputCallResponse);
// A sequence of requests followed by a sequence of responses.
// The server buffers all the client requests and then serves them in order. A
// stream of responses are returned to the client when the server starts with
// first request.
rpc HalfDuplexCall(stream StreamingOutputCallRequest)
returns (stream StreamingOutputCallResponse);
}

995
vendor/google.golang.org/grpc/test/healthcheck_test.go generated vendored Normal file
View File

@@ -0,0 +1,995 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package test
import (
"context"
"errors"
"fmt"
"net"
"sync"
"testing"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/connectivity"
_ "google.golang.org/grpc/health"
healthgrpc "google.golang.org/grpc/health/grpc_health_v1"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/internal"
"google.golang.org/grpc/internal/channelz"
"google.golang.org/grpc/internal/leakcheck"
"google.golang.org/grpc/resolver"
"google.golang.org/grpc/resolver/manual"
"google.golang.org/grpc/status"
testpb "google.golang.org/grpc/test/grpc_testing"
)
var testHealthCheckFunc = internal.HealthCheckFunc
func replaceHealthCheckFunc(f func(context.Context, func() (interface{}, error), func(bool), string) error) func() {
oldHcFunc := internal.HealthCheckFunc
internal.HealthCheckFunc = f
return func() {
internal.HealthCheckFunc = oldHcFunc
}
}
func newTestHealthServer() *testHealthServer {
return newTestHealthServerWithWatchFunc(defaultWatchFunc)
}
func newTestHealthServerWithWatchFunc(f func(s *testHealthServer, in *healthpb.HealthCheckRequest, stream healthgrpc.Health_WatchServer) error) *testHealthServer {
return &testHealthServer{
watchFunc: f,
update: make(chan struct{}, 1),
status: make(map[string]healthpb.HealthCheckResponse_ServingStatus),
}
}
// defaultWatchFunc will send a HealthCheckResponse to the client whenever SetServingStatus is called.
func defaultWatchFunc(s *testHealthServer, in *healthpb.HealthCheckRequest, stream healthgrpc.Health_WatchServer) error {
if in.Service != "foo" {
return status.Error(codes.FailedPrecondition,
"the defaultWatchFunc only handles request with service name to be \"foo\"")
}
var done bool
for {
select {
case <-stream.Context().Done():
done = true
case <-s.update:
}
if done {
break
}
s.mu.Lock()
resp := &healthpb.HealthCheckResponse{
Status: s.status[in.Service],
}
s.mu.Unlock()
stream.SendMsg(resp)
}
return nil
}
type testHealthServer struct {
watchFunc func(s *testHealthServer, in *healthpb.HealthCheckRequest, stream healthgrpc.Health_WatchServer) error
mu sync.Mutex
status map[string]healthpb.HealthCheckResponse_ServingStatus
update chan struct{}
}
func (s *testHealthServer) Check(ctx context.Context, in *healthpb.HealthCheckRequest) (*healthpb.HealthCheckResponse, error) {
return &healthpb.HealthCheckResponse{
Status: healthpb.HealthCheckResponse_SERVING,
}, nil
}
func (s *testHealthServer) Watch(in *healthpb.HealthCheckRequest, stream healthgrpc.Health_WatchServer) error {
return s.watchFunc(s, in, stream)
}
// SetServingStatus is called when need to reset the serving status of a service
// or insert a new service entry into the statusMap.
func (s *testHealthServer) SetServingStatus(service string, status healthpb.HealthCheckResponse_ServingStatus) {
s.mu.Lock()
s.status[service] = status
select {
case <-s.update:
default:
}
s.update <- struct{}{}
s.mu.Unlock()
}
func TestHealthCheckWatchStateChange(t *testing.T) {
defer leakcheck.Check(t)
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err: %v", err)
}
ts := newTestHealthServer()
healthgrpc.RegisterHealthServer(s, ts)
go s.Serve(lis)
defer s.Stop()
// The table below shows the expected series of addrConn connectivity transitions when server
// updates its health status. As there's only one addrConn corresponds with the ClientConn in this
// test, we use ClientConn's connectivity state as the addrConn connectivity state.
//+------------------------------+-------------------------------------------+
//| Health Check Returned Status | Expected addrConn Connectivity Transition |
//+------------------------------+-------------------------------------------+
//| NOT_SERVING | ->TRANSIENT FAILURE |
//| SERVING | ->READY |
//| SERVICE_UNKNOWN | ->TRANSIENT FAILURE |
//| SERVING | ->READY |
//| UNKNOWN | ->TRANSIENT FAILURE |
//+------------------------------+-------------------------------------------+
ts.SetServingStatus("foo", healthpb.HealthCheckResponse_NOT_SERVING)
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
defer cc.Close()
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "foo"
}
}`)
r.NewAddress([]resolver.Address{{Addr: lis.Addr().String()}})
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if ok := cc.WaitForStateChange(ctx, connectivity.Idle); !ok {
t.Fatal("ClientConn is still in IDLE state when the context times out.")
}
if ok := cc.WaitForStateChange(ctx, connectivity.Connecting); !ok {
t.Fatal("ClientConn is still in CONNECTING state when the context times out.")
}
if s := cc.GetState(); s != connectivity.TransientFailure {
t.Fatalf("ClientConn is in %v state, want TRANSIENT FAILURE", s)
}
ts.SetServingStatus("foo", healthpb.HealthCheckResponse_SERVING)
if ok := cc.WaitForStateChange(ctx, connectivity.TransientFailure); !ok {
t.Fatal("ClientConn is still in TRANSIENT FAILURE state when the context times out.")
}
if s := cc.GetState(); s != connectivity.Ready {
t.Fatalf("ClientConn is in %v state, want READY", s)
}
ts.SetServingStatus("foo", healthpb.HealthCheckResponse_SERVICE_UNKNOWN)
if ok := cc.WaitForStateChange(ctx, connectivity.Ready); !ok {
t.Fatal("ClientConn is still in READY state when the context times out.")
}
if s := cc.GetState(); s != connectivity.TransientFailure {
t.Fatalf("ClientConn is in %v state, want TRANSIENT FAILURE", s)
}
ts.SetServingStatus("foo", healthpb.HealthCheckResponse_SERVING)
if ok := cc.WaitForStateChange(ctx, connectivity.TransientFailure); !ok {
t.Fatal("ClientConn is still in TRANSIENT FAILURE state when the context times out.")
}
if s := cc.GetState(); s != connectivity.Ready {
t.Fatalf("ClientConn is in %v state, want READY", s)
}
ts.SetServingStatus("foo", healthpb.HealthCheckResponse_UNKNOWN)
if ok := cc.WaitForStateChange(ctx, connectivity.Ready); !ok {
t.Fatal("ClientConn is still in READY state when the context times out.")
}
if s := cc.GetState(); s != connectivity.TransientFailure {
t.Fatalf("ClientConn is in %v state, want TRANSIENT FAILURE", s)
}
}
// If Watch returns Unimplemented, then the ClientConn should go into READY state.
func TestHealthCheckHealthServerNotRegistered(t *testing.T) {
defer leakcheck.Check(t)
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err: %v", err)
}
go s.Serve(lis)
defer s.Stop()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
defer cc.Close()
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "foo"
}
}`)
r.NewAddress([]resolver.Address{{Addr: lis.Addr().String()}})
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if ok := cc.WaitForStateChange(ctx, connectivity.Idle); !ok {
t.Fatal("ClientConn is still in IDLE state when the context times out.")
}
if ok := cc.WaitForStateChange(ctx, connectivity.Connecting); !ok {
t.Fatal("ClientConn is still in CONNECTING state when the context times out.")
}
if s := cc.GetState(); s != connectivity.Ready {
t.Fatalf("ClientConn is in %v state, want READY", s)
}
}
// In the case of a goaway received, the health check stream should be terminated and health check
// function should exit.
func TestHealthCheckWithGoAway(t *testing.T) {
defer leakcheck.Check(t)
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err: %v", err)
}
ts := newTestHealthServer()
healthgrpc.RegisterHealthServer(s, ts)
testpb.RegisterTestServiceServer(s, &testServer{})
go s.Serve(lis)
defer s.Stop()
ts.SetServingStatus("foo", healthpb.HealthCheckResponse_SERVING)
hcExitChan := make(chan struct{})
testHealthCheckFuncWrapper := func(ctx context.Context, newStream func() (interface{}, error), update func(bool), service string) error {
err := testHealthCheckFunc(ctx, newStream, update, service)
close(hcExitChan)
return err
}
replace := replaceHealthCheckFunc(testHealthCheckFuncWrapper)
defer replace()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
defer cc.Close()
tc := testpb.NewTestServiceClient(cc)
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "foo"
}
}`)
r.NewAddress([]resolver.Address{{Addr: lis.Addr().String()}})
// make some rpcs to make sure connection is working.
if err := verifyResultWithDelay(func() (bool, error) {
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
return false, fmt.Errorf("TestService/EmptyCall(_, _) = _, %v, want _, <nil>", err)
}
return true, nil
}); err != nil {
t.Fatal(err)
}
// the stream rpc will persist through goaway event.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
stream, err := tc.FullDuplexCall(ctx, grpc.FailFast(false))
if err != nil {
t.Fatalf("%v.FullDuplexCall(_) = _, %v, want <nil>", tc, err)
}
respParam := []*testpb.ResponseParameters{{Size: 1}}
payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, int32(1))
if err != nil {
t.Fatal(err)
}
req := &testpb.StreamingOutputCallRequest{
ResponseParameters: respParam,
Payload: payload,
}
if err := stream.Send(req); err != nil {
t.Fatalf("%v.Send(_) = %v, want <nil>", stream, err)
}
if _, err := stream.Recv(); err != nil {
t.Fatalf("%v.Recv() = _, %v, want _, <nil>", stream, err)
}
select {
case <-hcExitChan:
t.Fatal("Health check function has exited, which is not expected.")
default:
}
// server sends GoAway
go s.GracefulStop()
select {
case <-hcExitChan:
case <-time.After(5 * time.Second):
t.Fatal("Health check function has not exited after 5s.")
}
// The existing RPC should be still good to proceed.
if err := stream.Send(req); err != nil {
t.Fatalf("%v.Send(_) = %v, want <nil>", stream, err)
}
if _, err := stream.Recv(); err != nil {
t.Fatalf("%v.Recv() = _, %v, want _, <nil>", stream, err)
}
}
func TestHealthCheckWithConnClose(t *testing.T) {
defer leakcheck.Check(t)
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err: %v", err)
}
ts := newTestHealthServer()
healthgrpc.RegisterHealthServer(s, ts)
testpb.RegisterTestServiceServer(s, &testServer{})
go s.Serve(lis)
defer s.Stop()
ts.SetServingStatus("foo", healthpb.HealthCheckResponse_SERVING)
hcExitChan := make(chan struct{})
testHealthCheckFuncWrapper := func(ctx context.Context, newStream func() (interface{}, error), update func(bool), service string) error {
err := testHealthCheckFunc(ctx, newStream, update, service)
close(hcExitChan)
return err
}
replace := replaceHealthCheckFunc(testHealthCheckFuncWrapper)
defer replace()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
defer cc.Close()
tc := testpb.NewTestServiceClient(cc)
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "foo"
}
}`)
r.NewAddress([]resolver.Address{{Addr: lis.Addr().String()}})
// make some rpcs to make sure connection is working.
if err := verifyResultWithDelay(func() (bool, error) {
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
return false, fmt.Errorf("TestService/EmptyCall(_, _) = _, %v, want _, <nil>", err)
}
return true, nil
}); err != nil {
t.Fatal(err)
}
select {
case <-hcExitChan:
t.Fatal("Health check function has exited, which is not expected.")
default:
}
// server closes the connection
s.Stop()
select {
case <-hcExitChan:
case <-time.After(5 * time.Second):
t.Fatal("Health check function has not exited after 5s.")
}
}
// addrConn drain happens when addrConn gets torn down due to its address being no longer in the
// address list returned by the resolver.
func TestHealthCheckWithAddrConnDrain(t *testing.T) {
defer leakcheck.Check(t)
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err: %v", err)
}
ts := newTestHealthServer()
healthgrpc.RegisterHealthServer(s, ts)
testpb.RegisterTestServiceServer(s, &testServer{})
go s.Serve(lis)
defer s.Stop()
ts.SetServingStatus("foo", healthpb.HealthCheckResponse_SERVING)
hcExitChan := make(chan struct{})
testHealthCheckFuncWrapper := func(ctx context.Context, newStream func() (interface{}, error), update func(bool), service string) error {
err := testHealthCheckFunc(ctx, newStream, update, service)
close(hcExitChan)
return err
}
replace := replaceHealthCheckFunc(testHealthCheckFuncWrapper)
defer replace()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
defer cc.Close()
tc := testpb.NewTestServiceClient(cc)
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "foo"
}
}`)
r.NewAddress([]resolver.Address{{Addr: lis.Addr().String()}})
// make some rpcs to make sure connection is working.
if err := verifyResultWithDelay(func() (bool, error) {
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
return false, fmt.Errorf("TestService/EmptyCall(_, _) = _, %v, want _, <nil>", err)
}
return true, nil
}); err != nil {
t.Fatal(err)
}
// the stream rpc will persist through goaway event.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
stream, err := tc.FullDuplexCall(ctx, grpc.FailFast(false))
if err != nil {
t.Fatalf("%v.FullDuplexCall(_) = _, %v, want <nil>", tc, err)
}
respParam := []*testpb.ResponseParameters{{Size: 1}}
payload, err := newPayload(testpb.PayloadType_COMPRESSABLE, int32(1))
if err != nil {
t.Fatal(err)
}
req := &testpb.StreamingOutputCallRequest{
ResponseParameters: respParam,
Payload: payload,
}
if err := stream.Send(req); err != nil {
t.Fatalf("%v.Send(_) = %v, want <nil>", stream, err)
}
if _, err := stream.Recv(); err != nil {
t.Fatalf("%v.Recv() = _, %v, want _, <nil>", stream, err)
}
select {
case <-hcExitChan:
t.Fatal("Health check function has exited, which is not expected.")
default:
}
// trigger teardown of the ac
r.NewAddress([]resolver.Address{})
select {
case <-hcExitChan:
case <-time.After(5 * time.Second):
t.Fatal("Health check function has not exited after 5s.")
}
// The existing RPC should be still good to proceed.
if err := stream.Send(req); err != nil {
t.Fatalf("%v.Send(_) = %v, want <nil>", stream, err)
}
if _, err := stream.Recv(); err != nil {
t.Fatalf("%v.Recv() = _, %v, want _, <nil>", stream, err)
}
}
// ClientConn close will lead to its addrConns being torn down.
func TestHealthCheckWithClientConnClose(t *testing.T) {
defer leakcheck.Check(t)
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err: %v", err)
}
ts := newTestHealthServer()
healthgrpc.RegisterHealthServer(s, ts)
testpb.RegisterTestServiceServer(s, &testServer{})
go s.Serve(lis)
defer s.Stop()
ts.SetServingStatus("foo", healthpb.HealthCheckResponse_SERVING)
hcExitChan := make(chan struct{})
testHealthCheckFuncWrapper := func(ctx context.Context, newStream func() (interface{}, error), update func(bool), service string) error {
err := testHealthCheckFunc(ctx, newStream, update, service)
close(hcExitChan)
return err
}
replace := replaceHealthCheckFunc(testHealthCheckFuncWrapper)
defer replace()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
defer cc.Close()
tc := testpb.NewTestServiceClient(cc)
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "foo"
}
}`)
r.NewAddress([]resolver.Address{{Addr: lis.Addr().String()}})
// make some rpcs to make sure connection is working.
if err := verifyResultWithDelay(func() (bool, error) {
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
return false, fmt.Errorf("TestService/EmptyCall(_, _) = _, %v, want _, <nil>", err)
}
return true, nil
}); err != nil {
t.Fatal(err)
}
select {
case <-hcExitChan:
t.Fatal("Health check function has exited, which is not expected.")
default:
}
// trigger addrConn teardown
cc.Close()
select {
case <-hcExitChan:
case <-time.After(5 * time.Second):
t.Fatal("Health check function has not exited after 5s.")
}
}
// This test is to test the logic in the createTransport after the health check function returns which
// closes the skipReset channel(since it has not been closed inside health check func) to unblock
// onGoAway/onClose goroutine.
func TestHealthCheckWithoutReportHealthCalledAddrConnShutDown(t *testing.T) {
defer leakcheck.Check(t)
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err %v", err)
}
ts := newTestHealthServerWithWatchFunc(func(s *testHealthServer, in *healthpb.HealthCheckRequest, stream healthgrpc.Health_WatchServer) error {
if in.Service != "delay" {
return status.Error(codes.FailedPrecondition,
"this special Watch function only handles request with service name to be \"delay\"")
}
// Do nothing to mock a delay of health check response from server side.
// This case is to help with the test that covers the condition that reportHealth is not
// called inside HealthCheckFunc before the func returns.
select {
case <-stream.Context().Done():
case <-time.After(5 * time.Second):
}
return nil
})
healthgrpc.RegisterHealthServer(s, ts)
testpb.RegisterTestServiceServer(s, &testServer{})
go s.Serve(lis)
defer s.Stop()
ts.SetServingStatus("delay", healthpb.HealthCheckResponse_SERVING)
hcEnterChan := make(chan struct{})
hcExitChan := make(chan struct{})
testHealthCheckFuncWrapper := func(ctx context.Context, newStream func() (interface{}, error), update func(bool), service string) error {
close(hcEnterChan)
err := testHealthCheckFunc(ctx, newStream, update, service)
close(hcExitChan)
return err
}
replace := replaceHealthCheckFunc(testHealthCheckFuncWrapper)
defer replace()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
defer cc.Close()
// The serviceName "delay" is specially handled at server side, where response will not be sent
// back to client immediately upon receiving the request (client should receive no response until
// test ends).
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "delay"
}
}`)
r.NewAddress([]resolver.Address{{Addr: lis.Addr().String()}})
select {
case <-hcExitChan:
t.Fatal("Health check function has exited, which is not expected.")
default:
}
select {
case <-hcEnterChan:
case <-time.After(5 * time.Second):
t.Fatal("Health check function has not been invoked after 5s.")
}
// trigger teardown of the ac, ac in SHUTDOWN state
r.NewAddress([]resolver.Address{})
// The health check func should exit without calling the reportHealth func, as server hasn't sent
// any response.
select {
case <-hcExitChan:
case <-time.After(5 * time.Second):
t.Fatal("Health check function has not exited after 5s.")
}
// The deferred leakcheck will check whether there's leaked goroutine, which is an indication
// whether we closes the skipReset channel to unblock onGoAway/onClose goroutine.
}
// This test is to test the logic in the createTransport after the health check function returns which
// closes the allowedToReset channel(since it has not been closed inside health check func) to unblock
// onGoAway/onClose goroutine.
func TestHealthCheckWithoutReportHealthCalled(t *testing.T) {
defer leakcheck.Check(t)
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err: %v", err)
}
ts := newTestHealthServerWithWatchFunc(func(s *testHealthServer, in *healthpb.HealthCheckRequest, stream healthgrpc.Health_WatchServer) error {
if in.Service != "delay" {
return status.Error(codes.FailedPrecondition,
"this special Watch function only handles request with service name to be \"delay\"")
}
// Do nothing to mock a delay of health check response from server side.
// This case is to help with the test that covers the condition that reportHealth is not
// called inside HealthCheckFunc before the func returns.
select {
case <-stream.Context().Done():
case <-time.After(5 * time.Second):
}
return nil
})
healthgrpc.RegisterHealthServer(s, ts)
testpb.RegisterTestServiceServer(s, &testServer{})
go s.Serve(lis)
defer s.Stop()
ts.SetServingStatus("delay", healthpb.HealthCheckResponse_SERVING)
hcEnterChan := make(chan struct{})
hcExitChan := make(chan struct{})
testHealthCheckFuncWrapper := func(ctx context.Context, newStream func() (interface{}, error), update func(bool), service string) error {
close(hcEnterChan)
err := testHealthCheckFunc(ctx, newStream, update, service)
close(hcExitChan)
return err
}
replace := replaceHealthCheckFunc(testHealthCheckFuncWrapper)
defer replace()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
defer cc.Close()
// The serviceName "delay" is specially handled at server side, where response will not be sent
// back to client immediately upon receiving the request (client should receive no response until
// test ends).
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "delay"
}
}`)
r.NewAddress([]resolver.Address{{Addr: lis.Addr().String()}})
select {
case <-hcExitChan:
t.Fatal("Health check function has exited, which is not expected.")
default:
}
select {
case <-hcEnterChan:
case <-time.After(5 * time.Second):
t.Fatal("Health check function has not been invoked after 5s.")
}
// trigger transport being closed
s.Stop()
// The health check func should exit without calling the reportHealth func, as server hasn't sent
// any response.
select {
case <-hcExitChan:
case <-time.After(5 * time.Second):
t.Fatal("Health check function has not exited after 5s.")
}
// The deferred leakcheck will check whether there's leaked goroutine, which is an indication
// whether we closes the allowedToReset channel to unblock onGoAway/onClose goroutine.
}
func testHealthCheckDisableWithDialOption(t *testing.T, addr string) {
hcEnterChan := make(chan struct{})
testHealthCheckFuncWrapper := func(ctx context.Context, newStream func() (interface{}, error), update func(bool), service string) error {
close(hcEnterChan)
return nil
}
replace := replaceHealthCheckFunc(testHealthCheckFuncWrapper)
defer replace()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"), grpc.WithDisableHealthCheck())
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
tc := testpb.NewTestServiceClient(cc)
defer cc.Close()
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "foo"
}
}`)
r.NewAddress([]resolver.Address{{Addr: addr}})
// send some rpcs to make sure transport has been created and is ready for use.
if err := verifyResultWithDelay(func() (bool, error) {
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
return false, fmt.Errorf("TestService/EmptyCall(_, _) = _, %v, want _, <nil>", err)
}
return true, nil
}); err != nil {
t.Fatal(err)
}
select {
case <-hcEnterChan:
t.Fatal("Health check function has exited, which is not expected.")
default:
}
}
func testHealthCheckDisableWithBalancer(t *testing.T, addr string) {
hcEnterChan := make(chan struct{})
testHealthCheckFuncWrapper := func(ctx context.Context, newStream func() (interface{}, error), update func(bool), service string) error {
close(hcEnterChan)
return nil
}
replace := replaceHealthCheckFunc(testHealthCheckFuncWrapper)
defer replace()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("pick_first"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
tc := testpb.NewTestServiceClient(cc)
defer cc.Close()
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "foo"
}
}`)
r.NewAddress([]resolver.Address{{Addr: addr}})
// send some rpcs to make sure transport has been created and is ready for use.
if err := verifyResultWithDelay(func() (bool, error) {
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
return false, fmt.Errorf("TestService/EmptyCall(_, _) = _, %v, want _, <nil>", err)
}
return true, nil
}); err != nil {
t.Fatal(err)
}
select {
case <-hcEnterChan:
t.Fatal("Health check function has started, which is not expected.")
default:
}
}
func testHealthCheckDisableWithServiceConfig(t *testing.T, addr string) {
hcEnterChan := make(chan struct{})
testHealthCheckFuncWrapper := func(ctx context.Context, newStream func() (interface{}, error), update func(bool), service string) error {
close(hcEnterChan)
return nil
}
replace := replaceHealthCheckFunc(testHealthCheckFuncWrapper)
defer replace()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
tc := testpb.NewTestServiceClient(cc)
defer cc.Close()
r.NewAddress([]resolver.Address{{Addr: addr}})
// send some rpcs to make sure transport has been created and is ready for use.
if err := verifyResultWithDelay(func() (bool, error) {
if _, err := tc.EmptyCall(context.Background(), &testpb.Empty{}); err != nil {
return false, fmt.Errorf("TestService/EmptyCall(_, _) = _, %v, want _, <nil>", err)
}
return true, nil
}); err != nil {
t.Fatal(err)
}
select {
case <-hcEnterChan:
t.Fatal("Health check function has started, which is not expected.")
default:
}
}
func TestHealthCheckDisable(t *testing.T) {
defer leakcheck.Check(t)
// set up server side
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err: %v", err)
}
ts := newTestHealthServer()
healthgrpc.RegisterHealthServer(s, ts)
testpb.RegisterTestServiceServer(s, &testServer{})
go s.Serve(lis)
defer s.Stop()
ts.SetServingStatus("foo", healthpb.HealthCheckResponse_SERVING)
// test client side disabling configuration.
testHealthCheckDisableWithDialOption(t, lis.Addr().String())
testHealthCheckDisableWithBalancer(t, lis.Addr().String())
testHealthCheckDisableWithServiceConfig(t, lis.Addr().String())
}
func TestHealthCheckChannelzCountingCallSuccess(t *testing.T) {
defer leakcheck.Check(t)
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err: %v", err)
}
ts := newTestHealthServerWithWatchFunc(func(s *testHealthServer, in *healthpb.HealthCheckRequest, stream healthgrpc.Health_WatchServer) error {
if in.Service != "channelzSuccess" {
return status.Error(codes.FailedPrecondition,
"this special Watch function only handles request with service name to be \"channelzSuccess\"")
}
return status.Error(codes.OK, "fake success")
})
healthgrpc.RegisterHealthServer(s, ts)
testpb.RegisterTestServiceServer(s, &testServer{})
go s.Serve(lis)
defer s.Stop()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
defer cc.Close()
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "channelzSuccess"
}
}`)
r.NewAddress([]resolver.Address{{Addr: lis.Addr().String()}})
if err := verifyResultWithDelay(func() (bool, error) {
cm, _ := channelz.GetTopChannels(0)
if len(cm) == 0 {
return false, errors.New("channelz.GetTopChannels return 0 top channel")
}
if len(cm[0].SubChans) == 0 {
return false, errors.New("there is 0 subchannel")
}
var id int64
for k := range cm[0].SubChans {
id = k
break
}
scm := channelz.GetSubChannel(id)
if scm == nil || scm.ChannelData == nil {
return false, errors.New("nil subchannel metric or nil subchannel metric ChannelData returned")
}
// exponential backoff retry may result in more than one health check call.
if scm.ChannelData.CallsStarted > 0 && scm.ChannelData.CallsSucceeded > 0 && scm.ChannelData.CallsFailed == 0 {
return true, nil
}
return false, fmt.Errorf("got %d CallsStarted, %d CallsSucceeded, want >0 >0", scm.ChannelData.CallsStarted, scm.ChannelData.CallsSucceeded)
}); err != nil {
t.Fatal(err)
}
}
func TestHealthCheckChannelzCountingCallFailure(t *testing.T) {
defer leakcheck.Check(t)
s := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("failed to listen due to err: %v", err)
}
ts := newTestHealthServerWithWatchFunc(func(s *testHealthServer, in *healthpb.HealthCheckRequest, stream healthgrpc.Health_WatchServer) error {
if in.Service != "channelzFailure" {
return status.Error(codes.FailedPrecondition,
"this special Watch function only handles request with service name to be \"channelzFailure\"")
}
return status.Error(codes.Internal, "fake failure")
})
healthgrpc.RegisterHealthServer(s, ts)
testpb.RegisterTestServiceServer(s, &testServer{})
go s.Serve(lis)
defer s.Stop()
r, rcleanup := manual.GenerateAndRegisterManualResolver()
defer rcleanup()
cc, err := grpc.Dial(r.Scheme()+":///test.server", grpc.WithInsecure(), grpc.WithBalancerName("round_robin"))
if err != nil {
t.Fatalf("dial failed due to err: %v", err)
}
defer cc.Close()
r.NewServiceConfig(`{
"healthCheckConfig": {
"serviceName": "channelzFailure"
}
}`)
r.NewAddress([]resolver.Address{{Addr: lis.Addr().String()}})
if err := verifyResultWithDelay(func() (bool, error) {
cm, _ := channelz.GetTopChannels(0)
if len(cm) == 0 {
return false, errors.New("channelz.GetTopChannels return 0 top channel")
}
if len(cm[0].SubChans) == 0 {
return false, errors.New("there is 0 subchannel")
}
var id int64
for k := range cm[0].SubChans {
id = k
break
}
scm := channelz.GetSubChannel(id)
if scm == nil || scm.ChannelData == nil {
return false, errors.New("nil subchannel metric or nil subchannel metric ChannelData returned")
}
// exponential backoff retry may result in more than one health check call.
if scm.ChannelData.CallsStarted > 0 && scm.ChannelData.CallsFailed > 0 && scm.ChannelData.CallsSucceeded == 0 {
return true, nil
}
return false, fmt.Errorf("got %d CallsStarted, %d CallsFailed, want >0, >0", scm.ChannelData.CallsStarted, scm.ChannelData.CallsFailed)
}); err != nil {
t.Fatal(err)
}
}

View File

24
vendor/google.golang.org/grpc/test/race.go generated vendored Normal file
View File

@@ -0,0 +1,24 @@
// +build race
/*
* Copyright 2016 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package test
func init() {
raceMode = true
}

345
vendor/google.golang.org/grpc/test/rawConnWrapper.go generated vendored Normal file
View File

@@ -0,0 +1,345 @@
/*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package test
import (
"bytes"
"fmt"
"io"
"net"
"strings"
"sync"
"time"
"golang.org/x/net/http2"
"golang.org/x/net/http2/hpack"
)
type listenerWrapper struct {
net.Listener
mu sync.Mutex
rcw *rawConnWrapper
}
func listenWithConnControl(network, address string) (net.Listener, error) {
l, err := net.Listen(network, address)
if err != nil {
return nil, err
}
return &listenerWrapper{Listener: l}, nil
}
// Accept blocks until Dial is called, then returns a net.Conn for the server
// half of the connection.
func (l *listenerWrapper) Accept() (net.Conn, error) {
c, err := l.Listener.Accept()
if err != nil {
return nil, err
}
l.mu.Lock()
l.rcw = newRawConnWrapperFromConn(c)
l.mu.Unlock()
return c, nil
}
func (l *listenerWrapper) getLastConn() *rawConnWrapper {
l.mu.Lock()
defer l.mu.Unlock()
return l.rcw
}
type dialerWrapper struct {
c net.Conn
rcw *rawConnWrapper
}
func (d *dialerWrapper) dialer(target string, t time.Duration) (net.Conn, error) {
c, err := net.DialTimeout("tcp", target, t)
d.c = c
d.rcw = newRawConnWrapperFromConn(c)
return c, err
}
func (d *dialerWrapper) getRawConnWrapper() *rawConnWrapper {
return d.rcw
}
type rawConnWrapper struct {
cc io.ReadWriteCloser
fr *http2.Framer
// writing headers:
headerBuf bytes.Buffer
hpackEnc *hpack.Encoder
// reading frames:
frc chan http2.Frame
frErrc chan error
readTimer *time.Timer
}
func newRawConnWrapperFromConn(cc io.ReadWriteCloser) *rawConnWrapper {
rcw := &rawConnWrapper{
cc: cc,
frc: make(chan http2.Frame, 1),
frErrc: make(chan error, 1),
}
rcw.hpackEnc = hpack.NewEncoder(&rcw.headerBuf)
rcw.fr = http2.NewFramer(cc, cc)
rcw.fr.ReadMetaHeaders = hpack.NewDecoder(4096 /*initialHeaderTableSize*/, nil)
return rcw
}
func (rcw *rawConnWrapper) Close() error {
return rcw.cc.Close()
}
func (rcw *rawConnWrapper) readFrame() (http2.Frame, error) {
go func() {
fr, err := rcw.fr.ReadFrame()
if err != nil {
rcw.frErrc <- err
} else {
rcw.frc <- fr
}
}()
t := time.NewTimer(2 * time.Second)
defer t.Stop()
select {
case f := <-rcw.frc:
return f, nil
case err := <-rcw.frErrc:
return nil, err
case <-t.C:
return nil, fmt.Errorf("timeout waiting for frame")
}
}
// greet initiates the client's HTTP/2 connection into a state where
// frames may be sent.
func (rcw *rawConnWrapper) greet() error {
rcw.writePreface()
rcw.writeInitialSettings()
rcw.wantSettings()
rcw.writeSettingsAck()
for {
f, err := rcw.readFrame()
if err != nil {
return err
}
switch f := f.(type) {
case *http2.WindowUpdateFrame:
// grpc's transport/http2_server sends this
// before the settings ack. The Go http2
// server uses a setting instead.
case *http2.SettingsFrame:
if f.IsAck() {
return nil
}
return fmt.Errorf("during greet, got non-ACK settings frame")
default:
return fmt.Errorf("during greet, unexpected frame type %T", f)
}
}
}
func (rcw *rawConnWrapper) writePreface() error {
n, err := rcw.cc.Write([]byte(http2.ClientPreface))
if err != nil {
return fmt.Errorf("error writing client preface: %v", err)
}
if n != len(http2.ClientPreface) {
return fmt.Errorf("writing client preface, wrote %d bytes; want %d", n, len(http2.ClientPreface))
}
return nil
}
func (rcw *rawConnWrapper) writeInitialSettings() error {
if err := rcw.fr.WriteSettings(); err != nil {
return fmt.Errorf("error writing initial SETTINGS frame from client to server: %v", err)
}
return nil
}
func (rcw *rawConnWrapper) writeSettingsAck() error {
if err := rcw.fr.WriteSettingsAck(); err != nil {
return fmt.Errorf("error writing ACK of server's SETTINGS: %v", err)
}
return nil
}
func (rcw *rawConnWrapper) wantSettings() (*http2.SettingsFrame, error) {
f, err := rcw.readFrame()
if err != nil {
return nil, fmt.Errorf("error while expecting a SETTINGS frame: %v", err)
}
sf, ok := f.(*http2.SettingsFrame)
if !ok {
return nil, fmt.Errorf("got a %T; want *SettingsFrame", f)
}
return sf, nil
}
func (rcw *rawConnWrapper) wantSettingsAck() error {
f, err := rcw.readFrame()
if err != nil {
return err
}
sf, ok := f.(*http2.SettingsFrame)
if !ok {
return fmt.Errorf("wanting a settings ACK, received a %T", f)
}
if !sf.IsAck() {
return fmt.Errorf("settings Frame didn't have ACK set")
}
return nil
}
// wait for any activity from the server
func (rcw *rawConnWrapper) wantAnyFrame() (http2.Frame, error) {
f, err := rcw.fr.ReadFrame()
if err != nil {
return nil, err
}
return f, nil
}
func (rcw *rawConnWrapper) encodeHeaderField(k, v string) error {
err := rcw.hpackEnc.WriteField(hpack.HeaderField{Name: k, Value: v})
if err != nil {
return fmt.Errorf("HPACK encoding error for %q/%q: %v", k, v, err)
}
return nil
}
// encodeHeader encodes headers and returns their HPACK bytes. headers
// must contain an even number of key/value pairs. There may be
// multiple pairs for keys (e.g. "cookie"). The :method, :path, and
// :scheme headers default to GET, / and https.
func (rcw *rawConnWrapper) encodeHeader(headers ...string) []byte {
if len(headers)%2 == 1 {
panic("odd number of kv args")
}
rcw.headerBuf.Reset()
if len(headers) == 0 {
// Fast path, mostly for benchmarks, so test code doesn't pollute
// profiles when we're looking to improve server allocations.
rcw.encodeHeaderField(":method", "GET")
rcw.encodeHeaderField(":path", "/")
rcw.encodeHeaderField(":scheme", "https")
return rcw.headerBuf.Bytes()
}
if len(headers) == 2 && headers[0] == ":method" {
// Another fast path for benchmarks.
rcw.encodeHeaderField(":method", headers[1])
rcw.encodeHeaderField(":path", "/")
rcw.encodeHeaderField(":scheme", "https")
return rcw.headerBuf.Bytes()
}
pseudoCount := map[string]int{}
keys := []string{":method", ":path", ":scheme"}
vals := map[string][]string{
":method": {"GET"},
":path": {"/"},
":scheme": {"https"},
}
for len(headers) > 0 {
k, v := headers[0], headers[1]
headers = headers[2:]
if _, ok := vals[k]; !ok {
keys = append(keys, k)
}
if strings.HasPrefix(k, ":") {
pseudoCount[k]++
if pseudoCount[k] == 1 {
vals[k] = []string{v}
} else {
// Allows testing of invalid headers w/ dup pseudo fields.
vals[k] = append(vals[k], v)
}
} else {
vals[k] = append(vals[k], v)
}
}
for _, k := range keys {
for _, v := range vals[k] {
rcw.encodeHeaderField(k, v)
}
}
return rcw.headerBuf.Bytes()
}
func (rcw *rawConnWrapper) writeHeadersGRPC(streamID uint32, path string) {
rcw.writeHeaders(http2.HeadersFrameParam{
StreamID: streamID,
BlockFragment: rcw.encodeHeader(
":method", "POST",
":path", path,
"content-type", "application/grpc",
"te", "trailers",
),
EndStream: false,
EndHeaders: true,
})
}
func (rcw *rawConnWrapper) writeHeaders(p http2.HeadersFrameParam) error {
if err := rcw.fr.WriteHeaders(p); err != nil {
return fmt.Errorf("error writing HEADERS: %v", err)
}
return nil
}
func (rcw *rawConnWrapper) writeData(streamID uint32, endStream bool, data []byte) error {
if err := rcw.fr.WriteData(streamID, endStream, data); err != nil {
return fmt.Errorf("error writing DATA: %v", err)
}
return nil
}
func (rcw *rawConnWrapper) writeRSTStream(streamID uint32, code http2.ErrCode) error {
if err := rcw.fr.WriteRSTStream(streamID, code); err != nil {
return fmt.Errorf("error writing RST_STREAM: %v", err)
}
return nil
}
func (rcw *rawConnWrapper) writeDataPadded(streamID uint32, endStream bool, data, padding []byte) error {
if err := rcw.fr.WriteDataPadded(streamID, endStream, data, padding); err != nil {
return fmt.Errorf("error writing DATA with padding: %v", err)
}
return nil
}
func (rcw *rawConnWrapper) writeGoAway(maxStreamID uint32, code http2.ErrCode, debugData []byte) error {
if err := rcw.fr.WriteGoAway(maxStreamID, code, debugData); err != nil {
return fmt.Errorf("error writing GoAway: %v", err)
}
return nil
}
func (rcw *rawConnWrapper) writeRawFrame(t http2.FrameType, flags http2.Flags, streamID uint32, payload []byte) error {
if err := rcw.fr.WriteRawFrame(t, flags, streamID, payload); err != nil {
return fmt.Errorf("error writing Raw Frame: %v", err)
}
return nil
}

551
vendor/google.golang.org/grpc/test/retry_test.go generated vendored Normal file
View File

@@ -0,0 +1,551 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package test
import (
"context"
"fmt"
"io"
"os"
"reflect"
"strconv"
"strings"
"testing"
"time"
"github.com/golang/protobuf/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/internal/envconfig"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
testpb "google.golang.org/grpc/test/grpc_testing"
)
func enableRetry() func() {
old := envconfig.Retry
envconfig.Retry = true
return func() { envconfig.Retry = old }
}
func TestRetryUnary(t *testing.T) {
defer enableRetry()()
i := -1
ss := &stubServer{
emptyCall: func(context.Context, *testpb.Empty) (*testpb.Empty, error) {
i++
switch i {
case 0, 2, 5:
return &testpb.Empty{}, nil
case 6, 8, 11:
return nil, status.New(codes.Internal, "non-retryable error").Err()
}
return nil, status.New(codes.AlreadyExists, "retryable error").Err()
},
}
if err := ss.Start([]grpc.ServerOption{}); err != nil {
t.Fatalf("Error starting endpoint server: %v", err)
}
defer ss.Stop()
ss.r.NewServiceConfig(`{
"methodConfig": [{
"name": [{"service": "grpc.testing.TestService"}],
"waitForReady": true,
"retryPolicy": {
"MaxAttempts": 4,
"InitialBackoff": ".01s",
"MaxBackoff": ".01s",
"BackoffMultiplier": 1.0,
"RetryableStatusCodes": [ "ALREADY_EXISTS" ]
}
}]}`)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
for {
if ctx.Err() != nil {
t.Fatalf("Timed out waiting for service config update")
}
if ss.cc.GetMethodConfig("/grpc.testing.TestService/EmptyCall").WaitForReady != nil {
break
}
time.Sleep(time.Millisecond)
}
cancel()
testCases := []struct {
code codes.Code
count int
}{
{codes.OK, 0},
{codes.OK, 2},
{codes.OK, 5},
{codes.Internal, 6},
{codes.Internal, 8},
{codes.Internal, 11},
{codes.AlreadyExists, 15},
}
for _, tc := range testCases {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
_, err := ss.client.EmptyCall(ctx, &testpb.Empty{})
cancel()
if status.Code(err) != tc.code {
t.Fatalf("EmptyCall(_, _) = _, %v; want _, <Code() = %v>", err, tc.code)
}
if i != tc.count {
t.Fatalf("i = %v; want %v", i, tc.count)
}
}
}
func TestRetryDisabledByDefault(t *testing.T) {
if strings.EqualFold(os.Getenv("GRPC_GO_RETRY"), "on") {
return
}
i := -1
ss := &stubServer{
emptyCall: func(context.Context, *testpb.Empty) (*testpb.Empty, error) {
i++
switch i {
case 0:
return nil, status.New(codes.AlreadyExists, "retryable error").Err()
}
return &testpb.Empty{}, nil
},
}
if err := ss.Start([]grpc.ServerOption{}); err != nil {
t.Fatalf("Error starting endpoint server: %v", err)
}
defer ss.Stop()
ss.r.NewServiceConfig(`{
"methodConfig": [{
"name": [{"service": "grpc.testing.TestService"}],
"waitForReady": true,
"retryPolicy": {
"MaxAttempts": 4,
"InitialBackoff": ".01s",
"MaxBackoff": ".01s",
"BackoffMultiplier": 1.0,
"RetryableStatusCodes": [ "ALREADY_EXISTS" ]
}
}]}`)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
for {
if ctx.Err() != nil {
t.Fatalf("Timed out waiting for service config update")
}
if ss.cc.GetMethodConfig("/grpc.testing.TestService/EmptyCall").WaitForReady != nil {
break
}
time.Sleep(time.Millisecond)
}
cancel()
testCases := []struct {
code codes.Code
count int
}{
{codes.AlreadyExists, 0},
}
for _, tc := range testCases {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
_, err := ss.client.EmptyCall(ctx, &testpb.Empty{})
cancel()
if status.Code(err) != tc.code {
t.Fatalf("EmptyCall(_, _) = _, %v; want _, <Code() = %v>", err, tc.code)
}
if i != tc.count {
t.Fatalf("i = %v; want %v", i, tc.count)
}
}
}
func TestRetryThrottling(t *testing.T) {
defer enableRetry()()
i := -1
ss := &stubServer{
emptyCall: func(context.Context, *testpb.Empty) (*testpb.Empty, error) {
i++
switch i {
case 0, 3, 6, 10, 11, 12, 13, 14, 16, 18:
return &testpb.Empty{}, nil
}
return nil, status.New(codes.Unavailable, "retryable error").Err()
},
}
if err := ss.Start([]grpc.ServerOption{}); err != nil {
t.Fatalf("Error starting endpoint server: %v", err)
}
defer ss.Stop()
ss.r.NewServiceConfig(`{
"methodConfig": [{
"name": [{"service": "grpc.testing.TestService"}],
"waitForReady": true,
"retryPolicy": {
"MaxAttempts": 4,
"InitialBackoff": ".01s",
"MaxBackoff": ".01s",
"BackoffMultiplier": 1.0,
"RetryableStatusCodes": [ "UNAVAILABLE" ]
}
}],
"retryThrottling": {
"maxTokens": 10,
"tokenRatio": 0.5
}
}`)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
for {
if ctx.Err() != nil {
t.Fatalf("Timed out waiting for service config update")
}
if ss.cc.GetMethodConfig("/grpc.testing.TestService/EmptyCall").WaitForReady != nil {
break
}
time.Sleep(time.Millisecond)
}
cancel()
testCases := []struct {
code codes.Code
count int
}{
{codes.OK, 0}, // tokens = 10
{codes.OK, 3}, // tokens = 8.5 (10 - 2 failures + 0.5 success)
{codes.OK, 6}, // tokens = 6
{codes.Unavailable, 8}, // tokens = 5 -- first attempt is retried; second aborted.
{codes.Unavailable, 9}, // tokens = 4
{codes.OK, 10}, // tokens = 4.5
{codes.OK, 11}, // tokens = 5
{codes.OK, 12}, // tokens = 5.5
{codes.OK, 13}, // tokens = 6
{codes.OK, 14}, // tokens = 6.5
{codes.OK, 16}, // tokens = 5.5
{codes.Unavailable, 17}, // tokens = 4.5
}
for _, tc := range testCases {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
_, err := ss.client.EmptyCall(ctx, &testpb.Empty{})
cancel()
if status.Code(err) != tc.code {
t.Errorf("EmptyCall(_, _) = _, %v; want _, <Code() = %v>", err, tc.code)
}
if i != tc.count {
t.Errorf("i = %v; want %v", i, tc.count)
}
}
}
func TestRetryStreaming(t *testing.T) {
defer enableRetry()()
req := func(b byte) *testpb.StreamingOutputCallRequest {
return &testpb.StreamingOutputCallRequest{Payload: &testpb.Payload{Body: []byte{b}}}
}
res := func(b byte) *testpb.StreamingOutputCallResponse {
return &testpb.StreamingOutputCallResponse{Payload: &testpb.Payload{Body: []byte{b}}}
}
largePayload, _ := newPayload(testpb.PayloadType_COMPRESSABLE, 500)
type serverOp func(stream testpb.TestService_FullDuplexCallServer) error
type clientOp func(stream testpb.TestService_FullDuplexCallClient) error
// Server Operations
sAttempts := func(n int) serverOp {
return func(stream testpb.TestService_FullDuplexCallServer) error {
const key = "grpc-previous-rpc-attempts"
md, ok := metadata.FromIncomingContext(stream.Context())
if !ok {
return status.Errorf(codes.Internal, "server: no header metadata received")
}
if got := md[key]; len(got) != 1 || got[0] != strconv.Itoa(n) {
return status.Errorf(codes.Internal, "server: metadata = %v; want <contains %q: %q>", md, key, n)
}
return nil
}
}
sReq := func(b byte) serverOp {
return func(stream testpb.TestService_FullDuplexCallServer) error {
want := req(b)
if got, err := stream.Recv(); err != nil || !proto.Equal(got, want) {
return status.Errorf(codes.Internal, "server: Recv() = %v, %v; want %v, <nil>", got, err, want)
}
return nil
}
}
sReqPayload := func(p *testpb.Payload) serverOp {
return func(stream testpb.TestService_FullDuplexCallServer) error {
want := &testpb.StreamingOutputCallRequest{Payload: p}
if got, err := stream.Recv(); err != nil || !proto.Equal(got, want) {
return status.Errorf(codes.Internal, "server: Recv() = %v, %v; want %v, <nil>", got, err, want)
}
return nil
}
}
sRes := func(b byte) serverOp {
return func(stream testpb.TestService_FullDuplexCallServer) error {
msg := res(b)
if err := stream.Send(msg); err != nil {
return status.Errorf(codes.Internal, "server: Send(%v) = %v; want <nil>", msg, err)
}
return nil
}
}
sErr := func(c codes.Code) serverOp {
return func(stream testpb.TestService_FullDuplexCallServer) error {
return status.New(c, "").Err()
}
}
sCloseSend := func() serverOp {
return func(stream testpb.TestService_FullDuplexCallServer) error {
if msg, err := stream.Recv(); msg != nil || err != io.EOF {
return status.Errorf(codes.Internal, "server: Recv() = %v, %v; want <nil>, io.EOF", msg, err)
}
return nil
}
}
sPushback := func(s string) serverOp {
return func(stream testpb.TestService_FullDuplexCallServer) error {
stream.SetTrailer(metadata.MD{"grpc-retry-pushback-ms": []string{s}})
return nil
}
}
// Client Operations
cReq := func(b byte) clientOp {
return func(stream testpb.TestService_FullDuplexCallClient) error {
msg := req(b)
if err := stream.Send(msg); err != nil {
return fmt.Errorf("client: Send(%v) = %v; want <nil>", msg, err)
}
return nil
}
}
cReqPayload := func(p *testpb.Payload) clientOp {
return func(stream testpb.TestService_FullDuplexCallClient) error {
msg := &testpb.StreamingOutputCallRequest{Payload: p}
if err := stream.Send(msg); err != nil {
return fmt.Errorf("client: Send(%v) = %v; want <nil>", msg, err)
}
return nil
}
}
cRes := func(b byte) clientOp {
return func(stream testpb.TestService_FullDuplexCallClient) error {
want := res(b)
if got, err := stream.Recv(); err != nil || !proto.Equal(got, want) {
return fmt.Errorf("client: Recv() = %v, %v; want %v, <nil>", got, err, want)
}
return nil
}
}
cErr := func(c codes.Code) clientOp {
return func(stream testpb.TestService_FullDuplexCallClient) error {
want := status.New(c, "").Err()
if c == codes.OK {
want = io.EOF
}
res, err := stream.Recv()
if res != nil ||
((err == nil) != (want == nil)) ||
(want != nil && !reflect.DeepEqual(err, want)) {
return fmt.Errorf("client: Recv() = %v, %v; want <nil>, %v", res, err, want)
}
return nil
}
}
cCloseSend := func() clientOp {
return func(stream testpb.TestService_FullDuplexCallClient) error {
if err := stream.CloseSend(); err != nil {
return fmt.Errorf("client: CloseSend() = %v; want <nil>", err)
}
return nil
}
}
var curTime time.Time
cGetTime := func() clientOp {
return func(_ testpb.TestService_FullDuplexCallClient) error {
curTime = time.Now()
return nil
}
}
cCheckElapsed := func(d time.Duration) clientOp {
return func(_ testpb.TestService_FullDuplexCallClient) error {
if elapsed := time.Since(curTime); elapsed < d {
return fmt.Errorf("Elapsed time: %v; want >= %v", elapsed, d)
}
return nil
}
}
cHdr := func() clientOp {
return func(stream testpb.TestService_FullDuplexCallClient) error {
_, err := stream.Header()
return err
}
}
cCtx := func() clientOp {
return func(stream testpb.TestService_FullDuplexCallClient) error {
stream.Context()
return nil
}
}
testCases := []struct {
desc string
serverOps []serverOp
clientOps []clientOp
}{{
desc: "Non-retryable error code",
serverOps: []serverOp{sReq(1), sErr(codes.Internal)},
clientOps: []clientOp{cReq(1), cErr(codes.Internal)},
}, {
desc: "One retry necessary",
serverOps: []serverOp{sReq(1), sErr(codes.Unavailable), sReq(1), sAttempts(1), sRes(1)},
clientOps: []clientOp{cReq(1), cRes(1), cErr(codes.OK)},
}, {
desc: "Exceed max attempts (4); check attempts header on server",
serverOps: []serverOp{
sReq(1), sErr(codes.Unavailable),
sReq(1), sAttempts(1), sErr(codes.Unavailable),
sAttempts(2), sReq(1), sErr(codes.Unavailable),
sAttempts(3), sReq(1), sErr(codes.Unavailable),
},
clientOps: []clientOp{cReq(1), cErr(codes.Unavailable)},
}, {
desc: "Multiple requests",
serverOps: []serverOp{
sReq(1), sReq(2), sErr(codes.Unavailable),
sReq(1), sReq(2), sRes(5),
},
clientOps: []clientOp{cReq(1), cReq(2), cRes(5), cErr(codes.OK)},
}, {
desc: "Multiple successive requests",
serverOps: []serverOp{
sReq(1), sErr(codes.Unavailable),
sReq(1), sReq(2), sErr(codes.Unavailable),
sReq(1), sReq(2), sReq(3), sRes(5),
},
clientOps: []clientOp{cReq(1), cReq(2), cReq(3), cRes(5), cErr(codes.OK)},
}, {
desc: "No retry after receiving",
serverOps: []serverOp{
sReq(1), sErr(codes.Unavailable),
sReq(1), sRes(3), sErr(codes.Unavailable),
},
clientOps: []clientOp{cReq(1), cRes(3), cErr(codes.Unavailable)},
}, {
desc: "No retry after header",
serverOps: []serverOp{sReq(1), sErr(codes.Unavailable)},
clientOps: []clientOp{cReq(1), cHdr(), cErr(codes.Unavailable)},
}, {
desc: "No retry after context",
serverOps: []serverOp{sReq(1), sErr(codes.Unavailable)},
clientOps: []clientOp{cReq(1), cCtx(), cErr(codes.Unavailable)},
}, {
desc: "Replaying close send",
serverOps: []serverOp{
sReq(1), sReq(2), sCloseSend(), sErr(codes.Unavailable),
sReq(1), sReq(2), sCloseSend(), sRes(1), sRes(3), sRes(5),
},
clientOps: []clientOp{cReq(1), cReq(2), cCloseSend(), cRes(1), cRes(3), cRes(5), cErr(codes.OK)},
}, {
desc: "Negative server pushback - no retry",
serverOps: []serverOp{sReq(1), sPushback("-1"), sErr(codes.Unavailable)},
clientOps: []clientOp{cReq(1), cErr(codes.Unavailable)},
}, {
desc: "Non-numeric server pushback - no retry",
serverOps: []serverOp{sReq(1), sPushback("xxx"), sErr(codes.Unavailable)},
clientOps: []clientOp{cReq(1), cErr(codes.Unavailable)},
}, {
desc: "Multiple server pushback values - no retry",
serverOps: []serverOp{sReq(1), sPushback("100"), sPushback("10"), sErr(codes.Unavailable)},
clientOps: []clientOp{cReq(1), cErr(codes.Unavailable)},
}, {
desc: "1s server pushback - delayed retry",
serverOps: []serverOp{sReq(1), sPushback("1000"), sErr(codes.Unavailable), sReq(1), sRes(2)},
clientOps: []clientOp{cGetTime(), cReq(1), cRes(2), cCheckElapsed(time.Second), cErr(codes.OK)},
}, {
desc: "Overflowing buffer - no retry",
serverOps: []serverOp{sReqPayload(largePayload), sErr(codes.Unavailable)},
clientOps: []clientOp{cReqPayload(largePayload), cErr(codes.Unavailable)},
}}
var serverOpIter int
var serverOps []serverOp
ss := &stubServer{
fullDuplexCall: func(stream testpb.TestService_FullDuplexCallServer) error {
for serverOpIter < len(serverOps) {
op := serverOps[serverOpIter]
serverOpIter++
if err := op(stream); err != nil {
return err
}
}
return nil
},
}
if err := ss.Start([]grpc.ServerOption{}, grpc.WithDefaultCallOptions(grpc.MaxRetryRPCBufferSize(200))); err != nil {
t.Fatalf("Error starting endpoint server: %v", err)
}
defer ss.Stop()
ss.r.NewServiceConfig(`{
"methodConfig": [{
"name": [{"service": "grpc.testing.TestService"}],
"waitForReady": true,
"retryPolicy": {
"MaxAttempts": 4,
"InitialBackoff": ".01s",
"MaxBackoff": ".01s",
"BackoffMultiplier": 1.0,
"RetryableStatusCodes": [ "UNAVAILABLE" ]
}
}]}`)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
for {
if ctx.Err() != nil {
t.Fatalf("Timed out waiting for service config update")
}
if ss.cc.GetMethodConfig("/grpc.testing.TestService/FullDuplexCall").WaitForReady != nil {
break
}
time.Sleep(time.Millisecond)
}
cancel()
for _, tc := range testCases {
func() {
serverOpIter = 0
serverOps = tc.serverOps
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
stream, err := ss.client.FullDuplexCall(ctx)
if err != nil {
t.Fatalf("%v: Error while creating stream: %v", tc.desc, err)
}
for _, op := range tc.clientOps {
if err := op(stream); err != nil {
t.Errorf("%v: %v", tc.desc, err)
break
}
}
if serverOpIter != len(serverOps) {
t.Errorf("%v: serverOpIter = %v; want %v", tc.desc, serverOpIter, len(serverOps))
}
}()
}
}

280
vendor/google.golang.org/grpc/test/servertester.go generated vendored Normal file
View File

@@ -0,0 +1,280 @@
/*
* Copyright 2016 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package test
import (
"bytes"
"errors"
"io"
"strings"
"testing"
"time"
"golang.org/x/net/http2"
"golang.org/x/net/http2/hpack"
)
// This is a subset of http2's serverTester type.
//
// serverTester wraps a io.ReadWriter (acting like the underlying
// network connection) and provides utility methods to read and write
// http2 frames.
//
// NOTE(bradfitz): this could eventually be exported somewhere. Others
// have asked for it too. For now I'm still experimenting with the
// API and don't feel like maintaining a stable testing API.
type serverTester struct {
cc io.ReadWriteCloser // client conn
t testing.TB
fr *http2.Framer
// writing headers:
headerBuf bytes.Buffer
hpackEnc *hpack.Encoder
// reading frames:
frc chan http2.Frame
frErrc chan error
readTimer *time.Timer
}
func newServerTesterFromConn(t testing.TB, cc io.ReadWriteCloser) *serverTester {
st := &serverTester{
t: t,
cc: cc,
frc: make(chan http2.Frame, 1),
frErrc: make(chan error, 1),
}
st.hpackEnc = hpack.NewEncoder(&st.headerBuf)
st.fr = http2.NewFramer(cc, cc)
st.fr.ReadMetaHeaders = hpack.NewDecoder(4096 /*initialHeaderTableSize*/, nil)
return st
}
func (st *serverTester) readFrame() (http2.Frame, error) {
go func() {
fr, err := st.fr.ReadFrame()
if err != nil {
st.frErrc <- err
} else {
st.frc <- fr
}
}()
t := time.NewTimer(2 * time.Second)
defer t.Stop()
select {
case f := <-st.frc:
return f, nil
case err := <-st.frErrc:
return nil, err
case <-t.C:
return nil, errors.New("timeout waiting for frame")
}
}
// greet initiates the client's HTTP/2 connection into a state where
// frames may be sent.
func (st *serverTester) greet() {
st.writePreface()
st.writeInitialSettings()
st.wantSettings()
st.writeSettingsAck()
for {
f, err := st.readFrame()
if err != nil {
st.t.Fatal(err)
}
switch f := f.(type) {
case *http2.WindowUpdateFrame:
// grpc's transport/http2_server sends this
// before the settings ack. The Go http2
// server uses a setting instead.
case *http2.SettingsFrame:
if f.IsAck() {
return
}
st.t.Fatalf("during greet, got non-ACK settings frame")
default:
st.t.Fatalf("during greet, unexpected frame type %T", f)
}
}
}
func (st *serverTester) writePreface() {
n, err := st.cc.Write([]byte(http2.ClientPreface))
if err != nil {
st.t.Fatalf("Error writing client preface: %v", err)
}
if n != len(http2.ClientPreface) {
st.t.Fatalf("Writing client preface, wrote %d bytes; want %d", n, len(http2.ClientPreface))
}
}
func (st *serverTester) writeInitialSettings() {
if err := st.fr.WriteSettings(); err != nil {
st.t.Fatalf("Error writing initial SETTINGS frame from client to server: %v", err)
}
}
func (st *serverTester) writeSettingsAck() {
if err := st.fr.WriteSettingsAck(); err != nil {
st.t.Fatalf("Error writing ACK of server's SETTINGS: %v", err)
}
}
func (st *serverTester) wantSettings() *http2.SettingsFrame {
f, err := st.readFrame()
if err != nil {
st.t.Fatalf("Error while expecting a SETTINGS frame: %v", err)
}
sf, ok := f.(*http2.SettingsFrame)
if !ok {
st.t.Fatalf("got a %T; want *SettingsFrame", f)
}
return sf
}
func (st *serverTester) wantSettingsAck() {
f, err := st.readFrame()
if err != nil {
st.t.Fatal(err)
}
sf, ok := f.(*http2.SettingsFrame)
if !ok {
st.t.Fatalf("Wanting a settings ACK, received a %T", f)
}
if !sf.IsAck() {
st.t.Fatal("Settings Frame didn't have ACK set")
}
}
// wait for any activity from the server
func (st *serverTester) wantAnyFrame() http2.Frame {
f, err := st.fr.ReadFrame()
if err != nil {
st.t.Fatal(err)
}
return f
}
func (st *serverTester) encodeHeaderField(k, v string) {
err := st.hpackEnc.WriteField(hpack.HeaderField{Name: k, Value: v})
if err != nil {
st.t.Fatalf("HPACK encoding error for %q/%q: %v", k, v, err)
}
}
// encodeHeader encodes headers and returns their HPACK bytes. headers
// must contain an even number of key/value pairs. There may be
// multiple pairs for keys (e.g. "cookie"). The :method, :path, and
// :scheme headers default to GET, / and https.
func (st *serverTester) encodeHeader(headers ...string) []byte {
if len(headers)%2 == 1 {
panic("odd number of kv args")
}
st.headerBuf.Reset()
if len(headers) == 0 {
// Fast path, mostly for benchmarks, so test code doesn't pollute
// profiles when we're looking to improve server allocations.
st.encodeHeaderField(":method", "GET")
st.encodeHeaderField(":path", "/")
st.encodeHeaderField(":scheme", "https")
return st.headerBuf.Bytes()
}
if len(headers) == 2 && headers[0] == ":method" {
// Another fast path for benchmarks.
st.encodeHeaderField(":method", headers[1])
st.encodeHeaderField(":path", "/")
st.encodeHeaderField(":scheme", "https")
return st.headerBuf.Bytes()
}
pseudoCount := map[string]int{}
keys := []string{":method", ":path", ":scheme"}
vals := map[string][]string{
":method": {"GET"},
":path": {"/"},
":scheme": {"https"},
}
for len(headers) > 0 {
k, v := headers[0], headers[1]
headers = headers[2:]
if _, ok := vals[k]; !ok {
keys = append(keys, k)
}
if strings.HasPrefix(k, ":") {
pseudoCount[k]++
if pseudoCount[k] == 1 {
vals[k] = []string{v}
} else {
// Allows testing of invalid headers w/ dup pseudo fields.
vals[k] = append(vals[k], v)
}
} else {
vals[k] = append(vals[k], v)
}
}
for _, k := range keys {
for _, v := range vals[k] {
st.encodeHeaderField(k, v)
}
}
return st.headerBuf.Bytes()
}
func (st *serverTester) writeHeadersGRPC(streamID uint32, path string) {
st.writeHeaders(http2.HeadersFrameParam{
StreamID: streamID,
BlockFragment: st.encodeHeader(
":method", "POST",
":path", path,
"content-type", "application/grpc",
"te", "trailers",
),
EndStream: false,
EndHeaders: true,
})
}
func (st *serverTester) writeHeaders(p http2.HeadersFrameParam) {
if err := st.fr.WriteHeaders(p); err != nil {
st.t.Fatalf("Error writing HEADERS: %v", err)
}
}
func (st *serverTester) writeData(streamID uint32, endStream bool, data []byte) {
if err := st.fr.WriteData(streamID, endStream, data); err != nil {
st.t.Fatalf("Error writing DATA: %v", err)
}
}
func (st *serverTester) writeRSTStream(streamID uint32, code http2.ErrCode) {
if err := st.fr.WriteRSTStream(streamID, code); err != nil {
st.t.Fatalf("Error writing RST_STREAM: %v", err)
}
}
func (st *serverTester) writeDataPadded(streamID uint32, endStream bool, data, padding []byte) {
if err := st.fr.WriteDataPadded(streamID, endStream, data, padding); err != nil {
st.t.Fatalf("Error writing DATA with padding: %v", err)
}
}

34
vendor/google.golang.org/grpc/test/tools/tools.go generated vendored Normal file
View File

@@ -0,0 +1,34 @@
// +build tools
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// This package exists to cause `go mod` and `go get` to believe these tools
// are dependencies, even though they are not runtime dependencies of any grpc
// package. This means they will appear in our `go.mod` file, but will not be
// a part of the build.
package tools
import (
_ "github.com/client9/misspell/cmd/misspell"
_ "github.com/golang/protobuf/protoc-gen-go"
_ "golang.org/x/lint/golint"
_ "golang.org/x/tools/cmd/goimports"
_ "honnef.co/go/tools/cmd/staticcheck"
)