_mining_test.go raw

   1  package mining
   2  
   3  import (
   4  	"container/heap"
   5  	"math/rand"
   6  	"testing"
   7  
   8  	"github.com/p9c/p9/pkg/util"
   9  )
  10  
  11  // TestTxFeePrioHeap ensures the priority queue for transaction fees and priorities works as expected.
  12  func TestTxFeePrioHeap(	t *testing.T) {
  13  	// Create some fake priority items that exercise the expected sort edge conditions.
  14  	testItems := []*txPrioItem{
  15  		{feePerKB: 5678, priority: 3},
  16  		{feePerKB: 5678, priority: 1},
  17  		{feePerKB: 5678, priority: 1}, // Duplicate fee and prio
  18  		{feePerKB: 5678, priority: 5},
  19  		{feePerKB: 5678, priority: 2},
  20  		{feePerKB: 1234, priority: 3},
  21  		{feePerKB: 1234, priority: 1},
  22  		{feePerKB: 1234, priority: 5},
  23  		{feePerKB: 1234, priority: 5}, // Duplicate fee and prio
  24  		{feePerKB: 1234, priority: 2},
  25  		{feePerKB: 10000, priority: 0}, // Higher fee, smaller prio
  26  		{feePerKB: 0, priority: 10000}, // Higher prio, lower fee
  27  	}
  28  	// Add random data in addition to the edge conditions already manually specified.
  29  	randSeed := rand.Int63()
  30  	defer func() {
  31  		if t.Failed() {
  32  			t.Logf("Random numbers using seed: %v", randSeed)
  33  		}
  34  	}()
  35  	prng := rand.New(rand.NewSource(randSeed))
  36  	for i := 0; i < 1000; i++ {
  37  		testItems = append(testItems, &txPrioItem{
  38  			feePerKB: int64(prng.Float64() * util.SatoshiPerBitcoin),
  39  			priority: prng.Float64() * 100,
  40  		})
  41  	}
  42  	// Test sorting by fee per KB then priority.
  43  	var highest *txPrioItem
  44  	priorityQueue := newTxPriorityQueue(len(testItems), true)
  45  	for i := 0; i < len(testItems); i++ {
  46  		prioItem := testItems[i]
  47  		if highest == nil {
  48  			highest = prioItem
  49  		}
  50  		if prioItem.feePerKB >= highest.feePerKB &&
  51  			prioItem.priority > highest.priority {
  52  			highest = prioItem
  53  		}
  54  		heap.Push(priorityQueue, prioItem)
  55  	}
  56  	for i := 0; i < len(testItems); i++ {
  57  		prioItem := heap.Pop(priorityQueue).(*txPrioItem)
  58  		if prioItem.feePerKB >= highest.feePerKB &&
  59  			prioItem.priority > highest.priority {
  60  			t.Fatalf("fee sort: item (fee per KB: %v, "+
  61  				"priority: %v) higher than than prev "+
  62  				"(fee per KB: %v, priority %v)",
  63  				prioItem.feePerKB, prioItem.priority,
  64  				highest.feePerKB, highest.priority)
  65  		}
  66  		highest = prioItem
  67  	}
  68  	// Test sorting by priority then fee per KB.
  69  	highest = nil
  70  	priorityQueue = newTxPriorityQueue(len(testItems), false)
  71  	for i := 0; i < len(testItems); i++ {
  72  		prioItem := testItems[i]
  73  		if highest == nil {
  74  			highest = prioItem
  75  		}
  76  		if prioItem.priority >= highest.priority &&
  77  			prioItem.feePerKB > highest.feePerKB {
  78  			highest = prioItem
  79  		}
  80  		heap.Push(priorityQueue, prioItem)
  81  	}
  82  	for i := 0; i < len(testItems); i++ {
  83  		prioItem := heap.Pop(priorityQueue).(*txPrioItem)
  84  		if prioItem.priority >= highest.priority &&
  85  			prioItem.feePerKB > highest.feePerKB {
  86  			t.Fatalf("priority sort: item (fee per KB: %v, "+
  87  				"priority: %v) higher than than prev "+
  88  				"(fee per KB: %v, priority %v)",
  89  				prioItem.feePerKB, prioItem.priority,
  90  				highest.feePerKB, highest.priority)
  91  		}
  92  		highest = prioItem
  93  	}
  94  }
  95