gitlab.com/flarenetwork/coreth@v0.1.1/plugin/evm/gasprice_update_test.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package evm
     5  
     6  import (
     7  	"math/big"
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  
    12  	"gitlab.com/flarenetwork/coreth/params"
    13  )
    14  
    15  type mockGasPriceSetter struct {
    16  	lock          sync.Mutex
    17  	price, minFee *big.Int
    18  }
    19  
    20  func (m *mockGasPriceSetter) SetGasPrice(price *big.Int) {
    21  	m.lock.Lock()
    22  	defer m.lock.Unlock()
    23  
    24  	m.price = price
    25  }
    26  
    27  func (m *mockGasPriceSetter) SetMinFee(minFee *big.Int) {
    28  	m.lock.Lock()
    29  	defer m.lock.Unlock()
    30  
    31  	m.minFee = minFee
    32  }
    33  
    34  func attemptAwait(t *testing.T, wg *sync.WaitGroup, delay time.Duration) {
    35  	ticker := make(chan struct{})
    36  
    37  	// Wait for [wg] and then close [ticket] to indicate that
    38  	// the wait group has finished.
    39  	go func() {
    40  		wg.Wait()
    41  		close(ticker)
    42  	}()
    43  
    44  	select {
    45  	case <-time.After(delay):
    46  		t.Fatal("Timed out waiting for wait group to complete")
    47  	case <-ticker:
    48  		// The wait group completed without issue
    49  	}
    50  }
    51  
    52  func TestUpdateGasPriceShutsDown(t *testing.T) {
    53  	shutdownChan := make(chan struct{})
    54  	wg := &sync.WaitGroup{}
    55  	config := *params.TestChainConfig
    56  	// Set ApricotPhase3BlockTime one hour in the future so that it will
    57  	// create a goroutine waiting for an hour before updating the gas price
    58  	config.ApricotPhase3BlockTimestamp = big.NewInt(time.Now().Add(time.Hour).Unix())
    59  	gpu := &gasPriceUpdater{
    60  		setter:       &mockGasPriceSetter{price: big.NewInt(1)},
    61  		chainConfig:  &config,
    62  		shutdownChan: shutdownChan,
    63  		wg:           wg,
    64  	}
    65  
    66  	gpu.start()
    67  	// Close [shutdownChan] and ensure that the wait group finishes in a reasonable
    68  	// amount of time.
    69  	close(shutdownChan)
    70  	attemptAwait(t, wg, 5*time.Second)
    71  }
    72  
    73  func TestUpdateGasPriceInitializesPrice(t *testing.T) {
    74  	shutdownChan := make(chan struct{})
    75  	wg := &sync.WaitGroup{}
    76  	gpu := &gasPriceUpdater{
    77  		setter:       &mockGasPriceSetter{price: big.NewInt(1)},
    78  		chainConfig:  params.TestChainConfig,
    79  		shutdownChan: shutdownChan,
    80  		wg:           wg,
    81  	}
    82  
    83  	gpu.start()
    84  	// The wait group should finish immediately since no goroutine
    85  	// should be created when all prices should be set from the start
    86  	attemptAwait(t, wg, time.Millisecond)
    87  
    88  	if gpu.setter.(*mockGasPriceSetter).price.Cmp(big.NewInt(0)) != 0 {
    89  		t.Fatalf("Expected price to match minimum base fee for apricot phase3")
    90  	}
    91  	if minFee := gpu.setter.(*mockGasPriceSetter).minFee; minFee == nil || minFee.Cmp(big.NewInt(params.ApricotPhase3MinBaseFee)) != 0 {
    92  		t.Fatalf("Expected min fee to match minimum fee for apricotPhase3, but found: %d", minFee)
    93  	}
    94  }
    95  
    96  func TestUpdateGasPriceUpdatesPrice(t *testing.T) {
    97  	shutdownChan := make(chan struct{})
    98  	wg := &sync.WaitGroup{}
    99  	config := *params.TestChainConfig
   100  	// Set ApricotPhase3BlockTime one hour in the future so that it will
   101  	// create a goroutine waiting for the time to update the gas price
   102  	config.ApricotPhase3BlockTimestamp = big.NewInt(time.Now().Add(250 * time.Millisecond).Unix())
   103  	gpu := &gasPriceUpdater{
   104  		setter:       &mockGasPriceSetter{price: big.NewInt(1)},
   105  		chainConfig:  &config,
   106  		shutdownChan: shutdownChan,
   107  		wg:           wg,
   108  	}
   109  
   110  	gpu.start()
   111  	// With ApricotPhase3 set slightly in the future, the gas price updater should create a
   112  	// goroutine to sleep until its time to update and mark the wait group as done when it has
   113  	// completed the update.
   114  	attemptAwait(t, wg, 5*time.Second)
   115  
   116  	if gpu.setter.(*mockGasPriceSetter).price.Cmp(big.NewInt(0)) != 0 {
   117  		t.Fatalf("Expected price to match minimum base fee for apricot phase3")
   118  	}
   119  	if minFee := gpu.setter.(*mockGasPriceSetter).minFee; minFee == nil || minFee.Cmp(big.NewInt(params.ApricotPhase3MinBaseFee)) != 0 {
   120  		t.Fatalf("Expected min fee to match minimum fee for apricotPhase3, but found: %d", minFee)
   121  	}
   122  }