123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- /*
- *
- * 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 binarylog
- import (
- "bytes"
- "fmt"
- "net"
- "testing"
- "time"
- "github.com/golang/protobuf/proto"
- dpb "github.com/golang/protobuf/ptypes/duration"
- pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/status"
- )
- func TestLog(t *testing.T) {
- idGen.reset()
- ml := newMethodLogger(10, 10)
- // Set sink to testing buffer.
- buf := bytes.NewBuffer(nil)
- ml.sink = newWriterSink(buf)
- addr := "1.2.3.4"
- port := 790
- tcpAddr, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("%v:%d", addr, port))
- addr6 := "2001:1db8:85a3::8a2e:1370:7334"
- port6 := 796
- tcpAddr6, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("[%v]:%d", addr6, port6))
- testProtoMsg := &pb.Message{
- Length: 1,
- Data: []byte{'a'},
- }
- testProtoBytes, _ := proto.Marshal(testProtoMsg)
- testCases := []struct {
- config LogEntryConfig
- want *pb.GrpcLogEntry
- }{
- {
- config: &ClientHeader{
- OnClientSide: false,
- Header: map[string][]string{
- "a": {"b", "bb"},
- },
- MethodName: "testservice/testmethod",
- Authority: "test.service.io",
- Timeout: 2*time.Second + 3*time.Nanosecond,
- PeerAddr: tcpAddr,
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
- Logger: pb.GrpcLogEntry_LOGGER_SERVER,
- Payload: &pb.GrpcLogEntry_ClientHeader{
- ClientHeader: &pb.ClientHeader{
- Metadata: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "a", Value: []byte{'b'}},
- {Key: "a", Value: []byte{'b', 'b'}},
- },
- },
- MethodName: "testservice/testmethod",
- Authority: "test.service.io",
- Timeout: &dpb.Duration{
- Seconds: 2,
- Nanos: 3,
- },
- },
- },
- PayloadTruncated: false,
- Peer: &pb.Address{
- Type: pb.Address_TYPE_IPV4,
- Address: addr,
- IpPort: uint32(port),
- },
- },
- },
- {
- config: &ClientHeader{
- OnClientSide: false,
- MethodName: "testservice/testmethod",
- Authority: "test.service.io",
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
- Logger: pb.GrpcLogEntry_LOGGER_SERVER,
- Payload: &pb.GrpcLogEntry_ClientHeader{
- ClientHeader: &pb.ClientHeader{
- Metadata: &pb.Metadata{},
- MethodName: "testservice/testmethod",
- Authority: "test.service.io",
- },
- },
- PayloadTruncated: false,
- },
- },
- {
- config: &ServerHeader{
- OnClientSide: true,
- Header: map[string][]string{
- "a": {"b", "bb"},
- },
- PeerAddr: tcpAddr6,
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
- Logger: pb.GrpcLogEntry_LOGGER_CLIENT,
- Payload: &pb.GrpcLogEntry_ServerHeader{
- ServerHeader: &pb.ServerHeader{
- Metadata: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "a", Value: []byte{'b'}},
- {Key: "a", Value: []byte{'b', 'b'}},
- },
- },
- },
- },
- PayloadTruncated: false,
- Peer: &pb.Address{
- Type: pb.Address_TYPE_IPV6,
- Address: addr6,
- IpPort: uint32(port6),
- },
- },
- },
- {
- config: &ClientMessage{
- OnClientSide: true,
- Message: testProtoMsg,
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE,
- Logger: pb.GrpcLogEntry_LOGGER_CLIENT,
- Payload: &pb.GrpcLogEntry_Message{
- Message: &pb.Message{
- Length: uint32(len(testProtoBytes)),
- Data: testProtoBytes,
- },
- },
- PayloadTruncated: false,
- Peer: nil,
- },
- },
- {
- config: &ServerMessage{
- OnClientSide: false,
- Message: testProtoMsg,
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE,
- Logger: pb.GrpcLogEntry_LOGGER_SERVER,
- Payload: &pb.GrpcLogEntry_Message{
- Message: &pb.Message{
- Length: uint32(len(testProtoBytes)),
- Data: testProtoBytes,
- },
- },
- PayloadTruncated: false,
- Peer: nil,
- },
- },
- {
- config: &ClientHalfClose{
- OnClientSide: false,
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE,
- Logger: pb.GrpcLogEntry_LOGGER_SERVER,
- Payload: nil,
- PayloadTruncated: false,
- Peer: nil,
- },
- },
- {
- config: &ServerTrailer{
- OnClientSide: true,
- Err: status.Errorf(codes.Unavailable, "test"),
- PeerAddr: tcpAddr,
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
- Logger: pb.GrpcLogEntry_LOGGER_CLIENT,
- Payload: &pb.GrpcLogEntry_Trailer{
- Trailer: &pb.Trailer{
- Metadata: &pb.Metadata{},
- StatusCode: uint32(codes.Unavailable),
- StatusMessage: "test",
- StatusDetails: nil,
- },
- },
- PayloadTruncated: false,
- Peer: &pb.Address{
- Type: pb.Address_TYPE_IPV4,
- Address: addr,
- IpPort: uint32(port),
- },
- },
- },
- { // Err is nil, Log OK status.
- config: &ServerTrailer{
- OnClientSide: true,
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
- Logger: pb.GrpcLogEntry_LOGGER_CLIENT,
- Payload: &pb.GrpcLogEntry_Trailer{
- Trailer: &pb.Trailer{
- Metadata: &pb.Metadata{},
- StatusCode: uint32(codes.OK),
- StatusMessage: "",
- StatusDetails: nil,
- },
- },
- PayloadTruncated: false,
- Peer: nil,
- },
- },
- {
- config: &Cancel{
- OnClientSide: true,
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_CANCEL,
- Logger: pb.GrpcLogEntry_LOGGER_CLIENT,
- Payload: nil,
- PayloadTruncated: false,
- Peer: nil,
- },
- },
- // gRPC headers should be omitted.
- {
- config: &ClientHeader{
- OnClientSide: false,
- Header: map[string][]string{
- "grpc-reserved": {"to be omitted"},
- ":authority": {"to be omitted"},
- "a": {"b", "bb"},
- },
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
- Logger: pb.GrpcLogEntry_LOGGER_SERVER,
- Payload: &pb.GrpcLogEntry_ClientHeader{
- ClientHeader: &pb.ClientHeader{
- Metadata: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "a", Value: []byte{'b'}},
- {Key: "a", Value: []byte{'b', 'b'}},
- },
- },
- },
- },
- PayloadTruncated: false,
- },
- },
- {
- config: &ServerHeader{
- OnClientSide: true,
- Header: map[string][]string{
- "grpc-reserved": {"to be omitted"},
- ":authority": {"to be omitted"},
- "a": {"b", "bb"},
- },
- },
- want: &pb.GrpcLogEntry{
- Timestamp: nil,
- CallId: 1,
- SequenceIdWithinCall: 0,
- Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
- Logger: pb.GrpcLogEntry_LOGGER_CLIENT,
- Payload: &pb.GrpcLogEntry_ServerHeader{
- ServerHeader: &pb.ServerHeader{
- Metadata: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "a", Value: []byte{'b'}},
- {Key: "a", Value: []byte{'b', 'b'}},
- },
- },
- },
- },
- PayloadTruncated: false,
- },
- },
- }
- for i, tc := range testCases {
- buf.Reset()
- tc.want.SequenceIdWithinCall = uint64(i + 1)
- ml.Log(tc.config)
- inSink := new(pb.GrpcLogEntry)
- if err := proto.Unmarshal(buf.Bytes()[4:], inSink); err != nil {
- t.Errorf("failed to unmarshal bytes in sink to proto: %v", err)
- continue
- }
- inSink.Timestamp = nil // Strip timestamp before comparing.
- if !proto.Equal(inSink, tc.want) {
- t.Errorf("Log(%+v), in sink: %+v, want %+v", tc.config, inSink, tc.want)
- }
- }
- }
- func TestTruncateMetadataNotTruncated(t *testing.T) {
- testCases := []struct {
- ml *MethodLogger
- mpPb *pb.Metadata
- }{
- {
- ml: newMethodLogger(maxUInt, maxUInt),
- mpPb: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "", Value: []byte{1}},
- },
- },
- },
- {
- ml: newMethodLogger(2, maxUInt),
- mpPb: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "", Value: []byte{1}},
- },
- },
- },
- {
- ml: newMethodLogger(1, maxUInt),
- mpPb: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "", Value: nil},
- },
- },
- },
- {
- ml: newMethodLogger(2, maxUInt),
- mpPb: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "", Value: []byte{1, 1}},
- },
- },
- },
- {
- ml: newMethodLogger(2, maxUInt),
- mpPb: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "", Value: []byte{1}},
- {Key: "", Value: []byte{1}},
- },
- },
- },
- // "grpc-trace-bin" is kept in log but not counted towards the size
- // limit.
- {
- ml: newMethodLogger(1, maxUInt),
- mpPb: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "", Value: []byte{1}},
- {Key: "grpc-trace-bin", Value: []byte("some.trace.key")},
- },
- },
- },
- }
- for i, tc := range testCases {
- truncated := tc.ml.truncateMetadata(tc.mpPb)
- if truncated {
- t.Errorf("test case %v, returned truncated, want not truncated", i)
- }
- }
- }
- func TestTruncateMetadataTruncated(t *testing.T) {
- testCases := []struct {
- ml *MethodLogger
- mpPb *pb.Metadata
- entryLen int
- }{
- {
- ml: newMethodLogger(2, maxUInt),
- mpPb: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "", Value: []byte{1, 1, 1}},
- },
- },
- entryLen: 0,
- },
- {
- ml: newMethodLogger(2, maxUInt),
- mpPb: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "", Value: []byte{1}},
- {Key: "", Value: []byte{1}},
- {Key: "", Value: []byte{1}},
- },
- },
- entryLen: 2,
- },
- {
- ml: newMethodLogger(2, maxUInt),
- mpPb: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "", Value: []byte{1, 1}},
- {Key: "", Value: []byte{1}},
- },
- },
- entryLen: 1,
- },
- {
- ml: newMethodLogger(2, maxUInt),
- mpPb: &pb.Metadata{
- Entry: []*pb.MetadataEntry{
- {Key: "", Value: []byte{1}},
- {Key: "", Value: []byte{1, 1}},
- },
- },
- entryLen: 1,
- },
- }
- for i, tc := range testCases {
- truncated := tc.ml.truncateMetadata(tc.mpPb)
- if !truncated {
- t.Errorf("test case %v, returned not truncated, want truncated", i)
- continue
- }
- if len(tc.mpPb.Entry) != tc.entryLen {
- t.Errorf("test case %v, entry length: %v, want: %v", i, len(tc.mpPb.Entry), tc.entryLen)
- }
- }
- }
- func TestTruncateMessageNotTruncated(t *testing.T) {
- testCases := []struct {
- ml *MethodLogger
- msgPb *pb.Message
- }{
- {
- ml: newMethodLogger(maxUInt, maxUInt),
- msgPb: &pb.Message{
- Data: []byte{1},
- },
- },
- {
- ml: newMethodLogger(maxUInt, 3),
- msgPb: &pb.Message{
- Data: []byte{1, 1},
- },
- },
- {
- ml: newMethodLogger(maxUInt, 2),
- msgPb: &pb.Message{
- Data: []byte{1, 1},
- },
- },
- }
- for i, tc := range testCases {
- truncated := tc.ml.truncateMessage(tc.msgPb)
- if truncated {
- t.Errorf("test case %v, returned truncated, want not truncated", i)
- }
- }
- }
- func TestTruncateMessageTruncated(t *testing.T) {
- testCases := []struct {
- ml *MethodLogger
- msgPb *pb.Message
- oldLength uint32
- }{
- {
- ml: newMethodLogger(maxUInt, 2),
- msgPb: &pb.Message{
- Length: 3,
- Data: []byte{1, 1, 1},
- },
- oldLength: 3,
- },
- }
- for i, tc := range testCases {
- truncated := tc.ml.truncateMessage(tc.msgPb)
- if !truncated {
- t.Errorf("test case %v, returned not truncated, want truncated", i)
- continue
- }
- if len(tc.msgPb.Data) != int(tc.ml.messageMaxLen) {
- t.Errorf("test case %v, message length: %v, want: %v", i, len(tc.msgPb.Data), tc.ml.messageMaxLen)
- }
- if tc.msgPb.Length != tc.oldLength {
- t.Errorf("test case %v, message.Length field: %v, want: %v", i, tc.msgPb.Length, tc.oldLength)
- }
- }
- }
|