github.com/vmware/transport-go@v1.3.4/bus/store_manager_test.go (about)

     1  // Copyright 2019-2020 VMware, Inc.
     2  // SPDX-License-Identifier: BSD-2-Clause
     3  
     4  package bus
     5  
     6  import (
     7  	"github.com/google/uuid"
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/mock"
    10  	"reflect"
    11  	"sync"
    12  	"sync/atomic"
    13  	"testing"
    14  )
    15  
    16  func createTestStoreManager() StoreManager {
    17  	return newStoreManager(GetBus())
    18  }
    19  
    20  func TestStoreManager_CreateStore(t *testing.T) {
    21  	storeManager := createTestStoreManager()
    22  	assert.NotNil(t, storeManager)
    23  
    24  	wg := sync.WaitGroup{}
    25  
    26  	for i := 0; i < 50; i++ {
    27  		wg.Add(1)
    28  		go func() {
    29  			store := storeManager.CreateStore("testStore")
    30  			assert.NotNil(t, store)
    31  			assert.Equal(t, store.GetName(), "testStore")
    32  			assert.Equal(t, store, storeManager.GetStore("testStore"))
    33  			wg.Done()
    34  		}()
    35  	}
    36  
    37  	wg.Wait()
    38  
    39  	store2 := storeManager.CreateStore("testStore2")
    40  	assert.NotEqual(t, store2, storeManager.GetStore("testStore"))
    41  }
    42  
    43  func TestStoreManager_GetStore(t *testing.T) {
    44  	storeManager := createTestStoreManager()
    45  	storeManager.CreateStore("testStore")
    46  	store := storeManager.GetStore("testStore")
    47  	assert.Equal(t, store.GetName(), "testStore")
    48  
    49  	assert.Nil(t, storeManager.GetStore("invalid-store"))
    50  }
    51  
    52  func TestStoreManager_DestroyStore(t *testing.T) {
    53  	storeManager := createTestStoreManager()
    54  	storeManager.CreateStore("testStore")
    55  
    56  	var counter int32 = 0
    57  
    58  	wg := sync.WaitGroup{}
    59  
    60  	for i := 0; i < 50; i++ {
    61  		wg.Add(1)
    62  		go func() {
    63  			if storeManager.DestroyStore("testStore") {
    64  				atomic.AddInt32(&counter, 1)
    65  			}
    66  			assert.Nil(t, storeManager.GetStore("testStore"))
    67  			wg.Done()
    68  		}()
    69  	}
    70  
    71  	wg.Wait()
    72  
    73  	// Verify that only one of the DestroyStore calls was successful (has returned true)
    74  	assert.Equal(t, counter, int32(1))
    75  }
    76  
    77  func TestStoreManager_ConfigureStoreSyncChannel(t *testing.T) {
    78  	m := createTestStoreManager()
    79  	id := uuid.New()
    80  	con := &MockBridgeConnection{Id: &id}
    81  
    82  	subId := uuid.New()
    83  	s := &MockBridgeSubscription{
    84  		Id: &subId,
    85  	}
    86  	syncChannelDst := "/topic-prefix/transport-store-sync." + id.String()
    87  	con.On("Subscribe", syncChannelDst).Return(s, nil)
    88  	con.On("SendMessage", syncChannelDst, mock.Anything).Return(nil)
    89  	m.ConfigureStoreSyncChannel(con, "/topic-prefix", "/pub-prefix")
    90  
    91  	storeManagerImpl := m.(*storeManager)
    92  
    93  	conf, ok := storeManagerImpl.syncChannels[id]
    94  	assert.True(t, ok)
    95  	assert.NotNil(t, conf.syncChannelName)
    96  	assert.Equal(t, conf.pubPrefix, "/pub-prefix/")
    97  	assert.Equal(t, conf.topicPrefix, "/topic-prefix/")
    98  	assert.Equal(t, conf.conn, con)
    99  
   100  	syncCh, _ := storeManagerImpl.eventBus.GetChannelManager().GetChannel(conf.syncChannelName)
   101  	assert.True(t, syncCh.galactic)
   102  
   103  	err := m.ConfigureStoreSyncChannel(con, "/topic-prefix", "/pub-prefix")
   104  	assert.EqualError(t, err, "store sync channel already configured for this connection")
   105  }
   106  
   107  func TestStoreManager_OpenGalacticStore(t *testing.T) {
   108  	m := createTestStoreManager()
   109  	id := uuid.New()
   110  	con := &MockBridgeConnection{Id: &id}
   111  
   112  	var s BusStore
   113  	var err error
   114  
   115  	s, err = m.OpenGalacticStore("galacticStore", con)
   116  
   117  	assert.Nil(t, s)
   118  	assert.EqualError(t, err, "sync channel is not configured for this connection")
   119  
   120  	subId := uuid.New()
   121  	sub := &MockBridgeSubscription{
   122  		Id: &subId,
   123  	}
   124  	con.On("Subscribe", mock.Anything).Return(sub, nil)
   125  	con.On("SendJSONMessage", mock.Anything, mock.Anything).Return(nil)
   126  	con.On("SendMessage", mock.Anything, mock.Anything, mock.Anything).Return(nil)
   127  	m.ConfigureStoreSyncChannel(con, "/topic-prefix", "/pub-prefix")
   128  
   129  	storeManagerImpl := m.(*storeManager)
   130  
   131  	conf, _ := storeManagerImpl.syncChannels[id]
   132  	assert.NotNil(t, conf)
   133  
   134  	s, err = m.OpenGalacticStore("galacticStore", con)
   135  
   136  	assert.Nil(t, err)
   137  	assert.True(t, s.IsGalactic())
   138  
   139  	wg := sync.WaitGroup{}
   140  	wg.Add(1)
   141  
   142  	s.WhenReady(func() {
   143  		assert.Equal(t, len(s.AllValues()), 2)
   144  		assert.Equal(t, s.GetValue("id1"), "value1")
   145  		assert.Equal(t, s.GetValue("id2"), "value2")
   146  
   147  		wg.Done()
   148  	})
   149  
   150  	var jsonBlob = []byte(`{
   151          "storeId": "galacticStore",
   152          "responseType": "storeContentResponse",
   153          "items": {
   154              "id1": "value1",
   155              "id2": "value2"
   156          } 
   157      }`)
   158  
   159  	storeManagerImpl.eventBus.SendResponseMessage(conf.syncChannelName, jsonBlob, nil)
   160  	wg.Wait()
   161  }
   162  
   163  type MockStoreItem struct {
   164  	From    string `json:"from"`
   165  	Message string `json:"message"`
   166  }
   167  
   168  func TestStoreManager_OpenGalacticStoreWithType(t *testing.T) {
   169  	m := createTestStoreManager()
   170  	id := uuid.New()
   171  	con := &MockBridgeConnection{Id: &id}
   172  
   173  	subId := uuid.New()
   174  	sub := &MockBridgeSubscription{
   175  		Id: &subId,
   176  	}
   177  	con.On("Subscribe", mock.Anything).Return(sub, nil)
   178  	con.On("SendJSONMessage", mock.Anything, mock.Anything).Return(nil)
   179  	con.On("SendMessage", mock.Anything, mock.Anything).Return(nil)
   180  	m.ConfigureStoreSyncChannel(con, "/topic-prefix", "/pub-prefix")
   181  
   182  	storeManagerImpl := m.(*storeManager)
   183  
   184  	conf, _ := storeManagerImpl.syncChannels[id]
   185  	assert.NotNil(t, conf)
   186  
   187  	store, _ := m.OpenGalacticStoreWithItemType("galacticStore", con, reflect.TypeOf(MockStoreItem{}))
   188  
   189  	store2, err := m.OpenGalacticStoreWithItemType("galacticStore", con, reflect.TypeOf(MockStoreItem{}))
   190  
   191  	assert.Equal(t, store, store2)
   192  	assert.Nil(t, err)
   193  
   194  	assert.True(t, store.IsGalactic())
   195  
   196  	wg := sync.WaitGroup{}
   197  	wg.Add(1)
   198  
   199  	store.WhenReady(func() {
   200  
   201  		assert.Equal(t, len(store.AllValues()), 1)
   202  		assert.Equal(t, store.GetValue("id1"), MockStoreItem{
   203  			From:    "test-user",
   204  			Message: "test-message",
   205  		})
   206  
   207  		wg.Done()
   208  	})
   209  
   210  	var jsonBlob = []byte(`{
   211          "storeId": "galacticStore",
   212          "responseType": "storeContentResponse",
   213          "items": {
   214              "id1": {
   215                  "from": "test-user",
   216                  "message": "test-message"
   217              }
   218          } 
   219      }`)
   220  
   221  	storeManagerImpl.eventBus.SendResponseMessage(conf.syncChannelName, jsonBlob, nil)
   222  	wg.Wait()
   223  }
   224  
   225  func TestStoreManager_OpenGalacticStoreWithLocalStoreId(t *testing.T) {
   226  
   227  	m := createTestStoreManager()
   228  	id := uuid.New()
   229  	con := &MockBridgeConnection{Id: &id}
   230  	subId := uuid.New()
   231  	sub := &MockBridgeSubscription{
   232  		Id: &subId,
   233  	}
   234  	con.On("Subscribe", mock.Anything).Return(sub, nil)
   235  	con.On("SendMessage", mock.Anything, mock.Anything).Return(nil)
   236  	m.ConfigureStoreSyncChannel(con, "/topic-prefix", "/pub-prefix")
   237  
   238  	localStore := m.CreateStore("localStore")
   239  
   240  	store, err := m.OpenGalacticStoreWithItemType("localStore", con, reflect.TypeOf(MockStoreItem{}))
   241  
   242  	assert.EqualError(t, err, "cannot open galactic store: there is a local store with the same name")
   243  	assert.Equal(t, store, localStore)
   244  }