github.com/theQRL/go-zond@v0.1.1/zond/tracers/tracker_test.go (about)

     1  // Copyright 2022 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 tracers
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  	"time"
    23  )
    24  
    25  func TestTracker(t *testing.T) {
    26  	var cases = []struct {
    27  		limit   int
    28  		calls   []uint64
    29  		expHead uint64
    30  	}{
    31  		// Release in order
    32  		{
    33  			limit:   3,
    34  			calls:   []uint64{0, 1, 2},
    35  			expHead: 3,
    36  		},
    37  		{
    38  			limit:   3,
    39  			calls:   []uint64{0, 1, 2, 3, 4, 5},
    40  			expHead: 6,
    41  		},
    42  
    43  		// Release out of order
    44  		{
    45  			limit:   3,
    46  			calls:   []uint64{1, 2, 0},
    47  			expHead: 3,
    48  		},
    49  		{
    50  			limit:   3,
    51  			calls:   []uint64{1, 2, 0, 5, 4, 3},
    52  			expHead: 6,
    53  		},
    54  	}
    55  	for _, c := range cases {
    56  		tracker := newStateTracker(c.limit, 0)
    57  		for _, call := range c.calls {
    58  			tracker.releaseState(call, func() {})
    59  		}
    60  		tracker.lock.RLock()
    61  		head := tracker.oldest
    62  		tracker.lock.RUnlock()
    63  
    64  		if head != c.expHead {
    65  			t.Fatalf("Unexpected head want %d got %d", c.expHead, head)
    66  		}
    67  	}
    68  
    69  	var calls = []struct {
    70  		number  uint64
    71  		expUsed []bool
    72  		expHead uint64
    73  	}{
    74  		// Release the first one, update the oldest flag
    75  		{
    76  			number:  0,
    77  			expUsed: []bool{false, false, false, false, false},
    78  			expHead: 1,
    79  		},
    80  		// Release the second one, oldest shouldn't be updated
    81  		{
    82  			number:  2,
    83  			expUsed: []bool{false, true, false, false, false},
    84  			expHead: 1,
    85  		},
    86  		// Release the forth one, oldest shouldn't be updated
    87  		{
    88  			number:  4,
    89  			expUsed: []bool{false, true, false, true, false},
    90  			expHead: 1,
    91  		},
    92  		// Release the first one, the first two should all be cleaned,
    93  		// and the remaining flags should all be left-shifted.
    94  		{
    95  			number:  1,
    96  			expUsed: []bool{false, true, false, false, false},
    97  			expHead: 3,
    98  		},
    99  		// Release the first one, the first two should all be cleaned
   100  		{
   101  			number:  3,
   102  			expUsed: []bool{false, false, false, false, false},
   103  			expHead: 5,
   104  		},
   105  	}
   106  	tracker := newStateTracker(5, 0) // limit = 5, oldest = 0
   107  	for _, call := range calls {
   108  		tracker.releaseState(call.number, nil)
   109  		tracker.lock.RLock()
   110  		if !reflect.DeepEqual(tracker.used, call.expUsed) {
   111  			t.Fatalf("Unexpected used array")
   112  		}
   113  		if tracker.oldest != call.expHead {
   114  			t.Fatalf("Unexpected head")
   115  		}
   116  		tracker.lock.RUnlock()
   117  	}
   118  }
   119  
   120  func TestTrackerWait(t *testing.T) {
   121  	var (
   122  		tracker = newStateTracker(5, 0) // limit = 5, oldest = 0
   123  		result  = make(chan error, 1)
   124  		doCall  = func(number uint64) {
   125  			go func() {
   126  				result <- tracker.wait(number)
   127  			}()
   128  		}
   129  		checkNoWait = func() {
   130  			select {
   131  			case <-result:
   132  				return
   133  			case <-time.NewTimer(time.Second).C:
   134  				t.Fatal("No signal fired")
   135  			}
   136  		}
   137  		checkWait = func() {
   138  			select {
   139  			case <-result:
   140  				t.Fatal("Unexpected signal")
   141  			case <-time.NewTimer(time.Millisecond * 100).C:
   142  			}
   143  		}
   144  	)
   145  	// States [0, 5) should all be available
   146  	doCall(0)
   147  	checkNoWait()
   148  
   149  	doCall(4)
   150  	checkNoWait()
   151  
   152  	// State 5 is not available
   153  	doCall(5)
   154  	checkWait()
   155  
   156  	// States [1, 6) are available
   157  	tracker.releaseState(0, nil)
   158  	checkNoWait()
   159  
   160  	// States [1, 6) are available
   161  	doCall(7)
   162  	checkWait()
   163  
   164  	// States [2, 7) are available
   165  	tracker.releaseState(1, nil)
   166  	checkWait()
   167  
   168  	// States [3, 8) are available
   169  	tracker.releaseState(2, nil)
   170  	checkNoWait()
   171  }