testutils/channel_opts.go (189 lines of code) (raw):
// Copyright (c) 2015 Uber Technologies, Inc.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package testutils
import (
"flag"
"net"
"testing"
"time"
"github.com/uber/tchannel-go"
"github.com/uber/tchannel-go/tos"
"go.uber.org/atomic"
"golang.org/x/net/context"
)
var connectionLog = flag.Bool("connectionLog", false, "Enables connection logging in tests")
// Default service names for the test channels.
const (
DefaultServerName = "testService"
DefaultClientName = "testService-client"
)
// ChannelOpts contains options to create a test channel using WithServer
type ChannelOpts struct {
tchannel.ChannelOptions
// ServiceName defaults to DefaultServerName or DefaultClientName.
ServiceName string
// LogVerification contains options for controlling the log verification.
LogVerification LogVerification
// DisableRelay disables the relay interposed between clients/servers.
// By default, all tests are run with a relay interposed.
DisableRelay bool
// DisableServer disables creation of the TChannel server.
// This is typically only used in relay tests when a custom server is required.
DisableServer bool
// OnlyRelay instructs TestServer the test must only be run with a relay.
OnlyRelay bool
// RunCount is the number of times the test should be run. Zero or
// negative values are treated as a single run.
RunCount int
// CheckFramePooling indicates whether we should check for frame leaks or not.
// This causes the same tests to be run twice, first with the default frame pool,
// then with the recording frame pool, which will double the amount of time it takes
// for the test.
CheckFramePooling bool
// postFns is a list of functions that are run after the test.
// They are run even if the test fails.
postFns []func()
// ServeTLS enables TLS support on server channel with test certs
ServeTLS bool
}
// LogVerification contains options to control the log verification.
type LogVerification struct {
Disabled bool
Filters []LogFilter
}
// LogFilter is a single substring match that can be ignored.
type LogFilter struct {
// Filter specifies the substring match to search
// for in the log message to skip raising an error.
Filter string
// Count is the maximum number of allowed warn+ logs matching
// Filter before errors are raised.
Count uint
// FieldFilters specifies expected substring matches for fields.
FieldFilters map[string]string
}
// Copy copies the channel options (so that they can be safely modified).
func (o *ChannelOpts) Copy() *ChannelOpts {
if o == nil {
return NewOpts()
}
copiedOpts := *o
return &copiedOpts
}
// SetServiceName sets ServiceName.
func (o *ChannelOpts) SetServiceName(svcName string) *ChannelOpts {
o.ServiceName = svcName
return o
}
// SetProcessName sets the ProcessName in ChannelOptions.
func (o *ChannelOpts) SetProcessName(processName string) *ChannelOpts {
o.ProcessName = processName
return o
}
// SetStatsReporter sets StatsReporter in ChannelOptions.
func (o *ChannelOpts) SetStatsReporter(statsReporter tchannel.StatsReporter) *ChannelOpts {
o.StatsReporter = statsReporter
return o
}
// SetFramePool sets FramePool in DefaultConnectionOptions.
func (o *ChannelOpts) SetFramePool(framePool tchannel.FramePool) *ChannelOpts {
o.DefaultConnectionOptions.FramePool = framePool
return o
}
// SetHealthChecks sets HealthChecks in DefaultConnectionOptions.
func (o *ChannelOpts) SetHealthChecks(healthChecks tchannel.HealthCheckOptions) *ChannelOpts {
o.DefaultConnectionOptions.HealthChecks = healthChecks
return o
}
// SetSendBufferSize sets the SendBufferSize in DefaultConnectionOptions.
func (o *ChannelOpts) SetSendBufferSize(bufSize int) *ChannelOpts {
o.DefaultConnectionOptions.SendBufferSize = bufSize
return o
}
// SetSendBufferSizeOverrides sets the SendBufferOverrides in DefaultConnectionOptions.
func (o *ChannelOpts) SetSendBufferSizeOverrides(overrides []tchannel.SendBufferSizeOverride) *ChannelOpts {
o.DefaultConnectionOptions.SendBufferSizeOverrides = overrides
return o
}
// SetTosPriority set TosPriority in DefaultConnectionOptions.
func (o *ChannelOpts) SetTosPriority(tosPriority tos.ToS) *ChannelOpts {
o.DefaultConnectionOptions.TosPriority = tosPriority
return o
}
// SetChecksumType sets the ChecksumType in DefaultConnectionOptions.
func (o *ChannelOpts) SetChecksumType(checksumType tchannel.ChecksumType) *ChannelOpts {
o.DefaultConnectionOptions.ChecksumType = checksumType
return o
}
// SetTimeNow sets TimeNow in ChannelOptions.
func (o *ChannelOpts) SetTimeNow(timeNow func() time.Time) *ChannelOpts {
o.TimeNow = timeNow
return o
}
// SetTimeTicker sets TimeTicker in ChannelOptions.
func (o *ChannelOpts) SetTimeTicker(timeTicker func(d time.Duration) *time.Ticker) *ChannelOpts {
o.TimeTicker = timeTicker
return o
}
// DisableLogVerification disables log verification for this channel.
func (o *ChannelOpts) DisableLogVerification() *ChannelOpts {
o.LogVerification.Disabled = true
return o
}
// NoRelay disables running the test with a relay interposed.
func (o *ChannelOpts) NoRelay() *ChannelOpts {
o.DisableRelay = true
return o
}
// SetRelayOnly instructs TestServer to only run with a relay in front of this channel.
func (o *ChannelOpts) SetRelayOnly() *ChannelOpts {
o.OnlyRelay = true
return o
}
// SetDisableServer disables creation of the TChannel server.
// This is typically only used in relay tests when a custom server is required.
func (o *ChannelOpts) SetDisableServer() *ChannelOpts {
o.DisableServer = true
return o
}
// SetRunCount sets the number of times run the test.
func (o *ChannelOpts) SetRunCount(n int) *ChannelOpts {
o.RunCount = n
return o
}
// AddLogFilter sets an allowed filter for warning/error logs and sets
// the maximum number of times that log can occur.
func (o *ChannelOpts) AddLogFilter(filter string, maxCount uint, fields ...string) *ChannelOpts {
fieldFilters := make(map[string]string)
for i := 0; i < len(fields); i += 2 {
fieldFilters[fields[i]] = fields[i+1]
}
o.LogVerification.Filters = append(o.LogVerification.Filters, LogFilter{
Filter: filter,
Count: maxCount,
FieldFilters: fieldFilters,
})
return o
}
func (o *ChannelOpts) addPostFn(f func()) {
o.postFns = append(o.postFns, f)
}
// SetRelayHost sets the channel's RelayHost, which enables relaying.
func (o *ChannelOpts) SetRelayHost(rh tchannel.RelayHost) *ChannelOpts {
o.ChannelOptions.RelayHost = rh
return o
}
// SetRelayLocal sets the channel's relay local handlers for service names
// that should be handled by the relay channel itself.
func (o *ChannelOpts) SetRelayLocal(relayLocal ...string) *ChannelOpts {
o.ChannelOptions.RelayLocalHandlers = relayLocal
return o
}
// SetRelayMaxTimeout sets the maximum allowable timeout for relayed calls.
func (o *ChannelOpts) SetRelayMaxTimeout(d time.Duration) *ChannelOpts {
o.ChannelOptions.RelayMaxTimeout = d
return o
}
// SetRelayMaxConnectionTimeout sets the maximum timeout for connection attempts.
func (o *ChannelOpts) SetRelayMaxConnectionTimeout(d time.Duration) *ChannelOpts {
o.ChannelOptions.RelayMaxConnectionTimeout = d
return o
}
// SetRelayMaxTombs sets the maximum number of tombs tracked in the relayer.
func (o *ChannelOpts) SetRelayMaxTombs(maxTombs uint64) *ChannelOpts {
o.ChannelOptions.RelayMaxTombs = maxTombs
return o
}
// SetOnPeerStatusChanged sets the callback for channel status change
// noficiations.
func (o *ChannelOpts) SetOnPeerStatusChanged(f func(*tchannel.Peer)) *ChannelOpts {
o.ChannelOptions.OnPeerStatusChanged = f
return o
}
// SetMaxIdleTime sets a threshold after which idle connections will
// automatically get dropped. See idle_sweep.go for more details.
func (o *ChannelOpts) SetMaxIdleTime(d time.Duration) *ChannelOpts {
o.ChannelOptions.MaxIdleTime = d
return o
}
// SetIdleCheckInterval sets the frequency of the periodic poller that removes
// stale connections from the channel.
func (o *ChannelOpts) SetIdleCheckInterval(d time.Duration) *ChannelOpts {
o.ChannelOptions.IdleCheckInterval = d
return o
}
// SetDialer sets the dialer used for outbound connections
func (o *ChannelOpts) SetDialer(f func(context.Context, string, string) (net.Conn, error)) *ChannelOpts {
o.ChannelOptions.Dialer = f
return o
}
// SetConnContext sets the connection's ConnContext function
func (o *ChannelOpts) SetConnContext(f func(context.Context, net.Conn) context.Context) *ChannelOpts {
o.ConnContext = f
return o
}
// SetCheckFramePooling sets a flag to enable frame pooling checks such as leaks or bad releases
func (o *ChannelOpts) SetCheckFramePooling() *ChannelOpts {
o.CheckFramePooling = true
return o
}
// SetServeTLS sets the ServeTLS flag to enable/disable TLS for test server
func (o *ChannelOpts) SetServeTLS(serveTLS bool) *ChannelOpts {
o.ServeTLS = serveTLS
return o
}
func defaultString(v string, defaultValue string) string {
if v == "" {
return defaultValue
}
return v
}
// NewOpts returns a new ChannelOpts that can be used in a chained fashion.
func NewOpts() *ChannelOpts { return &ChannelOpts{} }
// DefaultOpts will return opts if opts is non-nil, NewOpts otherwise.
func DefaultOpts(opts *ChannelOpts) *ChannelOpts {
if opts == nil {
return NewOpts()
}
return opts
}
// WrapLogger wraps the given logger with extra verification.
func (v *LogVerification) WrapLogger(t testing.TB, l tchannel.Logger) tchannel.Logger {
return errorLogger{l, t, v, &errorLoggerState{
matchCount: make([]atomic.Uint32, len(v.Filters)),
}}
}