-
Notifications
You must be signed in to change notification settings - Fork 0
/
list_test.go
126 lines (106 loc) · 3.38 KB
/
list_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package embedded_test
import (
"testing"
"unsafe"
embedded "github.com/heucuva/go-embedded-container"
)
type listEntry struct {
data int
link embedded.ListLink[listEntry]
}
var listEntryLinkField = unsafe.Offsetof(listEntry{}.link)
func TestEmbeddedList(t *testing.T) {
const testSize = 5500
const removeTarget = (testSize / 2) - 1
c := embedded.NewList[listEntry](listEntryLinkField)
testEmbeddedList(t, c, testSize, removeTarget)
}
func BenchmarkEmbeddedList_InsertLast(b *testing.B) {
list := embedded.NewList[listEntry](listEntryLinkField)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
list.InsertLast(&listEntry{data: i})
}
}
func BenchmarkEmbeddedList_InsertFirst(b *testing.B) {
list := embedded.NewList[listEntry](listEntryLinkField)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
list.InsertFirst(&listEntry{data: i})
}
}
func testEmbeddedList(t *testing.T, c embedded.List[listEntry], testSize int, removeTarget int) {
for i := 0; i < testSize; i++ {
c.InsertLast(&listEntry{data: i})
}
if c.IsEmpty() {
t.Fatal("embedded list should not be empty")
}
var removedEntry *listEntry
for i := testSize - 1; i >= 0; i-- {
var entry *listEntry
for cur := c.Last(); cur != nil; cur = c.Prev(cur) {
if cur.data == i {
entry = cur
break
}
}
if entry == nil {
t.Fatal("expected entry not found")
}
if i == removeTarget {
if actualEntry := c.Position(i); actualEntry != entry {
t.Fatalf("item not found at expected position")
}
if !c.IsContained(entry) {
t.Fatal("embedded list reports that contained item is not present")
}
removedEntry = c.Remove(entry)
if c.IsContained(entry) {
t.Fatal("embedded list reports that removed item is present")
}
}
}
for walk := c.First(); walk != nil; walk = c.Next(walk) {
if walk.data == removeTarget {
t.Fatal("removed item still present in embedded list")
}
}
for walk := c.Last(); walk != nil; walk = c.Prev(walk) {
if walk.data == removeTarget {
t.Fatal("removed item still present in embedded list")
}
}
expectedCount := c.Count()
if moveItem := c.First(); moveItem != nil {
c.MoveLast(moveItem)
if lastItem := c.Last(); moveItem == nil {
t.Fatal("could not find moved item in embedded list")
} else if lastItem != moveItem {
t.Fatal("expected to find moved item, but found something else")
}
} else {
t.Fatal("could not find any item in embedded list")
}
if actualCount := c.Count(); actualCount != expectedCount {
t.Fatalf("count changed unexpectedly (actual %d != expected %d)", actualCount, expectedCount)
}
c.MoveLast(removedEntry)
c.MoveAfter(c.First(), removedEntry)
c.MoveBefore(c.Last(), removedEntry)
c.MoveFirst(removedEntry)
if actualLast := c.RemoveLast(); actualLast == nil {
t.Fatal("no item at end of embedded list")
} else if expectedLast := 0; actualLast.data != expectedLast {
t.Fatalf("mismatched item at end of embedded list (actual %d != expected %d)", actualLast.data, expectedLast)
}
if actualFirst := c.RemoveFirst(); actualFirst == nil {
t.Fatal("no item at front of embedded list")
} else if expectedFirst := removeTarget; actualFirst.data != expectedFirst {
t.Fatalf("mismatched item at front of embedded list (actual %d != expected %d)", actualFirst.data, expectedFirst)
}
c.RemoveAll()
if actualCount := c.Count(); actualCount != 0 {
t.Fatalf("unexpected list count (actual %d != expected %d)", actualCount, 0)
}
}