...

Source file src/github.com/launchdarkly/go-server-sdk/v6/testhelpers/ldtestdata/test_data_source_test.go

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

     1  package ldtestdata
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/launchdarkly/go-server-sdk/v6/internal/sharedtest/mocks"
     8  
     9  	"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
    10  	"github.com/launchdarkly/go-server-sdk-evaluation/v2/ldbuilders"
    11  	"github.com/launchdarkly/go-server-sdk-evaluation/v2/ldmodel"
    12  	"github.com/launchdarkly/go-server-sdk/v6/interfaces"
    13  	"github.com/launchdarkly/go-server-sdk/v6/internal/datastore"
    14  	"github.com/launchdarkly/go-server-sdk/v6/internal/sharedtest"
    15  	"github.com/launchdarkly/go-server-sdk/v6/subsystems"
    16  	"github.com/launchdarkly/go-server-sdk/v6/subsystems/ldstoreimpl"
    17  	"github.com/launchdarkly/go-server-sdk/v6/testhelpers/ldservices"
    18  
    19  	th "github.com/launchdarkly/go-test-helpers/v3"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  	"github.com/stretchr/testify/require"
    23  )
    24  
    25  var (
    26  	threeStringValues = []ldvalue.Value{ldvalue.String("red"), ldvalue.String("green"), ldvalue.String("blue")}
    27  )
    28  
    29  type testDataSourceTestParams struct {
    30  	td      *TestDataSource
    31  	updates *mocks.MockDataSourceUpdates
    32  }
    33  
    34  func testDataSourceTest(t *testing.T, action func(testDataSourceTestParams)) {
    35  	t.Helper()
    36  	store := datastore.NewInMemoryDataStore(sharedtest.NewTestLoggers())
    37  	var p testDataSourceTestParams
    38  	p.td = DataSource()
    39  	p.updates = mocks.NewMockDataSourceUpdates(store)
    40  	action(p)
    41  }
    42  
    43  func (p testDataSourceTestParams) withDataSource(t *testing.T, action func(subsystems.DataSource)) {
    44  	t.Helper()
    45  	context := subsystems.BasicClientContext{DataSourceUpdateSink: p.updates}
    46  	ds, err := p.td.Build(context)
    47  	require.NoError(t, err)
    48  	defer ds.Close()
    49  
    50  	closer := make(chan struct{})
    51  	ds.Start(closer)
    52  	if !th.AssertChannelClosed(t, closer, time.Millisecond, "start did not close channel") {
    53  		t.FailNow()
    54  	}
    55  	p.updates.RequireStatusOf(t, interfaces.DataSourceStateValid)
    56  
    57  	action(ds)
    58  }
    59  
    60  func TestTestDataSource(t *testing.T) {
    61  	t.Run("initializes with empty data", func(t *testing.T) {
    62  		testDataSourceTest(t, func(p testDataSourceTestParams) {
    63  			p.withDataSource(t, func(ds subsystems.DataSource) {
    64  				expectedData := ldservices.NewServerSDKData()
    65  				p.updates.DataStore.WaitForInit(t, expectedData, time.Millisecond)
    66  				assert.True(t, ds.IsInitialized())
    67  			})
    68  		})
    69  	})
    70  
    71  	t.Run("initializes with flags", func(t *testing.T) {
    72  		testDataSourceTest(t, func(p testDataSourceTestParams) {
    73  			p.td.Update(p.td.Flag("flag1").On(true)).
    74  				Update(p.td.Flag("flag2").On(false))
    75  
    76  			p.withDataSource(t, func(subsystems.DataSource) {
    77  				initData := p.updates.DataStore.WaitForNextInit(t, time.Millisecond)
    78  				dataMap := sharedtest.DataSetToMap(initData)
    79  				require.Len(t, dataMap, 2)
    80  				flags := dataMap[ldstoreimpl.Features()]
    81  				require.Len(t, flags, 2)
    82  
    83  				assert.Equal(t, 1, flags["flag1"].Version)
    84  				assert.Equal(t, 1, flags["flag2"].Version)
    85  				assert.True(t, flags["flag1"].Item.(*ldmodel.FeatureFlag).On)
    86  				assert.False(t, flags["flag2"].Item.(*ldmodel.FeatureFlag).On)
    87  			})
    88  		})
    89  	})
    90  
    91  	t.Run("adds flag", func(t *testing.T) {
    92  		testDataSourceTest(t, func(p testDataSourceTestParams) {
    93  			p.withDataSource(t, func(subsystems.DataSource) {
    94  				p.td.Update(p.td.Flag("flag1").On(true))
    95  
    96  				up := p.updates.DataStore.WaitForUpsert(t, ldstoreimpl.Features(), "flag1", 1, time.Millisecond)
    97  				assert.True(t, up.Item.Item.(*ldmodel.FeatureFlag).On)
    98  			})
    99  		})
   100  	})
   101  
   102  	t.Run("updates flag", func(t *testing.T) {
   103  		testDataSourceTest(t, func(p testDataSourceTestParams) {
   104  			p.td.Update(p.td.Flag("flag1").On(false))
   105  
   106  			p.withDataSource(t, func(subsystems.DataSource) {
   107  				p.td.Update(p.td.Flag("flag1").On(true))
   108  
   109  				up := p.updates.DataStore.WaitForUpsert(t, ldstoreimpl.Features(), "flag1", 2, time.Millisecond)
   110  				assert.True(t, up.Item.Item.(*ldmodel.FeatureFlag).On)
   111  			})
   112  		})
   113  	})
   114  
   115  	t.Run("updates status", func(t *testing.T) {
   116  		testDataSourceTest(t, func(p testDataSourceTestParams) {
   117  			p.withDataSource(t, func(subsystems.DataSource) {
   118  				ei := interfaces.DataSourceErrorInfo{Kind: interfaces.DataSourceErrorKindNetworkError}
   119  				p.td.UpdateStatus(interfaces.DataSourceStateInterrupted, ei)
   120  
   121  				status := p.updates.RequireStatusOf(t, interfaces.DataSourceStateInterrupted)
   122  				assert.Equal(t, ei, status.LastError)
   123  			})
   124  		})
   125  	})
   126  
   127  	t.Run("adds or updates preconfigured flag", func(t *testing.T) {
   128  		flagv1 := ldbuilders.NewFlagBuilder("flagkey").Version(1).On(true).TrackEvents(true).Build()
   129  		testDataSourceTest(t, func(p testDataSourceTestParams) {
   130  			p.withDataSource(t, func(subsystems.DataSource) {
   131  				p.td.UsePreconfiguredFlag(flagv1)
   132  
   133  				up := p.updates.DataStore.WaitForUpsert(t, ldstoreimpl.Features(), flagv1.Key, 1, time.Millisecond)
   134  				assert.Equal(t, &flagv1, up.Item.Item.(*ldmodel.FeatureFlag))
   135  
   136  				updatedFlag := flagv1
   137  				updatedFlag.On = false
   138  				expectedFlagV2 := updatedFlag
   139  				expectedFlagV2.Version = 2
   140  				p.td.UsePreconfiguredFlag(updatedFlag)
   141  
   142  				up = p.updates.DataStore.WaitForUpsert(t, ldstoreimpl.Features(), flagv1.Key, 2, time.Millisecond)
   143  				assert.Equal(t, &expectedFlagV2, up.Item.Item.(*ldmodel.FeatureFlag))
   144  			})
   145  		})
   146  	})
   147  
   148  	t.Run("adds or updates preconfigured segment", func(t *testing.T) {
   149  		segmentv1 := ldbuilders.NewSegmentBuilder("segmentkey").Version(1).Included("a").Build()
   150  		testDataSourceTest(t, func(p testDataSourceTestParams) {
   151  			p.withDataSource(t, func(subsystems.DataSource) {
   152  				p.td.UsePreconfiguredSegment(segmentv1)
   153  
   154  				up := p.updates.DataStore.WaitForUpsert(t, ldstoreimpl.Segments(), segmentv1.Key, 1, time.Millisecond)
   155  				assert.Equal(t, &segmentv1, up.Item.Item.(*ldmodel.Segment))
   156  
   157  				updatedSegment := segmentv1
   158  				updatedSegment.Included = []string{"b"}
   159  				expectedSegmentV2 := updatedSegment
   160  				expectedSegmentV2.Version = 2
   161  				p.td.UsePreconfiguredSegment(updatedSegment)
   162  
   163  				up = p.updates.DataStore.WaitForUpsert(t, ldstoreimpl.Segments(), segmentv1.Key, 2, time.Millisecond)
   164  				assert.Equal(t, &expectedSegmentV2, up.Item.Item.(*ldmodel.Segment))
   165  			})
   166  		})
   167  	})
   168  }
   169  

View as plain text