├── .github └── workflows │ └── go.yml ├── .gitignore ├── LICENSE ├── README.md ├── TODO.md ├── address.go ├── address_test.go ├── builder.go ├── builder_test.go ├── color.go ├── color_test.go ├── country.go ├── country_test.go ├── currency.go ├── currency_test.go ├── faker.go ├── faker_test.go ├── gender.go ├── gender_test.go ├── go.mod ├── go.sum ├── init.go ├── internet.go ├── internet_test.go ├── lang.go ├── lang_test.go ├── misc.go ├── misc_test.go ├── name.go ├── name_test.go ├── number.go ├── number_test.go ├── pool.go ├── pool_test.go ├── random.go ├── random_test.go ├── sentence.go ├── sentence_test.go ├── slice.go ├── slice_test.go ├── string.go ├── string_test.go ├── time.go ├── time_test.go ├── unique.go ├── unique_test.go ├── utils.go └── utils_test.go /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | test: 11 | strategy: 12 | matrix: 13 | go-version: ['1.15', '1.16', '1.17', '1.19', '1.21'] 14 | # os: [ubuntu-latest, macos-latest, windows-latest] 15 | runs-on: ubuntu-latest 16 | # runs-on: ${{ matrix.os }} 17 | steps: 18 | - uses: actions/checkout@master 19 | - uses: actions/setup-go@v2 20 | with: 21 | go-version: ${{ matrix.go-version }} 22 | - name: Build project 23 | run: go build -v . 24 | - name: Run tests 25 | run: go test -race -coverprofile=coverage.txt -covermode=atomic 26 | - name: Upload coverage to Codecov 27 | uses: codecov/codecov-action@v1 28 | with: 29 | file: ./coverage.txt 30 | 31 | golangci: 32 | name: golangci-lint 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: actions/checkout@master 36 | - name: Run golangci-lint 37 | uses: golangci/golangci-lint-action@v2 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .#* 3 | ._* 4 | .env 5 | .git 6 | .idea 7 | .project 8 | .DS_Store 9 | __* 10 | 11 | coverage.* 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright 2020 Enrico Pilotto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Faker 2 | 3 | ![Go](https://github.com/pioz/faker/workflows/Go/badge.svg) 4 | [![Go Report Card](https://goreportcard.com/badge/github.com/pioz/faker)](https://goreportcard.com/report/github.com/pioz/faker) 5 | [![codecov](https://codecov.io/gh/pioz/faker/branch/master/graph/badge.svg)](https://codecov.io/gh/pioz/faker) 6 | [![awesome-go](https://camo.githubusercontent.com/13c4e50d88df7178ae1882a203ed57b641674f94/68747470733a2f2f63646e2e7261776769742e636f6d2f73696e647265736f726875732f617765736f6d652f643733303566333864323966656437386661383536353265336136336531353464643865383832392f6d656469612f62616467652e737667)](https://github.com/avelino/awesome-go) 7 | [![GoReference](https://pkg.go.dev/badge/mod/github.com/pioz/faker)](https://pkg.go.dev/github.com/pioz/faker) 8 | 9 | 10 | Random fake data and struct generator for Go. 11 | 12 | * More than 100 generator functions 13 | * Struct generator 14 | * Unique data generator 15 | * Builtin types support 16 | * Easily customizable 17 | * Zero dependencies 18 | * Recursive infinite loop detector 19 | * Benchmarks (coming soon) 20 | 21 | ## Installation 22 | 23 | go get github.com/pioz/faker 24 | 25 | ## Example 26 | 27 | ```go 28 | faker.SetSeed(623) 29 | 30 | fmt.Println(faker.Username()) 31 | fmt.Println(faker.String()) 32 | fmt.Println(faker.IntInRange(1, 10)) 33 | fmt.Println(faker.CurrencyName()) 34 | // Output: spicule 35 | // gzaazJyRGt3jDnVh6ik7R9FO0AU1HcOzdOXbmNVBRQ5pq8n9tHf9B21PIFozLEzsoY4wILvZjTxSLQmD3UOAamDgVR411T3YHleDTgLuz90XSO3NFZm1AnaJiJamVRcNGD2zmi4qWkcjKF3E4JKgn1DiCeC3eSb5WELsw8XqRzlvJqG 36 | // 10 37 | // Myanmar Kyat 38 | ``` 39 | 40 | Please refer to the [godoc](https://godoc.org/github.com/pioz/faker) for all available functions and more. 41 | 42 | ## Struct Builder Example 43 | 44 | ```go 45 | faker.SetSeed(622) 46 | 47 | // Define a new builder 48 | colorBuilder := func(params ...string) (interface{}, error) { 49 | return faker.Pick("Red", "Yellow", "Blue", "Black", "White"), nil 50 | } 51 | 52 | // Register a new builder named "color" for string type 53 | err := faker.RegisterBuilder("color", "string", colorBuilder) 54 | if err != nil { 55 | panic(err) 56 | } 57 | 58 | type Animal struct { 59 | Name string `faker:"username"` 60 | Color string `faker:"color"` // Use custom color builder 61 | } 62 | 63 | type Person struct { 64 | FirstName string `faker:"firstName"` // Any available function case insensitive 65 | LastName *string `faker:"lastName"` // Pointer are also supported 66 | Age int `faker:"intinrange(0,120)"` // Can call with parameters 67 | UUID string `faker:"uuid;unique"` // Guarantees a unique value 68 | Number int `faker:"-"` // Skip this field 69 | Code string // No tag to use default builder for this field type 70 | Pet Animal // Recursively fill this struct 71 | Nicknames []string `faker:"username;len=3"` // Build an array of size 3 using faker.Username function 72 | Extra map[string]string `faker:"stringWithSize(3);len=2"` // map are supported 73 | } 74 | 75 | p := Person{} 76 | err = faker.Build(&p) 77 | if err != nil { 78 | panic(err) 79 | } 80 | fmt.Println(p.FirstName) 81 | fmt.Println(*p.LastName) 82 | fmt.Println(p.Age) 83 | fmt.Println(p.UUID) 84 | fmt.Println(p.Number) 85 | fmt.Println(p.Code) 86 | fmt.Println(p.Pet.Name) 87 | fmt.Println(p.Pet.Color) 88 | fmt.Println(len(p.Nicknames)) 89 | fmt.Println(p.Nicknames[0]) 90 | fmt.Println(p.Nicknames[1]) 91 | fmt.Println(p.Nicknames[2]) 92 | fmt.Println(p.Extra) 93 | // Output: Wilber 94 | // Gutkowski 95 | // 25 96 | // ff8d6917-b920-46e6-b1be-dc2d48becfcb 97 | // 0 98 | // z 99 | // honegger 100 | // Red 101 | // 3 102 | // teagan 103 | // polypeptide 104 | // chinfest 105 | // map[70w:3F6 gQS:isq] 106 | ``` 107 | 108 | ## Factory 109 | 110 | One of the nice things about Faker is that it can also be used as a factory 111 | library. In fact when we call the `faker.Build` function if a value is not 112 | zero then it is not modified, leaving the original value. This allows you to 113 | create factory functions very easily: 114 | 115 | ```go 116 | faker.SetSeed(623) 117 | 118 | type User struct { 119 | Username string `faker:"username"` 120 | Email string `faker:"email"` 121 | Country string `faker:"CountryAlpha2"` 122 | } 123 | 124 | italianUserFactory := func() *User { 125 | u := &User{Country: "IT"} 126 | faker.Build(u) 127 | return u 128 | } 129 | 130 | italianUser := italianUserFactory() 131 | fmt.Println(italianUser) 132 | // Output: &{spicule hoag@ornamented.biz IT} 133 | ``` 134 | 135 | ## Customization 136 | 137 | A builder is a variadic function that will take an arbitrary number of strings 138 | as arguments and return an interface or an error. This function (builder) can 139 | be used to generate fake data and customize the behaviour of Faker. Here an example: 140 | 141 | ```go 142 | faker.SetSeed(1802) 143 | 144 | // Define a new builder 145 | builder := func(params ...string) (interface{}, error) { 146 | if len(params) > 0 && params[0] == "melee" { 147 | return faker.Pick("Barbarian", "Bard", "Fighter", "Monk", "Paladin", "Rogue"), nil 148 | } 149 | return faker.Pick("Cleric", "Druid", "Ranger", "Sorcerer", "Warlock", "Wizard"), nil 150 | } 151 | 152 | // Register a new builder named "dndClass" for string type 153 | err := faker.RegisterBuilder("dndClass", "string", builder) 154 | if err != nil { 155 | panic(err) 156 | } 157 | 158 | player := &struct { 159 | Class string `faker:"dndClass(melee)"` 160 | // other fields ... 161 | }{} 162 | 163 | // Build a struct with fake data 164 | faker.Build(&player) 165 | 166 | fmt.Println(player.Class) 167 | // Output: Paladin 168 | ``` 169 | 170 | ## Contributing with new generator functions 171 | 172 | If you want to contribute to faker with new generator functions please read this [wiki](https://github.com/pioz/faker/wiki/Contributing-with-new-generator-functions)! 173 | 174 | ## Contributing 175 | 176 | Bug reports and pull requests are welcome on GitHub at https://github.com/pioz/faker/issues. 177 | 178 | ## License 179 | 180 | The package is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). 181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # faker TODO 2 | 3 | - Think to remove data sub package and move `var DB` and `var builders` in the same file (init.go) 4 | - Wiki add new Builder 5 | 6 | ## Functions 7 | 8 | Latitude() float64 9 | LatitudeInRange(min, max float64) (float64, error) 10 | Longitude() float64 11 | LongitudeInRange(min, max float64) (float64, error) 12 | 13 | ### Code 14 | Faker::Code.npi #=> "0000126252" 15 | Faker::Code.isbn #=> "759021701-8" 16 | Faker::Code.ean #=> "4600051000057" 17 | Faker::Code.rut #=> "91389184-8" 18 | Faker::Code.nric #=> "S5589083H" 19 | Faker::Code.nric(min_age: 27, max_age: 34) #=> S8505970Z 20 | Faker::Code.imei #= "546327785982623" 21 | Faker::Code.asin #=> "B00000IGGJ" 22 | Faker::Code.sin #=> "159160274" 23 | Faker::Code.ssn 24 | 25 | ### PhoneNumber 26 | Faker::PhoneNumber.phone_number #=> "397.693.1309 x4321" 27 | Faker::PhoneNumber.cell_phone #=> "(186)285-7925" 28 | Faker::PhoneNumber.cell_phone_in_e164 #=> "+944937040625" 29 | Faker::PhoneNumber.area_code #=> "201" 30 | Faker::PhoneNumber.exchange_code #=> "208" 31 | Faker::PhoneNumber.subscriber_number #=> "3873" 32 | Faker::PhoneNumber.subscriber_number(length: 2) #=> "39" 33 | Faker::PhoneNumber.extension #=> "3764" 34 | Faker::PhoneNumber.country_code #=> "+20" 35 | Faker::PhoneNumber.phone_number_with_country_code #=> "+95 1-672-173-8153" 36 | Faker::PhoneNumber.cell_phone_with_country_code #=> "+974 (190) 987-9034" 37 | 38 | ### Internet 39 | Faker::Internet.email #=> "eliza@mann.net" 40 | Faker::Internet.email(name: 'Nancy') #=> "nancy@terry.biz" 41 | Faker::Internet.email(name: 'Janelle Santiago', separators: '+') #=> "janelle+santiago@becker.com" 42 | Faker::Internet.email(domain: 'example') #=> "alice@example.name" 43 | Faker::Internet.free_email #=> "freddy@gmail.com" 44 | Faker::Internet.free_email(name: 'Nancy') #=> "nancy@yahoo.com" 45 | Faker::Internet.safe_email #=> "christelle@example.org" 46 | Faker::Internet.safe_email(name: 'Nancy') #=> "nancy@example.net" 47 | Faker::Internet.username #=> "alexie" 48 | Faker::Internet.username(specifier: 'Nancy') #=> "nancy" 49 | Faker::Internet.username(specifier: 'Nancy Johnson', separators: %w(. _ -)) #=> "johnson-nancy" 50 | Faker::Internet.username(specifier: 5..8) 51 | Faker::Internet.username(specifier: 8) 52 | Faker::Internet.password #=> "Vg5mSvY1UeRg7" 53 | Faker::Internet.password(min_length: 8) #=> "YfGjIk0hGzDqS0" 54 | Faker::Internet.password(min_length: 10, max_length: 20) #=> "EoC9ShWd1hWq4vBgFw" 55 | Faker::Internet.password(min_length: 10, max_length: 20, mix_case: true) #=> "3k5qS15aNmG" 56 | Faker::Internet.password(min_length: 10, max_length: 20, mix_case: true, special_characters: true) #=> "*%NkOnJsH4" 57 | Faker::Internet.domain_name #=> "effertz.info" 58 | Faker::Internet.domain_name(domain: "example") #=> "example.net" 59 | Faker::Internet.domain_name(subdomain: true, domain: "example") #=> "horse.example.org" 60 | Faker::Internet.domain_word #=> "haleyziemann" 61 | Faker::Internet.domain_suffix #=> "info" 62 | Faker::Internet.ip_v4_address #=> "24.29.18.175" 63 | Faker::Internet.private_ip_v4_address #=> "10.0.0.1" 64 | Faker::Internet.public_ip_v4_address #=> "24.29.18.175" 65 | Faker::Internet.ip_v4_cidr #=> "24.29.18.175/21" 66 | Faker::Internet.ip_v6_address #=> "ac5f:d696:3807:1d72:2eb5:4e81:7d2b:e1df" 67 | Faker::Internet.ip_v6_cidr #=> "ac5f:d696:3807:1d72:2eb5:4e81:7d2b:e1df/78" 68 | Faker::Internet.mac_address #=> "e6:0d:00:11:ed:4f" 69 | Faker::Internet.mac_address(prefix: '55:44:33') #=> "55:44:33:02:1d:9b" 70 | Faker::Internet.url #=> "http://thiel.com/chauncey_simonis" 71 | Faker::Internet.url(host: 'example.com') #=> "http://example.com/clotilde.swift" 72 | Faker::Internet.url(host: 'example.com', path: '/foobar.html') #=> "http://example.com/foobar.html" 73 | Faker::Internet.slug #=> "pariatur_laudantium" 74 | Faker::Internet.slug(words: 'foo bar') #=> "foo.bar" 75 | Faker::Internet.slug(words: 'foo bar', glue: '-') #=> "foo-bar" 76 | Faker::Internet.user_agent #=> "Mozilla/5.0 (compatible; MSIE 9.0; AOL 9.7; AOLBuild 4343.19; Windows NT 6.1; WOW64; Trident/5.0; FunWebProducts)" 77 | Faker::Internet.user_agent(vendor: :firefox) #=> "Mozilla/5.0 (Windows NT x.y; Win64; x64; rv:10.0) Gecko/20100101 Firefox/10.0" 78 | Faker::Internet.uuid #=> "929ef6ef-b11f-38c9-111b-accd67a258b2" 79 | 80 | URL() string 81 | ImageURL(width int, height int) string 82 | DomainName() string 83 | DomainSuffix() string 84 | IPv4Address() string 85 | IPv6Address() string 86 | StatusCode() string 87 | SimpleStatusCode() int 88 | LogLevel(logType string) string 89 | HTTPMethod() string 90 | UserAgent() string 91 | ChromeUserAgent() string 92 | FirefoxUserAgent() string 93 | OperaUserAgent() string 94 | SafariUserAgent() string 95 | 96 | ### Gender 97 | Faker::Gender.type #=> "Non-binary" 98 | Faker::Gender.binary_type #=> "Female" 99 | Faker::Gender.short_binary_type #=> "f" 100 | 101 | ### Name ✅ 102 | Faker::Name.name #=> "Tyshawn Johns Sr." 103 | Faker::Name.name_with_middle #=> "Aditya Elton Douglas" 104 | Faker::Name.first_name #=> "Kaci" 105 | Faker::Name.middle_name #=> "Abraham" 106 | Faker::Name.last_name #=> "Ernser" 107 | Faker::Name.male_first_name #=> "Edward" 108 | Faker::Name.female_first_name #=> "Natasha" 109 | Faker::Name.prefix #=> "Mr." 110 | Faker::Name.suffix #=> "IV" 111 | Faker::Name.initials #=> "NJM" 112 | Faker::Name.initials(number: 2) #=> "NM" 113 | 114 | ### Words 115 | Noun() string 116 | Verb() string 117 | Adverb() string 118 | Preposition() string 119 | Adjective() string 120 | Word() string 121 | Sentence(wordCount int) string 122 | Paragraph(paragraphCount int, sentenceCount int, wordCount int, separator string) string 123 | LoremIpsumWord() string 124 | LoremIpsumSentence(wordCount int) string 125 | LoremIpsumParagraph(paragraphCount int, sentenceCount int, wordCount int, separator string) string 126 | Question() string 127 | Quote() string 128 | Phrase() string 129 | 130 | ### Misc 131 | Map() map[string]interface{} 132 | 133 | 134 | 135 | STOP HERE FOR FIRST RELEASE 136 | 137 | 138 | ### Colors 139 | Color() string 140 | HexColor() string 141 | RGBColor() []int 142 | SafeColor() string 143 | 144 | ### Payments 145 | Price(min, max float64) float64 146 | CreditCard() *CreditCardInfo 147 | CreditCardCvv() string 148 | CreditCardExp() string 149 | CreditCardNumber(*CreditCardOptions) string 150 | CreditCardType() string 151 | Currency() *CurrencyInfo 152 | CurrencyLong() string 153 | CurrencyShort() string 154 | AchRouting() string 155 | AchAccount() string 156 | BitcoinAddress() string 157 | BitcoinPrivateKey() string 158 | 159 | ### Company 160 | BS() string 161 | BuzzWord() string 162 | Company() string 163 | CompanySuffix() string 164 | Job() *JobInfo 165 | JobDescriptor() string 166 | JobLevel() string 167 | JobTitle() string 168 | 169 | ### App 170 | AppName() string 171 | AppVersion() string 172 | AppAuthor() string 173 | 174 | ### Emoji 175 | Emoji() string // 🤣 176 | EmojiDescription() string // winking face 177 | EmojiCategory() string // Smileys & Emotion 178 | EmojiAlias() string // smiley 179 | EmojiTag() string // happy 180 | 181 | ### Products 182 | 183 | ### Avatar (https://robohash.org) 184 | Avatar() 185 | AvatarWithParams(size, format, set) 186 | 187 | ### Placeholdit (https://placehold.it/300x300.png) 188 | Placeholdit() 189 | PlaceholditWithParams(...) 190 | 191 | ### Bank 192 | BankAccountNumber 193 | BankIban 194 | BankIbanWithCountryCode 195 | BankName 196 | BankRoutingNumber 197 | BankSwiftBic 198 | 199 | ### Blood 200 | BloodGroup 201 | 202 | ### Coin 203 | CoinFlip 204 | 205 | ### Marketing 206 | Faker::Marketing.buzzwords #=> "rubber meets 207 | 208 | ### Measurement 209 | Faker::Measurement.height #=> "6 inches" 210 | Faker::Measurement.height(amount: 1.4) #=> "1.4 inches" 211 | Faker::Measurement.height(amount: "none") #=> "inch" 212 | Faker::Measurement.height(amount: "all") #=> "inches" 213 | Faker::Measurement.length #=> "1 yard" 214 | Faker::Measurement.volume #=> "10 cups" 215 | Faker::Measurement.weight #=> "3 pounds" 216 | Faker::Measurement.metric_height #=> "2 meters" 217 | Faker::Measurement.metric_length #=> "0 decimeters" 218 | Faker::Measurement.metric_volume #=> "1 liter" 219 | Faker::Measurement.metric_weight #=> "8 grams" 220 | 221 | ### Job 222 | Faker::Job.title #=> "Lead Accounting Associate" 223 | Faker::Job.field #=> "Manufacturing" 224 | Faker::Job.seniority #=> "Lead" 225 | Faker::Job.position #=> "Supervisor" 226 | Faker::Job.key_skill #=> "Teamwork" 227 | Faker::Job.employment_type #=> "Full-time" 228 | Faker::Job.education_level #=> "Bachelor" 229 | 230 | ### Funny Name 231 | 232 | ### File 233 | Extension() 234 | MimeType() 235 | 236 | ### Educator 237 | Faker::Educator.university #=> "Mallowtown Technical College" 238 | Faker::Educator.secondary_school #=> "Iceborough Secondary College" 239 | Faker::Educator.degree #=> "Associate Degree in Criminology" 240 | Faker::Educator.course_name #=> "Criminology 101" 241 | Faker::Educator.subject #=> "Criminology" 242 | Faker::Educator.campus #=> "Vertapple Campus" 243 | 244 | ### Device 245 | Faker::Device.build_number #=> "5" 246 | Faker::Device.manufacturer #=> "Apple" 247 | Faker::Device.model_name #=> "iPhone 4" 248 | Faker::Device.platform #=> "webOS" 249 | Faker::Device.serial #=> "ejfjnRNInxh0363JC2WM" 250 | Faker::Device.version #=> "4" 251 | 252 | ### Crypto 253 | Faker::Crypto.md5 #=> "6b5ed240042e8a65c55ddb826c3408e6" 254 | Faker::Crypto.sha1 #=> "4e99e31c51eef8b2d290e709f757f92e558a503f" 255 | Faker::Crypto.sha256 #=> "51e4dbb424cd9db1ec5fb989514f2a35652ececef33f21c8dd1fd61bb8e3929d" 256 | 257 | -------------------------------------------------------------------------------- /address_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleAddressCity() { 12 | faker.SetSeed(1300) 13 | fmt.Println(faker.AddressCity()) 14 | // Output: Ntoroko 15 | } 16 | 17 | func ExampleAddressState() { 18 | faker.SetSeed(1301) 19 | fmt.Println(faker.AddressState()) 20 | // Output: Indiana 21 | } 22 | 23 | func ExampleAddressStateCode() { 24 | faker.SetSeed(1302) 25 | fmt.Println(faker.AddressStateCode()) 26 | // Output: DC 27 | } 28 | 29 | func ExampleAddressStreetName() { 30 | faker.SetSeed(1303) 31 | fmt.Println(faker.AddressStreetName()) 32 | // Output: Hopton Street 33 | } 34 | 35 | func ExampleAddressStreetNumber() { 36 | faker.SetSeed(1304) 37 | fmt.Println(faker.AddressStreetNumber()) 38 | // Output: 81-680 39 | } 40 | 41 | func ExampleAddressSecondaryAddress() { 42 | faker.SetSeed(1305) 43 | fmt.Println(faker.AddressSecondaryAddress()) 44 | // Output: Suite 208 45 | } 46 | 47 | func ExampleAddressZip() { 48 | faker.SetSeed(1306) 49 | fmt.Println(faker.AddressZip()) 50 | // Output: 36168 51 | } 52 | 53 | func ExampleAddressFull() { 54 | faker.SetSeed(1307) 55 | fmt.Println(faker.AddressFull()) 56 | // Output: John Snow 57 | // Apt. 248 58 | // 943 Wager Street 59 | // Berezniki PR 52209 60 | // Saudi Arabia 61 | } 62 | 63 | func TestAddressBuild(t *testing.T) { 64 | faker.SetSeed(1008) 65 | s := &struct { 66 | Field1 string `faker:"AddressCity"` 67 | Field2 string `faker:"AddressState"` 68 | Field3 string `faker:"AddressStateCode"` 69 | Field4 string `faker:"AddressStreetName"` 70 | Field5 string `faker:"AddressStreetNumber"` 71 | Field6 string `faker:"AddressSecondaryAddress"` 72 | Field7 string `faker:"AddressZip"` 73 | Field8 string `faker:"AddressFull"` 74 | }{} 75 | err := faker.Build(&s) 76 | assert.Nil(t, err) 77 | t.Log(s) 78 | assert.Equal(t, "Pryor Creek", s.Field1) 79 | assert.Equal(t, "Ohio", s.Field2) 80 | assert.Equal(t, "AP", s.Field3) 81 | assert.Equal(t, "Shuttle Street", s.Field4) 82 | assert.Equal(t, "72", s.Field5) 83 | assert.Equal(t, "Suite 516", s.Field6) 84 | assert.Equal(t, "05094", s.Field7) 85 | assert.Equal(t, "John Snow\nApt. 485\n632 Windsor Walk\nVidalia AL 71829-6715\nAndorra", s.Field8) 86 | } 87 | -------------------------------------------------------------------------------- /builder.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | type builderFunc func(...string) (interface{}, error) 10 | 11 | func builderKey(builderName, builderType string) string { 12 | return strings.ToLower(fmt.Sprintf("%s-%s", builderName, builderType)) 13 | } 14 | 15 | // RegisterBuilder register a new builder. A builder is a variadic function 16 | // that will take an arbitrary number of strings as arguments and return an 17 | // interface or an error. This function (builder) can be used to generate fake 18 | // data. builderName is the name of the builder, builderType is the type of 19 | // the interface returned by the builder. 20 | func RegisterBuilder(builderName, builderType string, fn builderFunc) error { 21 | key := builderKey(builderName, builderType) 22 | if _, ok := builders[key]; ok { 23 | return errors.New("builder already registered") 24 | } 25 | builders[key] = fn 26 | return nil 27 | } 28 | 29 | // UnregisterBuilder unregister/remove a builder. 30 | func UnregisterBuilder(builderName, builderType string) error { 31 | key := builderKey(builderName, builderType) 32 | if _, ok := builders[key]; !ok { 33 | return errors.New("builder not registered") 34 | } 35 | delete(builders, key) 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /builder_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestRegisterBuilder(t *testing.T) { 12 | err := faker.UnregisterBuilder("foo", "string") 13 | assert.NotNil(t, err) 14 | assert.Equal(t, "builder not registered", err.Error()) 15 | 16 | err = faker.RegisterBuilder("foo", "string", func(...string) (interface{}, error) { 17 | return "bar", nil 18 | }) 19 | assert.Nil(t, err) 20 | 21 | err = faker.RegisterBuilder("foo", "string", func(...string) (interface{}, error) { 22 | return "bar", nil 23 | }) 24 | assert.NotNil(t, err) 25 | assert.Equal(t, "builder already registered", err.Error()) 26 | 27 | err = faker.UnregisterBuilder("foo", "string") 28 | assert.Nil(t, err) 29 | } 30 | 31 | func ExampleRegisterBuilder() { 32 | faker.SetSeed(1802) 33 | 34 | // Define a new builder 35 | builder := func(params ...string) (interface{}, error) { 36 | if len(params) > 0 && params[0] == "melee" { 37 | return faker.Pick("Barbarian", "Bard", "Fighter", "Monk", "Paladin", "Rogue"), nil 38 | } 39 | return faker.Pick("Cleric", "Druid", "Ranger", "Sorcerer", "Warlock", "Wizard"), nil 40 | } 41 | 42 | // Register a new builder named "dndClass" for string type 43 | err := faker.RegisterBuilder("dndClass", "string", builder) 44 | if err != nil { 45 | panic(err) 46 | } 47 | 48 | player := &struct { 49 | Class string `faker:"dndClass(melee)"` 50 | // other fields ... 51 | }{} 52 | 53 | // Build a struct with fake data 54 | err = faker.Build(&player) 55 | if err != nil { 56 | panic(err) 57 | } 58 | 59 | fmt.Println(player.Class) 60 | // Output: Paladin 61 | } 62 | -------------------------------------------------------------------------------- /color.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | var colorData = PoolGroup{ 8 | "name": {"amaranth", "amber", "amethyst", "apricot", "aquamarine", "azure", "beige", "black", "blue", "blush", "bronze", "brown", "burgundy", "byzantium", "carmine", "cerise", "cerulean", "champagne", "chocolate", "coffee", "copper", "coral", "crimson", "cyan", "emerald", "erin", "fuchsia", "gold", "gray", "green", "grey", "harlequin", "indigo", "ivory", "jade", "lavender", "lemon", "lilac", "lime", "magenta", "maroon", "mauve", "ochre", "olive", "orange", "orchid", "peach", "pear", "periwinkle", "pink", "plum", "puce", "purple", "raspberry", "red", "rose", "ruby", "salmon", "sangria", "sapphire", "scarlet", "silver", "sky", "tan", "taupe", "teal", "turquoise", "ultramarine", "violet", "viridian", "white", "yellow"}, 9 | } 10 | 11 | // ColorName will build a random color name string. 12 | func ColorName() string { 13 | value, _ := GetData("color", "name") 14 | return value.(string) 15 | } 16 | 17 | // ColorHex will build a random hex color string. First element is the Red value 18 | // from 0 to 255; second element is the Green value from 0 to 255; third element 19 | // is the Blue value from 0 to 255. 20 | func ColorHex() string { 21 | c := ColorRGB() 22 | hex := "#" + getHex(c[0]) + getHex(c[1]) + getHex(c[2]) 23 | return hex 24 | } 25 | 26 | // ColorRGB will build a random RGB color. 27 | func ColorRGB() [3]int { 28 | var c [3]int 29 | c[0] = IntInRange(0, 255) 30 | c[1] = IntInRange(0, 255) 31 | c[2] = IntInRange(0, 255) 32 | return c 33 | } 34 | 35 | // ColorHSL will build a random HSL color. First element is Hue, a degree on the 36 | // color wheel from 0 to 360. 0 is red, 120 is green, 240 is blue. Second 37 | // element is Saturation, a percentage value; 0 means a shade of gray and 100 is 38 | // the full color. Third element is Lightness, also a percentage; 0 is black, 39 | // 100 is white. 40 | func ColorHSL() [3]int { 41 | var c [3]int 42 | c[0] = IntInRange(0, 360) 43 | c[1] = IntInRange(0, 100) 44 | c[2] = IntInRange(0, 100) 45 | return c 46 | } 47 | 48 | // Builder functions 49 | 50 | func colorNameBuilder(params ...string) (interface{}, error) { 51 | return ColorName(), nil 52 | } 53 | 54 | func colorHexBuilder(params ...string) (interface{}, error) { 55 | return ColorHex(), nil 56 | } 57 | 58 | func colorRGBBuilder(params ...string) (interface{}, error) { 59 | return ColorRGB(), nil 60 | } 61 | 62 | func colorHSLBuilder(params ...string) (interface{}, error) { 63 | return ColorHSL(), nil 64 | } 65 | 66 | // Private functions 67 | 68 | func getHex(num int) string { 69 | hex := fmt.Sprintf("%x", num) 70 | if len(hex) == 1 { 71 | hex = "0" + hex 72 | } 73 | return hex 74 | } 75 | -------------------------------------------------------------------------------- /color_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleColorName() { 12 | faker.SetSeed(1900) 13 | fmt.Println(faker.ColorName()) 14 | // Output: apricot 15 | } 16 | 17 | func ExampleColorHex() { 18 | faker.SetSeed(1902) 19 | fmt.Println(faker.ColorHex()) 20 | // Output: #1908b0 21 | } 22 | 23 | func ExampleColorRGB() { 24 | faker.SetSeed(1901) 25 | fmt.Println(faker.ColorRGB()) 26 | // Output: [137 240 27] 27 | } 28 | 29 | func ExampleColorHSL() { 30 | faker.SetSeed(1903) 31 | fmt.Println(faker.ColorHSL()) 32 | // Output: [135 5 41] 33 | } 34 | 35 | func TestColorBuild(t *testing.T) { 36 | faker.SetSeed(1904) 37 | s := &struct { 38 | Field1 string `faker:"ColorName"` 39 | Field2 string `faker:"ColorHex"` 40 | Field3 [3]int `faker:"ColorRGB"` 41 | Field4 [3]int `faker:"ColorHSL"` 42 | }{} 43 | err := faker.Build(&s) 44 | assert.Nil(t, err) 45 | t.Log(s) 46 | assert.Equal(t, "lilac", s.Field1) 47 | assert.Equal(t, "#c3e065", s.Field2) 48 | assert.Equal(t, [3]int{46, 59, 194}, s.Field3) 49 | assert.Equal(t, [3]int{56, 22, 19}, s.Field4) 50 | } 51 | -------------------------------------------------------------------------------- /country.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | var countryData = PoolGroup{ 4 | "name": {"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia (Plurinational State of)", "Bonaire, Sint Eustatius and Saba", "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cabo Verde", "Cambodia", "Cameroon", "Canada", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo", "Congo (Democratic Republic of the)", "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Curaçao", "Cyprus", "Czech Republic", "Côte d'Ivoire", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Malvinas)", "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia", "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Heard Island and McDonald Islands", "Holy See", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran (Islamic Republic of)", "Iraq", "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Korea (Democratic People's Republic of)", "Korea (Republic of)", "Kuwait", "Kyrgyzstan", "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia (the former Yugoslav Republic of)", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia (Federated States of)", "Moldova (Republic of)", "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau", "Palestine, State of", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Romania", "Russian Federation", "Rwanda", "Réunion", "Saint Barthélemy", "Saint Helena, Ascension and Tristan da Cunha", "Saint Kitts and Nevis", "Saint Lucia", "Saint Martin (French part)", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Sint Maarten (Dutch part)", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic", "Taiwan, Province of China", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-Leste", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom of Great Britain and Northern Ireland", "United States Minor Outlying Islands", "United States of America", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela (Bolivarian Republic of)", "Viet Nam", "Virgin Islands (British)", "Virgin Islands (U.S.)", "Wallis and Futuna", "Western Sahara", "Yemen", "Zambia", "Zimbabwe", "Åland Islands"}, 5 | "alpha2": {"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU", "CV", "CW", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "ZA", "ZM", "ZW"}, 6 | "alpha3": {"ABW", "AFG", "AGO", "AIA", "ALA", "ALB", "AND", "ARE", "ARG", "ARM", "ASM", "ATA", "ATF", "ATG", "AUS", "AUT", "AZE", "BDI", "BEL", "BEN", "BES", "BFA", "BGD", "BGR", "BHR", "BHS", "BIH", "BLM", "BLR", "BLZ", "BMU", "BOL", "BRA", "BRB", "BRN", "BTN", "BVT", "BWA", "CAF", "CAN", "CCK", "CHE", "CHL", "CHN", "CIV", "CMR", "COD", "COG", "COK", "COL", "COM", "CPV", "CRI", "CUB", "CUW", "CXR", "CYM", "CYP", "CZE", "DEU", "DJI", "DMA", "DNK", "DOM", "DZA", "ECU", "EGY", "ERI", "ESH", "ESP", "EST", "ETH", "FIN", "FJI", "FLK", "FRA", "FRO", "FSM", "GAB", "GBR", "GEO", "GGY", "GHA", "GIB", "GIN", "GLP", "GMB", "GNB", "GNQ", "GRC", "GRD", "GRL", "GTM", "GUF", "GUM", "GUY", "HKG", "HMD", "HND", "HRV", "HTI", "HUN", "IDN", "IMN", "IND", "IOT", "IRL", "IRN", "IRQ", "ISL", "ISR", "ITA", "JAM", "JEY", "JOR", "JPN", "KAZ", "KEN", "KGZ", "KHM", "KIR", "KNA", "KOR", "KWT", "LAO", "LBN", "LBR", "LBY", "LCA", "LIE", "LKA", "LSO", "LTU", "LUX", "LVA", "MAC", "MAF", "MAR", "MCO", "MDA", "MDG", "MDV", "MEX", "MHL", "MKD", "MLI", "MLT", "MMR", "MNE", "MNG", "MNP", "MOZ", "MRT", "MSR", "MTQ", "MUS", "MWI", "MYS", "MYT", "NAM", "NCL", "NER", "NFK", "NGA", "NIC", "NIU", "NLD", "NOR", "NPL", "NRU", "NZL", "OMN", "PAK", "PAN", "PCN", "PER", "PHL", "PLW", "PNG", "POL", "PRI", "PRK", "PRT", "PRY", "PSE", "PYF", "QAT", "REU", "ROU", "RUS", "RWA", "SAU", "SDN", "SEN", "SGP", "SGS", "SHN", "SJM", "SLB", "SLE", "SLV", "SMR", "SOM", "SPM", "SRB", "SSD", "STP", "SUR", "SVK", "SVN", "SWE", "SWZ", "SXM", "SYC", "SYR", "TCA", "TCD", "TGO", "THA", "TJK", "TKL", "TKM", "TLS", "TON", "TTO", "TUN", "TUR", "TUV", "TWN", "TZA", "UGA", "UKR", "UMI", "URY", "USA", "UZB", "VAT", "VCT", "VEN", "VGB", "VIR", "VNM", "VUT", "WLF", "WSM", "YEM", "ZAF", "ZMB", "ZWE"}, 7 | "nationality": {"Afghan", "Albanian", "Algerian", "American", "American Samoan", "Andorran", "Angolan", "Anguillian", "Antiguan, Barbudan", "Argentinean", "Armenian", "Aruban", "Australian", "Austrian", "Azerbaijani", "Bahamian", "Bahraini", "Bangladeshi", "Barbadian", "Belarusian", "Belgian", "Belizean", "Beninese", "Bermudian", "Bhutanese", "Bolivian", "Bosnian, Herzegovinian", "Brazilian", "British", "Bruneian", "Bulgarian", "Burkinabe", "Burundian", "Cambodian", "Cameroonian", "Canadian", "Cape Verdian", "Caymanian", "Central African", "Chadian", "Channel Islander", "Chilean", "Chinese", "Christmas Island", "Cocos Islander", "Colombian", "Comoran", "Congolese", "Cook Islander", "Costa Rican", "Croatian", "Cuban", "Cypriot", "Czech", "Danish", "Djibouti", "Dominican", "Dutch", "East Timorese", "Ecuadorean", "Egyptian", "Emirian", "Equatorial Guinean", "Eritrean", "Estonian", "Ethiopian", "Falkland Islander", "Faroese", "Fijian", "Filipino", "Finnish", "French", "French Guianan", "French Polynesian", "Gabonese", "Gambian", "Georgian", "German", "Ghanaian", "Gibraltar", "Greek", "Greenlandic", "Grenadian", "Guadeloupian", "Guamanian", "Guatemalan", "Guinea-Bissauan", "Guinean", "Guyanese", "Haitian", "Heard and McDonald Islander", "Honduran", "Hong Kongese", "Hungarian", "I-Kiribati", "Icelander", "Indian", "Indonesian", "Iranian", "Iraqi", "Irish", "Israeli", "Italian", "Ivorian", "Jamaican", "Japanese", "Jordanian", "Kazakhstani", "Kenyan", "Kirghiz", "Kittian and Nevisian", "Kuwaiti", "Laotian", "Latvian", "Lebanese", "Liberian", "Libyan", "Liechtensteiner", "Lithuanian", "Luxembourger", "Macedonian", "Malagasy", "Malawian", "Malaysian", "Maldivan", "Malian", "Maltese", "Manx", "Marshallese", "Mauritanian", "Mauritian", "Mexican", "Micronesian", "Moldovan", "Monegasque", "Mongolian", "Montenegrin", "Montserratian", "Moroccan", "Mosotho", "Motswana", "Mozambican", "Myanmarian", "Namibian", "Nauruan", "Nepalese", "New Caledonian", "New Zealander", "Ni-Vanuatu", "Nicaraguan", "Nigerian", "Niuean", "Norfolk Islander", "North Korean", "Norwegian", "Omani", "Pakistani", "Palauan", "Palestinian", "Panamanian", "Papua New Guinean", "Paraguayan", "Peruvian", "Pitcairn Islander", "Polish", "Portuguese", "Puerto Rican", "Qatari", "Romanian", "Russian", "Rwandan", "Sahrawi", "Saint Barthélemy Islander", "Saint Helenian", "Saint Lucian", "Saint Martin Islander", "Saint Vincentian", "Salvadoran", "Sammarinese", "Samoan", "Sao Tomean", "Saudi Arabian", "Senegalese", "Serbian", "Seychellois", "Sierra Leonean", "Singaporean", "Slovak", "Slovene", "Solomon Islander", "Somali", "South African", "South Georgia and the South Sandwich Islander", "South Korean", "South Sudanese", "Spanish", "Sri Lankan", "Sudanese", "Surinamer", "Swazi", "Swedish", "Swiss", "Syrian", "Tadzhik", "Taiwanese", "Tanzanian", "Thai", "Togolese", "Tokelauan", "Tongan", "Trinidadian", "Tunisian", "Turkish", "Turkmen", "Turks and Caicos Islander", "Tuvaluan", "Ugandan", "Ukrainian", "Uruguayan", "Uzbekistani", "Venezuelan", "Vietnamese", "Virgin Islander", "Wallis and Futuna Islander", "Yemeni", "Zambian", "Zimbabwean"}, 8 | "flag": {"🇦🇨", "🇦🇩", "🇦🇪", "🇦🇫", "🇦🇬", "🇦🇮", "🇦🇱", "🇦🇲", "🇦🇴", "🇦🇶", "🇦🇷", "🇦🇸", "🇦🇹", "🇦🇺", "🇦🇼", "🇦🇽", "🇦🇿", "🇧🇦", "🇧🇧", "🇧🇩", "🇧🇪", "🇧🇫", "🇧🇬", "🇧🇭", "🇧🇮", "🇧🇯", "🇧🇱", "🇧🇲", "🇧🇳", "🇧🇴", "🇧🇶", "🇧🇷", "🇧🇸", "🇧🇹", "🇧🇻", "🇧🇼", "🇧🇾", "🇧🇿", "🇨🇦", "🇨🇨", "🇨🇩", "🇨🇫", "🇨🇬", "🇨🇭", "🇨🇮", "🇨🇰", "🇨🇱", "🇨🇲", "🇨🇳", "🇨🇴", "🇨🇵", "🇨🇷", "🇨🇺", "🇨🇻", "🇨🇼", "🇨🇽", "🇨🇾", "🇨🇿", "🇩🇪", "🇩🇬", "🇩🇯", "🇩🇰", "🇩🇲", "🇩🇴", "🇩🇿", "🇪🇦", "🇪🇨", "🇪🇪", "🇪🇬", "🇪🇭", "🇪🇷", "🇪🇸", "🇪🇹", "🇪🇺", "🇫🇮", "🇫🇯", "🇫🇰", "🇫🇲", "🇫🇴", "🇫🇷", "🇬🇦", "🇬🇧", "🇬🇩", "🇬🇪", "🇬🇫", "🇬🇬", "🇬🇭", "🇬🇮", "🇬🇱", "🇬🇲", "🇬🇳", "🇬🇵", "🇬🇶", "🇬🇷", "🇬🇸", "🇬🇹", "🇬🇺", "🇬🇼", "🇬🇾", "🇭🇰", "🇭🇲", "🇭🇳", "🇭🇷", "🇭🇹", "🇭🇺", "🇮🇨", "🇮🇩", "🇮🇪", "🇮🇱", "🇮🇲", "🇮🇳", "🇮🇴", "🇮🇶", "🇮🇷", "🇮🇸", "🇮🇹", "🇯🇪", "🇯🇲", "🇯🇴", "🇯🇵", "🇰🇪", "🇰🇬", "🇰🇭", "🇰🇮", "🇰🇲", "🇰🇳", "🇰🇵", "🇰🇷", "🇰🇼", "🇰🇾", "🇰🇿", "🇱🇦", "🇱🇧", "🇱🇨", "🇱🇮", "🇱🇰", "🇱🇷", "🇱🇸", "🇱🇹", "🇱🇺", "🇱🇻", "🇱🇾", "🇲🇦", "🇲🇨", "🇲🇩", "🇲🇪", "🇲🇫", "🇲🇬", "🇲🇭", "🇲🇰", "🇲🇱", "🇲🇲", "🇲🇳", "🇲🇴", "🇲🇵", "🇲🇶", "🇲🇷", "🇲🇸", "🇲🇹", "🇲🇺", "🇲🇻", "🇲🇼", "🇲🇽", "🇲🇾", "🇲🇿", "🇳🇦", "🇳🇨", "🇳🇪", "🇳🇫", "🇳🇬", "🇳🇮", "🇳🇱", "🇳🇴", "🇳🇵", "🇳🇷", "🇳🇺", "🇳🇿", "🇴🇲", "🇵🇦", "🇵🇪", "🇵🇫", "🇵🇬", "🇵🇭", "🇵🇰", "🇵🇱", "🇵🇲", "🇵🇳", "🇵🇷", "🇵🇸", "🇵🇹", "🇵🇼", "🇵🇾", "🇶🇦", "🇷🇪", "🇷🇴", "🇷🇸", "🇷🇺", "🇷🇼", "🇸🇦", "🇸🇧", "🇸🇨", "🇸🇩", "🇸🇪", "🇸🇬", "🇸🇭", "🇸🇮", "🇸🇯", "🇸🇰", "🇸🇱", "🇸🇲", "🇸🇳", "🇸🇴", "🇸🇷", "🇸🇸", "🇸🇹", "🇸🇻", "🇸🇽", "🇸🇾", "🇸🇿", "🇹🇦", "🇹🇨", "🇹🇩", "🇹🇫", "🇹🇬", "🇹🇭", "🇹🇯", "🇹🇰", "🇹🇱", "🇹🇲", "🇹🇳", "🇹🇴", "🇹🇷", "🇹🇹", "🇹🇻", "🇹🇼", "🇹🇿", "🇺🇦", "🇺🇬", "🇺🇲", "🇺🇳", "🇺🇸", "🇺🇾", "🇺🇿", "🇻🇦", "🇻🇨", "🇻🇪", "🇻🇬", "🇻🇮", "🇻🇳", "🇻🇺", "🇼🇫", "🇼🇸", "🇽🇰", "🇾🇪", "🇾🇹", "🇿🇦", "🇿🇲", "🇿🇼", "🏴󠁧󠁢󠁥󠁮󠁧󠁿", "🏴󠁧󠁢󠁳󠁣󠁴󠁿", "🏴󠁧󠁢󠁷󠁬󠁳󠁿"}, //lint:ignore ST1018 Can not convert all flags 9 | } 10 | 11 | // CountryName will build a random country name string. 12 | func CountryName() string { 13 | value, _ := GetData("country", "name") 14 | return value.(string) 15 | } 16 | 17 | // CountryAlpha2 will build a random 2 characters country code string. 18 | func CountryAlpha2() string { 19 | value, _ := GetData("country", "alpha2") 20 | return value.(string) 21 | } 22 | 23 | // CountryAlpha3 will build a random 3 characters country code string. 24 | func CountryAlpha3() string { 25 | value, _ := GetData("country", "alpha3") 26 | return value.(string) 27 | } 28 | 29 | // CountryNationality will build a random nationality string. 30 | func CountryNationality() string { 31 | value, _ := GetData("country", "nationality") 32 | return value.(string) 33 | } 34 | 35 | // CountryFlag will build a random emoji flag string. 36 | func CountryFlag() string { 37 | value, _ := GetData("country", "flag") 38 | return value.(string) 39 | } 40 | 41 | // Builder functions 42 | 43 | func countryNameBuilder(params ...string) (interface{}, error) { 44 | return CountryName(), nil 45 | } 46 | 47 | func countryAlpha2Builder(params ...string) (interface{}, error) { 48 | return CountryAlpha2(), nil 49 | } 50 | 51 | func countryAlpha3Builder(params ...string) (interface{}, error) { 52 | return CountryAlpha3(), nil 53 | } 54 | 55 | func countryNationalityBuilder(params ...string) (interface{}, error) { 56 | return CountryNationality(), nil 57 | } 58 | 59 | func countryFlagBuilder(params ...string) (interface{}, error) { 60 | return CountryFlag(), nil 61 | } 62 | -------------------------------------------------------------------------------- /country_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleCountryName() { 12 | faker.SetSeed(1000) 13 | fmt.Println(faker.CountryName()) 14 | // Output: Rwanda 15 | } 16 | 17 | func ExampleCountryAlpha2() { 18 | faker.SetSeed(1001) 19 | fmt.Println(faker.CountryAlpha2()) 20 | // Output: ML 21 | } 22 | 23 | func ExampleCountryAlpha3() { 24 | faker.SetSeed(1002) 25 | fmt.Println(faker.CountryAlpha3()) 26 | // Output: TKM 27 | } 28 | 29 | func ExampleCountryNationality() { 30 | faker.SetSeed(1002) 31 | fmt.Println(faker.CountryNationality()) 32 | // Output: Venezuelan 33 | } 34 | 35 | func ExampleCountryFlag() { 36 | faker.SetSeed(1003) 37 | fmt.Println(faker.CountryFlag()) 38 | // Output: 🇳🇷 39 | } 40 | 41 | func TestCountryBuild(t *testing.T) { 42 | faker.SetSeed(1010) 43 | s := &struct { 44 | Field1 string `faker:"CountryName"` 45 | Field2 string `faker:"CountryAlpha2"` 46 | Field3 string `faker:"CountryAlpha3"` 47 | Field4 string `faker:"CountryNationality"` 48 | Field5 string `faker:"CountryFlag"` 49 | }{} 50 | err := faker.Build(&s) 51 | assert.Nil(t, err) 52 | t.Log(s) 53 | assert.Equal(t, "Iceland", s.Field1) 54 | assert.Equal(t, "IN", s.Field2) 55 | assert.Equal(t, "RUS", s.Field3) 56 | assert.Equal(t, "Cocos Islander", s.Field4) 57 | assert.Equal(t, "🇲🇹", s.Field5) 58 | } 59 | -------------------------------------------------------------------------------- /currency.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | var currencyData = PoolGroup{ 4 | "name": {"Afghan Afghani", "Albanian Lek", "Algerian Dinar", "Angolan Kwanza", "Argentine Peso", "Armenian Dram", "Aruban Florin", "Australian Dollar", "Azerbaijani Manat", "Bahamian Dollar", "Bahraini Dinar", "Bangladeshi Taka", "Barbadian Dollar", "Belarusian Ruble", "Belize Dollar", "Bermudian Dollar", "Bhutanese Ngultrum", "Bitcoin", "Bitcoin Cash", "Bolivian Boliviano", "Bosnia and Herzegovina Convertible Mark", "Botswana Pula", "Brazilian Real", "British Penny", "British Pound", "Brunei Dollar", "Bulgarian Lev", "Burundian Franc", "Cambodian Riel", "Canadian Dollar", "Cape Verdean Escudo", "Cayman Islands Dollar", "Central African Cfa Franc", "Cfp Franc", "Chilean Peso", "Chinese Renminbi Yuan", "Chinese Renminbi Yuan Offshore", "Codes specifically reserved for testing purposes", "Colombian Peso", "Comorian Franc", "Congolese Franc", "Costa Rican Colón", "Croatian Kuna", "Cuban Convertible Peso", "Cuban Peso", "Czech Koruna", "Danish Krone", "Djiboutian Franc", "Dominican Peso", "East Caribbean Dollar", "Egyptian Pound", "Eritrean Nakfa", "Estonian Kroon", "Ethiopian Birr", "Euro", "European Composite Unit", "European Monetary Unit", "European Unit of Account 17", "European Unit of Account 9", "Falkland Pound", "Fijian Dollar", "Gambian Dalasi", "Georgian Lari", "Ghanaian Cedi", "Gibraltar Pound", "Gold (Troy Ounce)", "Guatemalan Quetzal", "Guernsey Pound", "Guinean Franc", "Guyanese Dollar", "Haitian Gourde", "Honduran Lempira", "Hong Kong Dollar", "Hungarian Forint", "Icelandic Króna", "Indian Rupee", "Indonesian Rupiah", "Iranian Rial", "Iraqi Dinar", "Isle of Man Pound", "Israeli New Sheqel", "Jamaican Dollar", "Japanese Yen", "Jersey Pound", "Jordanian Dinar", "Kazakhstani Tenge", "Kenyan Shilling", "Kuwaiti Dinar", "Kyrgyzstani Som", "Lao Kip", "Latvian Lats", "Lebanese Pound", "Lesotho Loti", "Liberian Dollar", "Libyan Dinar", "Lithuanian Litas", "Macanese Pataca", "Macedonian Denar", "Malagasy Ariary", "Malawian Kwacha", "Malaysian Ringgit", "Maldivian Rufiyaa", "Maltese Lira", "Mauritanian Ouguiya", "Mauritian Rupee", "Mexican Peso", "Moldovan Leu", "Mongolian Tögrög", "Moroccan Dirham", "Mozambican Metical", "Myanmar Kyat", "Namibian Dollar", "Nepalese Rupee", "Netherlands Antillean Gulden", "New Taiwan Dollar", "New Zealand Dollar", "Nicaraguan Córdoba", "Nigerian Naira", "North Korean Won", "Norwegian Krone", "Omani Rial", "Pakistani Rupee", "Palladium", "Panamanian Balboa", "Papua New Guinean Kina", "Paraguayan Guaraní", "Peruvian Sol", "Philippine Peso", "Platinum", "Polish Złoty", "Qatari Riyal", "Romanian Leu", "Russian Ruble", "Rwandan Franc", "Saint Helenian Pound", "Salvadoran Colón", "Samoan Tala", "Saudi Riyal", "Serbian Dinar", "Seychellois Rupee", "Sierra Leonean Leone", "Silver (Troy Ounce)", "Singapore Dollar", "Slovak Koruna", "Solomon Islands Dollar", "Somali Shilling", "South African Rand", "South Korean Won", "South Sudanese Pound", "Special Drawing Rights", "Sri Lankan Rupee", "Sudanese Pound", "Surinamese Dollar", "Swazi Lilangeni", "Swedish Krona", "Swiss Franc", "Syrian Pound", "São Tomé and Príncipe Dobra", "Tajikistani Somoni", "Tanzanian Shilling", "Thai Baht", "Tongan Paʻanga", "Trinidad and Tobago Dollar", "Tunisian Dinar", "Turkish Lira", "Turkmenistani Manat", "UIC Franc", "Ugandan Shilling", "Ukrainian Hryvnia", "Unidad de Fomento", "United Arab Emirates Dirham", "United States Dollar", "Uruguayan Peso", "Uzbekistan Som", "Vanuatu Vatu", "Venezuelan Bolívar", "Venezuelan Bolívar Soberano", "Vietnamese Đồng", "West African Cfa Franc", "Yemeni Rial", "Zambian Kwacha", "Zimbabwean Dollar"}, 5 | "code": {"AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN", "BAM", "BBD", "BCH", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BRL", "BSD", "BTC", "BTN", "BWP", "BYN", "BYR", "BZD", "CAD", "CDF", "CHF", "CLF", "CLP", "CNH", "CNY", "COP", "CRC", "CUC", "CUP", "CVE", "CZK", "DJF", "DKK", "DOP", "DZD", "EEK", "EGP", "ERN", "ETB", "EUR", "FJD", "FKP", "GBP", "GBX", "GEL", "GGP", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD", "HKD", "HNL", "HRK", "HTG", "HUF", "IDR", "ILS", "IMP", "INR", "IQD", "IRR", "ISK", "JEP", "JMD", "JOD", "JPY", "KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT", "LAK", "LBP", "LKR", "LRD", "LSL", "LTL", "LVL", "LYD", "MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRO", "MRU", "MTL", "MUR", "MVR", "MWK", "MXN", "MYR", "MZN", "NAD", "NGN", "NIO", "NOK", "NPR", "NZD", "OMR", "PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG", "QAR", "RON", "RSD", "RUB", "RWF", "SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SKK", "SLL", "SOS", "SRD", "SSP", "STD", "SVC", "SYP", "SZL", "THB", "TJS", "TMM", "TMT", "TND", "TOP", "TRY", "TTD", "TWD", "TZS", "UAH", "UGX", "USD", "UYU", "UZS", "VEF", "VES", "VND", "VUV", "WST", "XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XFU", "XOF", "XPD", "XPF", "XPT", "XTS", "YER", "ZAR", "ZMK", "ZMW", "ZWD", "ZWL", "ZWN", "ZWR"}, 6 | "symbol": {"$", "Ar", "B/.", "Br", "Bs", "Bs.", "Bs.F", "C$", "CHF", "D", "Db", "E", "FRw", "Fdj", "Fr", "Ft", "G", "K", "KR", "KSh", "Kz", "Kč", "L", "Le", "Lei", "Ls", "Lt", "MK", "MTn", "MVR", "Nfk", "Nu.", "P", "Q", "R", "R$", "RM", "Rp", "S/", "SDR", "Sh", "Sk", "T", "T$", "UF", "UM", "USh", "Vt", "ZK", "kn", "kr", "kr.", "m", "oz t", "so'm", "som", "zł", "£", "£S", "¥", "ƒ", "ЅМ", "КМ", "РСД", "ден", "лв.", "դր.", "؋", "ب.د", "ج.م", "د.إ", "د.ا", "د.ت", "د.ج", "د.ك", "د.م.", "ر.س", "ر.ع.", "ر.ق", "ع.د", "ل.د", "ل.ل", "৳", "฿", "ლ", "៛", "₡", "₤", "₦", "₨", "₩", "₪", "₫", "€", "₭", "₮", "₱", "₲", "₴", "₵", "₸", "₹", "₺", "₼", "₽", "₿", "﷼"}, 7 | } 8 | 9 | // CurrencyName will build a random currency name string. 10 | func CurrencyName() string { 11 | value, _ := GetData("currency", "name") 12 | return value.(string) 13 | } 14 | 15 | // CurrencyCode will build a random currency code string. 16 | func CurrencyCode() string { 17 | value, _ := GetData("currency", "code") 18 | return value.(string) 19 | } 20 | 21 | // CurrencySymbol will build a random currency symbol string. 22 | func CurrencySymbol() string { 23 | value, _ := GetData("currency", "symbol") 24 | return value.(string) 25 | } 26 | 27 | // Builder functions 28 | 29 | func currencyNameBuilder(params ...string) (interface{}, error) { 30 | return CurrencyName(), nil 31 | } 32 | 33 | func currencyCodeBuilder(params ...string) (interface{}, error) { 34 | return CurrencyCode(), nil 35 | } 36 | 37 | func currencySymbolBuilder(params ...string) (interface{}, error) { 38 | return CurrencySymbol(), nil 39 | } 40 | -------------------------------------------------------------------------------- /currency_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleCurrencyName() { 12 | faker.SetSeed(1200) 13 | fmt.Println(faker.CurrencyName()) 14 | // Output: Sierra Leonean Leone 15 | } 16 | 17 | func ExampleCurrencyCode() { 18 | faker.SetSeed(1201) 19 | fmt.Println(faker.CurrencyCode()) 20 | // Output: XOF 21 | } 22 | 23 | func ExampleCurrencySymbol() { 24 | faker.SetSeed(1202) 25 | fmt.Println(faker.CurrencySymbol()) 26 | // Output: ₮ 27 | } 28 | 29 | func TestCurrencyBuild(t *testing.T) { 30 | faker.SetSeed(1210) 31 | s := &struct { 32 | Field1 string `faker:"CurrencyName"` 33 | Field2 string `faker:"CurrencyCode"` 34 | Field3 string `faker:"CurrencySymbol"` 35 | }{} 36 | err := faker.Build(&s) 37 | assert.Nil(t, err) 38 | t.Log(s) 39 | assert.Equal(t, "Bermudian Dollar", s.Field1) 40 | assert.Equal(t, "XCD", s.Field2) 41 | assert.Equal(t, "K", s.Field3) 42 | } 43 | -------------------------------------------------------------------------------- /faker.go: -------------------------------------------------------------------------------- 1 | // Package faker is a random data generator and struct fake data generator. 2 | package faker 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | "reflect" 8 | "regexp" 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | const ( 14 | tagName = "faker" 15 | skipTag = "-" 16 | uniqueTag = "unique" 17 | ) 18 | 19 | var ( 20 | tagFnCallRegexp = regexp.MustCompile(`(.+?)\((.+?)\)`) 21 | tagLenRegexp = regexp.MustCompile(`len=(\d+)`) 22 | tagSkipIfRegexp = regexp.MustCompile(`skip\s+if\s+(\w+)`) 23 | ) 24 | 25 | type fakerTag struct { 26 | funcName string 27 | skipIf string 28 | uniqueGroup string 29 | length int 30 | params []string 31 | } 32 | 33 | func (tag *fakerTag) mustSkip() bool { 34 | return tag.funcName == skipTag 35 | } 36 | 37 | // func decodeTag(tagString string) *fakerTag { 38 | func decodeTag(structReflectType reflect.Type, fieldIndex int) *fakerTag { 39 | fieldReflectType := structReflectType.Field(fieldIndex) 40 | tagString := fieldReflectType.Tag.Get(tagName) 41 | tag := &fakerTag{} 42 | for _, token := range strings.Split(tagString, ";") { 43 | if token == skipTag { 44 | tag.funcName = skipTag 45 | return tag 46 | } 47 | if m := tagSkipIfRegexp.FindStringSubmatch(token); len(m) == 2 { 48 | tag.skipIf = m[1] 49 | continue 50 | } 51 | if token == uniqueTag { 52 | tag.uniqueGroup = fmt.Sprintf("%s-%s", structReflectType.Name(), fieldReflectType.Name) 53 | continue 54 | } 55 | if m := tagLenRegexp.FindStringSubmatch(token); len(m) == 2 { 56 | tag.length, _ = strconv.Atoi(m[1]) 57 | continue 58 | } 59 | if tag.funcName == "" { 60 | if m := tagFnCallRegexp.FindStringSubmatch(token); len(m) == 3 { 61 | tag.funcName = m[1] 62 | tag.params = strings.Split(m[2], ",") 63 | continue 64 | } 65 | tag.funcName = token 66 | } 67 | } 68 | return tag 69 | } 70 | 71 | // Build fills in exported elements of a struct with random data based on the 72 | // value of `faker` tag of exported elements. The faker tag value can be any 73 | // available function (case insensitive). 74 | // 75 | // Use `faker:"-"` to explicitly skip an element. 76 | // 77 | // Use `faker:"skip if FieldName"` to explicitly skip this field if another 78 | // field (FieldName) is not empty. 79 | // 80 | // Use `faker:"unique"` to guarantee a unique value. 81 | // 82 | // Use `faker:"len=x"` to specify the length of a slice or the size of a map 83 | // (if ommitted, will be generated a slice or map with random size between 1 84 | // and 8). 85 | // 86 | // Built-in supported types are: bool, int, int8, int16, int32, int64, uint, 87 | // uint8, uint16, uint32, uint64, float32, float64, string. Other standard 88 | // library supported types are time.Time and time.Duration. But is really easy 89 | // to extend faker to add other builders to support other types and or 90 | // customize faker's behavior (see RegisterBuilder function). 91 | func Build(input interface{}) error { 92 | inputReflectType := reflect.TypeOf(input) 93 | if inputReflectType == nil { 94 | return errors.New("faker.Build input interface{} not allowed") 95 | } 96 | if inputReflectType.Kind() != reflect.Ptr { 97 | return errors.New("faker.Build input is not a pointer") 98 | } 99 | 100 | parentReflectTypes := make(map[reflect.Type]struct{}) 101 | inputReflectValue := reflect.ValueOf(input) 102 | err := build(inputReflectValue, parentReflectTypes, &fakerTag{}) 103 | if err != nil { 104 | return err 105 | } 106 | return nil 107 | } 108 | 109 | func build(inputReflectValue reflect.Value, parentReflectTypes map[reflect.Type]struct{}, tag *fakerTag) error { 110 | inputReflectType := inputReflectValue.Type() 111 | kind := inputReflectType.Kind() 112 | 113 | var ( 114 | fn builderFunc 115 | found bool 116 | key string 117 | ) 118 | 119 | key = builderKey(tag.funcName, inputReflectType.String()) 120 | fn, found = builders[key] 121 | 122 | if found { 123 | if !inputReflectValue.IsZero() { 124 | return nil 125 | } 126 | var ( 127 | value interface{} 128 | err error 129 | ) 130 | if tag.uniqueGroup != "" { 131 | value, err = Uniq(tag.uniqueGroup, 0, func() (interface{}, error) { 132 | return fn(tag.params...) 133 | }) 134 | } else { 135 | value, err = fn(tag.params...) 136 | } 137 | if err != nil { 138 | return err 139 | } 140 | inputReflectValue.Set(reflect.ValueOf(value)) 141 | return nil 142 | } 143 | 144 | switch kind { 145 | case reflect.Ptr: 146 | return buildPtr(inputReflectValue, inputReflectType, parentReflectTypes, tag) 147 | case reflect.Struct: 148 | return buildStruct(inputReflectValue, inputReflectType, parentReflectTypes, tag) 149 | case reflect.Slice: 150 | return buildSlice(inputReflectValue, inputReflectType, parentReflectTypes, tag) 151 | case reflect.Map: 152 | return buildMap(inputReflectValue, inputReflectType, parentReflectTypes, tag) 153 | default: 154 | if tag.funcName != "" { 155 | return fmt.Errorf("invalid faker function '%s' for type '%s'", tag.funcName, inputReflectType.String()) 156 | } 157 | return nil 158 | } 159 | } 160 | 161 | func buildPtr(inputReflectValue reflect.Value, inputReflectType reflect.Type, parentReflectTypes map[reflect.Type]struct{}, tag *fakerTag) error { 162 | if detectInfiniteLoopRecursion(parentReflectTypes, inputReflectType) { 163 | return nil 164 | } 165 | if inputReflectValue.IsNil() { 166 | newVar := reflect.New(inputReflectType.Elem()) 167 | inputReflectValue.Set(newVar) 168 | } 169 | return build(inputReflectValue.Elem(), parentReflectTypes, tag) 170 | } 171 | 172 | func buildStruct(inputReflectValue reflect.Value, inputReflectType reflect.Type, parentReflectTypes map[reflect.Type]struct{}, tag *fakerTag) error { 173 | if detectInfiniteLoopRecursion(parentReflectTypes, inputReflectType) { 174 | return nil 175 | } 176 | parentReflectTypesCopy := make(map[reflect.Type]struct{}) 177 | for k, v := range parentReflectTypes { 178 | parentReflectTypesCopy[k] = v 179 | } 180 | parentReflectTypesCopy[inputReflectType] = struct{}{} 181 | for i := 0; i < inputReflectValue.NumField(); i++ { 182 | fieldTag := decodeTag(inputReflectType, i) 183 | if fieldTag.mustSkip() { 184 | continue 185 | } 186 | if fieldTag.skipIf != "" { 187 | skipIfReflectValue := inputReflectValue.FieldByName(fieldTag.skipIf) 188 | if (skipIfReflectValue != reflect.Value{}) && !skipIfReflectValue.IsZero() { 189 | continue 190 | } 191 | } 192 | if !inputReflectValue.Field(i).CanSet() { 193 | continue // to avoid panic to set on unexported field in struct 194 | } 195 | err := build(inputReflectValue.Field(i), parentReflectTypesCopy, fieldTag) 196 | if err != nil { 197 | return err 198 | } 199 | } 200 | return nil 201 | } 202 | 203 | func buildSlice(inputReflectValue reflect.Value, inputReflectType reflect.Type, parentReflectTypes map[reflect.Type]struct{}, tag *fakerTag) error { 204 | if detectInfiniteLoopRecursion(parentReflectTypes, inputReflectType.Elem()) { 205 | return nil 206 | } 207 | if inputReflectValue.IsNil() { 208 | var sliceLen int 209 | if tag != nil && tag.length != 0 { 210 | sliceLen = tag.length 211 | } else { 212 | sliceLen = IntInRange(1, 8) 213 | } 214 | newSlice := reflect.MakeSlice(inputReflectType, sliceLen, sliceLen) 215 | inputReflectValue.Set(newSlice) 216 | return buildSliceElems(inputReflectValue, parentReflectTypes, tag) 217 | } 218 | if len(parentReflectTypes) == 0 { 219 | return buildSliceElems(inputReflectValue, parentReflectTypes, tag) 220 | } 221 | return nil 222 | } 223 | 224 | func buildMap(inputReflectValue reflect.Value, inputReflectType reflect.Type, parentReflectTypes map[reflect.Type]struct{}, tag *fakerTag) error { 225 | keyReflectType := inputReflectType.Key() 226 | if detectInfiniteLoopRecursion(parentReflectTypes, keyReflectType) { 227 | return nil 228 | } 229 | elemReflectType := inputReflectType.Elem() 230 | if detectInfiniteLoopRecursion(parentReflectTypes, elemReflectType) { 231 | return nil 232 | } 233 | if inputReflectValue.IsNil() { 234 | var ( 235 | mapLen int 236 | key reflect.Value 237 | elem reflect.Value 238 | err error 239 | ) 240 | if tag != nil && tag.length != 0 { 241 | mapLen = tag.length 242 | } else { 243 | mapLen = IntInRange(1, 8) 244 | } 245 | newMap := reflect.MakeMap(inputReflectType) 246 | for i := 0; i < mapLen; i++ { 247 | key = reflect.New(keyReflectType).Elem() 248 | elem = reflect.New(elemReflectType).Elem() 249 | err = build(key, parentReflectTypes, tag) 250 | if err != nil { 251 | return err 252 | } 253 | err = build(elem, parentReflectTypes, tag) 254 | if err != nil { 255 | return err 256 | } 257 | newMap.SetMapIndex(key, elem) 258 | } 259 | inputReflectValue.Set(newMap) 260 | } 261 | return nil 262 | } 263 | 264 | func buildSliceElems(inputReflectValue reflect.Value, parentReflectTypes map[reflect.Type]struct{}, tag *fakerTag) error { 265 | for i := 0; i < inputReflectValue.Len(); i++ { 266 | err := build(inputReflectValue.Index(i), parentReflectTypes, tag) 267 | if err != nil { 268 | return err 269 | } 270 | } 271 | return nil 272 | } 273 | 274 | func detectInfiniteLoopRecursion(parentReflectTypes map[reflect.Type]struct{}, reflectType reflect.Type) bool { 275 | for { 276 | if reflectType.Kind() == reflect.Ptr { 277 | reflectType = reflectType.Elem() 278 | } else { 279 | break 280 | } 281 | } 282 | _, found := parentReflectTypes[reflectType] 283 | return found 284 | } 285 | -------------------------------------------------------------------------------- /faker_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "testing" 7 | "time" 8 | 9 | "github.com/pioz/faker" 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestPtrBuild(t *testing.T) { 14 | faker.SetSeed(601) 15 | s := &struct { 16 | IntField int 17 | PtrIntField *int 18 | }{} 19 | err := faker.Build(&s) 20 | assert.Nil(t, err) 21 | t.Log(s) 22 | assert.Equal(t, 1222834422, s.IntField) 23 | assert.Equal(t, 1743740582, *s.PtrIntField) 24 | } 25 | 26 | func TestArgumentSliceBuild(t *testing.T) { 27 | faker.SetSeed(605) 28 | slice := make([]string, 2) 29 | err := faker.Build(&slice) 30 | assert.Nil(t, err) 31 | assert.Equal(t, "BlRzrRA", slice[0]) 32 | assert.Equal(t, "SHevwfBd", slice[1]) 33 | } 34 | 35 | func TestArgumentSliceNotAllZeroBuild(t *testing.T) { 36 | faker.SetSeed(606) 37 | slice := make([]string, 2) 38 | slice[0] = "test" 39 | err := faker.Build(&slice) 40 | assert.Nil(t, err) 41 | assert.Equal(t, "test", slice[0]) 42 | assert.Equal(t, "typkI", slice[1]) 43 | } 44 | 45 | func TestSliceBuild(t *testing.T) { 46 | faker.SetSeed(600) 47 | s := &struct { 48 | SliceIntField []int `faker:"len=1"` 49 | PtrSliceIntField *[]int `faker:"len=2"` 50 | SlicePtrIntField []*int `faker:"len=3"` 51 | SliceIntField2 []int 52 | }{} 53 | 54 | err := faker.Build(&s) 55 | assert.Nil(t, err) 56 | t.Log(s) 57 | 58 | assert.Equal(t, 1, len(s.SliceIntField)) 59 | assert.Equal(t, -1982024679, s.SliceIntField[0]) 60 | 61 | assert.Equal(t, 2, len(*s.PtrSliceIntField)) 62 | assert.Equal(t, 818547590, (*s.PtrSliceIntField)[0]) 63 | assert.Equal(t, -1723388666, (*s.PtrSliceIntField)[1]) 64 | 65 | assert.Equal(t, 3, len(s.SlicePtrIntField)) 66 | assert.Equal(t, -152085377, *s.SlicePtrIntField[0]) 67 | assert.Equal(t, 1775168364, *s.SlicePtrIntField[1]) 68 | assert.Equal(t, 546278985, *s.SlicePtrIntField[2]) 69 | 70 | assert.Equal(t, 5, len(s.SliceIntField2)) 71 | 72 | s.SliceIntField = []int{0, 1, 2, 3} 73 | err = faker.Build(&s) 74 | assert.Nil(t, err) 75 | assert.Equal(t, 0, s.SliceIntField[0]) 76 | } 77 | 78 | func TestMapBuild(t *testing.T) { 79 | faker.SetSeed(604) 80 | s := &struct { 81 | Field1 map[string]int `faker:"len=1"` 82 | Field2 *map[int]time.Duration `faker:"len=2"` 83 | Field3 map[int]*int `faker:"len=2"` 84 | Field4 map[*int]int `faker:"len=2"` 85 | Field5 map[*int]*int `faker:"len=2"` 86 | Field6 map[int]int 87 | }{} 88 | 89 | err := faker.Build(&s) 90 | assert.Nil(t, err) 91 | t.Log(s) 92 | t.Log(s.Field2) 93 | 94 | assert.Equal(t, 1, len(s.Field1)) 95 | assert.Equal(t, 414796793, s.Field1["pBrjY"]) 96 | 97 | assert.Equal(t, 2, len(*s.Field2)) 98 | assert.Equal(t, "-1670489h52m2.887881426s", (*s.Field2)[-244204264].String()) 99 | assert.Equal(t, "-13678h42m55.366897902s", (*s.Field2)[1577669889].String()) 100 | 101 | assert.Equal(t, 2, len(s.Field3)) 102 | assert.Equal(t, 2027576377, *s.Field3[-1215017291]) 103 | assert.Equal(t, -1688325745, *s.Field3[2062137016]) 104 | 105 | assert.Equal(t, 2, len(s.Field4)) 106 | assert.Equal(t, 2, len(s.Field5)) 107 | 108 | assert.Equal(t, 4, len(s.Field6)) 109 | assert.Equal(t, -1762085720, s.Field6[-1847156268]) 110 | } 111 | 112 | func TestTagFuncCallBuild(t *testing.T) { 113 | err := faker.RegisterBuilder("Ping", "string", func(params ...string) (interface{}, error) { 114 | return "pong", nil 115 | }) 116 | assert.Nil(t, err) 117 | 118 | s := &struct { 119 | Ping string `faker:"Ping"` 120 | }{} 121 | 122 | err = faker.Build(&s) 123 | assert.Nil(t, err) 124 | t.Log(s) 125 | 126 | assert.Equal(t, "pong", s.Ping) 127 | err = faker.UnregisterBuilder("Ping", "string") 128 | assert.Nil(t, err) 129 | } 130 | 131 | func TestTagFuncCallCaseSensitiveBuild(t *testing.T) { 132 | err := faker.RegisterBuilder("Ping", "string", func(params ...string) (interface{}, error) { 133 | return "pong", nil 134 | }) 135 | assert.Nil(t, err) 136 | 137 | s := &struct { 138 | Ping1 string `faker:"Ping"` 139 | Ping2 string `faker:"PING"` 140 | Ping3 string `faker:"ping"` 141 | Ping4 string `faker:"pInG"` 142 | Ping5 string `faker:"ping(a,b,c)"` 143 | }{} 144 | 145 | err = faker.Build(&s) 146 | assert.Nil(t, err) 147 | t.Log(s) 148 | 149 | assert.Equal(t, "pong", s.Ping1) 150 | assert.Equal(t, "pong", s.Ping2) 151 | assert.Equal(t, "pong", s.Ping3) 152 | assert.Equal(t, "pong", s.Ping4) 153 | assert.Equal(t, "pong", s.Ping5) 154 | err = faker.UnregisterBuilder("Ping", "string") 155 | assert.Nil(t, err) 156 | } 157 | 158 | func TestTagFuncCallWithParamsBuild(t *testing.T) { 159 | err := faker.RegisterBuilder("Temperature", "string", func(params ...string) (interface{}, error) { 160 | if len(params) == 1 { 161 | return params[0], nil 162 | } 163 | return "nil", nil 164 | }) 165 | assert.Nil(t, err) 166 | 167 | s := &struct { 168 | Temp1 string `faker:"Temperature"` 169 | Temp2 string `faker:"Temperature(hot)"` 170 | }{} 171 | 172 | err = faker.Build(&s) 173 | assert.Nil(t, err) 174 | t.Log(s) 175 | 176 | assert.Equal(t, "nil", s.Temp1) 177 | assert.Equal(t, "hot", s.Temp2) 178 | } 179 | 180 | func TestTagFuncCallReturnErrorBuild(t *testing.T) { 181 | err := faker.RegisterBuilder("Error", "string", func(params ...string) (interface{}, error) { 182 | return nil, errors.New("this is an error") 183 | }) 184 | assert.Nil(t, err) 185 | 186 | s := &struct { 187 | Err string `faker:"Error"` 188 | }{} 189 | 190 | err = faker.Build(&s) 191 | assert.NotNil(t, err) 192 | assert.Equal(t, "this is an error", err.Error()) 193 | } 194 | 195 | func TestTagFuncCallNotSupportedTypeBuild(t *testing.T) { 196 | err := faker.RegisterBuilder("Ping", "string", func(params ...string) (interface{}, error) { 197 | return "pong", nil 198 | }) 199 | assert.Nil(t, err) 200 | 201 | s := &struct { 202 | Ping int `faker:"Ping"` 203 | }{} 204 | 205 | err = faker.Build(&s) 206 | assert.NotNil(t, err) 207 | assert.Equal(t, "invalid faker function 'Ping' for type 'int'", err.Error()) 208 | err = faker.UnregisterBuilder("Ping", "string") 209 | assert.Nil(t, err) 210 | } 211 | 212 | func TestNoErrorOnNotSupportedType(t *testing.T) { 213 | s := &struct { 214 | Channel chan int 215 | }{} 216 | 217 | err := faker.Build(&s) 218 | assert.Nil(t, err) 219 | assert.Equal(t, chan int(nil), s.Channel) 220 | } 221 | 222 | func TestNotEmptyValueBuild(t *testing.T) { 223 | faker.SetSeed(603) 224 | s := &struct { 225 | Field1 int 226 | Field2 int 227 | }{Field2: 21} 228 | 229 | err := faker.Build(&s) 230 | assert.Nil(t, err) 231 | assert.Equal(t, -236043479, s.Field1) 232 | assert.Equal(t, 21, s.Field2) 233 | } 234 | 235 | func TestSkipTag(t *testing.T) { 236 | s := &struct { 237 | Field int `faker:"-"` 238 | PtrField *int `faker:"-"` 239 | }{} 240 | 241 | err := faker.Build(&s) 242 | assert.Nil(t, err) 243 | t.Log(s) 244 | 245 | assert.Empty(t, s.Field) 246 | assert.Nil(t, s.PtrField) 247 | } 248 | 249 | func TestSkipIfTag(t *testing.T) { 250 | faker.SetSeed(607) 251 | s := &struct { 252 | Field1 string 253 | Field2 string `faker:"skip if Field1"` 254 | Field3 *int `faker:"skip if Field1;IntInRange(0,10)"` 255 | Field4 string `faker:"skip if NotExistingFieldName;FirstName"` 256 | }{Field1: "Amazing"} 257 | 258 | err := faker.Build(&s) 259 | assert.Nil(t, err) 260 | t.Log(s) 261 | 262 | assert.Equal(t, s.Field1, "Amazing") 263 | assert.Empty(t, s.Field2) 264 | assert.Nil(t, s.Field3) 265 | assert.Equal(t, s.Field4, "Corey") 266 | } 267 | 268 | func TestUniqueTag(t *testing.T) { 269 | faker.SetSeed(602) 270 | type CustomType1 struct { 271 | Field1 int `faker:"IntInRange(0,1);unique"` 272 | Field2 int `faker:"IntInRange(0,1);unique"` 273 | } 274 | type CustomType2 struct { 275 | Field1 int `faker:"IntInRange(0,1);unique"` 276 | Field2 int `faker:"IntInRange(0,1);unique"` 277 | } 278 | 279 | ct11 := CustomType1{} 280 | err := faker.Build(&ct11) 281 | assert.Nil(t, err) 282 | t.Log(ct11) 283 | assert.Equal(t, 1, ct11.Field1) 284 | assert.Equal(t, 1, ct11.Field2) 285 | 286 | ct12 := CustomType1{} 287 | err = faker.Build(&ct12) 288 | assert.Nil(t, err) 289 | t.Log(ct12) 290 | assert.Equal(t, 0, ct12.Field1) 291 | assert.Equal(t, 0, ct12.Field2) 292 | 293 | ct13 := CustomType1{} 294 | err = faker.Build(&ct13) 295 | assert.NotNil(t, err) 296 | assert.Equal(t, "failed to generate a unique value for group 'CustomType1-Field1'", err.Error()) 297 | 298 | ct21 := CustomType2{} 299 | err = faker.Build(&ct21) 300 | assert.Nil(t, err) 301 | t.Log(ct21) 302 | assert.Equal(t, 0, ct21.Field1) 303 | assert.Equal(t, 1, ct21.Field2) 304 | } 305 | 306 | func TestInterfaceNotAllowed(t *testing.T) { 307 | var i interface{} 308 | err := faker.Build(i) 309 | assert.NotNil(t, err) 310 | assert.Equal(t, "faker.Build input interface{} not allowed", err.Error()) 311 | } 312 | 313 | func TestNoPtrNotAllowed(t *testing.T) { 314 | var i int 315 | err := faker.Build(i) 316 | assert.NotNil(t, err) 317 | assert.Equal(t, "faker.Build input is not a pointer", err.Error()) 318 | } 319 | 320 | func TestNilNotAllowed(t *testing.T) { 321 | err := faker.Build(nil) 322 | assert.NotNil(t, err) 323 | assert.Equal(t, "faker.Build input interface{} not allowed", err.Error()) 324 | } 325 | 326 | func TestWorkWithPrivateFields(t *testing.T) { 327 | faker.SetSeed(624) 328 | s := &struct { 329 | PublicField int 330 | privateField int 331 | }{} 332 | err := faker.Build(&s) 333 | assert.Nil(t, err) 334 | } 335 | 336 | func TestErrOnSliceBuild(t *testing.T) { 337 | faker.SetSeed(625) 338 | s := &struct { 339 | Field []int `faker:"StringWithSize(3)"` 340 | }{} 341 | err := faker.Build(&s) 342 | assert.NotNil(t, err) 343 | assert.Equal(t, "invalid faker function 'StringWithSize' for type 'int'", err.Error()) 344 | } 345 | 346 | func TestErrOnMapKeyBuild(t *testing.T) { 347 | faker.SetSeed(626) 348 | s := &struct { 349 | Field map[int]bool `faker:"StringWithSize(3)"` 350 | }{} 351 | err := faker.Build(&s) 352 | assert.NotNil(t, err) 353 | assert.Equal(t, "invalid faker function 'StringWithSize' for type 'int'", err.Error()) 354 | } 355 | 356 | func TestErrOnMapValueBuild(t *testing.T) { 357 | faker.SetSeed(627) 358 | s := &struct { 359 | Field map[int]bool `faker:"IntInRange(1,3)"` 360 | }{} 361 | err := faker.Build(&s) 362 | t.Log(s) 363 | assert.NotNil(t, err) 364 | // assert.Equal(t, "invalid faker function 'IntInRange' for type 'bool'", err.Error()) 365 | } 366 | 367 | type testRec1 struct { 368 | Name string 369 | Parent1 *testRec1 370 | Parent2 **testRec1 371 | Parents1 []testRec1 372 | Parents2 map[*testRec1]string 373 | Parents3 map[string]testRec1 374 | Child *testRec2 375 | } 376 | 377 | type testRec2 struct { 378 | Name string 379 | Parent1 testRec1 380 | Parent2 *testRec1 381 | } 382 | 383 | func TestRecursiveStructBuild(t *testing.T) { 384 | faker.SetSeed(621) 385 | s := testRec1{} 386 | err := faker.Build(&s) 387 | assert.Nil(t, err) 388 | t.Log(s) 389 | 390 | assert.Equal(t, "rpC", s.Name) 391 | assert.Nil(t, s.Parent1) 392 | assert.Nil(t, s.Parent2) 393 | assert.Nil(t, s.Parents1) 394 | assert.Nil(t, s.Parents2) 395 | assert.Nil(t, s.Parents3) 396 | assert.Equal(t, "QtCMxnMc", s.Child.Name) 397 | assert.Empty(t, s.Child.Parent1) 398 | assert.Nil(t, s.Child.Parent2) 399 | } 400 | 401 | type userTest struct { 402 | Username string `faker:"username"` 403 | Email string `faker:"email"` 404 | Comments []string `faker:"sentence;len=3"` 405 | Feedbacks map[string]int `faker:"feedbacks"` 406 | FakeFeedbacks map[string]int 407 | } 408 | 409 | // Generic quite complete test on struct 410 | func TestStructBuild(t *testing.T) { 411 | faker.SetSeed(620) 412 | err := faker.RegisterBuilder("coin", "string", func(...string) (interface{}, error) { 413 | if faker.Bool() { 414 | return "head", nil 415 | } else { 416 | return "tail", nil 417 | } 418 | }) 419 | assert.Nil(t, err) 420 | 421 | err = faker.RegisterBuilder("feedbacks", "map[string]int", func(...string) (interface{}, error) { 422 | f := make(map[string]int) 423 | f["power"] = 2 424 | f["speed"] = 3 425 | f["intellect"] = 4 426 | return f, nil 427 | }) 428 | assert.Nil(t, err) 429 | 430 | s := &struct { 431 | Number1 int `faker:"intinrange(0,5)"` 432 | Number2 uint 433 | Coin string `faker:"coin"` 434 | List []int `faker:"len=4"` 435 | NotEmpty string 436 | Unknown chan int 437 | User1 userTest 438 | User2 *userTest 439 | }{NotEmpty: "not changed"} 440 | 441 | err = faker.Build(&s) 442 | assert.Nil(t, err) 443 | t.Log(s) 444 | t.Log(s.User2) 445 | assert.Equal(t, 3, s.Number1) 446 | assert.Equal(t, uint(1593375208), s.Number2) 447 | assert.Equal(t, "tail", s.Coin) 448 | assert.Equal(t, []int{-1641723469, -1455267700, -2127403521, -434130014}, s.List) 449 | assert.Equal(t, "not changed", s.NotEmpty) 450 | assert.Equal(t, chan int(nil), s.Unknown) 451 | 452 | assert.Equal(t, "chorizo", s.User1.Username) 453 | assert.Equal(t, "anguished@retool.name", s.User1.Email) 454 | assert.Equal(t, 3, len(s.User1.Comments)) 455 | assert.Equal(t, "Washing and polishing the car,a grape can hardly be considered a calm scorpion without also being an octopus.", s.User1.Comments[0]) 456 | assert.Equal(t, map[string]int{"power": 2, "speed": 3, "intellect": 4}, s.User1.Feedbacks) 457 | assert.Equal(t, 5, len(s.User1.FakeFeedbacks)) 458 | assert.Equal(t, 1279188829, s.User1.FakeFeedbacks["2ATA"]) 459 | 460 | assert.Equal(t, "kenakenaf", s.User2.Username) 461 | assert.Equal(t, "tingly@consubstantial.net", s.User2.Email) 462 | assert.Equal(t, 3, len(s.User2.Comments)) 463 | assert.Equal(t, "A kitten is a goldfish's peach?", s.User2.Comments[0]) 464 | assert.Equal(t, map[string]int{"power": 2, "speed": 3, "intellect": 4}, s.User2.Feedbacks) 465 | assert.Equal(t, 7, len(s.User2.FakeFeedbacks)) 466 | assert.Equal(t, 1093938837, s.User2.FakeFeedbacks["5yjaG"]) 467 | } 468 | 469 | func ExampleBuild() { 470 | faker.SetSeed(621) 471 | type Person struct { 472 | Name string `faker:"firstName"` 473 | City string `faker:"addressCity"` 474 | Age int `faker:"intinrange(0,120)"` 475 | Code string 476 | UUID string `faker:"uuid;unique"` 477 | Number int 478 | } 479 | 480 | p := Person{} 481 | err := faker.Build(&p) 482 | if err != nil { 483 | panic(err) 484 | } 485 | fmt.Println(p.Name) 486 | fmt.Println(p.City) 487 | fmt.Println(p.Age) 488 | fmt.Println(p.Code) 489 | fmt.Println(p.UUID) 490 | fmt.Println(p.Number) 491 | // Output: Elizabeth 492 | // Thai Nguyen 493 | // 7 494 | // QtCMxnMc 495 | // 566235bc-4211-4ff2-b966-fa2d49d2b167 496 | // 1267435813 497 | } 498 | 499 | func ExampleBuild_recursive() { 500 | faker.SetSeed(622) 501 | 502 | // Define a new builder 503 | colorBuilder := func(params ...string) (interface{}, error) { 504 | return faker.Pick("Red", "Yellow", "Blue", "Black", "White"), nil 505 | } 506 | 507 | // Register a new builder named "color" for string type 508 | err := faker.RegisterBuilder("color", "string", colorBuilder) 509 | if err != nil { 510 | panic(err) 511 | } 512 | 513 | type Animal struct { 514 | Name string `faker:"username"` 515 | Color string `faker:"color"` // Use custom color builder 516 | } 517 | 518 | type Person struct { 519 | FirstName string `faker:"firstName"` // Any available function case insensitive 520 | LastName *string `faker:"lastName"` // Pointer are also supported 521 | Age int `faker:"intinrange(0,120)"` // Can call with parameters 522 | UUID string `faker:"uuid;unique"` // Guarantees a unique value 523 | Number int `faker:"-"` // Skip this field 524 | Code string // No tag to use default builder for this field type 525 | Pet Animal // Recursively fill this struct 526 | Nicknames []string `faker:"username;len=3"` // Build an array of size 3 using faker.Username function 527 | Extra map[string]string `faker:"stringWithSize(3);len=2"` // map are supported 528 | } 529 | 530 | p := Person{} 531 | err = faker.Build(&p) 532 | if err != nil { 533 | panic(err) 534 | } 535 | fmt.Println(p.FirstName) 536 | fmt.Println(*p.LastName) 537 | fmt.Println(p.Age) 538 | fmt.Println(p.UUID) 539 | fmt.Println(p.Number) 540 | fmt.Println(p.Code) 541 | fmt.Println(p.Pet.Name) 542 | fmt.Println(p.Pet.Color) 543 | fmt.Println(len(p.Nicknames)) 544 | fmt.Println(p.Nicknames[0]) 545 | fmt.Println(p.Nicknames[1]) 546 | fmt.Println(p.Nicknames[2]) 547 | fmt.Println(p.Extra) 548 | // Output: Wilber 549 | // Gutkowski 550 | // 25 551 | // ff8d6917-b920-46e6-b1be-dc2d48becfcb 552 | // 0 553 | // zN 554 | // clung 555 | // Red 556 | // 3 557 | // polypeptide 558 | // chinfest 559 | // chungchungking 560 | // map[0w3:F6Y QSi:sq7] 561 | } 562 | 563 | func ExampleBuild_factory() { 564 | faker.SetSeed(623) 565 | 566 | type User struct { 567 | Username string `faker:"username"` 568 | Email string `faker:"email"` 569 | Country string `faker:"CountryAlpha2"` 570 | } 571 | 572 | italianUserFactory := func() *User { 573 | u := &User{Country: "IT"} 574 | err := faker.Build(u) 575 | if err != nil { 576 | panic(err) 577 | } 578 | return u 579 | } 580 | 581 | italianUser := italianUserFactory() 582 | fmt.Println(italianUser) 583 | // Output: &{spicule hoag@ornamented.biz IT} 584 | } 585 | 586 | func ExampleBuild_array() { 587 | faker.SetSeed(623) 588 | 589 | type User struct { 590 | Username string `faker:"username"` 591 | Email string `faker:"email"` 592 | Country string `faker:"CountryAlpha2"` 593 | } 594 | 595 | // Build 3 users 596 | users := make([]User, 3) 597 | err := faker.Build(&users) 598 | if err != nil { 599 | panic(err) 600 | } 601 | fmt.Printf("%+v", users) 602 | // Output: [{Username:spicule Email:hoag@ornamented.biz Country:FI} {Username:twelvetone Email:mechanics@ramiform.name Country:TL} {Username:considerate Email:solnit@canonry.biz Country:TG}] 603 | } 604 | 605 | func ExampleBuild_conditionalSkip() { 606 | faker.SetSeed(623) 607 | 608 | type Author struct { 609 | Id uint64 `faker:"uint64inrange(1,10)"` 610 | Name string `faker:"FirstName"` 611 | } 612 | 613 | type Post struct { 614 | Title string `faker:"Sentence"` 615 | AuthorId uint64 `faker:"-"` 616 | Author *Author `faker:"skip if AuthorId"` 617 | } 618 | 619 | // Gen random Post with Author 620 | post1 := &Post{} 621 | err := faker.Build(&post1) 622 | if err != nil { 623 | panic(err) 624 | } 625 | 626 | // Gen random Post with same Author 627 | post2 := &Post{AuthorId: post1.Author.Id} 628 | err = faker.Build(&post2) 629 | if err != nil { 630 | panic(err) 631 | } 632 | 633 | fmt.Println(post1.Author.Id == post2.AuthorId) 634 | fmt.Println(post2.Author == nil) 635 | // Output: true 636 | // true 637 | } 638 | -------------------------------------------------------------------------------- /gender.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | var genderData = PoolGroup{ 4 | "types": {"Male", "Female", "Agender", "Androgyne", "Androgynous", "Bigender", "Cis", "Cisgender", "Cis Female", "Cis Male", "Cis Man", "Cis Woman", "Cisgender Female", "Cisgender Male", "Cisgender Man", "Cisgender Woman", "Female to Male", "FTM", "Gender Fluid", "Gender Nonconforming", "Gender Questioning", "Gender Variant", "Genderqueer", "Intersex", "Male to Female", "MTF", "Neither", "Neutrois", "Non-binary", "Other", "Pangender", "Trans", "Trans Female", "Trans Male", "Trans Man", "Trans Person", "Trans Woman", "Transfeminine", "Transgender", "Transgender Female", "Transgender Male", "Transgender Man", "Transgender Person", "Transgender Woman", "Transmasculine", "Transsexual", "Transsexual Female", "Transsexual Male", "Transsexual Man", "Transsexual Person", "Transsexual Woman", "Two-Spiri"}, 5 | "binary_types": {"Male", "Female"}, 6 | "short_binary_types": {"f", "m"}, 7 | } 8 | 9 | // Gender will build a random gender string. 10 | func Gender() string { 11 | value, _ := GetData("gender", "types") 12 | return value.(string) 13 | } 14 | 15 | // BinaryGender will build a random binary gender string (Male or Female). 16 | func BinaryGender() string { 17 | value, _ := GetData("gender", "binary_types") 18 | return value.(string) 19 | } 20 | 21 | // ShortBinaryGender will build a random short binary gender string (m or f). 22 | func ShortBinaryGender() string { 23 | value, _ := GetData("gender", "short_binary_types") 24 | return value.(string) 25 | } 26 | 27 | // Builder functions 28 | 29 | func genderBuilder(params ...string) (interface{}, error) { 30 | return Gender(), nil 31 | } 32 | 33 | func binaryGenderBuilder(params ...string) (interface{}, error) { 34 | return BinaryGender(), nil 35 | } 36 | 37 | func shortBinaryGenderBuilder(params ...string) (interface{}, error) { 38 | return ShortBinaryGender(), nil 39 | } 40 | -------------------------------------------------------------------------------- /gender_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleGender() { 12 | faker.SetSeed(1500) 13 | fmt.Println(faker.Gender()) 14 | // Output: Cisgender Male 15 | } 16 | 17 | func ExampleBinaryGender() { 18 | faker.SetSeed(1501) 19 | fmt.Println(faker.BinaryGender()) 20 | // Output: Male 21 | } 22 | 23 | func ExampleShortBinaryGender() { 24 | faker.SetSeed(1502) 25 | fmt.Println(faker.ShortBinaryGender()) 26 | // Output: m 27 | } 28 | 29 | func TestGenderBuild(t *testing.T) { 30 | faker.SetSeed(1520) 31 | s := &struct { 32 | Field1 string `faker:"Gender"` 33 | Field2 string `faker:"BinaryGender"` 34 | Field3 string `faker:"ShortBinaryGender"` 35 | }{} 36 | err := faker.Build(&s) 37 | assert.Nil(t, err) 38 | t.Log(s) 39 | assert.Equal(t, "Cis", s.Field1) 40 | assert.Equal(t, "Female", s.Field2) 41 | assert.Equal(t, "m", s.Field3) 42 | } 43 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pioz/faker 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/stretchr/testify v1.6.1 7 | ) 8 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 6 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 7 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 8 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 9 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 10 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 11 | -------------------------------------------------------------------------------- /init.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | var db = PoolData{ 4 | "address": addressData, 5 | "color": colorData, 6 | "country": countryData, 7 | "currency": currencyData, 8 | "gender": genderData, 9 | "internet": internetData, 10 | "lang": langData, 11 | "name": nameData, 12 | "sentence": sentenceData, 13 | "timezone": timezoneData, 14 | } 15 | 16 | var builders = map[string]builderFunc{ 17 | // address 18 | builderKey("AddressCity", "string"): addressCityBuilder, 19 | builderKey("AddressState", "string"): addressStateBuilder, 20 | builderKey("AddressStateCode", "string"): addressStateCodeBuilder, 21 | builderKey("AddressStreetName", "string"): addressStreetNameBuilder, 22 | builderKey("AddressStreetNumber", "string"): addressStreetNumberBuilder, 23 | builderKey("AddressSecondaryAddress", "string"): addressSecondaryAddressBuilder, 24 | builderKey("AddressZip", "string"): addressZipBuilder, 25 | builderKey("AddressFull", "string"): addressFullBuilder, 26 | // color 27 | builderKey("ColorName", "string"): colorNameBuilder, 28 | builderKey("ColorHex", "string"): colorHexBuilder, 29 | builderKey("ColorRGB", "[3]int"): colorRGBBuilder, 30 | builderKey("ColorHSL", "[3]int"): colorHSLBuilder, 31 | // country 32 | builderKey("CountryName", "string"): countryNameBuilder, 33 | builderKey("CountryAlpha2", "string"): countryAlpha2Builder, 34 | builderKey("CountryAlpha3", "string"): countryAlpha3Builder, 35 | builderKey("CountryNationality", "string"): countryNationalityBuilder, 36 | builderKey("CountryFlag", "string"): countryFlagBuilder, 37 | // currency 38 | builderKey("CurrencyName", "string"): currencyNameBuilder, 39 | builderKey("CurrencyCode", "string"): currencyCodeBuilder, 40 | builderKey("CurrencySymbol", "string"): currencySymbolBuilder, 41 | // gender 42 | builderKey("Gender", "string"): genderBuilder, 43 | builderKey("BinaryGender", "string"): binaryGenderBuilder, 44 | builderKey("ShortBinaryGender", "string"): shortBinaryGenderBuilder, 45 | // internet 46 | builderKey("Username", "string"): usernameBuilder, 47 | builderKey("Domain", "string"): domainBuilder, 48 | builderKey("Email", "string"): emailBuilder, 49 | builderKey("FreeEmail", "string"): freeEmailBuilder, 50 | builderKey("SafeEmail", "string"): safeEmailBuilder, 51 | builderKey("Slug", "string"): slugBuilder, 52 | builderKey("Url", "string"): urlBuilder, 53 | // lang 54 | builderKey("LangName", "string"): langNameBuilder, 55 | builderKey("LangCode", "string"): langCodeBuilder, 56 | // misc 57 | builderKey("Bool", "bool"): boolBuilder, 58 | builderKey("", "bool"): boolBuilder, 59 | builderKey("PhoneNumber", "string"): phoneNumberBuilder, 60 | builderKey("Uuid", "string"): uuidBuilder, 61 | // name 62 | builderKey("MaleFirstName", "string"): maleFirstNameBuilder, 63 | builderKey("FemaleFirstName", "string"): femaleFirstName, 64 | builderKey("NeutralFirstName", "string"): neutralFirstNameBuilder, 65 | builderKey("FirstName", "string"): firstNameBuilder, 66 | builderKey("LastName", "string"): lastNameBuilder, 67 | builderKey("NamePrefix", "string"): namePrefixBuilder, 68 | builderKey("NameSuffix", "string"): nameSuffixBuilder, 69 | builderKey("FullName", "string"): fullNameBuilder, 70 | builderKey("NameInitials", "string"): nameInitialsBuilder, 71 | // number 72 | builderKey("IntInRange", "int"): intInRangeBuilder, 73 | builderKey("Int", "int"): intBuilder, 74 | builderKey("", "int"): intBuilder, 75 | builderKey("Int64InRange", "int64"): int64InRangeBuilder, 76 | builderKey("Int64", "int64"): int64Builder, 77 | builderKey("", "int64"): int64Builder, 78 | builderKey("Int32InRange", "int32"): int32InRangeBuilder, 79 | builderKey("Int32", "int32"): int32Builder, 80 | builderKey("", "int32"): int32Builder, 81 | builderKey("Int16InRange", "int16"): int16InRangeBuilder, 82 | builderKey("Int16", "int16"): int16Builder, 83 | builderKey("", "int16"): int16Builder, 84 | builderKey("Int8InRange", "int8"): int8InRangeBuilder, 85 | builderKey("Int8", "int8"): int8Builder, 86 | builderKey("", "int8"): int8Builder, 87 | builderKey("UintInRange", "uint"): uintInRangeBuilder, 88 | builderKey("Uint", "uint"): uintBuilder, 89 | builderKey("", "uint"): uintBuilder, 90 | builderKey("Uint64InRange", "uint64"): uint64InRangeBuilder, 91 | builderKey("Uint64", "uint64"): uint64Builder, 92 | builderKey("", "uint64"): uint64Builder, 93 | builderKey("Uint32InRange", "uint32"): uint32InRangeBuilder, 94 | builderKey("Uint32", "uint32"): uint32Builder, 95 | builderKey("", "uint32"): uint32Builder, 96 | builderKey("Uint16InRange", "uint16"): uint16InRangeBuilder, 97 | builderKey("Uint16", "uint16"): uint16Builder, 98 | builderKey("", "uint16"): uint16Builder, 99 | builderKey("Uint8InRange", "uint8"): uint8InRangeBuilder, 100 | builderKey("Uint8", "uint8"): uint8Builder, 101 | builderKey("", "uint8"): uint8Builder, 102 | builderKey("Float64InRange", "float64"): float64InRangeBuilder, 103 | builderKey("Float64", "float64"): float64Builder, 104 | builderKey("", "float64"): float64Builder, 105 | builderKey("Float32InRange", "float32"): float32InRangeBuilder, 106 | builderKey("Float32", "float32"): float32Builder, 107 | builderKey("", "float32"): float32Builder, 108 | // sentence 109 | builderKey("Sentence", "string"): sentenceBuilder, 110 | builderKey("ParagraphWithSentenceCount", "string"): paragraphWithSentenceCountBuilder, 111 | builderKey("Paragraph", "string"): paragraphBuilder, 112 | builderKey("ArticleWithParagraphCount", "string"): articleWithParagraphCountBuilder, 113 | builderKey("Article", "string"): articleBuilder, 114 | // string 115 | builderKey("StringWithSize", "string"): stringWithSizeBuilder, 116 | builderKey("String", "string"): stringBuilder, 117 | builderKey("", "string"): stringBuilder, 118 | builderKey("DigitsWithSize", "string"): digitsWithSizeBuilder, 119 | builderKey("Digits", "string"): digitsBuilder, 120 | builderKey("LettersWithSize", "string"): lettersWithSizeBuilder, 121 | builderKey("Letters", "string"): lettersBuilder, 122 | builderKey("Lexify", "string"): lexifyBuilder, 123 | builderKey("Numerify", "string"): numerifyBuilder, 124 | builderKey("Parameterize", "string"): parameterizeBuilder, 125 | builderKey("Pick", "string"): pickBuilder, 126 | // time 127 | builderKey("DurationInRange", "time.Duration"): durationInRangeBuilder, 128 | builderKey("Duration", "time.Duration"): durationBuilder, 129 | builderKey("", "time.Duration"): durationBuilder, 130 | builderKey("Time", "time.Time"): timeBuilder, 131 | builderKey("", "time.Time"): timeBuilder, 132 | builderKey("TimeNow", "time.Time"): timeNowBuilder, 133 | builderKey("NanoSecond", "int"): nanoSecondBuilder, 134 | builderKey("Second", "int"): secondBuilder, 135 | builderKey("Minute", "int"): minuteBuilder, 136 | builderKey("Hour", "int"): hourBuilder, 137 | builderKey("Day", "int"): dayBuilder, 138 | builderKey("WeekDay", "string"): weekDayBuilder, 139 | builderKey("Month", "string"): monthBuilder, 140 | builderKey("Year", "int"): yearBuilder, 141 | builderKey("TimeZone", "string"): timeZoneBuilder, 142 | builderKey("TimeZoneAbbr", "string"): timeZoneAbbrBuilder, 143 | builderKey("TimeZoneFull", "string"): timeZoneFullBuilder, 144 | builderKey("TimeZoneOffset", "float32"): timeZoneOffsetBuilder, 145 | builderKey("TimeZoneRegion", "string"): timeZoneRegionBuilder, 146 | } 147 | -------------------------------------------------------------------------------- /internet_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleUsername() { 12 | faker.SetSeed(1700) 13 | fmt.Println(faker.Username()) 14 | // Output: polychasium 15 | } 16 | 17 | func ExampleDomain() { 18 | faker.SetSeed(1701) 19 | fmt.Println(faker.Domain()) 20 | // Output: lorusso.name 21 | } 22 | 23 | func ExampleEmail() { 24 | faker.SetSeed(1702) 25 | fmt.Println(faker.Email()) 26 | // Output: homocercal@fulmer.net 27 | } 28 | 29 | func ExampleFreeEmail() { 30 | faker.SetSeed(1703) 31 | fmt.Println(faker.FreeEmail()) 32 | // Output: atlas@gmail.com 33 | } 34 | 35 | func ExampleSafeEmail() { 36 | faker.SetSeed(1704) 37 | fmt.Println(faker.SafeEmail()) 38 | // Output: disbelieve@example.com 39 | } 40 | 41 | func ExampleSlug() { 42 | faker.SetSeed(1705) 43 | fmt.Println(faker.Slug()) 44 | // Output: a-reliable-seal-s-bee-comes-with-it-the-thought-that-the-adventurous-giraffe-is-an-alligator 45 | } 46 | 47 | func ExampleURL() { 48 | faker.SetSeed(1706) 49 | fmt.Println(faker.URL()) 50 | // Output: https://www.mcmillon.info/this-could-be-or-perhaps-their-alligator-was-in-this-moment-an-eager-spider 51 | } 52 | 53 | func TestInternetBuild(t *testing.T) { 54 | faker.SetSeed(1720) 55 | s := &struct { 56 | Field1 string `faker:"Username"` 57 | Field2 string `faker:"Domain"` 58 | Field3 string `faker:"Email"` 59 | Field4 string `faker:"SafeEmail"` 60 | Field5 string `faker:"FreeEmail"` 61 | Field6 string `faker:"Slug"` 62 | Field7 string `faker:"Url"` 63 | }{} 64 | err := faker.Build(&s) 65 | assert.Nil(t, err) 66 | t.Log(s) 67 | assert.Equal(t, "tight", s.Field1) 68 | assert.Equal(t, "extortionate.info", s.Field2) 69 | assert.Equal(t, "euchology@farris.info", s.Field3) 70 | assert.Equal(t, "andino@example.com", s.Field4) 71 | assert.Equal(t, "inflorescence@gmail.com", s.Field5) 72 | assert.Equal(t, "a-friendly-blackberry-is-an-eagle-of-the-mind", s.Field6) 73 | assert.Equal(t, "https://www.condescendence.info/nowhere-is-it-disputed-that-their-blueberry-was-in-this-moment-a-plausible-plum", s.Field7) 74 | } 75 | -------------------------------------------------------------------------------- /lang.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | var langData = PoolGroup{ 4 | "name": {"Abkhazian", "Afar", "Afrikaans", "Akan", "Albanian", "Amharic", "Arabic", "Aragonese", "Armenian", "Assamese", "Avaric", "Avestan", "Aymara", "Azerbaijani", "Bambara", "Bashkir", "Basque", "Belarusian", "Bengali", "Bislama", "Bosnian", "Breton", "Bulgarian", "Burmese", "Catalan", "Central Khmer", "Chamorro", "Chechen", "Chinese", "Church Slavic", "Chuvash", "Cornish", "Corsican", "Cree", "Croatian", "Czech", "Danish", "Dhivehi", "Dutch", "Dzongkha", "English", "Esperanto", "Estonian", "Ewe", "Faroese", "Fijian", "Finnish", "French", "Fulah", "Galician", "Ganda", "Georgian", "German", "Guarani", "Gujarati", "Haitian", "Hausa", "Hebrew", "Herero", "Hindi", "Hiri Motu", "Hungarian", "Icelandic", "Ido", "Igbo", "Indonesian", "Interlingua (International Auxiliary Language Association)", "Interlingue", "Inuktitut", "Inupiaq", "Irish", "Italian", "Japanese", "Javanese", "Kalaallisut", "Kannada", "Kanuri", "Kashmiri", "Kazakh", "Kikuyu", "Kinyarwanda", "Kirghiz", "Komi", "Kongo", "Korean", "Kuanyama", "Kurdish", "Lao", "Latin", "Latvian", "Limburgan", "Lingala", "Lithuanian", "Luba-Katanga", "Luxembourgish", "Macedonian", "Malagasy", "Malay", "Malayalam", "Maltese", "Manx", "Maori", "Marathi", "Marshallese", "Modern Greek (1453-)", "Mongolian", "Nauru", "Navajo", "Ndonga", "Nepali", "North Ndebele", "Northern Sami", "Norwegian", "Norwegian Bokmål", "Norwegian Nynorsk", "Nyanja", "Occitan (post 1500)", "Ojibwa", "Oriya", "Oromo", "Ossetian", "Pali", "Panjabi", "Persian", "Polish", "Portuguese", "Pushto", "Quechua", "Romanian", "Romansh", "Rundi", "Russian", "Samoan", "Sango", "Sanskrit", "Sardinian", "Scottish Gaelic", "Serbian", "Serbo-Croatian", "Shona", "Sichuan Yi", "Sindhi", "Sinhala", "Slovak", "Slovenian", "Somali", "South Ndebele", "Southern Sotho", "Spanish", "Sundanese", "Swahili", "Swati", "Swedish", "Tagalog", "Tahitian", "Tajik", "Tamil", "Tatar", "Telugu", "Thai", "Tibetan", "Tigrinya", "Tonga (Tonga Islands)", "Tsonga", "Tswana", "Turkish", "Turkmen", "Twi", "Uighur", "Ukrainian", "Urdu", "Uzbek", "Venda", "Vietnamese", "Volapük", "Walloon", "Welsh", "Western Frisian", "Wolof", "Xhosa", "Yiddish", "Yoruba", "Zhuang", "Zulu"}, 5 | "code": {"aa", "ab", "ae", "af", "ak", "am", "an", "ar", "as", "av", "ay", "az", "ba", "be", "bg", "bi", "bm", "bn", "bo", "br", "bs", "ca", "ce", "ch", "co", "cr", "cs", "cu", "cv", "cy", "da", "de", "dv", "dz", "ee", "el", "en", "eo", "es", "et", "eu", "fa", "ff", "fi", "fj", "fo", "fr", "fy", "ga", "gd", "gl", "gn", "gu", "gv", "ha", "he", "hi", "ho", "hr", "ht", "hu", "hy", "hz", "ia", "id", "ie", "ig", "ii", "ik", "io", "is", "it", "iu", "ja", "jv", "ka", "kg", "ki", "kj", "kk", "kl", "km", "kn", "ko", "kr", "ks", "ku", "kv", "kw", "ky", "la", "lb", "lg", "li", "ln", "lo", "lt", "lu", "lv", "mg", "mh", "mi", "mk", "ml", "mn", "mr", "ms", "mt", "my", "na", "nb", "nd", "ne", "ng", "nl", "nn", "no", "nr", "nv", "ny", "oc", "oj", "om", "or", "os", "pa", "pi", "pl", "ps", "pt", "qu", "rm", "rn", "ro", "ru", "rw", "sa", "sc", "sd", "se", "sg", "sh", "si", "sk", "sl", "sm", "sn", "so", "sq", "sr", "ss", "st", "su", "sv", "sw", "ta", "te", "tg", "th", "ti", "tk", "tl", "tn", "to", "tr", "ts", "tt", "tw", "ty", "ug", "uk", "ur", "uz", "ve", "vi", "vo", "wa", "wo", "xh", "yi", "yo", "za", "zh", "zu"}, 6 | } 7 | 8 | // LangName will build a random language name string. 9 | func LangName() string { 10 | value, _ := GetData("lang", "name") 11 | return value.(string) 12 | } 13 | 14 | // LangCode will build a random language code string. 15 | func LangCode() string { 16 | value, _ := GetData("lang", "code") 17 | return value.(string) 18 | } 19 | 20 | // Builder functions 21 | 22 | func langNameBuilder(params ...string) (interface{}, error) { 23 | return LangName(), nil 24 | } 25 | 26 | func langCodeBuilder(params ...string) (interface{}, error) { 27 | return LangCode(), nil 28 | } 29 | -------------------------------------------------------------------------------- /lang_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleLangName() { 12 | faker.SetSeed(1100) 13 | fmt.Println(faker.LangName()) 14 | // Output: Kirghiz 15 | } 16 | 17 | func ExampleLangCode() { 18 | faker.SetSeed(1101) 19 | fmt.Println(faker.LangCode()) 20 | // Output: sk 21 | } 22 | 23 | func TestLangBuild(t *testing.T) { 24 | faker.SetSeed(1110) 25 | s := &struct { 26 | Field1 string `faker:"LangName"` 27 | Field2 string `faker:"LangCode"` 28 | }{} 29 | err := faker.Build(&s) 30 | assert.Nil(t, err) 31 | t.Log(s) 32 | assert.Equal(t, "Samoan", s.Field1) 33 | assert.Equal(t, "fr", s.Field2) 34 | } 35 | -------------------------------------------------------------------------------- /misc.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "encoding/hex" 5 | ) 6 | 7 | // Bool will build a random boolean value (true or false). 8 | func Bool() bool { 9 | return IntInRange(0, 1) == 0 10 | } 11 | 12 | // PhoneNumber will build a random phone number string. 13 | func PhoneNumber() string { 14 | formats := []string{"???-???-????", "(???) ???-????", "1-???-???-????", "???.???.????"} 15 | i := IntInRange(0, len(formats)-1) 16 | return Numerify(formats[i]) 17 | } 18 | 19 | // UUID will build a random UUID string. 20 | func UUID() string { 21 | version := byte(4) 22 | uuid := make([]byte, 16) 23 | _, err := random.Read(uuid) 24 | if err != nil { 25 | panic(err) 26 | } 27 | 28 | // Set version 29 | uuid[6] = (uuid[6] & 0x0f) | (version << 4) 30 | 31 | // Set variant 32 | uuid[8] = (uuid[8] & 0xbf) | 0x80 33 | 34 | buf := make([]byte, 36) 35 | var dash byte = '-' 36 | hex.Encode(buf[0:8], uuid[0:4]) 37 | buf[8] = dash 38 | hex.Encode(buf[9:13], uuid[4:6]) 39 | buf[13] = dash 40 | hex.Encode(buf[14:18], uuid[6:8]) 41 | buf[18] = dash 42 | hex.Encode(buf[19:23], uuid[8:10]) 43 | buf[23] = dash 44 | hex.Encode(buf[24:], uuid[10:]) 45 | 46 | return string(buf) 47 | } 48 | 49 | // Builder functions 50 | 51 | func boolBuilder(params ...string) (interface{}, error) { 52 | return Bool(), nil 53 | } 54 | 55 | func phoneNumberBuilder(params ...string) (interface{}, error) { 56 | return PhoneNumber(), nil 57 | } 58 | 59 | func uuidBuilder(params ...string) (interface{}, error) { 60 | return UUID(), nil 61 | } 62 | -------------------------------------------------------------------------------- /misc_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleBool() { 12 | faker.SetSeed(102) 13 | fmt.Println(faker.Bool()) 14 | fmt.Println(faker.Bool()) 15 | // Output: true 16 | // false 17 | } 18 | 19 | func ExamplePhoneNumber() { 20 | faker.SetSeed(103) 21 | fmt.Println(faker.PhoneNumber()) 22 | // Output: 152.380.7298 23 | } 24 | 25 | func ExampleUUID() { 26 | faker.SetSeed(104) 27 | fmt.Println(faker.UUID()) 28 | // Output: 40abb44c-895e-45b8-9f67-cc02a811744a 29 | } 30 | 31 | func TestMiscBuild(t *testing.T) { 32 | faker.SetSeed(500) 33 | s := &struct { 34 | BoolField bool `faker:"bool"` 35 | DefaultBoolField bool 36 | Field1 string `faker:"PhoneNumber"` 37 | Field2 string `faker:"Uuid"` 38 | }{} 39 | err := faker.Build(&s) 40 | assert.Nil(t, err) 41 | t.Log(s) 42 | assert.True(t, s.BoolField) 43 | assert.True(t, s.DefaultBoolField) 44 | assert.Equal(t, "1-740-515-9178", s.Field1) 45 | assert.Equal(t, "05e3b503-b43d-4d23-bca4-224b2e3e12f3", s.Field2) 46 | } 47 | -------------------------------------------------------------------------------- /name_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleMaleFirstName() { 12 | faker.SetSeed(1400) 13 | fmt.Println(faker.MaleFirstName()) 14 | // Output: Lucien 15 | } 16 | 17 | func ExampleFemaleFirstName() { 18 | faker.SetSeed(1401) 19 | fmt.Println(faker.FemaleFirstName()) 20 | // Output: Sharell 21 | } 22 | 23 | func ExampleNeutralFirstName() { 24 | faker.SetSeed(1402) 25 | fmt.Println(faker.NeutralFirstName()) 26 | // Output: Hayden 27 | } 28 | 29 | func ExampleFirstName() { 30 | faker.SetSeed(1403) 31 | fmt.Println(faker.FirstName()) 32 | // Output: Barney 33 | } 34 | 35 | func ExampleLastName() { 36 | faker.SetSeed(1404) 37 | fmt.Println(faker.LastName()) 38 | // Output: Ankunding 39 | } 40 | 41 | func ExampleNamePrefix() { 42 | faker.SetSeed(1405) 43 | fmt.Println(faker.NamePrefix()) 44 | // Output: Msgr. 45 | } 46 | 47 | func ExampleNameSuffix() { 48 | faker.SetSeed(1406) 49 | fmt.Println(faker.NameSuffix()) 50 | // Output: PhD 51 | } 52 | 53 | func ExampleFullName() { 54 | faker.SetSeed(1407) 55 | fmt.Println(faker.FullName()) 56 | // Output: Sawyer Littel 57 | } 58 | 59 | func ExampleNameInitials() { 60 | faker.SetSeed(1408) 61 | fmt.Println(faker.NameInitials()) 62 | // Output: NP 63 | } 64 | 65 | func TestNameBuild(t *testing.T) { 66 | faker.SetSeed(1008) 67 | s := &struct { 68 | Field1 string `faker:"MaleFirstName"` 69 | Field2 string `faker:"FemaleFirstName"` 70 | Field3 string `faker:"NeutralFirstName"` 71 | Field4 string `faker:"FirstName"` 72 | Field5 string `faker:"LastName"` 73 | Field6 string `faker:"NamePrefix"` 74 | Field7 string `faker:"NameSuffix"` 75 | Field8 string `faker:"FullName"` 76 | Field9 string `faker:"NameInitials"` 77 | }{} 78 | err := faker.Build(&s) 79 | assert.Nil(t, err) 80 | t.Log(s) 81 | assert.Equal(t, "Bennett", s.Field1) 82 | assert.Equal(t, "Christi", s.Field2) 83 | assert.Equal(t, "Emerson", s.Field3) 84 | assert.Equal(t, "Lowell", s.Field4) 85 | assert.Equal(t, "Grady", s.Field5) 86 | assert.Equal(t, "Pres.", s.Field6) 87 | assert.Equal(t, "LLD", s.Field7) 88 | assert.Equal(t, "Frederick Bauch", s.Field8) 89 | assert.Equal(t, "QN", s.Field9) 90 | } 91 | -------------------------------------------------------------------------------- /number.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "math" 5 | ) 6 | 7 | // IntInRange will build a random int between min and max included. 8 | func IntInRange(min, max int) int { 9 | if min >= max { 10 | return min 11 | } 12 | return random.Intn(max-min+1) + min 13 | } 14 | 15 | // Int will build a random int. 16 | func Int() int { 17 | return IntInRange(math.MinInt32, math.MaxInt32) 18 | } 19 | 20 | // Int64InRange will build a random int64 between min and max included. 21 | func Int64InRange(min, max int64) int64 { 22 | if min >= max { 23 | return min 24 | } 25 | 26 | return random.Int63n(max-min) + min 27 | } 28 | 29 | // Int64 will build a random int64. 30 | func Int64() int64 { 31 | return random.Int63n(math.MaxInt64) + math.MinInt64 32 | } 33 | 34 | // Int32InRange will build a random int32 between min and max included. 35 | func Int32InRange(min, max int32) int32 { 36 | return int32(Int64InRange(int64(min), int64(max))) 37 | } 38 | 39 | // Int32 will build a random int32. 40 | func Int32() int32 { 41 | return Int32InRange(math.MinInt32, math.MaxInt32) 42 | } 43 | 44 | // Int16InRange will build a random int16 between min and max included. 45 | func Int16InRange(min, max int16) int16 { 46 | return int16(Int64InRange(int64(min), int64(max))) 47 | } 48 | 49 | // Int16 will build a random int16. 50 | func Int16() int16 { 51 | return Int16InRange(math.MinInt16, math.MaxInt16) 52 | } 53 | 54 | // Int8InRange will build a random int8 between min and max included. 55 | func Int8InRange(min, max int8) int8 { 56 | return int8(Int64InRange(int64(min), int64(max))) 57 | } 58 | 59 | // Int8 will build a random int8. 60 | func Int8() int8 { 61 | return Int8InRange(math.MinInt8, math.MaxInt8) 62 | } 63 | 64 | // UintInRange will build a random uint between min and max included. 65 | func UintInRange(min, max uint) uint { 66 | if min >= max { 67 | return min 68 | } 69 | return uint(random.Intn(int(max)-int(min)+1) + int(min)) 70 | } 71 | 72 | // Uint will build a random uint. 73 | func Uint() uint { 74 | return uint(IntInRange(0, math.MaxUint32)) 75 | } 76 | 77 | // Uint64InRange will build a random uint64 between min and max included. 78 | func Uint64InRange(min, max uint64) uint64 { 79 | if min >= max { 80 | return min 81 | } 82 | return uint64(random.Int63n(int64(max)-int64(min)) + int64(min)) 83 | } 84 | 85 | // Uint64 will build a random uint64. 86 | func Uint64() uint64 { 87 | return Uint64InRange(0, math.MaxInt64) + Uint64InRange(0, math.MaxInt64) 88 | } 89 | 90 | // Uint32InRange will build a random uint32 between min and max included. 91 | func Uint32InRange(min, max uint32) uint32 { 92 | return uint32(Uint64InRange(uint64(min), uint64(max))) 93 | } 94 | 95 | // Uint32 will build a random uint32. 96 | func Uint32() uint32 { 97 | return Uint32InRange(0, math.MaxUint32) 98 | } 99 | 100 | // Uint16InRange will build a random uint16 between min and max included. 101 | func Uint16InRange(min, max uint16) uint16 { 102 | return uint16(Uint64InRange(uint64(min), uint64(max))) 103 | } 104 | 105 | // Uint16 will build a random uint16. 106 | func Uint16() uint16 { 107 | return Uint16InRange(0, math.MaxUint16) 108 | } 109 | 110 | // Uint8InRange will build a random uint8 between min and max included. 111 | func Uint8InRange(min, max uint8) uint8 { 112 | return uint8(Uint64InRange(uint64(min), uint64(max))) 113 | } 114 | 115 | // Uint8 will build a random uint8. 116 | func Uint8() uint8 { 117 | return Uint8InRange(0, math.MaxUint8) 118 | } 119 | 120 | // Float64InRange will build a random float64 between min and max included. 121 | func Float64InRange(min, max float64) float64 { 122 | if min >= max { 123 | return min 124 | } 125 | return random.Float64()*(max-min) + min 126 | } 127 | 128 | // Float64 will build a random float64. 129 | func Float64() float64 { 130 | return Float64InRange(math.SmallestNonzeroFloat64, math.MaxFloat64) 131 | } 132 | 133 | // Float32InRange will build a random float32 between min and max included. 134 | func Float32InRange(min, max float32) float32 { 135 | if min >= max { 136 | return min 137 | } 138 | return random.Float32()*(max-min) + min 139 | } 140 | 141 | // Float32 will build a random float32. 142 | func Float32() float32 { 143 | return Float32InRange(math.SmallestNonzeroFloat32, math.MaxFloat32) 144 | } 145 | 146 | // Builder functions 147 | 148 | func intInRangeBuilder(params ...string) (interface{}, error) { 149 | min, max, err := paramsToMinMaxInt(params...) 150 | if err != nil { 151 | return nil, err 152 | } 153 | return IntInRange(min, max), nil 154 | } 155 | 156 | func intBuilder(params ...string) (interface{}, error) { 157 | return Int(), nil 158 | } 159 | 160 | func int64InRangeBuilder(params ...string) (interface{}, error) { 161 | min, max, err := paramsToMinMaxInt(params...) 162 | if err != nil { 163 | return nil, err 164 | } 165 | return Int64InRange(int64(min), int64(max)), nil 166 | } 167 | 168 | func int64Builder(params ...string) (interface{}, error) { 169 | return Int64(), nil 170 | } 171 | 172 | func int32InRangeBuilder(params ...string) (interface{}, error) { 173 | min, max, err := paramsToMinMaxInt(params...) 174 | if err != nil { 175 | return nil, err 176 | } 177 | return Int32InRange(int32(min), int32(max)), nil 178 | } 179 | 180 | func int32Builder(params ...string) (interface{}, error) { 181 | return Int32(), nil 182 | } 183 | 184 | func int16InRangeBuilder(params ...string) (interface{}, error) { 185 | min, max, err := paramsToMinMaxInt(params...) 186 | if err != nil { 187 | return nil, err 188 | } 189 | return Int16InRange(int16(min), int16(max)), nil 190 | } 191 | 192 | func int16Builder(params ...string) (interface{}, error) { 193 | return Int16(), nil 194 | } 195 | 196 | func int8InRangeBuilder(params ...string) (interface{}, error) { 197 | min, max, err := paramsToMinMaxInt(params...) 198 | if err != nil { 199 | return nil, err 200 | } 201 | return Int8InRange(int8(min), int8(max)), nil 202 | } 203 | 204 | func int8Builder(params ...string) (interface{}, error) { 205 | return Int8(), nil 206 | } 207 | 208 | func uintInRangeBuilder(params ...string) (interface{}, error) { 209 | min, max, err := paramsToMinMaxInt(params...) 210 | if err != nil { 211 | return nil, err 212 | } 213 | return UintInRange(uint(min), uint(max)), nil 214 | } 215 | 216 | func uintBuilder(params ...string) (interface{}, error) { 217 | return Uint(), nil 218 | } 219 | 220 | func uint64InRangeBuilder(params ...string) (interface{}, error) { 221 | min, max, err := paramsToMinMaxInt(params...) 222 | if err != nil { 223 | return nil, err 224 | } 225 | return Uint64InRange(uint64(min), uint64(max)), nil 226 | } 227 | 228 | func uint64Builder(params ...string) (interface{}, error) { 229 | return Uint64(), nil 230 | } 231 | 232 | func uint32InRangeBuilder(params ...string) (interface{}, error) { 233 | min, max, err := paramsToMinMaxInt(params...) 234 | if err != nil { 235 | return nil, err 236 | } 237 | return Uint32InRange(uint32(min), uint32(max)), nil 238 | } 239 | 240 | func uint32Builder(params ...string) (interface{}, error) { 241 | return Uint32(), nil 242 | } 243 | 244 | func uint16InRangeBuilder(params ...string) (interface{}, error) { 245 | min, max, err := paramsToMinMaxInt(params...) 246 | if err != nil { 247 | return nil, err 248 | } 249 | return Uint16InRange(uint16(min), uint16(max)), nil 250 | } 251 | 252 | func uint16Builder(params ...string) (interface{}, error) { 253 | return Uint16(), nil 254 | } 255 | 256 | func uint8InRangeBuilder(params ...string) (interface{}, error) { 257 | min, max, err := paramsToMinMaxInt(params...) 258 | if err != nil { 259 | return nil, err 260 | } 261 | return Uint8InRange(uint8(min), uint8(max)), nil 262 | } 263 | 264 | func uint8Builder(params ...string) (interface{}, error) { 265 | return Uint8(), nil 266 | } 267 | 268 | func float64InRangeBuilder(params ...string) (interface{}, error) { 269 | min, max, err := paramsToMinMaxFloat64(params...) 270 | if err != nil { 271 | return nil, err 272 | } 273 | return Float64InRange(min, max), nil 274 | } 275 | 276 | func float64Builder(params ...string) (interface{}, error) { 277 | return Float64(), nil 278 | } 279 | 280 | func float32InRangeBuilder(params ...string) (interface{}, error) { 281 | min, max, err := paramsToMinMaxFloat64(params...) 282 | if err != nil { 283 | return nil, err 284 | } 285 | return Float32InRange(float32(min), float32(max)), nil 286 | } 287 | 288 | func float32Builder(params ...string) (interface{}, error) { 289 | return Float32(), nil 290 | } 291 | -------------------------------------------------------------------------------- /number_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleIntInRange() { 12 | faker.SetSeed(3) 13 | fmt.Println(faker.IntInRange(10, 20)) 14 | fmt.Println(faker.IntInRange(-20, -10)) 15 | fmt.Println(faker.IntInRange(-20, -30)) 16 | // Output: 16 17 | // -14 18 | // -20 19 | } 20 | 21 | func ExampleInt() { 22 | faker.SetSeed(4) 23 | fmt.Println(faker.Int()) 24 | // Output: 477987042 25 | } 26 | 27 | func ExampleInt64InRange() { 28 | faker.SetSeed(5) 29 | fmt.Println(faker.Int64InRange(10, 20)) 30 | fmt.Println(faker.Int64InRange(-20, -10)) 31 | fmt.Println(faker.Int64InRange(-20, -30)) 32 | // Output: 10 33 | // -19 34 | // -20 35 | } 36 | 37 | func ExampleInt64() { 38 | faker.SetSeed(6) 39 | fmt.Println(faker.Int64()) 40 | // Output: -5917743806733054187 41 | } 42 | 43 | func ExampleInt32InRange() { 44 | faker.SetSeed(7) 45 | fmt.Println(faker.Int32InRange(10, 20)) 46 | fmt.Println(faker.Int32InRange(-20, -10)) 47 | fmt.Println(faker.Int32InRange(-20, -30)) 48 | // Output: 15 49 | // -16 50 | // -20 51 | } 52 | 53 | func ExampleInt32() { 54 | faker.SetSeed(8) 55 | fmt.Println(faker.Int32()) 56 | // Output: -417194768 57 | } 58 | 59 | func ExampleInt16InRange() { 60 | faker.SetSeed(9) 61 | fmt.Println(faker.Int16InRange(10, 20)) 62 | fmt.Println(faker.Int16InRange(-20, -10)) 63 | fmt.Println(faker.Int16InRange(-20, -30)) 64 | // Output: 14 65 | // -16 66 | // -20 67 | } 68 | 69 | func ExampleInt16() { 70 | faker.SetSeed(10) 71 | fmt.Println(faker.Int16()) 72 | // Output: -24938 73 | } 74 | 75 | func ExampleInt8InRange() { 76 | faker.SetSeed(11) 77 | fmt.Println(faker.Int8InRange(10, 20)) 78 | fmt.Println(faker.Int8InRange(-20, -10)) 79 | fmt.Println(faker.Int8InRange(-20, -30)) 80 | // Output: 15 81 | // -14 82 | // -20 83 | } 84 | 85 | func ExampleInt8() { 86 | faker.SetSeed(12) 87 | fmt.Println(faker.Int8()) 88 | // Output: -101 89 | } 90 | 91 | func ExampleUintInRange() { 92 | faker.SetSeed(13) 93 | fmt.Println(faker.UintInRange(10, 20)) 94 | fmt.Println(faker.UintInRange(20, 10)) 95 | // Output: 15 96 | // 20 97 | } 98 | 99 | func ExampleUint() { 100 | faker.SetSeed(14) 101 | fmt.Println(faker.Uint()) 102 | // Output: 2486533097 103 | } 104 | 105 | func ExampleUint64InRange() { 106 | faker.SetSeed(15) 107 | fmt.Println(faker.Uint64InRange(10, 20)) 108 | fmt.Println(faker.Uint64InRange(20, 10)) 109 | // Output: 13 110 | // 20 111 | } 112 | 113 | func ExampleUint64() { 114 | faker.SetSeed(16) 115 | fmt.Println(faker.Uint64()) 116 | // Output: 16676020418646319060 117 | } 118 | 119 | func ExampleUint32InRange() { 120 | faker.SetSeed(17) 121 | fmt.Println(faker.Uint32InRange(10, 20)) 122 | fmt.Println(faker.Uint32InRange(20, 10)) 123 | // Output: 16 124 | // 20 125 | } 126 | 127 | func ExampleUint32() { 128 | faker.SetSeed(18) 129 | fmt.Println(faker.Uint32()) 130 | // Output: 1185777406 131 | } 132 | 133 | func ExampleUint16InRange() { 134 | faker.SetSeed(19) 135 | fmt.Println(faker.Uint16InRange(10, 20)) 136 | fmt.Println(faker.Uint16InRange(20, 10)) 137 | // Output: 13 138 | // 20 139 | } 140 | 141 | func ExampleUint16() { 142 | faker.SetSeed(20) 143 | fmt.Println(faker.Uint16()) 144 | // Output: 29810 145 | } 146 | 147 | func ExampleUint8InRange() { 148 | faker.SetSeed(21) 149 | fmt.Println(faker.Uint8InRange(10, 20)) 150 | fmt.Println(faker.Uint8InRange(20, 10)) 151 | // Output: 18 152 | // 20 153 | } 154 | 155 | func ExampleUint8() { 156 | faker.SetSeed(22) 157 | fmt.Println(faker.Uint8()) 158 | // Output: 231 159 | } 160 | 161 | func ExampleFloat64InRange() { 162 | faker.SetSeed(23) 163 | fmt.Println(faker.Float64InRange(1, 2)) 164 | fmt.Println(faker.Float64InRange(-2, -1)) 165 | fmt.Println(faker.Float64InRange(-2, -3)) 166 | // Output: 167 | // 1.8120965248489755 168 | // -1.4513652135502495 169 | // -2 170 | } 171 | 172 | func ExampleFloat64() { 173 | faker.SetSeed(24) 174 | fmt.Println(faker.Float64()) 175 | // Output: 6.696671980874496e+307 176 | } 177 | 178 | func ExampleFloat32InRange() { 179 | faker.SetSeed(25) 180 | fmt.Println(faker.Float32InRange(10, 20)) 181 | fmt.Println(faker.Float32InRange(-20, -10)) 182 | fmt.Println(faker.Float32InRange(-20, -30)) 183 | // Output: 18.961363 184 | // -15.832848 185 | // -20 186 | } 187 | 188 | func ExampleFloat32() { 189 | faker.SetSeed(26) 190 | fmt.Println(faker.Float32()) 191 | // Output: 1.5426473e+38 192 | } 193 | 194 | func TestNumberBuild(t *testing.T) { 195 | faker.SetSeed(30) 196 | s := &struct { 197 | IntInRangeField int `faker:"intinrange(1,10)"` 198 | IntField int `faker:"int"` 199 | DefaultIntField int 200 | Int64InRangeField int64 `faker:"int64inrange(1,10)"` 201 | Int64Field int64 `faker:"int64"` 202 | DefaultInt64Field int64 203 | Int32InRangeField int32 `faker:"int32inrange(1,10)"` 204 | Int32Field int32 `faker:"int32"` 205 | DefaultInt32Field int32 206 | Int16InRangeField int16 `faker:"int16inrange(1,10)"` 207 | Int16Field int16 `faker:"int16"` 208 | DefaultInt16Field int16 209 | Int8InRangeField int8 `faker:"int8inrange(1,10)"` 210 | Int8Field int8 `faker:"int8"` 211 | DefaultInt8Field int8 212 | UintInRangeField uint `faker:"uintinrange(1,10)"` 213 | UintField uint `faker:"uint"` 214 | DefaultUintField uint 215 | Uint64InRangeField uint64 `faker:"uint64inrange(1,10)"` 216 | Uint64Field uint64 `faker:"uint64"` 217 | DefaultUint64Field uint64 218 | Uint32InRangeField uint32 `faker:"uint32inrange(1,10)"` 219 | Uint32Field uint32 `faker:"uint32"` 220 | DefaultUint32Field uint32 221 | Uint16InRangeField uint16 `faker:"uint16inrange(1,10)"` 222 | Uint16Field uint16 `faker:"uint16"` 223 | DefaultUint16Field uint16 224 | Uint8InRangeField uint8 `faker:"uint8inrange(1,10)"` 225 | Uint8Field uint8 `faker:"uint8"` 226 | DefaultUint8Field uint8 227 | Float64InRangeField float64 `faker:"Float64InRange(1,10.6)"` 228 | Float64Field float64 `faker:"float64"` 229 | DefaultFloat64Field float64 230 | Float32InRangeField float32 `faker:"Float32InRange(1,10.6)"` 231 | Float32Field float32 `faker:"float32"` 232 | DefaultFloat32Field float32 233 | }{} 234 | err := faker.Build(&s) 235 | assert.Nil(t, err) 236 | t.Log(s) 237 | 238 | assert.Equal(t, 9, s.IntInRangeField) 239 | assert.Equal(t, -1588912014, s.IntField) 240 | assert.Equal(t, -1491768569, s.DefaultIntField) 241 | 242 | assert.Equal(t, int64(5), s.Int64InRangeField) 243 | assert.Equal(t, int64(-5089836721814089834), s.Int64Field) 244 | assert.Equal(t, int64(-3837974256891962760), s.DefaultInt64Field) 245 | 246 | assert.Equal(t, int32(1), s.Int32InRangeField) 247 | assert.Equal(t, int32(-1416661755), s.Int32Field) 248 | assert.Equal(t, int32(-1243937080), s.DefaultInt32Field) 249 | 250 | assert.Equal(t, int16(5), s.Int16InRangeField) 251 | assert.Equal(t, int16(18620), s.Int16Field) 252 | assert.Equal(t, int16(-3431), s.DefaultInt16Field) 253 | 254 | assert.Equal(t, int8(1), s.Int8InRangeField) 255 | assert.Equal(t, int8(84), s.Int8Field) 256 | assert.Equal(t, int8(-17), s.DefaultInt8Field) 257 | 258 | assert.Equal(t, uint(8), s.UintInRangeField) 259 | assert.Equal(t, uint(1869826397), s.UintField) 260 | assert.Equal(t, uint(498610181), s.DefaultUintField) 261 | 262 | assert.Equal(t, uint64(3), s.Uint64InRangeField) 263 | assert.Equal(t, uint64(8118072143219141702), s.Uint64Field) 264 | assert.Equal(t, uint64(10753327993520087958), s.DefaultUint64Field) 265 | 266 | assert.Equal(t, uint32(1), s.Uint32InRangeField) 267 | assert.Equal(t, uint32(2486160442), s.Uint32Field) 268 | assert.Equal(t, uint32(2189451667), s.DefaultUint32Field) 269 | 270 | assert.Equal(t, uint16(6), s.Uint16InRangeField) 271 | assert.Equal(t, uint16(38236), s.Uint16Field) 272 | assert.Equal(t, uint16(55644), s.DefaultUint16Field) 273 | 274 | assert.Equal(t, uint8(1), s.Uint8InRangeField) 275 | assert.Equal(t, uint8(98), s.Uint8Field) 276 | assert.Equal(t, uint8(68), s.DefaultUint8Field) 277 | 278 | assert.Equal(t, float64(9.535379483774388), s.Float64InRangeField) 279 | assert.Equal(t, float64(1.6249093496264468e+308), s.Float64Field) 280 | assert.Equal(t, float64(2.2516638145714746e+307), s.DefaultFloat64Field) 281 | 282 | assert.Equal(t, float32(7.8864875), s.Float32InRangeField) 283 | assert.Equal(t, float32(3.0873776e+38), s.Float32Field) 284 | assert.Equal(t, float32(3.3773583e+38), s.DefaultFloat32Field) 285 | } 286 | 287 | func TestNumberInvalidParams(t *testing.T) { 288 | faker.SetSeed(31) 289 | s1 := &struct { 290 | Field int `faker:"IntInRange(a)"` 291 | }{} 292 | err := faker.Build(&s1) 293 | assert.NotNil(t, err) 294 | assert.Equal(t, "invalid parameters", err.Error()) 295 | 296 | s2 := &struct { 297 | Field int64 `faker:"Int64InRange(a)"` 298 | }{} 299 | err = faker.Build(&s2) 300 | assert.NotNil(t, err) 301 | assert.Equal(t, "invalid parameters", err.Error()) 302 | 303 | s3 := &struct { 304 | Field int32 `faker:"Int32InRange(1,a)"` 305 | }{} 306 | err = faker.Build(&s3) 307 | assert.NotNil(t, err) 308 | assert.Equal(t, "invalid parameters: strconv.Atoi: parsing \"a\": invalid syntax", err.Error()) 309 | 310 | s4 := &struct { 311 | Field int16 `faker:"Int16InRange(a)"` 312 | }{} 313 | err = faker.Build(&s4) 314 | assert.NotNil(t, err) 315 | assert.Equal(t, "invalid parameters", err.Error()) 316 | 317 | s5 := &struct { 318 | Field int8 `faker:"Int8InRange(a)"` 319 | }{} 320 | err = faker.Build(&s5) 321 | assert.NotNil(t, err) 322 | assert.Equal(t, "invalid parameters", err.Error()) 323 | 324 | s6 := &struct { 325 | Field uint `faker:"UintInRange(a)"` 326 | }{} 327 | err = faker.Build(&s6) 328 | assert.NotNil(t, err) 329 | assert.Equal(t, "invalid parameters", err.Error()) 330 | 331 | s7 := &struct { 332 | Field uint64 `faker:"Uint64InRange(a)"` 333 | }{} 334 | err = faker.Build(&s7) 335 | assert.NotNil(t, err) 336 | assert.Equal(t, "invalid parameters", err.Error()) 337 | 338 | s8 := &struct { 339 | Field uint32 `faker:"Uint32InRange(a)"` 340 | }{} 341 | err = faker.Build(&s8) 342 | assert.NotNil(t, err) 343 | assert.Equal(t, "invalid parameters", err.Error()) 344 | 345 | s9 := &struct { 346 | Field uint16 `faker:"Uint16InRange(a)"` 347 | }{} 348 | err = faker.Build(&s9) 349 | assert.NotNil(t, err) 350 | assert.Equal(t, "invalid parameters", err.Error()) 351 | 352 | s10 := &struct { 353 | Field uint8 `faker:"Uint8InRange(a)"` 354 | }{} 355 | err = faker.Build(&s10) 356 | assert.NotNil(t, err) 357 | assert.Equal(t, "invalid parameters", err.Error()) 358 | 359 | s11 := &struct { 360 | Field float64 `faker:"float64InRange(a)"` 361 | }{} 362 | err = faker.Build(&s11) 363 | assert.NotNil(t, err) 364 | assert.Equal(t, "invalid parameters", err.Error()) 365 | 366 | s12 := &struct { 367 | Field float32 `faker:"float32InRange(a)"` 368 | }{} 369 | err = faker.Build(&s12) 370 | assert.NotNil(t, err) 371 | assert.Equal(t, "invalid parameters", err.Error()) 372 | } 373 | -------------------------------------------------------------------------------- /pool.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | // Pool type is a slice that contains fake data. 9 | type Pool []interface{} 10 | 11 | // PoolGroup type is a map that groups Pool types. 12 | type PoolGroup map[string]Pool 13 | 14 | // PoolData type is a map that groups PoolGroup types. 15 | type PoolData map[string]PoolGroup 16 | 17 | var dbMutex = &sync.Mutex{} 18 | 19 | // GetData return a random value of the Pool present in the group group with 20 | // namespace namespace or error if the pool does not exist. Faker organize 21 | // fake data in a map of string and map of string and array of interface. The 22 | // keys of the first level map are called namespaces, the keys of the second 23 | // level map are called groups. 24 | func GetData(namespace, group string) (interface{}, error) { 25 | dbMutex.Lock() 26 | defer dbMutex.Unlock() 27 | var ( 28 | poolGroup PoolGroup 29 | pool Pool 30 | found bool 31 | ) 32 | poolGroup, found = db[namespace] 33 | if !found { 34 | return "", fmt.Errorf("the namespace '%s' does not exist", namespace) 35 | } 36 | 37 | pool, found = poolGroup[group] 38 | if !found { 39 | return "", fmt.Errorf("the group '%s' in namespace '%s' does not exist", group, namespace) 40 | } 41 | 42 | i := IntInRange(0, len(pool)-1) 43 | return pool[i], nil 44 | } 45 | 46 | // SetPool add a new Pool under the group group with namespace namespace (see 47 | // GetData). 48 | func SetPool(namespace, group string, pool Pool) { 49 | dbMutex.Lock() 50 | defer dbMutex.Unlock() 51 | var ( 52 | poolGroup PoolGroup 53 | found bool 54 | ) 55 | _, found = db[namespace] 56 | if !found { 57 | db[namespace] = make(PoolGroup) 58 | } 59 | poolGroup = db[namespace] 60 | poolGroup[group] = pool 61 | } 62 | 63 | // SetPoolGroup add a new PoolGroup under the namespace namespace (see 64 | // GetData). 65 | func SetPoolGroup(namespace string, poolGroup PoolGroup) { 66 | dbMutex.Lock() 67 | defer dbMutex.Unlock() 68 | db[namespace] = poolGroup 69 | } 70 | -------------------------------------------------------------------------------- /pool_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleGetData() { 12 | faker.SetSeed(801) 13 | faker.SetPool("address", "city", faker.Pool{"New York", "Rome"}) 14 | value, err := faker.GetData("address", "city") 15 | if err != nil { 16 | panic(err) 17 | } 18 | fmt.Println(value) 19 | // Output: New York 20 | } 21 | 22 | func TestGetAndSetPool(t *testing.T) { 23 | faker.SetSeed(802) 24 | faker.SetPool("ns1", "grp1", faker.Pool{"foo", "bar"}) 25 | value, err := faker.GetData("ns1", "grp1") 26 | assert.Nil(t, err) 27 | t.Log(value) 28 | assert.Equal(t, "foo", value) 29 | 30 | faker.SetPool("ns2", "grp1", faker.Pool{"foo", "bar"}) 31 | value, err = faker.GetData("ns2", "grp1") 32 | assert.Nil(t, err) 33 | t.Log(value) 34 | assert.Equal(t, "bar", value) 35 | 36 | faker.SetPool("ns2", "grp2", faker.Pool{"foo", "bar"}) 37 | value, err = faker.GetData("ns2", "grp2") 38 | assert.Nil(t, err) 39 | t.Log(value) 40 | assert.Equal(t, "foo", value) 41 | 42 | faker.SetPoolGroup("ns3", faker.PoolGroup{"grp1": faker.Pool{"foo", "bar"}}) 43 | value, err = faker.GetData("ns3", "grp1") 44 | assert.Nil(t, err) 45 | t.Log(value) 46 | assert.Equal(t, "bar", value) 47 | } 48 | 49 | func TestGetDataWithNamespaceError(t *testing.T) { 50 | faker.SetPool("ns4", "grp1", faker.Pool{"foo", "bar"}) 51 | _, err := faker.GetData("not-exist", "grp1") 52 | assert.NotNil(t, err) 53 | assert.Equal(t, "the namespace 'not-exist' does not exist", err.Error()) 54 | } 55 | 56 | func TestGetDataWithGroupError(t *testing.T) { 57 | faker.SetPool("ns5", "grp1", faker.Pool{"foo", "bar"}) 58 | _, err := faker.GetData("ns5", "not-exist") 59 | assert.NotNil(t, err) 60 | assert.Equal(t, "the group 'not-exist' in namespace 'ns5' does not exist", err.Error()) 61 | } 62 | -------------------------------------------------------------------------------- /random.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "math/rand" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | var ( 10 | random = rand.New(rand.NewSource(time.Now().UnixNano())) 11 | randomMutex = &sync.Mutex{} 12 | ) 13 | 14 | // SetRand set a new source of random numbers (see rand.Rand). The default 15 | // source is: 16 | // 17 | // rand.New(rand.NewSource(time.Now().UnixNano())) 18 | // 19 | func SetRand(r *rand.Rand) { 20 | randomMutex.Lock() 21 | random = r 22 | randomMutex.Unlock() 23 | } 24 | 25 | // SetSeed uses the provided seed value to initialize the generator to a 26 | // deterministic state (see rand.Seed). 27 | func SetSeed(seed int64) { 28 | randomMutex.Lock() 29 | random.Seed(seed) 30 | randomMutex.Unlock() 31 | } 32 | -------------------------------------------------------------------------------- /random_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "math/rand" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestSetRand(t *testing.T) { 12 | random := rand.New(rand.NewSource(21)) 13 | assert.NotPanics(t, func() { 14 | faker.SetRand(random) 15 | }) 16 | } 17 | 18 | func TestSetSeed(t *testing.T) { 19 | assert.NotPanics(t, func() { 20 | faker.SetSeed(21) 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /sentence.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "regexp" 7 | "strings" 8 | "text/template" 9 | "unicode" 10 | ) 11 | 12 | var sentenceData = PoolGroup{ 13 | "noun": {"alligator", "ant", "apple", "apricot", "banana", "bear", "bee", "bird", "blackberry", "blueberry", "camel", "cat", "cheetah", "cherry", "chicken", "chimpanzee", "cow", "cranberry", "crocodile", "currant", "deer", "dog", "dolphin", "duck", "eagle", "elephant", "fig", "fish", "fly", "fox", "frog", "giraffe", "goat", "goldfish", "grape", "grapefruit", "grapes", "hamster", "hippopotamus", "horse", "kangaroo", "kitten", "kiwi", "kumquat", "lemon", "lime", "lion", "lobster", "melon", "monkey", "nectarine", "octopus", "orange", "owl", "panda", "peach", "pear", "persimmon", "pig", "pineapple", "plum", "pomegranate", "prune", "puppy", "rabbit", "raspberry", "rat", "scorpion", "seal", "shark", "sheep", "snail", "snake", "spider", "squirrel", "strawberry", "tangerine", "tiger", "turtle", "watermelon", "wolf", "zebra"}, 14 | "adjective": {"adaptable", "adventurous", "affable", "affectionate", "agreeable", "alert", "alluring", "ambitious", "amiable", "amicable", "amused", "amusing", "boundless", "brave", "bright", "broad-minded", "calm", "capable", "careful", "charming", "cheerful", "coherent", "comfortable", "communicative", "compassionate", "confident", "conscientious", "considerate", "convivial", "cooperative", "courageous", "courteous", "creative", "credible", "cultured", "dashing", "dazzling", "debonair", "decisive", "decorous", "delightful", "detailed", "determined", "diligent", "diplomatic", "discreet", "dynamic", "eager", "easygoing", "efficient", "elated", "eminent", "emotional", "enchanting", "encouraging", "endurable", "energetic", "entertaining", "enthusiastic", "excellent", "excited", "exclusive", "exuberant", "fabulous", "fair", "fair-minded", "faithful", "fantastic", "fearless", "fine", "forceful", "frank", "friendly", "funny", "generous", "gentle", "glorious", "good", "gregarious", "happy", "hard-working", "harmonious", "helpful", "hilarious", "honest", "honorable", "humorous", "imaginative", "impartial", "independent", "industrious", "instinctive", "intellectual", "intelligent", "intuitive", "inventive", "jolly", "joyous", "kind", "kind-hearted", "knowledgeable", "level", "likeable", "lively", "lovely", "loving", "loyal", "lucky", "mature", "modern", "modest", "neat", "nice", "obedient", "optimistic", "painstaking", "passionate", "patient", "peaceful", "perfect", "persistent", "philosophical", "pioneering", "placid", "plausible", "pleasant", "plucky", "polite", "powerful", "practical", "pro-active", "productive", "protective", "proud", "punctual", "quick-witted", "quiet", "rational", "receptive", "reflective", "reliable", "relieved", "reserved", "resolute", "resourceful", "responsible", "rhetorical", "righteous", "romantic", "sedate", "seemly", "selective", "self-assured", "self-confident", "self-disciplined", "sensible", "sensitive", "shrewd", "shy", "silly", "sincere", "skillful", "smiling", "sociable", "splendid", "steadfast", "stimulating", "straightforward", "successful", "succinct", "sympathetic", "talented", "thoughtful", "thrifty", "tidy", "tough", "trustworthy", "unassuming", "unbiased", "understanding", "unusual", "upbeat", "versatile", "vigorous", "vivacious", "warm", "warmhearted", "willing", "wise", "witty", "wonderful"}, 15 | "sentence_template": {"the {{noun}} is {{anoun}}", "{{anoun}} is {{anAdjective}} {{noun}}", "the first {{adjective}} {{noun}} is, in its own way, {{anoun}}", "their {{noun}} was, in this moment, {{anAdjective}} {{noun}}", "{{anoun}} is {{anoun}} from the right perspective", "the literature would have us believe that {{anAdjective}} {{noun}} is not but {{anoun}}", "{{anAdjective}} {{noun}} is {{anoun}} of the mind", "the {{adjective}} {{noun}} reveals itself as {{anAdjective}} {{noun}} to those who look", "authors often misinterpret the {{noun}} as {{anAdjective}} {{noun}}, when in actuality it feels more like {{anAdjective}} {{noun}}", "we can assume that any instance of {{anoun}} can be construed as {{anAdjective}} {{noun}}", "they were lost without the {{adjective}} {{noun}} that composed their {{noun}}", "the {{adjective}} {{noun}} comes from {{anAdjective}} {{noun}}", "{{anoun}} can hardly be considered {{anAdjective}} {{noun}} without also being {{anoun}}", "few can name {{anAdjective}} {{noun}} that isn't {{anAdjective}} {{noun}}", "some posit the {{adjective}} {{noun}} to be less than {{adjective}}", "{{anoun}} of the {{noun}} is assumed to be {{anAdjective}} {{noun}}", "{{anoun}} sees {{anoun}} as {{anAdjective}} {{noun}}", "the {{noun}} of {{anoun}} becomes {{anAdjective}} {{noun}}", "{{anoun}} is {{anoun}}'s {{noun}}", "{{anoun}} is the {{noun}} of {{anoun}}", "{{anAdjective}} {{noun}}'s {{noun}} comes with it the thought that the {{adjective}} {{noun}} is {{anoun}}", "{{nouns}} are {{adjective}} {{nouns}}", "{{adjective}} {{nouns}} show us how {{nouns}} can be {{nouns}}", "before {{nouns}}, {{nouns}} were only {{nouns}}", "those {{nouns}} are nothing more than {{nouns}}", "some {{adjective}} {{nouns}} are thought of simply as {{nouns}}", "one cannot separate {{nouns}} from {{adjective}} {{nouns}}", "the {{nouns}} could be said to resemble {{adjective}} {{nouns}}", "{{anAdjective}} {{noun}} without {{nouns}} is truly a {{noun}} of {{adjective}} {{nouns}}"}, 16 | "starting_phrase": {"to be more specific, ", "in recent years, ", "however, ", "by the way", "of course, ", "some assert that ", "if this was somewhat unclear, ", "unfortunately, that is wrong; on the contrary, ", "it's very tricky, if not impossible, ", "this could be, or perhaps ", "this is not to discredit the idea that ", "we know that ", "it's an undeniable fact, really; ", "framed in a different way, ", "what we don't know for sure is whether or not ", "as far as we can estimate, ", "as far as he is concerned, ", "the zeitgeist contends that ", "though we assume the latter, ", "far from the truth, ", "extending this logic, ", "nowhere is it disputed that ", "in modern times ", "in ancient times ", "recent controversy aside, ", "washing and polishing the car,", "having been a gymnast, ", "after a long day at school and work, ", "waking to the buzz of the alarm clock, ", "draped neatly on a hanger, ", "shouting with happiness, "}, 17 | } 18 | 19 | // Sentence will build a random sentence string. 20 | func Sentence() string { 21 | phrase := randomStartingPhrase() 22 | phrase += makeSentence() 23 | phrase = capitalize(phrase) 24 | phrase += pickLastPunc() 25 | return phrase 26 | } 27 | 28 | // ParagraphWithSentenceCount will build a random paragraph string consisting 29 | // of n sentences. 30 | func ParagraphWithSentenceCount(n int) string { 31 | p := make([]string, 0, n) 32 | for i := 0; i < n; i++ { 33 | p = append(p, Sentence()) 34 | } 35 | return strings.Join(p, " ") 36 | } 37 | 38 | // Paragraph will build a random paragraph. 39 | func Paragraph() string { 40 | n := IntInRange(4, 11) 41 | return ParagraphWithSentenceCount(n) 42 | } 43 | 44 | // ArticleWithParagraphCount will build a random article string consisting 45 | // of n paragraphs. 46 | func ArticleWithParagraphCount(n int) string { 47 | p := make([]string, 0, n) 48 | for i := 0; i < n; i++ { 49 | p = append(p, Paragraph()) 50 | } 51 | return strings.Join(p, "\n") 52 | } 53 | 54 | // Article will build a random article. 55 | func Article() string { 56 | n := IntInRange(4, 11) 57 | return ArticleWithParagraphCount(n) 58 | } 59 | 60 | // Builder functions 61 | 62 | func sentenceBuilder(params ...string) (interface{}, error) { 63 | return Sentence(), nil 64 | } 65 | 66 | func paragraphWithSentenceCountBuilder(params ...string) (interface{}, error) { 67 | size, err := paramsToInt(params...) 68 | if err != nil { 69 | return nil, err 70 | } 71 | return ParagraphWithSentenceCount(size), nil 72 | } 73 | 74 | func paragraphBuilder(params ...string) (interface{}, error) { 75 | return Paragraph(), nil 76 | } 77 | 78 | func articleWithParagraphCountBuilder(params ...string) (interface{}, error) { 79 | size, err := paramsToInt(params...) 80 | if err != nil { 81 | return nil, err 82 | } 83 | return ArticleWithParagraphCount(size), nil 84 | } 85 | 86 | func articleBuilder(params ...string) (interface{}, error) { 87 | return Article(), nil 88 | } 89 | 90 | // Private functions 91 | 92 | var ( 93 | punctuation = []string{".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "!", "?", "!", "?", ";"} 94 | pluralizeRegexp = regexp.MustCompile(`(ss|ish|ch|x|us)$`) 95 | ) 96 | 97 | const vowels = "aeiouy" 98 | 99 | func makeSentence() string { 100 | sentenceTemplate, _ := GetData("sentence", "sentence_template") 101 | 102 | funcMap := template.FuncMap{ 103 | "noun": func() string { 104 | value, _ := GetData("sentence", "noun") 105 | return value.(string) 106 | }, 107 | "anoun": func() string { 108 | value, _ := GetData("sentence", "noun") 109 | return articleize(value.(string)) 110 | }, 111 | "nouns": func() string { 112 | value, _ := GetData("sentence", "noun") 113 | return pluralize(value.(string)) 114 | }, 115 | "adjective": func() string { 116 | value, _ := GetData("sentence", "adjective") 117 | return value.(string) 118 | }, 119 | "anAdjective": func() string { 120 | value, _ := GetData("sentence", "adjective") 121 | return articleize(value.(string)) 122 | }, 123 | } 124 | 125 | buf := bytes.NewBufferString("") 126 | tmpl := template.Must(template.New("sentence").Funcs(funcMap).Parse(sentenceTemplate.(string))) 127 | err := tmpl.Execute(buf, "") 128 | if err != nil { 129 | panic(err) 130 | } 131 | return buf.String() 132 | } 133 | 134 | func randomStartingPhrase() string { 135 | if Float32InRange(0, 1) < 0.33 { 136 | phrase, err := GetData("sentence", "starting_phrase") 137 | if err != nil { 138 | panic(err) 139 | } 140 | return phrase.(string) 141 | } 142 | return "" 143 | } 144 | 145 | func pickLastPunc() string { 146 | i := IntInRange(0, len(punctuation)-1) 147 | return punctuation[i] 148 | } 149 | 150 | func pluralize(word string) string { 151 | if strings.HasSuffix(word, "s") { 152 | return word 153 | } 154 | 155 | if pluralizeRegexp.MatchString(word) { 156 | word += "e" 157 | } else { 158 | if strings.HasSuffix(word, "y") && !strings.Contains(vowels, string(word[len(word)-2])) { 159 | word = strings.TrimSuffix(word, string(word[len(word)-1])) 160 | word += "ie" 161 | } 162 | } 163 | return word + "s" 164 | } 165 | 166 | func articleize(word string) string { 167 | a := "a" 168 | if strings.Contains("aeiou", string(word[0])) { 169 | a = "an" 170 | } 171 | return fmt.Sprintf("%s %s", a, word) 172 | } 173 | 174 | func capitalize(word string) string { 175 | chars := []rune(word) 176 | chars[0] = unicode.ToUpper(chars[0]) 177 | return string(chars) 178 | } 179 | -------------------------------------------------------------------------------- /sentence_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleSentence() { 12 | faker.SetSeed(1600) 13 | fmt.Println(faker.Sentence()) 14 | // Output: A knowledgeable pomegranate without peaches is truly a panda of compassionate sharks. 15 | } 16 | 17 | func ExampleParagraphWithSentenceCount() { 18 | faker.SetSeed(1601) 19 | fmt.Println(faker.ParagraphWithSentenceCount(5)) 20 | // Output: Their squirrel was, in this moment, an affable goat. A camel is a lion's panda! In modern times dazzling lemons show us how plums can be horses. This is not to discredit the idea that a cat can hardly be considered an amused fish without also being a lobster? An exuberant goldfish is a wolf of the mind. 21 | } 22 | 23 | func ExampleParagraph() { 24 | faker.SetSeed(1602) 25 | fmt.Println(faker.Paragraph()) 26 | // Output: A currant is a deer from the right perspective. Having been a gymnast, authors often misinterpret the tangerine as an intelligent camel, when in actuality it feels more like a communicative bear; As far as he is concerned, a shark is the zebra of a dog. Those kumquats are nothing more than elephants. It's an undeniable fact, really; some posit the hilarious prune to be less than intellectual. A communicative zebra's goat comes with it the thought that the honest snake is a cow? Washing and polishing the car,excited cranberries show us how grapefruits can be elephants. One cannot separate bears from dynamic cows! One cannot separate cats from stimulating spiders. Extending this logic, a goldfish can hardly be considered a succinct spider without also being a cheetah. 27 | } 28 | 29 | func ExampleArticleWithParagraphCount() { 30 | faker.SetSeed(1603) 31 | fmt.Println(faker.ArticleWithParagraphCount(5)) 32 | // Output: The fly of a pig becomes an alert blueberry. The vivacious apricot reveals itself as a powerful lime to those who look! Few can name a resolute turtle that isn't a happy kiwi; The pandas could be said to resemble fair-minded goats. Few can name a modest wolf that isn't a sensible fly! Some generous alligators are thought of simply as chimpanzees. Few can name a thrifty pineapple that isn't a pleasant apricot. 33 | // By the waybefore chickens, snakes were only lemons. If this was somewhat unclear, a kitten is a cow from the right perspective? Shouting with happiness, rabbits are romantic fishes. A watermelon is a humorous apricot. The willing deer comes from a diplomatic turtle? We can assume that any instance of a strawberry can be construed as an affable fish. Framed in a different way, the dolphins could be said to resemble receptive cherries. An intuitive fly's seal comes with it the thought that the relieved cranberry is a sheep. A blackberry is a panda's cheetah. 34 | // A turtle sees a panda as an efficient octopus. Seals are compassionate figs; Shouting with happiness, one cannot separate cherries from talented monkeys! Some skillful giraffes are thought of simply as elephants! Few can name an impartial cranberry that isn't a painstaking grapes. A cheetah can hardly be considered a resolute shark without also being a kitten. We know that they were lost without the helpful cherry that composed their giraffe. An energetic goldfish's grapes comes with it the thought that the eminent lemon is a blueberry! As far as he is concerned, their kumquat was, in this moment, a happy eagle. A careful grape's plum comes with it the thought that the industrious turtle is a duck. 35 | // Their strawberry was, in this moment, a delightful seal. A lively lion is a monkey of the mind. An ant of the plum is assumed to be a kind-hearted frog. It's an undeniable fact, really; they were lost without the brave fish that composed their snail. A mature tiger's zebra comes with it the thought that the resourceful rat is a sheep. 36 | // In modern times a hamster sees a peach as a helpful fig. In modern times a dog is the fox of a bee. One cannot separate chimpanzees from diplomatic snakes. Some funny seals are thought of simply as grapes; Having been a gymnast, they were lost without the encouraging nectarine that composed their pineapple. This is not to discredit the idea that punctual lions show us how zebras can be pears. Skillful chickens show us how chimpanzees can be lobsters! Few can name an inventive turtle that isn't an adaptable raspberry. Washing and polishing the car,we can assume that any instance of a lime can be construed as an intellectual currant. A cat can hardly be considered a peaceful scorpion without also being a crocodile; 37 | } 38 | 39 | func ExampleArticle() { 40 | faker.SetSeed(1604) 41 | fmt.Println(faker.Article()) 42 | // Output: Few can name a sincere chimpanzee that isn't a selective cranberry. They were lost without the straightforward camel that composed their puppy; However, the zebras could be said to resemble tidy bears. Cultured hippopotamus show us how blackberries can be squirrels. In recent years, a cherry sees a nectarine as a resolute bear. This is not to discredit the idea that a crocodile is an emotional prune; 43 | // An amiable watermelon is a horse of the mind. To be more specific, a panda can hardly be considered an inventive hamster without also being a lime? A camel of the kangaroo is assumed to be a cooperative tiger; Before plums, kangaroos were only melons. 44 | // In modern times those puppies are nothing more than persimmons. The literature would have us believe that a silly octopus is not but a rabbit. Their blackberry was, in this moment, a protective banana. A puppy is the pear of a grapes. Some posit the amiable pig to be less than helpful. 45 | // Far from the truth, authors often misinterpret the owl as a calm crocodile, when in actuality it feels more like a placid orange. Extending this logic, some honest turtles are thought of simply as horses. The cherry of an apple becomes a brave chimpanzee; Draped neatly on a hanger, authors often misinterpret the octopus as a happy cranberry, when in actuality it feels more like a harmonious kiwi. The oranges could be said to resemble unusual lemons! Their melon was, in this moment, an impartial hippopotamus. Plums are diligent frogs. By the waya zebra is a thrifty fish. 46 | // The giraffes could be said to resemble broad-minded kangaroos. The first jolly plum is, in its own way, a grape! Extending this logic, the lobster is an orange. Shouting with happiness, the affable grape comes from a thrifty kiwi. However, their panda was, in this moment, an upbeat spider. An inventive deer's kumquat comes with it the thought that the excited cranberry is a spider. 47 | // Those bears are nothing more than goldfishes. Authors often misinterpret the bird as an imaginative persimmon, when in actuality it feels more like an intellectual apricot! An apple is an owl from the right perspective. A camel is the fig of an octopus. What we don't know for sure is whether or not foxes are faithful lions. The literature would have us believe that a pleasant tiger is not but a shark. 48 | } 49 | 50 | func TestSentenceBuild(t *testing.T) { 51 | faker.SetSeed(1720) 52 | s := &struct { 53 | Field1 string `faker:"Sentence"` 54 | Field2 string `faker:"ParagraphWithSentenceCount(3)"` 55 | Field3 string `faker:"Paragraph"` 56 | Field4 string `faker:"ArticleWithParagraphCount(2)"` 57 | Field5 string `faker:"Article"` 58 | }{} 59 | err := faker.Build(&s) 60 | assert.Nil(t, err) 61 | t.Log(s) 62 | assert.Equal(t, "As far as he is concerned, the faithful zebra comes from a peaceful raspberry.", s.Field1) 63 | assert.Equal(t, "The successful cranberry comes from a neat eagle. To be more specific, authors often misinterpret the grape as an obedient crocodile, when in actuality it feels more like a plucky blueberry; In ancient times few can name a practical sheep that isn't a hilarious fish.", s.Field2) 64 | assert.Equal(t, "In ancient times the fishes could be said to resemble amused foxes. The first detailed kitten is, in its own way, a cranberry. What we don't know for sure is whether or not the raspberry is an ant. The zeitgeist contends that a chimpanzee is the grapes of a bear. They were lost without the romantic melon that composed their fly! A proud nectarine without birds is truly a dog of polite giraffes; Recent controversy aside, the alluring goldfish comes from a knowledgeable spider.", s.Field3) 65 | assert.Equal(t, "A straightforward currant's lime comes with it the thought that the placid cow is a cheetah. The literature would have us believe that a painstaking kangaroo is not but a cherry? Of course, they were lost without the obedient fox that composed their alligator. A cat of the shark is assumed to be a humorous pig.\nDraped neatly on a hanger, the happy lobster reveals itself as an optimistic hippopotamus to those who look. However, the glorious alligator reveals itself as a lively monkey to those who look? An alligator is an ant from the right perspective. Unfortunately, that is wrong; on the contrary, a pro-active squirrel is a fish of the mind;", s.Field4) 66 | assert.Equal(t, "As far as he is concerned, the wolf of a crocodile becomes a talented goldfish. An adaptable owl's hippopotamus comes with it the thought that the cooperative bird is a seal. The first amusing kitten is, in its own way, a monkey? Some assert that the lion is a cow. The ants could be said to resemble comfortable watermelons. This is not to discredit the idea that the zebras could be said to resemble creative turtles. The first eminent elephant is, in its own way, a cheetah. The peaches could be said to resemble responsible rabbits; Far from the truth, few can name a decorous kumquat that isn't a sincere cat!\nOf course, some intelligent blackberries are thought of simply as ants. To be more specific, skillful monkeys show us how goldfishes can be grapes. We can assume that any instance of a nectarine can be construed as an agreeable crocodile. The hamster of an elephant becomes a joyous lime. Draped neatly on a hanger, some posit the amused deer to be less than reflective. Though we assume the latter, hamsters are industrious apricots? Before fishes, goldfishes were only scorpions; Recent controversy aside, a camel can hardly be considered a stimulating frog without also being a pineapple. Some posit the harmonious wolf to be less than sincere.\nThe literature would have us believe that an eager pig is not but a rabbit; A kitten can hardly be considered an imaginative sheep without also being a kiwi. Recent controversy aside, the first energetic camel is, in its own way, a blackberry. Authors often misinterpret the grape as an agreeable snake, when in actuality it feels more like a stimulating blackberry. A grape is an intellectual grape. Of course, those nectarines are nothing more than lemons! They were lost without the generous rabbit that composed their strawberry. This could be, or perhaps the raspberry of a pineapple becomes a splendid raspberry. Of course, amiable birds show us how lobsters can be deers. The literature would have us believe that an amicable blackberry is not but an apple?\nThe eagles could be said to resemble intelligent currants. Fabulous crocodiles show us how kiwis can be bees. A raspberry can hardly be considered a loving lemon without also being a grapes? One cannot separate plums from resolute blackberries. We can assume that any instance of a turtle can be construed as an amicable seal. The orange of a puppy becomes a wise sheep. What we don't know for sure is whether or not some posit the sensitive chimpanzee to be less than proud? The scorpion is a rat. Those snakes are nothing more than snails? A lemon is the kitten of a currant!\nSome posit the boundless monkey to be less than fine. A succinct tiger's zebra comes with it the thought that the enchanting hamster is an elephant. A bee is an elated monkey? The powerful alligator reveals itself as a righteous kitten to those who look. The first gentle lion is, in its own way, a blackberry. Recent controversy aside, watermelons are tough cows? The instinctive scorpion reveals itself as a broad-minded deer to those who look;\nA kumquat is the strawberry of a blueberry. The literature would have us believe that an affable apple is not but a pomegranate. The literature would have us believe that an optimistic pomegranate is not but a pig. A persimmon is a credible currant; A panda sees an orange as a quick-witted ant; Nowhere is it disputed that before ants, rats were only frogs; This is not to discredit the idea that the first modern kangaroo is, in its own way, a dolphin? Shouting with happiness, a relieved horse's lobster comes with it the thought that the fabulous cherry is a fig. This is not to discredit the idea that an alluring cherry without snakes is truly a scorpion of dynamic grapefruits! The literature would have us believe that a faithful bird is not but a giraffe. Draped neatly on a hanger, dazzling melons show us how goldfishes can be ducks;\nThe hamsters could be said to resemble encouraging deers. The frog of a squirrel becomes an amiable apricot. Some upbeat giraffes are thought of simply as bananas. If this was somewhat unclear, an exclusive frog's strawberry comes with it the thought that the fair-minded horse is a hippopotamus!", s.Field5) 67 | } 68 | 69 | func TestSentenceInvalidParams(t *testing.T) { 70 | faker.SetSeed(1721) 71 | s1 := &struct { 72 | Field string `faker:"ParagraphWithSentenceCount(a)"` 73 | }{} 74 | err := faker.Build(&s1) 75 | assert.NotNil(t, err) 76 | assert.Equal(t, "invalid parameters: strconv.Atoi: parsing \"a\": invalid syntax", err.Error()) 77 | 78 | s2 := &struct { 79 | Field string `faker:"ArticleWithParagraphCount(a)"` 80 | }{} 81 | err = faker.Build(&s2) 82 | assert.NotNil(t, err) 83 | assert.Equal(t, "invalid parameters: strconv.Atoi: parsing \"a\": invalid syntax", err.Error()) 84 | } 85 | -------------------------------------------------------------------------------- /slice.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | // Slice will build a random slice of interface{} of length n. The elements of 8 | // the slice are genereted by the function fn. 9 | func Slice(size int, fn func() interface{}) []interface{} { 10 | slice := make([]interface{}, 0, size) 11 | for i := 0; i < size; i++ { 12 | slice = append(slice, fn()) 13 | } 14 | return slice 15 | } 16 | 17 | // Sample return a random element of slice. Sample panics if slice is not a 18 | // slice, is nil or is empty. 19 | func Sample(slice interface{}) interface{} { 20 | if reflect.TypeOf(slice).Kind() != reflect.Slice { 21 | panic("faker.Sample param must be a slice") 22 | } 23 | sliceReflectValue := reflect.ValueOf(slice) 24 | if sliceReflectValue.IsNil() { 25 | panic("faker.Sample param is nil") 26 | } 27 | if sliceReflectValue.Len() == 0 { 28 | panic("faker.Sample param is empty") 29 | } 30 | i := IntInRange(0, sliceReflectValue.Len()-1) 31 | return sliceReflectValue.Index(i).Interface() 32 | } 33 | -------------------------------------------------------------------------------- /slice_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleSlice() { 12 | faker.SetSeed(200) 13 | fmt.Println(faker.Slice(3, func() interface{} { return faker.IntInRange(0, 10) })) 14 | // Output: [6 9 9] 15 | } 16 | 17 | func ExampleSample() { 18 | faker.SetSeed(201) 19 | slice := []int{1, 2, 3, 4, 5} 20 | fmt.Println(faker.Sample(slice)) 21 | // Output: 5 22 | } 23 | 24 | func TestSampleWithNoSliceArg(t *testing.T) { 25 | assert.PanicsWithValue(t, "faker.Sample param must be a slice", func() { 26 | faker.Sample(2) 27 | }) 28 | } 29 | 30 | func TestSampleWithNilSlice(t *testing.T) { 31 | var slice []int 32 | assert.PanicsWithValue(t, "faker.Sample param is nil", func() { 33 | faker.Sample(slice) 34 | }) 35 | } 36 | 37 | func TestSampleWithEmptySlice(t *testing.T) { 38 | slice := make([]int, 0) 39 | assert.PanicsWithValue(t, "faker.Sample param is empty", func() { 40 | faker.Sample(slice) 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /string.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | ) 7 | 8 | const digits = "0123456789" 9 | const lowerLetters = "abcdefghijklmnopqrstuvwxyz" 10 | const upperLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 11 | const charset = digits + lowerLetters + upperLetters 12 | 13 | // StringWithSize will build a random string of length size. 14 | func StringWithSize(size int) string { 15 | return stringWithSize(size, charset) 16 | } 17 | 18 | // String will build a random string of length between 1 and 8. 19 | func String() string { 20 | return StringWithSize(IntInRange(1, 8)) 21 | } 22 | 23 | // DigitsWithSize will build a random string of only digits of length size. 24 | func DigitsWithSize(size int) string { 25 | return stringWithSize(size, digits) 26 | } 27 | 28 | // Digits will build a random string of only digits of length between 1 and 8. 29 | func Digits() string { 30 | return DigitsWithSize(IntInRange(1, 8)) 31 | } 32 | 33 | // LettersWithSize will build a random string of only letters of length size. 34 | func LettersWithSize(size int) string { 35 | return stringWithSize(size, lowerLetters+upperLetters) 36 | } 37 | 38 | // Letters will build a random string of only letters of length between 1 and 8. 39 | func Letters() string { 40 | return LettersWithSize(IntInRange(1, 8)) 41 | } 42 | 43 | // Lexify will replace all occurrences of "?" in str with a random letter. 44 | func Lexify(str string) string { 45 | return replaceChar(str, "?", func() string { return LettersWithSize(1) }) 46 | } 47 | 48 | // Numerify will replace all occurrences of "?" in str with a random digit. 49 | func Numerify(str string) string { 50 | return replaceChar(str, "?", func() string { return DigitsWithSize(1) }) 51 | } 52 | 53 | // Parameterize replaces special characters in str so that it may be used as part of a 'pretty' URL. 54 | func Parameterize(str string) string { 55 | notAlphaNumRegExp := regexp.MustCompile("[^A-Za-z0-9]+") 56 | firstLastDashRegexp := regexp.MustCompile("^-|-$") 57 | 58 | parameterizeString := notAlphaNumRegExp.ReplaceAllString(str, "-") 59 | parameterizeString = firstLastDashRegexp.ReplaceAllString(parameterizeString, "") 60 | return strings.ToLower(parameterizeString) 61 | } 62 | 63 | // Pick returns a random string among those passed as parameters. 64 | func Pick(pool ...string) string { 65 | if len(pool) == 0 { 66 | return "" 67 | } 68 | i := IntInRange(0, len(pool)-1) 69 | return pool[i] 70 | } 71 | 72 | // Private functions 73 | 74 | func stringWithSize(size int, charset string) string { 75 | b := make([]byte, size) 76 | for i := range b { 77 | b[i] = charset[random.Intn(len(charset))] 78 | } 79 | return string(b) 80 | } 81 | 82 | func replaceChar(str, chr string, fn func() string) string { 83 | r := str 84 | count := strings.Count(str, chr) 85 | for i := 0; i < count; i++ { 86 | r = strings.Replace(r, chr, fn(), 1) 87 | } 88 | return r 89 | } 90 | 91 | // Builder functions 92 | 93 | func stringWithSizeBuilder(params ...string) (interface{}, error) { 94 | size, err := paramsToInt(params...) 95 | if err != nil { 96 | return nil, err 97 | } 98 | return StringWithSize(size), nil 99 | } 100 | 101 | func stringBuilder(params ...string) (interface{}, error) { 102 | return String(), nil 103 | } 104 | 105 | func digitsWithSizeBuilder(params ...string) (interface{}, error) { 106 | size, err := paramsToInt(params...) 107 | if err != nil { 108 | return nil, err 109 | } 110 | return DigitsWithSize(size), nil 111 | } 112 | 113 | func digitsBuilder(params ...string) (interface{}, error) { 114 | return Digits(), nil 115 | } 116 | 117 | func lettersWithSizeBuilder(params ...string) (interface{}, error) { 118 | size, err := paramsToInt(params...) 119 | if err != nil { 120 | return nil, err 121 | } 122 | return LettersWithSize(size), nil 123 | } 124 | 125 | func lettersBuilder(params ...string) (interface{}, error) { 126 | return Letters(), nil 127 | } 128 | 129 | func lexifyBuilder(params ...string) (interface{}, error) { 130 | if len(params) != 1 { 131 | return nil, parametersError(nil) 132 | } 133 | return Lexify(params[0]), nil 134 | } 135 | 136 | func numerifyBuilder(params ...string) (interface{}, error) { 137 | if len(params) != 1 { 138 | return nil, parametersError(nil) 139 | } 140 | return Numerify(params[0]), nil 141 | } 142 | 143 | func parameterizeBuilder(params ...string) (interface{}, error) { 144 | if len(params) != 1 { 145 | return nil, parametersError(nil) 146 | } 147 | return Parameterize(params[0]), nil 148 | } 149 | 150 | func pickBuilder(params ...string) (interface{}, error) { 151 | return Pick(params...), nil 152 | } 153 | -------------------------------------------------------------------------------- /string_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func ExampleStringWithSize() { 12 | faker.SetSeed(900) 13 | fmt.Println(faker.StringWithSize(5)) 14 | // Output: zVCVi 15 | } 16 | 17 | func ExampleString() { 18 | faker.SetSeed(901) 19 | fmt.Println(faker.String()) 20 | // Output: PMIWvi6i 21 | } 22 | 23 | func ExampleDigitsWithSize() { 24 | faker.SetSeed(902) 25 | fmt.Println(faker.DigitsWithSize(6)) 26 | // Output: 083232 27 | } 28 | 29 | func ExampleDigits() { 30 | faker.SetSeed(903) 31 | fmt.Println(faker.Digits()) 32 | // Output: 615512 33 | } 34 | 35 | func ExampleLettersWithSize() { 36 | faker.SetSeed(904) 37 | fmt.Println(faker.LettersWithSize(7)) 38 | // Output: ZHCbqwV 39 | } 40 | 41 | func ExampleLetters() { 42 | faker.SetSeed(905) 43 | fmt.Println(faker.Letters()) 44 | // Output: HZ 45 | } 46 | 47 | func ExampleLexify() { 48 | faker.SetSeed(906) 49 | fmt.Println(faker.Lexify("ab?c??d?")) 50 | // Output: abxcZhdZ 51 | } 52 | 53 | func ExampleNumerify() { 54 | faker.SetSeed(907) 55 | fmt.Println(faker.Numerify("ab?c??d???")) 56 | // Output: ab5c30d754 57 | } 58 | 59 | func ExampleParameterize() { 60 | faker.SetSeed(908) 61 | fmt.Println(faker.Parameterize("The Amazing Zanzò 153 ")) 62 | // Output: the-amazing-zanz-153 63 | } 64 | 65 | func ExamplePick() { 66 | faker.SetSeed(909) 67 | fmt.Println(faker.Pick("cat", "dog", "mouse", "lion", "bear")) 68 | // Output: dog 69 | } 70 | 71 | func TestPickWithNoArgs(t *testing.T) { 72 | faker.SetSeed(910) 73 | assert.Equal(t, "", faker.Pick()) 74 | } 75 | 76 | func TestStringBuild(t *testing.T) { 77 | faker.SetSeed(920) 78 | s := &struct { 79 | Field1 string `faker:"StringWithSize(4)"` 80 | Field2 string `faker:"String"` 81 | Field3 string `faker:"DigitsWithSize(5)"` 82 | Field4 string `faker:"Digits(4)"` 83 | Field5 string `faker:"LettersWithSize(6)"` 84 | Field6 string `faker:"Letters"` 85 | Field7 string `faker:"Lexify(a?b?c)"` 86 | Field8 string `faker:"Numerify(???x)"` 87 | Field9 string `faker:"Parameterize(Go is the best programming language!)"` 88 | Field10 string `faker:"Pick(cat,dog,mouse,lion,bear)"` 89 | }{} 90 | err := faker.Build(&s) 91 | assert.Nil(t, err) 92 | t.Log(s) 93 | 94 | assert.Equal(t, "1nkm", s.Field1) 95 | assert.Equal(t, "TeF", s.Field2) 96 | assert.Equal(t, "61017", s.Field3) 97 | assert.Equal(t, "43939689", s.Field4) 98 | assert.Equal(t, "odEMfI", s.Field5) 99 | assert.Equal(t, "VBilXp", s.Field6) 100 | assert.Equal(t, "abbqc", s.Field7) 101 | assert.Equal(t, "111x", s.Field8) 102 | assert.Equal(t, "go-is-the-best-programming-language", s.Field9) 103 | assert.Equal(t, "cat", s.Field10) 104 | } 105 | 106 | func TestStringInvalidParams(t *testing.T) { 107 | faker.SetSeed(921) 108 | s1 := &struct { 109 | Field string `faker:"DigitsWithSize(a)"` 110 | }{} 111 | err := faker.Build(&s1) 112 | assert.NotNil(t, err) 113 | assert.Equal(t, "invalid parameters: strconv.Atoi: parsing \"a\": invalid syntax", err.Error()) 114 | 115 | s2 := &struct { 116 | Field string `faker:"LettersWithSize(a)"` 117 | }{} 118 | err = faker.Build(&s2) 119 | assert.NotNil(t, err) 120 | assert.Equal(t, "invalid parameters: strconv.Atoi: parsing \"a\": invalid syntax", err.Error()) 121 | 122 | s3 := &struct { 123 | Field string `faker:"Lexify"` 124 | }{} 125 | err = faker.Build(&s3) 126 | assert.NotNil(t, err) 127 | assert.Equal(t, "invalid parameters", err.Error()) 128 | 129 | s4 := &struct { 130 | Field string `faker:"Numerify"` 131 | }{} 132 | err = faker.Build(&s4) 133 | assert.NotNil(t, err) 134 | assert.Equal(t, "invalid parameters", err.Error()) 135 | 136 | s5 := &struct { 137 | Field string `faker:"Parameterize"` 138 | }{} 139 | err = faker.Build(&s5) 140 | assert.NotNil(t, err) 141 | assert.Equal(t, "invalid parameters", err.Error()) 142 | } 143 | -------------------------------------------------------------------------------- /time.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "strconv" 5 | "time" 6 | ) 7 | 8 | var timezoneData = PoolGroup{ 9 | "offset": {"-12", "-11", "-10", "-8", "-7", "-6", "-5", "-4.5", "-4", "-3", "-2.5", "-2", "-1", "0", "-1", "0", "1", "2", "3", "4", "4.5", "5", "5.5", "5.75", "6", "6.5", "7", "8", "9", "9.5", "10", "11", "12", "13"}, 10 | "abbr": {"DST", "U", "HST", "AKDT", "PDT", "PDT", "PST", "UMST", "MDT", "MDT", "CAST", "CDT", "CDT", "CCST", "SPST", "EDT", "UEDT", "VST", "PYT", "ADT", "CBST", "SWST", "PSST", "NDT", "ESAST", "AST", "SEST", "GDT", "MST", "BST", "U", "MDT", "ADT", "CVST", "MDT", "UTC", "GMT", "BST", "GDT", "GST", "WEDT", "CEDT", "RDT", "CEDT", "WCAST", "NST", "GDT", "MEDT", "EST", "SDT", "EEDT", "SAST", "FDT", "TDT", "JDT", "LST", "JST", "AST", "KST", "AST", "EAST", "MSK", "SAMT", "IDT", "AST", "ADT", "MST", "GST", "CST", "AST", "WAST", "YEKT", "PKT", "IST", "SLST", "NST", "CAST", "BST", "MST", "SAST", "NCAST", "CST", "NAST", "MPST", "WAST", "TST", "UST", "NAEST", "JST", "KST", "CAST", "ACST", "EAST", "AEST", "WPST", "TST", "YST", "CPST", "VST", "NZST", "U", "FST", "MST", "KDT", "TST", "SST"}, 11 | "text": {"Dateline Standard Time", "UTC-11", "Hawaiian Standard Time", "Alaskan Standard Time", "Pacific Standard Time (Mexico)", "Pacific Daylight Time", "Pacific Standard Time", "US Mountain Standard Time", "Mountain Standard Time (Mexico)", "Mountain Standard Time", "Central America Standard Time", "Central Standard Time", "Central Standard Time (Mexico)", "Canada Central Standard Time", "SA Pacific Standard Time", "Eastern Standard Time", "US Eastern Standard Time", "Venezuela Standard Time", "Paraguay Standard Time", "Atlantic Standard Time", "Central Brazilian Standard Time", "SA Western Standard Time", "Pacific SA Standard Time", "Newfoundland Standard Time", "E. South America Standard Time", "Argentina Standard Time", "SA Eastern Standard Time", "Greenland Standard Time", "Montevideo Standard Time", "Bahia Standard Time", "UTC-02", "Mid-Atlantic Standard Time", "Azores Standard Time", "Cape Verde Standard Time", "Morocco Standard Time", "UTC", "Greenwich Mean Time", "British Summer Time", "GMT Standard Time", "Greenwich Standard Time", "W. Europe Standard Time", "Central Europe Standard Time", "Romance Standard Time", "Central European Standard Time", "W. Central Africa Standard Time", "Namibia Standard Time", "GTB Standard Time", "Middle East Standard Time", "Egypt Standard Time", "Syria Standard Time", "E. Europe Standard Time", "South Africa Standard Time", "FLE Standard Time", "Turkey Standard Time", "Israel Standard Time", "Libya Standard Time", "Jordan Standard Time", "Arabic Standard Time", "Kaliningrad Standard Time", "Arab Standard Time", "E. Africa Standard Time", "Moscow Standard Time", "Samara Time", "Iran Standard Time", "Arabian Standard Time", "Azerbaijan Standard Time", "Mauritius Standard Time", "Georgian Standard Time", "Caucasus Standard Time", "Afghanistan Standard Time", "West Asia Standard Time", "Yekaterinburg Time", "Pakistan Standard Time", "India Standard Time", "Sri Lanka Standard Time", "Nepal Standard Time", "Central Asia Standard Time", "Bangladesh Standard Time", "Myanmar Standard Time", "SE Asia Standard Time", "N. Central Asia Standard Time", "China Standard Time", "North Asia Standard Time", "Singapore Standard Time", "W. Australia Standard Time", "Taipei Standard Time", "Ulaanbaatar Standard Time", "North Asia East Standard Time", "Japan Standard Time", "Korea Standard Time", "Cen. Australia Standard Time", "AUS Central Standard Time", "E. Australia Standard Time", "AUS Eastern Standard Time", "West Pacific Standard Time", "Tasmania Standard Time", "Yakutsk Standard Time", "Central Pacific Standard Time", "Vladivostok Standard Time", "New Zealand Standard Time", "UTC+12", "Fiji Standard Time", "Magadan Standard Time", "Kamchatka Standard Time", "Tonga Standard Time", "Samoa Standard Time"}, 12 | "full": {"(UTC-12:00) International Date Line West", "(UTC-11:00) Coordinated Universal Time-11", "(UTC-10:00) Hawaii", "(UTC-09:00) Alaska", "(UTC-08:00) Baja California", "(UTC-07:00) Pacific Time (US & Canada)", "(UTC-08:00) Pacific Time (US & Canada)", "(UTC-07:00) Arizona", "(UTC-07:00) Chihuahua, La Paz, Mazatlan", "(UTC-07:00) Mountain Time (US & Canada)", "(UTC-06:00) Central America", "(UTC-06:00) Central Time (US & Canada)", "(UTC-06:00) Guadalajara, Mexico City, Monterrey", "(UTC-06:00) Saskatchewan", "(UTC-05:00) Bogota, Lima, Quito", "(UTC-05:00) Eastern Time (US & Canada)", "(UTC-05:00) Indiana (East)", "(UTC-04:30) Caracas", "(UTC-04:00) Asuncion", "(UTC-04:00) Atlantic Time (Canada)", "(UTC-04:00) Cuiaba", "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", "(UTC-04:00) Santiago", "(UTC-03:30) Newfoundland", "(UTC-03:00) Brasilia", "(UTC-03:00) Buenos Aires", "(UTC-03:00) Cayenne, Fortaleza", "(UTC-03:00) Greenland", "(UTC-03:00) Montevideo", "(UTC-03:00) Salvador", "(UTC-02:00) Coordinated Universal Time-02", "(UTC-02:00) Mid-Atlantic - Old", "(UTC-01:00) Azores", "(UTC-01:00) Cape Verde Is.", "(UTC) Casablanca", "(UTC) Coordinated Universal Time", "(UTC) Edinburgh, London", "(UTC+01:00) Edinburgh, London", "(UTC) Dublin, Lisbon", "(UTC) Monrovia, Reykjavik", "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", "(UTC+01:00) West Central Africa", "(UTC+01:00) Windhoek", "(UTC+02:00) Athens, Bucharest", "(UTC+02:00) Beirut", "(UTC+02:00) Cairo", "(UTC+02:00) Damascus", "(UTC+02:00) E. Europe", "(UTC+02:00) Harare, Pretoria", "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", "(UTC+03:00) Istanbul", "(UTC+02:00) Jerusalem", "(UTC+02:00) Tripoli", "(UTC+03:00) Amman", "(UTC+03:00) Baghdad", "(UTC+03:00) Kaliningrad, Minsk", "(UTC+03:00) Kuwait, Riyadh", "(UTC+03:00) Nairobi", "(UTC+03:00) Moscow, St. Petersburg, Volgograd", "(UTC+04:00) Samara, Ulyanovsk, Saratov", "(UTC+03:30) Tehran", "(UTC+04:00) Abu Dhabi, Muscat", "(UTC+04:00) Baku", "(UTC+04:00) Port Louis", "(UTC+04:00) Tbilisi", "(UTC+04:00) Yerevan", "(UTC+04:30) Kabul", "(UTC+05:00) Ashgabat, Tashkent", "(UTC+05:00) Yekaterinburg", "(UTC+05:00) Islamabad, Karachi", "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", "(UTC+05:30) Sri Jayawardenepura", "(UTC+05:45) Kathmandu", "(UTC+06:00) Astana", "(UTC+06:00) Dhaka", "(UTC+06:30) Yangon (Rangoon)", "(UTC+07:00) Bangkok, Hanoi, Jakarta", "(UTC+07:00) Novosibirsk", "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", "(UTC+08:00) Krasnoyarsk", "(UTC+08:00) Kuala Lumpur, Singapore", "(UTC+08:00) Perth", "(UTC+08:00) Taipei", "(UTC+08:00) Ulaanbaatar", "(UTC+09:00) Irkutsk", "(UTC+09:00) Osaka, Sapporo, Tokyo", "(UTC+09:00) Seoul", "(UTC+09:30) Adelaide", "(UTC+09:30) Darwin", "(UTC+10:00) Brisbane", "(UTC+10:00) Canberra, Melbourne, Sydney", "(UTC+10:00) Guam, Port Moresby", "(UTC+10:00) Hobart", "(UTC+10:00) Yakutsk", "(UTC+11:00) Solomon Is., New Caledonia", "(UTC+11:00) Vladivostok", "(UTC+12:00) Auckland, Wellington", "(UTC+12:00) Coordinated Universal Time+12", "(UTC+12:00) Fiji", "(UTC+12:00) Magadan", "(UTC+12:00) Petropavlovsk-Kamchatsky - Old", "(UTC+13:00) Nuku'alofa", "(UTC+13:00) Samoa"}, 13 | "region": {"Africa/Abidjan", "Africa/Accra", "Africa/Addis_Ababa", "Africa/Algiers", "Africa/Asmara", "Africa/Bamako", "Africa/Bangui", "Africa/Banjul", "Africa/Bissau", "Africa/Blantyre", "Africa/Brazzaville", "Africa/Bujumbura", "Africa/Cairo", "Africa/Casablanca", "Africa/Ceuta", "Africa/Conakry", "Africa/Dakar", "Africa/Dar_es_Salaam", "Africa/Djibouti", "Africa/Douala", "Africa/El_Aaiun", "Africa/Freetown", "Africa/Gaborone", "Africa/Harare", "Africa/Johannesburg", "Africa/Juba", "Africa/Kampala", "Africa/Khartoum", "Africa/Kigali", "Africa/Kinshasa", "Africa/Lagos", "Africa/Libreville", "Africa/Lome", "Africa/Luanda", "Africa/Lubumbashi", "Africa/Lusaka", "Africa/Malabo", "Africa/Maputo", "Africa/Maseru", "Africa/Mbabane", "Africa/Mogadishu", "Africa/Monrovia", "Africa/Nairobi", "Africa/Ndjamena", "Africa/Niamey", "Africa/Nouakchott", "Africa/Ouagadougou", "Africa/Porto-Novo", "Africa/Sao_Tome", "Africa/Timbuktu", "Africa/Tripoli", "Africa/Tunis", "Africa/Windhoek", "America/Adak", "America/Anchorage", "America/Anguilla", "America/Antigua", "America/Araguaina", "America/Argentina/Buenos_Aires", "America/Argentina/Catamarca", "America/Argentina/ComodRivadavia", "America/Argentina/Cordoba", "America/Argentina/Jujuy", "America/Argentina/La_Rioja", "America/Argentina/Mendoza", "America/Argentina/Rio_Gallegos", "America/Argentina/Salta", "America/Argentina/San_Juan", "America/Argentina/San_Luis", "America/Argentina/Tucuman", "America/Argentina/Ushuaia", "America/Aruba", "America/Asuncion", "America/Atikokan", "America/Atka", "America/Bahia", "America/Bahia_Banderas", "America/Barbados", "America/Belem", "America/Belize", "America/Blanc-Sablon", "America/Boa_Vista", "America/Bogota", "America/Boise", "America/Buenos_Aires", "America/Cambridge_Bay", "America/Campo_Grande", "America/Cancun", "America/Caracas", "America/Catamarca", "America/Cayenne", "America/Cayman", "America/Chicago", "America/Chihuahua", "America/Coral_Harbour", "America/Cordoba", "America/Costa_Rica", "America/Creston", "America/Cuiaba", "America/Curacao", "America/Danmarkshavn", "America/Dawson", "America/Dawson_Creek", "America/Denver", "America/Detroit", "America/Dominica", "America/Edmonton", "America/Eirunepe", "America/El_Salvador", "America/Ensenada", "America/Fort_Nelson", "America/Fort_Wayne", "America/Fortaleza", "America/Glace_Bay", "America/Godthab", "America/Goose_Bay", "America/Grand_Turk", "America/Grenada", "America/Guadeloupe", "America/Guatemala", "America/Guayaquil", "America/Guyana", "America/Halifax", "America/Havana", "America/Hermosillo", "America/Indiana/Indianapolis", "America/Indiana/Knox", "America/Indiana/Marengo", "America/Indiana/Petersburg", "America/Indiana/Tell_City", "America/Indiana/Vevay", "America/Indiana/Vincennes", "America/Indiana/Winamac", "America/Indianapolis", "America/Inuvik", "America/Iqaluit", "America/Jamaica", "America/Jujuy", "America/Juneau", "America/Kentucky/Louisville", "America/Kentucky/Monticello", "America/Knox_IN", "America/Kralendijk", "America/La_Paz", "America/Lima", "America/Los_Angeles", "America/Louisville", "America/Lower_Princes", "America/Maceio", "America/Managua", "America/Manaus", "America/Marigot", "America/Martinique", "America/Matamoros", "America/Mazatlan", "America/Mendoza", "America/Menominee", "America/Merida", "America/Metlakatla", "America/Mexico_City", "America/Miquelon", "America/Moncton", "America/Monterrey", "America/Montevideo", "America/Montreal", "America/Montserrat", "America/Nassau", "America/New_York", "America/Nipigon", "America/Nome", "America/Noronha", "America/North_Dakota/Beulah", "America/North_Dakota/Center", "America/North_Dakota/New_Salem", "America/Ojinaga", "America/Panama", "America/Pangnirtung", "America/Paramaribo", "America/Phoenix", "America/Port_of_Spain", "America/Port-au-Prince", "America/Porto_Acre", "America/Porto_Velho", "America/Puerto_Rico", "America/Punta_Arenas", "America/Rainy_River", "America/Rankin_Inlet", "America/Recife", "America/Regina", "America/Resolute", "America/Rio_Branco", "America/Rosario", "America/Santa_Isabel", "America/Santarem", "America/Santiago", "America/Santo_Domingo", "America/Sao_Paulo", "America/Scoresbysund", "America/Shiprock", "America/Sitka", "America/St_Barthelemy", "America/St_Johns", "America/St_Kitts", "America/St_Lucia", "America/St_Thomas", "America/St_Vincent", "America/Swift_Current", "America/Tegucigalpa", "America/Thule", "America/Thunder_Bay", "America/Tijuana", "America/Toronto", "America/Tortola", "America/Vancouver", "America/Virgin", "America/Whitehorse", "America/Winnipeg", "America/Yakutat", "America/Yellowknife", "Antarctica/Casey", "Antarctica/Davis", "Antarctica/DumontDUrville", "Antarctica/Macquarie", "Antarctica/Mawson", "Antarctica/McMurdo", "Antarctica/Palmer", "Antarctica/Rothera", "Antarctica/South_Pole", "Antarctica/Syowa", "Antarctica/Troll", "Antarctica/Vostok", "Arctic/Longyearbyen", "Asia/Aden", "Asia/Almaty", "Asia/Amman", "Asia/Anadyr", "Asia/Aqtau", "Asia/Aqtobe", "Asia/Ashgabat", "Asia/Ashkhabad", "Asia/Atyrau", "Asia/Baghdad", "Asia/Bahrain", "Asia/Baku", "Asia/Bangkok", "Asia/Barnaul", "Asia/Beirut", "Asia/Bishkek", "Asia/Brunei", "Asia/Calcutta", "Asia/Chita", "Asia/Choibalsan", "Asia/Chongqing", "Asia/Chungking", "Asia/Colombo", "Asia/Dacca", "Asia/Damascus", "Asia/Dhaka", "Asia/Dili", "Asia/Dubai", "Asia/Dushanbe", "Asia/Famagusta", "Asia/Gaza", "Asia/Harbin", "Asia/Hebron", "Asia/Ho_Chi_Minh", "Asia/Hong_Kong", "Asia/Hovd", "Asia/Irkutsk", "Asia/Istanbul", "Asia/Jakarta", "Asia/Jayapura", "Asia/Jerusalem", "Asia/Kabul", "Asia/Kamchatka", "Asia/Karachi", "Asia/Kashgar", "Asia/Kathmandu", "Asia/Katmandu", "Asia/Khandyga", "Asia/Kolkata", "Asia/Krasnoyarsk", "Asia/Kuala_Lumpur", "Asia/Kuching", "Asia/Kuwait", "Asia/Macao", "Asia/Macau", "Asia/Magadan", "Asia/Makassar", "Asia/Manila", "Asia/Muscat", "Asia/Novokuznetsk", "Asia/Novosibirsk", "Asia/Omsk", "Asia/Oral", "Asia/Phnom_Penh", "Asia/Pontianak", "Asia/Pyongyang", "Asia/Qatar", "Asia/Qyzylorda", "Asia/Rangoon", "Asia/Riyadh", "Asia/Saigon", "Asia/Sakhalin", "Asia/Samarkand", "Asia/Seoul", "Asia/Shanghai", "Asia/Singapore", "Asia/Srednekolymsk", "Asia/Taipei", "Asia/Tashkent", "Asia/Tbilisi", "Asia/Tehran", "Asia/Tel_Aviv", "Asia/Thimbu", "Asia/Thimphu", "Asia/Tokyo", "Asia/Tomsk", "Asia/Ujung_Pandang", "Asia/Ulaanbaatar", "Asia/Ulan_Bator", "Asia/Urumqi", "Asia/Ust-Nera", "Asia/Vientiane", "Asia/Vladivostok", "Asia/Yakutsk", "Asia/Yangon", "Asia/Yekaterinburg", "Asia/Yerevan", "Atlantic/Azores", "Atlantic/Bermuda", "Atlantic/Canary", "Atlantic/Cape_Verde", "Atlantic/Faeroe", "Atlantic/Faroe", "Atlantic/Jan_Mayen", "Atlantic/Madeira", "Atlantic/Reykjavik", "Atlantic/South_Georgia", "Atlantic/St_Helena", "Atlantic/Stanley", "Australia/Adelaide", "Australia/Brisbane", "Australia/Broken_Hill", "Australia/Canberra", "Australia/Currie", "Australia/Darwin", "Australia/Eucla", "Australia/Hobart", "Australia/Lindeman", "Australia/Lord_Howe", "Australia/Melbourne", "Australia/Perth", "Australia/Sydney", "Australia/Yancowinna", "Etc/GMT", "Etc/GMT+0", "Etc/GMT+1", "Etc/GMT+10", "Etc/GMT+11", "Etc/GMT+12", "Etc/GMT+2", "Etc/GMT+3", "Etc/GMT+4", "Etc/GMT+5", "Etc/GMT+6", "Etc/GMT+7", "Etc/GMT+8", "Etc/GMT+9", "Etc/GMT0", "Etc/GMT-0", "Etc/GMT-1", "Etc/GMT-10", "Etc/GMT-11", "Etc/GMT-12", "Etc/GMT-13", "Etc/GMT-14", "Etc/GMT-2", "Etc/GMT-3", "Etc/GMT-4", "Etc/GMT-5", "Etc/GMT-6", "Etc/GMT-7", "Etc/GMT-8", "Etc/GMT-9", "Etc/UTC", "Europe/Amsterdam", "Europe/Andorra", "Europe/Astrakhan", "Europe/Athens", "Europe/Belfast", "Europe/Belgrade", "Europe/Berlin", "Europe/Bratislava", "Europe/Brussels", "Europe/Bucharest", "Europe/Budapest", "Europe/Busingen", "Europe/Chisinau", "Europe/Copenhagen", "Europe/Dublin", "Europe/Gibraltar", "Europe/Guernsey", "Europe/Helsinki", "Europe/Isle_of_Man", "Europe/Istanbul", "Europe/Jersey", "Europe/Kaliningrad", "Europe/Kiev", "Europe/Kirov", "Europe/Lisbon", "Europe/Ljubljana", "Europe/London", "Europe/Luxembourg", "Europe/Madrid", "Europe/Malta", "Europe/Mariehamn", "Europe/Minsk", "Europe/Monaco", "Europe/Moscow", "Asia/Nicosia", "Europe/Oslo", "Europe/Paris", "Europe/Podgorica", "Europe/Prague", "Europe/Riga", "Europe/Rome", "Europe/Samara", "Europe/San_Marino", "Europe/Sarajevo", "Europe/Saratov", "Europe/Simferopol", "Europe/Skopje", "Europe/Sofia", "Europe/Stockholm", "Europe/Tallinn", "Europe/Tirane", "Europe/Tiraspol", "Europe/Ulyanovsk", "Europe/Uzhgorod", "Europe/Vaduz", "Europe/Vatican", "Europe/Vienna", "Europe/Vilnius", "Europe/Volgograd", "Europe/Warsaw", "Europe/Zagreb", "Europe/Zaporozhye", "Europe/Zurich", "Indian/Antananarivo", "Indian/Chagos", "Indian/Christmas", "Indian/Cocos", "Indian/Comoro", "Indian/Kerguelen", "Indian/Mahe", "Indian/Maldives", "Indian/Mauritius", "Indian/Mayotte", "Indian/Reunion", "Pacific/Apia", "Pacific/Auckland", "Pacific/Bougainville", "Pacific/Chatham", "Pacific/Chuuk", "Pacific/Easter", "Pacific/Efate", "Pacific/Enderbury", "Pacific/Fakaofo", "Pacific/Fiji", "Pacific/Funafuti", "Pacific/Galapagos", "Pacific/Gambier", "Pacific/Guadalcanal", "Pacific/Guam", "Pacific/Honolulu", "Pacific/Johnston", "Pacific/Kiritimati", "Pacific/Kosrae", "Pacific/Kwajalein", "Pacific/Majuro", "Pacific/Marquesas", "Pacific/Midway", "Pacific/Nauru", "Pacific/Niue", "Pacific/Norfolk", "Pacific/Noumea", "Pacific/Pago_Pago", "Pacific/Palau", "Pacific/Pitcairn", "Pacific/Pohnpei", "Pacific/Ponape", "Pacific/Port_Moresby", "Pacific/Rarotonga", "Pacific/Saipan", "Pacific/Samoa", "Pacific/Tahiti", "Pacific/Tarawa", "Pacific/Tongatapu", "Pacific/Truk", "Pacific/Wake", "Pacific/Wallis", "Pacific/Yap"}, 14 | } 15 | 16 | // DurationInRange will build a random time.Duration between min and max 17 | // included. 18 | func DurationInRange(min, max time.Duration) time.Duration { 19 | return time.Duration(Int64InRange(int64(min), int64(max))) 20 | } 21 | 22 | // Duration will build a random time.Duration. 23 | func Duration() time.Duration { 24 | return time.Duration(Int64()) 25 | } 26 | 27 | // TimeInRange will build a random time.Time between min and max included. 28 | func TimeInRange(min, max time.Time) time.Time { 29 | if min.After(max) { 30 | return min 31 | } 32 | d := DurationInRange(0, max.Sub(min)) 33 | return min.Add(d) 34 | } 35 | 36 | // Time will build a random time.Time. 37 | func Time() time.Time { 38 | return time.Now().Add(Duration()) 39 | } 40 | 41 | // TimeNow will build the current time. 42 | func TimeNow() time.Time { 43 | return time.Now() 44 | } 45 | 46 | // NanoSecond will build a random nano second. 47 | func NanoSecond() int { 48 | return IntInRange(0, 999999999) 49 | } 50 | 51 | // Second will build a random second. 52 | func Second() int { 53 | return IntInRange(0, 59) 54 | } 55 | 56 | // Minute will build a random minute. 57 | func Minute() int { 58 | return IntInRange(0, 59) 59 | } 60 | 61 | // Hour will build a random hour in military time. 62 | func Hour() int { 63 | return IntInRange(0, 23) 64 | } 65 | 66 | // Day will build a random day between 1 - 31. 67 | func Day() int { 68 | return IntInRange(1, 31) 69 | } 70 | 71 | // WeekDay will build a random weekday string (Monday-Sunday). 72 | func WeekDay() string { 73 | return time.Weekday(IntInRange(0, 6)).String() 74 | } 75 | 76 | // Month will build a random month string. 77 | func Month() string { 78 | return time.Month(IntInRange(1, 12)).String() 79 | } 80 | 81 | // Year will build a random year between 1900 - 2100. 82 | func Year() int { 83 | return IntInRange(1900, 2100) 84 | } 85 | 86 | // TimeZone will build a random timezone string. 87 | func TimeZone() string { 88 | timezone, _ := GetData("timezone", "text") 89 | return timezone.(string) 90 | } 91 | 92 | // TimeZoneAbbr will build a random abbreviated timezone string. 93 | func TimeZoneAbbr() string { 94 | timezone, _ := GetData("timezone", "abbr") 95 | return timezone.(string) 96 | } 97 | 98 | // TimeZoneFull will build a random full timezone string. 99 | func TimeZoneFull() string { 100 | timezone, _ := GetData("timezone", "full") 101 | return timezone.(string) 102 | } 103 | 104 | // TimeZoneOffset will build a random timezone offset. 105 | func TimeZoneOffset() float32 { 106 | offsetString, _ := GetData("timezone", "offset") 107 | offset, err := strconv.ParseFloat(offsetString.(string), 32) 108 | if err != nil { 109 | panic(err) 110 | } 111 | return float32(offset) 112 | } 113 | 114 | // TimeZoneRegion will build a random timezone region string. 115 | func TimeZoneRegion() string { 116 | timezone, _ := GetData("timezone", "region") 117 | return timezone.(string) 118 | } 119 | 120 | // Builder functions 121 | 122 | func durationInRangeBuilder(params ...string) (interface{}, error) { 123 | min, max, err := paramsToMinMaxDuration(params...) 124 | if err != nil { 125 | return nil, err 126 | } 127 | return DurationInRange(min, max), nil 128 | } 129 | 130 | func durationBuilder(params ...string) (interface{}, error) { 131 | return Duration(), nil 132 | } 133 | 134 | func timeBuilder(params ...string) (interface{}, error) { 135 | return Time(), nil 136 | } 137 | 138 | func timeNowBuilder(params ...string) (interface{}, error) { 139 | return TimeNow(), nil 140 | } 141 | 142 | func nanoSecondBuilder(params ...string) (interface{}, error) { 143 | return NanoSecond(), nil 144 | } 145 | 146 | func secondBuilder(params ...string) (interface{}, error) { 147 | return Second(), nil 148 | } 149 | 150 | func minuteBuilder(params ...string) (interface{}, error) { 151 | return Minute(), nil 152 | } 153 | 154 | func hourBuilder(params ...string) (interface{}, error) { 155 | return Hour(), nil 156 | } 157 | 158 | func dayBuilder(params ...string) (interface{}, error) { 159 | return Day(), nil 160 | } 161 | 162 | func weekDayBuilder(params ...string) (interface{}, error) { 163 | return WeekDay(), nil 164 | } 165 | 166 | func monthBuilder(params ...string) (interface{}, error) { 167 | return Month(), nil 168 | } 169 | 170 | func yearBuilder(params ...string) (interface{}, error) { 171 | return Year(), nil 172 | } 173 | 174 | func timeZoneBuilder(params ...string) (interface{}, error) { 175 | return TimeZone(), nil 176 | } 177 | 178 | func timeZoneAbbrBuilder(params ...string) (interface{}, error) { 179 | return TimeZoneAbbr(), nil 180 | } 181 | 182 | func timeZoneFullBuilder(params ...string) (interface{}, error) { 183 | return TimeZoneFull(), nil 184 | } 185 | 186 | func timeZoneOffsetBuilder(params ...string) (interface{}, error) { 187 | return TimeZoneOffset(), nil 188 | } 189 | 190 | func timeZoneRegionBuilder(params ...string) (interface{}, error) { 191 | return TimeZoneRegion(), nil 192 | } 193 | -------------------------------------------------------------------------------- /time_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | 8 | "github.com/pioz/faker" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func ExampleDurationInRange() { 13 | faker.SetSeed(41) 14 | fmt.Println(faker.DurationInRange(100, 200)) 15 | // Output: 158ns 16 | } 17 | 18 | func ExampleDuration() { 19 | faker.SetSeed(42) 20 | fmt.Println(faker.Duration()) 21 | // Output: -1606331h18m2.623497133s 22 | } 23 | 24 | func TestTimeInRange(t *testing.T) { 25 | faker.SetSeed(43) 26 | var minTime, maxTime, value time.Time 27 | 28 | minTime, _ = time.ParseInLocation(time.RFC3339, "1984-10-21T22:08:41+00:00", time.UTC) 29 | maxTime, _ = time.ParseInLocation(time.RFC3339, "1980-10-21T22:08:41+00:00", time.UTC) 30 | value = faker.TimeInRange(minTime, maxTime) 31 | t.Log(value) 32 | assert.Equal(t, "1984-10-21 22:08:41 +0000 UTC", value.String()) 33 | 34 | minTime, _ = time.ParseInLocation(time.RFC3339, "1984-10-21T22:08:41+00:00", time.UTC) 35 | maxTime, _ = time.ParseInLocation(time.RFC3339, "2020-10-21T22:08:41+00:00", time.UTC) 36 | value = faker.TimeInRange(minTime, maxTime) 37 | t.Log(value) 38 | assert.Equal(t, "1992-10-10 23:04:44.977812265 +0000 UTC", value.String()) 39 | } 40 | 41 | func TestTime(t *testing.T) { 42 | faker.SetSeed(44) 43 | value := faker.Time() 44 | t.Log(value) 45 | assert.NotEmpty(t, value) 46 | } 47 | 48 | func TestNowTime(t *testing.T) { 49 | faker.SetSeed(44) 50 | value := faker.TimeNow() 51 | t.Log(value) 52 | assert.NotEmpty(t, value) 53 | } 54 | 55 | func ExampleNanoSecond() { 56 | faker.SetSeed(45) 57 | fmt.Println(faker.NanoSecond()) 58 | // Output: 299642157 59 | } 60 | 61 | func ExampleSecond() { 62 | faker.SetSeed(46) 63 | fmt.Println(faker.Second()) 64 | // Output: 51 65 | } 66 | 67 | func ExampleMinute() { 68 | faker.SetSeed(47) 69 | fmt.Println(faker.Minute()) 70 | // Output: 40 71 | } 72 | 73 | func ExampleHour() { 74 | faker.SetSeed(48) 75 | fmt.Println(faker.Hour()) 76 | // Output: 9 77 | } 78 | 79 | func ExampleDay() { 80 | faker.SetSeed(49) 81 | fmt.Println(faker.Day()) 82 | // Output: 5 83 | } 84 | 85 | func ExampleWeekDay() { 86 | faker.SetSeed(50) 87 | fmt.Println(faker.WeekDay()) 88 | // Output: Saturday 89 | } 90 | 91 | func ExampleMonth() { 92 | faker.SetSeed(51) 93 | fmt.Println(faker.Month()) 94 | // Output: July 95 | } 96 | 97 | func ExampleYear() { 98 | faker.SetSeed(52) 99 | fmt.Println(faker.Year()) 100 | // Output: 2032 101 | } 102 | 103 | func ExampleTimeZone() { 104 | faker.SetSeed(53) 105 | fmt.Println(faker.TimeZone()) 106 | // Output: Venezuela Standard Time 107 | } 108 | 109 | func ExampleTimeZoneAbbr() { 110 | faker.SetSeed(54) 111 | fmt.Println(faker.TimeZoneAbbr()) 112 | // Output: MEDT 113 | } 114 | 115 | func ExampleTimeZoneFull() { 116 | faker.SetSeed(55) 117 | fmt.Println(faker.TimeZoneFull()) 118 | // Output: (UTC-03:00) Cayenne, Fortaleza 119 | } 120 | 121 | func ExampleTimeZoneOffset() { 122 | faker.SetSeed(56) 123 | fmt.Println(faker.TimeZoneOffset()) 124 | // Output: -1 125 | } 126 | 127 | func ExampleTimeZoneRegion() { 128 | faker.SetSeed(57) 129 | fmt.Println(faker.TimeZoneRegion()) 130 | // Output: Africa/Accra 131 | } 132 | 133 | func TestTimeBuild(t *testing.T) { 134 | faker.SetSeed(301) 135 | s := &struct { 136 | Field1 time.Duration `faker:"DurationInRange(58m,1h)"` 137 | Field2 time.Duration `faker:"duration"` 138 | Field3 time.Duration 139 | Field4 time.Time `faker:"time"` 140 | Field5 time.Time 141 | Field6 int `faker:"NanoSecond"` 142 | Field7 int `faker:"Second"` 143 | Field8 int `faker:"Minute"` 144 | Field9 int `faker:"Hour"` 145 | Field10 int `faker:"Day"` 146 | Field11 string `faker:"WeekDay"` 147 | Field12 string `faker:"Month"` 148 | Field13 int `faker:"Year"` 149 | Field14 string `faker:"TimeZone"` 150 | Field15 string `faker:"TimeZoneAbbr"` 151 | Field16 string `faker:"TimeZoneFull"` 152 | Field17 float32 `faker:"TimeZoneOffset"` 153 | Field18 string `faker:"TimeZoneRegion"` 154 | }{} 155 | err := faker.Build(&s) 156 | assert.Nil(t, err) 157 | t.Log(s) 158 | assert.Equal(t, "59m0.054463842s", s.Field1.String()) 159 | assert.Equal(t, "-1578403h18m50.786383245s", s.Field2.String()) 160 | assert.Equal(t, "-2000121h17m20.98416526s", s.Field3.String()) 161 | assert.NotEmpty(t, s.Field4) 162 | assert.NotEmpty(t, s.Field5) 163 | assert.Equal(t, 377478642, s.Field6) 164 | assert.Equal(t, 23, s.Field7) 165 | assert.Equal(t, 19, s.Field8) 166 | assert.Equal(t, 11, s.Field9) 167 | assert.Equal(t, 19, s.Field10) 168 | assert.Equal(t, "Monday", s.Field11) 169 | assert.Equal(t, "June", s.Field12) 170 | assert.Equal(t, 1919, s.Field13) 171 | assert.Equal(t, "Central Asia Standard Time", s.Field14) 172 | assert.Equal(t, "NAST", s.Field15) 173 | assert.Equal(t, "(UTC+02:00) Tripoli", s.Field16) 174 | assert.Equal(t, float32(-1), s.Field17) 175 | assert.Equal(t, "Etc/GMT+5", s.Field18) 176 | } 177 | -------------------------------------------------------------------------------- /unique.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | const uniqueDefaultMaxRetry = 10000 9 | 10 | var uniqueCacheMutex = &sync.Mutex{} 11 | var uniqueCache = make(map[string]map[interface{}]int) 12 | 13 | // Uniq run max maxRetry times fn function until fn returns a unique value for 14 | // the group of runs group. Returns error if the number of runs reach 15 | // maxRetry. If maxRetry is zero use default value that is 10000. 16 | func Uniq(group string, maxRetry int, fn func() (interface{}, error)) (interface{}, error) { 17 | if maxRetry == 0 { 18 | maxRetry = uniqueDefaultMaxRetry 19 | } 20 | uniqueCacheMutex.Lock() 21 | defer uniqueCacheMutex.Unlock() 22 | if _, found := uniqueCache[group]; !found { 23 | uniqueCache[group] = make(map[interface{}]int) 24 | } 25 | var value interface{} 26 | var err error 27 | for i := 0; i < maxRetry; i++ { 28 | value, err = fn() 29 | if err != nil { 30 | return nil, err 31 | } 32 | if _, found := uniqueCache[group][value]; !found { 33 | uniqueCache[group][value] = 0 34 | return value, nil 35 | } 36 | } 37 | // If the value is a string avoid to return an error, and generate a unique 38 | // value adding an index after the string. 39 | valueAsString, ok := value.(string) 40 | if ok { 41 | uniqValue := fmt.Sprintf("%s %d", valueAsString, uniqueCache[group][value]) 42 | uniqueCache[group][value]++ 43 | return uniqValue, nil 44 | } 45 | return value, fmt.Errorf("failed to generate a unique value for group '%s'", group) 46 | } 47 | 48 | // UniqSlice run max maxRetry times fn function until fn returns a unique 49 | // slice for the group of runs group. Returns error if the number of runs 50 | // reach maxRetry. If maxRetry is zero use default value that is 10000. 51 | func UniqSlice(size int, group string, maxRetry int, fn func() (interface{}, error)) ([]interface{}, error) { 52 | var value interface{} 53 | var err error 54 | slice := Slice(size, func() interface{} { 55 | value, err = Uniq(group, maxRetry, fn) 56 | return value 57 | }) 58 | if err != nil { 59 | return nil, err 60 | } 61 | return slice, nil 62 | } 63 | 64 | // ClearUniqCache delete all results for the group group. 65 | func ClearUniqCache(group string) { 66 | uniqueCacheMutex.Lock() 67 | delete(uniqueCache, group) 68 | uniqueCacheMutex.Unlock() 69 | } 70 | 71 | // ClearAllUniqCache delete all results for all groups of run. 72 | func ClearAllUniqCache() { 73 | uniqueCacheMutex.Lock() 74 | uniqueCache = make(map[string]map[interface{}]int) 75 | uniqueCacheMutex.Unlock() 76 | } 77 | -------------------------------------------------------------------------------- /unique_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "testing" 7 | 8 | "github.com/pioz/faker" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func ExampleUniq() { 13 | faker.SetSeed(403) 14 | generator := func() (interface{}, error) { return faker.IntInRange(0, 1), nil } 15 | value1, _ := faker.Uniq("test", 0, generator) 16 | fmt.Println(value1) 17 | value2, _ := faker.Uniq("test", 0, generator) 18 | fmt.Println(value2) 19 | faker.ClearUniqCache("test") 20 | value3, _ := faker.Uniq("test", 0, generator) 21 | fmt.Println(value3) 22 | // Output: 23 | // 1 24 | // 0 25 | // 0 26 | } 27 | 28 | func TestUniq(t *testing.T) { 29 | faker.SetSeed(400) 30 | values := make([]int, 0) 31 | for i := 0; i < 11; i++ { 32 | value, err := faker.Uniq("test", 0, func() (interface{}, error) { return faker.IntInRange(0, 10), nil }) 33 | assert.Nil(t, err) 34 | values = append(values, value.(int)) 35 | } 36 | assert.Equal(t, 11, len(values)) 37 | 38 | faker.ClearUniqCache("notexistingkey") 39 | _, err := faker.Uniq("test", 0, func() (interface{}, error) { return faker.IntInRange(0, 10), nil }) 40 | assert.NotNil(t, err) 41 | assert.Equal(t, "failed to generate a unique value for group 'test'", err.Error()) 42 | 43 | faker.ClearUniqCache("test") 44 | _, err = faker.Uniq("test", 0, func() (interface{}, error) { return faker.IntInRange(0, 0), nil }) 45 | assert.Nil(t, err) 46 | 47 | _, err = faker.Uniq("test", 0, func() (interface{}, error) { return faker.IntInRange(0, 0), nil }) 48 | assert.NotNil(t, err) 49 | assert.Equal(t, "failed to generate a unique value for group 'test'", err.Error()) 50 | 51 | faker.ClearAllUniqCache() 52 | _, err = faker.Uniq("test", 0, func() (interface{}, error) { return faker.IntInRange(0, 0), nil }) 53 | assert.Nil(t, err) 54 | } 55 | 56 | func TestUniqNoErrorIfValueIsString(t *testing.T) { 57 | faker.SetSeed(405) 58 | valuesRound1 := make([]string, 0) 59 | for i := 0; i < 15; i++ { 60 | value, err := faker.Uniq("test", 0, func() (interface{}, error) { return faker.NamePrefix(), nil }) 61 | assert.Nil(t, err) 62 | valuesRound1 = append(valuesRound1, value.(string)) 63 | } 64 | assert.Equal(t, 15, len(valuesRound1)) 65 | 66 | valuesRound2 := make([]string, 0) 67 | for i := 0; i < 15; i++ { 68 | value, err := faker.Uniq("test", 0, func() (interface{}, error) { return faker.NamePrefix(), nil }) 69 | assert.Nil(t, err) 70 | valuesRound2 = append(valuesRound2, value.(string)) 71 | } 72 | assert.Equal(t, 15, len(valuesRound2)) 73 | 74 | valuesRound3 := make([]string, 0) 75 | for i := 0; i < 15; i++ { 76 | value, err := faker.Uniq("test", 0, func() (interface{}, error) { return faker.NamePrefix(), nil }) 77 | assert.Nil(t, err) 78 | valuesRound3 = append(valuesRound3, value.(string)) 79 | } 80 | assert.Equal(t, 15, len(valuesRound3)) 81 | 82 | checkUniquenes := map[string]struct{}{} 83 | 84 | for _, s := range append(append(valuesRound1, valuesRound2...), valuesRound3...) { 85 | _, found := checkUniquenes[s] 86 | assert.False(t, found) 87 | checkUniquenes[s] = struct{}{} 88 | } 89 | } 90 | 91 | func TestUniqError(t *testing.T) { 92 | _, err := faker.Uniq("test", 0, func() (interface{}, error) { return nil, errors.New("this is an error") }) 93 | assert.NotNil(t, err) 94 | assert.Equal(t, "this is an error", err.Error()) 95 | } 96 | 97 | func TestUniqSlice(t *testing.T) { 98 | faker.SetSeed(401) 99 | randIntSlice, err := faker.UniqSlice(100, "testSlice", 0, func() (interface{}, error) { 100 | return faker.IntInRange(1, 100), nil 101 | }) 102 | t.Log(randIntSlice) 103 | assert.Nil(t, err) 104 | assert.Equal(t, 100, len(randIntSlice)) 105 | for _, randInt := range randIntSlice { 106 | assert.NotEmpty(t, randInt) 107 | } 108 | } 109 | 110 | func TestUniqSliceError(t *testing.T) { 111 | faker.SetSeed(402) 112 | randIntSlice, err := faker.UniqSlice(10, "testSlice", 0, func() (interface{}, error) { 113 | return faker.IntInRange(1, 9), nil 114 | }) 115 | t.Log(randIntSlice) 116 | assert.NotNil(t, err) 117 | assert.Equal(t, "failed to generate a unique value for group 'testSlice'", err.Error()) 118 | } 119 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | package faker 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "time" 7 | ) 8 | 9 | func paramsToMinMaxInt(params ...string) (int, int, error) { 10 | if len(params) != 2 { 11 | return 0, 0, parametersError(nil) 12 | } 13 | var min, max int 14 | var err error 15 | min, err = strconv.Atoi(params[0]) 16 | if err != nil { 17 | return 0, 0, parametersError(err) 18 | } 19 | max, err = strconv.Atoi(params[1]) 20 | if err != nil { 21 | return 0, 0, parametersError(err) 22 | } 23 | return min, max, nil 24 | } 25 | 26 | func paramsToMinMaxFloat64(params ...string) (float64, float64, error) { 27 | if len(params) != 2 { 28 | return 0.0, 0.0, parametersError(nil) 29 | } 30 | var min, max float64 31 | var err error 32 | min, err = strconv.ParseFloat(params[0], 64) 33 | if err != nil { 34 | return 0.0, 0.0, parametersError(err) 35 | } 36 | max, err = strconv.ParseFloat(params[1], 64) 37 | if err != nil { 38 | return 0.0, 0.0, parametersError(err) 39 | } 40 | return min, max, nil 41 | } 42 | 43 | func paramsToMinMaxDuration(params ...string) (time.Duration, time.Duration, error) { 44 | if len(params) != 2 { 45 | return 0, 0, parametersError(nil) 46 | } 47 | var min, max time.Duration 48 | var err error 49 | min, err = time.ParseDuration(params[0]) 50 | if err != nil { 51 | return 0, 0, parametersError(err) 52 | } 53 | max, err = time.ParseDuration(params[1]) 54 | if err != nil { 55 | return 0, 0, parametersError(err) 56 | } 57 | return min, max, nil 58 | } 59 | 60 | func paramsToInt(params ...string) (int, error) { 61 | if len(params) != 1 { 62 | return 0, parametersError(nil) 63 | } 64 | number, err := strconv.Atoi(params[0]) 65 | if err != nil { 66 | return 0, parametersError(err) 67 | } 68 | return number, nil 69 | } 70 | 71 | func parametersError(err error) error { 72 | if err == nil { 73 | return fmt.Errorf("invalid parameters") 74 | } 75 | return fmt.Errorf("invalid parameters: %s", err.Error()) 76 | } 77 | -------------------------------------------------------------------------------- /utils_test.go: -------------------------------------------------------------------------------- 1 | package faker_test 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/pioz/faker" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestParamsToMinMaxIntInvaliParams1(t *testing.T) { 12 | faker.SetSeed(700) 13 | s := &struct { 14 | IntField int `faker:"IntInRange"` 15 | }{} 16 | err := faker.Build(&s) 17 | assert.NotNil(t, err) 18 | assert.Equal(t, "invalid parameters", err.Error()) 19 | } 20 | 21 | func TestParamsToMinMaxIntInvaliParams2(t *testing.T) { 22 | faker.SetSeed(700) 23 | s := &struct { 24 | IntField int `faker:"IntInRange(1)"` 25 | }{} 26 | err := faker.Build(&s) 27 | assert.NotNil(t, err) 28 | assert.Equal(t, "invalid parameters", err.Error()) 29 | } 30 | 31 | func TestParamsToMinMaxIntInvaliParams3(t *testing.T) { 32 | faker.SetSeed(700) 33 | s := &struct { 34 | IntField int `faker:"IntInRange(a,b)"` 35 | }{} 36 | err := faker.Build(&s) 37 | assert.NotNil(t, err) 38 | assert.Equal(t, "invalid parameters: strconv.Atoi: parsing \"a\": invalid syntax", err.Error()) 39 | } 40 | 41 | func TestParamsToMinMaxIntInvaliParams4(t *testing.T) { 42 | faker.SetSeed(700) 43 | s := &struct { 44 | IntField int `faker:"IntInRange(1,b)"` 45 | }{} 46 | err := faker.Build(&s) 47 | assert.NotNil(t, err) 48 | assert.Equal(t, "invalid parameters: strconv.Atoi: parsing \"b\": invalid syntax", err.Error()) 49 | } 50 | 51 | func TestParamsToMinMaxFloat64InvaliParams1(t *testing.T) { 52 | s := &struct { 53 | Field float64 `faker:"Float64InRange"` 54 | }{} 55 | err := faker.Build(&s) 56 | assert.NotNil(t, err) 57 | assert.Equal(t, "invalid parameters", err.Error()) 58 | } 59 | 60 | func TestParamsToMinMaxFloat64InvaliParams2(t *testing.T) { 61 | s := &struct { 62 | Field float64 `faker:"Float64InRange(1.0,b)"` 63 | }{} 64 | err := faker.Build(&s) 65 | assert.NotNil(t, err) 66 | assert.Equal(t, "invalid parameters: strconv.ParseFloat: parsing \"b\": invalid syntax", err.Error()) 67 | } 68 | 69 | func TestParamsToMinMaxFloat64InvaliParams3(t *testing.T) { 70 | s := &struct { 71 | Field float64 `faker:"Float64InRange(a,2)"` 72 | }{} 73 | err := faker.Build(&s) 74 | assert.NotNil(t, err) 75 | assert.Equal(t, "invalid parameters: strconv.ParseFloat: parsing \"a\": invalid syntax", err.Error()) 76 | } 77 | 78 | func TestParamsToMinMaxDurationInvalidParams1(t *testing.T) { 79 | s := &struct { 80 | Field time.Duration `faker:"DurationInRange"` 81 | }{} 82 | err := faker.Build(&s) 83 | assert.NotNil(t, err) 84 | assert.Equal(t, "invalid parameters", err.Error()) 85 | } 86 | 87 | func TestParamsToMinMaxDurationInvalidParams2(t *testing.T) { 88 | s := &struct { 89 | Field time.Duration `faker:"DurationInRange(2s,b)"` 90 | }{} 91 | err := faker.Build(&s) 92 | assert.NotNil(t, err) 93 | assert.Equal(t, "invalid parameters: time: invalid duration \"b\"", err.Error()) 94 | } 95 | 96 | func TestParamsToMinMaxDurationInvalidParams3(t *testing.T) { 97 | s := &struct { 98 | Field time.Duration `faker:"DurationInRange(a,2ms)"` 99 | }{} 100 | err := faker.Build(&s) 101 | assert.NotNil(t, err) 102 | assert.Equal(t, "invalid parameters: time: invalid duration \"a\"", err.Error()) 103 | } 104 | 105 | func TestParamsToIntInvalidParams1(t *testing.T) { 106 | s := &struct { 107 | Field string `faker:"StringWithSize"` 108 | }{} 109 | err := faker.Build(&s) 110 | assert.NotNil(t, err) 111 | assert.Equal(t, "invalid parameters", err.Error()) 112 | } 113 | 114 | func TestParamsToIntInvalidParams2(t *testing.T) { 115 | s := &struct { 116 | Field string `faker:"StringWithSize(a)"` 117 | }{} 118 | err := faker.Build(&s) 119 | assert.NotNil(t, err) 120 | assert.Equal(t, "invalid parameters: strconv.Atoi: parsing \"a\": invalid syntax", err.Error()) 121 | } 122 | --------------------------------------------------------------------------------