Simplify built-in database field types

This commit is contained in:
Tobie Morgan Hitchcock 2018-10-18 00:39:09 +01:00
parent e52f0d3243
commit 26b138b9b0
14 changed files with 329 additions and 236 deletions

13
glide.lock generated
View file

@ -1,8 +1,8 @@
hash: 7227d566f4817cbb8b1eb609aeb5928f1bc420f763fbf387d5effcfa2e8e6509 hash: bb2fdd0ae1ce4cc20cd04c5fb3720722f46051ec869b6e61e21d9b8e7f020081
updated: 2018-09-11T13:25:49.903968+01:00 updated: 2018-10-17T23:52:04.807878+01:00
imports: imports:
- name: cloud.google.com/go - name: cloud.google.com/go
version: c728a003b238b26cef9ab6753a5dc424b331c3ad version: dfffe386c33fb24c34ee501e5723df5b97b98514
subpackages: subpackages:
- compute/metadata - compute/metadata
- iam - iam
@ -39,7 +39,7 @@ imports:
- name: github.com/armon/go-metrics - name: github.com/armon/go-metrics
version: 3c58d8115a78a6879e5df75ae900846768d36895 version: 3c58d8115a78a6879e5df75ae900846768d36895
- name: github.com/aws/aws-sdk-go - name: github.com/aws/aws-sdk-go
version: 71a2a92b0063297b055b6f5a014d441c142da2ce version: 66832f7f150914a46ffbfc03210f3b9cb0e4c005
subpackages: subpackages:
- aws - aws
- aws/awserr - aws/awserr
@ -58,6 +58,7 @@ imports:
- aws/request - aws/request
- aws/session - aws/session
- aws/signer/v4 - aws/signer/v4
- internal/s3err
- internal/sdkio - internal/sdkio
- internal/sdkrand - internal/sdkrand
- internal/sdkuri - internal/sdkuri
@ -139,6 +140,8 @@ imports:
version: 80517062f582ea3340cd4baf70e86d539ae7d84d version: 80517062f582ea3340cd4baf70e86d539ae7d84d
subpackages: subpackages:
- internal/load - internal/load
- name: github.com/konsorten/go-windows-terminal-sequences
version: 5c8c8bd35d3832f5d134ae1e1e375b69a4d25242
- name: github.com/kr/text - name: github.com/kr/text
version: e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f version: e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f
- name: github.com/mattn/go-colorable - name: github.com/mattn/go-colorable
@ -175,7 +178,7 @@ imports:
subpackages: subpackages:
- diffmatchpatch - diffmatchpatch
- name: github.com/sirupsen/logrus - name: github.com/sirupsen/logrus
version: 3e01752db0189b9157070a0e1668a620f9a85da2 version: ad15b42461921f1fb3529b058c6786c6a45d5162
- name: github.com/spf13/cobra - name: github.com/spf13/cobra
version: ef82de70bb3f60c65fb8eebacbb2d122ef517385 version: ef82de70bb3f60c65fb8eebacbb2d122ef517385
- name: github.com/spf13/pflag - name: github.com/spf13/pflag

View file

@ -33,7 +33,7 @@ import:
subpackages: subpackages:
- diffmatchpatch - diffmatchpatch
- package: github.com/sirupsen/logrus - package: github.com/sirupsen/logrus
version: ^1.0.6 version: ^1.1.1
- package: github.com/spf13/cobra - package: github.com/spf13/cobra
version: ^0.0.3 version: ^0.0.3
- package: github.com/ugorji/go - package: github.com/ugorji/go

View file

