Skip to content
This repository has been archived by the owner on Dec 8, 2022. It is now read-only.

fix slice tag bug AND add chinese name #141

Merged
merged 20 commits into from Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 44 additions & 3 deletions faker.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Copy link
Owner

@bxcodec bxcodec Jan 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remind me again, what are these priority tags used for?

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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -653,7 +673,28 @@ func decodeTags(typ reflect.Type, i int) structTag {
uni = true
continue
}
res = append(res, tag)
// res = append(res, tag)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove if not used anymore

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{
Expand Down
55 changes: 49 additions & 6 deletions faker_test.go
Expand Up @@ -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
Expand Down Expand Up @@ -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"`
Expand Down Expand Up @@ -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")
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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")
}
Expand Down
108 changes: 108 additions & 0 deletions person.go
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
}
31 changes: 31 additions & 0 deletions person_test.go
Expand Up @@ -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) {
Expand All @@ -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)
}