From c827eb7948dc8ce1ed66424449b6aa3bf6a6cf70 Mon Sep 17 00:00:00 2001 From: Michael Engelhardt Date: Sat, 21 Nov 2020 13:11:37 +0100 Subject: [PATCH] some refactorings and add test cases --- config/web.go | 26 +++++++---- config/web_test.go | 111 +++++++++++++++++++-------------------------- 2 files changed, 64 insertions(+), 73 deletions(-) diff --git a/config/web.go b/config/web.go index 97c1e074..59a9926d 100644 --- a/config/web.go +++ b/config/web.go @@ -21,7 +21,7 @@ type webConfig struct { } // validateAndSetDefaults checks and sets missing values based on the defaults -// in given in DefaultAddress and DefaultPort if necessary +// in given in DefaultWebContext, DefaultAddress and DefaultPort if necessary func (web *webConfig) validateAndSetDefaults() { if len(web.Address) == 0 { web.Address = DefaultAddress @@ -31,17 +31,27 @@ func (web *webConfig) validateAndSetDefaults() { } else if web.Port < 0 || web.Port > math.MaxUint16 { panic(fmt.Sprintf("port has an invalid: value should be between %d and %d", 0, math.MaxUint16)) } - if len(web.ContextRoot) == 0 { - web.ContextRoot = DefaultContextRoot + + web.ContextRoot = validateAndBuild(web.ContextRoot) +} + +// validateAndBuild validates and builds a checked +// path for the context root +func validateAndBuild(contextRoot string) string { + trimedContextRoot := strings.Trim(contextRoot, "/") + + if len(trimedContextRoot) == 0 { + return DefaultContextRoot } else { - url, err := url.Parse(web.ContextRoot) + url, err := url.Parse(trimedContextRoot) if err != nil { - panic(fmt.Sprintf("Invalid context root %s - error: %s.", web.ContextRoot, err)) + panic(fmt.Sprintf("Invalid context root %s - error: %s.", contextRoot, err)) } - if url.Path != web.ContextRoot { - panic(fmt.Sprintf("Invalid context root %s, simple path required.", web.ContextRoot)) + if url.Path != trimedContextRoot { + panic(fmt.Sprintf("Invalid context root %s, simple path required.", contextRoot)) } - web.ContextRoot = strings.TrimRight(url.Path, "/") + "/" + + return "/" + strings.Trim(url.Path, "/") + "/" } } diff --git a/config/web_test.go b/config/web_test.go index 36333c9d..7d0df8b8 100644 --- a/config/web_test.go +++ b/config/web_test.go @@ -15,62 +15,67 @@ func TestWebConfig_SocketAddress(t *testing.T) { } } -func TestWebConfig_ContextRootEmpty(t *testing.T) { - const expected = "/" +// validContextRootTest specifies all test case which should end up in +// a valid context root used to bind the web interface to +var validContextRootTests = []struct { + name string + path string + expectedPath string +}{ + {"Empty", "", "/"}, + {"/", "/", "/"}, + {"///", "///", "/"}, + {"Single character 'a'", "a", "/a/"}, + {"Slash at the beginning", "/status", "/status/"}, + {"Slashes at start and end", "/status/", "/status/"}, + {"Multiple slashes at start", "//status", "/status/"}, + {"Mutliple slashes at start and end", "///status////", "/status/"}, + {"Contains '@' in path'", "me@/status/gatus", "/me@/status/gatus/"}, +} - web := &webConfig{ - ContextRoot: "", - } - - web.validateAndSetDefaults() - - if web.ContextRoot != expected { - t.Errorf("expected %s, got %s", expected, web.ContextRoot) +func TestWebConfig_ValidContextRoots(t *testing.T) { + for idx, test := range validContextRootTests { + t.Run(fmt.Sprintf("%d: %s", idx, test.name), func(t *testing.T) { + expectValidResultForContextRoot(t, test.path, test.expectedPath) + }) } } -func TestWebConfig_ContextRoot(t *testing.T) { - const expected = "/status/" +// invalidContextRootTests contains all tests for context root which are +// expected to +var invalidContextRootTests = []struct { + name string + path string +}{ + {"Only a fragment identifier", "#"}, + {"Invalid character in path", "/invalid" + string([]byte{0x7F}) + "/"}, + {"Starts with protocol", "http://status/gatus"}, + {"Path with fragment", "/status/gatus#here"}, + {"starts with '://'", "://status"}, + {"contains query parameter", "/status/h?ello=world"}, + {"contains '?'", "/status?/"}, +} - web := &webConfig{ - ContextRoot: "/status/", - } - - web.validateAndSetDefaults() - - if web.ContextRoot != expected { - t.Errorf("expected %s, got %s", expected, web.ContextRoot) +func TestWebConfig_InvalidContextRoots(t *testing.T) { + for idx, test := range invalidContextRootTests { + t.Run(fmt.Sprintf("%d: %s", idx, test.name), func(t *testing.T) { + expectInvalidResultForContextRoot(t, test.path) + }) } } -func TestWebConfig_ContextRootInvalid(t *testing.T) { +func expectInvalidResultForContextRoot(t *testing.T, path string) { defer func() { recover() }() - web := &webConfig{ - ContextRoot: "/s?=ta t u&s/", - } - + web := &webConfig{ContextRoot: path} web.validateAndSetDefaults() - t.Fatal("Should've panicked because the configuration specifies an invalid context root") + t.Fatal(fmt.Sprintf("Should've panicked because the configuration specifies an invalid context root: %s", path)) } -func TestWebConfig_ContextRootNonParseable(t *testing.T) { - defer func() { recover() }() - +func expectValidResultForContextRoot(t *testing.T, path string, expected string) { web := &webConfig{ - ContextRoot: "/invalid" + string([]byte{0x7F}) + "/", - } - - web.validateAndSetDefaults() - - t.Fatal(fmt.Sprintf("Should've panicked because the configuration specifies an invalid context root %s", web.ContextRoot)) -} - -func TestWebConfig_ContextRootMultiPath(t *testing.T) { - const expected = "/app/status/" - web := &webConfig{ - ContextRoot: "/app/status", + ContextRoot: path, } web.validateAndSetDefaults() @@ -79,27 +84,3 @@ func TestWebConfig_ContextRootMultiPath(t *testing.T) { t.Errorf("expected %s, got %s", expected, web.ContextRoot) } } - -func TestWebConfig_ContextRootAppendWithEmptyContextRoot(t *testing.T) { - const expected = "/bla/" - web := &webConfig{} - - web.validateAndSetDefaults() - - if web.AppendToContexRoot("/bla/") != expected { - t.Errorf("expected %s, got %s", expected, web.AppendToContexRoot("/bla/")) - } -} - -func TestWebConfig_ContextRootAppendWithContext(t *testing.T) { - const expected = "/app/status/bla/" - web := &webConfig{ - ContextRoot: "/app/status", - } - - web.validateAndSetDefaults() - - if web.AppendToContexRoot("/bla/") != expected { - t.Errorf("expected %s, got %s", expected, web.AppendToContexRoot("/bla/")) - } -}