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 relayenv or streams package. 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 credential.SDKCredential, body []byte) *http.Request
- func CallHandlerAndAwaitStatus(t *testing.T, handler http.Handler, req *http.Request, timeout time.Duration) int
- func DataSourceThatNeverStarts() subsystems.DataSource
- func DataSourceThatStartsWithoutInitializing() subsystems.DataSource
- func DeletedItem(version int) ldstoretypes.ItemDescriptor
- func DoRequest(req *http.Request, handler http.Handler) (*http.Response, []byte)
- func ExistingInstance[T any](instance T) subsystems.ComponentConfigurer[T]
- func ExpectBody(expectedBody string) m.Matcher
- func ExpectJSONBody(expectedBody string) m.Matcher
- func ExpectJSONEntity(entity interface{}) m.Matcher
- func ExpectNoBody() m.Matcher
- 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, 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) subsystems.DataStore
- func NewInMemoryStore() subsystems.DataStore
- func SegmentDesc(segment ldmodel.Segment) ldstoretypes.ItemDescriptor
- func ToBase64(s string) string
- func UpsertFlag(store subsystems.DataStore, flag ldmodel.FeatureFlag) (bool, error)
- func UpsertSegment(store subsystems.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
- type NoOpSDKBigSegmentStore
- type ReceivedItemUpdate
- 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)}, {Key: Flag8ContextAware.Flag.Key, Item: FlagDesc(Flag8ContextAware.Flag)}, }, }, { Kind: ldstoreimpl.Segments(), Items: []ldstoretypes.KeyedItemDescriptor{ {Key: Segment1.Key, Item: SegmentDesc(Segment1)}, }, }, }
var AllFlags = []TestFlag{Flag1ServerSide, Flag2ServerSide, Flag3ServerSideNotMobile, Flag4ClientSide, Flag5ClientSide, Flag6ClientSideNotMobile, Flag7Mobile, Flag8ContextAware}
var BasicUserForTestFlags = ldcontext.New("me")
var ClientSideFlags = []TestFlag{Flag4ClientSide, Flag5ClientSide, Flag6ClientSideNotMobile, Flag8ContextAware}
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(ldattr.KeyAttr, 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 Flag8ContextAware = TestFlag{ Flag: ldbuilders.NewFlagBuilder("context-aware-flag-key"). On(true). FallthroughVariation(0). Variations(ldvalue.String("wrong"), ldvalue.String("right")). AddRule( ldbuilders.NewRuleBuilder().Variation(1).ID("r").Clauses( ldbuilders.ClauseWithKind("user", "key", "in", ldvalue.String(BasicUserForTestFlags.Key())), ), ). ClientSideUsingEnvironmentID(true). ClientSideUsingMobileKey(true). Version(1).Build(), ExpectedValue: "right", ExpectedVariation: 1, ExpectedReason: map[string]interface{}{"kind": "RULE_MATCH", "ruleId": "r", "ruleIndex": 0}, }
var MobileFlags = []TestFlag{Flag1ServerSide, Flag2ServerSide, Flag4ClientSide, Flag5ClientSide, Flag7Mobile, Flag8ContextAware}
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 ¶
func BuildRequestWithAuth(method, url string, authKey credential.SDKCredential, body []byte) *http.Request
BuildRequestWithAuth creates a GET request with an Authorization header.
func CallHandlerAndAwaitStatus ¶
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 DataSourceThatNeverStarts ¶
func DataSourceThatNeverStarts() subsystems.DataSource
func DataSourceThatStartsWithoutInitializing ¶
func DataSourceThatStartsWithoutInitializing() subsystems.DataSource
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 ExistingInstance ¶
func ExistingInstance[T any](instance T) subsystems.ComponentConfigurer[T]
func ExpectBody ¶
func ExpectJSONBody ¶
func ExpectJSONEntity ¶
func ExpectNoBody ¶
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 ¶
func MakeBasicHTTPConfig() httpconfig.HTTPConfig
func MakeEvalBody ¶
func MakeSDKEvalEndpointRequest ¶
func MakeSDKEvalEndpointRequest(baseURL string, kind basictypes.SDKKind, testEnv TestEnv, userJSON string, variant SDKRequestVariant) *http.Request
func MakeSDKStreamEndpointRequest ¶
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) subsystems.DataStore
func NewInMemoryStore ¶
func NewInMemoryStore() subsystems.DataStore
func SegmentDesc ¶
func SegmentDesc(segment ldmodel.Segment) ldstoretypes.ItemDescriptor
func UpsertFlag ¶
func UpsertFlag(store subsystems.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.
Types ¶
type NoOpSDKBigSegmentStore ¶
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 ¶
func (m *NoOpSDKBigSegmentStore) Close() error
func (*NoOpSDKBigSegmentStore) GetMembership ¶
func (m *NoOpSDKBigSegmentStore) GetMembership( contextHash string, ) (subsystems.BigSegmentMembership, error)
func (*NoOpSDKBigSegmentStore) GetMetadata ¶
func (m *NoOpSDKBigSegmentStore) GetMetadata() (subsystems.BigSegmentStoreMetadata, error)
type ReceivedItemUpdate ¶
type ReceivedItemUpdate struct { Kind ldstoretypes.DataKind Key string Item ldstoretypes.ItemDescriptor }
type SDKRequestVariant ¶
type SDKRequestVariant int
SDKRequestVariant represents distinctions between endpoints that are not described in full by basictypes.SDKKind or basictypes.StreamKind.
const ( // 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 credential.SDKCredential
func (UnsupportedSDKCredential) Compare ¶
func (k UnsupportedSDKCredential) Compare(_ credential.AutoConfig) (credential.SDKCredential, credential.Status)
func (UnsupportedSDKCredential) Defined ¶
func (k UnsupportedSDKCredential) Defined() bool
func (UnsupportedSDKCredential) GetAuthorizationHeaderValue ¶
func (k UnsupportedSDKCredential) GetAuthorizationHeaderValue() string
func (UnsupportedSDKCredential) String ¶
func (k UnsupportedSDKCredential) String() 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. |