From 94fb167e5b163c82281468d7f16821730c7f9f42 Mon Sep 17 00:00:00 2001 From: Felipe Zipitria Date: Thu, 9 Nov 2023 12:10:13 +0100 Subject: [PATCH 1/6] feat: move test type to its own package Signed-off-by: Felipe Zipitria --- go.mod | 3 ++- go.sum | 11 +++----- runner/run.go | 17 ++++++------ test/types.go | 75 +++++++-------------------------------------------- 4 files changed, 24 insertions(+), 82 deletions(-) diff --git a/go.mod b/go.mod index 6979645..d5b72e2 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,10 @@ module github.com/coreruleset/go-ftw -go 1.18 +go 1.21 require ( github.com/Masterminds/sprig v2.22.0+incompatible + github.com/coreruleset/ftw-tests-schema v1.0.0 github.com/go-logr/zerologr v1.2.3 github.com/goccy/go-yaml v1.9.2 github.com/google/uuid v1.4.0 diff --git a/go.sum b/go.sum index 029d468..0241efd 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/antchfx/htmlquery v1.3.0/go.mod h1:zKPDVTMhfOmcwxheXUsx4rKJy8KEY/PU6e github.com/antchfx/xpath v1.2.3 h1:CCZWOzv5bAqjVv0offZ2LVgVYFbeldKQVuLNbViZdes= github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreruleset/ftw-tests-schema v1.0.0 h1:qvBx9hXoaqZGEDQ3E2cAIZowtmrV8afBZ5Yv4oFL7S4= +github.com/coreruleset/ftw-tests-schema v1.0.0/go.mod h1:eGixZc1HY61s6ze0f3TExkILnvmXwix4GS10iUXbDmU= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -104,14 +106,13 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tonglil/buflogr v1.0.1 h1:WXFZLKxLfqcVSmckwiMCF8jJwjIgmStJmg63YKRF1p0= +github.com/tonglil/buflogr v1.0.1/go.mod h1:yYWwvSpn/3uAaqjf6mJg/XMiAciaR0QcRJH2gJGDxNE= github.com/yargevad/filepathx v1.0.0 h1:SYcT+N3tYGi+NvazubCNlvgIPbzAk7i7y2dwg3I5FYc= github.com/yargevad/filepathx v1.0.0/go.mod h1:BprfX/gpYNJHJfc35GjRRpVcwWXS89gGulUIU5tK3tA= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -120,8 +121,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -139,8 +138,6 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -151,8 +148,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/runner/run.go b/runner/run.go index d4f6218..047289c 100644 --- a/runner/run.go +++ b/runner/run.go @@ -12,6 +12,7 @@ import ( "github.com/google/uuid" "github.com/rs/zerolog/log" + "github.com/coreruleset/ftw-tests-schema/types" "github.com/coreruleset/go-ftw/check" "github.com/coreruleset/go-ftw/config" "github.com/coreruleset/go-ftw/ftwhttp" @@ -24,7 +25,7 @@ import ( var errBadTestInput = errors.New("ftw/run: bad test input: choose between data, encoded_request, or raw_request") // Run runs your tests with the specified Config. -func Run(cfg *config.FTWConfiguration, tests []test.FTWTest, c RunnerConfig, out *output.Output) (*TestRunContext, error) { +func Run(cfg *config.FTWConfiguration, tests []types.FTWTest, c RunnerConfig, out *output.Output) (*TestRunContext, error) { out.Println("%s", out.Message("** Running go-ftw!")) logLines, err := waflog.NewFTWLogLines(cfg) @@ -72,12 +73,12 @@ func Run(cfg *config.FTWConfiguration, tests []test.FTWTest, c RunnerConfig, out // RunTest runs an individual test. // runContext contains information for the current test run // ftwTest is the test you want to run -func RunTest(runContext *TestRunContext, ftwTest test.FTWTest) error { +func RunTest(runContext *TestRunContext, ftwTest types.FTWTest) error { changed := true for _, testCase := range ftwTest.Tests { // if we received a particular testid, skip until we find it - if needToSkipTest(runContext.Include, runContext.Exclude, testCase.TestTitle, *ftwTest.Meta.Enabled) { + if needToSkipTest(runContext.Include, runContext.Exclude, testCase.TestTitle, ftwTest.Meta.Enabled) { runContext.Stats.addResultToStats(Skipped, testCase.TestTitle, 0) if !*ftwTest.Meta.Enabled && !runContext.ShowOnlyFailed { runContext.Output.Println("\tskipping %s - (enabled: false) in file.", testCase.TestTitle) @@ -113,13 +114,13 @@ func RunTest(runContext *TestRunContext, ftwTest test.FTWTest) error { // ftwCheck is the current check utility // testCase is the test case the stage belongs to // stage is the stage you want to run -func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase test.Test, stage test.Stage) error { +func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase types.Test, stage types.Stage) error { stageStartTime := time.Now() stageID := uuid.NewString() // Apply global overrides initially - testInput := stage.Input + testInput := stage.SD.Input test.ApplyInputOverrides(&runContext.Config.TestOverride.Overrides, &testInput) - expectedOutput := stage.Output + expectedOutput := stage.SD.Output expectErr := false if expectedOutput.ExpectError != nil { expectErr = *expectedOutput.ExpectError @@ -273,7 +274,7 @@ func needToSkipTest(include *regexp.Regexp, exclude *regexp.Regexp, title string return result } -func checkTestSanity(testInput test.Input) bool { +func checkTestSanity(testInput types.Input) bool { return (utils.IsNotEmpty(testInput.Data) && testInput.EncodedRequest != "") || (utils.IsNotEmpty(testInput.Data) && testInput.RAWRequest != "") || (testInput.EncodedRequest != "" && testInput.RAWRequest != "") @@ -356,7 +357,7 @@ func checkResult(c *check.FTWCheck, response *ftwhttp.Response, responseError er return Success } -func getRequestFromTest(testInput test.Input) *ftwhttp.Request { +func getRequestFromTest(testInput types.Input) *ftwhttp.Request { var req *ftwhttp.Request // get raw request, if anything raw, err := testInput.GetRawRequest() diff --git a/test/types.go b/test/types.go index 5d7e26c..2485084 100644 --- a/test/types.go +++ b/test/types.go @@ -4,29 +4,10 @@ package test import ( + "github.com/coreruleset/ftw-tests-schema/types" "github.com/coreruleset/go-ftw/ftwhttp" ) -// Input represents the input request in a stage -// The fields `Version`, `Method` and `URI` we want to explicitly know when they are set to "" - -type Input struct { - DestAddr *string `yaml:"dest_addr,omitempty"` - Port *int `yaml:"port,omitempty"` - Protocol *string `yaml:"protocol,omitempty"` - URI *string `yaml:"uri,omitempty"` - Version *string `yaml:"version,omitempty"` - Headers ftwhttp.Header `yaml:"headers,omitempty"` - Method *string `yaml:"method,omitempty"` - Data *string `yaml:"data,omitempty"` - SaveCookie *bool `yaml:"save_cookie,omitempty"` - // Deprecated: replaced with AutocompleteHeaders - StopMagic *bool `yaml:"stop_magic"` - AutocompleteHeaders *bool `yaml:"autocomplete_headers"` - EncodedRequest string `yaml:"encoded_request,omitempty"` - RAWRequest string `yaml:"raw_request,omitempty"` -} - // Overrides represents the overridden inputs that have to be applied to tests type Overrides struct { DestAddr *string `yaml:"dest_addr,omitempty" koanf:"dest_addr,omitempty"` @@ -46,44 +27,8 @@ type Overrides struct { OverrideEmptyHostHeader *bool `yaml:"override_empty_host_header,omitempty" koanf:"override_empty_host_header,omitempty"` } -// Output is the response expected from the test -type Output struct { - Status []int `yaml:"status,flow,omitempty"` - ResponseContains string `yaml:"response_contains,omitempty"` - LogContains string `yaml:"log_contains,omitempty"` - NoLogContains string `yaml:"no_log_contains,omitempty"` - ExpectError *bool `yaml:"expect_error,omitempty"` -} - -// Stage is an individual test stage -type Stage struct { - Input Input `yaml:"input"` - Output Output `yaml:"output"` -} - -// Test is an individual test -type Test struct { - TestTitle string `yaml:"test_title"` - TestDescription string `yaml:"desc,omitempty"` - Stages []struct { - Stage Stage `yaml:"stage"` - } `yaml:"stages"` -} - -// FTWTest is the base type used when unmarshaling -type FTWTest struct { - FileName string - Meta struct { - Author string `yaml:"author,omitempty"` - Enabled *bool `yaml:"enabled,omitempty"` - Name string `yaml:"name,omitempty"` - Description string `yaml:"description,omitempty"` - } `yaml:"meta"` - Tests []Test `yaml:"tests"` -} - // ApplyInputOverride will check if config had global overrides and write that into the test. -func ApplyInputOverrides(overrides *Overrides, input *Input) { +func ApplyInputOverrides(overrides *Overrides, input *types.Input) { applySimpleOverrides(overrides, input) applyDestAddrOverride(overrides, input) applyHeadersOverride(overrides, input) @@ -92,7 +37,7 @@ func ApplyInputOverrides(overrides *Overrides, input *Input) { } } -func applyDestAddrOverride(overrides *Overrides, input *Input) { +func applyDestAddrOverride(overrides *Overrides, input *types.Input) { if overrides.DestAddr != nil { input.DestAddr = overrides.DestAddr if input.Headers == nil { @@ -104,7 +49,7 @@ func applyDestAddrOverride(overrides *Overrides, input *Input) { } } -func applySimpleOverrides(overrides *Overrides, input *Input) { +func applySimpleOverrides(overrides *Overrides, input *types.Input) { if overrides.Port != nil { input.Port = overrides.Port } @@ -142,7 +87,7 @@ func applySimpleOverrides(overrides *Overrides, input *Input) { } } -func applyHeadersOverride(overrides *Overrides, input *Input) { +func applyHeadersOverride(overrides *Overrides, input *types.Input) { if overrides.Headers != nil { if input.Headers == nil { input.Headers = ftwhttp.Header{} @@ -153,27 +98,27 @@ func applyHeadersOverride(overrides *Overrides, input *Input) { } } -func postLoadTestFTWTest(ftwTest *FTWTest) { +func postLoadTestFTWTest(ftwTest *types.FTWTest) { for _, test := range ftwTest.Tests { postLoadTest(&test) } } -func postLoadTest(test *Test) { +func postLoadTest(test *types.Test) { for index := range test.Stages { postLoadStage(&test.Stages[index].Stage) } } -func postLoadStage(stage *Stage) { +func postLoadStage(stage *types.Stage) { postLoadInput(&stage.Input) } -func postLoadInput(input *Input) { +func postLoadInput(input *types.Input) { postProcessAutocompleteHeaders(input.AutocompleteHeaders, input.StopMagic, input) } -func postProcessAutocompleteHeaders(autocompleteHeaders *bool, stopMagic *bool, input *Input) { +func postProcessAutocompleteHeaders(autocompleteHeaders *bool, stopMagic *bool, input *types.Input) { autocompleteHeadersMissing := autocompleteHeaders == nil stopMagicMissing := stopMagic == nil // default value From 3a4cb517f0e2d796a121a2e78701a8c15ec0af64 Mon Sep 17 00:00:00 2001 From: Matteo Pace Date: Sat, 11 Nov 2023 17:42:56 +0100 Subject: [PATCH 2/6] relies on external schema --- go.mod | 2 +- go.sum | 4 ++-- runner/run.go | 22 +++++++++++----------- runner/run_input_override_test.go | 8 ++++---- test/defaults.go | 22 ++++++++++++++++++++++ test/types.go | 28 +++++++++++++++------------- test/types_test.go | 18 +++++++++--------- 7 files changed, 64 insertions(+), 40 deletions(-) diff --git a/go.mod b/go.mod index d5b72e2..c1d5af1 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/Masterminds/sprig v2.22.0+incompatible - github.com/coreruleset/ftw-tests-schema v1.0.0 + github.com/coreruleset/ftw-tests-schema v1.0.1-0.20231111145830-87a7096e32e1 github.com/go-logr/zerologr v1.2.3 github.com/goccy/go-yaml v1.9.2 github.com/google/uuid v1.4.0 diff --git a/go.sum b/go.sum index 0241efd..7ca512d 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/antchfx/htmlquery v1.3.0/go.mod h1:zKPDVTMhfOmcwxheXUsx4rKJy8KEY/PU6e github.com/antchfx/xpath v1.2.3 h1:CCZWOzv5bAqjVv0offZ2LVgVYFbeldKQVuLNbViZdes= github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreruleset/ftw-tests-schema v1.0.0 h1:qvBx9hXoaqZGEDQ3E2cAIZowtmrV8afBZ5Yv4oFL7S4= -github.com/coreruleset/ftw-tests-schema v1.0.0/go.mod h1:eGixZc1HY61s6ze0f3TExkILnvmXwix4GS10iUXbDmU= +github.com/coreruleset/ftw-tests-schema v1.0.1-0.20231111145830-87a7096e32e1 h1:7qEBrJOMPvIp+Vnl5ASi1egZy+gQlLNaKM4TZfuBIgU= +github.com/coreruleset/ftw-tests-schema v1.0.1-0.20231111145830-87a7096e32e1/go.mod h1:eGixZc1HY61s6ze0f3TExkILnvmXwix4GS10iUXbDmU= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/runner/run.go b/runner/run.go index 047289c..1f54c65 100644 --- a/runner/run.go +++ b/runner/run.go @@ -25,7 +25,7 @@ import ( var errBadTestInput = errors.New("ftw/run: bad test input: choose between data, encoded_request, or raw_request") // Run runs your tests with the specified Config. -func Run(cfg *config.FTWConfiguration, tests []types.FTWTest, c RunnerConfig, out *output.Output) (*TestRunContext, error) { +func Run(cfg *config.FTWConfiguration, tests []test.FTWTest, c RunnerConfig, out *output.Output) (*TestRunContext, error) { out.Println("%s", out.Message("** Running go-ftw!")) logLines, err := waflog.NewFTWLogLines(cfg) @@ -73,7 +73,7 @@ func Run(cfg *config.FTWConfiguration, tests []types.FTWTest, c RunnerConfig, ou // RunTest runs an individual test. // runContext contains information for the current test run // ftwTest is the test you want to run -func RunTest(runContext *TestRunContext, ftwTest types.FTWTest) error { +func RunTest(runContext *TestRunContext, ftwTest test.FTWTest) error { changed := true for _, testCase := range ftwTest.Tests { @@ -100,7 +100,7 @@ func RunTest(runContext *TestRunContext, ftwTest types.FTWTest) error { if err != nil { return err } - if err := RunStage(runContext, ftwCheck, testCase, stage.Stage); err != nil { + if err := RunStage(runContext, ftwCheck, testCase, stage.SD); err != nil { return err } } @@ -114,13 +114,13 @@ func RunTest(runContext *TestRunContext, ftwTest types.FTWTest) error { // ftwCheck is the current check utility // testCase is the test case the stage belongs to // stage is the stage you want to run -func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase types.Test, stage types.Stage) error { +func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase types.Test, stage types.StageData) error { stageStartTime := time.Now() stageID := uuid.NewString() // Apply global overrides initially - testInput := stage.SD.Input + testInput := (test.Input)(stage.Input) test.ApplyInputOverrides(&runContext.Config.TestOverride.Overrides, &testInput) - expectedOutput := stage.SD.Output + expectedOutput := stage.Output expectErr := false if expectedOutput.ExpectError != nil { expectErr = *expectedOutput.ExpectError @@ -181,7 +181,7 @@ func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase typ } // Set expected test output in check - ftwCheck.SetExpectTestOutput(&expectedOutput) + ftwCheck.SetExpectTestOutput((*test.Output)(&expectedOutput)) // now get the test result based on output testResult := checkResult(ftwCheck, response, responseErr) @@ -240,9 +240,9 @@ func markAndFlush(runContext *TestRunContext, dest *ftwhttp.Destination, stageID return nil, fmt.Errorf("can't find log marker. Am I reading the correct log? Log file: %s", runContext.Config.LogFile) } -func needToSkipTest(include *regexp.Regexp, exclude *regexp.Regexp, title string, enabled bool) bool { +func needToSkipTest(include *regexp.Regexp, exclude *regexp.Regexp, title string, enabled *bool) bool { // skip disabled tests - if !enabled { + if enabled != nil && !*enabled { return true } @@ -274,7 +274,7 @@ func needToSkipTest(include *regexp.Regexp, exclude *regexp.Regexp, title string return result } -func checkTestSanity(testInput types.Input) bool { +func checkTestSanity(testInput test.Input) bool { return (utils.IsNotEmpty(testInput.Data) && testInput.EncodedRequest != "") || (utils.IsNotEmpty(testInput.Data) && testInput.RAWRequest != "") || (testInput.EncodedRequest != "" && testInput.RAWRequest != "") @@ -357,7 +357,7 @@ func checkResult(c *check.FTWCheck, response *ftwhttp.Response, responseError er return Success } -func getRequestFromTest(testInput types.Input) *ftwhttp.Request { +func getRequestFromTest(testInput test.Input) *ftwhttp.Request { var req *ftwhttp.Request // get raw request, if anything raw, err := testInput.GetRawRequest() diff --git a/runner/run_input_override_test.go b/runner/run_input_override_test.go index d341817..4a5316c 100644 --- a/runner/run_input_override_test.go +++ b/runner/run_input_override_test.go @@ -175,7 +175,7 @@ func (s *inputOverrideTestSuite) TestSetHostFromDestAddr() { s.NotNil(testInput.Headers, "Header map must exist after overriding `dest_addr`") - hostHeader := testInput.Headers.Get("Host") + hostHeader := testInput.GetHeaders().Get("Host") s.NotEqual("", hostHeader, "Host header must be set after overriding `dest_addr`") s.Equal(overrideHost, hostHeader, "Host header must be identical to `dest_addr` after overrding `dest_addr`") } @@ -191,7 +191,7 @@ func (s *inputOverrideTestSuite) TestSetHostFromHostHeaderOverride() { test.ApplyInputOverrides(&s.cfg.TestOverride.Overrides, &testInput) - hostHeader := testInput.Headers.Get("Host") + hostHeader := testInput.GetHeaders().Get("Host") s.NotEqual("", hostHeader, "Host header must be set after overriding the `Host` header") if hostHeader == overrideHostHeader { s.Equal(overrideHostHeader, hostHeader, "Host header override must take precence over OverrideEmptyHostHeader") @@ -213,7 +213,7 @@ func (s *inputOverrideTestSuite) TestSetHeaderOverridingExistingOne() { test.ApplyInputOverrides(&s.cfg.TestOverride.Overrides, &testInput) - overriddenHeader := testInput.Headers.Get("unique_id") + overriddenHeader := testInput.GetHeaders().Get("unique_id") s.NotEqual("", overriddenHeader, "unique_id header must be set after overriding it") s.Equal(overrideHeaderValue, overriddenHeader, "Host header must be identical to overridden `Host` header.") } @@ -231,7 +231,7 @@ func (s *inputOverrideTestSuite) TestApplyInputOverrides() { test.ApplyInputOverrides(&s.cfg.TestOverride.Overrides, &testInput) - overriddenHeader := testInput.Headers.Get("unique_id") + overriddenHeader := testInput.GetHeaders().Get("unique_id") s.NotEqual("", overriddenHeader, "unique_id header must be set after overriding it") s.Equal(overrideHeaderValue, overriddenHeader, "Host header must be identical to overridden `Host` header.") } diff --git a/test/defaults.go b/test/defaults.go index c593250..acdad48 100644 --- a/test/defaults.go +++ b/test/defaults.go @@ -6,9 +6,15 @@ package test import ( "encoding/base64" + schema "github.com/coreruleset/ftw-tests-schema/types" + "github.com/coreruleset/go-ftw/ftwhttp" "github.com/coreruleset/go-ftw/utils" ) +type Input schema.Input +type Output schema.Output +type FTWTest schema.FTWTest + // GetMethod returns the proper semantic when the field is empty func (i *Input) GetMethod() string { if i.Method == nil { @@ -57,6 +63,14 @@ func (i *Input) GetPort() int { return *i.Port } +// GetHeaders returns the headers wrapped in a ftwhttp.Header +func (i *Input) GetHeaders() ftwhttp.Header { + if i.Headers == nil { + return ftwhttp.Header{} + } + return ftwhttp.Header(i.Headers) +} + // GetRawRequest returns the proper raw data, and error if there was none func (i *Input) GetRawRequest() ([]byte, error) { if utils.IsNotEmpty(i.EncodedRequest) { @@ -68,3 +82,11 @@ func (i *Input) GetRawRequest() ([]byte, error) { } return nil, nil } + +// GetAutocompleteHeaders returns the proper raw data, and error if there was none +func (i *Input) GetAutocompleteHeaders() bool { + if i.AutocompleteHeaders == nil { + return true + } + return *i.AutocompleteHeaders +} diff --git a/test/types.go b/test/types.go index 2485084..112c6eb 100644 --- a/test/types.go +++ b/test/types.go @@ -28,7 +28,7 @@ type Overrides struct { } // ApplyInputOverride will check if config had global overrides and write that into the test. -func ApplyInputOverrides(overrides *Overrides, input *types.Input) { +func ApplyInputOverrides(overrides *Overrides, input *Input) { applySimpleOverrides(overrides, input) applyDestAddrOverride(overrides, input) applyHeadersOverride(overrides, input) @@ -37,19 +37,21 @@ func ApplyInputOverrides(overrides *Overrides, input *types.Input) { } } -func applyDestAddrOverride(overrides *Overrides, input *types.Input) { +func applyDestAddrOverride(overrides *Overrides, input *Input) { if overrides.DestAddr != nil { input.DestAddr = overrides.DestAddr if input.Headers == nil { input.Headers = ftwhttp.Header{} } - if overrides.OverrideEmptyHostHeader != nil && *overrides.OverrideEmptyHostHeader && input.Headers.Get("Host") == "" { - input.Headers.Set("Host", *overrides.DestAddr) + if overrides.OverrideEmptyHostHeader != nil && + *overrides.OverrideEmptyHostHeader && + input.GetHeaders().Get("Host") == "" { + input.GetHeaders().Set("Host", *overrides.DestAddr) } } } -func applySimpleOverrides(overrides *Overrides, input *types.Input) { +func applySimpleOverrides(overrides *Overrides, input *Input) { if overrides.Port != nil { input.Port = overrides.Port } @@ -87,18 +89,18 @@ func applySimpleOverrides(overrides *Overrides, input *types.Input) { } } -func applyHeadersOverride(overrides *Overrides, input *types.Input) { +func applyHeadersOverride(overrides *Overrides, input *Input) { if overrides.Headers != nil { if input.Headers == nil { input.Headers = ftwhttp.Header{} } for k, v := range overrides.Headers { - input.Headers.Set(k, v) + input.GetHeaders().Set(k, v) } } } -func postLoadTestFTWTest(ftwTest *types.FTWTest) { +func postLoadTestFTWTest(ftwTest *FTWTest) { for _, test := range ftwTest.Tests { postLoadTest(&test) } @@ -106,19 +108,19 @@ func postLoadTestFTWTest(ftwTest *types.FTWTest) { func postLoadTest(test *types.Test) { for index := range test.Stages { - postLoadStage(&test.Stages[index].Stage) + postLoadStage(&test.Stages[index].SD) } } -func postLoadStage(stage *types.Stage) { - postLoadInput(&stage.Input) +func postLoadStage(stage *types.StageData) { + postLoadInput((*Input)(&stage.Input)) } -func postLoadInput(input *types.Input) { +func postLoadInput(input *Input) { postProcessAutocompleteHeaders(input.AutocompleteHeaders, input.StopMagic, input) } -func postProcessAutocompleteHeaders(autocompleteHeaders *bool, stopMagic *bool, input *types.Input) { +func postProcessAutocompleteHeaders(autocompleteHeaders *bool, stopMagic *bool, input *Input) { autocompleteHeadersMissing := autocompleteHeaders == nil stopMagicMissing := stopMagic == nil // default value diff --git a/test/types_test.go b/test/types_test.go index 97e309c..94ffa20 100644 --- a/test/types_test.go +++ b/test/types_test.go @@ -177,7 +177,7 @@ func (s *typesTestSuite) TestAutocompleteHeadersDefault_StopMagicDefault() { test, err := GetTestFromYaml([]byte(autocompleteHeadersDefaultYaml)) s.NoError(err, "Parsing YAML shouldn't fail") - input := test.Tests[0].Stages[0].Stage.Input + input := test.Tests[0].Stages[0].SD.Input s.True(*input.AutocompleteHeaders) s.False(*input.StopMagic) } @@ -186,7 +186,7 @@ func (s *typesTestSuite) TestAutocompleteHeadersDefault_StopMagicTrue() { test, err := GetTestFromYaml([]byte(autocompleteHeadersDefaultYaml)) s.NoError(err, "Parsing YAML shouldn't fail") - input := test.Tests[1].Stages[0].Stage.Input + input := test.Tests[1].Stages[0].SD.Input s.False(*input.AutocompleteHeaders) s.True(*input.StopMagic) } @@ -194,7 +194,7 @@ func (s *typesTestSuite) TestAutocompleteHeadersDefault_StopMagicFalse() { test, err := GetTestFromYaml([]byte(autocompleteHeadersDefaultYaml)) s.NoError(err, "Parsing YAML shouldn't fail") - input := test.Tests[2].Stages[0].Stage.Input + input := test.Tests[2].Stages[0].SD.Input s.True(*input.AutocompleteHeaders) s.False(*input.StopMagic) } @@ -203,7 +203,7 @@ func (s *typesTestSuite) TestAutocompleteHeadersFalse_StopMagicDefault() { test, err := GetTestFromYaml([]byte(autocompleteHeadersFalseYaml)) s.NoError(err, "Parsing YAML shouldn't fail") - input := test.Tests[0].Stages[0].Stage.Input + input := test.Tests[0].Stages[0].SD.Input s.False(*input.AutocompleteHeaders) s.True(*input.StopMagic) } @@ -212,7 +212,7 @@ func (s *typesTestSuite) TestAutocompleteHeadersFalse_StopMagicTrue() { test, err := GetTestFromYaml([]byte(autocompleteHeadersFalseYaml)) s.NoError(err, "Parsing YAML shouldn't fail") - input := test.Tests[1].Stages[0].Stage.Input + input := test.Tests[1].Stages[0].SD.Input s.False(*input.AutocompleteHeaders) s.True(*input.StopMagic) } @@ -221,7 +221,7 @@ func (s *typesTestSuite) TestAutocompleteHeadersFalse_StopMagicFalse() { test, err := GetTestFromYaml([]byte(autocompleteHeadersFalseYaml)) s.NoError(err, "Parsing YAML shouldn't fail") - input := test.Tests[2].Stages[0].Stage.Input + input := test.Tests[2].Stages[0].SD.Input s.False(*input.AutocompleteHeaders) s.True(*input.StopMagic) } @@ -230,7 +230,7 @@ func (s *typesTestSuite) TestAutocompleteHeadersTrue_StopMagicDefault() { test, err := GetTestFromYaml([]byte(autocompleteHeadersTrueYaml)) s.NoError(err, "Parsing YAML shouldn't fail") - input := test.Tests[0].Stages[0].Stage.Input + input := test.Tests[0].Stages[0].SD.Input s.True(*input.AutocompleteHeaders) s.False(*input.StopMagic) } @@ -239,7 +239,7 @@ func (s *typesTestSuite) TestAutocompleteHeadersTrue_StopMagicTrue() { test, err := GetTestFromYaml([]byte(autocompleteHeadersTrueYaml)) s.NoError(err, "Parsing YAML shouldn't fail") - input := test.Tests[1].Stages[0].Stage.Input + input := test.Tests[1].Stages[0].SD.Input s.True(*input.AutocompleteHeaders) s.False(*input.StopMagic) } @@ -248,7 +248,7 @@ func (s *typesTestSuite) TestAutocompleteHeadersTrue_StopMagicFalse() { test, err := GetTestFromYaml([]byte(autocompleteHeadersTrueYaml)) s.NoError(err, "Parsing YAML shouldn't fail") - input := test.Tests[2].Stages[0].Stage.Input + input := test.Tests[2].Stages[0].SD.Input s.True(*input.AutocompleteHeaders) s.False(*input.StopMagic) } From a9b334fb18841265c4c722bcc8e8c38b71681ea2 Mon Sep 17 00:00:00 2001 From: Matteo Pace Date: Sat, 11 Nov 2023 20:52:59 +0100 Subject: [PATCH 3/6] reduces not needed diffs --- runner/run.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runner/run.go b/runner/run.go index 1f54c65..7ceb677 100644 --- a/runner/run.go +++ b/runner/run.go @@ -78,7 +78,7 @@ func RunTest(runContext *TestRunContext, ftwTest test.FTWTest) error { for _, testCase := range ftwTest.Tests { // if we received a particular testid, skip until we find it - if needToSkipTest(runContext.Include, runContext.Exclude, testCase.TestTitle, ftwTest.Meta.Enabled) { + if needToSkipTest(runContext.Include, runContext.Exclude, testCase.TestTitle, *ftwTest.Meta.Enabled) { runContext.Stats.addResultToStats(Skipped, testCase.TestTitle, 0) if !*ftwTest.Meta.Enabled && !runContext.ShowOnlyFailed { runContext.Output.Println("\tskipping %s - (enabled: false) in file.", testCase.TestTitle) @@ -240,9 +240,9 @@ func markAndFlush(runContext *TestRunContext, dest *ftwhttp.Destination, stageID return nil, fmt.Errorf("can't find log marker. Am I reading the correct log? Log file: %s", runContext.Config.LogFile) } -func needToSkipTest(include *regexp.Regexp, exclude *regexp.Regexp, title string, enabled *bool) bool { +func needToSkipTest(include *regexp.Regexp, exclude *regexp.Regexp, title string, enabled bool) bool { // skip disabled tests - if enabled != nil && !*enabled { + if !enabled { return true } From b95b76902248357d3f8e4c917fc52558dc99acdb Mon Sep 17 00:00:00 2001 From: Matteo Pace Date: Sat, 11 Nov 2023 21:26:08 +0100 Subject: [PATCH 4/6] updates ftw schema to v1.1.0 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c1d5af1..7b36bd9 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/Masterminds/sprig v2.22.0+incompatible - github.com/coreruleset/ftw-tests-schema v1.0.1-0.20231111145830-87a7096e32e1 + github.com/coreruleset/ftw-tests-schema v1.1.0 github.com/go-logr/zerologr v1.2.3 github.com/goccy/go-yaml v1.9.2 github.com/google/uuid v1.4.0 diff --git a/go.sum b/go.sum index 7ca512d..72db0ee 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/antchfx/htmlquery v1.3.0/go.mod h1:zKPDVTMhfOmcwxheXUsx4rKJy8KEY/PU6e github.com/antchfx/xpath v1.2.3 h1:CCZWOzv5bAqjVv0offZ2LVgVYFbeldKQVuLNbViZdes= github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreruleset/ftw-tests-schema v1.0.1-0.20231111145830-87a7096e32e1 h1:7qEBrJOMPvIp+Vnl5ASi1egZy+gQlLNaKM4TZfuBIgU= -github.com/coreruleset/ftw-tests-schema v1.0.1-0.20231111145830-87a7096e32e1/go.mod h1:eGixZc1HY61s6ze0f3TExkILnvmXwix4GS10iUXbDmU= +github.com/coreruleset/ftw-tests-schema v1.1.0 h1:3+NYrdLE3HVmOc3nGrisRBBvY9lGjePUrV+YkT5Ay3s= +github.com/coreruleset/ftw-tests-schema v1.1.0/go.mod h1:gRd9wBxjUI85HypWRDxJzbk1JqHC4KTxl0l/Y2p9QK4= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= From eca1638389ead9d939110b0af57c3edd2c774120 Mon Sep 17 00:00:00 2001 From: Matteo Pace Date: Sat, 11 Nov 2023 21:28:34 +0100 Subject: [PATCH 5/6] nit: fix description of getter --- test/defaults.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/defaults.go b/test/defaults.go index acdad48..0fb012d 100644 --- a/test/defaults.go +++ b/test/defaults.go @@ -83,7 +83,7 @@ func (i *Input) GetRawRequest() ([]byte, error) { return nil, nil } -// GetAutocompleteHeaders returns the proper raw data, and error if there was none +// GetAutocompleteHeaders returns the proper the autocompleteHeaders value, defaults to true func (i *Input) GetAutocompleteHeaders() bool { if i.AutocompleteHeaders == nil { return true From cf99a9e781fe5a9d6e5f497ecce288ced608669c Mon Sep 17 00:00:00 2001 From: Matteo Pace Date: Sat, 11 Nov 2023 23:17:42 +0100 Subject: [PATCH 6/6] address review --- test/defaults.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/defaults.go b/test/defaults.go index 0fb012d..fb6a50c 100644 --- a/test/defaults.go +++ b/test/defaults.go @@ -83,7 +83,7 @@ func (i *Input) GetRawRequest() ([]byte, error) { return nil, nil } -// GetAutocompleteHeaders returns the proper the autocompleteHeaders value, defaults to true +// GetAutocompleteHeaders returns the autocompleteHeaders value, defaults to true func (i *Input) GetAutocompleteHeaders() bool { if i.AutocompleteHeaders == nil { return true