diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 27d62a6e4de..c90ecd2384c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,6 +5,7 @@ # Core API Squad ownership of CI test pipeline and developer tooling. +/bin/ @TykTechnologies/core-api-squad .github/workflows/ci-tests.yml @TykTechnologies/core-api-squad .github/workflows/release-tests.yml @TykTechnologies/core-api-squad /.taskfiles/ @TykTechnologies/core-api-squad diff --git a/bin/ci-benchmark.sh b/bin/ci-benchmark.sh index 93ad8a4d2da..9333213424c 100755 --- a/bin/ci-benchmark.sh +++ b/bin/ci-benchmark.sh @@ -1,7 +1,17 @@ #!/bin/bash - set -e -benchRegex=${1:-.} +# Build gw test binary +go test -o gateway.test -c ./gateway + +BENCHMARKS=$(./gateway.test -test.list=Bench.+) -TYK_LOGLEVEL= go test -run=NONE -bench=$benchRegex || fatal "go test -run=NONE -bench=$benchRegex" +for benchmark in $BENCHMARKS; do + echo $benchmark + benchRegex="^${benchmark}$" + ./gateway.test -test.run=^$ -test.bench=$benchRegex -test.count=1 \ + -test.benchtime 30s -test.benchmem \ + -test.cpuprofile=coverage/$benchmark-cpu.out \ + -test.memprofile=coverage/$benchmark-mem.out \ + -test.trace=coverage/$benchmark-trace.out +done diff --git a/gateway/api_definition_test.go b/gateway/api_definition_test.go index 2444332b9db..88e2eb3c368 100644 --- a/gateway/api_definition_test.go +++ b/gateway/api_definition_test.go @@ -1024,6 +1024,8 @@ func (ts *Test) testPrepareDefaultVersion() (string, *APISpec) { spec.Proxy.ListenPath = "/" spec.UseKeylessAccess = false + spec.DisableRateLimit = true + spec.DisableQuota = true })[0] return CreateSession(ts.Gw, func(s *user.SessionState) { diff --git a/gateway/event_system_test.go b/gateway/event_system_test.go index 43f850f1ab8..ec603547d98 100644 --- a/gateway/event_system_test.go +++ b/gateway/event_system_test.go @@ -173,6 +173,8 @@ func TestInitGenericEventHandlers(t *testing.T) { } func BenchmarkInitGenericEventHandlers(b *testing.B) { + b.Skip() + ts := StartTest(nil) defer ts.Close() diff --git a/gateway/mw_basic_auth_test.go b/gateway/mw_basic_auth_test.go index 48b311e461b..2a35743c168 100644 --- a/gateway/mw_basic_auth_test.go +++ b/gateway/mw_basic_auth_test.go @@ -21,7 +21,6 @@ func genAuthHeader(username, password string) string { } func (ts *Test) testPrepareBasicAuth(cacheDisabled bool) *user.SessionState { - session := CreateStandardSession() session.BasicAuthData.Password = "password" session.AccessRights = map[string]user.AccessDefinition{"test": {APIID: "test", Versions: []string{"v1"}}} @@ -33,6 +32,8 @@ func (ts *Test) testPrepareBasicAuth(cacheDisabled bool) *user.SessionState { spec.UseKeylessAccess = false spec.Proxy.ListenPath = "/" spec.OrgID = "default" + spec.DisableRateLimit = true + spec.DisableQuota = true }) return session diff --git a/gateway/mw_jwt_test.go b/gateway/mw_jwt_test.go index 766c11bcf17..af27d22373e 100644 --- a/gateway/mw_jwt_test.go +++ b/gateway/mw_jwt_test.go @@ -141,6 +141,8 @@ func (ts *Test) prepareGenericJWTSession(testName string, method string, claimNa spec.EnableJWT = true spec.Proxy.ListenPath = "/" spec.JWTSkipKid = ApiSkipKid + spec.DisableRateLimit = true + spec.DisableQuota = true if claimName != KID { spec.JWTIdentityBaseField = claimName @@ -471,6 +473,8 @@ func (ts *Test) prepareJWTSessionRSAWithRawSourceOnWithClientID(isBench bool) st spec.JWTIdentityBaseField = "user_id" spec.JWTClientIDBaseField = "azp" spec.Proxy.ListenPath = "/" + spec.DisableRateLimit = true + spec.DisableQuota = true })[0] policyID := ts.CreatePolicy(func(p *user.Policy) { @@ -552,6 +556,8 @@ func (ts *Test) prepareJWTSessionRSAWithRawSource() string { spec.JWTIdentityBaseField = "user_id" spec.JWTPolicyFieldName = "policy_id" spec.Proxy.ListenPath = "/" + spec.DisableRateLimit = true + spec.DisableQuota = true }) pID := ts.CreatePolicy(func(p *user.Policy) { @@ -1511,6 +1517,8 @@ func (ts *Test) prepareJWTSessionRSAWithJWK() string { spec.JWTIdentityBaseField = "user_id" spec.JWTPolicyFieldName = "policy_id" spec.Proxy.ListenPath = "/" + spec.DisableRateLimit = true + spec.DisableQuota = true }) pID := ts.CreatePolicy(func(p *user.Policy) { @@ -1579,6 +1587,8 @@ func (ts *Test) prepareJWTSessionRSAWithEncodedJWK() (*APISpec, string) { spec.JWTIdentityBaseField = "user_id" spec.JWTPolicyFieldName = "policy_id" spec.Proxy.ListenPath = "/" + spec.DisableRateLimit = true + spec.DisableQuota = true })[0] pID := ts.CreatePolicy(func(p *user.Policy) { diff --git a/gateway/mw_transform_test.go b/gateway/mw_transform_test.go index 009c484dd57..da242ec6af1 100644 --- a/gateway/mw_transform_test.go +++ b/gateway/mw_transform_test.go @@ -37,11 +37,10 @@ func TestTransformNonAscii(t *testing.T) { ts := StartTest(nil) defer ts.Close() - ad := apidef.APIDefinition{} - spec := APISpec{APIDefinition: &ad} - spec.EnableContextVars = false - base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw} - base.Spec.EnableContextVars = false + ad := &apidef.APIDefinition{} + spec := &APISpec{APIDefinition: ad} + base := &BaseMiddleware{Spec: spec, Gw: ts.Gw} + transform := TransformMiddleware{base} if err := transformBody(r, tmeta, &transform); err != nil { @@ -64,15 +63,16 @@ func BenchmarkTransformNonAscii(b *testing.B) { ts := StartTest(nil) defer ts.Close() - spec := APISpec{} - base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw} - base.Spec.EnableContextVars = false - transform := TransformMiddleware{base} + ad := &apidef.APIDefinition{} + spec := &APISpec{APIDefinition: ad} + base := &BaseMiddleware{Spec: spec, Gw: ts.Gw} + + transform := &TransformMiddleware{base} for i := 0; i < b.N; i++ { r := TestReq(b, "GET", "/", in) - if err := transformBody(r, tmeta, &transform); err != nil { + if err := transformBody(r, tmeta, transform); err != nil { b.Fatalf("wanted nil error, got %v", err) } } @@ -90,10 +90,10 @@ func TestTransformXMLCrash(t *testing.T) { ts := StartTest(nil) defer ts.Close() - ad := apidef.APIDefinition{} - spec := APISpec{APIDefinition: &ad} - base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw} - base.Spec.EnableContextVars = false + ad := &apidef.APIDefinition{} + spec := &APISpec{APIDefinition: ad} + base := &BaseMiddleware{Spec: spec, Gw: ts.Gw} + transform := TransformMiddleware{base} if err := transformBody(r, tmeta, &transform); err == nil { @@ -145,10 +145,10 @@ func TestTransformJSONMarshalXMLInput(t *testing.T) { ts := StartTest(nil) defer ts.Close() - ad := apidef.APIDefinition{} - spec := APISpec{APIDefinition: &ad} - base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw} - base.Spec.EnableContextVars = false + ad := &apidef.APIDefinition{} + spec := &APISpec{APIDefinition: ad} + base := &BaseMiddleware{Spec: spec, Gw: ts.Gw} + transform := TransformMiddleware{base} if err := transformBody(r, tmeta, &transform); err != nil { @@ -172,10 +172,10 @@ func TestTransformJSONMarshalJSONInput(t *testing.T) { ts := StartTest(nil) defer ts.Close() - ad := apidef.APIDefinition{} - spec := APISpec{APIDefinition: &ad} - base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw} - base.Spec.EnableContextVars = false + ad := &apidef.APIDefinition{} + spec := &APISpec{APIDefinition: ad} + base := &BaseMiddleware{Spec: spec, Gw: ts.Gw} + transform := TransformMiddleware{base} if err := transformBody(r, tmeta, &transform); err != nil { @@ -211,10 +211,10 @@ func TestTransformJSONMarshalJSONArrayInput(t *testing.T) { ts := StartTest(nil) defer ts.Close() - ad := apidef.APIDefinition{} - spec := APISpec{APIDefinition: &ad} - base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw} - base.Spec.EnableContextVars = false + ad := &apidef.APIDefinition{} + spec := &APISpec{APIDefinition: ad} + base := &BaseMiddleware{Spec: spec, Gw: ts.Gw} + transform := TransformMiddleware{base} if err := transformBody(r, tmeta, &transform); err != nil { @@ -236,9 +236,10 @@ func BenchmarkTransformJSONMarshal(b *testing.B) { ts := StartTest(nil) defer ts.Close() - spec := APISpec{} - base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw} - base.Spec.EnableContextVars = false + ad := &apidef.APIDefinition{} + spec := &APISpec{APIDefinition: ad} + base := &BaseMiddleware{Spec: spec, Gw: ts.Gw} + transform := TransformMiddleware{base} for i := 0; i < b.N; i++ { @@ -258,10 +259,10 @@ func TestTransformXMLMarshal(t *testing.T) { ts := StartTest(nil) defer ts.Close() - ad := apidef.APIDefinition{} - spec := APISpec{APIDefinition: &ad} - base := &BaseMiddleware{Spec: &spec, Gw: ts.Gw} - base.Spec.EnableContextVars = false + ad := &apidef.APIDefinition{} + spec := &APISpec{APIDefinition: ad} + base := &BaseMiddleware{Spec: spec, Gw: ts.Gw} + transform := TransformMiddleware{base} if err := transformBody(r, tmeta, &transform); err != nil { diff --git a/gateway/mw_version_check_test.go b/gateway/mw_version_check_test.go index 46da7580a89..ce7e16edd1e 100644 --- a/gateway/mw_version_check_test.go +++ b/gateway/mw_version_check_test.go @@ -20,6 +20,8 @@ func (ts *Test) testPrepareVersioning() (string, string) { spec.VersionDefinition.Location = "header" spec.VersionDefinition.Key = "version" spec.Proxy.ListenPath = "/" + spec.DisableRateLimit = true + spec.DisableQuota = true spec.VersionData.Versions["expired"] = apidef.VersionInfo{ Name: "expired", Expires: "2006-01-02 15:04", diff --git a/gateway/oauth_manager_test.go b/gateway/oauth_manager_test.go index ecc74e6d474..52aabdd10ab 100644 --- a/gateway/oauth_manager_test.go +++ b/gateway/oauth_manager_test.go @@ -1401,6 +1401,8 @@ func TestPurgeOAuthClientTokens(t *testing.T) { } func BenchmarkPurgeLapsedOAuthTokens(b *testing.B) { + b.Skip() + conf := func(globalConf *config.Config) { // set tokens to be expired after 1 second globalConf.OauthTokenExpire = 1 diff --git a/gateway/res_handler_header_injector_test.go b/gateway/res_handler_header_injector_test.go index cc9c1f2d961..9530058f385 100644 --- a/gateway/res_handler_header_injector_test.go +++ b/gateway/res_handler_header_injector_test.go @@ -16,6 +16,8 @@ func testPrepareResponseHeaderInjection(ts *Test) { spec.UseKeylessAccess = true spec.Proxy.ListenPath = "/" spec.OrgID = "default" + spec.DisableRateLimit = true + spec.DisableQuota = true UpdateAPIVersion(spec, "v1", func(v *apidef.VersionInfo) { v.UseExtendedPaths = true json.Unmarshal([]byte(`[ @@ -136,10 +138,6 @@ func BenchmarkResponseHeaderInjection(b *testing.B) { } deleteHeaders := map[string]string{ - "X-Tyk-Test": "1", - cachedResponseHeader: "1", - } - deleteHeadersCached := map[string]string{ "X-Tyk-Test": "1", } @@ -151,9 +149,12 @@ func BenchmarkResponseHeaderInjection(b *testing.B) { {Method: "GET", Path: "/test-with-slash", HeadersMatch: addHeaders, HeadersNotMatch: deleteHeaders}, {Method: "GET", Path: "/test-no-slash", HeadersMatch: addHeaders, HeadersNotMatch: deleteHeaders}, {Method: "GET", Path: "/rewrite-test", HeadersMatch: addHeaders, HeadersNotMatch: deleteHeaders, BodyMatch: `"Url":"/newpath"`}, - {Method: "GET", Path: "/rewrite-test", HeadersMatch: addHeadersCached, HeadersNotMatch: deleteHeadersCached, BodyMatch: `"X-I-Am":"Request"`}, - {Method: "GET", Path: "/rewrite-test", HeadersMatch: addHeadersCached, HeadersNotMatch: deleteHeadersCached, BodyMatch: userAgent}, + {Method: "GET", Path: "/rewrite-test", HeadersMatch: addHeadersCached, HeadersNotMatch: deleteHeaders, BodyMatch: `"X-I-Am":"Request"`}, + {Method: "GET", Path: "/rewrite-test", HeadersMatch: addHeadersCached, HeadersNotMatch: deleteHeaders, BodyMatch: userAgent}, }...) + + // It's a loop, first time won't be cached. + addHeaders[cachedResponseHeader] = "1" } } diff --git a/gateway/session_manager.go b/gateway/session_manager.go index c685ae4b4fe..95a734d3ddd 100644 --- a/gateway/session_manager.go +++ b/gateway/session_manager.go @@ -58,6 +58,9 @@ type SessionLimiter struct { smoothing *rate.Smoothing } +// Encourage reuse in NewSessionLimiter. +var sessionLimiterBucketStore = memorycache.New() + // NewSessionLimiter initializes the session limiter. // // The session limiter initializes the storage required for rate limiters. @@ -70,7 +73,7 @@ func NewSessionLimiter(ctx context.Context, conf *config.Config, drlManager *drl ctx: ctx, drlManager: drlManager, config: conf, - bucketStore: memorycache.New(), + bucketStore: sessionLimiterBucketStore, } log.Infof("[RATELIMIT] %s", conf.RateLimit.String())