code.vegaprotocol.io/vega@v0.79.0/datanode/broker/mocks/broker_drop_in_mock.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package mocks 17 18 import ( 19 "sync" 20 21 "code.vegaprotocol.io/vega/core/events" 22 23 "github.com/golang/mock/gomock" 24 ) 25 26 // MockBroker - drop in mock that allows us to check the events themselves in unit tests (and as such ensure the state changes are correct) 27 // We're only overriding the Send and SendBatch functions. The way in which this is done shouldn't be a problem, even when using DoAndReturn, but you never know... 28 type MockBroker struct { 29 // embed the broker mock here... this is how we can end up with a drop-in replacement 30 *MockTestInterface 31 32 // settlement has a TestConcurrent test, which causes data race on this wrapped mock 33 mu *sync.Mutex 34 // all events in a map per type 35 // the last of each event type 36 // and last events for each event type by ID (e.g. latest order event given the order ID) 37 allEvts map[events.Type][]events.Event 38 lastEvts map[events.Type]events.Event 39 lastEvtsID map[events.Type]map[string]events.Event 40 } 41 42 func NewMockBroker(ctrl *gomock.Controller) *MockBroker { 43 mbi := NewMockTestInterface(ctrl) 44 return &MockBroker{ 45 MockTestInterface: mbi, 46 mu: &sync.Mutex{}, 47 allEvts: map[events.Type][]events.Event{}, 48 lastEvts: map[events.Type]events.Event{}, 49 lastEvtsID: map[events.Type]map[string]events.Event{}, 50 } 51 } 52 53 // Send - first call Send on the underlying mock, then add the argument to the various maps. 54 func (b *MockBroker) Send(event events.Event) { 55 // first call the regular mock 56 b.MockTestInterface.Send(event) 57 b.mu.Lock() 58 t := event.Type() 59 s, ok := b.allEvts[t] 60 if !ok { 61 s = []events.Event{} 62 } 63 s = append(s, event) 64 b.allEvts[t] = s 65 b.lastEvts[t] = event 66 if ok, id := isIDEvt(event); ok { 67 m, ok := b.lastEvtsID[t] 68 if !ok { 69 m = map[string]events.Event{} 70 } 71 m[id] = event 72 b.lastEvtsID[t] = m 73 } 74 b.mu.Unlock() 75 } 76 77 // GetAllByType returns all events of a given type the mock has received. 78 func (b *MockBroker) GetAllByType(t events.Type) []events.Event { 79 b.mu.Lock() 80 allEvts := b.allEvts 81 b.mu.Unlock() 82 if s, ok := allEvts[t]; ok { 83 return s 84 } 85 return nil 86 } 87 88 // GetLastByType returns the most recent event for a given type. If SendBatch was called, this is the last event of the batch. 89 func (b *MockBroker) GetLastByType(t events.Type) events.Event { 90 b.mu.Lock() 91 defer b.mu.Unlock() 92 return b.lastEvts[t] 93 } 94 95 // GetLastByTypeAndID returns the last event of a given type, for a specific identified (party, market, order, etc...) 96 // list of implemented events - and ID's used: 97 // - Order (by order ID) 98 // - Account (by account ID) 99 // - Asset (by asset ID) 100 // - Auction (by market ID) 101 // - Deposit (party ID) 102 // - Proposal (proposal ID) 103 // - LP (by party ID) 104 // - MarginLevels (party ID) 105 // - MarketData (market ID) 106 // - PosRes (market ID) 107 // - RiskFactor (market ID) 108 // - SettleDistressed (party ID) 109 // - Vote (currently PartyID, might want to use proposalID, too?) 110 // - Withdrawal (PartyID) 111 func (b *MockBroker) GetLastByTypeAndID(t events.Type, id string) events.Event { 112 b.mu.Lock() 113 m, ok := b.lastEvtsID[t] 114 b.mu.Unlock() 115 if !ok { 116 return nil 117 } 118 return m[id] 119 } 120 121 // @TODO loss socialization. Given that this is something that would impact several parties, there's most likely 122 // no real point to filtering by ID. 123 // Not implemented yet, but worth considering: 124 // - Trade 125 // - TransferResponse 126 // 127 // Implemented events: 128 // - Order (by order ID) 129 // - Account (by account ID) 130 // - Asset (by asset ID) 131 // - Auction (by market ID) 132 // - Deposit (party ID) 133 // - Proposal (proposal ID) 134 // - LP (by party ID) 135 // - MarginLevels (party ID) 136 // - MarketData (market ID) 137 // - PosRes (market ID) 138 // - RiskFactor (market ID) 139 // - SettleDistressed (party ID) 140 // - Vote (currently PartyID, might want to use proposalID, too?) 141 // - Withdrawal (PartyID) 142 func isIDEvt(e events.Event) (bool, string) { 143 switch et := e.(type) { 144 case *events.Order: 145 return true, et.Order().Id 146 case events.Order: 147 return true, et.Order().Id 148 case *events.Acc: 149 return true, et.Account().Id 150 case events.Acc: 151 return true, et.Account().Id 152 case *events.Asset: 153 return true, et.Asset().Id 154 case events.Asset: 155 return true, et.Asset().Id 156 case *events.Auction: 157 return true, et.MarketID() 158 case events.Auction: 159 return true, et.MarketID() 160 case *events.Deposit: 161 return true, et.Deposit().PartyId 162 case events.Deposit: 163 return true, et.Deposit().PartyId 164 case *events.Proposal: 165 return true, et.ProposalID() 166 case events.Proposal: 167 return true, et.ProposalID() 168 case *events.LiquidityProvision: 169 return true, et.PartyID() 170 case events.LiquidityProvision: 171 return true, et.PartyID() 172 case *events.MarginLevels: 173 return true, et.PartyID() 174 case events.MarginLevels: 175 return true, et.PartyID() 176 case *events.MarketData: 177 return true, et.MarketID() 178 case events.MarketData: 179 return true, et.MarketID() 180 case *events.PosRes: 181 return true, et.MarketID() 182 case events.PosRes: 183 return true, et.MarketID() 184 case *events.RiskFactor: 185 return true, et.MarketID() 186 case events.RiskFactor: 187 return true, et.MarketID() 188 case *events.SettleDistressed: 189 return true, et.PartyID() 190 case events.SettleDistressed: 191 return true, et.PartyID() 192 case *events.Vote: 193 return true, et.PartyID() 194 case events.Vote: 195 return true, et.PartyID() 196 case *events.Withdrawal: 197 return true, et.PartyID() 198 case events.Withdrawal: 199 return true, et.PartyID() 200 } 201 return false, "" 202 }