blob: c4ebc0e499231f87eaf9815c210e6b24ef851dc7 [file] [log] [blame]
// Copyright 2021 The LUCI 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 grpcmon
import (
"context"
"net"
"testing"
"google.golang.org/grpc"
"google.golang.org/grpc/stats"
. "github.com/smartystreets/goconvey/convey"
)
type testStatsHandler struct {
tagRPC func()
}
func (tsh *testStatsHandler) HandleRPC(ctx context.Context, s stats.RPCStats) {
}
func (tsh *testStatsHandler) TagRPC(ctx context.Context, i *stats.RPCTagInfo) context.Context {
tsh.tagRPC()
return ctx
}
func (tsh *testStatsHandler) TagConn(ctx context.Context, t *stats.ConnTagInfo) context.Context {
return ctx
}
// HandleConn processes the Conn stats.
func (tsh *testStatsHandler) HandleConn(context.Context, stats.ConnStats) {
// do nothing
}
func TestWithMultiStatsHandler(t *testing.T) {
Convey("Test WithMultiStatsHandler", t, func() {
ctx := context.Background()
h1 := &testStatsHandler{}
h2 := &testStatsHandler{}
// spin up a server
srv, svc := grpc.NewServer(), &echoService{}
RegisterEchoServer(srv, svc)
l, err := net.Listen("tcp", "localhost:0")
So(err, ShouldBeNil)
go func() { _ = srv.Serve(l) }()
defer srv.Stop()
connect := func(opt grpc.DialOption) *grpc.ClientConn {
conn, err := grpc.Dial(
l.Addr().String(),
grpc.WithInsecure(),
grpc.WithBlock(),
opt,
)
So(err, ShouldBeNil)
return conn
}
Convey("w/o params", func() {
conn := connect(WithMultiStatsHandler())
defer func() { So(conn.Close(), ShouldBeNil) }()
NewEchoClient(conn).Say(ctx, &SayRequest{Msg: "echo!"})
})
Convey("w/ testStatsHandler", func() {
ch := make(chan int, 1)
h1.tagRPC = func() {
ch <- 1
}
Convey("alone", func() {
conn := connect(WithMultiStatsHandler(h1))
defer func() { So(conn.Close(), ShouldBeNil) }()
NewEchoClient(conn).Say(ctx, &SayRequest{Msg: "echo!"})
})
Convey("w/ nil", func() {
conn := connect(WithMultiStatsHandler(nil, h1, nil))
defer func() { So(conn.Close(), ShouldBeNil) }()
NewEchoClient(conn).Say(ctx, &SayRequest{Msg: "echo!"})
})
close(ch)
So(<-ch, ShouldEqual, 1)
})
Convey("runs the handlers in order", func() {
ch := make(chan int, 3)
h1.tagRPC = func() {
ch <- 2
}
h2.tagRPC = func() {
ch <- 1
}
conn := connect(WithMultiStatsHandler(h1, h2, h1))
defer func() { So(conn.Close(), ShouldBeNil) }()
NewEchoClient(conn).Say(ctx, &SayRequest{Msg: "echo!"})
close(ch)
values := []int{}
for val := range ch {
values = append(values, val)
}
So(values, ShouldResemble, []int{2, 1, 2})
})
})
}