Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libgo / go / runtime / lfstack_test.go
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 }