Skip to content

Commit

Permalink
Commit message
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyk committed Aug 1, 2019
1 parent 998c77a commit d629d1a
Show file tree
Hide file tree
Showing 529 changed files with 5,573 additions and 54,450 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ petstore.json
*.pdf
*.mmdb
*.cov
*.so
!testdata/*.mmdb
*.pid
coprocess_gen_test.go
Expand Down
18 changes: 4 additions & 14 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ addons:

matrix:
include:
- go: 1.10.x
- go: 1.11.x
- go: 1.9.x
env: LATEST_GO=true # run linters and report coverage

- go: 1.10.x

services:
- redis-server
Expand All @@ -31,22 +30,13 @@ install:
- go install ./...
# As of 1.9, ./... no longer includes ./vendor/...
- go install ./vendor/{golang.org/x/tools/cmd/goimports,github.com/wadey/gocovmerge,github.com/mattn/goveralls}
- go get github.com/go-swagger/go-swagger/cmd/swagger

script:
- sudo pip3 install google
- sudo pip3 install protobuf
### Needed to convert the swagger 2.0 file to openapi 3.0
### The swagger docs are actually written as per the 2.0 spec as there is no
### support for openapi 3.0 in Go - at least for now.
### https://github.com/nodesource/distributions/blob/master/README.md#debinstall
- curl -sL https://deb.nodesource.com/setup_11.x | sudo -E bash -
- sudo -E apt-get -yq --no-install-suggests --no-install-recommends $(travis_apt_get_options) install nodejs
- sudo npm install -g api-spec-converter --unsafe-perm=true --allow-root
- go build -tags 'coprocess python'
- go build -tags 'coprocess lua'
- go build -tags 'coprocess grpc'
- ./bin/ci-swagger.sh
- ./bin/ci-test.sh
- ./utils/ci-test.sh
- if [[ $LATEST_GO ]]; then goveralls -coverprofile=<(gocovmerge *.cov); fi
- ./bin/ci-benchmark.sh
- ./utils/ci-benchmark.sh
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ We'd love to accept your patches! Before we can take them, we have to jump a cou

The Tyk CLA [must be signed](https://github.com/TykTechnologies/tyk/blob/master/CLA.md) by all contributors. You will be automatically asked to sign CLA once PR will be created.

Once you are CLA'ed, we'll be able to accept your pull requests. For any issues that you face during this process, please create a GitHub issue explaining the problem and we will help get it sorted out.
Once you are CLA'ed, we'll be able to accept your pull requests. For any issues that you face during this process, please create an GitHub issue explaining the problem and we will help get it sorted out.

***NOTE***: Only original source code from you and other people that have
signed the CLA can be accepted into the repository. This policy does not
Expand Down Expand Up @@ -65,11 +65,11 @@ some bugs or smaller features. It is always better to discuss your idea with our
You need to clone Tyk from GitHub to your GOPATH folder, or alternatively you can run `go get -d github.com/TykTechnologies/tyk` which automatically downloads project to the right path.

### Building the project
You need to have working Go environment: see [golang.org](https://golang.org/doc/code.html) for more info on how Go works with code.
You need to have working Go enironment: see [golang.org](https://golang.org/doc/code.html) for more info on how Go works with code.

To build and test Tyk use built-in `go` commands: `go build` and `go test -v`. If you want to just test a subset of the project, you can pass the `-run` argument with the name of the test. Note that logs are hidden by default when running the tests, which you can override by setting `TYK_LOGLEVEL=info`.
To build and test Tyk use built-in `go` commands: `go build` and `go test -v`. If you want to just test a subset of the project, you can pass the `-run` argument with name of the test. Note that logs are hidden by default when running the tests, which you can override by setting `TYK_LOGLEVEL=info`.

Currently, in order for tests to pass, a **Redis host is required**. We know, this is terrible and should be handled with an interface, and it is, however in the current version there is a hard requirement for the application to have its default memory setup to use Redis as part of a deployment, this is to make it easier to install the application for the end-user. Future versions will work around this, or we may drop the memory requirement. The simplest way to run Redis is to use official Docker image [https://hub.docker.com/_/redis/](https://hub.docker.com/_/redis/)
Currently in order for tests to pass, a **Redis host is required**. We know, this is terrible and should be handled with an interface, and it is, however in the current version there is a hard requirement for the application to have its default memory setup to use redis as part of a deployment, this is to make it easier to install the application for the end-user. Future versions will work around this, or we may drop the memory requirement. Simplest way to run Redis is to use official Docker image [https://hub.docker.com/_/redis/](https://hub.docker.com/_/redis/)

### Adding dependencies

Expand Down
12 changes: 4 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

[![Build Status](https://travis-ci.org/TykTechnologies/tyk.svg?branch=master)](https://travis-ci.org/TykTechnologies/tyk)
[![Go Report Card](https://goreportcard.com/badge/github.com/TykTechnologies/tyk)](https://goreportcard.com/report/github.com/TykTechnologies/tyk)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FTykTechnologies%2Ftyk.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FTykTechnologies%2Ftyk?ref=badge_shield)

Tyk is a lightweight, open source API Gateway and Management Platform enables you to control who accesses your API, when they access it and how they access it. Tyk will
also record detailed analytics on how your users are interacting with your API and when things go wrong.

Go version 1.10 is required to build `master`, the current
Go version 1.9 is required to build `master`, the current
development version. Tyk is officially supported on `linux/amd64`,
`linux/i386` and `linux/arm64`.

Tests are run against both Go versions 1.10 & 1.11, however at present, only Go 1.10 is officially supported.
Tests are run against both Go versions 1.9 & 1.10, however at present, only Go 1.9 is officially supported.

## What is an API Gateway?

Expand Down Expand Up @@ -56,16 +55,13 @@ All the documentation can be found at http://tyk.io/docs/.

Tyk is released under the MPL v2.0; please see [LICENSE.md](LICENSE.md) for a full version of the license.


[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FTykTechnologies%2Ftyk.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FTykTechnologies%2Ftyk?ref=badge_large)

### Contributing

For more information about contributing PRs and issues, see [CONTRIBUTING.md](CONTRIBUTING.md).

### Roadmap

To coordinate development and be completely transparent as to where the project is going, the version roadmap for the next version, as well as proposed features
and adopted proposals can be viewed on our public [Tyk Roadmap Repository](https://github.com/TykTechnologies/tyk-roadmap).
and adopted proposals can be viewed on our public [Trello board](https://trello.com/b/59d5kAZ5/tyk-api-gateway-roadmap).

Any proposals can be made in the Github issue tracker. Proposals that are adopted will be placed into roadmap.
Any proposals can be made in the Github issue tracker. Proposals that are adopted will be placed into trello and then moved according to their status.
129 changes: 30 additions & 99 deletions TESTING.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,16 @@
Table of Contents
=================

* [Tyk testing guide](#tyk-testing-guide)
* [Initializing test server](#initializing-test-server)
* [Loading and configuring APIs](#loading-and-configuring-apis)
* [Running the tests](#running-the-tests)
* [Changing config variables](#changing-config-variables)
* [Upstream test server](#upstream-test-server)
* [Coprocess plugin testing](#coprocess-plugin-testing)
* [Creating user sessions](#creating-user-sessions)
* [Mocking dashboard](#mocking-dashboard)
* [Mocking RPC (Hybrid)](#mocking-rpc-hybrid)
* [Mocking DNS](#mocking-dns)
* [Test Framework](#test-framework)


## Tyk testing guide

When it comes to the tests, one of the main questions is how to keep balance between expressivity, extendability, repeatability and performance. There are countless discussions if you should write integration or unit tests, should your mock or not, should you write tests first or after and etc. Since you will never find the right answer, on a growing code base, multiple people start introducing own methodology and distinct test helpers. Even looking at our quite small code base, you can find like 3-4 ways to write the same test.
When it comes to the tests, one of the main questions is how to keep balance between expressivity, extendability, repeatability and performance. There are countless discussions if you should write integration or unit tests, should your mock or not, should you write tests first or after and etc. Since you will never find the right answer, on a growing code base, multiple people start introducing own methodology and distinct test helpers. Even looking at our quite small code base, I can find like 3-4 ways to write the same test. Additionally expressivity of our tests are quite bad: it is quite hard to understand what actually get tested, lot of boilerplate code not related to test logic, and amount of copy-paste growing with each test.

This document describes Tyk test framework and unified guidelines on writing tests.
In order to fix issues described above, I think it is important to have an official guide on writing the tests.

Main points of the test framework are:
This idea behind this framework is not new, and we already had pieces of it around the code. My goal was to unify all the patterns we used previously, and design a small layer on top of it, to streamline process of writing the tests.

Main points of the new framework are:
- All tests run HTTP requests though the full HTTP stack, same as user will do
- Test definition logic separated from test runner.
- Official mocks for the Dashboard, RPC, and Bundler

Framework located inside "github.com/TykTechnologies/tyk/test" package.
See its API docs https://godoc.org/github.com/TykTechnologies/tyk/test

Let’s learn by example:

```go
Expand Down Expand Up @@ -219,27 +201,30 @@ Tests are defined using new `test` package `TestCase` structure, which allows yo

```go
type TestCase struct {
Method, Path string `json:",omitempty"`
Domain string `json:",omitempty"`
Proto string `json:",omitempty"`
Code int `json:",omitempty"`
Data interface{} `json:",omitempty"`
Headers map[string]string `json:",omitempty"`
PathParams map[string]string `json:",omitempty"`
Cookies []*http.Cookie `json:",omitempty"`
Delay time.Duration `json:",omitempty"`
BodyMatch string `json:",omitempty"`
BodyMatchFunc func([]byte) bool `json:",omitempty"`
BodyNotMatch string `json:",omitempty"`
HeadersMatch map[string]string `json:",omitempty"`
HeadersNotMatch map[string]string `json:",omitempty"`
JSONMatch map[string]string `json:",omitempty"`
ErrorMatch string `json:",omitempty"`
BeforeFn func() `json:"-"`
Client *http.Client `json:"-"`

AdminAuth bool `json:",omitempty"`
ControlRequest bool `json:",omitempty"`
Method string
Path string
Domain string
// Request body, can be any object. If not string, It will be automatically serialized
Data interface{}
Headers map[string]string
PathParams map[string]string
Cookies []*http.Cookie
BeforeFn func()
// If need custom http client settings, like SSL client certificate or custom timeouts
Client *http.Client
// If true, pass valid admin-auth header
AdminAuth bool
// if Control API run on separate port (or domain), tell to run request on this listener
ControlRequest bool

// Assertions
Code int
BodyMatch string
BodyNotMatch string
HeadersMatch map[string]string
HeadersNotMatch map[string]string
// If http request returns non http error, like TLS or Timeout
ErrorMatch string
}
```

Expand Down Expand Up @@ -399,58 +384,4 @@ func TestSyncAPISpecsRPCSuccess(t *testing.T) {
### DNS mocks
Inside tests we override default network resolver to use custom DNS server mock, creating using awesome `github.com/miekg/dns` library. Domain -\> IP mapping set via map inside `helpers_test.go` file. By default you have access to domains: `localhost`, `host1.local`, `host2.local` and `host3.local`. Access to all unknown domains will cause panic.

Using DNS mock means that you are able to create tests with APIs on multiple domains, without modifying machine `/etc/hosts` file.

## Test Framework

Usage of framework described above is not limited by Tyk Gateway, and it is used across variety of Tyk projects.
The main building block is the test runner.
```go
type HTTPTestRunner struct {
Do func(*http.Request, *TestCase) (*http.Response, error)
Assert func(*http.Response, *TestCase) error
RequestBuilder func(*TestCase) (*http.Request, error)
}
func (r HTTPTestRunner) Run(t testing.TB, testCases ...TestCase) {
...
}
```
By overriding its variables, you can tune runner behavior.
For example http runner can be look like:
```
import "github.com/TykTechnologies/tyk/test"
...
baseURL := "http://example.com"
runner := test.HTTPTestRunner{
Do: func(r *http.Request, tc *TestCase) (*http.Response, error) {
return tc.Client.Do(r)
}
RequestBuilder: func(tc *TestCase) (*http.Request, error) {
tc.BaseURL = baseURL
return NewRequest(tc)
},
}
runner.Run(t, testCases...)
...
```
And Unit testing of http handlers can be:
```
import "github.com/TykTechnologies/tyk/test"
...
handler := func(wr http.RequestWriter, r *http.Request){...}
runner := test.HTTPTestRunner{
Do: func(r *http.Request, _ *TestCase) (*http.Response, error) {
rec := httptest.NewRecorder()
handler(rec, r)
return rec.Result(), nil
},
}
runner.Run(t, testCases...)
...
```

This package already exports functions for cases mentioned above:
- `func TestHttpServer(t testing.TB, baseURL string, testCases ...TestCase)`
- `func TestHttpHandler(t testing.TB, handle http.HandlerFunc, testCases ...TestCase)`
Using DNS mock means that you are able to create tests with APIs on multiple domains, without modifying machine `/etc/hosts` file.
6 changes: 3 additions & 3 deletions gateway/analytics.go → analytics.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package gateway
package main

import (
"fmt"
Expand All @@ -8,8 +8,8 @@ import (
"sync/atomic"
"time"

maxminddb "github.com/oschwald/maxminddb-golang"
msgpack "gopkg.in/vmihailenco/msgpack.v2"
"github.com/oschwald/maxminddb-golang"
"gopkg.in/vmihailenco/msgpack.v2"

"github.com/TykTechnologies/tyk/config"
"github.com/TykTechnologies/tyk/regexp"
Expand Down
10 changes: 5 additions & 5 deletions gateway/analytics_test.go → analytics_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package gateway
package main

import (
"testing"
Expand Down Expand Up @@ -27,7 +27,7 @@ func TestGeoIPLookup(t *testing.T) {
}

func TestURLReplacer(t *testing.T) {
defer ResetTestConfig()
defer resetTestConfig()
globalConf := config.Global()
globalConf.AnalyticsConfig.NormaliseUrls.Enabled = true
globalConf.AnalyticsConfig.NormaliseUrls.NormaliseUUIDs = true
Expand Down Expand Up @@ -87,7 +87,7 @@ func TestURLReplacer(t *testing.T) {
func BenchmarkURLReplacer(b *testing.B) {
b.ReportAllocs()

defer ResetTestConfig()
defer resetTestConfig()

globalConf := config.Global()
globalConf.AnalyticsConfig.NormaliseUrls.Enabled = true
Expand Down Expand Up @@ -115,7 +115,7 @@ func BenchmarkURLReplacer(b *testing.B) {
}

func TestTagHeaders(t *testing.T) {
req := TestReq(t, "GET", "/tagmeplease", nil)
req := testReq(t, "GET", "/tagmeplease", nil)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Tag-Me", "1")
req.Header.Set("X-Tag-Me2", "2")
Expand Down Expand Up @@ -159,7 +159,7 @@ func TestTagHeaders(t *testing.T) {
func BenchmarkTagHeaders(b *testing.B) {
b.ReportAllocs()

req := TestReq(b, "GET", "/tagmeplease", nil)
req := testReq(b, "GET", "/tagmeplease", nil)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Tag-Me", "1")
req.Header.Set("X-Tag-Me2", "2")
Expand Down
Loading

0 comments on commit d629d1a

Please sign in to comment.