github.com/tursom/GoCollections@v0.3.10/concurrent/collections/ConcurrentLinkedQueue_test.go (about) 1 /* 2 * Copyright (c) 2022 tursom. All rights reserved. 3 * Use of this source code is governed by a GPL-3 4 * license that can be found in the LICENSE file. 5 */ 6 7 package collections 8 9 import ( 10 "fmt" 11 "math/rand" 12 "sync" 13 "testing" 14 "unsafe" 15 16 "github.com/tursom/GoCollections/util/time" 17 18 "github.com/tursom/GoCollections/collections" 19 "github.com/tursom/GoCollections/exceptions" 20 "github.com/tursom/GoCollections/lang" 21 ) 22 23 type data struct { 24 lang.BaseObject 25 id int 26 index int 27 } 28 29 func (d *data) String() string { 30 return fmt.Sprintf("(%d,%d)", d.id, d.index) 31 } 32 33 func TestConcurrentLinkedQueue_NodeSize(t *testing.T) { 34 fmt.Println(unsafe.Alignof(linkedStackNode[*data]{})) 35 fmt.Println(unsafe.Sizeof(linkedStackNode[*data]{})) 36 } 37 38 func TestConcurrentLinkedQueue_Push(t *testing.T) { 39 queue := NewLinkedQueue[*data]() 40 cond := sync.WaitGroup{} 41 cond.Add(1) 42 for i := 0; i < 10; i++ { 43 id := i 44 go func() { 45 cond.Wait() 46 for i := 0; i < 100; i++ { 47 _ = queue.Offer(&data{id: id, index: i}) 48 } 49 }() 50 } 51 time.Sleep(time.Second) 52 cond.Done() 53 time.Sleep(time.Second) 54 fmt.Println(queue) 55 } 56 57 func TestConcurrentLinkedQueue_ThreadSafe(t *testing.T) { 58 times := 400000 59 queue := NewLinkedQueue[*data]() 60 for i := 0; i < 100; i++ { 61 id := i 62 go func() { 63 //nodes := make([]QueueNode[*data], 0) 64 for j := 0; j < times; j++ { 65 _ = queue.Offer(&data{id: id, index: j}) 66 //node, _ := queue.OfferAndGetNode(&data{id: id, index: j}) 67 //nodes = append(nodes, node) 68 //fmt.Println(queue) 69 } 70 //time.Sleep(time.Second * 1) 71 fmt.Println(queue.Size()) 72 //for _, node := range nodes { 73 // exceptions.Exec0r0(node.Remove) 74 //} 75 for j := 0; j < times; j++ { 76 offer, _ := queue.Poll() 77 if offer == nil { 78 panic("offer is nil") 79 } 80 } 81 }() 82 } 83 84 time.Sleep(time.Second * 10) 85 if queue.Size() != 0 { 86 t.Fatalf(fmt.Sprintf("queue remain %d element, is not thread safe", queue.Size())) 87 } 88 //for !queue.IsEmpty() { 89 // fmt.Println(queue.Offer()) 90 //} 91 } 92 93 func Test_concurrentLinkedQueueIterator_Remove(t *testing.T) { 94 queue := NewLinkedQueue[lang.Int]() 95 96 for i := 0; i < 16; i++ { 97 testConcurrentLinkedQueueIteratorRemove(t, queue, 1000) 98 t.Logf("Test_concurrentLinkedQueueIterator_Remove passed on %d loop", i+1) 99 } 100 } 101 102 func testConcurrentLinkedQueueIteratorRemove(t *testing.T, queue *ConcurrentLinkedQueue[lang.Int], nodeNumber int) { 103 nodes := make(chan collections.StackNode[lang.Int], nodeNumber) 104 nodesIndex := make([]bool, nodeNumber) 105 b := rand.Int()&1 == 1 106 if b { 107 for i := 0; i < 4; i++ { 108 go func() { 109 for node := range nodes { 110 index := exceptions.Exec0r1(node.RemoveAndGet) 111 if nodesIndex[index] { 112 t.Fatalf("TODO Fatalf") 113 } 114 nodesIndex[index] = true 115 } 116 }() 117 } 118 } 119 120 for i := 0; i < nodeNumber; i++ { 121 node, _ := queue.OfferAndGetNode(lang.Int(i)) 122 nodes <- node 123 } 124 125 close(nodes) 126 127 if !b { 128 for i := 0; i < 4; i++ { 129 go func() { 130 for node := range nodes { 131 index := exceptions.Exec0r1(node.RemoveAndGet) 132 if nodesIndex[index] { 133 t.Fatalf("TODO Fatalf") 134 } 135 nodesIndex[index] = true 136 } 137 }() 138 } 139 } 140 141 time.Sleep(time.Second / 5) 142 143 head := queue.head 144 if head != nil && head.deleted { 145 head = head.next 146 } 147 if head != nil { 148 t.Fatalf(fmt.Sprintf("queue remain %d element, is not thread safe", queue.Size())) 149 } 150 }