...

Source file src/github.com/launchdarkly/go-server-sdk/v6/internal/sharedtest/mocks/mock_data_source_updates.go

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

     1  package mocks
     2  
     3  import (
     4  	"sync"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/launchdarkly/go-server-sdk/v6/interfaces"
     9  	"github.com/launchdarkly/go-server-sdk/v6/subsystems"
    10  	"github.com/launchdarkly/go-server-sdk/v6/subsystems/ldstoretypes"
    11  
    12  	th "github.com/launchdarkly/go-test-helpers/v3"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  // MockDataSourceUpdates is a mock implementation of DataSourceUpdates for testing data sources.
    18  type MockDataSourceUpdates struct {
    19  	DataStore               *CapturingDataStore
    20  	Statuses                chan interfaces.DataSourceStatus
    21  	dataStoreStatusProvider *mockDataStoreStatusProvider
    22  	lastStatus              interfaces.DataSourceStatus
    23  	lock                    sync.Mutex
    24  }
    25  
    26  // NewMockDataSourceUpdates creates an instance of MockDataSourceUpdates.
    27  //
    28  // The DataStoreStatusProvider can be nil if we are not doing a test that requires manipulation of that
    29  // component.
    30  func NewMockDataSourceUpdates(realStore subsystems.DataStore) *MockDataSourceUpdates {
    31  	dataStore := NewCapturingDataStore(realStore)
    32  	dataStoreStatusProvider := &mockDataStoreStatusProvider{
    33  		dataStore: dataStore,
    34  		status:    interfaces.DataStoreStatus{Available: true},
    35  		statusCh:  make(chan interfaces.DataStoreStatus, 10),
    36  	}
    37  	return &MockDataSourceUpdates{
    38  		DataStore:               dataStore,
    39  		Statuses:                make(chan interfaces.DataSourceStatus, 10),
    40  		dataStoreStatusProvider: dataStoreStatusProvider,
    41  	}
    42  }
    43  
    44  // Init in this test implementation, delegates to d.DataStore.CapturedUpdates.
    45  func (d *MockDataSourceUpdates) Init(allData []ldstoretypes.Collection) bool {
    46  	for _, coll := range allData {
    47  		AssertNotNil(coll.Kind)
    48  	}
    49  	err := d.DataStore.Init(allData)
    50  	return err == nil
    51  }
    52  
    53  // Upsert in this test implementation, delegates to d.DataStore.CapturedUpdates.
    54  func (d *MockDataSourceUpdates) Upsert(
    55  	kind ldstoretypes.DataKind,
    56  	key string,
    57  	newItem ldstoretypes.ItemDescriptor,
    58  ) bool {
    59  	AssertNotNil(kind)
    60  	_, err := d.DataStore.Upsert(kind, key, newItem)
    61  	return err == nil
    62  }
    63  
    64  // UpdateStatus in this test implementation, pushes a value onto the Statuses channel.
    65  func (d *MockDataSourceUpdates) UpdateStatus(
    66  	newState interfaces.DataSourceState,
    67  	newError interfaces.DataSourceErrorInfo,
    68  ) {
    69  	d.lock.Lock()
    70  	defer d.lock.Unlock()
    71  	if newState != d.lastStatus.State || newError.Kind != "" {
    72  		d.lastStatus = interfaces.DataSourceStatus{State: newState, LastError: newError}
    73  		d.Statuses <- d.lastStatus
    74  	}
    75  }
    76  
    77  // GetDataStoreStatusProvider returns a stub implementation that does not have full functionality
    78  // but enough to test a data source with.
    79  func (d *MockDataSourceUpdates) GetDataStoreStatusProvider() interfaces.DataStoreStatusProvider {
    80  	return d.dataStoreStatusProvider
    81  }
    82  
    83  // UpdateStoreStatus simulates a change in the data store status.
    84  func (d *MockDataSourceUpdates) UpdateStoreStatus(newStatus interfaces.DataStoreStatus) {
    85  	d.dataStoreStatusProvider.statusCh <- newStatus
    86  }
    87  
    88  // RequireStatusOf blocks until a new data source status is available, and verifies its state.
    89  func (d *MockDataSourceUpdates) RequireStatusOf(
    90  	t *testing.T,
    91  	newState interfaces.DataSourceState,
    92  ) interfaces.DataSourceStatus {
    93  	status := d.RequireStatus(t)
    94  	assert.Equal(t, string(newState), string(status.State))
    95  	// string conversion is due to a bug in assert with type aliases
    96  	return status
    97  }
    98  
    99  // RequireStatus blocks until a new data source status is available.
   100  func (d *MockDataSourceUpdates) RequireStatus(t *testing.T) interfaces.DataSourceStatus {
   101  	return th.RequireValue(t, d.Statuses, time.Second, "timed out waiting for new data source status")
   102  }
   103  
   104  type mockDataStoreStatusProvider struct {
   105  	dataStore subsystems.DataStore
   106  	status    interfaces.DataStoreStatus
   107  	statusCh  chan interfaces.DataStoreStatus
   108  	lock      sync.Mutex
   109  }
   110  
   111  func (m *mockDataStoreStatusProvider) GetStatus() interfaces.DataStoreStatus {
   112  	m.lock.Lock()
   113  	defer m.lock.Unlock()
   114  	return m.status
   115  }
   116  
   117  func (m *mockDataStoreStatusProvider) IsStatusMonitoringEnabled() bool {
   118  	return m.dataStore.IsStatusMonitoringEnabled()
   119  }
   120  
   121  func (m *mockDataStoreStatusProvider) AddStatusListener() <-chan interfaces.DataStoreStatus {
   122  	return m.statusCh
   123  }
   124  
   125  func (m *mockDataStoreStatusProvider) RemoveStatusListener(ch <-chan interfaces.DataStoreStatus) {
   126  }
   127  

View as plain text