// Copyright (c) 2016 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package main import ( "container/heap" "math/rand" "testing" "github.com/btcsuite/btcutil" ) // TestTxFeePrioHeap ensures the priority queue for transaction fees and // priorities works as expected. func TestTxFeePrioHeap(t *testing.T) { // Create some fake priority items that exercise the expected sort // edge conditions. testItems := []*txPrioItem{ {feePerKB: 5678, priority: 3}, {feePerKB: 5678, priority: 1}, {feePerKB: 5678, priority: 1}, // Duplicate fee and prio {feePerKB: 5678, priority: 5}, {feePerKB: 5678, priority: 2}, {feePerKB: 1234, priority: 3}, {feePerKB: 1234, priority: 1}, {feePerKB: 1234, priority: 5}, {feePerKB: 1234, priority: 5}, // Duplicate fee and prio {feePerKB: 1234, priority: 2}, {feePerKB: 10000, priority: 0}, // Higher fee, smaller prio {feePerKB: 0, priority: 10000}, // Higher prio, lower fee } // Add random data in addition to the edge conditions already manually // specified. randSeed := rand.Int63() defer func() { if t.Failed() { t.Logf("Random numbers using seed: %v", randSeed) } }() prng := rand.New(rand.NewSource(randSeed)) for i := 0; i < 1000; i++ { testItems = append(testItems, &txPrioItem{ feePerKB: int64(prng.Float64() * btcutil.SatoshiPerBitcoin), priority: prng.Float64() * 100, }) } // Test sorting by fee per KB then priority. var highest *txPrioItem priorityQueue := newTxPriorityQueue(len(testItems), true) for i := 0; i < len(testItems); i++ { prioItem := testItems[i] if highest == nil { highest = prioItem } if prioItem.feePerKB >= highest.feePerKB && prioItem.priority > highest.priority { highest = prioItem } heap.Push(priorityQueue, prioItem) } for i := 0; i < len(testItems); i++ { prioItem := heap.Pop(priorityQueue).(*txPrioItem) if prioItem.feePerKB >= highest.feePerKB && prioItem.priority > highest.priority { t.Fatalf("fee sort: item (fee per KB: %v, "+ "priority: %v) higher than than prev "+ "(fee per KB: %v, priority %v)", prioItem.feePerKB, prioItem.priority, highest.feePerKB, highest.priority) } highest = prioItem } // Test sorting by priority then fee per KB. highest = nil priorityQueue = newTxPriorityQueue(len(testItems), false) for i := 0; i < len(testItems); i++ { prioItem := testItems[i] if highest == nil { highest = prioItem } if prioItem.priority >= highest.priority && prioItem.feePerKB > highest.feePerKB { highest = prioItem } heap.Push(priorityQueue, prioItem) } for i := 0; i < len(testItems); i++ { prioItem := heap.Pop(priorityQueue).(*txPrioItem) if prioItem.priority >= highest.priority && prioItem.feePerKB > highest.feePerKB { t.Fatalf("priority sort: item (fee per KB: %v, "+ "priority: %v) higher than than prev "+ "(fee per KB: %v, priority %v)", prioItem.feePerKB, prioItem.priority, highest.feePerKB, highest.priority) } highest = prioItem } }