2018-08-18 00:26:43 +00:00
|
|
|
package delayheap
|
2018-03-02 00:28:02 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2022-03-15 12:42:43 +00:00
|
|
|
"github.com/hashicorp/nomad/ci"
|
2018-03-02 00:28:02 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
// HeapNodeImpl satisfies the HeapNode interface
|
|
|
|
type heapNodeImpl struct {
|
|
|
|
dataObject interface{}
|
|
|
|
id string
|
|
|
|
namespace string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *heapNodeImpl) Data() interface{} {
|
|
|
|
return d.dataObject
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *heapNodeImpl) ID() string {
|
|
|
|
return d.id
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *heapNodeImpl) Namespace() string {
|
|
|
|
return d.namespace
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDelayHeap_PushPop(t *testing.T) {
|
2022-03-15 12:42:43 +00:00
|
|
|
ci.Parallel(t)
|
|
|
|
|
2018-03-02 00:28:02 +00:00
|
|
|
delayHeap := NewDelayHeap()
|
|
|
|
now := time.Now()
|
|
|
|
require := require.New(t)
|
|
|
|
// a dummy type to use as the inner object in the heap
|
|
|
|
type myObj struct {
|
|
|
|
a int
|
|
|
|
b string
|
|
|
|
}
|
|
|
|
dataNode1 := &heapNodeImpl{
|
|
|
|
dataObject: &myObj{a: 0, b: "hey"},
|
|
|
|
id: "101",
|
|
|
|
namespace: "default",
|
|
|
|
}
|
|
|
|
delayHeap.Push(dataNode1, now.Add(-10*time.Minute))
|
|
|
|
|
|
|
|
dataNode2 := &heapNodeImpl{
|
|
|
|
dataObject: &myObj{a: 0, b: "hey"},
|
|
|
|
id: "102",
|
|
|
|
namespace: "default",
|
|
|
|
}
|
|
|
|
delayHeap.Push(dataNode2, now.Add(10*time.Minute))
|
|
|
|
|
|
|
|
dataNode3 := &heapNodeImpl{
|
|
|
|
dataObject: &myObj{a: 0, b: "hey"},
|
|
|
|
id: "103",
|
|
|
|
namespace: "default",
|
|
|
|
}
|
|
|
|
delayHeap.Push(dataNode3, now.Add(-15*time.Second))
|
|
|
|
|
|
|
|
dataNode4 := &heapNodeImpl{
|
|
|
|
dataObject: &myObj{a: 0, b: "hey"},
|
|
|
|
id: "101",
|
|
|
|
namespace: "test-namespace",
|
|
|
|
}
|
|
|
|
delayHeap.Push(dataNode4, now.Add(2*time.Hour))
|
|
|
|
|
|
|
|
expectedWaitTimes := []time.Time{now.Add(-10 * time.Minute), now.Add(-15 * time.Second), now.Add(10 * time.Minute), now.Add(2 * time.Hour)}
|
|
|
|
entries := getHeapEntries(delayHeap, now)
|
|
|
|
for i, entry := range entries {
|
|
|
|
require.Equal(expectedWaitTimes[i], entry.WaitUntil)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDelayHeap_Update(t *testing.T) {
|
2022-03-15 12:42:43 +00:00
|
|
|
ci.Parallel(t)
|
2022-08-16 14:06:30 +00:00
|
|
|
|
2018-03-02 00:28:02 +00:00
|
|
|
delayHeap := NewDelayHeap()
|
|
|
|
now := time.Now()
|
|
|
|
require := require.New(t)
|
|
|
|
// a dummy type to use as the inner object in the heap
|
|
|
|
type myObj struct {
|
|
|
|
a int
|
|
|
|
b string
|
|
|
|
}
|
|
|
|
dataNode1 := &heapNodeImpl{
|
|
|
|
dataObject: &myObj{a: 0, b: "hey"},
|
|
|
|
id: "101",
|
|
|
|
namespace: "default",
|
|
|
|
}
|
|
|
|
delayHeap.Push(dataNode1, now.Add(-10*time.Minute))
|
|
|
|
|
|
|
|
dataNode2 := &heapNodeImpl{
|
|
|
|
dataObject: &myObj{a: 0, b: "hey"},
|
|
|
|
id: "102",
|
|
|
|
namespace: "default",
|
|
|
|
}
|
|
|
|
delayHeap.Push(dataNode2, now.Add(10*time.Minute))
|
|
|
|
delayHeap.Update(dataNode1, now.Add(20*time.Minute))
|
|
|
|
|
|
|
|
expectedWaitTimes := []time.Time{now.Add(10 * time.Minute), now.Add(20 * time.Minute)}
|
|
|
|
expectedIdOrder := []string{"102", "101"}
|
|
|
|
entries := getHeapEntries(delayHeap, now)
|
|
|
|
for i, entry := range entries {
|
|
|
|
require.Equal(expectedWaitTimes[i], entry.WaitUntil)
|
|
|
|
require.Equal(expectedIdOrder[i], entry.Node.ID())
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-03-06 03:46:54 +00:00
|
|
|
func getHeapEntries(delayHeap *DelayHeap, now time.Time) []*delayHeapNode {
|
|
|
|
var entries []*delayHeapNode
|
2018-03-02 00:28:02 +00:00
|
|
|
for node := delayHeap.Pop(); node != nil; {
|
|
|
|
entries = append(entries, node)
|
|
|
|
node = delayHeap.Pop()
|
|
|
|
}
|
|
|
|
return entries
|
|
|
|
}
|