github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/in10nmem/v1/impl_test.go (about) 1 /* 2 * Copyright (c) 2021-present Sigma-Soft, Ltd. 3 * Aleksei Ponomarev 4 */ 5 6 package in10nmemv1 7 8 import ( 9 "context" 10 "strconv" 11 "sync" 12 "testing" 13 "time" 14 15 "github.com/stretchr/testify/require" 16 "github.com/voedger/voedger/pkg/appdef" 17 "github.com/voedger/voedger/pkg/in10n" 18 istructs "github.com/voedger/voedger/pkg/istructs" 19 ) 20 21 type callbackMock struct { 22 wait chan UpdateUnit 23 } 24 25 func TestBasicUsage(t *testing.T) { 26 var wg sync.WaitGroup 27 c := new(callbackMock) 28 c.wait = make(chan UpdateUnit) 29 30 projectionKeyExample := in10n.ProjectionKey{ 31 App: istructs.AppQName_test1_app1, 32 Projection: appdef.NewQName("test", "restaurant"), 33 WS: istructs.WSID(0), 34 } 35 36 quotasExample := in10n.Quotas{ 37 Channels: 1, 38 ChannelsPerSubject: 1, 39 Subscriptions: 1, 40 SubscriptionsPerSubject: 1, 41 } 42 req := require.New(t) 43 ctx, cancel := context.WithCancel(context.Background()) 44 45 broker := Provide(quotasExample) 46 47 var channel in10n.ChannelID 48 t.Run("Create channel.", func(t *testing.T) { 49 var subject istructs.SubjectLogin = "paa" 50 var err error 51 channel, err = broker.NewChannel(subject, 24*time.Hour) 52 req.NoError(err) 53 req.NotNil(channel) 54 }) 55 56 t.Run("Check channel count. count must be 1.", func(t *testing.T) { 57 numChannels := broker.MetricNumChannels() 58 req.Equal(1, numChannels) 59 }) 60 61 wg.Add(1) 62 go func() { 63 defer wg.Done() 64 broker.WatchChannel(ctx, channel, c.updatesMock) 65 }() 66 67 t.Run("Subscribe on projection.", func(t *testing.T) { 68 var notExistsChannel = "NotExistChannel" 69 // Try to subscribe on projection in not exist channel 70 // must receive error ErrChannelNotExists 71 err := broker.Subscribe(in10n.ChannelID(notExistsChannel), projectionKeyExample) 72 req.ErrorIs(err, in10n.ErrChannelDoesNotExist) 73 74 // check subscriptions, numSubscriptions must be equal 0 75 numSubscriptions := broker.MetricNumSubcriptions() 76 req.Equal(0, numSubscriptions) 77 78 // Subscribe on exist channel numSubscriptions must be equal 1 79 require.NoError(t, broker.Subscribe(channel, projectionKeyExample)) 80 numSubscriptions = broker.MetricNumSubcriptions() 81 req.Equal(1, numSubscriptions) 82 83 // Unsubscribe from not exist channel, raise error in10n.ErrChannelDoesNotExist 84 err = broker.Unsubscribe("Not exists channel", projectionKeyExample) 85 req.ErrorIs(err, in10n.ErrChannelDoesNotExist) 86 87 // Unsubscribe from exist channel 88 err = broker.Unsubscribe(channel, projectionKeyExample) 89 req.NoError(err) 90 // After unsubscribe numSubscriptions must be equal 0 91 numSubscriptions = broker.MetricNumSubcriptions() 92 req.Equal(0, numSubscriptions) 93 94 // Subscribe on exist channel numSubscriptions must be equal 1 95 require.NoError(t, broker.Subscribe(channel, projectionKeyExample)) 96 numSubscriptions = broker.MetricNumSubcriptions() 97 req.Equal(1, numSubscriptions) 98 99 }) 100 101 broker.Update(projectionKeyExample, istructs.Offset(122)) 102 broker.Update(projectionKeyExample, istructs.Offset(123)) 103 broker.Update(projectionKeyExample, istructs.Offset(124)) 104 broker.Update(projectionKeyExample, istructs.Offset(125)) 105 broker.Update(projectionKeyExample, istructs.Offset(126)) 106 107 for update := range c.wait { 108 if update.Offset == istructs.Offset(126) { 109 break 110 } 111 } 112 cancel() 113 wg.Wait() 114 } 115 116 func (c *callbackMock) updatesMock(projection in10n.ProjectionKey, offset istructs.Offset) { 117 var unit = UpdateUnit{ 118 Projection: projection, 119 Offset: offset, 120 } 121 c.wait <- unit 122 } 123 124 // Try watch on not exists channel. WatchChannel must exit. 125 func TestWatchNotExistsChannel(t *testing.T) { 126 req := require.New(t) 127 128 quotasExample := in10n.Quotas{ 129 Channels: 1, 130 ChannelsPerSubject: 1, 131 Subscriptions: 1, 132 SubscriptionsPerSubject: 1, 133 } 134 135 broker := Provide(quotasExample) 136 ctx := context.TODO() 137 138 t.Run("Create channel.", func(t *testing.T) { 139 var subject istructs.SubjectLogin = "paa" 140 channel, err := broker.NewChannel(subject, 24*time.Hour) 141 req.NoError(err) 142 req.NotNil(channel) 143 }) 144 145 t.Run("Try watch not exist channel", func(t *testing.T) { 146 req.Panics(func() { 147 broker.WatchChannel(ctx, "not exist channel id", nil) 148 }, "When try watch not exists channel - must panics") 149 150 }) 151 } 152 153 func TestQuotas(t *testing.T) { 154 req := require.New(t) 155 quotasExample := in10n.Quotas{ 156 Channels: 100, 157 ChannelsPerSubject: 10, 158 Subscriptions: 1000, 159 SubscriptionsPerSubject: 100, 160 } 161 162 t.Run("Test channel quotas per subject. We create more channels than allowed for subject.", func(t *testing.T) { 163 broker := Provide(quotasExample) 164 for i := 0; i <= 10; i++ { 165 _, err := broker.NewChannel("paa", 24*time.Hour) 166 if i == 10 { 167 req.ErrorIs(err, in10n.ErrQuotaExceeded_ChannelsPerSubject) 168 } 169 } 170 }) 171 172 t.Run("Test channel quotas for the whole service. We create more channels than allowed for service.", func(t *testing.T) { 173 broker := Provide(quotasExample) 174 var subject istructs.SubjectLogin 175 for i := 0; i < 10; i++ { 176 subject = istructs.SubjectLogin("paa" + strconv.Itoa(i)) 177 for c := 0; c <= 10; c++ { 178 _, err := broker.NewChannel(subject, 24*time.Hour) 179 if i == 9 && c == 10 { 180 req.ErrorIs(err, in10n.ErrQuotaExceeded_Channels) 181 } 182 } 183 } 184 }) 185 186 t.Run("Test subscription quotas for the whole service. We create more subscription than allowed for service.", func(t *testing.T) { 187 projectionKeyExample := in10n.ProjectionKey{ 188 App: istructs.AppQName_test1_app1, 189 Projection: appdef.NewQName("test", "restaurant"), 190 WS: istructs.WSID(1), 191 } 192 broker := Provide(quotasExample) 193 var subject istructs.SubjectLogin 194 for i := 0; i < 100; i++ { 195 subject = istructs.SubjectLogin("paa" + strconv.Itoa(i)) 196 channel, err := broker.NewChannel(subject, 24*time.Hour) 197 req.NoError(err) 198 for g := 0; g < 10; g++ { 199 projectionKeyExample.WS = istructs.WSID(i + g) 200 err = broker.Subscribe(channel, projectionKeyExample) 201 req.NoError(err) 202 if i == 99 && g == 9 { 203 numSubscriptions := broker.MetricNumSubcriptions() 204 req.Equal(1000, numSubscriptions) 205 projectionKeyExample.WS = istructs.WSID(i + 100000) 206 err = broker.Subscribe(channel, projectionKeyExample) 207 req.ErrorIs(err, in10n.ErrQuotaExceeded_Subsciptions) 208 } 209 } 210 } 211 212 }) 213 214 }