Browse Source

修改测试

yjp 1 năm trước cách đây
mục cha
commit
16a064ed9d

+ 31 - 0
framework/core/tag/rule/rule.go

@@ -0,0 +1,31 @@
+package rule
+
+import (
+	"git.sxidc.com/go-tools/utils/reflectutils"
+	"github.com/pkg/errors"
+	"reflect"
+)
+
+type OnParsedFieldTagFunc func(fieldName string, entityFieldElemValue reflect.Value, tag *Tag) error
+
+func UseTag(e any, onParsedFieldTagFunc OnParsedFieldTagFunc) error {
+	if e == nil {
+		return nil
+	}
+
+	entityValue := reflect.ValueOf(e)
+
+	// 类型校验
+	if !reflectutils.IsValueStructOrStructPointer(entityValue) {
+		return errors.New("参数不是结构或结构指针")
+	}
+
+	entityElemValue := reflectutils.PointerValueElem(entityValue)
+
+	err := parseTag(entityElemValue, onParsedFieldTagFunc)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}

+ 150 - 0
framework/core/tag/rule/tag.go

@@ -0,0 +1,150 @@
+package rule
+
+import (
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure/logger"
+	"git.sxidc.com/go-tools/utils/reflectutils"
+	"git.sxidc.com/go-tools/utils/strutils"
+	"github.com/pkg/errors"
+	"reflect"
+	"strings"
+)
+
+const (
+	TypeDefault = "default"
+	TypeString  = "string"
+	TypeTime    = "time"
+	TypeNumber  = "number"
+	TypeBool    = "bool"
+)
+
+func isDefaultType(typeStr string) bool {
+	return typeStr == TypeDefault
+}
+
+func isSupportedType(typeStr string) bool {
+	return typeStr == TypeString || typeStr == TypeTime || typeStr == TypeNumber || typeStr == TypeBool
+}
+
+const (
+	tagPartSeparator         = ";"
+	tagPartKeyValueSeparator = ":"
+)
+
+const (
+	tagKey  = "rule"
+	tagType = "type"
+)
+
+type Tag struct {
+	Type string
+}
+
+func parseTag(entityElemValue reflect.Value, onParsedFieldTagFunc OnParsedFieldTagFunc) error {
+	for i := 0; i < entityElemValue.NumField(); i++ {
+		entityField := entityElemValue.Type().Field(i)
+		entityFieldValue := entityElemValue.Field(i)
+
+		// 无效值,不进行映射
+		if !entityFieldValue.IsValid() {
+			continue
+		}
+
+		entityFieldElemValue := reflectutils.PointerValueElem(entityFieldValue)
+
+		tagStr, ok := entityField.Tag.Lookup(tagKey)
+		if !ok {
+			continue
+		}
+
+		tag, err := parseFieldTag(entityField, tagStr)
+		if err != nil {
+			return err
+		}
+
+		if tag == nil {
+			continue
+		}
+
+		// 结构类型的字段,解析结构内部
+		if entityFieldElemValue.Kind() == reflect.Struct &&
+			!reflectutils.IsValueTime(entityFieldElemValue) {
+			err := parseTag(entityFieldElemValue, onParsedFieldTagFunc)
+			if err != nil {
+				return err
+			}
+
+			continue
+		}
+
+		err = onParsedFieldTagFunc(entityField.Name, entityFieldElemValue, tag)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func parseFieldTag(field reflect.StructField, tagStr string) (*Tag, error) {
+	fieldType := reflectutils.PointerTypeElem(field.Type)
+	fieldKind := reflectutils.GroupTypeKind(fieldType)
+
+	var fieldTypeStr string
+
+	if fieldKind == reflect.Int64 || fieldKind == reflect.Uint64 || fieldKind == reflect.Float64 {
+		fieldTypeStr = TypeNumber
+	} else if fieldKind == reflect.String {
+		fieldTypeStr = TypeString
+	} else if fieldKind == reflect.Struct && fieldType.String() == "time.Time" {
+		fieldTypeStr = TypeTime
+	} else if fieldKind == reflect.Bool {
+		fieldTypeStr = TypeBool
+	} else {
+		return nil, errors.New("type支持的类型包括: string, number, time")
+	}
+
+	tag := &Tag{
+		Type: fieldTypeStr,
+	}
+
+	if strutils.IsStringEmpty(tagStr) {
+		return tag, nil
+	}
+
+	tagParts := strings.Split(tagStr, tagPartSeparator)
+	if tagParts != nil || len(tagParts) != 0 {
+		for _, tagPart := range tagParts {
+			tagPartKeyValue := strings.SplitN(strings.TrimSpace(tagPart), tagPartKeyValueSeparator, 2)
+			if tagPartKeyValue != nil && len(tagPartKeyValue) == 2 && strutils.IsStringNotEmpty(tagPartKeyValue[1]) {
+				tagPartKeyValue[1] = strings.Trim(tagPartKeyValue[1], "'")
+			}
+
+			if strutils.IsStringEmpty(tagPartKeyValue[0]) {
+				continue
+			}
+
+			switch tagPartKeyValue[0] {
+			case tagType:
+				if strutils.IsStringEmpty(tagPartKeyValue[1]) {
+					return nil, errors.New("type没有赋值字段类型")
+				}
+
+				if isDefaultType(tagPartKeyValue[1]) {
+					continue
+				}
+
+				if !isSupportedType(tagPartKeyValue[1]) {
+					return nil, errors.New("type支持的类型包括: string, number, time")
+				}
+
+				tag.Type = tagPartKeyValue[1]
+			default:
+				err := errors.New(tagKey + "不支持的tag: " + tagPartKeyValue[0])
+				logger.GetInstance().Error(err)
+				continue
+			}
+		}
+	}
+
+	return tag, nil
+}

+ 33 - 0
framework/core/tag/rule/usage.go

@@ -0,0 +1,33 @@
+package rule
+
+import (
+	"reflect"
+)
+
+type Field struct {
+	FieldName string
+	Type      string
+}
+
+func DefaultUsage(e any) ([]Field, error) {
+	fields := make([]Field, 0)
+
+	err := UseTag(e, defaultCallback(&fields))
+	if err != nil {
+		return nil, err
+	}
+
+	return fields, nil
+}
+
+func defaultCallback(fields *[]Field) OnParsedFieldTagFunc {
+	return func(fieldName string, entityFieldElemValue reflect.Value, tag *Tag) error {
+		field := Field{
+			FieldName: fieldName,
+			Type:      tag.Type,
+		}
+
+		*fields = append(*fields, field)
+		return nil
+	}
+}

+ 1 - 1
test/database_clause_test.go

@@ -16,7 +16,7 @@ FROM
   test.students
   JOIN test.classes ON classes.id = test.students.class_id
 WHERE
-  ("name" = ? AND "hobby" IN ?) AND ("age" = ? OR "gender" = ?)
+  (name = ? AND hobby IN ?) AND (age = ? OR gender = ?)
 ORDER BY name DESC
 LIMIT ? OFFSET ?`
 

+ 10 - 10
test/database_sql_test.go

@@ -25,15 +25,15 @@ func TestDatabaseSqlConditions(t *testing.T) {
 
 	exceptQueries := []string{
 		`name1 = ?`,
-		`"age" = ?`,
-		`"name2" LIKE ?`,
-		`"id1" IN ?`,
-		`"id2" NOT IN ?`,
-		`"id3" != ?`,
-		`"num1" < ?`,
-		`"num2" <= ?`,
-		`"num3" > ?`,
-		`"num4" >= ?`,
+		`age = ?`,
+		`name2 LIKE ?`,
+		`id1 IN ?`,
+		`id2 NOT IN ?`,
+		`id3 != ?`,
+		`num1 < ?`,
+		`num2 <= ?`,
+		`num3 > ?`,
+		`num4 >= ?`,
 	}
 
 	exceptArgs := []any{
@@ -49,7 +49,7 @@ func TestDatabaseSqlConditions(t *testing.T) {
 		40,
 	}
 
-	exceptAnd := `WHERE name1 = ? AND "age" = ? AND "name2" LIKE ? AND "id1" IN ? AND "id2" NOT IN ? AND "id3" != ? AND "num1" < ? AND "num2" <= ? AND "num3" > ? AND "num4" >= ?`
+	exceptAnd := `name1 = ? AND age = ? AND name2 LIKE ? AND id1 IN ? AND id2 NOT IN ? AND id3 != ? AND num1 < ? AND num2 <= ? AND num3 > ? AND num4 >= ?`
 
 	for i, query := range conditions.Queries() {
 		if exceptQueries[i] != query {

+ 459 - 0
test/rule_tag_test.go

@@ -0,0 +1,459 @@
+package test
+
+import (
+	"git.sxidc.com/go-framework/baize/framework/core/tag/rule"
+	"github.com/pkg/errors"
+	"reflect"
+	"testing"
+	"time"
+)
+
+type RuleTagStruct struct {
+	Ignore          string
+	StringValue     string    `rule:"type:default"`
+	IntValue        int       `rule:"type:default"`
+	Int8Value       int8      `rule:"type:default"`
+	Int16Value      int16     `rule:"type:default"`
+	Int32Value      int32     `rule:"type:default"`
+	Int64Value      int64     `rule:"type:default"`
+	UintValue       uint      `rule:"type:default"`
+	Uint8Value      uint8     `rule:"type:default"`
+	Uint16Value     uint16    `rule:"type:default"`
+	Uint32Value     uint32    `rule:"type:default"`
+	Uint64Value     uint64    `rule:"type:default"`
+	Float32Value    float32   `rule:"type:default"`
+	Float64Value    float64   `rule:"type:default"`
+	TimeValue       time.Time `rule:"type:default"`
+	BoolValue       bool      `rule:"type:default"`
+	TagStringValue  bool      `rule:"type:string"`
+	TagIntValue     string    `rule:"type:number"`
+	TagInt8Value    string    `rule:"type:number"`
+	TagInt16Value   string    `rule:"type:number"`
+	TagInt32Value   string    `rule:"type:number"`
+	TagInt64Value   string    `rule:"type:number"`
+	TagUintValue    string    `rule:"type:number"`
+	TagUint8Value   string    `rule:"type:number"`
+	TagUint16Value  string    `rule:"type:number"`
+	TagUint32Value  string    `rule:"type:number"`
+	TagUint64Value  string    `rule:"type:number"`
+	TagFloat32Value string    `rule:"type:number"`
+	TagFloat64Value string    `rule:"type:number"`
+	TagTimeValue    string    `rule:"type:time"`
+	TagBoolValue    string    `rule:"type:bool"`
+}
+
+func (s RuleTagStruct) checkFields(t *testing.T, fields []rule.Field) {
+	if len(fields) != reflect.TypeOf(s).NumField()-1 {
+		t.Fatalf("%+v\n", errors.Errorf("有字段没有被解析"))
+	}
+
+	for _, field := range fields {
+		if field.FieldName == "Ignore" && field.Type != "" {
+			t.Fatalf("%+v\n", errors.Errorf("忽略字段没有被忽略"))
+		}
+
+		switch field.FieldName {
+		case "StringValue":
+			if field.Type != "string" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "IntValue":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Int8Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Int16Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Int32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Int64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "UintValue":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Uint8Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Uint16Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Uint32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Uint64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Float32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Float64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TimeValue":
+			if field.Type != "time" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "BoolValue":
+			if field.Type != "bool" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagStringValue":
+			if field.Type != "string" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagIntValue":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagInt8Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagInt16Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagInt32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagInt64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagUintValue":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagUint8Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagUint16Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagUint32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagUint64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagFloat32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagFloat64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagTimeValue":
+			if field.Type != "time" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagBoolValue":
+			if field.Type != "bool" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		default:
+			t.Fatalf("%+v\n", errors.Errorf("未知的字段名: tag fieldName: %v", field.FieldName))
+		}
+	}
+}
+
+type RuleTagPointerFieldsStruct struct {
+	Ignore          *string
+	StringValue     *string    `rule:"type:default"`
+	IntValue        *int       `rule:"type:default"`
+	Int8Value       *int8      `rule:"type:default"`
+	Int16Value      *int16     `rule:"type:default"`
+	Int32Value      *int32     `rule:"type:default"`
+	Int64Value      *int64     `rule:"type:default"`
+	UintValue       *uint      `rule:"type:default"`
+	Uint8Value      *uint8     `rule:"type:default"`
+	Uint16Value     *uint16    `rule:"type:default"`
+	Uint32Value     *uint32    `rule:"type:default"`
+	Uint64Value     *uint64    `rule:"type:default"`
+	Float32Value    *float32   `rule:"type:default"`
+	Float64Value    *float64   `rule:"type:default"`
+	TimeValue       *time.Time `rule:"type:default"`
+	BoolValue       *bool      `rule:"type:default"`
+	TagStringValue  *bool      `rule:"type:string"`
+	TagIntValue     *string    `rule:"type:number"`
+	TagInt8Value    *string    `rule:"type:number"`
+	TagInt16Value   *string    `rule:"type:number"`
+	TagInt32Value   *string    `rule:"type:number"`
+	TagInt64Value   *string    `rule:"type:number"`
+	TagUintValue    *string    `rule:"type:number"`
+	TagUint8Value   *string    `rule:"type:number"`
+	TagUint16Value  *string    `rule:"type:number"`
+	TagUint32Value  *string    `rule:"type:number"`
+	TagUint64Value  *string    `rule:"type:number"`
+	TagFloat32Value *string    `rule:"type:number"`
+	TagFloat64Value *string    `rule:"type:number"`
+	TagTimeValue    *string    `rule:"type:time"`
+	TagBoolValue    *string    `rule:"type:bool"`
+}
+
+func (s RuleTagPointerFieldsStruct) checkFields(t *testing.T, fields []rule.Field) {
+	if len(fields) != reflect.TypeOf(s).NumField()-1 {
+		t.Fatalf("%+v\n", errors.Errorf("有字段没有被解析"))
+	}
+
+	for _, field := range fields {
+		if field.FieldName == "Ignore" && field.Type != "" {
+			t.Fatalf("%+v\n", errors.Errorf("忽略字段没有被忽略"))
+		}
+
+		switch field.FieldName {
+		case "StringValue":
+			if field.Type != "string" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "IntValue":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Int8Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Int16Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Int32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Int64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "UintValue":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Uint8Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Uint16Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Uint32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Uint64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Float32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "Float64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TimeValue":
+			if field.Type != "time" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "BoolValue":
+			if field.Type != "bool" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagStringValue":
+			if field.Type != "string" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagIntValue":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagInt8Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagInt16Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagInt32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagInt64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagUintValue":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagUint8Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagUint16Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagUint32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagUint64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagFloat32Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagFloat64Value":
+			if field.Type != "number" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagTimeValue":
+			if field.Type != "time" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		case "TagBoolValue":
+			if field.Type != "bool" {
+				t.Fatalf("%+v\n", errors.Errorf("列名解析测试错误: fieldName: %v, actual type: %v",
+					field.FieldName, field.Type))
+			}
+		default:
+			t.Fatalf("%+v\n", errors.Errorf("未知的字段名: tag fieldName: %v", field.FieldName))
+		}
+	}
+}
+
+func TestRuleTagDefaultUsage(t *testing.T) {
+	s := RuleTagStruct{}
+
+	sPointerFields := RuleTagPointerFieldsStruct{}
+
+	sPointerFieldsNil := RuleTagPointerFieldsStruct{}
+
+	fields, err := rule.DefaultUsage(s)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	s.checkFields(t, fields)
+
+	fields, err = rule.DefaultUsage(&s)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	s.checkFields(t, fields)
+
+	fields, err = rule.DefaultUsage(sPointerFields)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	sPointerFields.checkFields(t, fields)
+
+	fields, err = rule.DefaultUsage(&sPointerFields)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	sPointerFields.checkFields(t, fields)
+
+	fields, err = rule.DefaultUsage(sPointerFieldsNil)
+	if err != nil {
+		t.Fatalf("%+v\n", errors.Errorf("字段为nil"))
+	}
+
+	fields, err = rule.DefaultUsage(&sPointerFieldsNil)
+	if err != nil {
+		t.Fatalf("%+v\n", err)
+	}
+
+	sPointerFieldsNil.checkFields(t, fields)
+}