Skip to content

Commit

Permalink
Add SSN generator
Browse files Browse the repository at this point in the history
  • Loading branch information
neumachen committed Sep 21, 2019
1 parent 9a98f2d commit 519507f
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 0 deletions.
87 changes: 87 additions & 0 deletions random_ssn.go
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
}
12 changes: 12 additions & 0 deletions random_ssn_test.go
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)
}

0 comments on commit 519507f

Please sign in to comment.