gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/channelz/service/service_sktopt_test.go (about)

     1  //go:build linux && (386 || amd64)
     2  // +build linux
     3  // +build 386 amd64
     4  
     5  /*
     6   *
     7   * Copyright 2018 gRPC authors.
     8   *
     9   * Licensed under the Apache License, Version 2.0 (the "License");
    10   * you may not use this file except in compliance with the License.
    11   * You may obtain a copy of the License at
    12   *
    13   *     http://www.apache.org/licenses/LICENSE-2.0
    14   *
    15   * Unless required by applicable law or agreed to in writing, software
    16   * distributed under the License is distributed on an "AS IS" BASIS,
    17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    18   * See the License for the specific language governing permissions and
    19   * limitations under the License.
    20   *
    21   */
    22  
    23  // SocketOptions is only supported on linux system. The functions defined in
    24  // this file are to parse the socket option field and the test is specifically
    25  // to verify the behavior of socket option parsing.
    26  
    27  package service
    28  
    29  import (
    30  	"context"
    31  	"reflect"
    32  	"strconv"
    33  	"testing"
    34  
    35  	channelzpb "gitee.com/ks-custle/core-gm/grpc/channelz/grpc_channelz_v1"
    36  	"gitee.com/ks-custle/core-gm/grpc/internal/channelz"
    37  	"github.com/golang/protobuf/ptypes"
    38  	durpb "github.com/golang/protobuf/ptypes/duration"
    39  	"golang.org/x/sys/unix"
    40  )
    41  
    42  func init() {
    43  	// Assign protoToSocketOption to protoToSocketOpt in order to enable socket option
    44  	// data conversion from proto message to channelz defined struct.
    45  	protoToSocketOpt = protoToSocketOption
    46  }
    47  
    48  func convertToDuration(d *durpb.Duration) (sec int64, usec int64) {
    49  	if d != nil {
    50  		if dur, err := ptypes.Duration(d); err == nil {
    51  			sec = int64(int64(dur) / 1e9)
    52  			usec = (int64(dur) - sec*1e9) / 1e3
    53  		}
    54  	}
    55  	return
    56  }
    57  
    58  func protoToLinger(protoLinger *channelzpb.SocketOptionLinger) *unix.Linger {
    59  	linger := &unix.Linger{}
    60  	if protoLinger.GetActive() {
    61  		linger.Onoff = 1
    62  	}
    63  	lv, _ := convertToDuration(protoLinger.GetDuration())
    64  	linger.Linger = int32(lv)
    65  	return linger
    66  }
    67  
    68  func protoToSocketOption(skopts []*channelzpb.SocketOption) *channelz.SocketOptionData {
    69  	skdata := &channelz.SocketOptionData{}
    70  	for _, opt := range skopts {
    71  		switch opt.GetName() {
    72  		case "SO_LINGER":
    73  			protoLinger := &channelzpb.SocketOptionLinger{}
    74  			err := ptypes.UnmarshalAny(opt.GetAdditional(), protoLinger)
    75  			if err == nil {
    76  				skdata.Linger = protoToLinger(protoLinger)
    77  			}
    78  		case "SO_RCVTIMEO":
    79  			protoTimeout := &channelzpb.SocketOptionTimeout{}
    80  			err := ptypes.UnmarshalAny(opt.GetAdditional(), protoTimeout)
    81  			if err == nil {
    82  				skdata.RecvTimeout = protoToTime(protoTimeout)
    83  			}
    84  		case "SO_SNDTIMEO":
    85  			protoTimeout := &channelzpb.SocketOptionTimeout{}
    86  			err := ptypes.UnmarshalAny(opt.GetAdditional(), protoTimeout)
    87  			if err == nil {
    88  				skdata.SendTimeout = protoToTime(protoTimeout)
    89  			}
    90  		case "TCP_INFO":
    91  			tcpi := &channelzpb.SocketOptionTcpInfo{}
    92  			err := ptypes.UnmarshalAny(opt.GetAdditional(), tcpi)
    93  			if err == nil {
    94  				skdata.TCPInfo = &unix.TCPInfo{
    95  					State:          uint8(tcpi.TcpiState),
    96  					Ca_state:       uint8(tcpi.TcpiCaState),
    97  					Retransmits:    uint8(tcpi.TcpiRetransmits),
    98  					Probes:         uint8(tcpi.TcpiProbes),
    99  					Backoff:        uint8(tcpi.TcpiBackoff),
   100  					Options:        uint8(tcpi.TcpiOptions),
   101  					Rto:            tcpi.TcpiRto,
   102  					Ato:            tcpi.TcpiAto,
   103  					Snd_mss:        tcpi.TcpiSndMss,
   104  					Rcv_mss:        tcpi.TcpiRcvMss,
   105  					Unacked:        tcpi.TcpiUnacked,
   106  					Sacked:         tcpi.TcpiSacked,
   107  					Lost:           tcpi.TcpiLost,
   108  					Retrans:        tcpi.TcpiRetrans,
   109  					Fackets:        tcpi.TcpiFackets,
   110  					Last_data_sent: tcpi.TcpiLastDataSent,
   111  					Last_ack_sent:  tcpi.TcpiLastAckSent,
   112  					Last_data_recv: tcpi.TcpiLastDataRecv,
   113  					Last_ack_recv:  tcpi.TcpiLastAckRecv,
   114  					Pmtu:           tcpi.TcpiPmtu,
   115  					Rcv_ssthresh:   tcpi.TcpiRcvSsthresh,
   116  					Rtt:            tcpi.TcpiRtt,
   117  					Rttvar:         tcpi.TcpiRttvar,
   118  					Snd_ssthresh:   tcpi.TcpiSndSsthresh,
   119  					Snd_cwnd:       tcpi.TcpiSndCwnd,
   120  					Advmss:         tcpi.TcpiAdvmss,
   121  					Reordering:     tcpi.TcpiReordering}
   122  			}
   123  		}
   124  	}
   125  	return skdata
   126  }
   127  
   128  func (s) TestGetSocketOptions(t *testing.T) {
   129  	czCleanup := channelz.NewChannelzStorage()
   130  	defer cleanupWrapper(czCleanup, t)
   131  	ss := []*dummySocket{
   132  		{
   133  			socketOptions: &channelz.SocketOptionData{
   134  				Linger:      &unix.Linger{Onoff: 1, Linger: 2},
   135  				RecvTimeout: &unix.Timeval{Sec: 10, Usec: 1},
   136  				SendTimeout: &unix.Timeval{},
   137  				TCPInfo:     &unix.TCPInfo{State: 1},
   138  			},
   139  		},
   140  	}
   141  	svr := newCZServer()
   142  	ids := make([]int64, len(ss))
   143  	svrID := channelz.RegisterServer(&dummyServer{}, "")
   144  	defer channelz.RemoveEntry(svrID)
   145  	for i, s := range ss {
   146  		ids[i] = channelz.RegisterNormalSocket(s, svrID, strconv.Itoa(i))
   147  		defer channelz.RemoveEntry(ids[i])
   148  	}
   149  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   150  	defer cancel()
   151  	for i, s := range ss {
   152  		resp, _ := svr.GetSocket(ctx, &channelzpb.GetSocketRequest{SocketId: ids[i]})
   153  		metrics := resp.GetSocket()
   154  		if !reflect.DeepEqual(metrics.GetRef(), &channelzpb.SocketRef{SocketId: ids[i], Name: strconv.Itoa(i)}) || !reflect.DeepEqual(socketProtoToStruct(metrics), s) {
   155  			t.Fatalf("resp.GetSocket() want: metrics.GetRef() = %#v and %#v, got: metrics.GetRef() = %#v and %#v", &channelzpb.SocketRef{SocketId: ids[i], Name: strconv.Itoa(i)}, s, metrics.GetRef(), socketProtoToStruct(metrics))
   156  		}
   157  	}
   158  }