github.com/cloudreve/Cloudreve/v3@v3.0.0-20240224133659-3edb00a6484c/pkg/request/request_test.go (about)

     1  package request
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"github.com/cloudreve/Cloudreve/v3/pkg/cache"
     7  	"io"
     8  	"io/ioutil"
     9  	"net/http"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/cloudreve/Cloudreve/v3/pkg/auth"
    15  	"github.com/stretchr/testify/assert"
    16  	testMock "github.com/stretchr/testify/mock"
    17  )
    18  
    19  type ClientMock struct {
    20  	testMock.Mock
    21  }
    22  
    23  func (m ClientMock) Request(method, target string, body io.Reader, opts ...Option) *Response {
    24  	args := m.Called(method, target, body, opts)
    25  	return args.Get(0).(*Response)
    26  }
    27  
    28  func TestWithTimeout(t *testing.T) {
    29  	asserts := assert.New(t)
    30  	options := newDefaultOption()
    31  	WithTimeout(time.Duration(5) * time.Second).apply(options)
    32  	asserts.Equal(time.Duration(5)*time.Second, options.timeout)
    33  }
    34  
    35  func TestWithHeader(t *testing.T) {
    36  	asserts := assert.New(t)
    37  	options := newDefaultOption()
    38  	WithHeader(map[string][]string{"Origin": []string{"123"}}).apply(options)
    39  	asserts.Equal(http.Header{"Origin": []string{"123"}}, options.header)
    40  }
    41  
    42  func TestWithContentLength(t *testing.T) {
    43  	asserts := assert.New(t)
    44  	options := newDefaultOption()
    45  	WithContentLength(10).apply(options)
    46  	asserts.EqualValues(10, options.contentLength)
    47  }
    48  
    49  func TestWithContext(t *testing.T) {
    50  	asserts := assert.New(t)
    51  	options := newDefaultOption()
    52  	WithContext(context.Background()).apply(options)
    53  	asserts.NotNil(options.ctx)
    54  }
    55  
    56  func TestHTTPClient_Request(t *testing.T) {
    57  	asserts := assert.New(t)
    58  	client := NewClient(WithSlaveMeta("test"))
    59  
    60  	// 正常
    61  	{
    62  		resp := client.Request(
    63  			"POST",
    64  			"/test",
    65  			strings.NewReader(""),
    66  			WithContentLength(0),
    67  			WithEndpoint("http://cloudreveisnotexist.com"),
    68  			WithTimeout(time.Duration(1)*time.Microsecond),
    69  			WithCredential(auth.HMACAuth{SecretKey: []byte("123")}, 10),
    70  			WithoutHeader([]string{"origin", "origin"}),
    71  		)
    72  		asserts.Error(resp.Err)
    73  		asserts.Nil(resp.Response)
    74  	}
    75  
    76  	// 正常 带有ctx
    77  	{
    78  		resp := client.Request(
    79  			"GET",
    80  			"http://cloudreveisnotexist.com",
    81  			strings.NewReader(""),
    82  			WithTimeout(time.Duration(1)*time.Microsecond),
    83  			WithCredential(auth.HMACAuth{SecretKey: []byte("123")}, 10),
    84  			WithContext(context.Background()),
    85  			WithoutHeader([]string{"s s", "s s"}),
    86  			WithMasterMeta(),
    87  		)
    88  		asserts.Error(resp.Err)
    89  		asserts.Nil(resp.Response)
    90  	}
    91  
    92  }
    93  
    94  func TestResponse_GetResponse(t *testing.T) {
    95  	asserts := assert.New(t)
    96  
    97  	// 直接返回错误
    98  	{
    99  		resp := Response{
   100  			Err: errors.New("error"),
   101  		}
   102  		content, err := resp.GetResponse()
   103  		asserts.Empty(content)
   104  		asserts.Error(err)
   105  	}
   106  
   107  	// 正常
   108  	{
   109  		resp := Response{
   110  			Response: &http.Response{Body: ioutil.NopCloser(strings.NewReader("123"))},
   111  		}
   112  		content, err := resp.GetResponse()
   113  		asserts.Equal("123", content)
   114  		asserts.NoError(err)
   115  	}
   116  }
   117  
   118  func TestResponse_CheckHTTPResponse(t *testing.T) {
   119  	asserts := assert.New(t)
   120  
   121  	// 直接返回错误
   122  	{
   123  		resp := Response{
   124  			Err: errors.New("error"),
   125  		}
   126  		res := resp.CheckHTTPResponse(200)
   127  		asserts.Error(res.Err)
   128  	}
   129  
   130  	// 404错误
   131  	{
   132  		resp := Response{
   133  			Response: &http.Response{StatusCode: 404},
   134  		}
   135  		res := resp.CheckHTTPResponse(200)
   136  		asserts.Error(res.Err)
   137  	}
   138  
   139  	// 通过
   140  	{
   141  		resp := Response{
   142  			Response: &http.Response{StatusCode: 200},
   143  		}
   144  		res := resp.CheckHTTPResponse(200)
   145  		asserts.NoError(res.Err)
   146  	}
   147  }
   148  
   149  func TestResponse_GetRSCloser(t *testing.T) {
   150  	asserts := assert.New(t)
   151  
   152  	// 直接返回错误
   153  	{
   154  		resp := Response{
   155  			Err: errors.New("error"),
   156  		}
   157  		res, err := resp.GetRSCloser()
   158  		asserts.Error(err)
   159  		asserts.Nil(res)
   160  	}
   161  
   162  	// 正常
   163  	{
   164  		resp := Response{
   165  			Response: &http.Response{ContentLength: 3, Body: ioutil.NopCloser(strings.NewReader("123"))},
   166  		}
   167  		res, err := resp.GetRSCloser()
   168  		asserts.NoError(err)
   169  		content, err := ioutil.ReadAll(res)
   170  		asserts.NoError(err)
   171  		asserts.Equal("123", string(content))
   172  		offset, err := res.Seek(0, 0)
   173  		asserts.NoError(err)
   174  		asserts.Equal(int64(0), offset)
   175  		offset, err = res.Seek(0, 2)
   176  		asserts.NoError(err)
   177  		asserts.Equal(int64(3), offset)
   178  		_, err = res.Seek(1, 2)
   179  		asserts.Error(err)
   180  		asserts.NoError(res.Close())
   181  	}
   182  
   183  }
   184  
   185  func TestResponse_DecodeResponse(t *testing.T) {
   186  	asserts := assert.New(t)
   187  
   188  	// 直接返回错误
   189  	{
   190  		resp := Response{Err: errors.New("error")}
   191  		response, err := resp.DecodeResponse()
   192  		asserts.Error(err)
   193  		asserts.Nil(response)
   194  	}
   195  
   196  	// 无法解析响应
   197  	{
   198  		resp := Response{
   199  			Response: &http.Response{
   200  				Body: ioutil.NopCloser(strings.NewReader("test")),
   201  			},
   202  		}
   203  		response, err := resp.DecodeResponse()
   204  		asserts.Error(err)
   205  		asserts.Nil(response)
   206  	}
   207  
   208  	// 成功
   209  	{
   210  		resp := Response{
   211  			Response: &http.Response{
   212  				Body: ioutil.NopCloser(strings.NewReader("{\"code\":0}")),
   213  			},
   214  		}
   215  		response, err := resp.DecodeResponse()
   216  		asserts.NoError(err)
   217  		asserts.NotNil(response)
   218  		asserts.Equal(0, response.Code)
   219  	}
   220  }
   221  
   222  func TestNopRSCloser_SetFirstFakeChunk(t *testing.T) {
   223  	asserts := assert.New(t)
   224  	rsc := NopRSCloser{
   225  		status: &rscStatus{},
   226  	}
   227  	rsc.SetFirstFakeChunk()
   228  	asserts.True(rsc.status.IgnoreFirst)
   229  
   230  	rsc.SetContentLength(20)
   231  	asserts.EqualValues(20, rsc.status.Size)
   232  }
   233  
   234  func TestBlackHole(t *testing.T) {
   235  	a := assert.New(t)
   236  	cache.Set("setting_reset_after_upload_failed", "true", 0)
   237  	a.NotPanics(func() {
   238  		BlackHole(strings.NewReader("TestBlackHole"))
   239  	})
   240  }
   241  
   242  func TestHTTPClient_TPSLimit(t *testing.T) {
   243  	a := assert.New(t)
   244  	client := NewClient()
   245  
   246  	finished := make(chan struct{})
   247  	go func() {
   248  		client.Request(
   249  			"POST",
   250  			"/test",
   251  			strings.NewReader(""),
   252  			WithTPSLimit("TestHTTPClient_TPSLimit", 1, 1),
   253  		)
   254  		close(finished)
   255  	}()
   256  	select {
   257  	case <-finished:
   258  	case <-time.After(10 * time.Second):
   259  		a.Fail("Request should be finished instantly.")
   260  	}
   261  
   262  	finished = make(chan struct{})
   263  	go func() {
   264  		client.Request(
   265  			"POST",
   266  			"/test",
   267  			strings.NewReader(""),
   268  			WithTPSLimit("TestHTTPClient_TPSLimit", 1, 1),
   269  		)
   270  		close(finished)
   271  	}()
   272  	select {
   273  	case <-finished:
   274  	case <-time.After(2 * time.Second):
   275  		a.Fail("Request should be finished in 1 second.")
   276  	}
   277  
   278  }