api/internal/endpoint/handler/http/mock/handler_bench_test.go
Peter Kurfer d70ba748f5 Introduce Lifecycle for every endpoint and manage listeners in the renamed Orchestrator
- merge packages to get a more concise layout because plugins are no more and therefore there's not a lot to be exported
- fix test logger
- rework config parsing to be easier and more transparent
- remove unnecessary APIs because dynamic endpoint handling is rather a won't implement
2021-02-10 20:26:45 +00:00

155 lines
3.4 KiB
Go

package mock_test
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"io/ioutil"
"math/rand"
"net"
"net/http"
"net/url"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
"github.com/docker/go-connections/nat"
"github.com/testcontainers/testcontainers-go"
"gitlab.com/inetmock/inetmock/internal/test/integration"
)
const (
charSet = "abcdedfghijklmnopqrstABCDEFGHIJKLMNOP"
)
var (
availableExtensions = []string{"gif", "html", "ico", "jpg", "png", "txt"}
)
func init() {
rand.Seed(time.Now().Unix())
}
func Benchmark_httpHandler(b *testing.B) {
type benchmark struct {
name string
port string
scheme string
}
benchmarks := []benchmark{
{
name: "HTTP",
port: "80/tcp",
scheme: "http",
},
{
name: "HTTPS",
port: "443/tcp",
scheme: "https",
},
}
scenario := func(bm benchmark) func(bm *testing.B) {
return func(b *testing.B) {
var err error
var endpoint string
if endpoint, err = setupContainer(b, bm.scheme, bm.port); err != nil {
b.Errorf("setupContainer() error = %v", err)
}
var httpClient *http.Client
if httpClient, err = setupHTTPClient(); err != nil {
return
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
extension := availableExtensions[rand.Intn(len(availableExtensions))]
reqUrl, _ := url.Parse(fmt.Sprintf("%s/%s.%s", endpoint, randomString(15), extension))
req := &http.Request{
Method: http.MethodGet,
URL: reqUrl,
Close: false,
Host: "www.inetmock.com",
}
if resp, err := httpClient.Do(req); err != nil {
b.Error(err)
} else if resp.StatusCode != 200 {
b.Errorf("Got status code %d", resp.StatusCode)
}
}
})
}
}
for _, bm := range benchmarks {
b.Run(bm.name, scenario(bm))
}
}
func randomString(length int) (result string) {
buffer := strings.Builder{}
for i := 0; i < length; i++ {
buffer.WriteByte(charSet[rand.Intn(len(charSet))])
}
return buffer.String()
}
func setupContainer(b *testing.B, scheme, port string) (httpEndpoint string, err error) {
b.Helper()
startupCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
var inetMockContainer testcontainers.Container
if inetMockContainer, err = integration.SetupINetMockContainer(startupCtx, b, port); err != nil {
return
}
httpEndpoint, err = inetMockContainer.PortEndpoint(startupCtx, nat.Port(port), scheme)
return
}
func setupHTTPClient() (client *http.Client, err error) {
_, fileName, _, _ := runtime.Caller(0)
var repoRoot string
if repoRoot, err = filepath.Abs(filepath.Join(filepath.Dir(fileName), "..", "..", "..", "..", "..")); err != nil {
return
}
var demoCABytes []byte
if demoCABytes, err = ioutil.ReadFile(filepath.Join(repoRoot, "assets", "demoCA", "ca.pem")); err != nil {
return
}
rootCaPool := x509.NewCertPool()
if !rootCaPool.AppendCertsFromPEM(demoCABytes) {
err = errors.New("failed to add CA key")
return
}
client = &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
TLSClientConfig: &tls.Config{
RootCAs: rootCaPool,
},
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}
return
}