github.com/TykTechnologies/tyk/test
No package summary is available.
Package
Files: 10. Third party imports: 3. Imports from organisation: 0. Tests: 0. Benchmarks: 0.
Constants
const maxRetryCount = 2
Vars
var (
DomainsToAddresses = map[string][]string{
"host1.": {"127.0.0.1"},
"host2.": {"127.0.0.1"},
"host3.": {"127.0.0.1"},
}
DomainsToIgnore = []string{
"redis.",
"tyk-redis.",
"mongo.", // For dashboard integration tests
"tyk-mongo.",
}
)
var buflogger *BufferedLogger
var (
// exclusiveTestMu is used by Exclusive()
exclusiveTestMu sync.Mutex
)
var initOnce sync.Once
var once sync.Once
var retryReasons = []string{
"broken pipe",
"protocol wrong type for socket",
"connection reset by peer",
}
Types
BufferedLog
BufferedLog is the struct that holds the log entry.
| Field name | Field type | Comment |
|---|---|---|
| Message |
|
No comment on field. |
| Time |
|
No comment on field. |
| Level |
|
No comment on field. |
type BufferedLog struct {
Message string `json:"message"`
Time time.Time `json:"time"`
Level logrus.Level `json:"level"`
}
BufferedLogger
BufferedLogger is the struct that holds the logger and the buffer.
| Field name | Field type | Comment |
|---|---|---|
|
No comment on field. | |
| bufferingFormatter |
|
No comment on field. |
type BufferedLogger struct {
*logrus.Logger
bufferingFormatter *BufferingFormatter
}
BufferingFormatter
BufferingFormatter is the struct that holds the buffer of the logs.
| Field name | Field type | Comment |
|---|---|---|
| bufferMutex |
|
No comment on field. |
| buffer |
|
No comment on field. |
type BufferingFormatter struct {
bufferMutex sync.Mutex
buffer []*BufferedLog
}
DnsMockHandle
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| id |
|
No comment on field. |
| mockServer |
|
No comment on field. |
| ShutdownDnsMock |
|
No comment on field. |
type DnsMockHandle struct {
id string
mockServer *dns.Server
ShutdownDnsMock func() error
}
HTTPTestRunner
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| Do |
|
No comment on field. |
| Assert |
|
No comment on field. |
| RequestBuilder |
|
No comment on field. |
type HTTPTestRunner struct {
Do func(*http.Request, *TestCase) (*http.Response, error)
Assert func(*http.Response, *TestCase) error
RequestBuilder func(*TestCase) (*http.Request, error)
}
Monitor
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| Alloc |
|
No comment on field. |
| NumGC |
|
No comment on field. |
| NumGoroutine |
|
No comment on field. |
type Monitor struct {
Alloc,
TotalAlloc,
Sys,
Mallocs,
Frees,
LiveObjects,
PauseTotalNs uint64
NumGC uint32
NumGoroutine int
}
TCPTestCase
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| Action |
|
No comment on field. |
| Payload |
|
No comment on field. |
| ErrorMatch |
|
No comment on field. |
type TCPTestCase struct {
Action string //read or write
Payload string
ErrorMatch string
}
TCPTestRunner
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| UseSSL |
|
No comment on field. |
| Target |
|
No comment on field. |
| Hostname |
|
No comment on field. |
| TLSClientConfig |
|
No comment on field. |
type TCPTestRunner struct {
UseSSL bool
Target string
Hostname string
TLSClientConfig *tls.Config
}
TestCase
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| Host |
|
No comment on field. |
| Method |
|
No comment on field. |
| Path |
|
No comment on field. |
| BaseURL |
|
No comment on field. |
| Domain |
|
No comment on field. |
| Proto |
|
No comment on field. |
| Code |
|
Code is the expected HTTP response status code. |
| Data |
|
No comment on field. |
| Headers |
|
No comment on field. |
| PathParams |
|
No comment on field. |
| FormParams |
|
No comment on field. |
| QueryParams |
|
No comment on field. |
| Cookies |
|
No comment on field. |
| Delay |
|
No comment on field. |
| BodyMatch |
|
No comment on field. |
| BodyNotMatch |
|
No comment on field. |
| HeadersMatch |
|
No comment on field. |
| HeadersNotMatch |
|
No comment on field. |
| JSONMatch |
|
No comment on field. |
| ErrorMatch |
|
No comment on field. |
| BodyMatchFunc |
|
No comment on field. |
| BeforeFn |
|
No comment on field. |
| Client |
|
No comment on field. |
| AdminAuth |
|
No comment on field. |
| ControlRequest |
|
No comment on field. |
type TestCase struct {
Host string `json:",omitempty"`
Method string `json:",omitempty"`
Path string `json:",omitempty"`
BaseURL string `json:",omitempty"`
Domain string `json:",omitempty"`
Proto string `json:",omitempty"`
// Code is the expected HTTP response status code.
Code int `json:",omitempty"`
Data interface{} `json:",omitempty"`
Headers map[string]string `json:",omitempty"`
PathParams map[string]string `json:",omitempty"`
FormParams map[string]string `json:",omitempty"`
QueryParams map[string]string `json:",omitempty"`
Cookies []*http.Cookie `json:",omitempty"`
Delay time.Duration `json:",omitempty"`
BodyMatch string `json:",omitempty"` // regex
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"`
BodyMatchFunc func([]byte) bool `json:"-"`
BeforeFn func() `json:"-"`
Client *http.Client `json:"-"`
AdminAuth bool `json:",omitempty"`
ControlRequest bool `json:",omitempty"`
}
TestCases
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| type |
|
No comment on field. |
type TestCases []TestCase
ClientOption, TransportOption, DialContext
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| type |
|
No comment on field. |
| type |
|
No comment on field. |
| type |
|
No comment on field. |
type (
// Options for populating a http.Client
ClientOption func(*http.Client)
// Options for populating a http.Transport
TransportOption func(*http.Transport)
// DialContext function signature
DialContext func(ctx context.Context, network, addr string) (net.Conn, error)
)
dnsMockHandler
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| domainsToAddresses |
|
No comment on field. |
| domainsToErrors |
|
No comment on field. |
| muDomainsToAddresses |
|
No comment on field. |
type dnsMockHandler struct {
domainsToAddresses map[string][]string
domainsToErrors map[string]int
muDomainsToAddresses sync.RWMutex
}
nopCloser
nopCloser is just like ioutil's, but here to let us re-read the same buffer inside by moving position to the start every time we done with reading
| Field name | Field type | Comment |
|---|---|---|
|
No comment on field. |
type nopCloser struct {
io.ReadSeeker
}
Functions
func AssertResponse
func AssertResponse(resp *http.Response, tc *TestCase) error {
body, _ := ioutil.ReadAll(resp.Body)
resp.Body = ioutil.NopCloser(bytes.NewBuffer(body))
defer resp.Body.Close()
if tc.Code != 0 && resp.StatusCode != tc.Code {
return fmt.Errorf("Expected status code `%d` got `%d. %s`", tc.Code, resp.StatusCode, string(body))
}
if tc.BodyMatch != "" {
if bodyMatch := regexp.MustCompile(tc.BodyMatch); !bodyMatch.MatchString(string(body)) {
return fmt.Errorf("Response body does not match with regex `%s`. %s", tc.BodyMatch, string(body))
}
}
if tc.BodyNotMatch != "" && bytes.Contains(body, []byte(tc.BodyNotMatch)) {
return fmt.Errorf("Response body should not contain `%s`. %s", tc.BodyNotMatch, string(body))
}
if tc.BodyMatchFunc != nil && !tc.BodyMatchFunc(body) {
return fmt.Errorf("Response body did not pass BodyMatchFunc: %s", string(body))
}
if tc.Proto != "" && tc.Proto != resp.Proto {
return fmt.Errorf("Expected protocol `%s` got `%s`.", tc.Proto, resp.Proto)
}
for k, v := range tc.HeadersMatch {
if resp.Header.Get(k) != v {
return fmt.Errorf("Response header `%s` expected `%s` instead `%s`. %v", k, v, resp.Header.Get(k), resp.Header)
}
}
for k, v := range tc.HeadersNotMatch {
if resp.Header.Get(k) == v {
return fmt.Errorf("Response header `%s` should not be %s`", k, v)
}
}
if len(tc.JSONMatch) == 0 {
return nil
}
var jsonBody map[string]json.RawMessage
if err := json.Unmarshal(body, &jsonBody); err != nil {
return fmt.Errorf("Should return JSON body: %s. %d", string(body), resp.StatusCode)
}
for k, expect := range tc.JSONMatch {
if got, ok := jsonBody[k]; !ok {
return fmt.Errorf("`%s` JSON field not found: %s", k, string(body))
} else if string(got) != expect {
return fmt.Errorf("`%s` not match: `%s` != `%s`", k, got, expect)
}
}
return nil
}
Cognitive complexity: 33, Cyclomatic complexity: 20
func CI
CI returns true when a non-empty CI env is present
func CI() bool {
return os.Getenv("CI") != ""
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func Cert
Generate cert
func Cert(domain string) tls.Certificate {
private, _ := rsa.GenerateKey(rand.Reader, 512)
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
Organization: []string{"Test Co"},
CommonName: domain,
},
NotBefore: time.Time{},
NotAfter: time.Now().Add(60 * time.Minute),
IsCA: true,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
derBytes, _ := x509.CreateCertificate(rand.Reader, template, template, &private.PublicKey, private)
var cert, key bytes.Buffer
pem.Encode(&cert, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
pem.Encode(&key, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(private)})
tlscert, _ := tls.X509KeyPair(cert.Bytes(), key.Bytes())
return tlscert
}
Cognitive complexity: 7, Cyclomatic complexity: 1
func Flaky
Flaky skips a flaky test in a CI environment
func Flaky(t *testing.T, fake ...func() (bool, func(...interface{}))) {
skipCI(t, "Skipping flaky test", fake...)
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func GetPythonVersion
func GetPythonVersion() string {
pythonVersion := os.Getenv("PYTHON_VERSION")
if pythonVersion == "" {
pythonVersion = "3.5"
}
return pythonVersion
}
Cognitive complexity: 2, Cyclomatic complexity: 2
func HttpHandlerRunner
func HttpHandlerRunner(handler http.HandlerFunc) func(*http.Request, *TestCase) (*http.Response, error) {
return func(r *http.Request, _ *TestCase) (*http.Response, error) {
rec := httptest.NewRecorder()
handler(rec, r)
return rec.Result(), nil
}
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func HttpServerRequestBuilder
func HttpServerRequestBuilder(baseURL string) func(tc *TestCase) (*http.Request, error) {
return func(tc *TestCase) (*http.Request, error) {
tc.BaseURL = baseURL
return NewRequest(tc)
}
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func HttpServerRunner
func HttpServerRunner() func(*http.Request, *TestCase) (*http.Response, error) {
return func(r *http.Request, tc *TestCase) (*http.Response, error) {
return tc.Client.Do(r)
}
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func InitDNSMock
InitDNSMock initializes dns server on udp:0 address and replaces net.DefaultResolver in order to route all dns queries within tests to this server. InitDNSMock returns handle, which can be used to add/remove dns query mock responses or initialization error.
func InitDNSMock(domainsMap map[string][]string, domainsErrorMap map[string]int) (*DnsMockHandle, error) {
addr, _ := net.ResolveUDPAddr("udp", ":0")
conn, err := net.ListenUDP("udp", addr)
if err != nil {
return &DnsMockHandle{}, err
}
startResultChannel := make(chan error)
started := func() {
startResultChannel <- nil
}
mockServer := &dns.Server{PacketConn: conn, NotifyStartedFunc: started}
handle := &DnsMockHandle{id: time.Now().String(), mockServer: mockServer}
dnsMux := &dnsMockHandler{muDomainsToAddresses: sync.RWMutex{}}
if domainsMap != nil {
dnsMux.domainsToAddresses = domainsMap
} else {
dnsMux.domainsToAddresses = DomainsToAddresses
}
if domainsErrorMap != nil {
dnsMux.domainsToErrors = domainsErrorMap
}
mockServer.Handler = dnsMux
go func() {
startResultChannel <- mockServer.ActivateAndServe()
}()
err = <-startResultChannel
if err != nil {
close(startResultChannel)
return handle, err
}
mockResolver := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{}
return d.DialContext(ctx, network, mockServer.PacketConn.LocalAddr().String())
},
}
// TODO: this is destructive, TT-5112
once.Do(func() {
net.DefaultResolver = mockResolver
})
handle.ShutdownDnsMock = func() error {
// We run tests against O(1) packages, we can
// afford a dirty shutdown, if it means less
// flaky tests.
return nil // mockServer.Shutdown()
}
return handle, nil
}
Cognitive complexity: 22, Cyclomatic complexity: 5
func InitTestMain
func InitTestMain(_ context.Context, _ *testing.M) {
initOnce.Do(func() {
// Poor mans resource monitoring, prints runtime stats into logs
if interval := os.Getenv("TEST_MONITOR_INTERVAL"); interval != "" {
val, _ := strconv.Atoi(interval)
if val < 1 {
val = 1
}
go NewMonitor(val)
}
// Enable pprof server from test env
if pprof := os.Getenv("TEST_PPROF_ENABLE"); pprof == "1" {
var listen string
if listen = os.Getenv("TEST_PPROF_ADDR"); listen == "" {
listen = ":12345"
}
go func() {
log.Printf("Starting pprof on addr=%q", listen)
_ = http.ListenAndServe(listen, nil)
}()
}
})
}
Cognitive complexity: 10, Cyclomatic complexity: 5
func IsDnsRecordsAddrsEqualsTo
func IsDnsRecordsAddrsEqualsTo(itemAddrs, addrs []string) bool {
return reflect.DeepEqual(itemAddrs, addrs)
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func IsRaceEnabled
func IsRaceEnabled() bool {
return false
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func LocalDialer
LocalDialer provides a function to use to dial to localhost
func LocalDialer() func(context.Context, string, string) (net.Conn, error) {
return func(ctx context.Context, network, addr string) (net.Conn, error) {
_, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
host := "127.0.0.1"
dialer := net.Dialer{}
return dialer.DialContext(ctx, network, net.JoinHostPort(host, port))
}
}
Cognitive complexity: 4, Cyclomatic complexity: 2
func MarshalJSON
MarshalJSON returns a closure returning the marshalled json while asserting no error occurred during marshalling.
func MarshalJSON(tb testing.TB) func(interface{}) []byte {
tb.Helper()
return func(in interface{}) []byte {
b, err := json.Marshal(in)
require.NoError(tb, err)
return b
}
}
Cognitive complexity: 3, Cyclomatic complexity: 1
func NewBufferingLogger
NewBufferingLogger creates a new buffered logger.
func NewBufferingLogger() *BufferedLogger {
if buflogger != nil {
return buflogger
}
bufferingFormatter := &BufferingFormatter{buffer: make([]*BufferedLog, 0)}
logger := logrus.New()
logger.Level = logrus.DebugLevel
logger.Formatter = bufferingFormatter
buflogger = &BufferedLogger{
Logger: logger,
bufferingFormatter: bufferingFormatter,
}
return buflogger
}
Cognitive complexity: 4, Cyclomatic complexity: 2
func NewClient
NewClient creates a http.Client with options
func NewClient(opts ...ClientOption) *http.Client {
client := &http.Client{}
applyClientOptions(client, opts...)
return client
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func NewClientLocal
NewClientLocal returns a http.Client that can connect
only to localhost. See: WithLocalDialer.
func NewClientLocal(opts ...ClientOption) *http.Client {
client := NewClient(
WithTransport(
NewTransport(WithLocalDialer()),
),
)
applyClientOptions(client, opts...)
return client
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func NewMonitor
func NewMonitor(duration int) {
var m Monitor
var rtm runtime.MemStats
var interval = time.Duration(duration) * time.Second
for {
<-time.After(interval)
// Read full mem stats
runtime.ReadMemStats(&rtm)
// Number of goroutines
m.NumGoroutine = runtime.NumGoroutine()
if m.NumGoroutine > 4000 {
go func() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGQUIT)
buf := make([]byte, 1<<20)
for {
<-sigs
stacklen := runtime.Stack(buf, true)
log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf[:stacklen])
}
}()
}
// Misc memory stats
m.Alloc = rtm.Alloc
m.TotalAlloc = rtm.TotalAlloc
m.Sys = rtm.Sys
m.Mallocs = rtm.Mallocs
m.Frees = rtm.Frees
// Live objects = Mallocs - Frees
m.LiveObjects = m.Mallocs - m.Frees
// GC Stats
m.PauseTotalNs = rtm.PauseTotalNs
m.NumGC = rtm.NumGC
// Just encode to json and print
b, _ := json.Marshal(m)
fmt.Fprintln(os.Stderr, string(b))
}
}
Cognitive complexity: 7, Cyclomatic complexity: 4
func NewRequest
func NewRequest(tc *TestCase) (req *http.Request, err error) {
if tc.Method == "" {
tc.Method = "GET"
}
if tc.Path == "" {
tc.Path = "/"
}
if tc.Domain == "" {
tc.Domain = "127.0.0.1"
}
if tc.Client == nil {
tc.Client = &http.Client{}
}
uri := tc.Path
if tc.BaseURL != "" {
uri = tc.BaseURL + tc.Path
}
if strings.HasPrefix(uri, "http") {
uri = strings.Replace(uri, "[::]", tc.Domain, 1)
uri = strings.Replace(uri, "127.0.0.1", tc.Domain, 1)
req, err = http.NewRequest(tc.Method, uri, ReqBodyReader(tc.Data))
if err != nil {
return
}
} else {
req = httptest.NewRequest(tc.Method, uri, ReqBodyReader(tc.Data))
}
for k, v := range tc.Headers {
req.Header.Add(k, v)
}
req.Header.Add("Content-Type", "application/json")
for _, c := range tc.Cookies {
req.AddCookie(c)
}
formParams := url.Values{}
for k, v := range tc.FormParams {
formParams.Add(k, v)
}
req.PostForm = formParams
req.Form = formParams
if tc.QueryParams != nil {
queryParams := req.URL.Query()
for k, v := range tc.QueryParams {
queryParams.Add(k, v)
}
req.URL.RawQuery = queryParams.Encode()
}
return req, nil
}
Cognitive complexity: 32, Cyclomatic complexity: 13
func NewTransport
NewTransport creates a http.Transport with options
func NewTransport(opts ...TransportOption) *http.Transport {
transport := &http.Transport{}
for _, v := range opts {
v(transport)
}
return transport
}
Cognitive complexity: 4, Cyclomatic complexity: 2
func Racy
Racy skips a racy test in a CI environment
func Racy(t *testing.T, fake ...func() (bool, func(...interface{}))) {
skipCI(t, "Skipping racy test", fake...)
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func ReqBodyReader
func ReqBodyReader(body interface{}) io.Reader {
switch x := body.(type) {
case []byte:
return bytes.NewReader(x)
case string:
return strings.NewReader(x)
case io.Reader:
return x
case nil:
return nil
default: // JSON objects (structs)
bs, err := json.Marshal(x)
if err != nil {
panic(err)
}
return bytes.NewReader(bs)
}
}
Cognitive complexity: 9, Cyclomatic complexity: 7
func TcpMock
func TcpMock(useSSL bool, cb func(in []byte, err error) (out []byte)) net.Listener {
var l net.Listener
if useSSL {
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{Cert("localhost")},
InsecureSkipVerify: true,
MaxVersion: tls.VersionTLS12,
}
tlsConfig.BuildNameToCertificate()
l, _ = tls.Listen("tcp", ":0", tlsConfig)
} else {
l, _ = net.Listen("tcp", ":0")
}
go func() {
for {
// Listen for an incoming connection.
conn, err := l.Accept()
if err != nil {
log.Println("Mock Accept error", err.Error())
return
}
buf := make([]byte, 65535)
n, err := conn.Read(buf)
resp := cb(buf[:n], err)
if err != nil {
log.Println("Mock read error", err.Error())
return
}
if len(resp) > 0 {
if n, err = conn.Write(resp); err != nil {
log.Println("Mock Conn write error", err.Error())
}
}
}
}()
return l
}
Cognitive complexity: 17, Cyclomatic complexity: 7
func TestHttpHandler
func TestHttpHandler(t testing.TB, handle http.HandlerFunc, testCases ...TestCase) {
runner := HTTPTestRunner{
Do: HttpHandlerRunner(handle),
}
runner.Run(t, testCases...)
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func TestHttpServer
func TestHttpServer(t testing.TB, baseURL string, testCases ...TestCase) {
runner := HTTPTestRunner{
Do: HttpServerRunner(),
RequestBuilder: HttpServerRequestBuilder(baseURL),
}
runner.Run(t, testCases...)
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func WithDialer
WithDialer sets transport.DialContext
func WithDialer(dialer DialContext) TransportOption {
return TransportOption(func(transport *http.Transport) {
transport.DialContext = dialer
})
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func WithLocalDialer
WithLocalDialer sets a http.Transport DialContext, which only connects to 127.0.0.1.
func WithLocalDialer() TransportOption {
return TransportOption(func(transport *http.Transport) {
transport.DialContext = LocalDialer()
})
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func WithTransport
WithTransport sets a http.RoundTripper to a http.Client
func WithTransport(transport http.RoundTripper) ClientOption {
return ClientOption(func(c *http.Client) {
c.Transport = transport
})
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func (*BufferedLogger) ClearLogs
ClearLogs clears the logs from the buffer. IMPORTANT: Must be called before each test iteration.
func (bl *BufferedLogger) ClearLogs() {
bl.bufferingFormatter.bufferMutex.Lock()
defer bl.bufferingFormatter.bufferMutex.Unlock()
bl.bufferingFormatter.buffer = make([]*BufferedLog, 0)
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func (*BufferedLogger) GetLogs
GetLogs returns the logs that are stored in the buffer.
func (bl *BufferedLogger) GetLogs(Level logrus.Level) []*BufferedLog {
bl.bufferingFormatter.bufferMutex.Lock()
defer bl.bufferingFormatter.bufferMutex.Unlock()
logs := make([]*BufferedLog, 0)
for _, log := range bl.bufferingFormatter.buffer {
if log.Level == Level {
logs = append(logs, log)
}
}
return logs
}
Cognitive complexity: 5, Cyclomatic complexity: 3
func (*BufferingFormatter) Format
Format is the method that stores the log entry in the buffer.
func (f *BufferingFormatter) Format(entry *logrus.Entry) ([]byte, error) {
f.bufferMutex.Lock()
defer f.bufferMutex.Unlock()
bl := &BufferedLog{
Message: entry.Message,
Time: entry.Time.UTC(),
Level: entry.Level,
}
f.buffer = append(f.buffer, bl)
return nil, nil
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func (*DnsMockHandle) PushDomains
func (h *DnsMockHandle) PushDomains(domainsMap map[string][]string, domainsErrorMap map[string]int) func() {
handler := h.mockServer.Handler.(*dnsMockHandler)
handler.muDomainsToAddresses.Lock()
defer handler.muDomainsToAddresses.Unlock()
dta := handler.domainsToAddresses
dte := handler.domainsToErrors
prevDta := map[string][]string{}
prevDte := map[string]int{}
for key, value := range dta {
prevDta[key] = value
}
for key, value := range dte {
prevDte[key] = value
}
pullDomainsFunc := func() {
handler := h.mockServer.Handler.(*dnsMockHandler)
handler.muDomainsToAddresses.Lock()
defer handler.muDomainsToAddresses.Unlock()
handler.domainsToAddresses = prevDta
handler.domainsToErrors = prevDte
}
for key, ips := range domainsMap {
addr, ok := dta[key]
if !ok {
dta[key] = ips
} else {
dta[key] = append(addr, ips...)
}
}
for key, rCode := range domainsErrorMap {
dte[key] = rCode
}
return pullDomainsFunc
}
Cognitive complexity: 19, Cyclomatic complexity: 6
func (*dnsMockHandler) ServeDNS
func (d *dnsMockHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
msg := dns.Msg{}
msg.SetReply(r)
switch r.Question[0].Qtype {
case dns.TypeA:
msg.Authoritative = true
domain := msg.Question[0].Name
d.muDomainsToAddresses.RLock()
defer d.muDomainsToAddresses.RUnlock()
if rcode, ok := d.domainsToErrors[domain]; ok {
m := new(dns.Msg)
m.SetRcode(r, rcode)
w.WriteMsg(m)
return
}
for _, ignore := range DomainsToIgnore {
if strings.HasPrefix(domain, ignore) {
resolver := &net.Resolver{}
ipAddrs, err := resolver.LookupIPAddr(context.Background(), domain)
if err != nil {
m := new(dns.Msg)
m.SetRcode(r, dns.RcodeServerFailure)
w.WriteMsg(m)
return
}
msg.Answer = append(msg.Answer, &dns.A{
Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
A: ipAddrs[0].IP,
})
w.WriteMsg(&msg)
return
}
}
var addresses []string
for d, ips := range d.domainsToAddresses {
if strings.HasPrefix(domain, d) {
addresses = ips
}
}
if len(addresses) == 0 {
// ^ start of line
// localhost\. match literally
// ()* match between 0 and unlimited times
// [[:alnum:]]+\. match single character in [a-zA-Z0-9] minimum one time and ending in . literally
reg := regexp.MustCompile(`^localhost\.([[:alnum:]]+\.)*`)
if matched := reg.MatchString(domain); !matched {
panic(fmt.Sprintf("domain not mocked: %s", domain))
}
addresses = []string{"127.0.0.1"}
}
for _, addr := range addresses {
msg.Answer = append(msg.Answer, &dns.A{
Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
A: net.ParseIP(addr),
})
}
}
w.WriteMsg(&msg)
}
Cognitive complexity: 31, Cyclomatic complexity: 12
func (HTTPTestRunner) Run
func (r HTTPTestRunner) Run(t testing.TB, testCases ...TestCase) (*http.Response, error) {
t.Helper()
var lastResponse *http.Response
var lastError error
if r.Do == nil {
panic("Request runner not implemented")
}
if r.Assert == nil {
r.Assert = AssertResponse
}
if r.RequestBuilder == nil {
r.RequestBuilder = NewRequest
}
for ti, tc := range testCases {
var tc *TestCase = &tc
if tc.BeforeFn != nil {
tc.BeforeFn()
}
req, err := r.RequestBuilder(tc)
if err != nil {
t.Errorf("[%d] Request build error: %s", ti, err.Error())
continue
}
if tc.Host != "" {
req.Host = tc.Host
}
retryCount := 0
retry:
lastResponse, lastError = r.Do(req, tc)
tcJSON, _ := json.Marshal(tc)
if lastError != nil {
if retryCount < maxRetryCount && needRetry(lastError.Error()) {
retryCount++
goto retry
}
if tc.ErrorMatch != "" {
if !strings.Contains(lastError.Error(), tc.ErrorMatch) {
t.Errorf("[%d] Expect error `%s` to contain `%s`. %s", ti, lastError.Error(), tc.ErrorMatch, string(tcJSON))
}
} else {
t.Errorf("[%d] Connection error: %s. %s", ti, lastError.Error(), string(tcJSON))
}
continue
} else if tc.ErrorMatch != "" {
t.Error("Expect error.", string(tcJSON))
continue
}
respCopy := copyResponse(lastResponse)
if lastError = r.Assert(respCopy, tc); lastError != nil {
t.Errorf("[%d] %s. %s\n", ti, lastError.Error(), string(tcJSON))
}
if delay := tc.Delay; delay > 0 {
time.Sleep(delay)
}
}
return lastResponse, lastError
}
Cognitive complexity: 31, Cyclomatic complexity: 16
func (TCPTestRunner) Run
func (r TCPTestRunner) Run(t testing.TB, testCases ...TCPTestCase) error {
var err error
buf := make([]byte, 65535)
var client net.Conn
if r.UseSSL {
if r.TLSClientConfig == nil {
r.TLSClientConfig = &tls.Config{
ServerName: r.Hostname,
InsecureSkipVerify: true,
MaxVersion: tls.VersionTLS12,
}
}
client, err = tls.Dial("tcp", r.Target, r.TLSClientConfig)
if err != nil {
return err
}
} else {
client, err = net.Dial("tcp", r.Target)
if err != nil {
return err
}
}
defer client.Close()
for ti, tc := range testCases {
var n int
client.SetDeadline(time.Now().Add(time.Second))
switch tc.Action {
case "write":
_, err = client.Write([]byte(tc.Payload))
case "read":
n, err = client.Read(buf)
if err == nil {
if string(buf[:n]) != tc.Payload {
t.Fatalf("[%d] Expected read %s, got %v", ti, tc.Payload, string(buf[:n]))
}
}
}
if tc.ErrorMatch != "" {
if err == nil {
t.Fatalf("[%d] Expected error: %s", ti, tc.ErrorMatch)
}
if !strings.Contains(err.Error(), tc.ErrorMatch) {
t.Fatalf("[%d] Expected error %s, got %s", ti, err.Error(), tc.ErrorMatch)
}
} else {
if err != nil {
t.Fatalf("[%d] Unexpected error: %s", ti, err.Error())
}
}
}
return nil
}
Cognitive complexity: 32, Cyclomatic complexity: 15
func (nopCloser) Close
Close is a no-op Close
func (n nopCloser) Close() error {
return nil
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func (nopCloser) Read
Read just a wrapper around real Read which also moves position to the start if we get EOF to have it ready for next read-cycle
func (n nopCloser) Read(p []byte) (int, error) {
num, err := n.ReadSeeker.Read(p)
if errors.Is(err, io.EOF) { // move to start to have it ready for next read cycle
_, _ = n.Seek(0, io.SeekStart)
}
return num, err
}
Cognitive complexity: 2, Cyclomatic complexity: 2
Private functions
func applyClientOptions
applyClientOptions (c *http.Client, opts ...ClientOption)
func copyBody
copyBody (body io.ReadCloser) io.ReadCloser
References: bytes.Buffer, bytes.NewReader, io.Copy, io.SeekStart.
func copyResponse
copyResponse (r *http.Response) *http.Response
func needRetry
needRetry (errString string) bool
References: strings.Contains.
func skipCI
skipCI (t *testing.T, message string, fake ...func() (bool, func(...interface{})))
Tests
Files: 4. Third party imports: 2. Imports from organisation: 0. Tests: 8. Benchmarks: 0.