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