🇧🇷 CPF validation in Go

Merge pull request #2 from sysdharma/master

authored by

Eduardo Cuducos and committed by
GitHub
41a024a5 9f7ad50d

+42 -70
+32 -43
cpf.go
··· 14 14 return string(c) 15 15 } 16 16 17 - //Validate check if Cpf is in a valid format 18 - func (c Cpf) Validate() bool { 19 - toInt := func(chars []string) []int { 20 - digits := make([]int, len(chars)) 21 - for index, value := range chars { 22 - converted, _ := strconv.ParseInt(value, 10, 32) 23 - digits[index] = int(converted) 24 - } 25 - return digits 17 + func checksum(ds []int64) int64 { 18 + var s int64 19 + for i, n := range ds { 20 + s += n * int64(len(ds) + 1 - i) 21 + } 22 + r := 11 - (s % 11) 23 + if r == 10 { 24 + return 0 26 25 } 26 + return r 27 + } 27 28 28 - repeatedNumbers := func(digits []int) bool { 29 - hashTable := map[int]bool{} 30 - for _, digit := range digits { 31 - hashTable[digit] = true 32 - } 33 - return len(hashTable) == 1 29 + //Validate check if Cpf is in a valid format 30 + func (c Cpf) Validate() bool { 31 + u := c.Unmask() 34 32 33 + if len(u) != 11 { 34 + return false 35 35 } 36 36 37 - check := func(digits []int, expected int) bool { 38 - sum := 0 39 - for index, number := range digits { 40 - weight := (len(digits) + 1) - index 41 - sum += number * weight 37 + var ( 38 + ds = make([]int64, 11) 39 + m = map[int64]bool{} 40 + ) 41 + for i, v := range strings.Split(u, "") { 42 + c, err := strconv.ParseInt(v, 10, 32) 43 + if err != nil { 44 + return false 42 45 } 43 - result := 11 - (sum % 11) 44 - if result == 10 { 45 - return 0 == expected 46 - } 47 - return result == expected 46 + ds[i] = c 47 + m[c] = true 48 48 } 49 - 50 - unmasked := c.Unmask() 51 - if len(unmasked) != 11 { 49 + 50 + if len(m) == 1 { 52 51 return false 53 52 } 54 53 55 - digits := toInt(strings.Split(unmasked, "")) 56 - if repeatedNumbers(digits) { 57 - return false 58 - } 59 - 60 - check1 := check(digits[:9], digits[9]) 61 - check2 := check(digits[:10], digits[10]) 62 - return check1 && check2 63 - 54 + return checksum(ds[:9]) == ds[9] && checksum(ds[:10]) == ds[10] 64 55 } 65 56 66 57 //Mask return the formated value 67 58 func (c Cpf) Mask() string { 68 - unmasked := c.Unmask() 69 - if len(unmasked) < 11 { 59 + u := c.Unmask() 60 + if len(u) < 11 { 70 61 return string(c) 71 62 } 72 - return fmt.Sprintf("%s.%s.%s-%s", unmasked[:3], unmasked[3:6], unmasked[6:9], unmasked[9:]) 63 + return fmt.Sprintf("%s.%s.%s-%s", u[:3], u[3:6], u[6:9], u[9:]) 73 64 } 74 65 75 66 //Unmask remove format and return the raw data 76 67 func (c Cpf) Unmask() string { 77 - pattern := regexp.MustCompile(`\D`) 78 - unmasked := pattern.ReplaceAllString(c.String(), "") 79 - return unmasked 68 + return regexp.MustCompile(`\D`).ReplaceAllString(string(c), "") 80 69 }
+10 -27
cpf_test.go
··· 3 3 import "testing" 4 4 5 5 func TestMask(t *testing.T) { 6 - cpf := Cpf("11111111111") 7 - expect := "111.111.111-11" 8 - got := cpf.Mask() 9 - 10 - if expect != got { 11 - t.Errorf("Expected %s to be %s but got %s", cpf, expect, got) 6 + if got := Cpf("11111111111").Mask(); "111.111.111-11" != got { 7 + t.Errorf("Cpf(\"11111111111\").Mask() = %v; want 111.111.111-11", got) 12 8 } 13 9 } 14 10 15 11 func TestUnmask(t *testing.T) { 16 - cpf := Cpf("111.111.111-11") 17 - expect := "11111111111" 18 - got := cpf.Unmask() 19 - 20 - if expect != got { 21 - t.Errorf("Expected %s to be %s but got %s", cpf, expect, got) 12 + if got := Cpf("111.111.111-11").Unmask(); "11111111111" != got { 13 + t.Errorf("Cpf(\"111.111.111-11\").Unmask() = %v; want 11111111111", got) 22 14 } 23 15 24 16 } 25 17 26 18 func TestValidate(t *testing.T) { 27 - 28 - testTable := []struct { 19 + for _, tc := range []struct { 29 20 cpf Cpf 30 21 expected bool 31 22 }{ ··· 34 25 {Cpf("123"), false}, 35 26 {Cpf("111.111.111-11"), false}, 36 27 {Cpf("123.456.769/01"), false}, 37 - } 38 - 39 - for _, testCase := range testTable { 40 - assertValidate(t, testCase.cpf, testCase.expected) 28 + {Cpf("ABC.DEF.GHI-JK"), false}, 29 + } { 30 + if got := tc.cpf.Validate(); tc.expected != got { 31 + t.Errorf("Cpf(%v).Validate() = %v; want %v", tc.cpf, got, tc.expected) 32 + } 41 33 } 42 34 43 35 } 44 - 45 - func assertValidate(t *testing.T, cpf Cpf, expected bool) { 46 - t.Helper() 47 - got := cpf.Validate() 48 - 49 - if got != expected { 50 - t.Errorf("expected %q to be %t but got %t", cpf, expected, got) 51 - } 52 - }