Skip to content

Commit a889661

Browse files
authored
feat: Add instance-id capability to ensure headers are set (#287)
1 parent 72d8a81 commit a889661

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed

docs/service_spec.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ v4 of the event schema originally required a `contextKeys` property on several d
104104

105105
This capability is a superset of `"inline-context"`, as it was introduced afterwards.
106106

107+
#### Capability `"instance-id"`
108+
109+
Supports sending the `X-LaunchDarkly-Instance-Id` header in HTTP requests.
110+
107111
#### Capability `"migrations"`
108112

109113
This means that the SDK supports technology migrations, a feature which allows customers to migrate between data sources using well-defined migration stages.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package sdktests
2+
3+
import (
4+
"time"
5+
6+
"github.com/launchdarkly/go-sdk-common/v3/ldcontext"
7+
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
8+
"github.com/launchdarkly/sdk-test-harness/v2/framework/harness"
9+
"github.com/launchdarkly/sdk-test-harness/v2/framework/ldtest"
10+
o "github.com/launchdarkly/sdk-test-harness/v2/framework/opt"
11+
"github.com/launchdarkly/sdk-test-harness/v2/servicedef"
12+
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
// CommonInstanceIDTests groups together event-related test methods that are shared between server-side and client-side.
17+
type CommonInstanceIDTests struct {
18+
commonTestsBase
19+
}
20+
21+
func NewCommonInstanceIDTests(t *ldtest.T, testName string, baseSDKConfigurers ...SDKConfigurer) CommonInstanceIDTests {
22+
return CommonInstanceIDTests{newCommonTestsBase(t, testName, baseSDKConfigurers...)}
23+
}
24+
25+
func (c CommonInstanceIDTests) Run(t *ldtest.T) {
26+
t.RequireCapability(servicedef.CapabilityInstanceID)
27+
28+
verifyRequestHeader := func(t *ldtest.T, endpoint *harness.MockEndpoint) {
29+
request := endpoint.RequireConnection(t, time.Second)
30+
assert.NotEmpty(t, request.Headers.Get("X-LaunchDarkly-Instance-Id"))
31+
}
32+
33+
t.Run("stream requests", func(t *ldtest.T) {
34+
dataSource := NewSDKDataSource(t, nil, DataSourceOptionStreaming())
35+
configurers := c.baseSDKConfigurationPlus(dataSource)
36+
if c.isClientSide {
37+
// client-side SDKs in streaming mode may *also* need a polling data source
38+
configurers = append(configurers,
39+
NewSDKDataSource(t, nil, DataSourceOptionPolling()))
40+
}
41+
_ = NewSDKClient(t, configurers...)
42+
verifyRequestHeader(t, dataSource.Endpoint())
43+
})
44+
45+
t.Run("poll requests", func(t *ldtest.T) {
46+
t.Capabilities().HasAny(servicedef.CapabilityServerSidePolling, servicedef.CapabilityClientSide)
47+
48+
dataSource := NewSDKDataSource(t, nil, DataSourceOptionPolling())
49+
_ = NewSDKClient(t, c.baseSDKConfigurationPlus(dataSource)...)
50+
verifyRequestHeader(t, dataSource.Endpoint())
51+
})
52+
53+
t.Run("event posts", func(t *ldtest.T) {
54+
dataSource := NewSDKDataSource(t, nil)
55+
events := NewSDKEventSink(t)
56+
client := NewSDKClient(t, c.baseSDKConfigurationPlus(
57+
dataSource,
58+
events)...)
59+
60+
c.sendArbitraryEvent(t, client)
61+
client.FlushEvents(t)
62+
63+
verifyRequestHeader(t, events.Endpoint())
64+
})
65+
}
66+
67+
func (c CommonInstanceIDTests) RunPHP(t *ldtest.T) {
68+
t.RequireCapability(servicedef.CapabilityInstanceID)
69+
70+
verifyRequestHeader := func(t *ldtest.T, endpoint *harness.MockEndpoint) {
71+
request := endpoint.RequireConnection(t, time.Second)
72+
assert.NotEmpty(t, request.Headers.Get("X-LaunchDarkly-Instance-Id"))
73+
}
74+
75+
t.Run("poll requests", func(t *ldtest.T) {
76+
dataSource := NewSDKDataSource(t, nil)
77+
client := NewSDKClient(t, c.baseSDKConfigurationPlus(dataSource)...)
78+
client.EvaluateFlag(t, servicedef.EvaluateFlagParams{
79+
FlagKey: "flag-key",
80+
Context: o.Some(ldcontext.New("key")),
81+
ValueType: servicedef.ValueTypeBool,
82+
DefaultValue: ldvalue.Bool(false),
83+
Detail: false,
84+
})
85+
86+
verifyRequestHeader(t, dataSource.Endpoint())
87+
})
88+
89+
t.Run("event posts", func(t *ldtest.T) {
90+
dataSource := NewSDKDataSource(t, nil)
91+
events := NewSDKEventSink(t)
92+
client := NewSDKClient(t, c.baseSDKConfigurationPlus(
93+
dataSource,
94+
events)...)
95+
96+
c.sendArbitraryEvent(t, client)
97+
client.FlushEvents(t)
98+
99+
verifyRequestHeader(t, events.Endpoint())
100+
})
101+
}

sdktests/testsuite_entry_point.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ func doAllServerSideTests(t *ldtest.T) {
8787
t.Run("big segments", doServerSideBigSegmentsTests)
8888
t.Run("service endpoints", doServerSideServiceEndpointsTests)
8989
t.Run("tags", doServerSideTagsTests)
90+
t.Run("instance id", func(t *ldtest.T) {
91+
NewCommonInstanceIDTests(t, "doServerSideInstanceIdTests").Run(t)
92+
})
9093
t.Run("secure mode hash", doServerSideSecureModeHashTests)
9194
t.Run("context type", doSDKContextTypeTests)
9295
t.Run("migrations", doServerSideMigrationTests)
@@ -101,6 +104,9 @@ func doAllClientSideTests(t *ldtest.T) {
101104
t.Run("streaming", doClientSideStreamTests)
102105
t.Run("polling", doClientSidePollTests)
103106
t.Run("tags", doClientSideTagsTests)
107+
t.Run("instance id", func(t *ldtest.T) {
108+
NewCommonInstanceIDTests(t, "doClientSideInstanceIdTests").Run(t)
109+
})
104110
t.Run("context type", doSDKContextTypeTests)
105111
t.Run("autoEnvAttributes", doClientSideAutoEnvAttributesTests)
106112
t.Run("client independence", doClientSideClientIndependenceTests)
@@ -115,6 +121,9 @@ func doAllPHPTests(t *ldtest.T) {
115121
t.Run("secure mode hash", doServerSideSecureModeHashTests)
116122
t.Run("migrations", doServerSideMigrationTests)
117123
t.Run("big segments", doServerSideBigSegmentsTests)
124+
t.Run("instance id", func(t *ldtest.T) {
125+
NewCommonInstanceIDTests(t, "doPHPInstanceIdTests").RunPHP(t)
126+
})
118127
}
119128

120129
func allImportantServerSideCapabilities() framework.Capabilities {

servicedef/service_params.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const (
3636
CapabilityETagCaching = "etag-caching"
3737
CapabilityInlineContext = "inline-context"
3838
CapabilityInlineContextAll = "inline-context-all"
39+
CapabilityInstanceID = "instance-id"
3940
CapabilityAnonymousRedaction = "anonymous-redaction"
4041
CapabilityPollingGzip = "polling-gzip"
4142
CapabilityEvaluationHooks = "evaluation-hooks"

0 commit comments

Comments
 (0)