Skip to content

Commit

Permalink
coprocess: enhance tests with session metadata checks
Browse files Browse the repository at this point in the history
  • Loading branch information
matiasinsaurralde authored and buger committed Jun 13, 2018
1 parent 28a8100 commit cf3c47b
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 14 deletions.
128 changes: 114 additions & 14 deletions coprocess_grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io/ioutil"
"net"
"net/http"
"strings"
"testing"

"context"
Expand All @@ -18,6 +19,7 @@ import (
"github.com/TykTechnologies/tyk/config"
"github.com/TykTechnologies/tyk/coprocess"
"github.com/TykTechnologies/tyk/test"
"github.com/TykTechnologies/tyk/user"
)

const (
Expand All @@ -36,6 +38,56 @@ func (d *dispatcher) Dispatch(ctx context.Context, object *coprocess.Object) (*c
object.Request.SetHeaders = map[string]string{
testHeaderName: testHeaderValue,
}
case "testPostHook1":
testKeyValue, ok := object.Session.Metadata["testkey"]
if !ok {
object.Request.ReturnOverrides.ResponseError = "'testkey' not found in session metadata"
object.Request.ReturnOverrides.ResponseCode = 400
break
}
jsonObject := make(map[string]string)
if err := json.Unmarshal([]byte(testKeyValue), &jsonObject); err != nil {
object.Request.ReturnOverrides.ResponseError = "couldn't decode 'testkey' nested value"
object.Request.ReturnOverrides.ResponseCode = 400
break
}
nestedKeyValue, ok := jsonObject["nestedkey"]
if !ok {
object.Request.ReturnOverrides.ResponseError = "'nestedkey' not found in JSON object"
object.Request.ReturnOverrides.ResponseCode = 400
break
}
if nestedKeyValue != "nestedvalue" {
object.Request.ReturnOverrides.ResponseError = "'nestedvalue' value doesn't match"
object.Request.ReturnOverrides.ResponseCode = 400
break
}
testKey2Value, ok := object.Session.Metadata["testkey2"]
if !ok {
object.Request.ReturnOverrides.ResponseError = "'testkey' not found in session metadata"
object.Request.ReturnOverrides.ResponseCode = 400
break
}
if testKey2Value != "testvalue" {
object.Request.ReturnOverrides.ResponseError = "'testkey2' value doesn't match"
object.Request.ReturnOverrides.ResponseCode = 400
break
}

// Check for compatibility (object.Metadata should contain the same keys as object.Session.Metadata)
for k, v := range object.Metadata {
sessionKeyValue, ok := object.Session.Metadata[k]
if !ok {
object.Request.ReturnOverrides.ResponseError = k + " not found in object.Session.Metadata"
object.Request.ReturnOverrides.ResponseCode = 400
break
}
if strings.Compare(sessionKeyValue, v) != 0 {
object.Request.ReturnOverrides.ResponseError = k + " doesn't match value in object.Session.Metadata"
object.Request.ReturnOverrides.ResponseCode = 400
break
}
}
}
return object, nil
}
Expand All @@ -50,13 +102,14 @@ func newTestGRPCServer() (s *grpc.Server) {
return s
}

