// 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++ } }