decred.org/dcrdex@v1.0.5/server/book/orderpq_test.go (about)

     1  package book
     2  
     3  import (
     4  	"flag"
     5  	"math/rand"
     6  	crand "math/rand"
     7  	"os"
     8  	"sort"
     9  	"testing"
    10  
    11  	"decred.org/dcrdex/dex/order"
    12  	"decred.org/dcrdex/server/account"
    13  )
    14  
    15  type Order = order.LimitOrder
    16  
    17  var (
    18  	bigList []*Order
    19  	orders  []*Order
    20  	rnd     = rand.New(rand.NewSource(1))
    21  )
    22  
    23  func randomAccount() (user account.AccountID) {
    24  	crand.Read(user[:])
    25  	return
    26  }
    27  
    28  func newFakeAddr() string {
    29  	const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    30  	b := make([]byte, 35)
    31  	for i := range b {
    32  		b[i] = letters[rnd.Int63()%int64(len(letters))]
    33  	}
    34  	b[0], b[1] = 'D', 's' // at least have it resemble an address
    35  	return string(b)
    36  }
    37  
    38  func genBigList(listSize int) {
    39  	if bigList != nil {
    40  		return
    41  	}
    42  	seed := int64(-3405439173988651889)
    43  	rnd.Seed(seed)
    44  
    45  	dupRate := 800
    46  	if listSize < dupRate {
    47  		dupRate = listSize / 10
    48  	}
    49  	if dupRate == 0 {
    50  		dupRate = 2
    51  	}
    52  
    53  	bigList = make([]*Order, 0, listSize)
    54  	for i := 0; i < listSize; i++ {
    55  		lo := newLimitOrder(false, uint64(rnd.Int63n(90000000)), uint64(rnd.Int63n(6))+1, order.StandingTiF, rnd.Int63n(240)-120)
    56  		lo.Address = newFakeAddr()
    57  		// duplicate some prices
    58  		if (i+1)%(listSize/dupRate) == 0 {
    59  			lo.Rate = bigList[i/2].Rate
    60  			lo.Quantity = bigList[i/2].Quantity + 1
    61  		}
    62  		_ = lo.ID() // compute and cache the OrderID
    63  		bigList = append(bigList, lo)
    64  	}
    65  }
    66  
    67  const (
    68  	shortListLen = 12_000
    69  	longListLen  = 400_000
    70  )
    71  
    72  func TestMain(m *testing.M) {
    73  	flag.Parse() // for -short
    74  	rnd.Seed(4)  // some predetermined and reproducible order IDs
    75  	orders = []*Order{
    76  		newLimitOrder(false, 42000000, 2, order.StandingTiF, 0),
    77  		newLimitOrder(false, 10000, 2, order.StandingTiF, 0),
    78  		newLimitOrder(false, 42000000, 2, order.StandingTiF, -1000), // rate dup, different time
    79  		newLimitOrder(false, 123000000, 2, order.StandingTiF, 0),
    80  		newLimitOrder(false, 42000000, 1, order.StandingTiF, 0), // rate and time dup, different OrderID
    81  	}
    82  	if testing.Short() {
    83  		genBigList(shortListLen)
    84  	} else {
    85  		genBigList(longListLen)
    86  	}
    87  	// The first and last of the sells are the same user.
    88  	firstSell, lastSell := bookSellOrders[0], bookSellOrders[len(bookSellOrders)-1]
    89  	firstSell.Coins[0] = lastSell.Coins[0]
    90  	firstSell.Address = lastSell.Address
    91  	os.Exit(m.Run())
    92  }
    93  
    94  func TestLargeOrderMaxPriorityQueue(t *testing.T) {
    95  	// Max oriented queue
    96  	pq := NewMaxOrderPQ(uint32(len(bigList) - len(bigList)/16)) // a little smaller to force a realloc
    97  	for i, o := range bigList {
    98  		ok := pq.Insert(o)
    99  		if !ok {
   100  			t.Fatalf("Failed to insert order %d: %v", i, o)
   101  		}
   102  	}
   103  
   104  	if pq.Len() != len(bigList) {
   105  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   106  	}
   107  
   108  	initLen := pq.Len()
   109  	best := pq.ExtractBest()
   110  	allOrders := make([]*Order, 0, initLen)
   111  	allOrders = append(allOrders, best)
   112  
   113  	lastTime := best.Time()
   114  	lastRate := best.Price()
   115  	rates := make([]uint64, initLen)
   116  	rates[0] = lastRate
   117  
   118  	lastLen := pq.Len()
   119  	i := int(1) // already popped 0
   120  	for pq.Len() > 0 {
   121  		best = pq.ExtractBest()
   122  		allOrders = append(allOrders, best)
   123  		rate := best.Price()
   124  		if rate > lastRate {
   125  			t.Fatalf("Current rate %d > last rate %d. Should be less.",
   126  				rate, lastRate)
   127  		}
   128  		thisTime := best.Time()
   129  		if rate == lastRate && thisTime < lastTime {
   130  			t.Fatalf("Orders with the same rate; current time %d < last time %d. Should be greater.",
   131  				thisTime, lastTime)
   132  		}
   133  		lastRate = rate
   134  		lastTime = thisTime
   135  
   136  		rates[i] = rate
   137  		i++
   138  
   139  		if pq.Len() != lastLen-1 {
   140  			t.Fatalf("Queue length failed to shrink by 1.")
   141  		}
   142  		lastLen = pq.Len()
   143  	}
   144  
   145  	// Ensure sorted in a different way.
   146  	sorted := sort.SliceIsSorted(rates, func(i, j int) bool {
   147  		return rates[j] < rates[i]
   148  	})
   149  	if !sorted {
   150  		t.Errorf("Rates should have been sorted.")
   151  	}
   152  
   153  	pq.Reset(allOrders)
   154  	if pq.Len() != len(bigList) {
   155  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   156  	}
   157  	if pq.PeekBest().Price() != rates[0] {
   158  		t.Errorf("Heap Reset failed.")
   159  	}
   160  
   161  	pq.Reheap()
   162  	if pq.Len() != len(bigList) {
   163  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   164  	}
   165  	if pq.PeekBest().Price() != rates[0] {
   166  		t.Errorf("Heap Reset failed.")
   167  	}
   168  }
   169  
   170  func TestLargeOrderMinPriorityQueue(t *testing.T) {
   171  	// Min oriented queue
   172  	pq := NewMinOrderPQ(uint32(len(bigList) - len(bigList)/16)) // a little smaller to force a realloc
   173  	for _, o := range bigList {
   174  		ok := pq.Insert(o)
   175  		if !ok {
   176  			t.Fatalf("Failed to insert order %v", o)
   177  		}
   178  	}
   179  
   180  	if pq.Len() != len(bigList) {
   181  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   182  	}
   183  
   184  	initLen := pq.Len()
   185  	best := pq.ExtractBest()
   186  	allOrders := make([]*Order, 0, initLen)
   187  	allOrders = append(allOrders, best)
   188  
   189  	lastTime := best.Time()
   190  	lastRate := best.Price()
   191  	rates := make([]uint64, initLen)
   192  	rates[0] = lastRate
   193  
   194  	lastLen := pq.Len()
   195  	i := int(1) // already popped 0
   196  	for pq.Len() > 0 {
   197  		best = pq.ExtractBest()
   198  		allOrders = append(allOrders, best)
   199  		rate := best.Price()
   200  		if rate < lastRate {
   201  			t.Fatalf("Current (%d) rate %d < last rate %d. Should be greater.",
   202  				i, rate, lastRate)
   203  		}
   204  		thisTime := best.Time()
   205  		if rate == lastRate && thisTime < lastTime {
   206  			t.Fatalf("Orders with the same rate; current time %d < last time %d. Should be greater.",
   207  				thisTime, lastTime)
   208  		}
   209  		lastRate = rate
   210  		lastTime = thisTime
   211  
   212  		rates[i] = rate
   213  		i++
   214  
   215  		if pq.Len() != lastLen-1 {
   216  			t.Fatalf("Queue length failed to shrink by 1.")
   217  		}
   218  		lastLen = pq.Len()
   219  	}
   220  
   221  	// Ensure sorted in a different way.
   222  	sorted := sort.SliceIsSorted(rates, func(i, j int) bool {
   223  		return rates[i] < rates[j]
   224  	})
   225  	if !sorted {
   226  		t.Errorf("Rates should have been sorted.")
   227  	}
   228  
   229  	pq.Reset(allOrders)
   230  	if pq.Len() != len(bigList) {
   231  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   232  	}
   233  	if pq.PeekBest().Price() != rates[0] {
   234  		t.Errorf("Heap Reset failed.")
   235  	}
   236  
   237  	pq.Reheap()
   238  	if pq.Len() != len(bigList) {
   239  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   240  	}
   241  	if pq.PeekBest().Price() != rates[0] {
   242  		t.Errorf("Heap Reset failed.")
   243  	}
   244  }
   245  
   246  func TestLargeOrderMaxPriorityQueue_Orders(t *testing.T) {
   247  	// Max oriented queue (sell book)
   248  	pq := NewMaxOrderPQ(uint32(len(bigList)))
   249  	for _, o := range bigList {
   250  		ok := pq.Insert(o)
   251  		if !ok {
   252  			t.Fatalf("Failed to insert order %v", o)
   253  		}
   254  	}
   255  
   256  	if pq.Len() != len(bigList) {
   257  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   258  	}
   259  
   260  	// Copy out all orders, sorted.
   261  	ordersSorted := pq.Orders()
   262  
   263  	// Ensure sorted in a different way.
   264  	sorted := sort.SliceIsSorted(ordersSorted, func(i, j int) bool {
   265  		if ordersSorted[i].Price() == ordersSorted[j].Price() {
   266  			return ordersSorted[i].Time() < ordersSorted[j].Time()
   267  		}
   268  		return ordersSorted[i].Price() > ordersSorted[j].Price() // max pq
   269  	})
   270  	if !sorted {
   271  		t.Errorf("Rates should have been sorted")
   272  		// for _, op := range ordersSorted {
   273  		// 	t.Log(op.Price(), op.Time())
   274  		// }
   275  	}
   276  
   277  	ordersSorted2 := pq.OrdersN(pq.Count())
   278  	if len(ordersSorted2) != len(ordersSorted) {
   279  		t.Fatalf("Orders() and OrdersN(Count()) returned different slices.")
   280  	}
   281  	for i, o := range ordersSorted {
   282  		if o.ID() != ordersSorted2[i].ID() {
   283  			t.Errorf("Mismatched orders: %v != %v", o, ordersSorted2[i])
   284  		}
   285  	}
   286  
   287  	// Copy out just the six best orders.
   288  	sixOrders := pq.OrdersN(6)
   289  	for i := range sixOrders {
   290  		if sixOrders[i].UID() != ordersSorted[i].UID() {
   291  			t.Errorf("Order %d incorrect. Got %s, expected %s",
   292  				i, sixOrders[i].UID(), ordersSorted[i].UID())
   293  		}
   294  	}
   295  
   296  	// Do it again to ensure the queue is not changed by copying.
   297  	sixOrders2 := pq.OrdersN(6)
   298  	for i := range sixOrders2 {
   299  		if sixOrders[i].UID() != sixOrders2[i].UID() {
   300  			t.Errorf("Order %d incorrect. Got %s, expected %s",
   301  				i, sixOrders2[i].UID(), sixOrders[i].UID())
   302  		}
   303  	}
   304  
   305  	pq.Reset(ordersSorted)
   306  	if pq.Len() != len(bigList) {
   307  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   308  	}
   309  	if pq.PeekBest().Price() != ordersSorted[0].Price() {
   310  		t.Errorf("Heap Reset failed.")
   311  	}
   312  }
   313  
   314  func TestLargeOrderMaxPriorityQueue_realloc(t *testing.T) {
   315  	// Max oriented queue (sell book)
   316  	pq := NewMaxOrderPQ(uint32(len(bigList))) // no realloc for initial inserts
   317  	for _, o := range bigList {
   318  		ok := pq.Insert(o)
   319  		if !ok {
   320  			t.Fatalf("Failed to insert order %v", o)
   321  		}
   322  	}
   323  
   324  	if pq.Len() != len(bigList) {
   325  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   326  	}
   327  
   328  	newCap := pq.capacity * 3 / 2
   329  	pq.realloc(newCap)
   330  
   331  	if pq.capacity != newCap {
   332  		t.Errorf("Reallocated capacity incorrect. Expected %d, got %d",
   333  			newCap, pq.capacity)
   334  	}
   335  
   336  	if pq.Len() != len(bigList) {
   337  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   338  	}
   339  
   340  	// Extract all orders, sorted. This should realloc and decrease cap on the way.
   341  	ordersSorted := pq.ExtractN(pq.Count())
   342  
   343  	if !testing.Short() && pq.Cap() >= newCap { // only long list is big enough to trigger dealloc
   344  		t.Errorf("expected a capacity decrease")
   345  	}
   346  	t.Logf("OrderPQ capacity decreased from %d to %d after extracting all entries", newCap, pq.Cap())
   347  
   348  	// Ensure sorted in a different way.
   349  	sorted := sort.SliceIsSorted(ordersSorted, func(i, j int) bool {
   350  		if ordersSorted[i].Price() == ordersSorted[j].Price() {
   351  			return ordersSorted[i].Time() < ordersSorted[j].Time()
   352  		}
   353  		return ordersSorted[i].Price() > ordersSorted[j].Price() // max pq
   354  	})
   355  	if !sorted {
   356  		t.Errorf("Rates should have been sorted")
   357  		// for _, op := range ordersSorted {
   358  		// 	t.Log(op.Price(), op.Time())
   359  		// }
   360  	}
   361  
   362  	// Remake the queue with the extracted orders.
   363  	pq.Reset(ordersSorted)
   364  	if pq.Len() != len(bigList) {
   365  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   366  	}
   367  	if pq.PeekBest().Price() != ordersSorted[0].Price() {
   368  		t.Errorf("Heap Reset failed.")
   369  	}
   370  }
   371  
   372  func TestMinOrderPQ(t *testing.T) {
   373  	pq := NewMinOrderPQ(0) // zero cap to force a realloc right away
   374  
   375  	for _, o := range orders {
   376  		ok := pq.Insert(o)
   377  		if !ok {
   378  			t.Errorf("Failed to insert order %v", o)
   379  		}
   380  	}
   381  
   382  	best := pq.ExtractBest()
   383  	if best.UID() != orders[1].UID() {
   384  		t.Errorf("Incorrect lowest rate order returned: rate = %d, UID = %s",
   385  			best.Price(), best.UID())
   386  	}
   387  }
   388  
   389  func TestMaxOrderPQ(t *testing.T) {
   390  	pq := NewMaxOrderPQ(0)
   391  
   392  	for _, o := range orders {
   393  		ok := pq.Insert(o)
   394  		if !ok {
   395  			t.Errorf("Failed to insert order %v", o)
   396  		}
   397  	}
   398  
   399  	best := pq.ExtractBest()
   400  	if best.UID() != orders[3].UID() {
   401  		t.Errorf("Incorrect highest rate order returned: rate = %d, UID = %s",
   402  			best.Price(), best.UID())
   403  	}
   404  }
   405  
   406  func TestMaxOrderPQ_TieRate(t *testing.T) {
   407  	pq := NewMaxOrderPQ(4)
   408  
   409  	for _, o := range orders[:3] {
   410  		ok := pq.Insert(o)
   411  		if !ok {
   412  			t.Errorf("Failed to insert order %v", o)
   413  		}
   414  	}
   415  
   416  	best := pq.ExtractBest()
   417  	if best.UID() != orders[2].UID() {
   418  		t.Errorf("Incorrect highest rate order returned: rate = %d, UID = %s",
   419  			best.Price(), best.UID())
   420  	}
   421  }
   422  
   423  func TestMaxOrderPQ_TieRateAndTime(t *testing.T) {
   424  	pq := NewMaxOrderPQ(4)
   425  
   426  	// 3671433862ea385f967377d836040cfa74bd66cf35ee1795cc48cab2a9576bc1
   427  	ok := pq.Insert(orders[0])
   428  	if !ok {
   429  		t.Errorf("Failed to insert order %v", orders[0])
   430  	}
   431  
   432  	// 1cc5fe0804be6b8112b71dd2d8d4a48177ee78a7f2c663e620c369d3211c86a1 ** higher priority
   433  	ok = pq.Insert(orders[4])
   434  	if !ok {
   435  		t.Errorf("Failed to insert order %v", orders[4])
   436  	}
   437  
   438  	best := pq.ExtractBest()
   439  	if best.UID() != orders[4].UID() {
   440  		t.Errorf("Incorrect highest rate order returned: rate = %d, UID = %s",
   441  			best.Price(), best.UID())
   442  	}
   443  }
   444  
   445  func TestOrderPQCapacity(t *testing.T) {
   446  	pq := NewMaxOrderPQ(2)
   447  
   448  	ok := pq.Insert(orders[0])
   449  	if !ok {
   450  		t.Errorf("Failed to insert order %v", orders[0])
   451  	}
   452  
   453  	ok = pq.Insert(orders[1])
   454  	if !ok {
   455  		t.Errorf("Failed to insert order %v", orders[1])
   456  	}
   457  
   458  	ok = pq.Insert(orders[2])
   459  	if !ok {
   460  		t.Errorf("Failed to insert order %v", orders[2])
   461  	}
   462  
   463  	if pq.Cap() <= 2 {
   464  		t.Errorf("Failed to grow capacity")
   465  	}
   466  
   467  	if pq.Len() != 3 {
   468  		t.Errorf("Failed to insert order with capacity growth")
   469  	}
   470  
   471  	best := pq.PeekBest()
   472  	if best.UID() != orders[2].UID() {
   473  		t.Errorf("Incorrect highest rate order returned: rate = %d, UID = %s",
   474  			best.Price(), best.UID())
   475  	}
   476  }
   477  
   478  func TestOrderPQ_Insert_negative(t *testing.T) {
   479  	pq := NewMinOrderPQ(2)
   480  
   481  	ok := pq.Insert(orders[0])
   482  	if !ok {
   483  		t.Errorf("Failed to insert order %v", orders[0])
   484  	}
   485  
   486  	ok = pq.Insert(orders[0])
   487  	if ok {
   488  		t.Errorf("Inserted duplicate order %v", orders[1])
   489  	}
   490  
   491  	ok = pq.Insert(nil)
   492  	if ok {
   493  		t.Errorf("Inserted nil order %v", orders[1])
   494  	}
   495  }
   496  
   497  func TestOrderPQ_Remove(t *testing.T) {
   498  	pq := NewMaxOrderPQ(2)
   499  
   500  	ok := pq.Insert(orders[0])
   501  	if !ok {
   502  		t.Errorf("Failed to insert order %v", orders[0])
   503  	}
   504  
   505  	ok = pq.Insert(orders[1])
   506  	if !ok {
   507  		t.Errorf("Failed to insert order %v", orders[1])
   508  	}
   509  
   510  	pq.RemoveOrder(orders[1])
   511  	if pq.Len() != 1 {
   512  		t.Errorf("Queue length expected %d, got %d", 1, pq.Len())
   513  	}
   514  	remainingID := pq.PeekBest().ID()
   515  	if remainingID != orders[0].ID() {
   516  		t.Errorf("Remaining element expected %s, got %s", orders[0].ID(),
   517  			remainingID)
   518  	}
   519  	pq.RemoveOrderID(remainingID)
   520  	if pq.Len() != 0 {
   521  		t.Errorf("Expected empty queue, got %d", pq.Len())
   522  	}
   523  }
   524  
   525  func TestOrderPQ_RemoveUserOrders(t *testing.T) {
   526  	pq := NewMaxOrderPQ(6)
   527  
   528  	ok := pq.Insert(orders[0])
   529  	if !ok {
   530  		t.Errorf("Failed to insert order %v", orders[0])
   531  	}
   532  
   533  	ok = pq.Insert(orders[1])
   534  	if !ok {
   535  		t.Errorf("Failed to insert order %v", orders[1])
   536  	}
   537  
   538  	user0 := orders[0].AccountID
   539  
   540  	user1 := randomAccount()
   541  	other := newLimitOrder(false, 42000000, 2, order.StandingTiF, 0)
   542  	other.AccountID = user1
   543  	ok = pq.Insert(other)
   544  	if !ok {
   545  		t.Errorf("Failed to insert order %v", other)
   546  	}
   547  
   548  	amt, count := pq.UserOrderTotals(user0)
   549  	wantAmt := orders[0].Remaining() + orders[1].Remaining()
   550  	if amt != wantAmt {
   551  		t.Errorf("wanted %d remaining, got %d", wantAmt, amt)
   552  	}
   553  	if count != 2 {
   554  		t.Errorf("wanted %d orders, got %d", 2, count)
   555  	}
   556  
   557  	amt, count = pq.UserOrderTotals(user1)
   558  	wantAmt = other.Remaining()
   559  	if amt != wantAmt {
   560  		t.Errorf("wanted %d remaining, got %d", wantAmt, amt)
   561  	}
   562  	if count != 1 {
   563  		t.Errorf("wanted %d orders, got %d", 1, count)
   564  	}
   565  
   566  	removed := pq.RemoveUserOrders(user0)
   567  	if pq.Len() != 1 {
   568  		t.Errorf("Queue length expected %d, got %d", 1, pq.Len())
   569  	}
   570  	if len(removed) != 2 {
   571  		t.Fatalf("removed %d orders, expected %d", len(removed), 2)
   572  	}
   573  	for _, oid := range []order.OrderID{orders[0].ID(), orders[1].ID()} {
   574  		var found bool
   575  		for i := range removed {
   576  			if oid == removed[i].ID() {
   577  				found = true
   578  				break
   579  			}
   580  		}
   581  		if !found {
   582  			t.Errorf("didn't remove order %v", oid)
   583  		}
   584  	}
   585  
   586  	remainingID := pq.PeekBest().ID()
   587  	if remainingID != other.ID() {
   588  		t.Errorf("Remaining element expected %s, got %s", other.ID(),
   589  			remainingID)
   590  	}
   591  	removed = pq.RemoveUserOrders(user1)
   592  	if remain := pq.Len(); remain != 0 {
   593  		t.Errorf("didn't remove all orders, still have %d", remain)
   594  	}
   595  	if len(removed) != 1 {
   596  		t.Fatalf("removed %d orders, expected %d", len(removed), 1)
   597  	}
   598  	if removed[0].ID() != other.ID() {
   599  		t.Errorf("removed order %v, expected %v", removed[0], other.ID())
   600  	}
   601  }
   602  
   603  func TestOrderPQMin_Worst(t *testing.T) {
   604  	pq0 := NewMinOrderPQ(4)
   605  	worst := pq0.Worst()
   606  	if worst != nil {
   607  		t.Errorf("Worst for an empty queue should be nil, got %v", worst)
   608  	}
   609  
   610  	pq1 := NewMinOrderPQ(4)
   611  	if !pq1.Insert(bigList[0]) {
   612  		t.Fatalf("Failed to insert order %v", bigList[0])
   613  	}
   614  	worst = pq1.Worst()
   615  	if worst.UID() != bigList[0].UID() {
   616  		t.Errorf("Worst failed to return the only order in the queue, got %v", worst)
   617  	}
   618  
   619  	// Min oriented queue
   620  	pq := NewMinOrderPQ(uint32(len(bigList) - len(bigList)/16))
   621  	for _, o := range bigList {
   622  		ok := pq.Insert(o)
   623  		if !ok {
   624  			t.Fatalf("Failed to insert order %v", o)
   625  		}
   626  	}
   627  
   628  	if pq.Len() != len(bigList) {
   629  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   630  	}
   631  
   632  	sort.Slice(bigList, func(i, j int) bool {
   633  		if bigList[i].Price() == bigList[j].Price() {
   634  			return bigList[i].Time() < bigList[j].Time()
   635  		}
   636  		return bigList[i].Price() < bigList[j].Price()
   637  	})
   638  
   639  	// Worst for a min queue is highest rate.
   640  	worst = pq.Worst()
   641  	if worst.UID() != bigList[len(bigList)-1].UID() {
   642  		t.Errorf("Incorrect worst order. Got %s, expected %s", worst.UID(), bigList[len(bigList)-1].UID())
   643  	}
   644  }
   645  
   646  func TestOrderPQMax_Worst(t *testing.T) {
   647  	// Max oriented queue
   648  	pq := NewMaxOrderPQ(uint32(len(bigList)))
   649  	for _, o := range bigList {
   650  		ok := pq.Insert(o)
   651  		if !ok {
   652  			t.Fatalf("Failed to insert order %v", o)
   653  		}
   654  	}
   655  
   656  	if pq.Len() != len(bigList) {
   657  		t.Errorf("pq length incorrect. expected %d, got %d", len(bigList), pq.Len())
   658  	}
   659  
   660  	sort.Slice(bigList, func(j, i int) bool {
   661  		if bigList[i].Price() == bigList[j].Price() {
   662  			return bigList[i].Time() < bigList[j].Time()
   663  		}
   664  		return bigList[i].Price() < bigList[j].Price()
   665  	})
   666  
   667  	// Worst for a min queue is highest rate.
   668  	worst := pq.Worst()
   669  	if worst.UID() != bigList[len(bigList)-1].UID() {
   670  		t.Errorf("Incorrect worst order. Got %s, expected %s", worst.UID(), bigList[len(bigList)-1].UID())
   671  	}
   672  }
   673  
   674  func TestOrderPQMax_leafNodes(t *testing.T) {
   675  	// Max oriented queue
   676  	newQ := func(list []*Order) *OrderPQ {
   677  		pq := NewMaxOrderPQ(uint32(len(bigList)))
   678  		for _, o := range list {
   679  			ok := pq.Insert(o)
   680  			if !ok {
   681  				t.Fatalf("Failed to insert order %v", o)
   682  			}
   683  		}
   684  		return pq
   685  	}
   686  
   687  	for sz := 0; sz < 131; sz++ {
   688  		list := bigList[:sz]
   689  		pq := newQ(list)
   690  		leaves := pq.leafNodes()
   691  		total := pq.Count()
   692  		expectedNum := total / 2
   693  		if total%2 != 0 {
   694  			expectedNum++
   695  		}
   696  		if len(leaves) != expectedNum {
   697  			t.Errorf("Incorrect number of leaf nodes. Got %d, expected %d",
   698  				len(leaves), expectedNum)
   699  		}
   700  	}
   701  }