Skip to content

Commit

Permalink
Merge pull request #67 from ddosify/default_values
Browse files Browse the repository at this point in the history
Default values
  • Loading branch information
kursataktas authored Apr 27, 2022
2 parents 98d1eaf + c42be90 commit f9e738e
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17.x
go-version: 1.18.x

- name: Test
run: go test -coverpkg=./... -coverprofile=coverage.txt -parallel 1 -covermode=atomic -short ./... && go tool cover -func coverage.txt
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18
-
name: Docker Hub Login
uses: docker/login-action@v1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.15.x, 1.16.x, 1.17.x]
go-version: [1.15.x, 1.16.x, 1.17.x, 1.18.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.17-alpine as builder
FROM golang:1.18.1-alpine as builder
WORKDIR /app
COPY . ./
RUN go mod download
Expand Down
17 changes: 8 additions & 9 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
FROM golang:1.17.1
FROM golang:1.18.1

RUN apt update && apt install -y git gcc musl-dev curl iputils-ping telnet && rm -rf /var/lib/apt/lists/*
RUN apt update && apt install -y git gcc musl-dev curl iputils-ping telnet graphviz && rm -rf /var/lib/apt/lists/*

ENV GOPATH /go
ENV GOBIN /go/bin

WORKDIR /workspace

RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.42.0
RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.45.2

RUN go get -v golang.org/x/tools/[email protected]
RUN go get -v github.com/rogpeppe/[email protected]
RUN go get -v github.com/rakyll/[email protected]
RUN go get -v github.com/cweill/[email protected]
RUN go get -v github.com/ramya-rao-a/[email protected]
RUN go get -v github.com/go-delve/delve/cmd/[email protected]
RUN go install -v golang.org/x/tools/[email protected]
RUN go install -v github.com/rogpeppe/[email protected]
RUN go install -v github.com/rakyll/[email protected]
RUN go install -v github.com/ramya-rao-a/[email protected]
RUN go install -v github.com/go-delve/delve/cmd/[email protected]

COPY go.mod ./
COPY go.sum ./
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ There is an example config file at [config_examples/config.json](/config_example

```json
"others": {
"keep-alive": true, // Default false
"keep-alive": true, // Default true
"disable-compression": false, // Default true
"h2": true, // Enables HTTP/2. Default false.
"disable-redirect": true // Default false
Expand Down
1 change: 1 addition & 0 deletions core/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ func (e *engine) stop() {
<-e.reportService.DoneChan()
e.reportService.Report()
e.proxyService.Done()
e.scenarioService.Done()
}

func (e *engine) initReqCountArr() {
Expand Down
1 change: 1 addition & 0 deletions core/scenario/requester/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
type Requester interface {
Init(context.Context, types.ScenarioItem, *url.URL) error
Send() *types.ResponseItem
Done()
}

// NewRequester is the factory method of the Requester.
Expand Down
31 changes: 20 additions & 11 deletions core/scenario/requester/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ func (h *HttpRequester) Init(ctx context.Context, s types.ScenarioItem, proxyAdd
return
}

func (h *HttpRequester) Done() {
// MaxIdleConnsPerHost and MaxIdleConns at Transport layer configuration
// let us reuse the connections when keep-alive enabled(default)
// When the Job is finished, we have to Close idle connections to prevent sockets to lock in at the TIME_WAIT state.
// Otherwise, the next job can't use these sockets because they are reserved for the current target host.
h.client.CloseIdleConnections()
}

func (h *HttpRequester) Send() (res *types.ResponseItem) {
var statusCode int
var contentLength int64
Expand Down Expand Up @@ -105,10 +113,12 @@ func (h *HttpRequester) Send() (res *types.ResponseItem) {
} else {
contentLength = httpRes.ContentLength
statusCode = httpRes.StatusCode
}

// From the DOC: If the Body is not both read to EOF and closed,
// the Client's underlying RoundTripper (typically Transport)
// may not be able to re-use a persistent TCP connection to the server for a subsequent "keep-alive" request.
// From the DOC: If the Body is not both read to EOF and closed,
// the Client's underlying RoundTripper (typically Transport)
// may not be able to re-use a persistent TCP connection to the server for a subsequent "keep-alive" request.
if httpRes != nil {
io.Copy(ioutil.Discard, httpRes.Body)
httpRes.Body.Close()
}
Expand Down Expand Up @@ -178,12 +188,13 @@ func fetchErrType(err string) types.RequestError {

func (h *HttpRequester) initTransport(tlsConfig *tls.Config) *http.Transport {
tr := &http.Transport{
TLSClientConfig: tlsConfig,
Proxy: http.ProxyURL(h.proxyAddr),
// MaxIdleConnsPerHost: 100, TODO: Let's think about this.
TLSClientConfig: tlsConfig,
Proxy: http.ProxyURL(h.proxyAddr),
MaxIdleConnsPerHost: 60000,
MaxIdleConns: 0,
}

tr.DisableKeepAlives = true
tr.DisableKeepAlives = false
if val, ok := h.packet.Custom["keep-alive"]; ok {
tr.DisableKeepAlives = !val.(bool)
}
Expand Down Expand Up @@ -233,11 +244,9 @@ func (h *HttpRequester) initRequestInstance() (err error) {
}

// If keep-alive is false, prevent the reuse of the previous TCP connection at the request layer also.
h.request.Close = true
h.request.Close = false
if val, ok := h.packet.Custom["keep-alive"]; ok {
if val.(bool) {
h.request.Close = false
}
h.request.Close = !val.(bool)
}
return
}
Expand Down
34 changes: 17 additions & 17 deletions core/scenario/requester/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func TestInitClient(t *testing.T) {
expectedTr := &http.Transport{
TLSClientConfig: expectedTLS,
Proxy: http.ProxyURL(p),
DisableKeepAlives: true,
DisableKeepAlives: false,
}
expectedClient := &http.Client{
Transport: expectedTr,
Expand All @@ -93,7 +93,7 @@ func TestInitClient(t *testing.T) {
Timeout: types.DefaultTimeout,
Custom: map[string]interface{}{
"disable-redirect": true,
"keep-alive": true,
"keep-alive": false,
"disable-compression": true,
"hostname": "dummy.com",
},
Expand All @@ -105,7 +105,7 @@ func TestInitClient(t *testing.T) {
expectedTrCustomData := &http.Transport{
TLSClientConfig: expectedTLSCustomData,
Proxy: http.ProxyURL(p),
DisableKeepAlives: false,
DisableKeepAlives: true,
DisableCompression: true,
}
expectedClientWithCustomData := &http.Client{
Expand Down Expand Up @@ -133,7 +133,7 @@ func TestInitClient(t *testing.T) {
expectedTrHTTP2 := &http.Transport{
TLSClientConfig: expectedTLSHTTP2,
Proxy: http.ProxyURL(p),
DisableKeepAlives: true,
DisableKeepAlives: false,
}
http2.ConfigureTransport(expectedTrHTTP2)
expectedClientHTTP2 := &http.Client{
Expand Down Expand Up @@ -226,7 +226,7 @@ func TestInitRequest(t *testing.T) {
Payload: "payloadtest",
}
expected, _ := http.NewRequest(s.Method, s.URL, bytes.NewBufferString(s.Payload))
expected.Close = true
expected.Close = false
expected.Header = make(http.Header)

// Request with auth
Expand All @@ -242,7 +242,7 @@ func TestInitRequest(t *testing.T) {
},
}
expectedWithAuth, _ := http.NewRequest(sWithAuth.Method, sWithAuth.URL, bytes.NewBufferString(sWithAuth.Payload))
expectedWithAuth.Close = true
expectedWithAuth.Close = false
expectedWithAuth.Header = make(http.Header)
expectedWithAuth.SetBasicAuth(sWithAuth.Auth.Username, sWithAuth.Auth.Password)

Expand All @@ -266,7 +266,7 @@ func TestInitRequest(t *testing.T) {
}
expectedWithHeaders, _ := http.NewRequest(sWithHeaders.Method,
sWithHeaders.URL, bytes.NewBufferString(sWithHeaders.Payload))
expectedWithHeaders.Close = true
expectedWithHeaders.Close = false
expectedWithHeaders.Header = make(http.Header)
expectedWithHeaders.Header.Set("Header1", "Value1")
expectedWithHeaders.Header.Set("Header2", "Value2")
Expand All @@ -275,7 +275,7 @@ func TestInitRequest(t *testing.T) {
expectedWithHeaders.SetBasicAuth(sWithHeaders.Auth.Username, sWithHeaders.Auth.Password)

// Request keep-alive condition
sWithKeepAlive := types.ScenarioItem{
sWithoutKeepAlive := types.ScenarioItem{
ID: 1,
Protocol: types.ProtocolHTTPS,
Method: http.MethodGet,
Expand All @@ -290,16 +290,16 @@ func TestInitRequest(t *testing.T) {
"Header2": "Value2",
},
Custom: map[string]interface{}{
"keep-alive": true,
"keep-alive": false,
},
}
expectedWithKeepAlive, _ := http.NewRequest(sWithKeepAlive.Method,
sWithKeepAlive.URL, bytes.NewBufferString(sWithKeepAlive.Payload))
expectedWithKeepAlive.Close = false
expectedWithKeepAlive.Header = make(http.Header)
expectedWithKeepAlive.Header.Set("Header1", "Value1")
expectedWithKeepAlive.Header.Set("Header2", "Value2")
expectedWithKeepAlive.SetBasicAuth(sWithKeepAlive.Auth.Username, sWithKeepAlive.Auth.Password)
expectedWithoutKeepAlive, _ := http.NewRequest(sWithoutKeepAlive.Method,
sWithoutKeepAlive.URL, bytes.NewBufferString(sWithoutKeepAlive.Payload))
expectedWithoutKeepAlive.Close = true
expectedWithoutKeepAlive.Header = make(http.Header)
expectedWithoutKeepAlive.Header.Set("Header1", "Value1")
expectedWithoutKeepAlive.Header.Set("Header2", "Value2")
expectedWithoutKeepAlive.SetBasicAuth(sWithoutKeepAlive.Auth.Username, sWithoutKeepAlive.Auth.Password)

// Sub Tests
tests := []struct {
Expand All @@ -312,7 +312,7 @@ func TestInitRequest(t *testing.T) {
{"Basic", s, false, expected},
{"WithAuth", sWithAuth, false, expectedWithAuth},
{"WithHeaders", sWithHeaders, false, expectedWithHeaders},
{"WithKeepAlive", sWithKeepAlive, false, expectedWithKeepAlive},
{"WithoutKeepAlive", sWithoutKeepAlive, false, expectedWithoutKeepAlive},
}

for _, test := range tests {
Expand Down
8 changes: 8 additions & 0 deletions core/scenario/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ func (s *ScenarioService) Do(proxy *url.URL, startTime time.Time) (response *typ
return
}

func (s *ScenarioService) Done() {
for _, v := range s.clients {
for _, r := range v {
r.requester.Done()
}
}
}

func (s *ScenarioService) getOrCreateRequesters(proxy *url.URL) (requesters []scenarioItemRequester, err error) {
s.clientMutex.Lock()
defer s.clientMutex.Unlock()
Expand Down
73 changes: 73 additions & 0 deletions core/scenario/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
type MockRequester struct {
InitCalled bool
SendCalled bool
DoneCalled bool

FailInit bool
FailInitMsg string
Expand All @@ -55,6 +56,10 @@ func (m *MockRequester) Send() (res *types.ResponseItem) {
return m.ReturnSend
}

func (m *MockRequester) Done() {
m.DoneCalled = true
}

type MockSleep struct {
SleepCalled bool
SleepCallCount int
Expand Down Expand Up @@ -409,6 +414,74 @@ func TestDoErrorOnNewRequester(t *testing.T) {
}
}

func TestDone(t *testing.T) {
t.Parallel()

// Arrange
scenario := types.Scenario{
Scenario: []types.ScenarioItem{
{
ID: 1,
Protocol: types.DefaultProtocol,
Method: types.DefaultMethod,
URL: "test.com",
Timeout: types.DefaultDuration,
},
},
}
p1, _ := url.Parse("http://proxy_server.com:80")
p2, _ := url.Parse("http://proxy_server.com:8080")
ctx := context.TODO()

requester1 := &MockRequester{ReturnSend: &types.ResponseItem{ScenarioItemID: 1}}
requester2 := &MockRequester{ReturnSend: &types.ResponseItem{ScenarioItemID: 2}}
requester3 := &MockRequester{ReturnSend: &types.ResponseItem{ScenarioItemID: 1}}
requester4 := &MockRequester{ReturnSend: &types.ResponseItem{ScenarioItemID: 2}}
service := ScenarioService{
clients: map[*url.URL][]scenarioItemRequester{
p1: {
{
scenarioItemID: 1,
requester: requester1,
},
{
scenarioItemID: 2,
requester: requester2,
},
},
p2: {
{
scenarioItemID: 1,
requester: requester3,
},
{
scenarioItemID: 2,
requester: requester4,
},
},
},
scenario: scenario,
ctx: ctx,
}

// Act
service.Done()

// Assert
if !requester1.DoneCalled {
t.Fatalf("Requester1 Done should be called")
}
if !requester2.DoneCalled {
t.Fatalf("Requester2 Done should be called")
}
if !requester3.DoneCalled {
t.Fatalf("Requester3 Done should be called")
}
if !requester4.DoneCalled {
t.Fatalf("Requester4 Done should be called")
}
}

func TestGetOrCreateRequesters(t *testing.T) {
t.Parallel()

Expand Down

0 comments on commit f9e738e

Please sign in to comment.