Skip to content

Commit

Permalink
adding new file
Browse files Browse the repository at this point in the history
  • Loading branch information
fn-code committed May 8, 2019
1 parent f1f987d commit c5691c5
Show file tree
Hide file tree
Showing 14 changed files with 687 additions and 0 deletions.
23 changes: 23 additions & 0 deletions custom.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package govals

import (
"fmt"
"reflect"
)

// CustomValidate is validate data value
// with custom rule, your can write your regexp custom rule
func CustomValidate(val string, rule string) (bool, error) {
return checkRule(val, rule)
}

func (d *customValRule) validate() (bool, error) {
if d.count > 0 {
if d.tagType.Type.Kind() != reflect.String {
return false, fmt.Errorf("invalid value type, value type must be string")
}
val := d.val.String()
return checkRule(val, d.rule)
}
return false, nil
}
34 changes: 34 additions & 0 deletions custom_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package govals

import "testing"

func TestCustomValidate(t *testing.T) {
tc := []struct {
name string
val string
rule string
err error
}{
{name: "valid test", val: "ludinnento", rule: "^[a-zA-Z]*$"},
{name: "empty value", val: "", rule: "^[a-zA-Z]*$", err: errEmptyValue},
{name: "invalid value", val: "ludin1233", rule: "^[a-zA-Z]*$", err: errInvalidFormat},
{name: "invalid rule", val: "ludin", rule: "^[a-zA-Z", err: errInvalidRuleFormat},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
ok, err := CustomValidate(tt.val, tt.rule)
if tt.err != nil {
if tt.err != err {
t.Errorf("error value expects %v got %v\n", tt.err, err)
}
return
}

if !ok {
t.Errorf("%s invalid result", tt.val)
}
})
}

}
93 changes: 93 additions & 0 deletions default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package govals

import (
"regexp"
)

// Email validate string if is valid email format,
// this function return bool and error
// if value does not valid
func Email(s string) (bool, error) {
return checkRule(s, emailRules)
}

// Numeric validate string contains digits only [0-9]
// this function return bool and error
// if value does not valid
func Numeric(s string) (bool, error) {
return checkRule(s, numericRule)
}

// Alpha validate string contains letters only [a-zA-Z]
// this function return bool and error
// if value does not valid
func Alpha(s string) (bool, error) {
return checkRule(s, alphaRule)
}

// AlphaNumeric validate string contains letters
// and number only [a-zA-Z0-9]
// this function return bool and error
// if value does not valid
func AlphaNumeric(s string) (bool, error) {
return checkRule(s, alphaNumericRule)
}

// Date checking string format as date
// like mm-dd-yyyy or mm/dd/yyyy
// this function return bool and error
// if value does not valid
func Date(s string) (bool, error) {
return checkRule(s, dateRule)
}

// Times checking string format time
// like 12:00:01 or 12:00
func Times(s string) (bool, error) {
return checkRule(s, timeRule)
}

// PhoneNumber checking string match phone number
// like +62828882888 or 082323333333
// this function return bool and error
// if value does not valid
func PhoneNumber(s string) (bool, error) {
return checkRule(s, phoneNumberRule)
}

func (d *defaultValsRule) validate() (bool, error) {
val := d.val.String()
switch d.tag {
case "email":
return checkRule(val, emailRules)
case "time":
return checkRule(val, timeRule)
case "date":
return checkRule(val, dateRule)
case "alpha":
return checkRule(val, alphaRule)
case "numeric":
return checkRule(val, numericRule)
case "alphaNumeric":
return checkRule(val, alphaNumericRule)
case "phone":
return checkRule(val, phoneNumberRule)
}
return true, nil

}

func checkRule(s, rule string) (bool, error) {
if len(s) == 0 {
return false, errEmptyValue
}
re, err := regexp.Compile(rule)
if err != nil {
return false, errInvalidRuleFormat
}
ok := re.MatchString(s)
if !ok {
return false, errInvalidFormat
}
return ok, nil
}
147 changes: 147 additions & 0 deletions default_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package govals

import "testing"

type testCase struct {
name string
val string
err error
}

func TestEmail(t *testing.T) {
tc := []testCase{
{name: "valid email", val: "[email protected]"},
{name: "invalid email", val: "ludyyn$$##gmail.com", err: errInvalidFormat},
{name: "empty email", val: "", err: errEmptyValue},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
ok, err := Email(tt.val)
if tt.err != nil {
if tt.err != err && !ok {
t.Errorf("error email expects %v, got %v\n", tt.err, err)
}
}
})
}

}

