diff --git a/interceptor.go b/interceptor.go index b702b0a..8d43e7c 100644 --- a/interceptor.go +++ b/interceptor.go @@ -11,6 +11,7 @@ import ( "github.com/SkyAPM/go2sky" "github.com/SkyAPM/go2sky/propagation" + // nolint:staticcheck // ignore SA1019 Need to keep deprecated package for compatibility. "github.com/golang/protobuf/proto" @@ -175,6 +176,7 @@ func NewUnaryClientSkywalkingInterceptor(tracer *go2sky.Tracer) grpc.UnaryClient } // NewUnaryServerSkywalkingInterceptor skywalking server interceptor. +// nolint: govet func NewUnaryServerSkywalkingInterceptor(tracer *go2sky.Tracer, opts ...Option) grpc.UnaryServerInterceptor { options := &options{ reportTags: []string{}, diff --git a/interceptor_test.go b/interceptor_test.go index 2291766..7900a13 100644 --- a/interceptor_test.go +++ b/interceptor_test.go @@ -7,6 +7,8 @@ import ( "strings" "testing" + "github.com/SkyAPM/go2sky" + "github.com/SkyAPM/go2sky/reporter" grpc_testing "github.com/grpc-ecosystem/go-grpc-middleware/testing" pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/testing/testproto" "github.com/stretchr/testify/suite" @@ -14,7 +16,9 @@ import ( ) var ( - goodPing = &pb_testproto.PingRequest{Value: "goodPing", SleepTimeMs: 999} + goodPing = &pb_testproto.PingRequest{Value: "goodPing", SleepTimeMs: 999} + skyClientPing = &pb_testproto.PingRequest{Value: "skyClientPing", SleepTimeMs: 999} + skyServerPing = &pb_testproto.PingRequest{Value: "skyServerPing", SleepTimeMs: 999} ) type LogTestSuite struct { @@ -22,6 +26,16 @@ type LogTestSuite struct { reader, writer *os.File } +type SkywalkingClientTestSuite struct { + *grpc_testing.InterceptorTestSuite + reader, writer *os.File +} + +type SkywalkingServerTestSuite struct { + *grpc_testing.InterceptorTestSuite + reader, writer *os.File +} + func TestLogTestSuite(t *testing.T) { r, w, _ := os.Pipe() // 替换原有os.Stdout @@ -64,3 +78,83 @@ func (s *LogTestSuite) TestMarshalJSON() { s.Nil(err) s.True(strings.Contains(string(buf), "goodPing")) } + +func TestSkywalkingClientTestSuite(t *testing.T) { + r, w, _ := os.Pipe() + // 替换原有os.Stdout + report, err := reporter.NewLogReporter() + if err != nil { + return + } + tracer, err := go2sky.NewTracer("test", go2sky.WithReporter(report)) + os.Stdout = w + s := &SkywalkingClientTestSuite{ + InterceptorTestSuite: &grpc_testing.InterceptorTestSuite{ + ClientOpts: []grpc.DialOption{ + grpc.WithUnaryInterceptor(NewUnaryClientSkywalkingInterceptor(tracer)), + }, + }, + } + s.reader = r + s.writer = w + suite.Run(t, s) +} + +func (c *SkywalkingClientTestSuite) TestNewUnaryClientSkywalkingInterceptor() { + _, err := c.Client.Ping(c.SimpleCtx(), skyClientPing) + c.NoError(err) + + var buf bytes.Buffer + output := make(chan string, 1) + go func() { + io.Copy(&buf, c.reader) + output <- buf.String() + c.reader.Close() + }() + c.writer.Close() + + o := strings.Split(<-output, "\n") + // 输出空行 + c.Len(o, 1) + c.Equal(o[0], "") +} + +func TestSkywalkingServerTestSuite(t *testing.T) { + r, w, _ := os.Pipe() + // 替换原有os.Stdout + os.Stdout = w + report, err := reporter.NewLogReporter() + if err != nil { + return + } + tracer, err := go2sky.NewTracer("test", go2sky.WithReporter(report)) + s := &SkywalkingServerTestSuite{ + InterceptorTestSuite: &grpc_testing.InterceptorTestSuite{ + ServerOpts: []grpc.ServerOption{ + grpc.UnaryInterceptor(NewUnaryServerSkywalkingInterceptor(tracer)), + }, + }, + } + s.reader = r + s.writer = w + suite.Run(t, s) +} + +func (s *SkywalkingServerTestSuite) TestNewUnaryServerSkywalkingInterceptor() { + _, err := s.Client.Ping(s.SimpleCtx(), skyServerPing) + s.NoError(err) + + var buf bytes.Buffer + output := make(chan string, 1) + go func() { + io.Copy(&buf, s.reader) + output <- buf.String() + s.reader.Close() + }() + s.writer.Close() + + o := strings.Split(<-output, "\n") + // 输出空行 + s.Len(o, 1) + s.Equal(o[0], "") +} diff --git a/middleware.go b/middleware.go index 5716516..d35e05a 100644 --- a/middleware.go +++ b/middleware.go @@ -19,19 +19,21 @@ var ( type operation func(name string, r *http.Request) string +// nolint: govet type handler struct { - tracer *go2sky.Tracer - name string - next http.Handler - extraTags map[string]string // filter some health check request. filterURLs []string + next http.Handler + name string + tracer *go2sky.Tracer + extraTags map[string]string // get operation name. operationFunc operation } // responseWriter is a minimal wrapper for http.ResponseWriter that allows the // written HTTP status code to be captured for logging. +// nolint: govet,unused type responseWriter struct { http.ResponseWriter status int @@ -71,7 +73,7 @@ func FilterURL(filterURLs []string, url string) bool { return false } -func NewServerSkywalkingMiddleware(tracer *go2sky.Tracer, opts ...func(*handler)) (func(http.Handler) http.Handler, error) { +func NewServerSkywalkingHTTPMiddleware(tracer *go2sky.Tracer, opts ...func(*handler)) (func(http.Handler) http.Handler, error) { if tracer == nil { panic("tracer is nil.") } diff --git a/middleware_test.go b/middleware_test.go new file mode 100644 index 0000000..3404de2 --- /dev/null +++ b/middleware_test.go @@ -0,0 +1,42 @@ +package hutils + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/SkyAPM/go2sky" + "github.com/SkyAPM/go2sky/reporter" +) + +type Ping struct{} + +func TestSkywalkingHTTPMiddlewareTestSuite(t *testing.T) { + report, err := reporter.NewLogReporter() + if err != nil { + return + } + tracer, err := go2sky.NewTracer("test", go2sky.WithReporter(report)) + if err != nil { + return + } + middleware, err := NewServerSkywalkingHTTPMiddleware(tracer) + if err != nil { + return + } + mux := http.NewServeMux() + mux.Handle("/ping", middleware(&Ping{})) + + req := httptest.NewRequest("GET", "/ping", nil) + rw := httptest.NewRecorder() + mux.ServeHTTP(rw, req) + + response := rw.Body.String() + if response != "OK" { + t.Errorf("Response gotten was %q", response) + } +} + +func (p *Ping) ServeHTTP(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("OK")) +}