@ -84,13 +84,11 @@ var funcs = map[string]map[int]interface{}{
"union": {-1: nil}, "union": {-1: nil},
// Count implementation // Count implementation
"count": {1: nil}, "count": {1: nil},
"count.if": {2: nil}, "count.if": {2: nil},
"count.not": {2: nil}, "count.not": {2: nil},
// Purge implementation // Purge implementation
"purge": {1: nil}, "purge": {1: nil},
"purge.if": {2: nil}, "purge.if": {2: nil},
"purge.not": {2: nil}, "purge.not": {2: nil},
@ -217,6 +215,19 @@ var funcs = map[string]map[int]interface{}{
"scrypt.compare": {2: nil}, "scrypt.compare": {2: nil},
"scrypt.generate": {1: nil}, "scrypt.generate": {1: nil},
// Check implementation
"is.alpha": {1: nil},
"is.alphanum": {1: nil},
"is.ascii": {1: nil},
"is.domain": {1: nil},
"is.email": {1: nil},
"is.hexadecimal": {1: nil},
"is.latitude": {1: nil},
"is.longitude": {1: nil},
"is.numeric": {1: nil},
"is.semver": {1: nil},
"is.uuid": {1: nil},
// Random implementation // Random implementation
"rand": {0: nil}, "rand": {0: nil},
"guid": {0: nil}, "guid": {0: nil},

View file

@ -34,11 +34,9 @@ const (
var ( var (
allowedTypes = []string{ allowedTypes = []string{
"array", "boolean", "circle", "array", "boolean", "circle",
"datetime", "domain", "double", "datetime", "number", "object",
"email", "latitude", "longitude", "point", "polygon", "record",
"number", "object", "password", "string", "uuid",
"phone", "point", "polygon",
"record", "string", "uuid",
} }
allowedAlgorithms = []string{ allowedAlgorithms = []string{

View file

@ -2709,29 +2709,11 @@ func Test_Parse_Queries_Define(t *testing.T) {
}, },
{ {
sql: `DEFINE FIELD temp ON person TYPE`, sql: `DEFINE FIELD temp ON person TYPE`,
err: "Found `` but expected `array, boolean, circle, datetime, domain, double, email, latitude, longitude, number, object, password, phone, point, polygon, record, string, uuid`", err: "Found `` but expected `array, boolean, circle, datetime, number, object, point, polygon, record, string, uuid`",
}, },
{ {
sql: `DEFINE FIELD temp ON person TYPE something`, sql: `DEFINE FIELD temp ON person TYPE something`,
err: "Found `something` but expected `array, boolean, circle, datetime, domain, double, email, latitude, longitude, number, object, password, phone, point, polygon, record, string, uuid`", err: "Found `something` but expected `array, boolean, circle, datetime, number, object, point, polygon, record, string, uuid`",
},
{
sql: `DEFINE FIELD temp ON person TYPE email`,
res: &Query{Statements: []Statement{&DefineFieldStatement{
KV: "*", NS: "*", DB: "*",
Name: &Ident{"temp"},
What: Tables{&Table{"person"}},
Type: "email",
}}},
},
{
sql: `DEFINE FIELD temp ON person TYPE phone`,
res: &Query{Statements: []Statement{&DefineFieldStatement{
KV: "*", NS: "*", DB: "*",
Name: &Ident{"temp"},
What: Tables{&Table{"person"}},
Type: "phone",
}}},
}, },
{ {
sql: `DEFINE FIELD temp ON person TYPE array`, sql: `DEFINE FIELD temp ON person TYPE array`,
@ -2769,15 +2751,6 @@ func Test_Parse_Queries_Define(t *testing.T) {
Type: "number", Type: "number",
}}}, }}},
}, },
{
sql: `DEFINE FIELD temp ON person TYPE double`,
res: &Query{Statements: []Statement{&DefineFieldStatement{
KV: "*", NS: "*", DB: "*",
Name: &Ident{"temp"},
What: Tables{&Table{"person"}},
Type: "double",
}}},
},
{ {
sql: `DEFINE FIELD temp ON person TYPE record`, sql: `DEFINE FIELD temp ON person TYPE record`,
res: &Query{Statements: []Statement{&DefineFieldStatement{ res: &Query{Statements: []Statement{&DefineFieldStatement{

View file

@ -127,6 +127,8 @@ func toQuote(s string) bool {
continue continue
case c == '.', c == '*': case c == '.', c == '*':
continue continue
case c == '_':
continue
default: default:
return true return true
} }

View file

@ -1,43 +0,0 @@
// Copyright © 2016 Abcum Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package chck
func IsBase64(s string) bool {
return rBase64.MatchString(s)
}
func IsDomain(s string) bool {
return rDomain.MatchString(s)
}
func IsEmail(s string) bool {
return rEmail.MatchString(s)
}
func IsLatitude(s string) bool {
return rLatitude.MatchString(s)
}
func IsLongitude(s string) bool {
return rLongitude.MatchString(s)
}
func IsPhone(s string) bool {
return rPhone.MatchString(s)
}
func IsUUID(s string) bool {
return rUUID.MatchString(s)
}

View file

@ -1,37 +0,0 @@
// Copyright © 2016 Abcum Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package chck
import "regexp"
const (
sBase64 string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$"
sDomain string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`
sEmail string = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
sLatitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
sLongitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
sPhone string = `^[\s\d\+\-\(\)]+$`
sUUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
)
var (
rBase64 = regexp.MustCompile(sBase64)
rDomain = regexp.MustCompile(sDomain)
rEmail = regexp.MustCompile(sEmail)
rLatitude = regexp.MustCompile(sLatitude)
rLongitude = regexp.MustCompile(sLongitude)
rPhone = regexp.MustCompile(sPhone)
rUUID = regexp.MustCompile(sUUID)
)

View file

@ -20,7 +20,6 @@ import (
"time" "time"
"github.com/abcum/surreal/sql" "github.com/abcum/surreal/sql"
"github.com/abcum/surreal/util/chck"
) )
func toNumber(str string) (float64, error) { func toNumber(str string) (float64, error) {
@ -30,15 +29,6 @@ func toNumber(str string) (float64, error) {
err = fmt.Errorf("Expected a number, but found '%v'", str) err = fmt.Errorf("Expected a number, but found '%v'", str)
} }
return float64(int64(val)), err
}
func toDouble(str string) (float64, error) {
val, err := strconv.ParseFloat(str, 64)
if err != nil {
val = 0.0
err = fmt.Errorf("Expected a number, but found '%v'", str)
}
return float64(val), err return float64(val), err
} }
@ -117,63 +107,23 @@ func ConvertTo(t, k string, obj interface{}) (val interface{}, err error) {
switch t { switch t {
default: default:
return obj, nil return obj, nil
case "uuid":
return ConvertToUuid(obj)
case "email":
return ConvertToEmail(obj)
case "phone":
return ConvertToPhone(obj)
case "array": case "array":
return ConvertToArray(obj) return ConvertToArray(obj)
case "object": case "object":
return ConvertToObject(obj) return ConvertToObject(obj)
case "domain":
return ConvertToDomain(obj)
case "base64":
return ConvertToBase64(obj)
case "string": case "string":
return ConvertToString(obj) return ConvertToString(obj)
case "number": case "number":
return ConvertToNumber(obj) return ConvertToNumber(obj)
case "double":
return ConvertToDouble(obj)
case "boolean": case "boolean":
return ConvertToBoolean(obj) return ConvertToBoolean(obj)
case "datetime": case "datetime":
return ConvertToDatetime(obj) return ConvertToDatetime(obj)
case "latitude":
return ConvertToLatitude(obj)
case "longitude":
return ConvertToLongitude(obj)
case "record": case "record":
return ConvertToRecord(obj, k) return ConvertToRecord(obj, k)
} }
} }
func ConvertToUuid(obj interface{}) (val string, err error) {
val = fmt.Sprintf("%v", obj)
if !chck.IsUUID(val) {
err = fmt.Errorf("Expected a UUID, but found '%v'", obj)
}
return
}
func ConvertToEmail(obj interface{}) (val string, err error) {
val = fmt.Sprintf("%v", obj)
if !chck.IsEmail(val) {
err = fmt.Errorf("Expected an email address, but found '%v'", obj)
}
return
}
func ConvertToPhone(obj interface{}) (val string, err error) {
val = fmt.Sprintf("%v", obj)
if !chck.IsPhone(val) {
err = fmt.Errorf("Expected a phone number, but found '%v'", obj)
}
return
}
func ConvertToArray(obj interface{}) (val []interface{}, err error) { func ConvertToArray(obj interface{}) (val []interface{}, err error) {
if now, ok := obj.([]interface{}); ok { if now, ok := obj.([]interface{}); ok {
val = now val = now
@ -192,22 +142,6 @@ func ConvertToObject(obj interface{}) (val map[string]interface{}, err error) {
return return
} }
func ConvertToDomain(obj interface{}) (val string, err error) {
val = fmt.Sprintf("%v", obj)
if !chck.IsDomain(val) {
err = fmt.Errorf("Expected a domain name, but found '%v'", obj)
}
return
}
func ConvertToBase64(obj interface{}) (val string, err error) {
val = fmt.Sprintf("%v", obj)
if !chck.IsBase64(val) {
err = fmt.Errorf("Expected base64 data, but found '%v'", obj)
}
return
}
func ConvertToString(obj interface{}) (val string, err error) { func ConvertToString(obj interface{}) (val string, err error) {
switch now := obj.(type) { switch now := obj.(type) {
case string: case string:
@ -232,19 +166,6 @@ func ConvertToNumber(obj interface{}) (val float64, err error) {
} }
} }
func ConvertToDouble(obj interface{}) (val float64, err error) {
switch now := obj.(type) {
case int64:
return float64(now), err
case float64:
return float64(now), err
case string:
return toDouble(now)
default:
return toDouble(fmt.Sprintf("%v", obj))
}
}
func ConvertToBoolean(obj interface{}) (val bool, err error) { func ConvertToBoolean(obj interface{}) (val bool, err error) {
switch now := obj.(type) { switch now := obj.(type) {
case int64: case int64:
@ -270,22 +191,6 @@ func ConvertToDatetime(obj interface{}) (val time.Time, err error) {
return return
} }
func ConvertToLatitude(obj interface{}) (val float64, err error) {
str := fmt.Sprintf("%v", obj)
if !chck.IsLatitude(str) {
err = fmt.Errorf("Expected a latitude value, but found '%v'", obj)
}
return toNumber(str)
}
func ConvertToLongitude(obj interface{}) (val float64, err error) {
str := fmt.Sprintf("%v", obj)
if !chck.IsLongitude(str) {
err = fmt.Errorf("Expected a longitude value, but found '%v'", obj)
}
return toNumber(str)
}
func ConvertToRecord(obj interface{}, tb string) (val *sql.Thing, err error) { func ConvertToRecord(obj interface{}, tb string) (val *sql.Thing, err error) {
switch now := obj.(type) { switch now := obj.(type) {
case *sql.Thing: case *sql.Thing:

View file

@ -17,8 +17,6 @@ package fncs
import ( import (
"context" "context"
"strings" "strings"
"github.com/abcum/surreal/util/chck"
) )
func emailUser(ctx context.Context, args ...interface{}) (interface{}, error) { func emailUser(ctx context.Context, args ...interface{}) (interface{}, error) {
@ -36,8 +34,3 @@ func emailDomain(ctx context.Context, args ...interface{}) (interface{}, error)
} }
return nil, nil return nil, nil
} }
func emailValid(ctx context.Context, args ...interface{}) (interface{}, error) {
v, _ := ensureString(args[0])
return chck.IsEmail(v), nil
}

View file

@ -47,14 +47,4 @@ func TestEmail(t *testing.T) {
So(res, ShouldEqual, nil) So(res, ShouldEqual, nil)
}) })
Convey("email.valid(a) works properly", t, func() {
res, _ := Run(context.Background(), "email.valid", "tobie@abcum.com")
So(res, ShouldEqual, true)
})
Convey("email.valid(a) errors properly", t, func() {
res, _ := Run(context.Background(), "email.valid", "test")
So(res, ShouldEqual, false)
})
} }

View file

@ -272,8 +272,6 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er
return emailUser(ctx, args...) return emailUser(ctx, args...)
case "email.domain": case "email.domain":
return emailDomain(ctx, args...) return emailDomain(ctx, args...)
case "email.valid":
return emailValid(ctx, args...)
// Bcrypt implementation // Bcrypt implementation
case "bcrypt.compare": case "bcrypt.compare":
@ -287,6 +285,30 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er
case "scrypt.generate": case "scrypt.generate":
return scryptGenerate(ctx, args...) return scryptGenerate(ctx, args...)
// Check implementation
case "is.alpha":
return isAlpha(ctx, args...)
case "is.alphanum":
return isAlphanum(ctx, args...)
case "is.ascii":
return isAscii(ctx, args...)
case "is.domain":
return isDomain(ctx, args...)
case "is.email":
return isEmail(ctx, args...)
case "is.hexadecimal":
return isHexadecimal(ctx, args...)
case "is.latitude":
return isLatitude(ctx, args...)
case "is.longitude":
return isLongitude(ctx, args...)
case "is.numeric":
return isNumeric(ctx, args...)
case "is.semver":
return isSemver(ctx, args...)
case "is.uuid":
return isUuid(ctx, args...)
// Rand implementation // Rand implementation
case "rand": case "rand":
return rand(ctx, args...) return rand(ctx, args...)

125
util/fncs/is.go Normal file
View file

@ -0,0 +1,125 @@
// Copyright © 2016 Abcum Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package fncs
import (
"context"
"net/mail"
"regexp"
)
const (
sAlpha string = "^[a-zA-Z]+$"
sAlphanum string = "^[a-zA-Z0-9]+$"
sAscii string = "^[\x00-\x7F]+$"
sDomain string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`
sHexadecimal string = "^[0-9a-fA-F]+$"
sLatitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
sLongitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
sNumeric string = "^[0-9]+$"
sSemver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$"
sUUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
)
var (
rAlpha = regexp.MustCompile(sAlpha)
rAlphanum = regexp.MustCompile(sAlphanum)
rAscii = regexp.MustCompile(sAscii)
rDomain = regexp.MustCompile(sDomain)
rHexadecimal = regexp.MustCompile(sHexadecimal)
rLatitude = regexp.MustCompile(sLatitude)
rLongitude = regexp.MustCompile(sLongitude)
rNumeric = regexp.MustCompile(sNumeric)
rSemver = regexp.MustCompile(sSemver)
rUUID = regexp.MustCompile(sUUID)
)
func isAlpha(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); ok {
return rAlpha.MatchString(val), nil
}
return false, nil
}
func isAlphanum(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); ok {
return rAlphanum.MatchString(val), nil
}
return false, nil
}
func isAscii(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); ok {
return rAscii.MatchString(val), nil
}
return false, nil
}
func isDomain(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); ok {
return rDomain.MatchString(val), nil
}
return false, nil
}
func isEmail(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); len(val) > 0 && ok {
pse, err := mail.ParseAddress(val)
return err == nil && val == pse.Address, nil
}
return false, nil
}
func isHexadecimal(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); ok {
return rHexadecimal.MatchString(val), nil
}
return false, nil
}
func isLatitude(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); ok {
return rLatitude.MatchString(val), nil
}
return false, nil
}
func isLongitude(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); ok {
return rLongitude.MatchString(val), nil
}
return false, nil
}
func isNumeric(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); ok {
return rNumeric.MatchString(val), nil
}
return false, nil
}
func isSemver(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); ok {
return rSemver.MatchString(val), nil
}
return false, nil
}
func isUuid(ctx context.Context, args ...interface{}) (interface{}, error) {
if val, ok := ensureString(args[0]); ok {
return rUUID.MatchString(val), nil
}
return false, nil
}

