code.vegaprotocol.io/vega@v0.79.0/core/matching/snapshot_test.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 matching_test 17 18 import ( 19 "bytes" 20 "context" 21 "testing" 22 23 "code.vegaprotocol.io/vega/core/matching" 24 "code.vegaprotocol.io/vega/core/types" 25 vgcrypto "code.vegaprotocol.io/vega/libs/crypto" 26 "code.vegaprotocol.io/vega/libs/num" 27 "code.vegaprotocol.io/vega/libs/proto" 28 snapshot "code.vegaprotocol.io/vega/protos/vega/snapshot/v1" 29 30 "github.com/stretchr/testify/assert" 31 "github.com/stretchr/testify/require" 32 ) 33 34 const ( 35 market = "testing market" 36 key = market 37 party = "party" 38 ) 39 40 var priceFactor = num.DecimalFromInt64(10) 41 42 type orderdata struct { 43 id string 44 price uint64 45 size uint64 46 side types.Side 47 peggedOrder *types.PeggedOrder 48 } 49 50 func TestEmpty(t *testing.T) { 51 ob := getTestOrderBook(t, market) 52 53 payload, _, err := ob.ob.GetState(key) 54 assert.NoError(t, err) 55 assert.NotNil(t, payload) 56 57 _, _, err = ob.ob.GetState(key) 58 assert.NoError(t, err) 59 } 60 61 func TestBuyOrdersChangeState(t *testing.T) { 62 ob := getTestOrderBook(t, market) 63 64 orders := []orderdata{ 65 {id: vgcrypto.RandomHash(), price: 100, size: 10, side: types.SideBuy}, 66 {id: vgcrypto.RandomHash(), price: 101, size: 11, side: types.SideBuy}, 67 {id: vgcrypto.RandomHash(), price: 102, size: 12, side: types.SideBuy}, 68 {id: vgcrypto.RandomHash(), price: 103, size: 13, side: types.SideBuy}, 69 } 70 71 addOrders(t, ob.ob, orders) 72 73 s1, _, err := ob.ob.GetState(key) 74 assert.NoError(t, err) 75 s2, _, err := ob.ob.GetState(key) 76 assert.NoError(t, err) 77 // These should be the same 78 assert.True(t, bytes.Equal(s1, s2)) 79 80 // Add one more order and check that the state value changes 81 order := &types.Order{ 82 MarketID: market, 83 ID: vgcrypto.RandomHash(), 84 Price: num.NewUint(104), 85 Size: 14, 86 Remaining: 14, 87 Party: party, 88 Side: types.SideBuy, 89 TimeInForce: types.OrderTimeInForceGTC, 90 Type: types.OrderTypeLimit, 91 CreatedAt: 1010, 92 } 93 orderConf, err := ob.ob.SubmitOrder(order) 94 assert.NotNil(t, orderConf) 95 assert.NoError(t, err) 96 97 s3, _, err := ob.ob.GetState(key) 98 assert.NoError(t, err) 99 assert.False(t, bytes.Equal(s1, s3)) 100 } 101 102 func TestSellOrdersChangeState(t *testing.T) { 103 ob := getTestOrderBook(t, market) 104 105 orders := []orderdata{ 106 {id: vgcrypto.RandomHash(), price: 100, size: 10, side: types.SideSell}, 107 {id: vgcrypto.RandomHash(), price: 101, size: 11, side: types.SideSell}, 108 {id: vgcrypto.RandomHash(), price: 102, size: 12, side: types.SideSell}, 109 {id: vgcrypto.RandomHash(), price: 103, size: 13, side: types.SideSell}, 110 } 111 addOrders(t, ob.ob, orders) 112 113 s1, _, err := ob.ob.GetState(key) 114 assert.NoError(t, err) 115 s2, _, err := ob.ob.GetState(key) 116 assert.NoError(t, err) 117 // These should be the same 118 assert.True(t, bytes.Equal(s1, s2)) 119 120 // Add one more order and check that the state value changes 121 order := &types.Order{ 122 MarketID: market, 123 ID: vgcrypto.RandomHash(), 124 Price: num.NewUint(104), 125 Size: 14, 126 Remaining: 14, 127 Party: party, 128 Side: types.SideSell, 129 TimeInForce: types.OrderTimeInForceGTC, 130 Type: types.OrderTypeLimit, 131 CreatedAt: 1010, 132 } 133 orderConf, err := ob.ob.SubmitOrder(order) 134 assert.NotNil(t, orderConf) 135 assert.NoError(t, err) 136 137 s3, _, err := ob.ob.GetState(key) 138 assert.NoError(t, err) 139 assert.False(t, bytes.Equal(s1, s3)) 140 } 141 142 func addOrders(t *testing.T, ob *matching.CachedOrderBook, orders []orderdata) { 143 t.Helper() 144 baseorder := &types.Order{ 145 MarketID: market, 146 Party: party, 147 Side: types.SideSell, 148 TimeInForce: types.OrderTimeInForceGTC, 149 Type: types.OrderTypeLimit, 150 Status: types.OrderStatusActive, 151 } 152 153 createdAt := int64(1000) 154 for _, i := range orders { 155 order := baseorder.Clone() 156 order.ID = i.id 157 order.Price = num.NewUint(i.price) 158 159 order.PeggedOrder = i.peggedOrder 160 order.Size = i.size 161 162 order.Remaining = i.size 163 order.Side = i.side 164 order.CreatedAt = createdAt 165 createdAt++ 166 167 pf, _ := num.UintFromDecimal(priceFactor) 168 order.OriginalPrice = order.Price.Clone() 169 order.OriginalPrice.Div(order.Price, pf) 170 171 orderConf, err := ob.SubmitOrder(order) 172 assert.NotNil(t, orderConf) 173 assert.NoError(t, err) 174 } 175 } 176 177 func TestSaveAndLoadSnapshot(t *testing.T) { 178 ob := getTestOrderBook(t, market) 179 180 // Add some orders 181 orders := []orderdata{ 182 {id: vgcrypto.RandomHash(), price: 99, size: 10, side: types.SideBuy}, 183 {id: vgcrypto.RandomHash(), price: 100, size: 11, side: types.SideBuy}, 184 {id: vgcrypto.RandomHash(), price: 102, size: 12, side: types.SideSell}, 185 {id: vgcrypto.RandomHash(), price: 103, size: 13, side: types.SideSell}, 186 } 187 addOrders(t, ob.ob, orders) 188 189 // now add some pegged orders 190 details := &types.PeggedOrder{ 191 Offset: num.NewUint(100), 192 Reference: types.PeggedReferenceMid, 193 } 194 peggedOrders := []orderdata{ 195 {id: vgcrypto.RandomHash(), price: 95, size: 1, side: types.SideBuy, peggedOrder: details}, 196 {id: vgcrypto.RandomHash(), price: 105, size: 1, side: types.SideSell, peggedOrder: details}, 197 {id: vgcrypto.RandomHash(), price: 95, size: 1, side: types.SideBuy, peggedOrder: details}, 198 {id: vgcrypto.RandomHash(), price: 105, size: 1, side: types.SideSell, peggedOrder: details}, 199 {id: vgcrypto.RandomHash(), price: 95, size: 1, side: types.SideBuy, peggedOrder: details}, 200 {id: vgcrypto.RandomHash(), price: 105, size: 1, side: types.SideSell, peggedOrder: details}, 201 } 202 203 addOrders(t, ob.ob, peggedOrders) 204 205 // Create a snapshot 206 payload, _, err := ob.ob.GetState(key) 207 assert.NoError(t, err) 208 209 before, _, err := ob.ob.GetState(key) 210 assert.NoError(t, err) 211 212 orders2 := []orderdata{ 213 {id: vgcrypto.RandomHash(), price: 95, size: 1, side: types.SideBuy}, 214 {id: vgcrypto.RandomHash(), price: 105, size: 1, side: types.SideSell}, 215 } 216 addOrders(t, ob.ob, orders2) 217 218 different, _, err := ob.ob.GetState(key) 219 assert.NoError(t, err) 220 221 // Load the snapshot back in 222 ob2 := getTestOrderBook(t, market) 223 snap := &snapshot.Payload{} 224 err = proto.Unmarshal(payload, snap) 225 assert.NoError(t, err) 226 ob2.ob.LoadState(context.TODO(), types.PayloadFromProto(snap)) 227 228 // Get the state and check it's the same as before 229 after, _, err := ob2.ob.GetState(key) 230 assert.NoError(t, err) 231 assert.True(t, bytes.Equal(before, after)) 232 assert.False(t, bytes.Equal(before, different)) 233 234 for _, order := range orders { 235 o2, err := ob2.ob.OrderBook.GetOrderByID(order.id) 236 require.NoError(t, err) 237 238 // all original prices should be nil until we know the price factor 239 assert.Nil(t, o2.OriginalPrice) 240 } 241 242 ob2.ob.OrderBook.RestoreWithMarketPriceFactor(priceFactor) 243 244 // now the orders should be equal 245 for _, order := range orders { 246 o1, err := ob.ob.OrderBook.GetOrderByID(order.id) 247 require.NoError(t, err) 248 249 o2, err := ob2.ob.OrderBook.GetOrderByID(order.id) 250 require.NoError(t, err) 251 assert.Equal(t, o1, o2) 252 } 253 254 assert.Equal(t, ob.ob.GetActivePeggedOrderIDs(), ob2.ob.GetActivePeggedOrderIDs()) 255 } 256 257 func TestStopSnapshotTaking(t *testing.T) { 258 ob := getTestOrderBook(t, market) 259 260 _, _, err := ob.ob.GetState(key) 261 assert.NoError(t, err) 262 _, _, err = ob.ob.GetState(key) 263 assert.NoError(t, err) 264 265 // signal to kill the engine's snapshots 266 ob.ob.StopSnapshots() 267 268 s, _, err := ob.ob.GetState(key) 269 assert.NoError(t, err) 270 assert.Nil(t, s) 271 assert.True(t, ob.ob.Stopped()) 272 }