github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans/netpoll/http_client_handler_test.go (about)

     1  /*
     2   * Copyright 2021 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package netpoll
    18  
    19  import (
    20  	"context"
    21  	"net/http"
    22  	"strings"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/cloudwego/netpoll"
    27  
    28  	"github.com/cloudwego/kitex/internal/mocks"
    29  	"github.com/cloudwego/kitex/internal/test"
    30  	"github.com/cloudwego/kitex/pkg/remote"
    31  	"github.com/cloudwego/kitex/pkg/remote/trans"
    32  	"github.com/cloudwego/kitex/pkg/rpcinfo"
    33  	"github.com/cloudwego/kitex/pkg/serviceinfo"
    34  )
    35  
    36  var (
    37  	cliTransHdlr     remote.ClientTransHandler
    38  	httpCilTransHdlr remote.ClientTransHandler
    39  	cilopt           *remote.ClientOption
    40  )
    41  
    42  func init() {
    43  	cilopt = &remote.ClientOption{
    44  		SvcInfo: mocks.ServiceInfo(),
    45  		Codec: &MockCodec{
    46  			EncodeFunc: nil,
    47  			DecodeFunc: nil,
    48  		},
    49  		Dialer: NewDialer(),
    50  	}
    51  
    52  	cliTransHdlr, _ = NewCliTransHandlerFactory().NewTransHandler(cilopt)
    53  	httpCilTransHdlr, _ = NewHTTPCliTransHandlerFactory().NewTransHandler(cilopt)
    54  }
    55  
    56  // TestHTTPWrite test http_client_handler Write return err
    57  func TestHTTPWrite(t *testing.T) {
    58  	// 1. prepare mock data
    59  	conn := &MockNetpollConn{}
    60  	rwTimeout := time.Second
    61  	cfg := rpcinfo.NewRPCConfig()
    62  	rpcinfo.AsMutableRPCConfig(cfg).SetReadWriteTimeout(rwTimeout)
    63  	to := rpcinfo.NewEndpointInfo("", "", nil, map[string]string{
    64  		rpcinfo.HTTPURL: "https://example.com",
    65  	})
    66  	ri := rpcinfo.NewRPCInfo(nil, to, nil, cfg, rpcinfo.NewRPCStats())
    67  	ctx := context.Background()
    68  	msg := remote.NewMessage(nil, mocks.ServiceInfo(), ri, remote.Reply, remote.Client)
    69  
    70  	// 2. test
    71  	ctx, err := httpCilTransHdlr.Write(ctx, conn, msg)
    72  	// check ctx/err not nil
    73  	test.Assert(t, ctx != nil)
    74  	test.Assert(t, err != nil)
    75  }
    76  
    77  // TestHTTPRead test http_client_handler Read return err
    78  func TestHTTPRead(t *testing.T) {
    79  	// 1. prepare mock data
    80  	rwTimeout := time.Second
    81  
    82  	var readTimeout time.Duration
    83  	var isReaderBufReleased bool
    84  	conn := &MockNetpollConn{
    85  		SetReadTimeoutFunc: func(timeout time.Duration) (e error) {
    86  			readTimeout = timeout
    87  			return nil
    88  		},
    89  		ReaderFunc: func() (r netpoll.Reader) {
    90  			reader := &MockNetpollReader{
    91  				ReleaseFunc: func() (err error) {
    92  					isReaderBufReleased = true
    93  					return nil
    94  				},
    95  			}
    96  			return reader
    97  		},
    98  	}
    99  
   100  	cfg := rpcinfo.NewRPCConfig()
   101  	rpcinfo.AsMutableRPCConfig(cfg).SetRPCTimeout(rwTimeout)
   102  	ri := rpcinfo.NewRPCInfo(nil, nil, nil, cfg, rpcinfo.NewRPCStats())
   103  	ctx := context.Background()
   104  	msg := remote.NewMessage(nil, mocks.ServiceInfo(), ri, remote.Reply, remote.Client)
   105  
   106  	// 2. test
   107  	ctx, err := httpCilTransHdlr.Read(ctx, conn, msg)
   108  	// check ctx/err not nil
   109  	test.Assert(t, ctx != nil)
   110  	test.Assert(t, err != nil)
   111  
   112  	rpcinfo.AsMutableRPCConfig(cfg).SetRPCTimeout(rwTimeout)
   113  	httpCilTransHdlr.OnError(ctx, err, conn)
   114  	test.Assert(t, readTimeout == trans.GetReadTimeout(ri.Config()))
   115  	test.Assert(t, isReaderBufReleased)
   116  }
   117  
   118  // TestHTTPPanicAfterRead test http_client_handler OnMessage success
   119  func TestHTTPOnMessage(t *testing.T) {
   120  	// 1. prepare mock data
   121  	svcInfo := mocks.ServiceInfo()
   122  	svcSearchMap := map[string]*serviceinfo.ServiceInfo{
   123  		remote.BuildMultiServiceKey(mocks.MockServiceName, mocks.MockMethod):          svcInfo,
   124  		remote.BuildMultiServiceKey(mocks.MockServiceName, mocks.MockExceptionMethod): svcInfo,
   125  		remote.BuildMultiServiceKey(mocks.MockServiceName, mocks.MockErrorMethod):     svcInfo,
   126  		remote.BuildMultiServiceKey(mocks.MockServiceName, mocks.MockOnewayMethod):    svcInfo,
   127  		mocks.MockMethod:          svcInfo,
   128  		mocks.MockExceptionMethod: svcInfo,
   129  		mocks.MockErrorMethod:     svcInfo,
   130  		mocks.MockOnewayMethod:    svcInfo,
   131  	}
   132  	ri := rpcinfo.NewRPCInfo(nil, nil, rpcinfo.NewInvocation(svcInfo.ServiceName, method), nil, rpcinfo.NewRPCStats())
   133  	ctx := rpcinfo.NewCtxWithRPCInfo(context.Background(), ri)
   134  	recvMsg := remote.NewMessageWithNewer(svcInfo, svcSearchMap, ri, remote.Call, remote.Server, false)
   135  	sendMsg := remote.NewMessage(svcInfo.MethodInfo(method).NewResult(), svcInfo, ri, remote.Reply, remote.Server)
   136  
   137  	// 2. test
   138  	_, err := httpCilTransHdlr.OnMessage(ctx, recvMsg, sendMsg)
   139  	test.Assert(t, err == nil, err)
   140  }
   141  
   142  // TestAddMetaInfo test http_client_handler addMetaInfo success
   143  func TestAddMetaInfo(t *testing.T) {
   144  	// 1. prepare mock data
   145  	cfg := rpcinfo.NewRPCConfig()
   146  	ri := rpcinfo.NewRPCInfo(nil, nil, nil, cfg, rpcinfo.NewRPCStats())
   147  	var req interface{}
   148  	msg := remote.NewMessage(req, mocks.ServiceInfo(), ri, remote.Reply, remote.Client)
   149  	h := http.Header{}
   150  
   151  	// 2. test
   152  	head, wantHead := "Head", "HTTP/1.1 200 OK"
   153  	msg.Tags()[rpcinfo.HTTPHeader] = http.Header{
   154  		head: []string{wantHead},
   155  	}
   156  	err := addMetaInfo(msg, h)
   157  	getHead := h.Get(head)
   158  	test.Assert(t, err == nil)
   159  	test.Assert(t, getHead == wantHead)
   160  }
   161  
   162  // TestReadLine test http_client_handler readLine success
   163  func TestReadLine(t *testing.T) {
   164  	// 1. prepare mock data
   165  	wantHead := "HTTP/1.1 200 OK"
   166  	body := "{\"code\":0,\"data\":[\"mobile\",\"xxxxxxx\"],\"msg\":\"ok\"}"
   167  	resp := []byte(wantHead + "\r\nDate: Thu, 16 Aug 2018 03:10:03 GMT\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n" + body)
   168  	reader := remote.NewReaderBuffer(resp)
   169  
   170  	// 2. test
   171  	getHead, _ := readLine(reader)
   172  	test.Assert(t, strings.Compare(string(getHead), wantHead) == 0)
   173  }
   174  
   175  // TestSkipToBody test http_client_handler skipToBody success
   176  func TestSkipToBody(t *testing.T) {
   177  	// 1. prepare mock data
   178  	head := "HTTP/1.1 200 OK"
   179  	wantBody := "{\"code\":0,\"data\":[\"mobile\",\"xxxxxxx\"],\"msg\":\"ok\"}"
   180  	resp := []byte(head + "\r\nDate: Thu, 16 Aug 2018 03:10:03 GMT\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n" + wantBody)
   181  	reader := remote.NewReaderBuffer(resp)
   182  
   183  	// 2. test
   184  	err := skipToBody(reader)
   185  	test.Assert(t, err == nil)
   186  
   187  	getBody, err := reader.ReadBinary(reader.ReadableLen())
   188  	test.Assert(t, err == nil)
   189  	test.Assert(t, strings.Compare(string(getBody), wantBody) == 0)
   190  }
   191  
   192  // TestParseHTTPResponseHead test http_client_handler parseHTTPResponseHead success
   193  func TestParseHTTPResponseHead(t *testing.T) {
   194  	// 1. prepare mock data
   195  	head := "HTTP/1.1 200 OK"
   196  
   197  	// 2. test
   198  	major, minor, statusCode, err := parseHTTPResponseHead(head)
   199  	test.Assert(t, err == nil)
   200  	test.Assert(t, !(major != 1 || minor != 1 || statusCode != 200))
   201  }
   202  
   203  // TestGetBodyBufReader test http_client_handler getBodyBufReader return  err
   204  func TestGetBodyBufReader(t *testing.T) {
   205  	// 1. prepare mock data
   206  	head := "HTTP/1.1 200 OK"
   207  	body := "{\"code\":0,\"data\":[\"mobile\",\"xxxxxxx\"],\"msg\":\"ok\"}"
   208  	resp := []byte(head + "\r\nDate: Thu, 16 Aug 2018 03:10:03 GMT\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n" + body)
   209  	reader := remote.NewReaderBuffer(resp)
   210  
   211  	// 2. test
   212  	_, err := getBodyBufReader(reader)
   213  	// check err not nil
   214  	test.Assert(t, err != nil)
   215  }