github.com/kaleido-io/go-ethereum@v1.9.7/les/balance_test.go (about)

     1  // Copyright 2019 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package les
    18  
    19  import (
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/ethereum/go-ethereum/common/mclock"
    24  )
    25  
    26  func TestSetBalance(t *testing.T) {
    27  	var clock = &mclock.Simulated{}
    28  	var inputs = []struct {
    29  		pos uint64
    30  		neg uint64
    31  	}{
    32  		{1000, 0},
    33  		{0, 1000},
    34  		{1000, 1000},
    35  	}
    36  
    37  	tracker := balanceTracker{}
    38  	tracker.init(clock, 1000)
    39  	defer tracker.stop(clock.Now())
    40  
    41  	for _, i := range inputs {
    42  		tracker.setBalance(i.pos, i.neg)
    43  		pos, neg := tracker.getBalance(clock.Now())
    44  		if pos != i.pos {
    45  			t.Fatalf("Positive balance mismatch, want %v, got %v", i.pos, pos)
    46  		}
    47  		if neg != i.neg {
    48  			t.Fatalf("Negative balance mismatch, want %v, got %v", i.neg, neg)
    49  		}
    50  	}
    51  }
    52  
    53  func TestBalanceTimeCost(t *testing.T) {
    54  	var (
    55  		clock   = &mclock.Simulated{}
    56  		tracker = balanceTracker{}
    57  	)
    58  	tracker.init(clock, 1000)
    59  	defer tracker.stop(clock.Now())
    60  	tracker.setFactors(false, 1, 1)
    61  	tracker.setFactors(true, 1, 1)
    62  
    63  	tracker.setBalance(uint64(time.Minute), 0) // 1 minute time allowance
    64  
    65  	var inputs = []struct {
    66  		runTime time.Duration
    67  		expPos  uint64
    68  		expNeg  uint64
    69  	}{
    70  		{time.Second, uint64(time.Second * 59), 0},
    71  		{0, uint64(time.Second * 59), 0},
    72  		{time.Second * 59, 0, 0},
    73  		{time.Second, 0, uint64(time.Second)},
    74  	}
    75  	for _, i := range inputs {
    76  		clock.Run(i.runTime)
    77  		if pos, _ := tracker.getBalance(clock.Now()); pos != i.expPos {
    78  			t.Fatalf("Positive balance mismatch, want %v, got %v", i.expPos, pos)
    79  		}
    80  		if _, neg := tracker.getBalance(clock.Now()); neg != i.expNeg {
    81  			t.Fatalf("Negative balance mismatch, want %v, got %v", i.expNeg, neg)
    82  		}
    83  	}
    84  
    85  	tracker.setBalance(uint64(time.Minute), 0) // Refill 1 minute time allowance
    86  	for _, i := range inputs {
    87  		clock.Run(i.runTime)
    88  		if pos, _ := tracker.getBalance(clock.Now()); pos != i.expPos {
    89  			t.Fatalf("Positive balance mismatch, want %v, got %v", i.expPos, pos)
    90  		}
    91  		if _, neg := tracker.getBalance(clock.Now()); neg != i.expNeg {
    92  			t.Fatalf("Negative balance mismatch, want %v, got %v", i.expNeg, neg)
    93  		}
    94  	}
    95  }
    96  
    97  func TestBalanceReqCost(t *testing.T) {
    98  	var (
    99  		clock   = &mclock.Simulated{}
   100  		tracker = balanceTracker{}
   101  	)
   102  	tracker.init(clock, 1000)
   103  	defer tracker.stop(clock.Now())
   104  	tracker.setFactors(false, 1, 1)
   105  	tracker.setFactors(true, 1, 1)
   106  
   107  	tracker.setBalance(uint64(time.Minute), 0) // 1 minute time serving time allowance
   108  	var inputs = []struct {
   109  		reqCost uint64
   110  		expPos  uint64
   111  		expNeg  uint64
   112  	}{
   113  		{uint64(time.Second), uint64(time.Second * 59), 0},
   114  		{0, uint64(time.Second * 59), 0},
   115  		{uint64(time.Second * 59), 0, 0},
   116  		{uint64(time.Second), 0, uint64(time.Second)},
   117  	}
   118  	for _, i := range inputs {
   119  		tracker.requestCost(i.reqCost)
   120  		if pos, _ := tracker.getBalance(clock.Now()); pos != i.expPos {
   121  			t.Fatalf("Positive balance mismatch, want %v, got %v", i.expPos, pos)
   122  		}
   123  		if _, neg := tracker.getBalance(clock.Now()); neg != i.expNeg {
   124  			t.Fatalf("Negative balance mismatch, want %v, got %v", i.expNeg, neg)
   125  		}
   126  	}
   127  }
   128  
   129  func TestBalanceToPriority(t *testing.T) {
   130  	var (
   131  		clock   = &mclock.Simulated{}
   132  		tracker = balanceTracker{}
   133  	)
   134  	tracker.init(clock, 1000) // cap = 1000
   135  	defer tracker.stop(clock.Now())
   136  	tracker.setFactors(false, 1, 1)
   137  	tracker.setFactors(true, 1, 1)
   138  
   139  	var inputs = []struct {
   140  		pos      uint64
   141  		neg      uint64
   142  		priority int64
   143  	}{
   144  		{1000, 0, ^int64(1)},
   145  		{2000, 0, ^int64(2)}, // Higher balance, lower priority value
   146  		{0, 0, 0},
   147  		{0, 1000, 1000},
   148  	}
   149  	for _, i := range inputs {
   150  		tracker.setBalance(i.pos, i.neg)
   151  		priority := tracker.getPriority(clock.Now())
   152  		if priority != i.priority {
   153  			t.Fatalf("Priority mismatch, want %v, got %v", i.priority, priority)
   154  		}
   155  	}
   156  }
   157  
   158  func TestEstimatedPriority(t *testing.T) {
   159  	var (
   160  		clock   = &mclock.Simulated{}
   161  		tracker = balanceTracker{}
   162  	)
   163  	tracker.init(clock, 1000000000) // cap = 1000,000,000
   164  	defer tracker.stop(clock.Now())
   165  	tracker.setFactors(false, 1, 1)
   166  	tracker.setFactors(true, 1, 1)
   167  
   168  	tracker.setBalance(uint64(time.Minute), 0)
   169  	var inputs = []struct {
   170  		runTime    time.Duration // time cost
   171  		futureTime time.Duration // diff of future time
   172  		reqCost    uint64        // single request cost
   173  		priority   int64         // expected estimated priority
   174  	}{
   175  		{time.Second, time.Second, 0, ^int64(58)},
   176  		{0, time.Second, 0, ^int64(58)},
   177  
   178  		// 2 seconds time cost, 1 second estimated time cost, 10^9 request cost,
   179  		// 10^9 estimated request cost per second.
   180  		{time.Second, time.Second, 1000000000, ^int64(55)},
   181  
   182  		// 3 seconds time cost, 3 second estimated time cost, 10^9*2 request cost,
   183  		// 4*10^9 estimated request cost.
   184  		{time.Second, 3 * time.Second, 1000000000, ^int64(48)},
   185  
   186  		// All positive balance is used up
   187  		{time.Second * 55, 0, 0, 0},
   188  
   189  		// 1 minute estimated time cost, 4/58 * 10^9 estimated request cost per sec.
   190  		{0, time.Minute, 0, int64(time.Minute) + int64(time.Second)*120/29},
   191  	}
   192  	for _, i := range inputs {
   193  		clock.Run(i.runTime)
   194  		tracker.requestCost(i.reqCost)
   195  		priority := tracker.estimatedPriority(clock.Now()+mclock.AbsTime(i.futureTime), true)
   196  		if priority != i.priority {
   197  			t.Fatalf("Estimated priority mismatch, want %v, got %v", i.priority, priority)
   198  		}
   199  	}
   200  }
   201  
   202  func TestCallbackChecking(t *testing.T) {
   203  	var (
   204  		clock   = &mclock.Simulated{}
   205  		tracker = balanceTracker{}
   206  	)
   207  	tracker.init(clock, 1000000) // cap = 1000,000
   208  	defer tracker.stop(clock.Now())
   209  	tracker.setFactors(false, 1, 1)
   210  	tracker.setFactors(true, 1, 1)
   211  
   212  	var inputs = []struct {
   213  		priority int64
   214  		expDiff  time.Duration
   215  	}{
   216  		{^int64(500), time.Millisecond * 500},
   217  		{0, time.Second},
   218  		{int64(time.Second), 2 * time.Second},
   219  	}
   220  	tracker.setBalance(uint64(time.Second), 0)
   221  	for _, i := range inputs {
   222  		diff, _ := tracker.timeUntil(i.priority)
   223  		if diff != i.expDiff {
   224  			t.Fatalf("Time difference mismatch, want %v, got %v", i.expDiff, diff)
   225  		}
   226  	}
   227  }
   228  
   229  func TestCallback(t *testing.T) {
   230  	var (
   231  		clock   = &mclock.Simulated{}
   232  		tracker = balanceTracker{}
   233  	)
   234  	tracker.init(clock, 1000) // cap = 1000
   235  	defer tracker.stop(clock.Now())
   236  	tracker.setFactors(false, 1, 1)
   237  	tracker.setFactors(true, 1, 1)
   238  
   239  	callCh := make(chan struct{}, 1)
   240  	tracker.setBalance(uint64(time.Minute), 0)
   241  	tracker.addCallback(balanceCallbackZero, 0, func() { callCh <- struct{}{} })
   242  
   243  	clock.Run(time.Minute)
   244  	select {
   245  	case <-callCh:
   246  	case <-time.NewTimer(time.Second).C:
   247  		t.Fatalf("Callback hasn't been called yet")
   248  	}
   249  
   250  	tracker.setBalance(uint64(time.Minute), 0)
   251  	tracker.addCallback(balanceCallbackZero, 0, func() { callCh <- struct{}{} })
   252  	tracker.removeCallback(balanceCallbackZero)
   253  
   254  	clock.Run(time.Minute)
   255  	select {
   256  	case <-callCh:
   257  		t.Fatalf("Callback shouldn't be called")
   258  	case <-time.NewTimer(time.Millisecond * 100).C:
   259  	}
   260  }