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

fix: remove most uses of log.Fatal when running programatically #99

Merged
merged 1 commit into from
Nov 2, 2022
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
5 changes: 4 additions & 1 deletion cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,17 @@ var runCmd = &cobra.Command{
excludeRE = regexp.MustCompile(exclude)
}

currentRun := runner.Run(tests, runner.Config{
currentRun, err := runner.Run(tests, runner.Config{
Include: includeRE,
Exclude: excludeRE,
ShowTime: showTime,
Quiet: quiet,
ConnectTimeout: connectTimeout,
ReadTimeout: readTimeout,
})
if err != nil {
log.Fatal().Err(err)
}

os.Exit(currentRun.Stats.TotalFailed())
},
Expand Down
6 changes: 3 additions & 3 deletions ftwhttp/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ func NewClientConfig() ClientConfig {
}

// NewClient initializes the http client, creating the cookiejar
func NewClient(config ClientConfig) *Client {
func NewClient(config ClientConfig) (*Client, error) {
// All users of cookiejar should import "golang.org/x/net/publicsuffix"
jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
if err != nil {
log.Fatal().Err(err)
return nil, err
}
c := &Client{
Jar: jar,
config: config,
}
return c
return c, nil
}

// NewConnection creates a new Connection based on a Destination
Expand Down
32 changes: 20 additions & 12 deletions ftwhttp/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import (
)

func TestNewClient(t *testing.T) {
c := NewClient(NewClientConfig())
c, err := NewClient(NewClientConfig())
assert.NoError(t, err)

assert.NotNil(t, c.Jar, "Error creating Client")
}
Expand All @@ -19,9 +20,10 @@ func TestConnectDestinationHTTPS(t *testing.T) {
Protocol: "https",
}

c := NewClient(NewClientConfig())
c, err := NewClient(NewClientConfig())
assert.NoError(t, err)

err := c.NewConnection(*d)
err = c.NewConnection(*d)
assert.NoError(t, err, "This should not error")
assert.Equal(t, "https", c.Transport.protocol, "Error connecting to example.com using https")
}
Expand All @@ -33,11 +35,12 @@ func TestDoRequest(t *testing.T) {
Protocol: "https",
}

c := NewClient(NewClientConfig())
c, err := NewClient(NewClientConfig())
assert.NoError(t, err)

req := generateBaseRequestForTesting()

err := c.NewConnection(*d)
err = c.NewConnection(*d)
assert.NoError(t, err, "This should not error")

_, err = c.Do(*req)
Expand All @@ -52,7 +55,8 @@ func TestGetTrackedTime(t *testing.T) {
Protocol: "https",
}

c := NewClient(NewClientConfig())
c, err := NewClient(NewClientConfig())
assert.NoError(t, err)

rl := &RequestLine{
Method: "POST",
Expand All @@ -65,7 +69,7 @@ func TestGetTrackedTime(t *testing.T) {
data := []byte(`test=me&one=two&one=twice`)
req := NewRequest(rl, h, data, true)

err := c.NewConnection(*d)
err = c.NewConnection(*d)
assert.NoError(t, err, "This should not error")

c.StartTrackingTime()
Expand All @@ -90,7 +94,8 @@ func TestClientMultipartFormDataRequest(t *testing.T) {
Protocol: "https",
}

c := NewClient(NewClientConfig())
c, err := NewClient(NewClientConfig())
assert.NoError(t, err)

rl := &RequestLine{
Method: "POST",
Expand All @@ -112,7 +117,7 @@ Some-file-test-here

req := NewRequest(rl, h, data, true)

err := c.NewConnection(*d)
err = c.NewConnection(*d)
assert.NoError(t, err, "This should not error")

c.StartTrackingTime()
Expand All @@ -127,7 +132,8 @@ Some-file-test-here
}

func TestNewConnectionCreatesTransport(t *testing.T) {
c := NewClient(NewClientConfig())
c, err := NewClient(NewClientConfig())
assert.NoError(t, err)
assert.Nil(t, c.Transport, "Transport not expected to initialized yet")

server := testServer()
Expand All @@ -141,7 +147,8 @@ func TestNewConnectionCreatesTransport(t *testing.T) {
}

func TestNewOrReusedConnectionCreatesTransport(t *testing.T) {
c := NewClient(NewClientConfig())
c, err := NewClient(NewClientConfig())
assert.NoError(t, err)
assert.Nil(t, c.Transport, "Transport not expected to initialized yet")

server := testServer()
Expand All @@ -155,7 +162,8 @@ func TestNewOrReusedConnectionCreatesTransport(t *testing.T) {
}

func TestNewOrReusedConnectionReusesTransport(t *testing.T) {
c := NewClient(NewClientConfig())
c, err := NewClient(NewClientConfig())
assert.NoError(t, err)
assert.Nil(t, c.Transport, "Transport not expected to initialized yet")

server := testServer()
Expand Down
3 changes: 2 additions & 1 deletion ftwhttp/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"net"
"net/http"
Expand Down Expand Up @@ -82,7 +83,7 @@ func (c *Connection) Request(request *Request) error {
// Build request first, then connect and send, so timers are accurate
data, err := buildRequest(request)
if err != nil {
log.Fatal().Msgf("ftw/http: fatal error building request: %s", err.Error())
return fmt.Errorf("ftw/http: fatal error building request: %w", err)
}

log.Debug().Msgf("ftw/http: sending data:\n%s\n", data)
Expand Down
6 changes: 4 additions & 2 deletions ftwhttp/response_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ func TestResponse(t *testing.T) {

req := generateRequestForTesting(true)

client := NewClient(NewClientConfig())
client, err := NewClient(NewClientConfig())
assert.NoError(t, err)
err = client.NewConnection(*d)
assert.NoError(t, err)

Expand All @@ -107,7 +108,8 @@ func TestResponseWithCookies(t *testing.T) {
assert.NoError(t, err)
req := generateRequestForTesting(true)

client := NewClient(NewClientConfig())
client, err := NewClient(NewClientConfig())
assert.NoError(t, err)
err = client.NewConnection(*d)

assert.NoError(t, err)
Expand Down
49 changes: 33 additions & 16 deletions runner/run.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package runner

import (
"errors"
"fmt"
"regexp"
"time"
Expand All @@ -17,11 +18,16 @@ import (
"github.com/coreruleset/go-ftw/waflog"
)

var errBadTestRequest = errors.New("ftw/run: bad test: choose between data, encoded_request, or raw_request")

// Run runs your tests with the specified Config. Returns error if some test failed
func Run(tests []test.FTWTest, c Config) TestRunContext {
func Run(tests []test.FTWTest, c Config) (TestRunContext, error) {
printUnlessQuietMode(c.Quiet, ":rocket:Running go-ftw!\n")

logLines := waflog.NewFTWLogLines(waflog.WithLogFile(config.FTWConfig.LogFile))
logLines, err := waflog.NewFTWLogLines(waflog.WithLogFile(config.FTWConfig.LogFile))
if err != nil {
return TestRunContext{}, err
}

conf := ftwhttp.NewClientConfig()
if c.ConnectTimeout != 0 {
Expand All @@ -30,7 +36,10 @@ func Run(tests []test.FTWTest, c Config) TestRunContext {
if c.ReadTimeout != 0 {
conf.ReadTimeout = c.ReadTimeout
}
client := ftwhttp.NewClient(conf)
client, err := ftwhttp.NewClient(conf)
if err != nil {
return TestRunContext{}, err
}
runContext := TestRunContext{
Include: c.Include,
Exclude: c.Exclude,
Expand All @@ -41,21 +50,23 @@ func Run(tests []test.FTWTest, c Config) TestRunContext {
RunMode: config.FTWConfig.RunMode,
}

for _, test := range tests {
RunTest(&runContext, test)
for _, tc := range tests {
if err := RunTest(&runContext, tc); err != nil {
return TestRunContext{}, err
}
}

printSummary(c.Quiet, runContext.Stats)

defer cleanLogs(logLines)

return runContext
return runContext, nil
}

// 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) {
func RunTest(runContext *TestRunContext, ftwTest test.FTWTest) error {
changed := true

for _, testCase := range ftwTest.Tests {
Expand All @@ -78,17 +89,21 @@ func RunTest(runContext *TestRunContext, ftwTest test.FTWTest) {
// Iterate over stages
for _, stage := range testCase.Stages {
ftwCheck := check.NewCheck(config.FTWConfig)
RunStage(runContext, ftwCheck, testCase, stage.Stage)
if err := RunStage(runContext, ftwCheck, testCase, stage.Stage); err != nil {
return err
}
}
}

return nil
}

// RunStage runs an individual test stage.
// runContext contains information for the current test run
// 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) {
func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase test.Test, stage test.Stage) error {
stageStartTime := time.Now()
stageID := uuid.NewString()
// Apply global overrides initially
Expand All @@ -101,14 +116,14 @@ func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase tes

// Check sanity first
if checkTestSanity(testRequest) {
log.Fatal().Msgf("ftw/run: bad test: choose between data, encoded_request, or raw_request")
return errBadTestRequest
}

// Do not even run test if result is overridden. Just use the override and display the overridden result.
if overridden := overriddenTestResult(ftwCheck, testCase.TestTitle); overridden != Failed {
addResultToStats(overridden, testCase.TestTitle, &runContext.Stats)
displayResult(runContext.Output, overridden, time.Duration(0), time.Duration(0))
return
return nil
}

var req *ftwhttp.Request
Expand All @@ -123,7 +138,7 @@ func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase tes
if notRunningInCloudMode(ftwCheck) {
startMarker, err := markAndFlush(runContext, dest, stageID)
if err != nil && !expectedOutput.ExpectError {
log.Fatal().Caller().Err(err).Msg("Failed to find start marker")
return fmt.Errorf("failed to find start marker: %w", err)
}
ftwCheck.SetStartMarker(startMarker)
}
Expand All @@ -133,21 +148,21 @@ func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase tes
err = runContext.Client.NewConnection(*dest)

if err != nil && !expectedOutput.ExpectError {
log.Fatal().Caller().Err(err).Msgf("can't connect to destination %+v", dest)
return fmt.Errorf("can't connect to destination %+v: %w", dest, err)
}
runContext.Client.StartTrackingTime()

response, responseErr := runContext.Client.Do(*req)

runContext.Client.StopTrackingTime()
if responseErr != nil && !expectedOutput.ExpectError {
log.Fatal().Caller().Err(responseErr).Msgf("failed sending request to destination %+v", dest)
return fmt.Errorf("failed sending request to destination %+v: %w", dest, responseErr)
}

if notRunningInCloudMode(ftwCheck) {
endMarker, err := markAndFlush(runContext, dest, stageID)
if err != nil && !expectedOutput.ExpectError {
log.Fatal().Caller().Err(err).Msg("Failed to find end marker")
return fmt.Errorf("failed to find end marker: %w", err)

}
ftwCheck.SetEndMarker(endMarker)
Expand All @@ -171,6 +186,8 @@ func RunStage(runContext *TestRunContext, ftwCheck *check.FTWCheck, testCase tes

runContext.Stats.Run++
runContext.Stats.RunTime += stageTime

return nil
}

func markAndFlush(runContext *TestRunContext, dest *ftwhttp.Destination, stageID string) ([]byte, error) {
Expand Down Expand Up @@ -386,6 +403,6 @@ func notRunningInCloudMode(c *check.FTWCheck) bool {

func cleanLogs(logLines *waflog.FTWLogLines) {
if err := logLines.Cleanup(); err != nil {
log.Fatal().Err(err).Msg("Failed to cleanup log file")
log.Error().Err(err).Msg("Failed to cleanup log file")
}
}
Loading