github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/lfstack_test.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime_test 6 7 import ( 8 "math/rand" 9 . "runtime" 10 "testing" 11 "unsafe" 12 ) 13 14 type MyNode struct { 15 LFNode 16 data int 17 } 18 19 func fromMyNode(node *MyNode) *LFNode { 20 return (*LFNode)(unsafe.Pointer(node)) 21 } 22 23 func toMyNode(node *LFNode) *MyNode { 24 return (*MyNode)(unsafe.Pointer(node)) 25 } 26 27 func TestLFStack(t *testing.T) { 28 stack := new(uint64) 29 // Need to keep additional referenfces to nodes, the stack is not all that type-safe. 30 var nodes []*MyNode 31 32 // Check the stack is initially empty. 33 if LFStackPop(stack) != nil { 34 t.Fatalf("stack is not empty") 35 } 36 37 // Push one element. 38 node := &MyNode{data: 42} 39 nodes = append(nodes, node) 40 LFStackPush(stack, fromMyNode(node)) 41 42 // Push another. 43 node = &MyNode{data: 43} 44 nodes = append(nodes, node) 45 LFStackPush(stack, fromMyNode(node)) 46 47 // Pop one element. 48 node = toMyNode(LFStackPop(stack)) 49 if node == nil { 50 t.Fatalf("stack is empty") 51 } 52 if node.data != 43 { 53 t.Fatalf("no lifo") 54 } 55 56 // Pop another. 57 node = toMyNode(LFStackPop(stack)) 58 if node == nil { 59 t.Fatalf("stack is empty") 60 } 61 if node.data != 42 { 62 t.Fatalf("no lifo") 63 } 64 65 // Check the stack is empty again. 66 if LFStackPop(stack) != nil { 67 t.Fatalf("stack is not empty") 68 } 69 if *stack != 0 { 70 t.Fatalf("stack is not empty") 71 } 72 } 73 74 func TestLFStackStress(t *testing.T) { 75 const K = 100 76 P := 4 * GOMAXPROCS(-1) 77 N := 100000 78 if testing.Short() { 79 N /= 10 80 } 81 // Create 2 stacks. 82 stacks := [2]*uint64{new(uint64), new(uint64)} 83 // Need to keep additional referenfces to nodes, the stack is not all that type-safe. 84 var nodes []*MyNode 85 // Push K elements randomly onto the stacks. 86 sum := 0 87 for i := 0; i < K; i++ { 88 sum += i 89 node := &MyNode{data: i} 90 nodes = append(nodes, node) 91 LFStackPush(stacks[i%2], fromMyNode(node)) 92 } 93 c := make(chan bool, P) 94 for p := 0; p < P; p++ { 95 go func() { 96 r := rand.New(rand.NewSource(rand.Int63())) 97 // Pop a node from a random stack, then push it onto a random stack. 98 for i := 0; i < N; i++ { 99 node := toMyNode(LFStackPop(stacks[r.Intn(2)])) 100 if node != nil { 101 LFStackPush(stacks[r.Intn(2)], fromMyNode(node)) 102 } 103 } 104 c <- true 105 }() 106 } 107 for i := 0; i < P; i++ { 108 <-c 109 } 110 // Pop all elements from both stacks, and verify that nothing lost. 111 sum2 := 0 112 cnt := 0 113 for i := 0; i < 2; i++ { 114 for { 115 node := toMyNode(LFStackPop(stacks[i])) 116 if node == nil { 117 break 118 } 119 cnt++ 120 sum2 += node.data 121 node.Next = nil 122 } 123 } 124 if cnt != K { 125 t.Fatalf("Wrong number of nodes %d/%d", cnt, K) 126 } 127 if sum2 != sum { 128 t.Fatalf("Wrong sum %d/%d", sum2, sum) 129 } 130 }