github.com/supragya/TendermintConnector@v0.0.0-20210619045051-113e32b84fb1/_deprecated_chains/irisnet/libs/clist/clist_test.go (about)

     1  package clist
     2  
     3  import (
     4  	"fmt"
     5  	"runtime"
     6  	"sync/atomic"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	cmn "github.com/tendermint/tendermint/libs/common"
    12  )
    13  
    14  func TestPanicOnMaxLength(t *testing.T) {
    15  	maxLength := 1000
    16  
    17  	l := newWithMax(maxLength)
    18  	for i := 0; i < maxLength; i++ {
    19  		l.PushBack(1)
    20  	}
    21  	assert.Panics(t, func() {
    22  		l.PushBack(1)
    23  	})
    24  }
    25  
    26  func TestSmall(t *testing.T) {
    27  	l := New()
    28  	el1 := l.PushBack(1)
    29  	el2 := l.PushBack(2)
    30  	el3 := l.PushBack(3)
    31  	if l.Len() != 3 {
    32  		t.Error("Expected len 3, got ", l.Len())
    33  	}
    34  
    35  	//fmt.Printf("%p %v\n", el1, el1)
    36  	//fmt.Printf("%p %v\n", el2, el2)
    37  	//fmt.Printf("%p %v\n", el3, el3)
    38  
    39  	r1 := l.Remove(el1)
    40  
    41  	//fmt.Printf("%p %v\n", el1, el1)
    42  	//fmt.Printf("%p %v\n", el2, el2)
    43  	//fmt.Printf("%p %v\n", el3, el3)
    44  
    45  	r2 := l.Remove(el2)
    46  
    47  	//fmt.Printf("%p %v\n", el1, el1)
    48  	//fmt.Printf("%p %v\n", el2, el2)
    49  	//fmt.Printf("%p %v\n", el3, el3)
    50  
    51  	r3 := l.Remove(el3)
    52  
    53  	if r1 != 1 {
    54  		t.Error("Expected 1, got ", r1)
    55  	}
    56  	if r2 != 2 {
    57  		t.Error("Expected 2, got ", r2)
    58  	}
    59  	if r3 != 3 {
    60  		t.Error("Expected 3, got ", r3)
    61  	}
    62  	if l.Len() != 0 {
    63  		t.Error("Expected len 0, got ", l.Len())
    64  	}
    65  
    66  }
    67  
    68  /*
    69  This test is quite hacky because it relies on SetFinalizer
    70  which isn't guaranteed to run at all.
    71  */
    72  // nolint: megacheck
    73  func _TestGCFifo(t *testing.T) {
    74  
    75  	const numElements = 1000000
    76  	l := New()
    77  	gcCount := new(uint64)
    78  
    79  	// SetFinalizer doesn't work well with circular structures,
    80  	// so we construct a trivial non-circular structure to
    81  	// track.
    82  	type value struct {
    83  		Int int
    84  	}
    85  	done := make(chan struct{})
    86  
    87  	for i := 0; i < numElements; i++ {
    88  		v := new(value)
    89  		v.Int = i
    90  		l.PushBack(v)
    91  		runtime.SetFinalizer(v, func(v *value) {
    92  			atomic.AddUint64(gcCount, 1)
    93  		})
    94  	}
    95  
    96  	for el := l.Front(); el != nil; {
    97  		l.Remove(el)
    98  		//oldEl := el
    99  		el = el.Next()
   100  		//oldEl.DetachPrev()
   101  		//oldEl.DetachNext()
   102  	}
   103  
   104  	runtime.GC()
   105  	time.Sleep(time.Second * 3)
   106  	runtime.GC()
   107  	time.Sleep(time.Second * 3)
   108  	_ = done
   109  
   110  	if *gcCount != numElements {
   111  		t.Errorf("Expected gcCount to be %v, got %v", numElements,
   112  			*gcCount)
   113  	}
   114  }
   115  
   116  /*
   117  This test is quite hacky because it relies on SetFinalizer
   118  which isn't guaranteed to run at all.
   119  */
   120  // nolint: megacheck
   121  func _TestGCRandom(t *testing.T) {
   122  
   123  	const numElements = 1000000
   124  	l := New()
   125  	gcCount := 0
   126  
   127  	// SetFinalizer doesn't work well with circular structures,
   128  	// so we construct a trivial non-circular structure to
   129  	// track.
   130  	type value struct {
   131  		Int int
   132  	}
   133  
   134  	for i := 0; i < numElements; i++ {
   135  		v := new(value)
   136  		v.Int = i
   137  		l.PushBack(v)
   138  		runtime.SetFinalizer(v, func(v *value) {
   139  			gcCount++
   140  		})
   141  	}
   142  
   143  	els := make([]*CElement, 0, numElements)
   144  	for el := l.Front(); el != nil; el = el.Next() {
   145  		els = append(els, el)
   146  	}
   147  
   148  	for _, i := range cmn.RandPerm(numElements) {
   149  		el := els[i]
   150  		l.Remove(el)
   151  		_ = el.Next()
   152  	}
   153  
   154  	runtime.GC()
   155  	time.Sleep(time.Second * 3)
   156  
   157  	if gcCount != numElements {
   158  		t.Errorf("Expected gcCount to be %v, got %v", numElements,
   159  			gcCount)
   160  	}
   161  }
   162  
   163  func TestScanRightDeleteRandom(t *testing.T) {
   164  
   165  	const numElements = 1000
   166  	const numTimes = 100
   167  	const numScanners = 10
   168  
   169  	l := New()
   170  	stop := make(chan struct{})
   171  
   172  	els := make([]*CElement, numElements)
   173  	for i := 0; i < numElements; i++ {
   174  		el := l.PushBack(i)
   175  		els[i] = el
   176  	}
   177  
   178  	// Launch scanner routines that will rapidly iterate over elements.
   179  	for i := 0; i < numScanners; i++ {
   180  		go func(scannerID int) {
   181  			var el *CElement
   182  			restartCounter := 0
   183  			counter := 0
   184  		FOR_LOOP:
   185  			for {
   186  				select {
   187  				case <-stop:
   188  					fmt.Println("stopped")
   189  					break FOR_LOOP
   190  				default:
   191  				}
   192  				if el == nil {
   193  					el = l.FrontWait()
   194  					restartCounter++
   195  				}
   196  				el = el.Next()
   197  				counter++
   198  			}
   199  			fmt.Printf("Scanner %v restartCounter: %v counter: %v\n", scannerID, restartCounter, counter)
   200  		}(i)
   201  	}
   202  
   203  	// Remove an element, push back an element.
   204  	for i := 0; i < numTimes; i++ {
   205  		// Pick an element to remove
   206  		rmElIdx := cmn.RandIntn(len(els))
   207  		rmEl := els[rmElIdx]
   208  
   209  		// Remove it
   210  		l.Remove(rmEl)
   211  		//fmt.Print(".")
   212  
   213  		// Insert a new element
   214  		newEl := l.PushBack(-1*i - 1)
   215  		els[rmElIdx] = newEl
   216  
   217  		if i%100000 == 0 {
   218  			fmt.Printf("Pushed %vK elements so far...\n", i/1000)
   219  		}
   220  
   221  	}
   222  
   223  	// Stop scanners
   224  	close(stop)
   225  	// time.Sleep(time.Second * 1)
   226  
   227  	// And remove all the elements.
   228  	for el := l.Front(); el != nil; el = el.Next() {
   229  		l.Remove(el)
   230  	}
   231  	if l.Len() != 0 {
   232  		t.Fatal("Failed to remove all elements from CList")
   233  	}
   234  }
   235  
   236  func TestWaitChan(t *testing.T) {
   237  	l := New()
   238  	ch := l.WaitChan()
   239  
   240  	// 1) add one element to an empty list
   241  	go l.PushBack(1)
   242  	<-ch
   243  
   244  	// 2) and remove it
   245  	el := l.Front()
   246  	v := l.Remove(el)
   247  	if v != 1 {
   248  		t.Fatal("where is 1 coming from?")
   249  	}
   250  
   251  	// 3) test iterating forward and waiting for Next (NextWaitChan and Next)
   252  	el = l.PushBack(0)
   253  
   254  	done := make(chan struct{})
   255  	pushed := 0
   256  	go func() {
   257  		for i := 1; i < 100; i++ {
   258  			l.PushBack(i)
   259  			pushed++
   260  			time.Sleep(time.Duration(cmn.RandIntn(25)) * time.Millisecond)
   261  		}
   262  		close(done)
   263  	}()
   264  
   265  	next := el
   266  	seen := 0
   267  FOR_LOOP:
   268  	for {
   269  		select {
   270  		case <-next.NextWaitChan():
   271  			next = next.Next()
   272  			seen++
   273  			if next == nil {
   274  				continue
   275  			}
   276  		case <-done:
   277  			break FOR_LOOP
   278  		case <-time.After(10 * time.Second):
   279  			t.Fatal("max execution time")
   280  		}
   281  	}
   282  
   283  	if pushed != seen {
   284  		t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen)
   285  	}
   286  
   287  	// 4) test iterating backwards (PrevWaitChan and Prev)
   288  	prev := next
   289  	seen = 0
   290  FOR_LOOP2:
   291  	for {
   292  		select {
   293  		case <-prev.PrevWaitChan():
   294  			prev = prev.Prev()
   295  			seen++
   296  			if prev == nil {
   297  				t.Fatal("expected PrevWaitChan to block forever on nil when reached first elem")
   298  			}
   299  		case <-time.After(3 * time.Second):
   300  			break FOR_LOOP2
   301  		}
   302  	}
   303  
   304  	if pushed != seen {
   305  		t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen)
   306  	}
   307  }