...

Source file src/github.com/launchdarkly/go-server-sdk/v6/ldclient_service_endpoints_test.go

Documentation: github.com/launchdarkly/go-server-sdk/v6

     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  // These tests verify that the SDK is using the expected base URIs in various configurations.
    24  // Since we need to be able to intercept requests that would normally go to the production service
    25  // endpoints, and we don't care about simulating realistic responses, we'll use a fake HTTP client
    26  // rather than an embedded server.
    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