1 package ldclient
2
3 import (
4 "bytes"
5 "io"
6 "net/http"
7 "net/url"
8 "testing"
9 "time"
10
11 "github.com/launchdarkly/go-sdk-common/v3/ldlog"
12 "github.com/launchdarkly/go-sdk-common/v3/ldlogtest"
13 "github.com/launchdarkly/go-server-sdk/v6/interfaces"
14 "github.com/launchdarkly/go-server-sdk/v6/internal/endpoints"
15 "github.com/launchdarkly/go-server-sdk/v6/ldcomponents"
16
17 th "github.com/launchdarkly/go-test-helpers/v3"
18
19 "github.com/stretchr/testify/assert"
20 "github.com/stretchr/testify/require"
21 )
22
23
24
25
26
27
28 type recordingClientFactory struct {
29 requestURLs chan url.URL
30 status int
31 }
32
33 const customURI = "http://custom/"
34
35 func mustParseURI(s string) url.URL {
36 u, err := url.Parse(s)
37 if err != nil {
38 panic(err)
39 }
40 return *u
41 }
42
43 func baseURIOf(u url.URL) url.URL {
44 u.Path = "/"
45 return u
46 }
47
48 func newRecordingClientFactory(status int) *recordingClientFactory {
49 return &recordingClientFactory{status: status, requestURLs: make(chan url.URL, 100)}
50 }
51
52 func (r *recordingClientFactory) MakeClient() *http.Client {
53 c := *http.DefaultClient
54 c.Transport = r
55 return &c
56 }
57
58 func (r *recordingClientFactory) RoundTrip(req *http.Request) (*http.Response, error) {
59 r.requestURLs <- *req.URL
60 return &http.Response{
61 StatusCode: r.status,
62 Body: io.NopCloser(bytes.NewBuffer(nil)),
63 }, nil
64 }
65
66 func (r *recordingClientFactory) requireRequest(t *testing.T) url.URL {
67 return th.RequireValue(t, r.requestURLs, time.Second, "timed out waiting for request")
68 }
69
70 func TestDefaultStreamingDataSourceBaseUri(t *testing.T) {
71 rec := newRecordingClientFactory(401)
72 config := Config{
73 Events: ldcomponents.NoEvents(),
74 HTTP: ldcomponents.HTTPConfiguration().HTTPClientFactory(rec.MakeClient),
75 }
76 client, _ := MakeCustomClient(testSdkKey, config, time.Second*5)
77 require.NotNil(t, client)
78 defer client.Close()
79 u := rec.requireRequest(t)
80 assert.Equal(t, mustParseURI(endpoints.DefaultStreamingBaseURI), baseURIOf(u))
81 }
82
83 func TestDefaultPollingDataSourceBaseUri(t *testing.T) {
84 rec := newRecordingClientFactory(401)
85 config := Config{
86 DataSource: ldcomponents.PollingDataSource(),
87 Events: ldcomponents.NoEvents(),
88 HTTP: ldcomponents.HTTPConfiguration().HTTPClientFactory(rec.MakeClient),
89 }
90 client, _ := MakeCustomClient(testSdkKey, config, time.Second*5)
91 require.NotNil(t, client)
92 defer client.Close()
93 u := rec.requireRequest(t)
94 assert.Equal(t, mustParseURI(endpoints.DefaultPollingBaseURI), baseURIOf(u))
95 }
96
97 func TestDefaultEventsBaseUri(t *testing.T) {
98 rec := newRecordingClientFactory(401)
99 config := Config{
100 DataSource: ldcomponents.ExternalUpdatesOnly(),
101 HTTP: ldcomponents.HTTPConfiguration().HTTPClientFactory(rec.MakeClient),
102 }
103 client, _ := MakeCustomClient(testSdkKey, config, time.Second*5)
104 require.NotNil(t, client)
105 defer client.Close()
106 u := rec.requireRequest(t)
107 assert.Equal(t, mustParseURI(endpoints.DefaultEventsBaseURI), baseURIOf(u))
108 }
109
110 func TestCustomStreamingBaseURI(t *testing.T) {
111 rec := newRecordingClientFactory(401)
112 mockLog := ldlogtest.NewMockLog()
113 config := Config{
114 Events: ldcomponents.NoEvents(),
115 HTTP: ldcomponents.HTTPConfiguration().HTTPClientFactory(rec.MakeClient),
116 Logging: ldcomponents.Logging().Loggers(mockLog.Loggers),
117 ServiceEndpoints: interfaces.ServiceEndpoints{Streaming: customURI},
118 }
119 client, _ := MakeCustomClient(testSdkKey, config, time.Second*5)
120 require.NotNil(t, client)
121 defer client.Close()
122
123 u := rec.requireRequest(t)
124 assert.Equal(t, mustParseURI(customURI), baseURIOf(u))
125
126 mockLog.AssertMessageMatch(t, false, ldlog.Error, "You have set custom ServiceEndpoints without specifying")
127 }
128
129 func TestCustomPollingBaseURI(t *testing.T) {
130 rec := newRecordingClientFactory(401)
131 mockLog := ldlogtest.NewMockLog()
132 config := Config{
133 DataSource: ldcomponents.PollingDataSource(),
134 Events: ldcomponents.NoEvents(),
135 HTTP: ldcomponents.HTTPConfiguration().HTTPClientFactory(rec.MakeClient),
136 Logging: ldcomponents.Logging().Loggers(mockLog.Loggers),
137 ServiceEndpoints: interfaces.ServiceEndpoints{Polling: customURI},
138 }
139 client, _ := MakeCustomClient(testSdkKey, config, time.Second*5)
140 require.NotNil(t, client)
141 defer client.Close()
142
143 u := rec.requireRequest(t)
144 assert.Equal(t, mustParseURI(customURI), baseURIOf(u))
145
146 mockLog.AssertMessageMatch(t, false, ldlog.Error, "You have set custom ServiceEndpoints without specifying")
147 }
148
149 func TestCustomEventsBaseURI(t *testing.T) {
150 rec := newRecordingClientFactory(401)
151 mockLog := ldlogtest.NewMockLog()
152 config := Config{
153 DataSource: ldcomponents.ExternalUpdatesOnly(),
154 HTTP: ldcomponents.HTTPConfiguration().HTTPClientFactory(rec.MakeClient),
155 Logging: ldcomponents.Logging().Loggers(mockLog.Loggers),
156 ServiceEndpoints: interfaces.ServiceEndpoints{Events: customURI},
157 }
158 client, _ := MakeCustomClient(testSdkKey, config, time.Second*5)
159 require.NotNil(t, client)
160 defer client.Close()
161
162 u := rec.requireRequest(t)
163 assert.Equal(t, mustParseURI(customURI), baseURIOf(u))
164
165 mockLog.AssertMessageMatch(t, false, ldlog.Error, "You have set custom ServiceEndpoints without specifying")
166 }
167
168 func TestErrorIsLoggedIfANecessaryURIIsNotSetWhenOtherCustomURIsAreSet(t *testing.T) {
169 rec := newRecordingClientFactory(401)
170
171 mockLog1 := ldlogtest.NewMockLog()
172 config1 := Config{
173 Events: ldcomponents.NoEvents(),
174 HTTP: ldcomponents.HTTPConfiguration().HTTPClientFactory(rec.MakeClient),
175 Logging: ldcomponents.Logging().Loggers(mockLog1.Loggers),
176 ServiceEndpoints: interfaces.ServiceEndpoints{Events: customURI},
177 }
178 client1, _ := MakeCustomClient(testSdkKey, config1, time.Second*5)
179 require.NotNil(t, client1)
180 client1.Close()
181 mockLog1.AssertMessageMatch(t, true, ldlog.Error,
182 "You have set custom ServiceEndpoints without specifying the Streaming base URI")
183
184 mockLog2 := ldlogtest.NewMockLog()
185 config2 := Config{
186 DataSource: ldcomponents.PollingDataSource(),
187 Events: ldcomponents.NoEvents(),
188 HTTP: ldcomponents.HTTPConfiguration().HTTPClientFactory(rec.MakeClient),
189 Logging: ldcomponents.Logging().Loggers(mockLog2.Loggers),
190 ServiceEndpoints: interfaces.ServiceEndpoints{Streaming: customURI},
191 }
192 client2, _ := MakeCustomClient(testSdkKey, config2, time.Second*5)
193 require.NotNil(t, client2)
194 client2.Close()
195 mockLog2.AssertMessageMatch(t, true, ldlog.Error,
196 "You have set custom ServiceEndpoints without specifying the Polling base URI")
197
198 mockLog3 := ldlogtest.NewMockLog()
199 config3 := Config{
200 DataSource: ldcomponents.ExternalUpdatesOnly(),
201 HTTP: ldcomponents.HTTPConfiguration().HTTPClientFactory(rec.MakeClient),
202 Logging: ldcomponents.Logging().Loggers(mockLog3.Loggers),
203 ServiceEndpoints: interfaces.ServiceEndpoints{Streaming: customURI},
204 }
205 client3, _ := MakeCustomClient(testSdkKey, config3, time.Second*5)
206 require.NotNil(t, client3)
207 client3.Close()
208 mockLog3.AssertMessageMatch(t, true, ldlog.Error,
209 "You have set custom ServiceEndpoints without specifying the Events base URI")
210 }
211
View as plain text