blob: 5839bf63c3144a5eaf823a0f8c6bbf4d830b1806 [file] [log] [blame]
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime_test
import (
"runtime"
"testing"
"unsafe"
)
type listedVal struct {
val int
aNode runtime.ListNode
bNode runtime.ListNode
}
func newListedVal(v int) *listedVal {
return &listedVal{
val: v,
}
}
func TestListPush(t *testing.T) {
var headA runtime.ListHead
headA.Init(unsafe.Offsetof(listedVal{}.aNode))
one := newListedVal(1)
headA.Push(unsafe.Pointer(one))
two := newListedVal(2)
headA.Push(unsafe.Pointer(two))
three := newListedVal(3)
headA.Push(unsafe.Pointer(three))
p := headA.Pop()
v := (*listedVal)(p)
if v == nil {
t.Fatalf("pop got nil want 3")
}
if v.val != 3 {
t.Errorf("pop got %d want 3", v.val)
}
p = headA.Pop()
v = (*listedVal)(p)
if v == nil {
t.Fatalf("pop got nil want 2")
}
if v.val != 2 {
t.Errorf("pop got %d want 2", v.val)
}
p = headA.Pop()
v = (*listedVal)(p)
if v == nil {
t.Fatalf("pop got nil want 1")
}
if v.val != 1 {
t.Errorf("pop got %d want 1", v.val)
}
p = headA.Pop()
v = (*listedVal)(p)
if v != nil {
t.Fatalf("pop got %+v want nil", v)
}
}
func wantVal(t *testing.T, v *listedVal, i int) {
t.Helper()
if v == nil {
t.Fatalf("listedVal got nil want %d", i)
}
if v.val != i {
t.Errorf("pop got %d want %d", v.val, i)
}
}
func TestListRemoveHead(t *testing.T) {
var headA runtime.ListHead
headA.Init(unsafe.Offsetof(listedVal{}.aNode))
one := newListedVal(1)
headA.Push(unsafe.Pointer(one))
two := newListedVal(2)
headA.Push(unsafe.Pointer(two))
three := newListedVal(3)
headA.Push(unsafe.Pointer(three))
headA.Remove(unsafe.Pointer(three))
p := headA.Pop()
v := (*listedVal)(p)
wantVal(t, v, 2)
p = headA.Pop()
v = (*listedVal)(p)
wantVal(t, v, 1)
p = headA.Pop()
v = (*listedVal)(p)
if v != nil {
t.Fatalf("pop got %+v want nil", v)
}
}
func TestListRemoveMiddle(t *testing.T) {
var headA runtime.ListHead
headA.Init(unsafe.Offsetof(listedVal{}.aNode))
one := newListedVal(1)
headA.Push(unsafe.Pointer(one))
two := newListedVal(2)
headA.Push(unsafe.Pointer(two))
three := newListedVal(3)
headA.Push(unsafe.Pointer(three))
headA.Remove(unsafe.Pointer(two))
p := headA.Pop()
v := (*listedVal)(p)
wantVal(t, v, 3)
p = headA.Pop()
v = (*listedVal)(p)
wantVal(t, v, 1)
p = headA.Pop()
v = (*listedVal)(p)
if v != nil {
t.Fatalf("pop got %+v want nil", v)
}
}
func TestListRemoveTail(t *testing.T) {
var headA runtime.ListHead
headA.Init(unsafe.Offsetof(listedVal{}.aNode))
one := newListedVal(1)
headA.Push(unsafe.Pointer(one))
two := newListedVal(2)
headA.Push(unsafe.Pointer(two))
three := newListedVal(3)
headA.Push(unsafe.Pointer(three))
headA.Remove(unsafe.Pointer(one))
p := headA.Pop()
v := (*listedVal)(p)
wantVal(t, v, 3)
p = headA.Pop()
v = (*listedVal)(p)
wantVal(t, v, 2)
p = headA.Pop()
v = (*listedVal)(p)
if v != nil {
t.Fatalf("pop got %+v want nil", v)
}
}
func TestListRemoveAll(t *testing.T) {
var headA runtime.ListHead
headA.Init(unsafe.Offsetof(listedVal{}.aNode))
one := newListedVal(1)
headA.Push(unsafe.Pointer(one))
two := newListedVal(2)
headA.Push(unsafe.Pointer(two))
three := newListedVal(3)
headA.Push(unsafe.Pointer(three))
headA.Remove(unsafe.Pointer(one))
headA.Remove(unsafe.Pointer(two))
headA.Remove(unsafe.Pointer(three))
p := headA.Pop()
v := (*listedVal)(p)
if v != nil {
t.Fatalf("pop got %+v want nil", v)
}
}
func BenchmarkListPushPop(b *testing.B) {
var head runtime.ListHead
head.Init(unsafe.Offsetof(listedVal{}.aNode))
vals := make([]listedVal, 10000)
i := 0
for b.Loop() {
if i == len(vals) {
for range len(vals) {
head.Pop()
}
i = 0
}
head.Push(unsafe.Pointer(&vals[i]))
i++
}
}