github.com/ava-labs/avalanchego@v1.11.11/vms/components/gas/dimensions_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package gas 5 6 import ( 7 "math" 8 "testing" 9 10 "github.com/stretchr/testify/require" 11 12 safemath "github.com/ava-labs/avalanchego/utils/math" 13 ) 14 15 func Test_Dimensions_Add(t *testing.T) { 16 tests := []struct { 17 name string 18 lhs Dimensions 19 rhs []*Dimensions 20 expected Dimensions 21 expectedErr error 22 }{ 23 { 24 name: "no error single entry", 25 lhs: Dimensions{ 26 Bandwidth: 1, 27 DBRead: 2, 28 DBWrite: 3, 29 Compute: 4, 30 }, 31 rhs: []*Dimensions{ 32 { 33 Bandwidth: 10, 34 DBRead: 20, 35 DBWrite: 30, 36 Compute: 40, 37 }, 38 }, 39 expected: Dimensions{ 40 Bandwidth: 11, 41 DBRead: 22, 42 DBWrite: 33, 43 Compute: 44, 44 }, 45 expectedErr: nil, 46 }, 47 { 48 name: "no error multiple entries", 49 lhs: Dimensions{ 50 Bandwidth: 1, 51 DBRead: 2, 52 DBWrite: 3, 53 Compute: 4, 54 }, 55 rhs: []*Dimensions{ 56 { 57 Bandwidth: 10, 58 DBRead: 20, 59 DBWrite: 30, 60 Compute: 40, 61 }, 62 { 63 Bandwidth: 100, 64 DBRead: 200, 65 DBWrite: 300, 66 Compute: 400, 67 }, 68 }, 69 expected: Dimensions{ 70 Bandwidth: 111, 71 DBRead: 222, 72 DBWrite: 333, 73 Compute: 444, 74 }, 75 expectedErr: nil, 76 }, 77 { 78 name: "bandwidth overflow", 79 lhs: Dimensions{ 80 Bandwidth: math.MaxUint64, 81 DBRead: 2, 82 DBWrite: 3, 83 Compute: 4, 84 }, 85 rhs: []*Dimensions{ 86 { 87 Bandwidth: 10, 88 DBRead: 20, 89 DBWrite: 30, 90 Compute: 40, 91 }, 92 }, 93 expected: Dimensions{ 94 Bandwidth: 0, 95 DBRead: 2, 96 DBWrite: 3, 97 Compute: 4, 98 }, 99 expectedErr: safemath.ErrOverflow, 100 }, 101 { 102 name: "db read overflow", 103 lhs: Dimensions{ 104 Bandwidth: 1, 105 DBRead: math.MaxUint64, 106 DBWrite: 3, 107 Compute: 4, 108 }, 109 rhs: []*Dimensions{ 110 { 111 Bandwidth: 10, 112 DBRead: 20, 113 DBWrite: 30, 114 Compute: 40, 115 }, 116 }, 117 expected: Dimensions{ 118 Bandwidth: 11, 119 DBRead: 0, 120 DBWrite: 3, 121 Compute: 4, 122 }, 123 expectedErr: safemath.ErrOverflow, 124 }, 125 { 126 name: "db write overflow", 127 lhs: Dimensions{ 128 Bandwidth: 1, 129 DBRead: 2, 130 DBWrite: math.MaxUint64, 131 Compute: 4, 132 }, 133 rhs: []*Dimensions{ 134 { 135 Bandwidth: 10, 136 DBRead: 20, 137 DBWrite: 30, 138 Compute: 40, 139 }, 140 }, 141 expected: Dimensions{ 142 Bandwidth: 11, 143 DBRead: 22, 144 DBWrite: 0, 145 Compute: 4, 146 }, 147 expectedErr: safemath.ErrOverflow, 148 }, 149 { 150 name: "compute overflow", 151 lhs: Dimensions{ 152 Bandwidth: 1, 153 DBRead: 2, 154 DBWrite: 3, 155 Compute: math.MaxUint64, 156 }, 157 rhs: []*Dimensions{ 158 { 159 Bandwidth: 10, 160 DBRead: 20, 161 DBWrite: 30, 162 Compute: 40, 163 }, 164 }, 165 expected: Dimensions{ 166 Bandwidth: 11, 167 DBRead: 22, 168 DBWrite: 33, 169 Compute: 0, 170 }, 171 expectedErr: safemath.ErrOverflow, 172 }, 173 } 174 for _, test := range tests { 175 t.Run(test.name, func(t *testing.T) { 176 require := require.New(t) 177 178 actual, err := test.lhs.Add(test.rhs...) 179 require.ErrorIs(err, test.expectedErr) 180 require.Equal(test.expected, actual) 181 }) 182 } 183 } 184 185 func Test_Dimensions_Sub(t *testing.T) { 186 tests := []struct { 187 name string 188 lhs Dimensions 189 rhs []*Dimensions 190 expected Dimensions 191 expectedErr error 192 }{ 193 { 194 name: "no error single entry", 195 lhs: Dimensions{ 196 Bandwidth: 11, 197 DBRead: 22, 198 DBWrite: 33, 199 Compute: 44, 200 }, 201 rhs: []*Dimensions{ 202 { 203 Bandwidth: 1, 204 DBRead: 2, 205 DBWrite: 3, 206 Compute: 4, 207 }, 208 }, 209 expected: Dimensions{ 210 Bandwidth: 10, 211 DBRead: 20, 212 DBWrite: 30, 213 Compute: 40, 214 }, 215 expectedErr: nil, 216 }, 217 { 218 name: "no error multiple entries", 219 lhs: Dimensions{ 220 Bandwidth: 11, 221 DBRead: 22, 222 DBWrite: 33, 223 Compute: 44, 224 }, 225 rhs: []*Dimensions{ 226 { 227 Bandwidth: 1, 228 DBRead: 2, 229 DBWrite: 3, 230 Compute: 4, 231 }, 232 { 233 Bandwidth: 5, 234 DBRead: 5, 235 DBWrite: 5, 236 Compute: 5, 237 }, 238 }, 239 expected: Dimensions{ 240 Bandwidth: 5, 241 DBRead: 15, 242 DBWrite: 25, 243 Compute: 35, 244 }, 245 expectedErr: nil, 246 }, 247 { 248 name: "bandwidth underflow", 249 lhs: Dimensions{ 250 Bandwidth: 11, 251 DBRead: 22, 252 DBWrite: 33, 253 Compute: 44, 254 }, 255 rhs: []*Dimensions{ 256 { 257 Bandwidth: math.MaxUint64, 258 DBRead: 2, 259 DBWrite: 3, 260 Compute: 4, 261 }, 262 }, 263 expected: Dimensions{ 264 Bandwidth: 0, 265 DBRead: 22, 266 DBWrite: 33, 267 Compute: 44, 268 }, 269 expectedErr: safemath.ErrUnderflow, 270 }, 271 { 272 name: "db read underflow", 273 lhs: Dimensions{ 274 Bandwidth: 11, 275 DBRead: 22, 276 DBWrite: 33, 277 Compute: 44, 278 }, 279 rhs: []*Dimensions{ 280 { 281 Bandwidth: 1, 282 DBRead: math.MaxUint64, 283 DBWrite: 3, 284 Compute: 4, 285 }, 286 }, 287 expected: Dimensions{ 288 Bandwidth: 10, 289 DBRead: 0, 290 DBWrite: 33, 291 Compute: 44, 292 }, 293 expectedErr: safemath.ErrUnderflow, 294 }, 295 { 296 name: "db write underflow", 297 lhs: Dimensions{ 298 Bandwidth: 11, 299 DBRead: 22, 300 DBWrite: 33, 301 Compute: 44, 302 }, 303 rhs: []*Dimensions{ 304 { 305 Bandwidth: 1, 306 DBRead: 2, 307 DBWrite: math.MaxUint64, 308 Compute: 4, 309 }, 310 }, 311 expected: Dimensions{ 312 Bandwidth: 10, 313 DBRead: 20, 314 DBWrite: 0, 315 Compute: 44, 316 }, 317 expectedErr: safemath.ErrUnderflow, 318 }, 319 { 320 name: "compute underflow", 321 lhs: Dimensions{ 322 Bandwidth: 11, 323 DBRead: 22, 324 DBWrite: 33, 325 Compute: 44, 326 }, 327 rhs: []*Dimensions{ 328 { 329 Bandwidth: 1, 330 DBRead: 2, 331 DBWrite: 3, 332 Compute: math.MaxUint64, 333 }, 334 }, 335 expected: Dimensions{ 336 Bandwidth: 10, 337 DBRead: 20, 338 DBWrite: 30, 339 Compute: 0, 340 }, 341 expectedErr: safemath.ErrUnderflow, 342 }, 343 } 344 for _, test := range tests { 345 t.Run(test.name, func(t *testing.T) { 346 require := require.New(t) 347 348 actual, err := test.lhs.Sub(test.rhs...) 349 require.ErrorIs(err, test.expectedErr) 350 require.Equal(test.expected, actual) 351 }) 352 } 353 } 354 355 func Test_Dimensions_ToGas(t *testing.T) { 356 tests := []struct { 357 name string 358 units Dimensions 359 weights Dimensions 360 expected Gas 361 expectedErr error 362 }{ 363 { 364 name: "no error", 365 units: Dimensions{ 366 Bandwidth: 1, 367 DBRead: 2, 368 DBWrite: 3, 369 Compute: 4, 370 }, 371 weights: Dimensions{ 372 Bandwidth: 1000, 373 DBRead: 100, 374 DBWrite: 10, 375 Compute: 1, 376 }, 377 expected: 1*1000 + 2*100 + 3*10 + 4*1, 378 expectedErr: nil, 379 }, 380 { 381 name: "multiplication overflow", 382 units: Dimensions{ 383 Bandwidth: 2, 384 DBRead: 1, 385 DBWrite: 1, 386 Compute: 1, 387 }, 388 weights: Dimensions{ 389 Bandwidth: math.MaxUint64, 390 DBRead: 1, 391 DBWrite: 1, 392 Compute: 1, 393 }, 394 expected: 0, 395 expectedErr: safemath.ErrOverflow, 396 }, 397 { 398 name: "addition overflow", 399 units: Dimensions{ 400 Bandwidth: 1, 401 DBRead: 1, 402 DBWrite: 0, 403 Compute: 0, 404 }, 405 weights: Dimensions{ 406 Bandwidth: math.MaxUint64, 407 DBRead: math.MaxUint64, 408 DBWrite: 1, 409 Compute: 1, 410 }, 411 expected: 0, 412 expectedErr: safemath.ErrOverflow, 413 }, 414 } 415 for _, test := range tests { 416 t.Run(test.name, func(t *testing.T) { 417 require := require.New(t) 418 419 actual, err := test.units.ToGas(test.weights) 420 require.ErrorIs(err, test.expectedErr) 421 require.Equal(test.expected, actual) 422 423 actual, err = test.weights.ToGas(test.units) 424 require.ErrorIs(err, test.expectedErr) 425 require.Equal(test.expected, actual) 426 }) 427 } 428 } 429 430 func Benchmark_Dimensions_Add(b *testing.B) { 431 lhs := Dimensions{600, 10, 10, 1000} 432 rhs := []*Dimensions{ 433 {1, 1, 1, 1}, 434 {10, 10, 10, 10}, 435 {100, 100, 100, 100}, 436 {200, 200, 200, 200}, 437 {500, 500, 500, 500}, 438 {1_000, 1_000, 1_000, 1_000}, 439 {10_000, 10_000, 10_000, 10_000}, 440 } 441 442 b.Run("single", func(b *testing.B) { 443 for i := 0; i < b.N; i++ { 444 _, _ = lhs.Add(rhs[0]) 445 } 446 }) 447 448 b.Run("multiple", func(b *testing.B) { 449 for i := 0; i < b.N; i++ { 450 _, _ = lhs.Add(rhs[0], rhs[1], rhs[2], rhs[3], rhs[4], rhs[5], rhs[6]) 451 } 452 }) 453 } 454 455 func Benchmark_Dimensions_Sub(b *testing.B) { 456 lhs := Dimensions{10_000, 10_000, 10_000, 100_000} 457 rhs := []*Dimensions{ 458 {1, 1, 1, 1}, 459 {10, 10, 10, 10}, 460 {100, 100, 100, 100}, 461 {200, 200, 200, 200}, 462 {500, 500, 500, 500}, 463 {1_000, 1_000, 1_000, 1_000}, 464 } 465 466 b.Run("single", func(b *testing.B) { 467 for i := 0; i < b.N; i++ { 468 _, _ = lhs.Sub(rhs[0]) 469 } 470 }) 471 472 b.Run("multiple", func(b *testing.B) { 473 for i := 0; i < b.N; i++ { 474 _, _ = lhs.Sub(rhs[0], rhs[1], rhs[2], rhs[3], rhs[4], rhs[5]) 475 } 476 }) 477 }