-
-
Notifications
You must be signed in to change notification settings - Fork 234
/
main_test.go
157 lines (149 loc) · 3.97 KB
/
main_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package main
import (
"bytes"
"log"
"net/http"
"net/http/httptest"
"os"
"testing"
txhttp "github.com/corazawaf/coraza/v3/http"
)
func setupTestServer(t *testing.T) *httptest.Server {
t.Helper()
waf := createWAF()
return httptest.NewServer(txhttp.WrapHandler(waf, http.HandlerFunc(exampleHandler)))
}
func doGetRequest(t *testing.T, getPath string) int {
t.Helper()
resp, err := http.Get(getPath)
if err != nil {
log.Fatalln(err)
}
resp.Body.Close()
return resp.StatusCode
}
func doPostRequest(t *testing.T, postPath string, data []byte) int {
t.Helper()
resp, err := http.Post(postPath, "application/x-www-form-urlencoded", bytes.NewBuffer(data))
if err != nil {
log.Fatalln(err)
}
resp.Body.Close()
return resp.StatusCode
}
func TestHttpServer(t *testing.T) {
tests := []struct {
name string
path string
expStatus int
envVars map[string]string
body []byte // if body is populated, POST request is sent
}{
{"negative", "/", 200, nil, nil},
{"positive for query parameter", "/?id=0", 403, nil, nil},
{
"positive for response body",
"/",
403,
map[string]string{
"DIRECTIVES_FILE": "./testdata/response-body.conf",
"RESPONSE_BODY": "creditcard",
},
nil,
},
{
"positive for response header",
"/",
403,
map[string]string{
"DIRECTIVES_FILE": "./testdata/response-headers.conf",
"RESPONSE_HEADERS": "foo:bar",
},
nil,
},
{
"negative for request body process partial (payload beyond processed body)",
"/",
200,
map[string]string{
"DIRECTIVES_FILE": "./testdata/request-body-limits-processpartial.conf",
},
[]byte("beyond the limit script"),
},
{
"positive for response body limit reject",
"/",
413,
map[string]string{
"DIRECTIVES_FILE": "./testdata/response-body-limits-reject.conf",
"RESPONSE_BODY": "response body beyond the limit",
},
nil,
},
}
// Perform tests
for _, tc := range tests {
tt := tc
var statusCode int
t.Run(tt.name, func(t *testing.T) {
if len(tt.envVars) > 0 {
for k, v := range tt.envVars {
os.Setenv(k, v)
defer os.Unsetenv(k)
}
}
// Spin up the test server
testServer := setupTestServer(t)
defer testServer.Close()
if tt.body == nil {
statusCode = doGetRequest(t, testServer.URL+tt.path)
} else {
statusCode = doPostRequest(t, testServer.URL+tt.path, tt.body)
}
if want, have := tt.expStatus, statusCode; want != have {
t.Errorf("Unexpected status code, want: %d, have: %d", want, have)
}
})
}
}
// TestHttpServerConcurrent is meant to be run with the "-race" flag.
// Multiple requests are sent concurrently to the server and race conditions are checked.
// It is especially useful to ensure that rules and their metadata are not edited in an unsafe way
// after parsing time.
func TestHttpServerConcurrent(t *testing.T) {
tests := []struct {
name string
path string
expStatus int
body []byte // if body is populated, POST request is sent
}{
{"negative", "/", 200, nil},
{"positive for query parameter 1", "/?id=0", 403, nil},
{"positive for request body", "/", 403, []byte("password")},
}
// Spin up the test server with default.conf configuration
testServer := setupTestServer(t)
defer testServer.Close()
// a t.Run wraps all the concurrent tests and permits to close the server only once test is done
// See https://github.com/golang/go/issues/17791
t.Run("concurrent test", func(t *testing.T) {
for _, tc := range tests {
tt := tc
for i := 0; i < 10; i++ {
// Each test case is added 10 times and then run concurrently
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
var statusCode int
if tt.body == nil {
statusCode = doGetRequest(t, testServer.URL+tt.path)
} else {
statusCode = doPostRequest(t, testServer.URL+tt.path, tt.body)
}
if want, have := tt.expStatus, statusCode; want != have {
t.Errorf("Unexpected status code, want: %d, have: %d", want, have)
}
})
}
}
})
}