From ed04195f7e08f992fe11a2d941a24415276ea0fd Mon Sep 17 00:00:00 2001 From: Peter Jausovec Date: Fri, 1 Mar 2019 10:16:06 -0800 Subject: [PATCH] Add stricter func name validation The valid function names contain a combination of lowercase letters, numbers and separators (., -, _). Name can only start and end with a letter or a number and there can only be one separator in the row (e.g. my---funcname is not valid, however my-func_name is valid). Fixes #503 --- commands/init.go | 15 ++++--- init_test.go | 115 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 112 insertions(+), 18 deletions(-) diff --git a/commands/init.go b/commands/init.go index 98c2f0b2..72ec2c53 100644 --- a/commands/init.go +++ b/commands/init.go @@ -28,6 +28,7 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "strings" "github.com/fnproject/cli/common" @@ -397,14 +398,14 @@ func (a *initFnCmd) bindFn(fn *modelsV2.Fn) { } } -// ValidateFuncName checks if the func name is valid, the name can't contain a colon and -// must be all lowercase +// ValidateFuncName checks if the func name is valid, the name can only contain alphanumerical +// lowercase characters, separated by ., _ or -. func ValidateFuncName(name string) error { - if strings.Contains(name, ":") { - return errors.New("Function name cannot contain a colon") - } - if strings.ToLower(name) != name { - return errors.New("Function name must be lowercase") + // Match multiple groups of lowercase charaters and numbers, followed by 0 or 1 instances + // of the separators; the string also needs to end with a character or a number (not separator) + isValid := regexp.MustCompile(`^([a-z0-9]+[._-]?)*[a-z0-9]$`).MatchString + if !isValid(name) { + return errors.New("Function name cannot contain spaces, start with separators or contain uppercase letters") } return nil } diff --git a/init_test.go b/init_test.go index e02cbbb1..7acb1db7 100644 --- a/init_test.go +++ b/init_test.go @@ -58,17 +58,110 @@ func TestInit(t *testing.T) { } } -func funcNameValidation(name string, t *testing.T) { - err := commands.ValidateFuncName("fooFunc") - if err == nil { - t.Error("Expected validation error for function name") +func TestFuncNameValidation(t *testing.T) { + tc := []struct { + name string + value string + errExpected bool + }{ + { + name: "strings only", + value: "somename", + errExpected: false, + }, + { + name: "numbers only", + value: "12345", + errExpected: false, + }, + { + name: "uppercase letters", + value: "HelloFuncName", + errExpected: true, + }, + { + name: "starts with separator", + value: ".myfunc", + errExpected: true, + }, + { + name: "starts with separator (*)", + value: "*myfunc", + errExpected: true, + }, + { + name: "starts with separator (-)", + value: "-myfunc", + errExpected: true, + }, + { + name: "ends with separator", + value: "myfunc-", + errExpected: true, + }, + { + name: "ends with separator (.)", + value: "myfunc.", + errExpected: true, + }, + { + name: "ends with separator (*)", + value: "myfunc*", + errExpected: true, + }, + { + name: "contains spaces", + value: "my func blah", + errExpected: true, + }, + { + name: "hypen in name", + value: "my-func-blah", + errExpected: false, + }, + { + name: "underscore in name", + value: "my_funcblah", + errExpected: false, + }, + { + name: "dot in name", + value: "my.funcblah", + errExpected: false, + }, + { + name: "multiple separators in row", + value: "my___funcblah", + errExpected: true, + }, + { + name: "multiple different separators in row", + value: "my_.funcblah", + errExpected: true, + }, + { + name: "multiple separators in the name", + value: "my_func-blah.test", + errExpected: false, + }, } -} - -func TestFuncNameWithUpperCase(t *testing.T) { - funcNameValidation("fooMyFunc", t) -} -func TestFuncNameWithColon(t *testing.T) { - funcNameValidation("foo:myfunc", t) + t.Log("Test func name validation") + { + for i, tst := range tc { + t.Logf("\tTest %d: \t%s", i, tst.name) + { + err := commands.ValidateFuncName(tst.value) + if err != nil { + if !tst.errExpected { + t.Fatalf("\tValidateFuncName failed : got unexpected error [%v]\n", err) + } + } else { + if tst.errExpected { + t.Fatalf("\tValidateFuncName failed : error expected for value '%s' but was nil\n", tst.value) + } + } + } + } + } }