github.com/koko1123/flow-go-1@v0.29.6/fvm/meter/meter_test.go (about) 1 package meter_test 2 3 import ( 4 "fmt" 5 "math" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 "github.com/onflow/cadence/runtime/common" 12 13 "github.com/koko1123/flow-go-1/fvm/errors" 14 "github.com/koko1123/flow-go-1/fvm/meter" 15 ) 16 17 func TestWeightedComputationMetering(t *testing.T) { 18 19 t.Run("get limits", func(t *testing.T) { 20 m := meter.NewMeter( 21 meter.DefaultParameters(). 22 WithComputationLimit(1). 23 WithMemoryLimit(2), 24 ) 25 require.Equal(t, uint(1), m.TotalComputationLimit()) 26 require.Equal(t, uint64(2), m.TotalMemoryLimit()) 27 }) 28 29 t.Run("get limits max", func(t *testing.T) { 30 m := meter.NewMeter( 31 meter.DefaultParameters(). 32 WithComputationLimit(math.MaxUint32). 33 WithMemoryLimit(math.MaxUint32), 34 ) 35 require.Equal(t, uint(math.MaxUint32), m.TotalComputationLimit()) 36 require.Equal(t, uint64(math.MaxUint32), m.TotalMemoryLimit()) 37 }) 38 39 t.Run("meter computation and memory", func(t *testing.T) { 40 m := meter.NewMeter( 41 meter.DefaultParameters(). 42 WithComputationLimit(10). 43 WithComputationWeights( 44 map[common.ComputationKind]uint64{0: 1 << meter.MeterExecutionInternalPrecisionBytes}). 45 WithMemoryLimit(10). 46 WithMemoryWeights(map[common.MemoryKind]uint64{0: 1}), 47 ) 48 49 err := m.MeterComputation(0, 1) 50 require.NoError(t, err) 51 require.Equal(t, uint64(1), m.TotalComputationUsed()) 52 53 err = m.MeterComputation(0, 2) 54 require.NoError(t, err) 55 require.Equal(t, uint64(1+2), m.TotalComputationUsed()) 56 57 err = m.MeterComputation(0, 8) 58 require.Error(t, err) 59 require.True(t, errors.IsComputationLimitExceededError(err)) 60 require.Equal(t, err.Error(), errors.NewComputationLimitExceededError(10).Error()) 61 62 err = m.MeterMemory(0, 2) 63 require.NoError(t, err) 64 require.Equal(t, uint64(2), m.TotalMemoryEstimate()) 65 66 err = m.MeterMemory(0, 3) 67 require.NoError(t, err) 68 require.Equal(t, uint64(2+3), m.TotalMemoryEstimate()) 69 70 err = m.MeterMemory(0, 8) 71 require.Error(t, err) 72 require.True(t, errors.IsMemoryLimitExceededError(err)) 73 require.Equal(t, err.Error(), errors.NewMemoryLimitExceededError(10).Error()) 74 }) 75 76 t.Run("meter computation and memory with weights", func(t *testing.T) { 77 m := meter.NewMeter( 78 meter.DefaultParameters(). 79 WithComputationLimit(100). 80 WithComputationWeights( 81 map[common.ComputationKind]uint64{0: 13 << meter.MeterExecutionInternalPrecisionBytes}). 82 WithMemoryLimit(100). 83 WithMemoryWeights(map[common.MemoryKind]uint64{0: 17}), 84 ) 85 86 err := m.MeterComputation(0, 1) 87 require.NoError(t, err) 88 require.Equal(t, uint64(13), m.TotalComputationUsed()) 89 require.Equal(t, uint(1), m.ComputationIntensities()[0]) 90 91 err = m.MeterMemory(0, 2) 92 require.NoError(t, err) 93 require.Equal(t, uint64(34), m.TotalMemoryEstimate()) 94 require.Equal(t, uint(2), m.MemoryIntensities()[0]) 95 }) 96 97 t.Run("meter computation with weights lower than MeterInternalPrecisionBytes", func(t *testing.T) { 98 m := meter.NewMeter( 99 meter.DefaultParameters(). 100 WithComputationLimit(100). 101 WithComputationWeights(map[common.ComputationKind]uint64{0: 1}). 102 WithMemoryLimit(100). 103 WithMemoryWeights(map[common.MemoryKind]uint64{0: 1}), 104 ) 105 106 internalPrecisionMinusOne := uint((1 << meter.MeterExecutionInternalPrecisionBytes) - 1) 107 108 err := m.MeterComputation(0, internalPrecisionMinusOne) 109 require.NoError(t, err) 110 require.Equal(t, uint64(0), m.TotalComputationUsed()) 111 require.Equal(t, internalPrecisionMinusOne, m.ComputationIntensities()[0]) 112 113 err = m.MeterComputation(0, 1) 114 require.NoError(t, err) 115 require.Equal(t, uint64(1), m.TotalComputationUsed()) 116 require.Equal(t, uint(1<<meter.MeterExecutionInternalPrecisionBytes), m.ComputationIntensities()[0]) 117 }) 118 119 t.Run("merge meters", func(t *testing.T) { 120 compKind := common.ComputationKind(0) 121 m := meter.NewMeter( 122 meter.DefaultParameters(). 123 WithComputationLimit(9). 124 WithComputationWeights( 125 map[common.ComputationKind]uint64{0: 1 << meter.MeterExecutionInternalPrecisionBytes}). 126 WithMemoryLimit(0). 127 WithMemoryWeights(map[common.MemoryKind]uint64{0: 1}), 128 ) 129 130 err := m.MeterComputation(compKind, 1) 131 require.NoError(t, err) 132 133 child1 := meter.NewMeter(m.MeterParameters) 134 err = child1.MeterComputation(compKind, 2) 135 require.NoError(t, err) 136 137 child2 := meter.NewMeter(m.MeterParameters) 138 err = child2.MeterComputation(compKind, 3) 139 require.NoError(t, err) 140 141 child3 := meter.NewMeter(m.MeterParameters) 142 err = child3.MeterComputation(compKind, 4) 143 require.NoError(t, err) 144 145 m.MergeMeter(child1) 146 require.Equal(t, uint64(1+2), m.TotalComputationUsed()) 147 require.Equal(t, uint(1+2), m.ComputationIntensities()[compKind]) 148 149 m.MergeMeter(child2) 150 require.Equal(t, uint64(1+2+3), m.TotalComputationUsed()) 151 require.Equal(t, uint(1+2+3), m.ComputationIntensities()[compKind]) 152 153 // merge hits limit, but is accepted. 154 m.MergeMeter(child3) 155 require.Equal(t, uint64(1+2+3+4), m.TotalComputationUsed()) 156 require.Equal(t, uint(1+2+3+4), m.ComputationIntensities()[compKind]) 157 158 // error after merge (hitting limit) 159 err = m.MeterComputation(compKind, 0) 160 require.Error(t, err) 161 require.True(t, errors.IsComputationLimitExceededError(err)) 162 require.Equal(t, err.Error(), errors.NewComputationLimitExceededError(9).Error()) 163 }) 164 165 t.Run("merge meters - ignore limits", func(t *testing.T) { 166 compKind := common.ComputationKind(0) 167 m := meter.NewMeter( 168 meter.DefaultParameters(). 169 WithComputationLimit(9). 170 WithMemoryLimit(0). 171 WithComputationWeights(map[common.ComputationKind]uint64{0: 1 << meter.MeterExecutionInternalPrecisionBytes}), 172 ) 173 174 err := m.MeterComputation(compKind, 1) 175 require.NoError(t, err) 176 177 child := meter.NewMeter(m.MeterParameters) 178 err = child.MeterComputation(compKind, 1) 179 require.NoError(t, err) 180 181 // hitting limit and ignoring it 182 m.MergeMeter(child) 183 require.Equal(t, uint64(1+1), m.TotalComputationUsed()) 184 require.Equal(t, uint(1+1), m.ComputationIntensities()[compKind]) 185 }) 186 187 t.Run("merge meters - large values - computation", func(t *testing.T) { 188 m := meter.NewMeter( 189 meter.DefaultParameters(). 190 WithComputationLimit(math.MaxUint32). 191 WithComputationWeights(map[common.ComputationKind]uint64{ 192 0: math.MaxUint32 << meter.MeterExecutionInternalPrecisionBytes, 193 }), 194 ) 195 196 err := m.MeterComputation(0, 1) 197 require.NoError(t, err) 198 199 child1 := meter.NewMeter(m.MeterParameters) 200 err = child1.MeterComputation(0, 1) 201 require.NoError(t, err) 202 203 m.MergeMeter(child1) 204 205 err = m.MeterComputation(0, 0) 206 require.True(t, errors.IsComputationLimitExceededError(err)) 207 }) 208 209 t.Run("merge meters - large values - memory", func(t *testing.T) { 210 m := meter.NewMeter( 211 meter.DefaultParameters(). 212 WithMemoryLimit(math.MaxUint32). 213 WithMemoryWeights(map[common.MemoryKind]uint64{ 214 0: math.MaxUint32, 215 }), 216 ) 217 218 err := m.MeterMemory(0, 1) 219 require.NoError(t, err) 220 221 child1 := meter.NewMeter(m.MeterParameters) 222 err = child1.MeterMemory(0, 1) 223 require.NoError(t, err) 224 225 m.MergeMeter(child1) 226 227 err = m.MeterMemory(0, 0) 228 require.Error(t, err) 229 require.True(t, errors.IsMemoryLimitExceededError(err)) 230 require.Equal(t, err.Error(), errors.NewMemoryLimitExceededError(math.MaxUint32).Error()) 231 }) 232 233 t.Run("add intensity - test limits - computation", func(t *testing.T) { 234 var m *meter.Meter 235 reset := func() { 236 m = meter.NewMeter( 237 meter.DefaultParameters(). 238 WithComputationLimit(math.MaxUint32). 239 WithComputationWeights(map[common.ComputationKind]uint64{ 240 0: 0, 241 1: 1, 242 2: 1 << meter.MeterExecutionInternalPrecisionBytes, 243 3: math.MaxUint64, 244 }), 245 ) 246 } 247 248 reset() 249 err := m.MeterComputation(0, 1) 250 require.NoError(t, err) 251 require.Equal(t, uint64(0), m.TotalComputationUsed()) 252 reset() 253 err = m.MeterComputation(0, 1<<meter.MeterExecutionInternalPrecisionBytes) 254 require.NoError(t, err) 255 require.Equal(t, uint64(0), m.TotalComputationUsed()) 256 reset() 257 err = m.MeterComputation(0, math.MaxUint32) 258 require.NoError(t, err) 259 require.Equal(t, uint64(0), m.TotalComputationUsed()) 260 261 reset() 262 err = m.MeterComputation(1, 1) 263 require.NoError(t, err) 264 require.Equal(t, uint64(0), m.TotalComputationUsed()) 265 reset() 266 err = m.MeterComputation(1, 1<<meter.MeterExecutionInternalPrecisionBytes) 267 require.NoError(t, err) 268 require.Equal(t, uint64(1), m.TotalComputationUsed()) 269 reset() 270 err = m.MeterComputation(1, math.MaxUint32) 271 require.NoError(t, err) 272 require.Equal(t, uint64(1<<16-1), m.TotalComputationUsed()) 273 274 reset() 275 err = m.MeterComputation(2, 1) 276 require.NoError(t, err) 277 require.Equal(t, uint64(1), m.TotalComputationUsed()) 278 reset() 279 err = m.MeterComputation(2, 1<<meter.MeterExecutionInternalPrecisionBytes) 280 require.NoError(t, err) 281 require.Equal(t, uint64(1<<16), m.TotalComputationUsed()) 282 reset() 283 err = m.MeterComputation(2, math.MaxUint32) 284 require.NoError(t, err) 285 require.Equal(t, uint64(math.MaxUint32), m.TotalComputationUsed()) 286 287 reset() 288 err = m.MeterComputation(3, 1) 289 require.True(t, errors.IsComputationLimitExceededError(err)) 290 reset() 291 err = m.MeterComputation(3, 1<<meter.MeterExecutionInternalPrecisionBytes) 292 require.True(t, errors.IsComputationLimitExceededError(err)) 293 reset() 294 err = m.MeterComputation(3, math.MaxUint32) 295 require.True(t, errors.IsComputationLimitExceededError(err)) 296 }) 297 298 t.Run("add intensity - test limits - memory", func(t *testing.T) { 299 var m *meter.Meter 300 reset := func() { 301 m = meter.NewMeter( 302 meter.DefaultParameters(). 303 WithMemoryLimit(math.MaxUint32). 304 WithMemoryWeights(map[common.MemoryKind]uint64{ 305 0: 0, 306 1: 1, 307 2: 2, 308 3: math.MaxUint64, 309 }), 310 ) 311 } 312 313 reset() 314 err := m.MeterMemory(0, 1) 315 require.NoError(t, err) 316 require.Equal(t, uint64(0), m.TotalMemoryEstimate()) 317 reset() 318 err = m.MeterMemory(0, 1) 319 require.NoError(t, err) 320 require.Equal(t, uint64(0), m.TotalMemoryEstimate()) 321 reset() 322 err = m.MeterMemory(0, math.MaxUint32) 323 require.NoError(t, err) 324 require.Equal(t, uint64(0), m.TotalMemoryEstimate()) 325 326 reset() 327 err = m.MeterMemory(1, 1) 328 require.NoError(t, err) 329 require.Equal(t, uint64(1), m.TotalMemoryEstimate()) 330 reset() 331 err = m.MeterMemory(1, 1) 332 require.NoError(t, err) 333 require.Equal(t, uint64(1), m.TotalMemoryEstimate()) 334 reset() 335 err = m.MeterMemory(1, math.MaxUint32) 336 require.NoError(t, err) 337 require.Equal(t, uint64(math.MaxUint32), m.TotalMemoryEstimate()) 338 339 reset() 340 err = m.MeterMemory(2, 1) 341 require.NoError(t, err) 342 require.Equal(t, uint64(2), m.TotalMemoryEstimate()) 343 reset() 344 err = m.MeterMemory(2, 1) 345 require.NoError(t, err) 346 require.Equal(t, uint64(2), m.TotalMemoryEstimate()) 347 reset() 348 err = m.MeterMemory(2, math.MaxUint32) 349 require.True(t, errors.IsMemoryLimitExceededError(err)) 350 351 reset() 352 err = m.MeterMemory(3, 1) 353 require.True(t, errors.IsMemoryLimitExceededError(err)) 354 reset() 355 err = m.MeterMemory(3, 1) 356 require.True(t, errors.IsMemoryLimitExceededError(err)) 357 reset() 358 err = m.MeterMemory(3, math.MaxUint32) 359 require.True(t, errors.IsMemoryLimitExceededError(err)) 360 }) 361 } 362 363 func TestMemoryWeights(t *testing.T) { 364 for kind := common.MemoryKindUnknown + 1; kind < common.MemoryKindLast; kind++ { 365 weight, ok := meter.DefaultMemoryWeights[kind] 366 assert.True(t, ok, fmt.Sprintf("missing weight for memory kind '%s'", kind.String())) 367 assert.Greater( 368 t, 369 weight, 370 uint64(0), 371 fmt.Sprintf( 372 "weight for memory kind '%s' is not a positive integer: %d", 373 kind.String(), 374 weight, 375 ), 376 ) 377 } 378 } 379 380 func TestStorageLimits(t *testing.T) { 381 t.Run("metering storage read - within limit", func(t *testing.T) { 382 meter1 := meter.NewMeter( 383 meter.DefaultParameters(), 384 ) 385 386 key1 := meter.StorageInteractionKey{Owner: "", Key: "1"} 387 val1 := []byte{0x1, 0x2, 0x3} 388 size1 := meter.GetStorageKeyValueSizeForTesting(key1, val1) 389 390 // first read of key1 391 err := meter1.MeterStorageRead(key1, val1, false) 392 require.NoError(t, err) 393 require.Equal(t, meter1.TotalBytesReadFromStorage(), size1) 394 395 // second read of key1 396 err = meter1.MeterStorageRead(key1, val1, false) 397 require.NoError(t, err) 398 require.Equal(t, meter1.TotalBytesReadFromStorage(), size1) 399 400 // first read of key2 401 key2 := meter.StorageInteractionKey{Owner: "", Key: "2"} 402 val2 := []byte{0x3, 0x2, 0x1} 403 size2 := meter.GetStorageKeyValueSizeForTesting(key2, val2) 404 405 err = meter1.MeterStorageRead(key2, val2, false) 406 require.NoError(t, err) 407 require.Equal(t, meter1.TotalBytesReadFromStorage(), size1+size2) 408 }) 409 410 t.Run("metering storage written - within limit", func(t *testing.T) { 411 meter1 := meter.NewMeter( 412 meter.DefaultParameters(), 413 ) 414 415 key1 := meter.StorageInteractionKey{Owner: "", Key: "1"} 416 val1 := []byte{0x1, 0x2, 0x3} 417 val2 := []byte{0x1, 0x2, 0x3, 0x4} 418 419 // first write of key1 420 err := meter1.MeterStorageWrite(key1, val1, false) 421 require.NoError(t, err) 422 require.Equal(t, meter1.TotalBytesWrittenToStorage(), meter.GetStorageKeyValueSizeForTesting(key1, val1)) 423 424 // second write of key1 with val2 425 err = meter1.MeterStorageWrite(key1, val2, false) 426 require.NoError(t, err) 427 require.Equal(t, meter1.TotalBytesWrittenToStorage(), meter.GetStorageKeyValueSizeForTesting(key1, val2)) 428 429 // first write of key2 430 key2 := meter.StorageInteractionKey{Owner: "", Key: "2"} 431 err = meter1.MeterStorageWrite(key2, val2, false) 432 require.NoError(t, err) 433 require.Equal(t, meter1.TotalBytesWrittenToStorage(), 434 meter.GetStorageKeyValueSizeForTesting(key1, val2)+meter.GetStorageKeyValueSizeForTesting(key2, val2)) 435 }) 436 437 t.Run("metering storage read - exceeding limit - not enforced", func(t *testing.T) { 438 meter1 := meter.NewMeter( 439 meter.DefaultParameters().WithStorageInteractionLimit(1), 440 ) 441 442 key1 := meter.StorageInteractionKey{Owner: "", Key: "1"} 443 val1 := []byte{0x1, 0x2, 0x3} 444 445 err := meter1.MeterStorageRead(key1, val1, false /* not enforced */) 446 require.NoError(t, err) 447 require.Equal(t, meter1.TotalBytesReadFromStorage(), meter.GetStorageKeyValueSizeForTesting(key1, val1)) 448 }) 449 450 t.Run("metering storage read - exceeding limit - enforced", func(t *testing.T) { 451 testLimit := uint64(1) 452 meter1 := meter.NewMeter( 453 meter.DefaultParameters().WithStorageInteractionLimit(testLimit), 454 ) 455 456 key1 := meter.StorageInteractionKey{Owner: "", Key: "1"} 457 val1 := []byte{0x1, 0x2, 0x3} 458 459 err := meter1.MeterStorageRead(key1, val1, true /* enforced */) 460 461 ledgerInteractionLimitExceedError := errors.NewLedgerInteractionLimitExceededError( 462 meter.GetStorageKeyValueSizeForTesting(key1, val1), 463 testLimit, 464 ) 465 require.ErrorAs(t, err, &ledgerInteractionLimitExceedError) 466 }) 467 468 t.Run("metering storage written - exceeding limit - not enforced", func(t *testing.T) { 469 testLimit := uint64(1) 470 meter1 := meter.NewMeter( 471 meter.DefaultParameters().WithStorageInteractionLimit(testLimit), 472 ) 473 474 key1 := meter.StorageInteractionKey{Owner: "", Key: "1"} 475 val1 := []byte{0x1, 0x2, 0x3} 476 477 err := meter1.MeterStorageWrite(key1, val1, false /* not enforced */) 478 require.NoError(t, err) 479 }) 480 481 t.Run("metering storage written - exceeding limit - enforced", func(t *testing.T) { 482 testLimit := uint64(1) 483 meter1 := meter.NewMeter( 484 meter.DefaultParameters().WithStorageInteractionLimit(testLimit), 485 ) 486 487 key1 := meter.StorageInteractionKey{Owner: "", Key: "1"} 488 val1 := []byte{0x1, 0x2, 0x3} 489 490 err := meter1.MeterStorageWrite(key1, val1, true /* enforced */) 491 492 ledgerInteractionLimitExceedError := errors.NewLedgerInteractionLimitExceededError( 493 meter.GetStorageKeyValueSizeForTesting(key1, val1), 494 testLimit, 495 ) 496 require.ErrorAs(t, err, &ledgerInteractionLimitExceedError) 497 }) 498 499 t.Run("metering storage read and written - within limit", func(t *testing.T) { 500 meter1 := meter.NewMeter( 501 meter.DefaultParameters(), 502 ) 503 504 key1 := meter.StorageInteractionKey{Owner: "", Key: "1"} 505 key2 := meter.StorageInteractionKey{Owner: "", Key: "2"} 506 val1 := []byte{0x1, 0x2, 0x3} 507 val2 := []byte{0x1, 0x2, 0x3, 0x4} 508 size1 := meter.GetStorageKeyValueSizeForTesting(key1, val1) 509 size2 := meter.GetStorageKeyValueSizeForTesting(key2, val2) 510 511 // read of key1 512 err := meter1.MeterStorageRead(key1, val1, false) 513 require.NoError(t, err) 514 require.Equal(t, meter1.TotalBytesReadFromStorage(), size1) 515 require.Equal(t, meter1.TotalBytesOfStorageInteractions(), size1) 516 517 // write of key2 518 err = meter1.MeterStorageWrite(key2, val2, false) 519 require.NoError(t, err) 520 require.Equal(t, meter1.TotalBytesWrittenToStorage(), size2) 521 require.Equal(t, meter1.TotalBytesOfStorageInteractions(), size1+size2) 522 }) 523 524 t.Run("metering storage read and written - exceeding limit - not enforced", func(t *testing.T) { 525 key1 := meter.StorageInteractionKey{Owner: "", Key: "1"} 526 key2 := meter.StorageInteractionKey{Owner: "", Key: "2"} 527 val1 := []byte{0x1, 0x2, 0x3} 528 val2 := []byte{0x1, 0x2, 0x3, 0x4} 529 size1 := meter.GetStorageKeyValueSizeForTesting(key1, val1) 530 size2 := meter.GetStorageKeyValueSizeForTesting(key2, val2) 531 532 meter1 := meter.NewMeter( 533 meter.DefaultParameters().WithStorageInteractionLimit(size1 + size2 - 1), 534 ) 535 536 // read of key1 537 err := meter1.MeterStorageRead(key1, val1, false) 538 require.NoError(t, err) 539 require.Equal(t, meter1.TotalBytesReadFromStorage(), size1) 540 require.Equal(t, meter1.TotalBytesOfStorageInteractions(), size1) 541 542 // write of key2 543 err = meter1.MeterStorageWrite(key2, val2, false) 544 require.NoError(t, err) 545 require.Equal(t, meter1.TotalBytesWrittenToStorage(), size2) 546 require.Equal(t, meter1.TotalBytesOfStorageInteractions(), size1+size2) 547 }) 548 549 t.Run("metering storage read and written - exceeding limit - enforced", func(t *testing.T) { 550 key1 := meter.StorageInteractionKey{Owner: "", Key: "1"} 551 key2 := meter.StorageInteractionKey{Owner: "", Key: "2"} 552 val1 := []byte{0x1, 0x2, 0x3} 553 val2 := []byte{0x1, 0x2, 0x3, 0x4} 554 size1 := meter.GetStorageKeyValueSizeForTesting(key1, val1) 555 size2 := meter.GetStorageKeyValueSizeForTesting(key2, val2) 556 testLimit := size1 + size2 - 1 557 meter1 := meter.NewMeter( 558 meter.DefaultParameters().WithStorageInteractionLimit(testLimit), 559 ) 560 561 // read of key1 562 err := meter1.MeterStorageRead(key1, val1, true) 563 require.NoError(t, err) 564 require.Equal(t, meter1.TotalBytesReadFromStorage(), size1) 565 require.Equal(t, meter1.TotalBytesOfStorageInteractions(), size1) 566 567 // write of key2 568 err = meter1.MeterStorageWrite(key2, val2, true) 569 ledgerInteractionLimitExceedError := errors.NewLedgerInteractionLimitExceededError( 570 size1+size2, 571 testLimit, 572 ) 573 require.ErrorAs(t, err, &ledgerInteractionLimitExceedError) 574 }) 575 576 t.Run("merge storage metering", func(t *testing.T) { 577 // meter 1 578 meter1 := meter.NewMeter( 579 meter.DefaultParameters(), 580 ) 581 readKey1 := meter.StorageInteractionKey{Owner: "", Key: "r1"} 582 readVal1 := []byte{0x1, 0x2, 0x3} 583 readSize1 := meter.GetStorageKeyValueSizeForTesting(readKey1, readVal1) 584 err := meter1.MeterStorageRead(readKey1, readVal1, false) 585 require.NoError(t, err) 586 587 writeKey1 := meter.StorageInteractionKey{Owner: "", Key: "w1"} 588 writeVal1 := []byte{0x1, 0x2, 0x3, 0x4} 589 writeSize1 := meter.GetStorageKeyValueSizeForTesting(writeKey1, writeVal1) 590 err = meter1.MeterStorageWrite(writeKey1, writeVal1, false) 591 require.NoError(t, err) 592 593 // meter 2 594 meter2 := meter.NewMeter( 595 meter.DefaultParameters(), 596 ) 597 598 // read the same key value as meter1 599 err = meter2.MeterStorageRead(readKey1, readVal1, false) 600 require.NoError(t, err) 601 602 writeKey2 := meter.StorageInteractionKey{Owner: "", Key: "w2"} 603 writeVal2 := []byte{0x1, 0x2, 0x3, 0x4, 0x5} 604 writeSize2 := meter.GetStorageKeyValueSizeForTesting(writeKey2, writeVal2) 605 err = meter2.MeterStorageWrite(writeKey2, writeVal2, false) 606 require.NoError(t, err) 607 608 // merge 609 meter1.MergeMeter(meter2) 610 611 require.Equal(t, meter1.TotalBytesOfStorageInteractions(), readSize1*2+writeSize1+writeSize2) 612 require.Equal(t, meter1.TotalBytesReadFromStorage(), readSize1*2) 613 require.Equal(t, meter1.TotalBytesWrittenToStorage(), writeSize1+writeSize2) 614 615 storageUpdateSizeMap := meter1.GetStorageUpdateSizeMapForTesting() 616 readKey1Val, ok := storageUpdateSizeMap[readKey1] 617 require.True(t, ok) 618 require.Equal(t, readKey1Val, readSize1) // meter merge only takes child values for rw bookkeeping 619 writeKey1Val, ok := storageUpdateSizeMap[writeKey1] 620 require.True(t, ok) 621 require.Equal(t, writeKey1Val, writeSize1) 622 writeKey2Val, ok := storageUpdateSizeMap[writeKey2] 623 require.True(t, ok) 624 require.Equal(t, writeKey2Val, writeSize2) 625 }) 626 } 627 628 func TestEventLimits(t *testing.T) { 629 t.Run("metering event emit - within limit", func(t *testing.T) { 630 meter1 := meter.NewMeter( 631 meter.DefaultParameters(), 632 ) 633 634 testSize1, testSize2 := uint64(123), uint64(234) 635 636 err := meter1.MeterEmittedEvent(testSize1) 637 require.NoError(t, err) 638 require.Equal(t, testSize1, meter1.TotalEmittedEventBytes()) 639 640 err = meter1.MeterEmittedEvent(testSize2) 641 require.NoError(t, err) 642 require.Equal(t, testSize1+testSize2, meter1.TotalEmittedEventBytes()) 643 }) 644 645 t.Run("metering event emit - exceeding limit", func(t *testing.T) { 646 testSize1, testSize2 := uint64(123), uint64(234) 647 testEventLimit := testSize1 + testSize2 - 1 // make it fail at 2nd meter 648 meter1 := meter.NewMeter( 649 meter.DefaultParameters().WithEventEmitByteLimit(testEventLimit), 650 ) 651 652 err := meter1.MeterEmittedEvent(testSize1) 653 require.NoError(t, err) 654 require.Equal(t, testSize1, meter1.TotalEmittedEventBytes()) 655 656 err = meter1.MeterEmittedEvent(testSize2) 657 eventLimitExceededError := errors.NewEventLimitExceededError( 658 testSize1+testSize2, 659 testEventLimit) 660 require.ErrorAs(t, err, &eventLimitExceededError) 661 }) 662 663 t.Run("merge event metering", func(t *testing.T) { 664 // meter 1 665 meter1 := meter.NewMeter( 666 meter.DefaultParameters(), 667 ) 668 testSize1 := uint64(123) 669 err := meter1.MeterEmittedEvent(testSize1) 670 require.NoError(t, err) 671 672 // meter 2 673 meter2 := meter.NewMeter( 674 meter.DefaultParameters(), 675 ) 676 testSize2 := uint64(234) 677 err = meter2.MeterEmittedEvent(testSize2) 678 require.NoError(t, err) 679 680 // merge 681 meter1.MergeMeter(meter2) 682 require.Equal(t, testSize1+testSize2, meter1.TotalEmittedEventBytes()) 683 }) 684 }