...

Source file src/google.golang.org/grpc/internal/binarylog/method_logger_test.go

Documentation: google.golang.org/grpc/internal/binarylog

     1  /*
     2   *
     3   * Copyright 2018 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  package binarylog
    20  
    21  import (
    22  	"bytes"
    23  	"context"
    24  	"fmt"
    25  	"net"
    26  	"testing"
    27  	"time"
    28  
    29  	binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
    30  	"google.golang.org/grpc/codes"
    31  	"google.golang.org/grpc/status"
    32  	"google.golang.org/protobuf/proto"
    33  	"google.golang.org/protobuf/types/known/durationpb"
    34  )
    35  
    36  func (s) TestLog(t *testing.T) {
    37  	idGen.reset()
    38  	ml := NewTruncatingMethodLogger(10, 10)
    39  	// Set sink to testing buffer.
    40  	buf := bytes.NewBuffer(nil)
    41  	ml.sink = newWriterSink(buf)
    42  
    43  	addr := "1.2.3.4"
    44  	port := 790
    45  	tcpAddr, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("%v:%d", addr, port))
    46  	addr6 := "2001:1db8:85a3::8a2e:1370:7334"
    47  	port6 := 796
    48  	tcpAddr6, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("[%v]:%d", addr6, port6))
    49  
    50  	testProtoMsg := &binlogpb.Message{
    51  		Length: 1,
    52  		Data:   []byte{'a'},
    53  	}
    54  	testProtoBytes, _ := proto.Marshal(testProtoMsg)
    55  
    56  	testCases := []struct {
    57  		config LogEntryConfig
    58  		want   *binlogpb.GrpcLogEntry
    59  	}{
    60  		{
    61  			config: &ClientHeader{
    62  				OnClientSide: false,
    63  				Header: map[string][]string{
    64  					"a": {"b", "bb"},
    65  				},
    66  				MethodName: "testservice/testmethod",
    67  				Authority:  "test.service.io",
    68  				Timeout:    2*time.Second + 3*time.Nanosecond,
    69  				PeerAddr:   tcpAddr,
    70  			},
    71  			want: &binlogpb.GrpcLogEntry{
    72  				Timestamp:            nil,
    73  				CallId:               1,
    74  				SequenceIdWithinCall: 0,
    75  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
    76  				Logger:               binlogpb.GrpcLogEntry_LOGGER_SERVER,
    77  				Payload: &binlogpb.GrpcLogEntry_ClientHeader{
    78  					ClientHeader: &binlogpb.ClientHeader{
    79  						Metadata: &binlogpb.Metadata{
    80  							Entry: []*binlogpb.MetadataEntry{
    81  								{Key: "a", Value: []byte{'b'}},
    82  								{Key: "a", Value: []byte{'b', 'b'}},
    83  							},
    84  						},
    85  						MethodName: "testservice/testmethod",
    86  						Authority:  "test.service.io",
    87  						Timeout: &durationpb.Duration{
    88  							Seconds: 2,
    89  							Nanos:   3,
    90  						},
    91  					},
    92  				},
    93  				PayloadTruncated: false,
    94  				Peer: &binlogpb.Address{
    95  					Type:    binlogpb.Address_TYPE_IPV4,
    96  					Address: addr,
    97  					IpPort:  uint32(port),
    98  				},
    99  			},
   100  		},
   101  		{
   102  			config: &ClientHeader{
   103  				OnClientSide: false,
   104  				MethodName:   "testservice/testmethod",
   105  				Authority:    "test.service.io",
   106  			},
   107  			want: &binlogpb.GrpcLogEntry{
   108  				Timestamp:            nil,
   109  				CallId:               1,
   110  				SequenceIdWithinCall: 0,
   111  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
   112  				Logger:               binlogpb.GrpcLogEntry_LOGGER_SERVER,
   113  				Payload: &binlogpb.GrpcLogEntry_ClientHeader{
   114  					ClientHeader: &binlogpb.ClientHeader{
   115  						Metadata:   &binlogpb.Metadata{},
   116  						MethodName: "testservice/testmethod",
   117  						Authority:  "test.service.io",
   118  					},
   119  				},
   120  				PayloadTruncated: false,
   121  			},
   122  		},
   123  		{
   124  			config: &ServerHeader{
   125  				OnClientSide: true,
   126  				Header: map[string][]string{
   127  					"a": {"b", "bb"},
   128  				},
   129  				PeerAddr: tcpAddr6,
   130  			},
   131  			want: &binlogpb.GrpcLogEntry{
   132  				Timestamp:            nil,
   133  				CallId:               1,
   134  				SequenceIdWithinCall: 0,
   135  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
   136  				Logger:               binlogpb.GrpcLogEntry_LOGGER_CLIENT,
   137  				Payload: &binlogpb.GrpcLogEntry_ServerHeader{
   138  					ServerHeader: &binlogpb.ServerHeader{
   139  						Metadata: &binlogpb.Metadata{
   140  							Entry: []*binlogpb.MetadataEntry{
   141  								{Key: "a", Value: []byte{'b'}},
   142  								{Key: "a", Value: []byte{'b', 'b'}},
   143  							},
   144  						},
   145  					},
   146  				},
   147  				PayloadTruncated: false,
   148  				Peer: &binlogpb.Address{
   149  					Type:    binlogpb.Address_TYPE_IPV6,
   150  					Address: addr6,
   151  					IpPort:  uint32(port6),
   152  				},
   153  			},
   154  		},
   155  		{
   156  			config: &ClientMessage{
   157  				OnClientSide: true,
   158  				Message:      testProtoMsg,
   159  			},
   160  			want: &binlogpb.GrpcLogEntry{
   161  				Timestamp:            nil,
   162  				CallId:               1,
   163  				SequenceIdWithinCall: 0,
   164  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE,
   165  				Logger:               binlogpb.GrpcLogEntry_LOGGER_CLIENT,
   166  				Payload: &binlogpb.GrpcLogEntry_Message{
   167  					Message: &binlogpb.Message{
   168  						Length: uint32(len(testProtoBytes)),
   169  						Data:   testProtoBytes,
   170  					},
   171  				},
   172  				PayloadTruncated: false,
   173  				Peer:             nil,
   174  			},
   175  		},
   176  		{
   177  			config: &ServerMessage{
   178  				OnClientSide: false,
   179  				Message:      testProtoMsg,
   180  			},
   181  			want: &binlogpb.GrpcLogEntry{
   182  				Timestamp:            nil,
   183  				CallId:               1,
   184  				SequenceIdWithinCall: 0,
   185  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE,
   186  				Logger:               binlogpb.GrpcLogEntry_LOGGER_SERVER,
   187  				Payload: &binlogpb.GrpcLogEntry_Message{
   188  					Message: &binlogpb.Message{
   189  						Length: uint32(len(testProtoBytes)),
   190  						Data:   testProtoBytes,
   191  					},
   192  				},
   193  				PayloadTruncated: false,
   194  				Peer:             nil,
   195  			},
   196  		},
   197  		{
   198  			config: &ClientHalfClose{
   199  				OnClientSide: false,
   200  			},
   201  			want: &binlogpb.GrpcLogEntry{
   202  				Timestamp:            nil,
   203  				CallId:               1,
   204  				SequenceIdWithinCall: 0,
   205  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE,
   206  				Logger:               binlogpb.GrpcLogEntry_LOGGER_SERVER,
   207  				Payload:              nil,
   208  				PayloadTruncated:     false,
   209  				Peer:                 nil,
   210  			},
   211  		},
   212  		{
   213  			config: &ServerTrailer{
   214  				OnClientSide: true,
   215  				Err:          status.Errorf(codes.Unavailable, "test"),
   216  				PeerAddr:     tcpAddr,
   217  			},
   218  			want: &binlogpb.GrpcLogEntry{
   219  				Timestamp:            nil,
   220  				CallId:               1,
   221  				SequenceIdWithinCall: 0,
   222  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
   223  				Logger:               binlogpb.GrpcLogEntry_LOGGER_CLIENT,
   224  				Payload: &binlogpb.GrpcLogEntry_Trailer{
   225  					Trailer: &binlogpb.Trailer{
   226  						Metadata:      &binlogpb.Metadata{},
   227  						StatusCode:    uint32(codes.Unavailable),
   228  						StatusMessage: "test",
   229  						StatusDetails: nil,
   230  					},
   231  				},
   232  				PayloadTruncated: false,
   233  				Peer: &binlogpb.Address{
   234  					Type:    binlogpb.Address_TYPE_IPV4,
   235  					Address: addr,
   236  					IpPort:  uint32(port),
   237  				},
   238  			},
   239  		},
   240  		{ // Err is nil, Log OK status.
   241  			config: &ServerTrailer{
   242  				OnClientSide: true,
   243  			},
   244  			want: &binlogpb.GrpcLogEntry{
   245  				Timestamp:            nil,
   246  				CallId:               1,
   247  				SequenceIdWithinCall: 0,
   248  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
   249  				Logger:               binlogpb.GrpcLogEntry_LOGGER_CLIENT,
   250  				Payload: &binlogpb.GrpcLogEntry_Trailer{
   251  					Trailer: &binlogpb.Trailer{
   252  						Metadata:      &binlogpb.Metadata{},
   253  						StatusCode:    uint32(codes.OK),
   254  						StatusMessage: "",
   255  						StatusDetails: nil,
   256  					},
   257  				},
   258  				PayloadTruncated: false,
   259  				Peer:             nil,
   260  			},
   261  		},
   262  		{
   263  			config: &Cancel{
   264  				OnClientSide: true,
   265  			},
   266  			want: &binlogpb.GrpcLogEntry{
   267  				Timestamp:            nil,
   268  				CallId:               1,
   269  				SequenceIdWithinCall: 0,
   270  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_CANCEL,
   271  				Logger:               binlogpb.GrpcLogEntry_LOGGER_CLIENT,
   272  				Payload:              nil,
   273  				PayloadTruncated:     false,
   274  				Peer:                 nil,
   275  			},
   276  		},
   277  
   278  		// gRPC headers should be omitted.
   279  		{
   280  			config: &ClientHeader{
   281  				OnClientSide: false,
   282  				Header: map[string][]string{
   283  					"grpc-reserved": {"to be omitted"},
   284  					":authority":    {"to be omitted"},
   285  					"a":             {"b", "bb"},
   286  				},
   287  			},
   288  			want: &binlogpb.GrpcLogEntry{
   289  				Timestamp:            nil,
   290  				CallId:               1,
   291  				SequenceIdWithinCall: 0,
   292  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
   293  				Logger:               binlogpb.GrpcLogEntry_LOGGER_SERVER,
   294  				Payload: &binlogpb.GrpcLogEntry_ClientHeader{
   295  					ClientHeader: &binlogpb.ClientHeader{
   296  						Metadata: &binlogpb.Metadata{
   297  							Entry: []*binlogpb.MetadataEntry{
   298  								{Key: "a", Value: []byte{'b'}},
   299  								{Key: "a", Value: []byte{'b', 'b'}},
   300  							},
   301  						},
   302  					},
   303  				},
   304  				PayloadTruncated: false,
   305  			},
   306  		},
   307  		{
   308  			config: &ServerHeader{
   309  				OnClientSide: true,
   310  				Header: map[string][]string{
   311  					"grpc-reserved": {"to be omitted"},
   312  					":authority":    {"to be omitted"},
   313  					"a":             {"b", "bb"},
   314  				},
   315  			},
   316  			want: &binlogpb.GrpcLogEntry{
   317  				Timestamp:            nil,
   318  				CallId:               1,
   319  				SequenceIdWithinCall: 0,
   320  				Type:                 binlogpb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
   321  				Logger:               binlogpb.GrpcLogEntry_LOGGER_CLIENT,
   322  				Payload: &binlogpb.GrpcLogEntry_ServerHeader{
   323  					ServerHeader: &binlogpb.ServerHeader{
   324  						Metadata: &binlogpb.Metadata{
   325  							Entry: []*binlogpb.MetadataEntry{
   326  								{Key: "a", Value: []byte{'b'}},
   327  								{Key: "a", Value: []byte{'b', 'b'}},
   328  							},
   329  						},
   330  					},
   331  				},
   332  				PayloadTruncated: false,
   333  			},
   334  		},
   335  	}
   336  	for i, tc := range testCases {
   337  		buf.Reset()
   338  		tc.want.SequenceIdWithinCall = uint64(i + 1)
   339  		ml.Log(context.Background(), tc.config)
   340  		inSink := new(binlogpb.GrpcLogEntry)
   341  		if err := proto.Unmarshal(buf.Bytes()[4:], inSink); err != nil {
   342  			t.Errorf("failed to unmarshal bytes in sink to proto: %v", err)
   343  			continue
   344  		}
   345  		inSink.Timestamp = nil // Strip timestamp before comparing.
   346  		if !proto.Equal(inSink, tc.want) {
   347  			t.Errorf("Log(%+v), in sink: %+v, want %+v", tc.config, inSink, tc.want)
   348  		}
   349  	}
   350  }
   351  
   352  func (s) TestTruncateMetadataNotTruncated(t *testing.T) {
   353  	testCases := []struct {
   354  		ml   *TruncatingMethodLogger
   355  		mpPb *binlogpb.Metadata
   356  	}{
   357  		{
   358  			ml: NewTruncatingMethodLogger(maxUInt, maxUInt),
   359  			mpPb: &binlogpb.Metadata{
   360  				Entry: []*binlogpb.MetadataEntry{
   361  					{Key: "", Value: []byte{1}},
   362  				},
   363  			},
   364  		},
   365  		{
   366  			ml: NewTruncatingMethodLogger(2, maxUInt),
   367  			mpPb: &binlogpb.Metadata{
   368  				Entry: []*binlogpb.MetadataEntry{
   369  					{Key: "", Value: []byte{1}},
   370  				},
   371  			},
   372  		},
   373  		{
   374  			ml: NewTruncatingMethodLogger(1, maxUInt),
   375  			mpPb: &binlogpb.Metadata{
   376  				Entry: []*binlogpb.MetadataEntry{
   377  					{Key: "", Value: nil},
   378  				},
   379  			},
   380  		},
   381  		{
   382  			ml: NewTruncatingMethodLogger(2, maxUInt),
   383  			mpPb: &binlogpb.Metadata{
   384  				Entry: []*binlogpb.MetadataEntry{
   385  					{Key: "", Value: []byte{1, 1}},
   386  				},
   387  			},
   388  		},
   389  		{
   390  			ml: NewTruncatingMethodLogger(2, maxUInt),
   391  			mpPb: &binlogpb.Metadata{
   392  				Entry: []*binlogpb.MetadataEntry{
   393  					{Key: "", Value: []byte{1}},
   394  					{Key: "", Value: []byte{1}},
   395  				},
   396  			},
   397  		},
   398  		// "grpc-trace-bin" is kept in log but not counted towards the size
   399  		// limit.
   400  		{
   401  			ml: NewTruncatingMethodLogger(1, maxUInt),
   402  			mpPb: &binlogpb.Metadata{
   403  				Entry: []*binlogpb.MetadataEntry{
   404  					{Key: "", Value: []byte{1}},
   405  					{Key: "grpc-trace-bin", Value: []byte("some.trace.key")},
   406  				},
   407  			},
   408  		},
   409  	}
   410  
   411  	for i, tc := range testCases {
   412  		truncated := tc.ml.truncateMetadata(tc.mpPb)
   413  		if truncated {
   414  			t.Errorf("test case %v, returned truncated, want not truncated", i)
   415  		}
   416  	}
   417  }
   418  
   419  func (s) TestTruncateMetadataTruncated(t *testing.T) {
   420  	testCases := []struct {
   421  		ml   *TruncatingMethodLogger
   422  		mpPb *binlogpb.Metadata
   423  
   424  		entryLen int
   425  	}{
   426  		{
   427  			ml: NewTruncatingMethodLogger(2, maxUInt),
   428  			mpPb: &binlogpb.Metadata{
   429  				Entry: []*binlogpb.MetadataEntry{
   430  					{Key: "", Value: []byte{1, 1, 1}},
   431  				},
   432  			},
   433  			entryLen: 0,
   434  		},
   435  		{
   436  			ml: NewTruncatingMethodLogger(2, maxUInt),
   437  			mpPb: &binlogpb.Metadata{
   438  				Entry: []*binlogpb.MetadataEntry{
   439  					{Key: "", Value: []byte{1}},
   440  					{Key: "", Value: []byte{1}},
   441  					{Key: "", Value: []byte{1}},
   442  				},
   443  			},
   444  			entryLen: 2,
   445  		},
   446  		{
   447  			ml: NewTruncatingMethodLogger(2, maxUInt),
   448  			mpPb: &binlogpb.Metadata{
   449  				Entry: []*binlogpb.MetadataEntry{
   450  					{Key: "", Value: []byte{1, 1}},
   451  					{Key: "", Value: []byte{1}},
   452  				},
   453  			},
   454  			entryLen: 1,
   455  		},
   456  		{
   457  			ml: NewTruncatingMethodLogger(2, maxUInt),
   458  			mpPb: &binlogpb.Metadata{
   459  				Entry: []*binlogpb.MetadataEntry{
   460  					{Key: "", Value: []byte{1}},
   461  					{Key: "", Value: []byte{1, 1}},
   462  				},
   463  			},
   464  			entryLen: 1,
   465  		},
   466  	}
   467  
   468  	for i, tc := range testCases {
   469  		truncated := tc.ml.truncateMetadata(tc.mpPb)
   470  		if !truncated {
   471  			t.Errorf("test case %v, returned not truncated, want truncated", i)
   472  			continue
   473  		}
   474  		if len(tc.mpPb.Entry) != tc.entryLen {
   475  			t.Errorf("test case %v, entry length: %v, want: %v", i, len(tc.mpPb.Entry), tc.entryLen)
   476  		}
   477  	}
   478  }
   479  
   480  func (s) TestTruncateMessageNotTruncated(t *testing.T) {
   481  	testCases := []struct {
   482  		ml    *TruncatingMethodLogger
   483  		msgPb *binlogpb.Message
   484  	}{
   485  		{
   486  			ml: NewTruncatingMethodLogger(maxUInt, maxUInt),
   487  			msgPb: &binlogpb.Message{
   488  				Data: []byte{1},
   489  			},
   490  		},
   491  		{
   492  			ml: NewTruncatingMethodLogger(maxUInt, 3),
   493  			msgPb: &binlogpb.Message{
   494  				Data: []byte{1, 1},
   495  			},
   496  		},
   497  		{
   498  			ml: NewTruncatingMethodLogger(maxUInt, 2),
   499  			msgPb: &binlogpb.Message{
   500  				Data: []byte{1, 1},
   501  			},
   502  		},
   503  	}
   504  
   505  	for i, tc := range testCases {
   506  		truncated := tc.ml.truncateMessage(tc.msgPb)
   507  		if truncated {
   508  			t.Errorf("test case %v, returned truncated, want not truncated", i)
   509  		}
   510  	}
   511  }
   512  
   513  func (s) TestTruncateMessageTruncated(t *testing.T) {
   514  	testCases := []struct {
   515  		ml    *TruncatingMethodLogger
   516  		msgPb *binlogpb.Message
   517  
   518  		oldLength uint32
   519  	}{
   520  		{
   521  			ml: NewTruncatingMethodLogger(maxUInt, 2),
   522  			msgPb: &binlogpb.Message{
   523  				Length: 3,
   524  				Data:   []byte{1, 1, 1},
   525  			},
   526  			oldLength: 3,
   527  		},
   528  	}
   529  
   530  	for i, tc := range testCases {
   531  		truncated := tc.ml.truncateMessage(tc.msgPb)
   532  		if !truncated {
   533  			t.Errorf("test case %v, returned not truncated, want truncated", i)
   534  			continue
   535  		}
   536  		if len(tc.msgPb.Data) != int(tc.ml.messageMaxLen) {
   537  			t.Errorf("test case %v, message length: %v, want: %v", i, len(tc.msgPb.Data), tc.ml.messageMaxLen)
   538  		}
   539  		if tc.msgPb.Length != tc.oldLength {
   540  			t.Errorf("test case %v, message.Length field: %v, want: %v", i, tc.msgPb.Length, tc.oldLength)
   541  		}
   542  	}
   543  }
   544  

View as plain text