Skip to content

Commit

Permalink
e2e: add rate limit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Choraden committed Sep 13, 2023
1 parent e521325 commit 9b88eb0
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
10 changes: 10 additions & 0 deletions e2e/forwarder/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,16 @@ func (s *Service) WithDenyDomainExclude(domains ...string) *Service {
return s
}

func (s *Service) WithReadLimit(limit string) *Service {
s.Environment["FORWARDER_READ_LIMIT"] = limit
return s
}

func (s *Service) WithWriteLimit(limit string) *Service {
s.Environment["FORWARDER_WRITE_LIMIT"] = limit
return s
}

func (s *Service) Service() *compose.Service {
return (*compose.Service)(s)
}
Expand Down
28 changes: 28 additions & 0 deletions e2e/setups.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func AllSetups() []setup.Setup {
SetupFlagInsecure(l)
SetupFlagMITM(l)
SetupFlagDenyDomain(l)
SetupFlagRateLimit(l)
SetupSC2450(l)

return l.Build()
Expand Down Expand Up @@ -360,6 +361,33 @@ func SetupFlagDenyDomain(l *setupList) {
)
}

func SetupFlagRateLimit(l *setupList) {
l.Add(
setup.Setup{
Name: "flag-read-limit",
Compose: compose.NewBuilder().
AddService(
forwarder.HttpbinService()).
AddService(
forwarder.ProxyService().
WithReadLimit("1M")).
MustBuild(),
Run: "^TestFlagReadLimit$",
},
setup.Setup{
Name: "flag-write-limit",
Compose: compose.NewBuilder().
AddService(
forwarder.HttpbinService()).
AddService(
forwarder.ProxyService().
WithWriteLimit("1M")).
MustBuild(),
Run: "^TestFlagWriteLimit$",
},
)
}

func SetupSC2450(l *setupList) {
l.Add(setup.Setup{
Name: "sc-2450",
Expand Down
50 changes: 50 additions & 0 deletions e2e/tests/flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
package tests

import (
"fmt"
"net"
"net/http"
"sync"
"testing"
"time"
)

func TestFlagProxyLocalhost(t *testing.T) {
Expand Down Expand Up @@ -94,3 +97,50 @@ func TestFlagDenyDomain(t *testing.T) {
newClient(t, "https://www.google.com").GET("/").ExpectStatus(http.StatusForbidden)
newClient(t, httpbin).GET("/status/200").ExpectStatus(http.StatusOK)
}

func TestFlagWriteLimit(t *testing.T) {
size := 10 * 1024 * 1024 // 10MiB
// It streams 10MiB, the write limit is 1MB/s, but minimum burst is 4MiB, so it should take approximately 6 seconds.
expectedTime := 6 * time.Second

ts := time.Now()
c := newClient(t, httpbin)
c.GET(fmt.Sprintf("/stream-bytes/%d", size)).ExpectStatus(http.StatusOK).ExpectBodySize(size)
if elapsed := time.Since(ts); elapsed.Round(time.Second) != expectedTime {
t.Fatalf("Expected request to take approximately %s, took %s", expectedTime, elapsed)
}
}

func TestFlagReadLimit(t *testing.T) {
var (
workers = 4
requests = 500
// GET /status/200 requests with 140 `X-Test-Read-Limit` headers takes around 4KB.
// The read limit is 1MB/s, but minimum burst is 4MiB,
// 4 * 500 * 4000 = 8000000 bytes, so it should take approximately 4 seconds.
expectedTime = 4 * time.Second

wg sync.WaitGroup
)

ts := time.Now()
for i := 0; i < workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
c := newClient(t, httpbin)
for j := 0; j < requests; j++ {
c.GET("/status/200", func(req *http.Request) {
for i := 0; i < 140; i++ {
req.Header.Add(fmt.Sprintf("X-Test-Read-Limit-%v", i), "test")
}
}).ExpectStatus(http.StatusOK)
}
}()
}
wg.Wait()

if elapsed := time.Since(ts); elapsed.Round(time.Second) != expectedTime {
t.Fatalf("Expected request to take approximately %s, took %s", expectedTime, elapsed)
}
}

0 comments on commit 9b88eb0

Please sign in to comment.