I'm unit testing a quick queue I wrote using containers.list.List from Go stdlib. It uses mutexes on reads and writes, and I wanted to test whether the mutexes work.
This is my logic: Since Pop() returns nil when there's nothing in the queue, I can count that as a soft fail. So at the end when both methods are finished if the amount of nulls are equal to the number of elements left in the queue, then the test passed. Otherwise it hard fails. My problem is that it still occasionally fails and I'm not exactly sure why. Is it my code or is it something internal I don't understand?
Here is some sample output:
vagrant@vagrant-ubuntu-trusty-64:~/yyyyyyyy$ sh run_queue_test.sh
ok http://ift.tt/1IeXf6c 0.367s
vagrant@vagrant-ubuntu-trusty-64:~/yyyyyyyy$ sh run_queue_test.sh
ok http://ift.tt/1IeXf6c 0.341s
vagrant@vagrant-ubuntu-trusty-64:~/yyyyyyyy$ sh run_queue_test.sh
ok http://ift.tt/1IeXf6c 0.337s
vagrant@vagrant-ubuntu-trusty-64:~/yyyyyyyy$ sh run_queue_test.sh
ok http://ift.tt/1IeXf6c 0.347s
vagrant@vagrant-ubuntu-trusty-64:~/yyyyyyyy$ sh run_queue_test.sh
ok http://ift.tt/1IeXf6c 0.373s
vagrant@vagrant-ubuntu-trusty-64:~/yyyyyyyy$ sh run_queue_test.sh
ok http://ift.tt/1IeXf6c 0.336s
vagrant@vagrant-ubuntu-trusty-64:~/yyyyyyyy$ sh run_queue_test.sh
ok http://ift.tt/1IeXf6c 0.351s
vagrant@vagrant-ubuntu-trusty-64:~/yyyyyyyy$ sh run_queue_test.sh
--- FAIL: TestNew (0.33s)
queue_test.go:30: finished push
queue_test.go:48: finished pop
queue_test.go:50: push sent ok flag
queue_test.go:52:
Elements Left: 8912
Failed 9819 times
FAIL
FAIL http://ift.tt/1IeXf6c 0.337s
vagrant@vagrant-ubuntu-trusty-64:~/yyyyyyyy$ sh run_queue_test.sh
ok http://ift.tt/1IeXf6c 0.340s
As you can see.. it fails. Here are the relevant parts of my queue:
type Queue struct {
*list.List
*sync.Mutex
}
func New() *Queue {
queue := &Queue{list.New(), &sync.Mutex{}}
return queue
}
func (queue *Queue) Push(e interface{}) interface{} {
queue.Lock()
defer queue.Unlock()
element := queue.PushBack(e)
return element
}
func (queue *Queue) Pop() interface{} {
queue.Lock()
defer queue.Unlock()
front := queue.Front()
if front == nil {
return nil
}
return queue.Remove(front)
}
And here is the relevant test code:
func TestNew(test *testing.T) {
queue := New()
sema := make(chan bool)
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
queue.TestPush(test, sema)
}()
go func() {
defer wg.Done()
queue.TestPop(test, sema)
}()
wg.Wait()
}
func (queue *Queue) TestPush(test *testing.T, semaphore chan bool) {
for i := 0; i < 100000; i++ {
go func() {
queue.Push(i)
}()
}
test.Log("finished push")
semaphore <- true
}
func (queue *Queue) TestPop(test *testing.T, semaphore chan bool) {
var fc int
var wg sync.WaitGroup
for i := 0; i < 100000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
e := queue.Pop()
if e == nil {
fc++
}
}()
}
wg.Wait()
test.Log("finished pop")
<-semaphore
test.Log("push sent ok flag")
if fc != queue.Len() {
test.Fatalf("\nElements Left: %d\nFailed %d times", queue.Len(), fc)
}
}
If anyone has any idea what's causing it to fail, I'd really appreciate an explanation :) I assume I failed some code or error in logic, but maybe it's above my head.
Thanks
Aucun commentaire:
Enregistrer un commentaire