diff --git a/faker.go b/faker.go index 2248af6..d237a61 100644 --- a/faker.go +++ b/faker.go @@ -102,6 +102,9 @@ const ( FirstNameFemaleTag = "first_name_female" LastNameTag = "last_name" NAME = "name" + ChineseFirstNameTag = "chinese_first_name" + ChineseLastNameTag = "chinese_last_name" + ChineseNameTag = "chinese_name" GENDER = "gender" UnixTimeTag = "unix_time" DATE = "date" @@ -134,6 +137,15 @@ const ( //hyphen = "-" ) +// PriorityTags define the priority order of the tag +var PriorityTags = []string{ID, HyphenatedID, EmailTag, MacAddressTag, DomainNameTag, UserNameTag, URLTag, IPV4Tag, + IPV6Tag, PASSWORD, JWT, LATITUDE, LONGITUDE, CreditCardNumber, CreditCardType, PhoneNumber, TollFreeNumber, + E164PhoneNumberTag, TitleMaleTag, TitleFemaleTag, FirstNameTag, FirstNameMaleTag, FirstNameFemaleTag, LastNameTag, + NAME, ChineseFirstNameTag, ChineseLastNameTag, ChineseNameTag, GENDER, UnixTimeTag, DATE, TIME, MonthNameTag, + YEAR, DayOfWeekTag, DayOfMonthTag, TIMESTAMP, CENTURY, TIMEZONE, TimePeriodTag, WORD, SENTENCE, PARAGRAPH, + CurrencyTag, AmountTag, AmountWithCurrencyTag, SKIP, Length, SliceLength, Language, BoundaryStart, BoundaryEnd, ONEOF, +} + var defaultTag = map[string]string{ EmailTag: EmailTag, MacAddressTag: MacAddressTag, @@ -158,6 +170,9 @@ var defaultTag = map[string]string{ FirstNameFemaleTag: FirstNameFemaleTag, LastNameTag: LastNameTag, NAME: NAME, + ChineseFirstNameTag: ChineseFirstNameTag, + ChineseLastNameTag: ChineseLastNameTag, + ChineseNameTag: ChineseNameTag, GENDER: GENDER, UnixTimeTag: UnixTimeTag, DATE: DATE, @@ -208,6 +223,9 @@ var mapperTag = map[string]TaggedFunction{ FirstNameFemaleTag: GetPerson().FirstNameFemale, LastNameTag: GetPerson().LastName, NAME: GetPerson().Name, + ChineseFirstNameTag: GetPerson().ChineseFirstName, + ChineseLastNameTag: GetPerson().ChineseLastName, + ChineseNameTag: GetPerson().ChineseName, GENDER: GetPerson().Gender, UnixTimeTag: GetDateTimer().UnixTime, DATE: GetDateTimer().Date, @@ -422,7 +440,7 @@ func AddProvider(tag string, provider TaggedFunction) error { if _, ok := mapperTag[tag]; ok { return errors.New(ErrTagAlreadyExists) } - + PriorityTags = append(PriorityTags, tag) mapperTag[tag] = provider return nil @@ -640,11 +658,13 @@ func isZero(field reflect.Value) (bool, error) { } func decodeTags(typ reflect.Type, i int) structTag { - tags := strings.Split(typ.Field(i).Tag.Get(tagName), ",") + tagField := typ.Field(i).Tag.Get(tagName) + tags := strings.Split(tagField, ",") keepOriginal := false uni := false res := make([]string, 0) + pMap := make(map[string]string) for _, tag := range tags { if tag == keep { keepOriginal = true @@ -653,7 +673,28 @@ func decodeTags(typ reflect.Type, i int) structTag { uni = true continue } - res = append(res, tag) + // res = append(res, tag) + ptag := strings.ToLower(strings.Trim(strings.Split(tag, "=")[0], " ")) + pMap[ptag] = tag + ptag = strings.ToLower(strings.Trim(strings.Split(tag, ":")[0], " ")) + pMap[ptag] = tag + } + // Priority + for _, ptag := range PriorityTags { + if tag, ok := pMap[ptag]; ok { + if ptag == ONEOF { + res = append(res, tags...) + } else { + res = append(res, tag) + } + delete(pMap, ptag) + } + } + // custom,keep,unique + if len(res) < 1 { + if !keepOriginal && !uni { + res = append(res, tags...) + } } return structTag{ diff --git a/faker_test.go b/faker_test.go index c1b39bc..eef3064 100644 --- a/faker_test.go +++ b/faker_test.go @@ -33,6 +33,34 @@ var ( sliceLenIncorrectTags = [3]string{"slice_len=b", "slice_len=-1", "slice_len=-10"} ) +type Coupon struct { + ID int `json:"id" xorm:"id"` + BrokerCode string `json:"broker_code" xorm:"broker_code"` + IgetUID int `json:"iget_uid" xorm:"iget_uid"` + CreateTime string `json:"create_time" xorm:"create_time"` + CFirstName string `json:"chinese_first_name" faker:"chinese_first_name"` + CLsstName string `json:"chinese_last_name" faker:"chinese_last_name"` + CName string `json:"name" faker:"chinese_name"` + AdNames []string `json:"ad_name" xorm:"ad_name" faker:"slice_len=5,len=10"` // faker:"len=10,slice_len=5" + CdNames []string `json:"cd_name" xorm:"cd_name" faker:"len=10,slice_len=5"` // +} + +func TestPLen(t *testing.T) { + coupon := Coupon{} + err := FakeData(&coupon) + if err != nil { + t.Fatal(err) + return + } + if len(coupon.AdNames[0]) != 10 || len(coupon.AdNames) != 5 { + t.Fatal("slice len is error") + } + if len(coupon.CdNames[0]) != 10 || len(coupon.CdNames) != 5 { + t.Fatal("slice len is error") + } + t.Logf("%+v\n", coupon) +} + type SomeInt32 int32 type TArray [16]byte @@ -224,6 +252,9 @@ type TaggedStruct struct { FirstNameFemale string `faker:"first_name_female"` LastName string `faker:"last_name"` Name string `faker:"name"` + ChineseFirstName string `faker:"chinese_first_name"` + ChineseLastName string `faker:"chinese_last_name"` + ChineseName string `faker:"chinese_name"` UnixTime int64 `faker:"unix_time"` Date string `faker:"date"` Time string `faker:"time"` @@ -394,19 +425,28 @@ func TestSetDataIfArgumentNotHaveReflect(t *testing.T) { func TestSetDataErrorDataParseTagStringType(t *testing.T) { temp := &struct { - Test string `faker:"test"` + Test string `faker:"test_no_exist"` }{} - fmt.Printf("%+v ", temp) + for idx, tag := range PriorityTags { + if tag == "test_no_exist" { + PriorityTags[idx] = "" + } + } if err := FakeData(temp); err == nil { - t.Error("Exptected error Unsupported tag, but got nil") + t.Error("Exptected error Unsupported tag, but got nil", temp, err) } + } func TestSetDataErrorDataParseTagIntType(t *testing.T) { temp := &struct { - Test int `faker:"test"` + Test int `faker:"test_no_exist"` }{} - + for idx, tag := range PriorityTags { + if tag == "test_no_exist" { + PriorityTags[idx] = "" + } + } if err := FakeData(temp); err == nil { t.Error("Expected error Unsupported tag, but got nil") } @@ -1672,6 +1712,7 @@ func TestOneOfTag__BadInputsForFloats(t *testing.T) { err := FakeData(&a) if err == nil { t.Errorf("expected error, but got no error") + return } actual := err.Error() expected := ErrNotEnoughTagArguments @@ -1705,7 +1746,7 @@ func TestOneOfTag__BadInputsForFloats(t *testing.T) { a := CustomWrongFloat9{} err := FakeData(&a) if err == nil { - t.Fatal("expected error, but got no error") + t.Fatal("expected error, but got no error", err) } actual := err.Error() expected := ErrUnsupportedTagArguments @@ -1809,11 +1850,13 @@ func TestOneOfTag__BadInputsForInts(t *testing.T) { type CustomTypeInt64Wrong struct { Age int64 `faker:"oneof: 1_000_000, oops"` + Avg int64 `faker:"boundary_start=31, boundary_end=88"` } t.Run("should error for int64 with bad tag arguments", func(t *testing.T) { a := CustomTypeInt64Wrong{} err := FakeData(&a) + t.Log(a.Age, a.Avg) if err == nil { t.Errorf("expected error but got nil") } diff --git a/person.go b/person.go index 8123fa1..569bade 100644 --- a/person.go +++ b/person.go @@ -15,6 +15,9 @@ type Dowser interface { LastName(v reflect.Value) (interface{}, error) Name(v reflect.Value) (interface{}, error) Gender(v reflect.Value) (interface{}, error) + ChineseFirstName(v reflect.Value) (interface{}, error) + ChineseLastName(v reflect.Value) (interface{}, error) + ChineseName(v reflect.Value) (interface{}, error) } var person Dowser @@ -111,6 +114,60 @@ var randNameFlag int var genders = []string{"Male", "Female", "Prefer to skip"} +var chineseFirstNames = []string{ + "赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨", "朱", "秦", "尤", "许", + "何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏", "陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章", + "云", "苏", "潘", "葛", "奚", "范", "彭", "郎", "鲁", "韦", "昌", "马", "苗", "凤", "花", "方", "俞", "任", "袁", "柳", + "酆", "鲍", "史", "唐", "费", "廉", "岑", "薛", "雷", "贺", "倪", "汤", "滕", "殷", "罗", "毕", "郝", "邬", "安", "常", + "乐", "于", "时", "傅", "皮", "卞", "齐", "康", "伍", "余", "元", "卜", "顾", "孟", "平", "黄", "和", "穆", "萧", "尹", + "姚", "邵", "湛", "汪", "祁", "毛", "禹", "狄", "米", "贝", "明", "臧", "计", "伏", "成", "戴", "谈", "宋", "茅", "庞", + "熊", "纪", "舒", "屈", "项", "祝", "董", "梁", "杜", "阮", "蓝", "闵", "席", "季", "麻", "强", "贾", "路", "娄", "危", + "江", "童", "颜", "郭", "梅", "盛", "林", "刁", "钟", "徐", "邱", "骆", "高", "夏", "蔡", "田", "樊", "胡", "凌", "霍", + "虞", "万", "支", "柯", "昝", "管", "卢", "莫", "经", "房", "裘", "缪", "干", "解", "应", "宗", "丁", "宣", "贲", "邓", + "郁", "单", "杭", "洪", "包", "诸", "左", "石", "崔", "吉", "钮", "龚", "程", "嵇", "邢", "滑", "裴", "陆", "荣", "翁", + "荀", "羊", "於", "惠", "甄", "麴", "家", "封", "芮", "羿", "储", "靳", "汲", "邴", "糜", "松", "井", "段", "富", "巫", + "乌", "焦", "巴", "弓", "牧", "隗", "山", "谷", "车", "侯", "宓", "蓬", "全", "郗", "班", "仰", "秋", "仲", "伊", "宫", + "宁", "仇", "栾", "暴", "甘", "钭", "厉", "戎", "祖", "武", "符", "刘", "景", "詹", "束", "龙", "叶", "幸", "司", "韶", + "郜", "黎", "蓟", "薄", "印", "宿", "白", "怀", "蒲", "邰", "从", "鄂", "索", "咸", "籍", "赖", "卓", "蔺", "屠", "蒙", + "池", "乔", "阴", "郁", "胥", "能", "苍", "双", "闻", "莘", "党", "翟", "谭", "贡", "劳", "逄", "姬", "申", "扶", "堵", + "冉", "宰", "郦", "雍", "舄", "璩", "桑", "桂", "濮", "牛", "寿", "通", "边", "扈", "燕", "冀", "郏", "浦", "尚", "农", + "温", "别", "庄", "晏", "柴", "瞿", "阎", "充", "慕", "连", "茹", "习", "宦", "艾", "鱼", "容", "向", "古", "易", "慎", + "戈", "廖", "庾", "终", "暨", "居", "衡", "步", "都", "耿", "满", "弘", "匡", "国", "文", "寇", "广", "禄", "阙", "东", + "殴", "殳", "沃", "利", "蔚", "越", "夔", "隆", "师", "巩", "厍", "聂", "晁", "勾", "敖", "融", "冷", "訾", "辛", "阚", + "那", "简", "饶", "空", "曾", "毋", "沙", "乜", "养", "鞠", "须", "丰", "巢", "关", "蒯", "相", "查", "後", "荆", "红", + "游", "竺", "权", "逯", "盖", "益", "桓", "公", "司马", "上官", "欧阳", "夏侯", "诸葛", +} + +var chineseLastNames = []string{ + "澄邈", "德泽", "海超", "海阳", "海荣", "海逸", "海昌", "瀚钰", "瀚文", "涵亮", "涵煦", "明宇", + "涵衍", "浩皛", "浩波", "浩博", "浩初", "浩宕", "浩歌", "浩广", "浩邈", "浩气", "浩思", "浩言", + "鸿宝", "鸿波", "鸿博", "鸿才", "鸿畅", "鸿畴", "鸿达", "鸿德", "鸿飞", "鸿风", "鸿福", "鸿光", + "鸿晖", "鸿朗", "鸿文", "鸿轩", "鸿煊", "鸿骞", "鸿远", "鸿云", "鸿哲", "鸿祯", "鸿志", "鸿卓", + "嘉澍", "光济", "澎湃", "彭泽", "鹏池", "鹏海", "浦和", "浦泽", "瑞渊", "越泽", "博耘", "德运", + "辰宇", "辰皓", "辰钊", "辰铭", "辰锟", "辰阳", "辰韦", "辰良", "辰沛", "晨轩", "晨涛", "晨濡", + "晨潍", "鸿振", "吉星", "铭晨", "起运", "运凡", "运凯", "运鹏", "运浩", "运诚", "运良", "运鸿", + "运锋", "运盛", "运升", "运杰", "运珧", "运骏", "运凯", "运乾", "维运", "运晟", "运莱", "运华", + "耘豪", "星爵", "星腾", "星睿", "星泽", "星鹏", "星然", "震轩", "震博", "康震", "震博", "振强", + "振博", "振华", "振锐", "振凯", "振海", "振国", "振平", "昂然", "昂雄", "昂杰", "昂熙", "昌勋", + "昌盛", "昌淼", "昌茂", "昌黎", "昌燎", "昌翰", "晨朗", "德明", "德昌", "德曜", "范明", "飞昂", + "高旻", "晗日", "昊然", "昊天", "昊苍", "昊英", "昊宇", "昊嘉", "昊明", "昊伟", "昊硕", "昊磊", + "昊东", "鸿晖", "鸿朗", "华晖", "金鹏", "晋鹏", "敬曦", "景明", "景天", "景浩", "俊晖", "君昊", + "昆锐", "昆卉", "昆峰", "昆颉", "昆谊", "昆皓", "昆鹏", "昆明", "昆杰", "昆雄", "昆纶", "鹏涛", + "依秋", "依波", "香巧", "紫萱", "涵易", "忆之", "幻巧", "美倩", "安寒", "白亦", "惜玉", "碧春", + "怜雪", "听南", "念蕾", "紫夏", "凌旋", "芷梦", "凌寒", "梦竹", "千凡", "丹蓉", "慧贞", "思菱", + "平卉", "笑柳", "雪卉", "南蓉", "谷梦", "巧兰", "绿蝶", "飞荷", "佳蕊", "芷荷", "怀瑶", "慕易", + "若芹", "紫安", "曼冬", "寻巧", "雅昕", "尔槐", "以旋", "初夏", "依丝", "怜南", "傲菡", "谷蕊", + "笑槐", "飞兰", "笑卉", "迎荷", "佳音", "梦君", "妙绿", "觅雪", "寒安", "沛凝", "白容", "乐蓉", + "映安", "依云", "映冬", "凡雁", "梦秋", "梦凡", "秋巧", "若云", "元容", "怀蕾", "灵寒", "天薇", + "翠安", "乐琴", "宛南", "怀蕊", "白风", "访波", "亦凝", "易绿", "夜南", "曼凡", "亦巧", "青易", + "冰真", "白萱", "友安", "海之", "小蕊", "又琴", "天风", "若松", "盼菡", "秋荷", "香彤", "语梦", + "惜蕊", "迎彤", "沛白", "雁彬", "易蓉", "雪晴", "诗珊", "春冬", "晴钰", "冰绿", "半梅", "笑容", + "沛凝", "映秋", "盼烟", "晓凡", "涵雁", "问凝", "冬萱", "晓山", "雁蓉", "梦蕊", "山菡", "南莲", + "飞双", "凝丝", "思萱", "怀梦", "雨梅", "冷霜", "向松", "迎丝", "迎梅", "雅彤", "香薇", "以山", + "碧萱", "寒云", "向南", "书雁", "怀薇", "思菱", "忆文", "翠巧", "书文", "若山", "向秋", "凡白", + "绮烟", "从蕾", "天曼", "又亦", "从语", "绮彤", "之玉", "凡梅", "依琴", "沛槐", "又槐", "元绿", +} + // GetPerson returns a new Dowser interface of Person struct func GetPerson() Dowser { mu.Lock() @@ -269,3 +326,54 @@ func Gender() string { return p.gender() }).(string) } + +// ChineseFirstName returns a random chinese first name +func (p Person) ChineseFirstName(v reflect.Value) (interface{}, error) { + return p.chineseFirstName(), nil +} + +func (p Person) chineseFirstName() string { + return randomElementFromSliceString(chineseFirstNames) +} + +// ChineseFirstName get chinese first name +func ChineseFirstName() string { + return singleFakeData(ChineseFirstNameTag, func() interface{} { + p := Person{} + return p.chineseFirstName() + }).(string) +} + +// ChineseLastName returns a random chinese last name +func (p Person) ChineseLastName(v reflect.Value) (interface{}, error) { + return p.chineseLastName(), nil +} + +func (p Person) chineseLastName() string { + return randomElementFromSliceString(chineseLastNames) +} + +// ChineseLastName get chinese lsst name +func ChineseLastName() string { + return singleFakeData(ChineseLastNameTag, func() interface{} { + p := Person{} + return p.chineseLastName() + }).(string) +} + +// ChineseName returns a random nhinese name +func (p Person) ChineseName(v reflect.Value) (interface{}, error) { + return p.chineseName(), nil +} + +func (p Person) chineseName() string { + return fmt.Sprintf("%s%s", randomElementFromSliceString(chineseFirstNames), randomElementFromSliceString(chineseLastNames)) +} + +// ChineseName get chinese lsst name +func ChineseName() string { + return singleFakeData(ChineseNameTag, func() interface{} { + p := Person{} + return p.chineseName() + }).(string) +} diff --git a/person_test.go b/person_test.go index ce98a47..421ad37 100644 --- a/person_test.go +++ b/person_test.go @@ -147,6 +147,7 @@ func TestFakeNameFemale(t *testing.T) { if name == "" { t.Error("Expected from function name string get empty string") } + t.Log(name) } func TestFakeGender(t *testing.T) { @@ -165,3 +166,33 @@ func TestFakeGenderPublicFunction(t *testing.T) { t.Error("Expected value from variable genders in function Gender") } } + +func TestChineseFirstName(t *testing.T) { + firstname, err := GetPerson().ChineseFirstName(reflect.Value{}) + if err != nil { + t.Error("Expected not error, got err", err) + } + t.Log(firstname) + if !slice.Contains(chineseFirstNames, firstname.(string)) { + t.Error("Expected value from either chineseFirstNames in function ChineseFirstName") + } +} + +func TestChineseLastName(t *testing.T) { + firstname, err := GetPerson().ChineseLastName(reflect.Value{}) + if err != nil { + t.Error("Expected not error, got err", err) + } + t.Log(firstname) + if !slice.Contains(chineseLastNames, firstname.(string)) { + t.Error("Expected value from either chineseLastNames in function ChineseLastName") + } +} + +func TestChineseName(t *testing.T) { + firstname, err := GetPerson().ChineseName(reflect.Value{}) + if err != nil { + t.Error("Expected not error, got err", err) + } + t.Log(firstname) +}