Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: move test type to its own package #208

Merged
merged 6 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -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.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
Expand Down
11 changes: 3 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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.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=
Expand Down Expand Up @@ -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=
Expand All @@ -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=
Expand All @@ -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=
Expand All @@ -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=
Expand Down
9 changes: 5 additions & 4 deletions runner/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -99,7 +100,7 @@ func RunTest(runContext *TestRunContext, ftwTest test.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
}
}
Expand All @@ -113,11 +114,11 @@ 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.StageData) error {
stageStartTime := time.Now()
stageID := uuid.NewString()
// Apply global overrides initially
testInput := stage.Input
testInput := (test.Input)(stage.Input)
test.ApplyInputOverrides(&runContext.Config.TestOverride.Overrides, &testInput)
expectedOutput := stage.Output
expectErr := false
Expand Down Expand Up @@ -180,7 +181,7 @@ func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase tes
}

// 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)
Expand Down
8 changes: 4 additions & 4 deletions runner/run_input_override_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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`")
}
Expand All @@ -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")
Expand All @@ -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.")
}
Expand All @@ -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.")
}
Expand Down
22 changes: 22 additions & 0 deletions test/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand All @@ -68,3 +82,11 @@ func (i *Input) GetRawRequest() ([]byte, error) {
}
return nil, nil
}

// GetAutocompleteHeaders returns the autocompleteHeaders value, defaults to true
func (i *Input) GetAutocompleteHeaders() bool {
if i.AutocompleteHeaders == nil {
return true
}
return *i.AutocompleteHeaders
}
73 changes: 10 additions & 63 deletions test/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand All @@ -46,42 +27,6 @@ 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) {
applySimpleOverrides(overrides, input)
Expand All @@ -98,8 +43,10 @@ func applyDestAddrOverride(overrides *Overrides, input *Input) {
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)
}
}
}
Expand Down Expand Up @@ -148,7 +95,7 @@ func applyHeadersOverride(overrides *Overrides, input *Input) {
input.Headers = ftwhttp.Header{}
}
for k, v := range overrides.Headers {
input.Headers.Set(k, v)
input.GetHeaders().Set(k, v)
}
}
}
Expand All @@ -159,14 +106,14 @@ func postLoadTestFTWTest(ftwTest *FTWTest) {
}
}

func postLoadTest(test *Test) {
func postLoadTest(test *types.Test) {
for index := range test.Stages {
postLoadStage(&test.Stages[index].Stage)
postLoadStage(&test.Stages[index].SD)
}
}

func postLoadStage(stage *Stage) {
postLoadInput(&stage.Input)
func postLoadStage(stage *types.StageData) {
postLoadInput((*Input)(&stage.Input))
}

func postLoadInput(input *Input) {
Expand Down
18 changes: 9 additions & 9 deletions test/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -186,15 +186,15 @@ 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)
}
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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}