github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/service/session_pool_test.go (about) 1 /* 2 * Copyright (C) 2018 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package service 19 20 import ( 21 "fmt" 22 "testing" 23 "time" 24 25 "github.com/mysteriumnetwork/node/mocks" 26 "github.com/mysteriumnetwork/node/pb" 27 "github.com/mysteriumnetwork/node/session" 28 sessionEvent "github.com/mysteriumnetwork/node/session/event" 29 "github.com/mysteriumnetwork/node/trace" 30 "github.com/stretchr/testify/assert" 31 ) 32 33 var ( 34 sessionExisting, _ = NewSession( 35 &Instance{ID: "1"}, 36 &pb.SessionRequest{Consumer: &pb.ConsumerInfo{Id: "deadbeef"}}, 37 trace.NewTracer(""), 38 ) 39 ) 40 41 func TestSessionPool_FindSession_Existing(t *testing.T) { 42 pool := mockPool(mocks.NewEventBus(), sessionExisting) 43 44 sessionInstance, found := pool.Find(sessionExisting.ID) 45 46 assert.True(t, found) 47 assert.Exactly(t, sessionExisting, sessionInstance) 48 } 49 50 func TestSessionPool_FindSession_Unknown(t *testing.T) { 51 storage := mockPool(mocks.NewEventBus(), sessionExisting) 52 53 sessionInstance, found := storage.Find(session.ID("unknown-id")) 54 assert.False(t, found) 55 assert.Nil(t, sessionInstance) 56 } 57 58 func TestSessionPool_Add(t *testing.T) { 59 pool := mockPool(mocks.NewEventBus(), sessionExisting) 60 sessionNew, _ := NewSession(&Instance{}, &pb.SessionRequest{}, trace.NewTracer("")) 61 62 pool.Add(sessionNew) 63 assert.Exactly( 64 t, 65 map[session.ID]*Session{sessionExisting.ID: sessionExisting, sessionNew.ID: sessionNew}, 66 pool.sessions, 67 ) 68 } 69 70 func TestSessionPool_Add_PublishesEvents(t *testing.T) { 71 // given 72 session, _ := NewSession(&Instance{}, &pb.SessionRequest{}, trace.NewTracer("")) 73 mp := mocks.NewEventBus() 74 pool := NewSessionPool(mp) 75 76 // when 77 pool.Add(session) 78 79 // then 80 assert.Eventually(t, lastEventMatches(mp, session.ID, sessionEvent.CreatedStatus), 2*time.Second, 10*time.Millisecond) 81 } 82 83 func TestSessionPool_FindByPeer(t *testing.T) { 84 pool := mockPool(mocks.NewEventBus(), sessionExisting) 85 session, ok := pool.FindBy(FindOpts{&sessionExisting.ConsumerID, ""}) 86 assert.True(t, ok) 87 assert.Equal(t, sessionExisting.ID, session.ID) 88 } 89 90 func TestSessionPool_GetAll(t *testing.T) { 91 sessionFirst, _ := NewSession(&Instance{}, &pb.SessionRequest{}, trace.NewTracer("")) 92 sessionSecond, _ := NewSession(&Instance{}, &pb.SessionRequest{}, trace.NewTracer("")) 93 94 pool := &SessionPool{ 95 sessions: map[session.ID]*Session{ 96 sessionFirst.ID: sessionFirst, 97 sessionSecond.ID: sessionSecond, 98 }, 99 } 100 101 sessions := pool.GetAll() 102 assert.Contains(t, sessions, sessionFirst) 103 assert.Contains(t, sessions, sessionSecond) 104 } 105 106 func TestSessionPool_Remove(t *testing.T) { 107 pool := mockPool(mocks.NewEventBus(), sessionExisting) 108 109 pool.Remove(sessionExisting.ID) 110 assert.Len(t, pool.sessions, 0) 111 } 112 113 func TestSessionPool_RemoveNonExisting(t *testing.T) { 114 pool := &SessionPool{ 115 sessions: map[session.ID]*Session{}, 116 publisher: mocks.NewEventBus(), 117 } 118 pool.Remove(sessionExisting.ID) 119 assert.Len(t, pool.sessions, 0) 120 } 121 122 func TestSessionPool_Remove_Does_Not_Panic(t *testing.T) { 123 pool := mockPool(mocks.NewEventBus(), sessionExisting) 124 125 sessionFirst, _ := NewSession(&Instance{}, &pb.SessionRequest{}, trace.NewTracer("")) 126 pool.Add(sessionFirst) 127 128 sessionSecond, _ := NewSession(&Instance{}, &pb.SessionRequest{}, trace.NewTracer("")) 129 pool.Add(sessionSecond) 130 131 pool.Remove(sessionFirst.ID) 132 pool.Remove(sessionSecond.ID) 133 assert.Len(t, pool.sessions, 1) 134 } 135 136 func TestSessionPool_Remove_PublishesEvents(t *testing.T) { 137 // given 138 mp := mocks.NewEventBus() 139 pool := mockPool(mp, sessionExisting) 140 141 // when 142 pool.Remove(sessionExisting.ID) 143 144 // then 145 assert.Eventually(t, lastEventMatches(mp, sessionExisting.ID, sessionEvent.RemovedStatus), 2*time.Second, 10*time.Millisecond) 146 } 147 148 func TestSessionPool_RemoveForService_PublishesEvents(t *testing.T) { 149 // given 150 mp := mocks.NewEventBus() 151 pool := mockPool(mp, sessionExisting) 152 153 // when 154 pool.RemoveForService(sessionExisting.ServiceID) 155 156 // then 157 assert.Eventually(t, lastEventMatches(mp, sessionExisting.ID, sessionEvent.RemovedStatus), 2*time.Second, 10*time.Millisecond) 158 } 159 160 func mockPool(publisher publisher, sessionInstance *Session) *SessionPool { 161 return &SessionPool{ 162 sessions: map[session.ID]*Session{sessionInstance.ID: sessionInstance}, 163 publisher: publisher, 164 } 165 } 166 167 func lastEventMatches(mp *mocks.EventBus, id session.ID, action sessionEvent.Status) func() bool { 168 return func() bool { 169 last := mp.Pop() 170 evt, ok := last.(sessionEvent.AppEventSession) 171 if !ok { 172 return false 173 } 174 return evt.Session.ID == string(id) && evt.Status == action 175 } 176 } 177 178 // to avoid compiler optimizing away our bench 179 var benchmarkSessionPoolGetAllResult int 180 181 func Benchmark_SessionPool_GetAll(b *testing.B) { 182 // Findings are as follows - with 100k sessions, we should be fine with a performance of 0.04s on my mac 183 pool := NewSessionPool(mocks.NewEventBus()) 184 sessionsToStore := 100000 185 for i := 0; i < sessionsToStore; i++ { 186 pool.Add(&Session{ID: session.ID(fmt.Sprintf("ID%v", i)), CreatedAt: time.Now()}) 187 } 188 189 var r int 190 for n := 0; n < b.N; n++ { 191 storedValues := pool.GetAll() 192 r += len(storedValues) 193 } 194 benchmarkSessionPoolGetAllResult = r 195 }