func TestNumeric(t *testing.T) {
tc := []testCase{
{name: "valid numeric", val: "122323"},
{name: "invalid numeric", val: "23dsdfdfsdf", err: errInvalidFormat},
{name: "empty numeric", val: "", err: errEmptyValue},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
ok, err := Numeric(tt.val)
if tt.err != nil {
if tt.err != err && !ok {
t.Errorf("error numeric expects %v, got %v\n", tt.err, err)
}
}
})
}

}

func TestAlpha(t *testing.T) {
tc := []testCase{
{name: "valid alpha", val: "Ludin Nento"},
{name: "invalid alpha", val: "sdfnj23434", err: errInvalidFormat},
{name: "empty alpha", val: "", err: errEmptyValue},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
ok, err := Alpha(tt.val)
if tt.err != nil {
if tt.err != err && !ok {
t.Errorf("error alpha expects %v, got %v\n", tt.err, err)
}
}
})
}

}
func TestAlphaNumeric(t *testing.T) {
tc := []testCase{
{name: "valid alpha numeric", val: "Ludin Nento2323"},
{name: "invalid alpha numeric", val: "sdfnj23434^^&9", err: errInvalidFormat},
{name: "empty alpha numeric", val: "", err: errEmptyValue},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
ok, err := AlphaNumeric(tt.val)
if tt.err != nil {
if tt.err != err && !ok {
t.Errorf("error alpha numeric expects %v, got %v\n", tt.err, err)
}
}
})
}

}

func TestDate(t *testing.T) {
tc := []testCase{
{name: "valid date", val: "12-12-1996"},
{name: "invalid date", val: "12-", err: errInvalidFormat},
{name: "empty date", val: "", err: errEmptyValue},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
ok, err := Date(tt.val)
if tt.err != nil {
if tt.err != err && !ok {
t.Errorf("error date expects %v, got %v\n", tt.err, err)
}
}
})
}

}

func TestTimes(t *testing.T) {
tc := []testCase{
{name: "valid time", val: "12:12:01"},
{name: "invalid time", val: "12:", err: errInvalidFormat},
{name: "empty time", val: "", err: errEmptyValue},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
ok, err := Times(tt.val)
if tt.err != nil {
if tt.err != err && !ok {
t.Errorf("error time expects %v, got %v\n", tt.err, err)
}
}
})
}

}
func TestPhoneNumber(t *testing.T) {
tc := []testCase{
{name: "valid phone number", val: "+6282290202728"},
{name: "invalid phone number", val: "12--&&809098^^%$:", err: errInvalidFormat},
{name: "empty phone number", val: "", err: errEmptyValue},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
ok, err := PhoneNumber(tt.val)
if tt.err != nil {
if tt.err != err && !ok {
t.Errorf("error phone number expects %v, got %v\n", tt.err, err)
}
}
})
}

}
12 changes: 12 additions & 0 deletions error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package govals

import (
"errors"
)

var (
errFieldNotResgister = errors.New("field is not register")
errEmptyValue = errors.New("value cannot be empty")
errInvalidFormat = errors.New("value format is invalid")
errInvalidRuleFormat = errors.New("Rule format is invalid")
)
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/fn-code/govals

go 1.12
55 changes: 55 additions & 0 deletions len.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package govals

import (
"fmt"
"reflect"
"strconv"
)

// RuneLength is validate text length
func RuneLength(s string, min, max int) (bool, error) {
return minMax(s, min, max)
}

// Length is validate number length
func Length(s int, min, max int) (bool, error) {
num := strconv.Itoa(s)
return minMax(num, min, max)
}

func (d *lengthValsRule) validate() (ok bool, err error) {

switch d.tagType.Type.Kind() {
case reflect.String:
val := d.val.String()
if d.count > 1 {
return minMax(val, d.min, d.max)
}

case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
val := d.val.Int()
if d.count > 1 {
return minMax(strconv.Itoa(int(val)), d.min, d.max)
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
val := d.val.Uint()
return minMax(strconv.Itoa(int(val)), d.min, d.max)
}
return true, nil
}

func minMax(s string, min, max int) (bool, error) {
if len(s) == 0 {
return false, errEmptyValue
}
if min > max {
return false, fmt.Errorf("invalid rule, min must less than max")
}
if len(s) < min {
return false, fmt.Errorf("value must greater than %d", min)
}
if len(s) > max {
return false, fmt.Errorf("value must less than %d", max)
}
return true, nil
}
Loading

0 comments on commit c5691c5

Please sign in to comment.