151
util/fncs/is_test.go Normal file
View file

@ -0,0 +1,151 @@
// Copyright © 2016 Abcum Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package fncs
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestIs(t *testing.T) {
var res interface{}
Convey("is.alpha(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.alpha", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.alpha", "test-©")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.alpha", "aBcDe")
So(res, ShouldEqual, true)
})
Convey("is.alphanum(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.alphanum", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.alphanum", "test-©")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.alphanum", "aB3De")
So(res, ShouldEqual, true)
})
Convey("is.ascii(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.ascii", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.ascii", "testing®")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.ascii", "aB3De")
So(res, ShouldEqual, true)
})
Convey("is.domain(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.domain", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.domain", "test-©")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.domain", "abcum.com")
So(res, ShouldEqual, true)
})
Convey("is.email(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.email", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.email", "test-©")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.email", "info@abcum.com")
So(res, ShouldEqual, true)
})
Convey("is.hexadecimal(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.hexadecimal", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.hexadecimal", "test-©")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.hexadecimal", "00bfff")
So(res, ShouldEqual, true)
})
Convey("is.latitude(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.latitude", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.latitude", "test-©")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.latitude", 0)
So(res, ShouldEqual, true)
res, _ = Run(context.Background(), "is.latitude", -90)
So(res, ShouldEqual, true)
res, _ = Run(context.Background(), "is.latitude", +90)
So(res, ShouldEqual, true)
res, _ = Run(context.Background(), "is.latitude", "-90")
So(res, ShouldEqual, true)
res, _ = Run(context.Background(), "is.latitude", "+90")
So(res, ShouldEqual, true)
res, _ = Run(context.Background(), "is.latitude", -95)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.latitude", +95)
So(res, ShouldEqual, false)
})
Convey("is.longitude(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.longitude", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.longitude", "test-©")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.longitude", 0)
So(res, ShouldEqual, true)
res, _ = Run(context.Background(), "is.longitude", -180)
So(res, ShouldEqual, true)
res, _ = Run(context.Background(), "is.longitude", +180)
So(res, ShouldEqual, true)
res, _ = Run(context.Background(), "is.longitude", "-180")
So(res, ShouldEqual, true)
res, _ = Run(context.Background(), "is.longitude", "+180")
So(res, ShouldEqual, true)
res, _ = Run(context.Background(), "is.longitude", -185)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.longitude", +185)
So(res, ShouldEqual, false)
})
Convey("is.numeric(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.numeric", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.numeric", "test-©")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.numeric", "123456")
So(res, ShouldEqual, true)
})
Convey("is.semver(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.semver", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.semver", "test-©")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.semver", "1.0.32")
So(res, ShouldEqual, true)
})
Convey("is.uuid(a) works properly", t, func() {
res, _ = Run(context.Background(), "is.uuid", nil)
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.uuid", "test-©")
So(res, ShouldEqual, false)
res, _ = Run(context.Background(), "is.uuid", "8ddb11e8-755f-47cf-a84f-8033d1cfa1b9")
So(res, ShouldEqual, true)
})
}