Compare commits

...

7 Commits

Author SHA1 Message Date
wb-wzc505509 ecd18128a4 add slice validate 2020-08-21 17:24:40 +08:00
wb-wzc505509 f16f5b0116 improve test 2020-07-16 15:41:36 +08:00
wb-wzc505509 8291a17aca validate support null param 2020-07-09 13:52:35 +08:00
wb-wzc505509 7ad16974b6 validate support null param 2020-07-09 13:39:59 +08:00
wb-wzc505509 8918f7f891 fix timeout error 2020-07-08 17:20:59 +08:00
wb-wzc505509 29a23a75ba add recover 2020-07-06 10:25:53 +08:00
wb-wzc505509 d9c5d0857b add SetErrMsg to SDKError 2020-07-03 13:21:52 +08:00
2 changed files with 170 additions and 42 deletions
+100 -30
View File
@@ -39,7 +39,7 @@ var basicTypes = []string{
}
// Verify whether the parameters meet the requirements
var validateParams = []string{"require", "pattern", "maxLength", "minLength", "maximum", "minimum"}
var validateParams = []string{"require", "pattern", "maxLength", "minLength", "maximum", "minimum", "maxItems", "minItems"}
// CastError is used for cast type fails
type CastError struct {
@@ -71,6 +71,8 @@ type SDKError struct {
Code *string
Message *string
Data *string
Stack *string
errMsg *string
}
// RuntimeObject is used for converting http configuration
@@ -178,6 +180,20 @@ func NewSDKError(obj map[string]interface{}) *SDKError {
return err
}
// Set ErrMsg by msg
func (err *SDKError) SetErrMsg(msg string) {
err.errMsg = String(msg)
}
func (err *SDKError) Error() string {
if err.errMsg == nil {
str := fmt.Sprintf("SDKError:\n Code: %s\n Message: %s\n Data: %s\n",
StringValue(err.Code), StringValue(err.Message), StringValue(err.Data))
err.SetErrMsg(str)
}
return StringValue(err.errMsg)
}
// Return message of CastError
func (err *CastError) Error() string {
return StringValue(err.Message)
@@ -190,6 +206,14 @@ func Convert(in interface{}, out interface{}) error {
return err
}
// Convert is use convert map[string]interface object to struct
func Recover(in interface{}) error {
if in == nil {
return nil
}
return errors.New(fmt.Sprint(in))
}
// ReadBody is used read response body
func (response *Response) ReadBody() (body []byte, err error) {
defer response.Body.Close()
@@ -283,7 +307,7 @@ func DoRequest(request *Request, requestRuntime map[string]interface{}) (respons
if err != nil {
return nil, err
}
client.httpClient.Timeout = time.Duration(IntValue(runtimeObject.ConnectTimeout)) * time.Second
client.httpClient.Timeout = time.Duration(IntValue(runtimeObject.ReadTimeout)) * time.Millisecond
client.httpClient.Transport = trans
client.ifInit = true
}
@@ -367,7 +391,7 @@ func getHttpTransport(req *Request, runtime *RuntimeObject) (*http.Transport, er
}
dialer, err := proxy.SOCKS5(strings.ToLower(StringValue(runtime.Socks5NetWork)), socks5Proxy.String(), auth,
&net.Dialer{
Timeout: time.Duration(IntValue(runtime.ConnectTimeout)) * time.Second,
Timeout: time.Duration(IntValue(runtime.ConnectTimeout)) * time.Millisecond,
DualStack: true,
LocalAddr: getLocalAddr(StringValue(runtime.LocalAddr), IntValue(req.Port)),
})
@@ -495,11 +519,6 @@ func setDialContext(runtime *RuntimeObject, port int) func(cxt context.Context,
}
}
func (err *SDKError) Error() string {
return fmt.Sprintf("SDKError:\n Code: %s\n Message: %s\n Data: %s\n",
StringValue(err.Code), StringValue(err.Message), StringValue(err.Data))
}
func ToObject(obj interface{}) map[string]interface{} {
result := make(map[string]interface{})
byt, _ := json.Marshal(obj)
@@ -759,8 +778,14 @@ func Sleep(backoffTime *int) {
}
func Validate(params interface{}) error {
requestValue := reflect.ValueOf(params).Elem()
err := validate(requestValue)
if params == nil {
return nil
}
requestValue := reflect.ValueOf(params)
if requestValue.IsNil() {
return nil
}
err := validate(requestValue.Elem())
return err
}
@@ -795,12 +820,12 @@ func validateParam(field reflect.StructField, valueField reflect.Value, tagName
}
}
if strings.HasPrefix(field.Type.String(), "[]") { // Verify the parameters of the array type
err := validateSlice(valueField, containsTag, tag, tagName)
err := validateSlice(field, valueField, containsTag, tag, tagName)
if err != nil {
return err
}
} else if valueField.Kind() == reflect.Ptr { // Determines whether it is a pointer object
err := validatePtr(valueField, containsTag, tag, tagName)
err := validatePtr(field, valueField, containsTag, tag, tagName)
if err != nil {
return err
}
@@ -808,12 +833,28 @@ func validateParam(field reflect.StructField, valueField reflect.Value, tagName
return nil
}
func validateSlice(valueField reflect.Value, containsregexpTag bool, tag, tagName string) error {
func validateSlice(field reflect.StructField, valueField reflect.Value, containsregexpTag bool, tag, tagName string) error {
if valueField.IsValid() && !valueField.IsNil() { // Determines whether the parameter has a value
if containsregexpTag {
if tagName == "maxItems" {
err := checkMaxItems(field, valueField, tag)
if err != nil {
return err
}
}
if tagName == "minItems" {
err := checkMinItems(field, valueField, tag)
if err != nil {
return err
}
}
}
for m := 0; m < valueField.Len(); m++ {
elementValue := valueField.Index(m)
if elementValue.Type().Kind() == reflect.Ptr { // Determines whether the child elements of an array are of a basic type
err := validatePtr(elementValue, containsregexpTag, tag, tagName)
err := validatePtr(field, elementValue, containsregexpTag, tag, tagName)
if err != nil {
return err
}
@@ -823,43 +864,42 @@ func validateSlice(valueField reflect.Value, containsregexpTag bool, tag, tagNam
return nil
}
func validatePtr(elementValue reflect.Value, containsregexpTag bool, tag, tagName string) error {
func validatePtr(field reflect.StructField, elementValue reflect.Value, containsregexpTag bool, tag, tagName string) error {
if elementValue.IsNil() {
return nil
}
if isFilterType(elementValue.Elem().Type().String(), basicTypes) {
if containsregexpTag {
if tagName == "pattern" {
err := checkPattern(elementValue.Elem(), tag)
err := checkPattern(field, elementValue.Elem(), tag)
if err != nil {
return err
}
}
if tagName == "maxLength" {
err := checkMaxLength(elementValue.Elem(), tag)
err := checkMaxLength(field, elementValue.Elem(), tag)
if err != nil {
return err
}
}
if tagName == "minLength" {
err := checkMinLength(elementValue.Elem(), tag)
err := checkMinLength(field, elementValue.Elem(), tag)
if err != nil {
return err
}
}
if tagName == "maximum" {
err := checkMaximum(elementValue.Elem(), tag)
err := checkMaximum(field, elementValue.Elem(), tag)
if err != nil {
return err
}
}
if tagName == "minimum" {
err := checkMinimum(elementValue.Elem(), tag)
err := checkMinimum(field, elementValue.Elem(), tag)
if err != nil {
return err
}
@@ -884,7 +924,7 @@ func checkRequire(field reflect.StructField, valueField reflect.Value) error {
return errors.New(name + " should be setted")
}
func checkPattern(valueField reflect.Value, tag string) error {
func checkPattern(field reflect.StructField, valueField reflect.Value, tag string) error {
if valueField.IsValid() && valueField.String() != "" {
value := valueField.String()
if match, _ := regexp.MatchString(tag, value); !match { // Determines whether the parameter value satisfies the regular expression or not, and throws an error
@@ -894,7 +934,37 @@ func checkPattern(valueField reflect.Value, tag string) error {
return nil
}
func checkMaxLength(valueField reflect.Value, tag string) error {
func checkMaxItems(field reflect.StructField, valueField reflect.Value, tag string) error {
if valueField.IsValid() && valueField.String() != "" {
maxItems, err := strconv.Atoi(tag)
if err != nil {
return err
}
length := valueField.Len()
if maxItems < length {
errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxItems)
return errors.New(errMsg)
}
}
return nil
}
func checkMinItems(field reflect.StructField, valueField reflect.Value, tag string) error {
if valueField.IsValid() {
minItems, err := strconv.Atoi(tag)
if err != nil {
return err
}
length := valueField.Len()
if minItems > length {
errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minItems)
return errors.New(errMsg)
}
}
return nil
}
func checkMaxLength(field reflect.StructField, valueField reflect.Value, tag string) error {
if valueField.IsValid() && valueField.String() != "" {
maxLength, err := strconv.Atoi(tag)
if err != nil {
@@ -905,14 +975,14 @@ func checkMaxLength(valueField reflect.Value, tag string) error {
length = strings.Count(valueField.String(), "") - 1
}
if maxLength < length {
errMsg := fmt.Sprintf("Length of %s is more than %d", valueField.String(), maxLength)
errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxLength)
return errors.New(errMsg)
}
}
return nil
}
func checkMinLength(valueField reflect.Value, tag string) error {
func checkMinLength(field reflect.StructField, valueField reflect.Value, tag string) error {
if valueField.IsValid() {
minLength, err := strconv.Atoi(tag)
if err != nil {
@@ -923,14 +993,14 @@ func checkMinLength(valueField reflect.Value, tag string) error {
length = strings.Count(valueField.String(), "") - 1
}
if minLength > length {
errMsg := fmt.Sprintf("Length of %s is less than %d", valueField.String(), minLength)
errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minLength)
return errors.New(errMsg)
}
}
return nil
}
func checkMaximum(valueField reflect.Value, tag string) error {
func checkMaximum(field reflect.StructField, valueField reflect.Value, tag string) error {
if valueField.IsValid() && valueField.String() != "" {
maximum, err := strconv.ParseFloat(tag, 64)
if err != nil {
@@ -942,14 +1012,14 @@ func checkMaximum(valueField reflect.Value, tag string) error {
return err
}
if maximum < num {
errMsg := fmt.Sprintf("%f is greater than %f", num, maximum)
errMsg := fmt.Sprintf("The size of %s is %f which is greater than %f", field.Name, num, maximum)
return errors.New(errMsg)
}
}
return nil
}
func checkMinimum(valueField reflect.Value, tag string) error {
func checkMinimum(field reflect.StructField, valueField reflect.Value, tag string) error {
if valueField.IsValid() && valueField.String() != "" {
minimum, err := strconv.ParseFloat(tag, 64)
if err != nil {
@@ -962,7 +1032,7 @@ func checkMinimum(valueField reflect.Value, tag string) error {
return err
}
if minimum > num {
errMsg := fmt.Sprintf("%f is less than %f", num, minimum)
errMsg := fmt.Sprintf("The size of %s is %f which is less than %f", field.Name, num, minimum)
return errors.New(errMsg)
}
}
+70 -12
View File
@@ -55,7 +55,9 @@ type validateTest struct {
MinLength *errMinLength `json:"MinLength,omitempty"`
Maximum *errMaximum `json:"Maximum,omitempty"`
Minimum *errMinimum `json:"Minimum,omitempty"`
List []*string `json:"list,omitempty" pattern:"^[a-d]*$" maxLength:"4"`
MaxItems *errMaxItems `json:"MaxItems,omitempty"`
MinItems *errMinItems `json:"MinItems,omitempty"`
List []*string `json:"list,omitempty" pattern:"^[a-d]*$" minItems:"2" maxItems:"3" maxLength:"4"`
}
type errMaxLength struct {
@@ -74,6 +76,14 @@ type errMinimum struct {
Num *int `json:"num" minimum:"a"`
}
type errMaxItems struct {
NumMax []*int `json:"num" maxItems:"a"`
}
type errMinItems struct {
NumMin []*int `json:"num" minItems:"a"`
}
type Progresstest struct {
}
@@ -158,6 +168,9 @@ func TestSDKError(t *testing.T) {
})
utils.AssertNotNil(t, err)
utils.AssertEqual(t, "SDKError:\n Code: code\n Message: message\n Data: {\"hostId\":\"github.com/alibabacloud/tea\",\"httpCode\":\"404\",\"requestId\":\"dfadfa32cgfdcasd4313\"}\n", err.Error())
err.SetErrMsg("test")
utils.AssertEqual(t, "test", err.Error())
}
func TestSDKErrorCode404(t *testing.T) {
@@ -370,6 +383,7 @@ func Test_DoRequest(t *testing.T) {
request.Pathname = String("?log")
request.Headers["tea"] = String("")
request.Headers["content-length"] = nil
runtimeObj["httpsProxy"] = "http://someuser:somepassword@ecs.aliyun.com"
resp, err = DoRequest(request, runtimeObj)
utils.AssertNil(t, resp)
@@ -551,6 +565,27 @@ func Test_Validate(t *testing.T) {
}
err := Validate(config)
utils.AssertNil(t, err)
err = Validate(new(validateTest))
utils.AssertEqual(t, err.Error(), "num1 should be setted")
var tmp *validateTest
err = Validate(tmp)
utils.AssertNil(t, err)
err = Validate(nil)
utils.AssertNil(t, err)
}
func Test_Recover(t *testing.T) {
err := Recover(nil)
utils.AssertNil(t, err)
defer func() {
if r := Recover(recover()); r != nil {
utils.AssertEqual(t, "test", r.Error())
}
}()
panic("test")
}
func Test_validate(t *testing.T) {
@@ -564,7 +599,6 @@ func Test_validate(t *testing.T) {
Num1: &num,
Num2: &num,
Str: &str0,
List: []*string{&str0},
}
err = validate(reflect.ValueOf(val))
@@ -572,7 +606,7 @@ func Test_validate(t *testing.T) {
val.Str = &str1
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, "Length of abcddd is more than 4", err.Error())
utils.AssertEqual(t, "The length of Str is 6 which is more than 4", err.Error())
val.Num1 = nil
err = validate(reflect.ValueOf(val))
@@ -584,13 +618,35 @@ func Test_validate(t *testing.T) {
val.Num1 = &num
val.Str = &str0
val.List = []*string{&str1}
val.List = []*string{&str0}
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, "Length of abcddd is more than 4", err.Error())
utils.AssertEqual(t, "The length of List is 1 which is less than 2", err.Error())
val.Str = nil
val.List = []*string{&str0, &str1}
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, "Length of abcddd is more than 4", err.Error())
utils.AssertEqual(t, "The length of List is 6 which is more than 4", err.Error())
val.List = []*string{&str0, &str0}
err = validate(reflect.ValueOf(val))
utils.AssertNil(t, err)
val.MaxItems = &errMaxItems{
NumMax: []*int{&num},
}
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, `strconv.Atoi: parsing "a": invalid syntax`, err.Error())
val.MaxItems = nil
val.MinItems = &errMinItems{
NumMin: []*int{&num},
}
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, `strconv.Atoi: parsing "a": invalid syntax`, err.Error())
val.MinItems = nil
val.List = []*string{&str0, &str0, &str0, &str0}
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, "The length of List is 4 which is more than 3", err.Error())
str2 := "test"
val.Str = &str2
@@ -605,6 +661,7 @@ func Test_validate(t *testing.T) {
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, `strconv.Atoi: parsing "a": invalid syntax`, err.Error())
val.List = nil
val.MaxLength = nil
val.MinLength = &errMinLength{
Num: &num,
@@ -612,6 +669,7 @@ func Test_validate(t *testing.T) {
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, `strconv.Atoi: parsing "a": invalid syntax`, err.Error())
val.Name2 = String("tea")
val.MinLength = nil
val.Maximum = &errMaximum{
Num: &num,
@@ -629,22 +687,22 @@ func Test_validate(t *testing.T) {
val.Minimum = nil
val.Num2 = Int(10)
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, `10.000000 is greater than 6.000000`, err.Error())
utils.AssertEqual(t, `The size of Num2 is 10.000000 which is greater than 6.000000`, err.Error())
val.Num2 = nil
val.Name1 = String("maxLengthTouch")
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, `Length of maxLengthTouch is more than 4`, err.Error())
utils.AssertEqual(t, `The length of Name1 is 14 which is more than 4`, err.Error())
val.Name1 = nil
val.Name2 = String("")
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, `Length of is less than 2`, err.Error())
utils.AssertEqual(t, `The length of Name2 is 0 which is less than 2`, err.Error())
val.Name2 = nil
val.Name2 = String("tea")
val.Num1 = Int(0)
err = validate(reflect.ValueOf(val))
utils.AssertEqual(t, `0.000000 is less than 2.000000`, err.Error())
utils.AssertEqual(t, `The size of Num1 is 0.000000 which is less than 2.000000`, err.Error())
}
func Test_Prettify(t *testing.T) {