From 26b138b9b0583683ac39632150820281a9a4149c Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Thu, 18 Oct 2018 00:39:09 +0100 Subject: [PATCH] Simplify built-in database field types --- glide.lock | 13 ++-- glide.yaml | 2 +- sql/funcs.go | 15 +++- sql/sql.go | 8 +-- sql/sql_test.go | 31 +-------- sql/string.go | 2 + util/chck/chck.go | 43 ------------ util/chck/regex.go | 37 ---------- util/conv/conv.go | 95 ------------------------- util/fncs/email.go | 7 -- util/fncs/email_test.go | 10 --- util/fncs/fnc.go | 26 ++++++- util/fncs/is.go | 125 +++++++++++++++++++++++++++++++++ util/fncs/is_test.go | 151 ++++++++++++++++++++++++++++++++++++++++ 14 files changed, 329 insertions(+), 236 deletions(-) delete mode 100644 util/chck/chck.go delete mode 100644 util/chck/regex.go create mode 100644 util/fncs/is.go create mode 100644 util/fncs/is_test.go diff --git a/glide.lock b/glide.lock index 86d96f83..59c21b79 100644 --- a/glide.lock +++ b/glide.lock @@ -1,8 +1,8 @@ -hash: 7227d566f4817cbb8b1eb609aeb5928f1bc420f763fbf387d5effcfa2e8e6509 -updated: 2018-09-11T13:25:49.903968+01:00 +hash: bb2fdd0ae1ce4cc20cd04c5fb3720722f46051ec869b6e61e21d9b8e7f020081 +updated: 2018-10-17T23:52:04.807878+01:00 imports: - name: cloud.google.com/go - version: c728a003b238b26cef9ab6753a5dc424b331c3ad + version: dfffe386c33fb24c34ee501e5723df5b97b98514 subpackages: - compute/metadata - iam @@ -39,7 +39,7 @@ imports: - name: github.com/armon/go-metrics version: 3c58d8115a78a6879e5df75ae900846768d36895 - name: github.com/aws/aws-sdk-go - version: 71a2a92b0063297b055b6f5a014d441c142da2ce + version: 66832f7f150914a46ffbfc03210f3b9cb0e4c005 subpackages: - aws - aws/awserr @@ -58,6 +58,7 @@ imports: - aws/request - aws/session - aws/signer/v4 + - internal/s3err - internal/sdkio - internal/sdkrand - internal/sdkuri @@ -139,6 +140,8 @@ imports: version: 80517062f582ea3340cd4baf70e86d539ae7d84d subpackages: - internal/load +- name: github.com/konsorten/go-windows-terminal-sequences + version: 5c8c8bd35d3832f5d134ae1e1e375b69a4d25242 - name: github.com/kr/text version: e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f - name: github.com/mattn/go-colorable @@ -175,7 +178,7 @@ imports: subpackages: - diffmatchpatch - name: github.com/sirupsen/logrus - version: 3e01752db0189b9157070a0e1668a620f9a85da2 + version: ad15b42461921f1fb3529b058c6786c6a45d5162 - name: github.com/spf13/cobra version: ef82de70bb3f60c65fb8eebacbb2d122ef517385 - name: github.com/spf13/pflag diff --git a/glide.yaml b/glide.yaml index 795c13ed..e2240417 100644 --- a/glide.yaml +++ b/glide.yaml @@ -33,7 +33,7 @@ import: subpackages: - diffmatchpatch - package: github.com/sirupsen/logrus - version: ^1.0.6 + version: ^1.1.1 - package: github.com/spf13/cobra version: ^0.0.3 - package: github.com/ugorji/go diff --git a/sql/funcs.go b/sql/funcs.go index b77beb0c..5caffbf9 100644 --- a/sql/funcs.go +++ b/sql/funcs.go @@ -84,13 +84,11 @@ var funcs = map[string]map[int]interface{}{ "union": {-1: nil}, // Count implementation - "count": {1: nil}, "count.if": {2: nil}, "count.not": {2: nil}, // Purge implementation - "purge": {1: nil}, "purge.if": {2: nil}, "purge.not": {2: nil}, @@ -217,6 +215,19 @@ var funcs = map[string]map[int]interface{}{ "scrypt.compare": {2: 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 "rand": {0: nil}, "guid": {0: nil}, diff --git a/sql/sql.go b/sql/sql.go index 1fc2d637..0a673524 100644 --- a/sql/sql.go +++ b/sql/sql.go @@ -34,11 +34,9 @@ const ( var ( allowedTypes = []string{ "array", "boolean", "circle", - "datetime", "domain", "double", - "email", "latitude", "longitude", - "number", "object", "password", - "phone", "point", "polygon", - "record", "string", "uuid", + "datetime", "number", "object", + "point", "polygon", "record", + "string", "uuid", } allowedAlgorithms = []string{ diff --git a/sql/sql_test.go b/sql/sql_test.go index 4d96af0d..96cf9053 100644 --- a/sql/sql_test.go +++ b/sql/sql_test.go @@ -2709,29 +2709,11 @@ func Test_Parse_Queries_Define(t *testing.T) { }, { 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`, - err: "Found `something` but expected `array, boolean, circle, datetime, domain, double, email, latitude, longitude, number, object, password, phone, 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", - }}}, + err: "Found `something` but expected `array, boolean, circle, datetime, number, object, point, polygon, record, string, uuid`", }, { sql: `DEFINE FIELD temp ON person TYPE array`, @@ -2769,15 +2751,6 @@ func Test_Parse_Queries_Define(t *testing.T) { 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`, res: &Query{Statements: []Statement{&DefineFieldStatement{ diff --git a/sql/string.go b/sql/string.go index 96e6ccc8..521c3d27 100644 --- a/sql/string.go +++ b/sql/string.go @@ -127,6 +127,8 @@ func toQuote(s string) bool { continue case c == '.', c == '*': continue + case c == '_': + continue default: return true } diff --git a/util/chck/chck.go b/util/chck/chck.go deleted file mode 100644 index 685a72de..00000000 --- a/util/chck/chck.go +++ /dev/null @@ -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) -} diff --git a/util/chck/regex.go b/util/chck/regex.go deleted file mode 100644 index 3099e5b6..00000000 --- a/util/chck/regex.go +++ /dev/null @@ -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) -) diff --git a/util/conv/conv.go b/util/conv/conv.go index ac0e0800..b8c6cbb1 100644 --- a/util/conv/conv.go +++ b/util/conv/conv.go @@ -20,7 +20,6 @@ import ( "time" "github.com/abcum/surreal/sql" - "github.com/abcum/surreal/util/chck" ) 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) } - 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 } @@ -117,63 +107,23 @@ func ConvertTo(t, k string, obj interface{}) (val interface{}, err error) { switch t { default: return obj, nil - case "uuid": - return ConvertToUuid(obj) - case "email": - return ConvertToEmail(obj) - case "phone": - return ConvertToPhone(obj) case "array": return ConvertToArray(obj) case "object": return ConvertToObject(obj) - case "domain": - return ConvertToDomain(obj) - case "base64": - return ConvertToBase64(obj) case "string": return ConvertToString(obj) case "number": return ConvertToNumber(obj) - case "double": - return ConvertToDouble(obj) case "boolean": return ConvertToBoolean(obj) case "datetime": return ConvertToDatetime(obj) - case "latitude": - return ConvertToLatitude(obj) - case "longitude": - return ConvertToLongitude(obj) case "record": 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) { if now, ok := obj.([]interface{}); ok { val = now @@ -192,22 +142,6 @@ func ConvertToObject(obj interface{}) (val map[string]interface{}, err error) { 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) { switch now := obj.(type) { 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) { switch now := obj.(type) { case int64: @@ -270,22 +191,6 @@ func ConvertToDatetime(obj interface{}) (val time.Time, err error) { 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) { switch now := obj.(type) { case *sql.Thing: diff --git a/util/fncs/email.go b/util/fncs/email.go index f41feb62..6bcecc6c 100644 --- a/util/fncs/email.go +++ b/util/fncs/email.go @@ -17,8 +17,6 @@ package fncs import ( "context" "strings" - - "github.com/abcum/surreal/util/chck" ) 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 } - -func emailValid(ctx context.Context, args ...interface{}) (interface{}, error) { - v, _ := ensureString(args[0]) - return chck.IsEmail(v), nil -} diff --git a/util/fncs/email_test.go b/util/fncs/email_test.go index c6f43a50..81b097bb 100644 --- a/util/fncs/email_test.go +++ b/util/fncs/email_test.go @@ -47,14 +47,4 @@ func TestEmail(t *testing.T) { 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) - }) - } diff --git a/util/fncs/fnc.go b/util/fncs/fnc.go index 80c233b1..5c049bd0 100644 --- a/util/fncs/fnc.go +++ b/util/fncs/fnc.go @@ -272,8 +272,6 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er return emailUser(ctx, args...) case "email.domain": return emailDomain(ctx, args...) - case "email.valid": - return emailValid(ctx, args...) // Bcrypt implementation case "bcrypt.compare": @@ -287,6 +285,30 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er case "scrypt.generate": 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 case "rand": return rand(ctx, args...) diff --git a/util/fncs/is.go b/util/fncs/is.go new file mode 100644 index 00000000..fb2ecca3 --- /dev/null +++ b/util/fncs/is.go @@ -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 +} diff --git a/util/fncs/is_test.go b/util/fncs/is_test.go new file mode 100644 index 00000000..0343f845 --- /dev/null +++ b/util/fncs/is_test.go @@ -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) + }) + +}