func loadTestGRPCSpec() *APISpec {
spec := buildAndLoadAPI(func(spec *APISpec) {
spec.APIID = "999999"
func loadTestGRPCAPIs() {
buildAndLoadAPI(func(spec *APISpec) {
spec.APIID = "1"
spec.OrgID = "default"
spec.Auth = apidef.Auth{
AuthHeaderName: "authorization",
}
spec.UseKeylessAccess = false
spec.VersionData = struct {
NotVersioned bool `bson:"not_versioned" json:"not_versioned"`
DefaultVersion string `bson:"default_version" json:"default_version"`
Expand All @@ -77,9 +130,34 @@ func loadTestGRPCSpec() *APISpec {
},
Driver: apidef.GrpcDriver,
}
})[0]

return spec
}, func(spec *APISpec) {
spec.APIID = "2"
spec.OrgID = "default"
spec.Auth = apidef.Auth{
AuthHeaderName: "authorization",
}
spec.UseKeylessAccess = false
spec.VersionData = struct {
NotVersioned bool `bson:"not_versioned" json:"not_versioned"`
DefaultVersion string `bson:"default_version" json:"default_version"`
Versions map[string]apidef.VersionInfo `bson:"versions" json:"versions"`
}{
NotVersioned: true,
Versions: map[string]apidef.VersionInfo{
"v1": {
Name: "v1",
},
},
}
spec.Proxy.ListenPath = "/grpc-test-api-2/"
spec.Proxy.StripListenPath = true
spec.CustomMiddleware = apidef.MiddlewareSection{
Post: []apidef.MiddlewareDefinition{
{Name: "testPostHook1"},
},
Driver: apidef.GrpcDriver,
}
})
}

func startTykWithGRPC() (*tykTestServer, *grpc.Server) {
Expand All @@ -95,8 +173,8 @@ func startTykWithGRPC() (*tykTestServer, *grpc.Server) {
}
ts := newTykTestServer(tykTestServerConfig{coprocessConfig: cfg})

// Load a test API:
loadTestGRPCSpec()
// Load test APIs:
loadTestGRPCAPIs()
return &ts, grpcServer
}

Expand All @@ -105,11 +183,20 @@ func TestGRPCDispatch(t *testing.T) {
defer ts.Close()
defer grpcServer.Stop()

keyID := createSession(func(s *user.SessionState) {
s.MetaData = map[string]interface{}{
"testkey": map[string]interface{}{"nestedkey": "nestedvalue"},
"testkey2": "testvalue",
}
})
headers := map[string]string{"authorization": keyID}

t.Run("Pre Hook with SetHeaders", func(t *testing.T) {
res, err := ts.Run(t, test.TestCase{
Path: "/grpc-test-api/",
Method: http.MethodGet,
Code: http.StatusOK,
Path: "/grpc-test-api/",
Method: http.MethodGet,
Code: http.StatusOK,
Headers: headers,
})
if err != nil {
t.Fatalf("Request failed: %s", err.Error())
Expand All @@ -132,21 +219,34 @@ func TestGRPCDispatch(t *testing.T) {
}
})

t.Run("Post Hook with metadata", func(t *testing.T) {
ts.Run(t, test.TestCase{
Path: "/grpc-test-api-2/",
Method: http.MethodGet,
Code: http.StatusOK,
Headers: headers,
})
})

}

func BenchmarkGRPCDispatch(b *testing.B) {
ts, grpcServer := startTykWithGRPC()
defer ts.Close()
defer grpcServer.Stop()

keyID := createSession(func(s *user.SessionState) {})
headers := map[string]string{"authorization": keyID}

b.Run("Pre Hook with SetHeaders", func(b *testing.B) {
path := "/grpc-test-api/"
b.ReportAllocs()
for i := 0; i < b.N; i++ {
ts.Run(b, test.TestCase{
Path: path,
Method: http.MethodGet,
Code: http.StatusOK,
Path: path,
Method: http.MethodGet,
Code: http.StatusOK,
Headers: headers,
})
}
})
Expand Down
73 changes: 73 additions & 0 deletions coprocess_python_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/TykTechnologies/tyk/config"
"github.com/TykTechnologies/tyk/test"
"github.com/TykTechnologies/tyk/user"
)

var pythonBundleWithAuthCheck = map[string]string{
Expand Down Expand Up @@ -42,6 +43,51 @@ def MyAuthHook(request, session, metadata, spec):
`,
}

var pythonBundleWithPostHook = map[string]string{
"manifest.json": `
{
"file_list": [
"middleware.py"
],
"custom_middleware": {
"driver": "python",
"post": [{
"name": "MyPostHook"
}]
}
}
`,
"middleware.py": `
from tyk.decorators import *
from gateway import TykGateway as tyk
import json
@Hook
def MyPostHook(request, session, spec):
print("called", session.metadata)
if "testkey" not in session.metadata.keys():
request.object.return_overrides.response_code = 400
request.object.return_overrides.response_error = "'testkey' not found in metadata"
return request, session
nested_data = json.loads(session.metadata["testkey"])
if "nestedkey" not in nested_data:
request.object.return_overrides.response_code = 400
request.object.return_overrides.response_error = "'nestedkey' not found in nested metadata"
return request, session
if "stringkey" not in session.metadata.keys():
request.object.return_overrides.response_code = 400
request.object.return_overrides.response_error = "'stringkey' not found in metadata"
return request, session
stringkey = session.metadata["stringkey"]
if stringkey != "testvalue":
request.object.return_overrides.response_code = 400
request.object.return_overrides.response_error = "'stringkey' value doesn't match"
return request, session
return request, session
`,
}

func TestPythonBundles(t *testing.T) {
ts := newTykTestServer(tykTestServerConfig{
coprocessConfig: config.CoProcessConfig{
Expand All @@ -50,6 +96,7 @@ func TestPythonBundles(t *testing.T) {
defer ts.Close()

bundleID := registerBundle("python_with_auth_check", pythonBundleWithAuthCheck)
bundleID2 := registerBundle("python_with_post_hook", pythonBundleWithPostHook)

t.Run("Single-file bundle with authentication hook", func(t *testing.T) {
buildAndLoadAPI(func(spec *APISpec) {
Expand All @@ -70,4 +117,30 @@ func TestPythonBundles(t *testing.T) {
{Path: "/test-api/", Code: 403, Headers: invalidAuth},
}...)
})

t.Run("Single-file bundle with post hook", func(t *testing.T) {

keyID := createSession(func(s *user.SessionState) {
s.MetaData = map[string]interface{}{
"testkey": map[string]interface{}{"nestedkey": "nestedvalue"},
"stringkey": "testvalue",
}
})

buildAndLoadAPI(func(spec *APISpec) {
spec.Proxy.ListenPath = "/test-api-2/"
spec.UseKeylessAccess = false
spec.EnableCoProcessAuth = false
spec.CustomMiddlewareBundle = bundleID2
spec.VersionData.NotVersioned = true
})

time.Sleep(1 * time.Second)

auth := map[string]string{"Authorization": keyID}

ts.Run(t, []test.TestCase{
{Path: "/test-api-2/", Code: 200, Headers: auth},
}...)
})
}

0 comments on commit cf3c47b

Please sign in to comment.