Documentation ¶
Overview ¶
Package sharedtest provides helper code and test data that may be used by tests in all Relay components and distributions.
Non-test code should never import this package or any of its subpackages.
To avoid circular references, code in this package cannot reference the main core package, core/relayenv, or core/streams. Any helpers that need to do so must be in a subpackage.
Index ¶
- Constants
- Variables
- func AddQueryParam(url, query string) string
- func AssertEndpointSupportsOptionsRequest(t *testing.T, handler http.Handler, url, usualMethod string)
- func AssertExpectedCORSHeaders(t *testing.T, resp *http.Response, endpointMethod string, host string)
- func AssertJSONPathMatch(t *testing.T, expected interface{}, inValue ldvalue.Value, path ...string)
- func AssertNonStreamingHeaders(t *testing.T, h http.Header)
- func AssertStreamingContentType(t *testing.T, h http.Header)
- func AssertStreamingHeaders(t *testing.T, h http.Header)
- func BuildRequest(method, url string, body []byte, headers http.Header) *http.Request
- func BuildRequestWithAuth(method, url string, authKey config.SDKCredential, body []byte) *http.Request
- func CallHandlerAndAwaitStatus(t *testing.T, handler http.Handler, req *http.Request, timeout time.Duration) int
- func DeletedItem(version int) ldstoretypes.ItemDescriptor
- func DoRequest(req *http.Request, handler http.Handler) (*http.Response, []byte)
- func ExpectNoStreamChEvent(t *testing.T, ch <-chan eventsource.Event, timeout time.Duration)
- func ExpectNoStreamEvent(t *testing.T, stream *eventsource.Stream, timeout time.Duration)
- func ExpectNoTestRequests(t *testing.T, ch <-chan httphelpers.HTTPRequestInfo, timeout time.Duration)
- func ExpectStreamChEvent(t *testing.T, ch <-chan eventsource.Event, timeout time.Duration) eventsource.Event
- func ExpectStreamEvent(t *testing.T, stream *eventsource.Stream, timeout time.Duration) eventsource.Event
- func ExpectTestRequest(t *testing.T, ch <-chan httphelpers.HTTPRequestInfo, timeout time.Duration) httphelpers.HTTPRequestInfo
- func FlagDesc(flag ldmodel.FeatureFlag) ldstoretypes.ItemDescriptor
- func FlagsMap(testFlags []TestFlag) map[string]interface{}
- func GetAvailablePort(t *testing.T) int
- func MakeBasicHTTPConfig() httpconfig.HTTPConfig
- func MakeEnvConfigs(envs ...TestEnv) map[string]*config.EnvConfig
- func MakeEvalBody(flags []TestFlag, fullData bool, reasons bool) string
- func MakeSDKEvalEndpointRequest(baseURL string, kind basictypes.SDKKind, testEnv TestEnv, userJSON string, ...) *http.Request
- func MakeSDKStreamEndpointRequest(baseURL string, kind basictypes.StreamKind, testEnv TestEnv, userJSON string, ...) *http.Request
- func MakeStoreWithData(initialized bool) interfaces.DataStore
- func NewInMemoryStore() interfaces.DataStore
- func SegmentDesc(segment ldmodel.Segment) ldstoretypes.ItemDescriptor
- func ToBase64(s string) string
- func UpsertFlag(store interfaces.DataStore, flag ldmodel.FeatureFlag) (bool, error)
- func UpsertSegment(store interfaces.DataStore, segment ldmodel.Segment) (bool, error)
- func WithListenerForAnyPort(t *testing.T, fn func(net.Listener, int))
- func WithStreamRequest(t *testing.T, req *http.Request, handler http.Handler, ...) *http.Response
- func WithStreamRequestLines(t *testing.T, req *http.Request, handler http.Handler, ...) *http.Response
- func WithTempDir(fn func(path string))
- type BodyMatcher
- type DataSourceThatNeverStarts
- type DataSourceThatStartsWithoutInitializing
- type ExistingDataSourceFactory
- type ExistingDataStoreFactory
- type NoOpSDKBigSegmentStore
- type ReceivedItemUpdate
- type SDKContextImpl
- type SDKRequestVariant
- type StreamRecorder
- type TestEnv
- type TestFlag
- type TestMetricsData
- type TestMetricsExporter
- func (e *TestMetricsExporter) AwaitData(t *testing.T, timeout time.Duration, loggers ldlog.Loggers, ...)
- func (e *TestMetricsExporter) AwaitSpan(t *testing.T, timeout time.Duration) *trace.SpanData
- func (e *TestMetricsExporter) ExportSpan(s *trace.SpanData)
- func (e *TestMetricsExporter) ExportView(viewData *view.Data)
- func (e *TestMetricsExporter) WithExporter(fn func())
- type TestMetricsRow
- type UnsupportedSDKCredential
Constants ¶
const ( // The "undefined" values are well-formed, but do not match any environment in our test data. UndefinedSDKKey = config.SDKKey("sdk-99999999-9999-4999-8999-999999999999") UndefinedMobileKey = config.MobileKey("mob-99999999-9999-4999-8999-999999999999") UndefinedEnvID = config.EnvironmentID("999999999999999999999999") // The "malformed" values contain an unsupported authorization scheme. MalformedSDKKey = config.SDKKey("fake_key sdk-99999999-9999-4999-8999-999999999999") MalformedMobileKey = config.MobileKey("fake_key mob-99999999-9999-4999-8999-999999999999") )
const SimpleUserJSON = `{"key":"userkey"}`
SimpleUserJSON is a basic user.
Variables ¶
var AllData = []ldstoretypes.Collection{ { Kind: ldstoreimpl.Features(), Items: []ldstoretypes.KeyedItemDescriptor{ {Key: Flag1ServerSide.Flag.Key, Item: FlagDesc(Flag1ServerSide.Flag)}, {Key: Flag2ServerSide.Flag.Key, Item: FlagDesc(Flag2ServerSide.Flag)}, {Key: Flag3ServerSideNotMobile.Flag.Key, Item: FlagDesc(Flag3ServerSideNotMobile.Flag)}, {Key: Flag4ClientSide.Flag.Key, Item: FlagDesc(Flag4ClientSide.Flag)}, {Key: Flag5ClientSide.Flag.Key, Item: FlagDesc(Flag5ClientSide.Flag)}, {Key: Flag6ClientSideNotMobile.Flag.Key, Item: FlagDesc(Flag6ClientSideNotMobile.Flag)}, {Key: Flag7Mobile.Flag.Key, Item: FlagDesc(Flag7Mobile.Flag)}, }, }, { Kind: ldstoreimpl.Segments(), Items: []ldstoretypes.KeyedItemDescriptor{ {Key: Segment1.Key, Item: SegmentDesc(Segment1)}, }, }, }
var AllFlags = []TestFlag{Flag1ServerSide, Flag2ServerSide, Flag3ServerSideNotMobile, Flag4ClientSide, Flag5ClientSide, Flag6ClientSideNotMobile, Flag7Mobile}
var ClientSideFlags = []TestFlag{Flag4ClientSide, Flag5ClientSide, Flag6ClientSideNotMobile}
var EnvClientSide = TestEnv{ Name: "ProjectName JSClientSideEnv", Config: config.EnvConfig{ SDKKey: config.SDKKey("sdk-98e2b0b4-2688-4a59-9810-1e0e3d7e42d1"), EnvID: config.EnvironmentID("507f1f77bcf86cd799439011"), }, }
var EnvClientSideSecureMode = TestEnv{ Name: "ProjectName JSClientSideSecureModeEnv", Config: config.EnvConfig{ SDKKey: config.SDKKey("sdk-98e2b0b4-2688-4a59-9810-1e0e3d7e42d9"), EnvID: config.EnvironmentID("507f1f77bcf86cd799439019"), SecureMode: true, }, }
var EnvMain = TestEnv{ Name: "ProjectName ServerSideEnv", Config: config.EnvConfig{ SDKKey: config.SDKKey("sdk-98e2b0b4-2688-4a59-9810-1e0e3d7e42d0"), }, }
var EnvMobile = TestEnv{ Name: "ProjectName MobileEnv", Config: config.EnvConfig{ SDKKey: config.SDKKey("sdk-98e2b0b4-2688-4a59-9810-1e0e3d7e42d2"), MobileKey: config.MobileKey("mob-98e2b0b4-2688-4a59-9810-1e0e3d7e42db"), }, }
var EnvWithAllCredentials = TestEnv{ Name: "ProjectName EnvWithAllCredentials", Config: config.EnvConfig{ SDKKey: config.SDKKey("sdk-98e2b0b4-2688-4a59-9810-2e1e4d8e52e9"), MobileKey: config.MobileKey("mob-98e2b0b4-2688-4a59-9810-1e0e3d7e42ec"), EnvID: config.EnvironmentID("507f1f77bcf86cd79943902a"), }, }
var EnvWithTTL = TestEnv{ Name: "ProjectName ServerSideEnvWithTTL", Config: config.EnvConfig{ SDKKey: config.SDKKey("sdk-98e2b0b4-2688-4a59-9810-1e0e3d7e42d5"), TTL: ct.NewOptDuration(10 * time.Minute), }, }
var Flag1ServerSide = TestFlag{ Flag: ldbuilders.NewFlagBuilder("some-flag-key").OffVariation(0).Variations(ldvalue.Bool(true)).Version(2).Build(), ExpectedValue: true, ExpectedVariation: 0, ExpectedReason: map[string]interface{}{"kind": "OFF"}, }
var Flag2ServerSide = TestFlag{ Flag: ldbuilders.NewFlagBuilder("another-flag-key").On(true).FallthroughVariation(0).Variations(ldvalue.Int(3)).Version(1).Build(), ExpectedValue: 3, ExpectedVariation: 0, ExpectedReason: map[string]interface{}{"kind": "FALLTHROUGH"}, }
var Flag3ServerSideNotMobile = TestFlag{ Flag: ldbuilders.NewFlagBuilder("off-variation-key").Version(3).ClientSideUsingMobileKey(false).Build(), ExpectedValue: nil, ExpectedReason: map[string]interface{}{"kind": "OFF"}, }
var Flag4ClientSide = TestFlag{ Flag: ldbuilders.NewFlagBuilder("client-flag-key").OffVariation(0).Variations(ldvalue.Int(5)).Version(2). ClientSideUsingEnvironmentID(true).Build(), ExpectedValue: 5, ExpectedVariation: 0, ExpectedReason: map[string]interface{}{"kind": "OFF"}, }
var Flag5ClientSide = TestFlag{ Flag: ldbuilders.NewFlagBuilder("fallthrough-experiment-flag-key").On(true).FallthroughVariation(0).Variations(ldvalue.Int(3)). TrackEventsFallthrough(true).ClientSideUsingEnvironmentID(true).Version(1).Build(), ExpectedValue: 3, ExpectedReason: map[string]interface{}{"kind": "FALLTHROUGH"}, IsExperiment: true, }
var Flag6ClientSideNotMobile = TestFlag{ Flag: ldbuilders.NewFlagBuilder("rule-match-experiment-flag-key").On(true). AddRule(ldbuilders.NewRuleBuilder().ID("rule-id").Variation(0).TrackEvents(true). Clauses(ldbuilders.Negate(ldbuilders.Clause(lduser.KeyAttribute, ldmodel.OperatorIn, ldvalue.String("not-a-real-user-key"))))). Variations(ldvalue.Int(4)).ClientSideUsingEnvironmentID(true).ClientSideUsingMobileKey(false).Version(1).Build(), ExpectedValue: 4, ExpectedReason: map[string]interface{}{"kind": "RULE_MATCH", "ruleIndex": 0, "ruleId": "rule-id"}, IsExperiment: true, }
var Flag7Mobile = TestFlag{ Flag: ldbuilders.NewFlagBuilder("mobile-flag-key").OffVariation(0).Variations(ldvalue.Int(5)).Version(2). ClientSideUsingMobileKey(true).Build(), ExpectedValue: 5, ExpectedVariation: 0, ExpectedReason: map[string]interface{}{"kind": "OFF"}, }
var MobileFlags = []TestFlag{Flag1ServerSide, Flag2ServerSide, Flag4ClientSide, Flag5ClientSide, Flag7Mobile}
var Segment1 = ldbuilders.NewSegmentBuilder("segment-key").Build()
Functions ¶
func AddQueryParam ¶
AddQueryParam is a shortcut for concatenating a query string to a URL that may or may not have one.
func AssertJSONPathMatch ¶
AssertJSONPathMatch checks for a value within a nested JSON data structure.
func BuildRequest ¶
BuildRequest is a simple shortcut for creating a request that may or may not have a body.
func BuildRequestWithAuth ¶ added in v6.2.0
func BuildRequestWithAuth(method, url string, authKey config.SDKCredential, body []byte) *http.Request
BuildRequestWithAuth creates a GET request with an Authorization header.
func CallHandlerAndAwaitStatus ¶ added in v6.1.6
func CallHandlerAndAwaitStatus(t *testing.T, handler http.Handler, req *http.Request, timeout time.Duration) int
CallHandlerAndAwaitStatus calls an HTTP handler directly with a request and then blocks until the handler has started a response, returning the response status (and cancelling the request). We use this when we don't need to wait for a complete response (or when there's no such thing as a complete response, as in the case of streaming endpoints). It raises a fatal test failure if the timeout elapses before receiving a status.
func DeletedItem ¶
func DeletedItem(version int) ldstoretypes.ItemDescriptor
func DoRequest ¶
DoRequest is a shortcut for executing an endpoint handler against a request and getting the response.
func ExpectNoStreamChEvent ¶ added in v6.4.2
ExpectNoStreamChEvent causes a test failure if an event is seen on an SSE stream channel.
func ExpectNoStreamEvent ¶ added in v6.2.0
ExpectNoStreamEvent causes a test failure if an event is seen on an SSE stream.
func ExpectNoTestRequests ¶
func ExpectNoTestRequests(t *testing.T, ch <-chan httphelpers.HTTPRequestInfo, timeout time.Duration)
ExpectNoTestRequests causes a test failure if an httphelpers request-capturing channel is not empty.
func ExpectStreamChEvent ¶ added in v6.4.2
func ExpectStreamChEvent(t *testing.T, ch <-chan eventsource.Event, timeout time.Duration) eventsource.Event
ExpectStreamChEvent is a shortcut for reading from an SSE stream channel with a timeout.
func ExpectStreamEvent ¶ added in v6.2.0
func ExpectStreamEvent(t *testing.T, stream *eventsource.Stream, timeout time.Duration) eventsource.Event
ExpectStreamEvent is a shortcut for reading from an SSE stream with a timeout.
func ExpectTestRequest ¶
func ExpectTestRequest(t *testing.T, ch <-chan httphelpers.HTTPRequestInfo, timeout time.Duration) httphelpers.HTTPRequestInfo
ExpectTestRequest is a shortcut for reading from an httphelpers request-capturing channel with a timeout.
func FlagDesc ¶
func FlagDesc(flag ldmodel.FeatureFlag) ldstoretypes.ItemDescriptor
func GetAvailablePort ¶
GetAvailablePort finds an available port (by creating and then immediately closing a listener) and returns the port number.
func MakeBasicHTTPConfig ¶ added in v6.4.0
func MakeBasicHTTPConfig() httpconfig.HTTPConfig
func MakeSDKEvalEndpointRequest ¶ added in v6.2.0
func MakeSDKEvalEndpointRequest(baseURL string, kind basictypes.SDKKind, testEnv TestEnv, userJSON string, variant SDKRequestVariant) *http.Request
func MakeSDKStreamEndpointRequest ¶ added in v6.2.0
func MakeSDKStreamEndpointRequest( baseURL string, kind basictypes.StreamKind, testEnv TestEnv, userJSON string, variant SDKRequestVariant, ) *http.Request
MakeSDKStreamEndpointRequest creates a request to one of the streaming SDK endpoints.
func MakeStoreWithData ¶
func MakeStoreWithData(initialized bool) interfaces.DataStore
func NewInMemoryStore ¶
func NewInMemoryStore() interfaces.DataStore
func SegmentDesc ¶
func SegmentDesc(segment ldmodel.Segment) ldstoretypes.ItemDescriptor
func UpsertFlag ¶
func UpsertFlag(store interfaces.DataStore, flag ldmodel.FeatureFlag) (bool, error)
func UpsertSegment ¶
func WithListenerForAnyPort ¶
WithListenerForAnyPort creates a listener for an available port, calls the function with the listener and the port number, and then closes the listener.
func WithStreamRequest ¶
func WithStreamRequest( t *testing.T, req *http.Request, handler http.Handler, action func(<-chan eventsource.Event), ) *http.Response
WithStreamRequest makes a request that should receive an SSE stream, and calls the given code with a channel that will read from that stream. A nil value is pushed to the channel when the stream closes or encounters an error.
func WithStreamRequestLines ¶
func WithTempDir ¶ added in v6.1.0
func WithTempDir(fn func(path string))
WithTempDir creates a temporary directory, calls the function with its path, then removes it.
Types ¶
type BodyMatcher ¶
func ExpectBody ¶
func ExpectBody(expectedBody string) BodyMatcher
func ExpectJSONBody ¶
func ExpectJSONBody(expectedBody string) BodyMatcher
func ExpectJSONEntity ¶
func ExpectJSONEntity(entity interface{}) BodyMatcher
type DataSourceThatNeverStarts ¶ added in v6.1.7
type DataSourceThatNeverStarts struct{}
func (DataSourceThatNeverStarts) Close ¶ added in v6.1.7
func (d DataSourceThatNeverStarts) Close() error
func (DataSourceThatNeverStarts) IsInitialized ¶ added in v6.1.7
func (d DataSourceThatNeverStarts) IsInitialized() bool
func (DataSourceThatNeverStarts) Start ¶ added in v6.1.7
func (d DataSourceThatNeverStarts) Start(chan<- struct{})
type DataSourceThatStartsWithoutInitializing ¶ added in v6.1.7
type DataSourceThatStartsWithoutInitializing struct{}
func (DataSourceThatStartsWithoutInitializing) Close ¶ added in v6.1.7
func (d DataSourceThatStartsWithoutInitializing) Close() error
func (DataSourceThatStartsWithoutInitializing) IsInitialized ¶ added in v6.1.7
func (d DataSourceThatStartsWithoutInitializing) IsInitialized() bool
func (DataSourceThatStartsWithoutInitializing) Start ¶ added in v6.1.7
func (d DataSourceThatStartsWithoutInitializing) Start(closeWhenReady chan<- struct{})
type ExistingDataSourceFactory ¶ added in v6.1.7
type ExistingDataSourceFactory struct{ Instance interfaces.DataSource }
func (ExistingDataSourceFactory) CreateDataSource ¶ added in v6.1.7
func (f ExistingDataSourceFactory) CreateDataSource( context interfaces.ClientContext, updates interfaces.DataSourceUpdates, ) (interfaces.DataSource, error)
type ExistingDataStoreFactory ¶
type ExistingDataStoreFactory struct {
Instance interfaces.DataStore
}
func (ExistingDataStoreFactory) CreateDataStore ¶
func (f ExistingDataStoreFactory) CreateDataStore( interfaces.ClientContext, interfaces.DataStoreUpdates, ) (interfaces.DataStore, error)
type NoOpSDKBigSegmentStore ¶ added in v6.4.2
type NoOpSDKBigSegmentStore struct{}
NoOpSDKBigSegmentStore is a stub implementation of the SDK's BigSegmentStore (not the type of the same name that Relay uses internally).
func (*NoOpSDKBigSegmentStore) Close ¶ added in v6.4.2
func (m *NoOpSDKBigSegmentStore) Close() error
func (*NoOpSDKBigSegmentStore) GetMetadata ¶ added in v6.4.2
func (m *NoOpSDKBigSegmentStore) GetMetadata() (interfaces.BigSegmentStoreMetadata, error)
func (*NoOpSDKBigSegmentStore) GetUserMembership ¶ added in v6.4.2
func (m *NoOpSDKBigSegmentStore) GetUserMembership( userHash string, ) (interfaces.BigSegmentMembership, error)
type ReceivedItemUpdate ¶
type ReceivedItemUpdate struct { Kind ldstoretypes.DataKind Key string Item ldstoretypes.ItemDescriptor }
type SDKContextImpl ¶
type SDKContextImpl struct {
// contains filtered or unexported fields
}
func (SDKContextImpl) GetBasic ¶
func (s SDKContextImpl) GetBasic() interfaces.BasicConfiguration
func (SDKContextImpl) GetHTTP ¶
func (s SDKContextImpl) GetHTTP() interfaces.HTTPConfiguration
func (SDKContextImpl) GetLogging ¶
func (s SDKContextImpl) GetLogging() interfaces.LoggingConfiguration
type SDKRequestVariant ¶ added in v6.2.0
type SDKRequestVariant int
SDKRequestVariant represents distinctions between endpoints that are not described in full by basictypes.SDKKind or basictypes.StreamKind.
const ( // Evalx indicates that a client-side request wants the "evalx" format rather than the older // value-only format. Evalx SDKRequestVariant = 2 // ReportMode means a client-side request should be done with REPORT rather than GET. ReportMode SDKRequestVariant = 4 )
type StreamRecorder ¶
type StreamRecorder struct { *bufio.Writer *httptest.ResponseRecorder }
StreamRecorder is an extension of ResponseRecorder to handle streaming content.
func NewStreamRecorder ¶
func NewStreamRecorder() (StreamRecorder, io.Reader)
func (StreamRecorder) Flush ¶
func (r StreamRecorder) Flush()
type TestFlag ¶
type TestFlag struct { Flag ldmodel.FeatureFlag ExpectedValue interface{} ExpectedVariation int ExpectedReason map[string]interface{} IsExperiment bool }
type TestMetricsData ¶
type TestMetricsData map[string][]TestMetricsRow
TestMetricsData is a map of OpenCensus view names to row data.
func (TestMetricsData) HasRow ¶
func (d TestMetricsData) HasRow(viewName string, expectedRow TestMetricsRow) bool
HasRow returns true if this row exists for the specified view name.
type TestMetricsExporter ¶
type TestMetricsExporter struct {
// contains filtered or unexported fields
}
TestMetricsExporter accumulates OpenCensus metrics for tests. It deaggregates the view data to make it easier to test for a specific row that we expect to see in the data.
func NewTestMetricsExporter ¶
func NewTestMetricsExporter() *TestMetricsExporter
NewTestMetricsExporter creates a TestMetricsExporter.
func (*TestMetricsExporter) AwaitData ¶
func (e *TestMetricsExporter) AwaitData(t *testing.T, timeout time.Duration, loggers ldlog.Loggers, fn func(TestMetricsData) bool)
AwaitData waits until matching view data is received.
func (*TestMetricsExporter) ExportSpan ¶
func (e *TestMetricsExporter) ExportSpan(s *trace.SpanData)
ExportSpan is called by OpenCensus.
func (*TestMetricsExporter) ExportView ¶
func (e *TestMetricsExporter) ExportView(viewData *view.Data)
ExportView is called by OpenCensus.
func (*TestMetricsExporter) WithExporter ¶
func (e *TestMetricsExporter) WithExporter(fn func())
WithExporter registers the exporter, then calls the function, then unregisters the exporter. It also overrides the default OpenCensus reporting parameters to ensure that data is exported promptly.
type TestMetricsRow ¶
TestMetricsRow is a simplified version of an OpenCensus view row.
type UnsupportedSDKCredential ¶
type UnsupportedSDKCredential struct{} // implements config.SDKCredential
func (UnsupportedSDKCredential) GetAuthorizationHeaderValue ¶
func (k UnsupportedSDKCredential) GetAuthorizationHeaderValue() string
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package testclient contains test helpers that reference the SDK-related packages.
|
Package testclient contains test helpers that reference the SDK-related packages. |
Package testenv contains test helpers that reference the relayenv package.
|
Package testenv contains test helpers that reference the relayenv package. |
Package testsuites contains shared test suites that should be run against every version of Relay to validate the behavior of the core code.
|
Package testsuites contains shared test suites that should be run against every version of Relay to validate the behavior of the core code. |