github.com/artisanhe/tools@v1.0.1-0.20210607022958-19a8fef2eb04/httplib/trans_to_req_test.go (about)

     1  package httplib
     2  
     3  import (
     4  	"io/ioutil"
     5  	"mime/multipart"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  
    10  	"github.com/artisanhe/tools/courier/status_error"
    11  	"github.com/artisanhe/tools/courier/transport_http/transform"
    12  	"github.com/artisanhe/tools/httplib/testify"
    13  	"github.com/artisanhe/tools/timelib"
    14  	"github.com/artisanhe/tools/validate"
    15  )
    16  
    17  func v_ok(v interface{}) (bool, string) {
    18  	return v.(bool), "not ok"
    19  }
    20  
    21  func v_data(v interface{}) (bool, string) {
    22  	return v.(int32) == int32(1), "invalid data"
    23  }
    24  
    25  func init() {
    26  	validate.AddValidateFunc("v_ok", v_ok)
    27  	validate.AddValidateFunc("v_data", v_data)
    28  }
    29  
    30  type SimpleModel struct {
    31  	Data int32 `json:"data" validate:"v_data"`
    32  }
    33  
    34  type SimpleReqBodyBasic struct {
    35  	Name string `json:"name" default:""`
    36  	ID   uint64 `json:"id"`
    37  }
    38  
    39  type SimpleReqBody struct {
    40  	SimpleReqBodyBasic
    41  	Price  float32                 `json:"price" default:"0.1"`
    42  	OK     bool                    `json:"ok" validate:"v_ok" default:"false"`
    43  	Models []SimpleModel           `json:"models"`
    44  	V      int32                   `json:"v" default:"1"`
    45  	D      string                  `json:"d" default:"abc"`
    46  	G      uint32                  `json:"g" default:"2"`
    47  	Time   *timelib.MySQLTimestamp `json:"time" default:""`
    48  }
    49  
    50  type CommonReq struct {
    51  	ObjID   uint64 `name:"obj_id" in:"path"`
    52  	ObjName string `name:"obj_name" in:"query"`
    53  }
    54  
    55  type Ctx struct {
    56  	C string
    57  }
    58  
    59  type SimpleReq struct {
    60  	CommonReq
    61  	Ctx        *Ctx          `name:"ctx" in:"context"`
    62  	Body       SimpleReqBody `in:"body"`
    63  	ID         uint          `name:"id" in:"query"`
    64  	IntSlice   []uint64      `name:"int_slice" in:"query" default:""`
    65  	StrSlice   []string      `name:"str_slice" in:"query" default:""`
    66  	FloatSlice []float64     `name:"float_slice" in:"query" default:""`
    67  	ObjFloat   float32       `name:"obj_float" in:"path"`
    68  	ObjBool    bool          `name:"obj_bool" in:"path"`
    69  	HID        uint          `name:"h_id" in:"header" default:"0"`
    70  	HName      string        `name:"h_name" in:"header" default:""`
    71  	HFloat     float64       `name:"h_float" in:"header" default:"0.0"`
    72  	HBool      bool          `name:"h_bool" in:"header" default:"false"`
    73  }
    74  
    75  func TestTrans(t *testing.T) {
    76  	tt := assert.New(t)
    77  
    78  	expectedReq := SimpleReq{
    79  		Ctx: &Ctx{
    80  			C: "12123",
    81  		},
    82  		Body: SimpleReqBody{
    83  			SimpleReqBodyBasic: SimpleReqBodyBasic{
    84  				Name: "a",
    85  				ID:   1,
    86  			},
    87  			Price: 0.2,
    88  			OK:    true,
    89  			V:     1,
    90  			D:     "abc",
    91  			G:     2,
    92  			Models: []SimpleModel{
    93  				{
    94  					Data: 1,
    95  				},
    96  				{
    97  					Data: 1,
    98  				},
    99  				{
   100  					Data: 1,
   101  				},
   102  			},
   103  		},
   104  		CommonReq: CommonReq{
   105  			ObjID:   123,
   106  			ObjName: "aaa",
   107  		},
   108  		ID:         1,
   109  		IntSlice:   []uint64{1, 2, 3},
   110  		StrSlice:   []string{"a", "b", "c"},
   111  		FloatSlice: []float64{1.1, 1.2, 1.3},
   112  		ObjFloat:   12.2,
   113  		ObjBool:    true,
   114  		HID:        1,
   115  		HName:      "bc",
   116  		HBool:      true,
   117  		HFloat:     1.2,
   118  	}
   119  
   120  	{
   121  		c := testify.NewContext("POST", "/:obj_id/:obj_float/:obj_bool/", expectedReq)
   122  
   123  		req := SimpleReq{}
   124  		err := TransToReq(c, &req)
   125  		tt.NoError(err)
   126  		tt.Equal(expectedReq, req)
   127  	}
   128  
   129  	{
   130  		expectedReq.Body.ID = 0
   131  		expectedReq.Body.Models[1].Data = 2
   132  		expectedReq.ObjFloat = 0
   133  		expectedReq.Body.OK = false
   134  
   135  		c := testify.NewContext("POST", "/:obj_id/:obj_float/:obj_bool/", expectedReq)
   136  
   137  		req := SimpleReq{}
   138  		err := TransToReq(c, &req)
   139  
   140  		tt.Equal(status_error.ErrorFields{
   141  			{
   142  				Field: "id",
   143  				Msg:   "缺失必填字段",
   144  				In:    "body",
   145  			},
   146  			{
   147  				Field: "models[1].data",
   148  				Msg:   "invalid data",
   149  				In:    "body",
   150  			},
   151  			{
   152  				Field: "obj_float",
   153  				Msg:   "缺失必填字段",
   154  				In:    "path",
   155  			},
   156  			{
   157  				Field: "ok",
   158  				Msg:   "not ok",
   159  				In:    "body",
   160  			},
   161  		}, status_error.FromError(err).ErrorFields.Sort())
   162  	}
   163  }
   164  
   165  type Counter struct {
   166  	Total int32 `json:"total" in:"query" default:"0"`
   167  }
   168  
   169  func (c Counter) ValidateTotal() string {
   170  	if c.Total > 1 {
   171  		return "total too large"
   172  	}
   173  	return ""
   174  }
   175  
   176  type Req struct {
   177  	Counter
   178  	Pager
   179  	CreateTimeRange
   180  	Body Counter `in:"body"`
   181  }
   182  
   183  func (r Req) ValidateCreateStartTime() string {
   184  	return "CreateStartTime Error"
   185  }
   186  
   187  func TestTransToReqWithValidateHook(t *testing.T) {
   188  	tt := assert.New(t)
   189  
   190  	expectedReq := Req{}
   191  	expectedReq.Total = 4
   192  	expectedReq.Body.Total = 4
   193  	expectedReq.CreateStartTime, _ = timelib.ParseMySQLTimestampFromString("2017-01-01T20:00:00.000Z")
   194  	expectedReq.CreateEndTime, _ = timelib.ParseMySQLTimestampFromString("2017-01-01T09:00:00.000Z")
   195  
   196  	c := testify.NewContext("POST", "/", expectedReq)
   197  
   198  	reqWithReqGroupForValid := Req{}
   199  
   200  	err := TransToReq(c, &reqWithReqGroupForValid)
   201  
   202  	if err != nil {
   203  		tt.Equal(status_error.ErrorFields{
   204  			{
   205  				Field: "createEndTime",
   206  				Msg:   "终止时间不得小于开始时间",
   207  				In:    "query",
   208  			},
   209  			{
   210  				Field: "createStartTime",
   211  				Msg:   "CreateStartTime Error",
   212  				In:    "query",
   213  			},
   214  			{
   215  				Field: "total",
   216  				Msg:   "total too large",
   217  				In:    "query",
   218  			},
   219  			{
   220  				Field: "total",
   221  				Msg:   "total too large",
   222  				In:    "body",
   223  			},
   224  		}, status_error.FromError(err).ErrorFields.Sort())
   225  	}
   226  }
   227  
   228  type SingleFormFile struct {
   229  	FormData struct {
   230  		SingleFile *multipart.FileHeader `name:"singleFile"`
   231  	} `in:"formData,multipart"`
   232  }
   233  
   234  func TestTransSingleFormFile(t *testing.T) {
   235  	tt := assert.New(t)
   236  
   237  	req := SingleFormFile{}
   238  	req.FormData.SingleFile, _ = transform.NewFileHeader("singleFile", "SingleFile", []byte("1,2,3,4"))
   239  
   240  	c := testify.NewContext("POST", "/", req)
   241  	r := SingleFormFile{}
   242  	err := TransToReq(c, &r)
   243  	tt.Nil(err)
   244  
   245  	actualFile, _ := r.FormData.SingleFile.Open()
   246  	actualBytes, _ := ioutil.ReadAll(actualFile)
   247  	tt.Equal([]byte("1,2,3,4"), actualBytes)
   248  }
   249  
   250  type MultiFormFile struct {
   251  	FormData struct {
   252  		FirstFile  *multipart.FileHeader `json:"firstFile"`
   253  		SecondFile *multipart.FileHeader `json:"secondFile"`
   254  	} `in:"formData,multipart"`
   255  }
   256  
   257  func TestTransMultiFormFile(t *testing.T) {
   258  	tt := assert.New(t)
   259  
   260  	req := MultiFormFile{}
   261  	req.FormData.FirstFile, _ = transform.NewFileHeader("firstFile", "SingleFile", []byte("1"))
   262  	req.FormData.SecondFile, _ = transform.NewFileHeader("secondFile", "SecondFile", []byte("2"))
   263  
   264  	c := testify.NewContext("POST", "/", req)
   265  	r := MultiFormFile{}
   266  	err := TransToReq(c, &r)
   267  	tt.Nil(err)
   268  
   269  	{
   270  		actualFile, _ := r.FormData.FirstFile.Open()
   271  		actualBytes, _ := ioutil.ReadAll(actualFile)
   272  		tt.Equal([]byte("1"), actualBytes)
   273  	}
   274  
   275  	{
   276  		actualFile, _ := r.FormData.SecondFile.Open()
   277  		actualBytes, _ := ioutil.ReadAll(actualFile)
   278  		tt.Equal([]byte("2"), actualBytes)
   279  	}
   280  }