-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
99 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package randata | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"math/rand" | ||
"strconv" | ||
"sync" | ||
"time" | ||
) | ||
|
||
// RandomSSN will try to generate a valid random SSN by generating up until | ||
// the given retries or until it generates a valid SSN whichever comes first. | ||
// The retires default to 100 if no value is given. | ||
// If formatted it will return a string with the format XXX-XX-XXXX opposed to | ||
// non formatted XXXXXXXXX. | ||
func RandomSSN(formatted bool, routines int) string { | ||
validSSN := make(chan string) | ||
|
||
if routines == 0 { | ||
routines = 100 | ||
} | ||
|
||
min := 100000000 | ||
max := 999999999 | ||
|
||
ctx := context.Background() | ||
ctx, cancel := context.WithCancel(ctx) | ||
wg := sync.WaitGroup{} | ||
for i := 0; i < routines; i++ { | ||
wg.Add(1) | ||
go func() { | ||
defer wg.Done() | ||
select { | ||
case <-ctx.Done(): | ||
return | ||
default: | ||
r := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) | ||
rand.Seed(time.Now().UTC().UnixNano()) | ||
ssn := r.Intn(max-min+1) + min | ||
ssnStr := strconv.Itoa(ssn) | ||
valid, _ := validateSSN(ssnStr) | ||
if valid { | ||
cancel() | ||
validSSN <- ssnStr | ||
|
||
} | ||
} | ||
}() | ||
} | ||
|
||
go func() { | ||
wg.Wait() | ||
close(validSSN) | ||
}() | ||
|
||
var result string | ||
for ssn := range validSSN { | ||
result = ssn | ||
break | ||
} | ||
return result | ||
} | ||
|
||
func validateSSN(ssn string) (bool, error) { | ||
if len(ssn) != 9 { | ||
return false, errors.New("SSN length must be equal to 9") | ||
} | ||
|
||
if string(ssn[0]) == "0" { | ||
return false, errors.New("can not start with zero") | ||
} | ||
|
||
if ssn[0:2] == "000" || ssn[3:4] == "00" || ssn[5:8] == "0000" { | ||
return false, errors.New("no group can all be zeroes") | ||
} | ||
|
||
ssnInt, err := strconv.Atoi(ssn) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
if ssnInt < 987654329 && ssnInt > 987654320 { | ||
return false, errors.New("SSN can not be in the range of 987654320-987654329") | ||
} | ||
return true, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package randata | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestRandomSSN(t *testing.T) { | ||
ssn := RandomSSN(false, 100) | ||
require.NotEmpty(t, ssn) | ||
} |