2018-07-16 20:34:20 -04:00
|
|
|
package setmatrix
|
2017-06-07 16:09:50 -04:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"strconv"
|
2017-08-29 20:49:42 -04:00
|
|
|
"strings"
|
2017-06-07 16:09:50 -04:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestSetSerialInsertDelete(t *testing.T) {
|
|
|
|
s := NewSetMatrix()
|
|
|
|
|
|
|
|
b, i := s.Insert("a", "1")
|
|
|
|
if !b || i != 1 {
|
|
|
|
t.Fatalf("error in insert %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Insert("a", "1")
|
|
|
|
if b || i != 1 {
|
|
|
|
t.Fatalf("error in insert %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Insert("a", "2")
|
|
|
|
if !b || i != 2 {
|
|
|
|
t.Fatalf("error in insert %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Insert("a", "1")
|
|
|
|
if b || i != 2 {
|
|
|
|
t.Fatalf("error in insert %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Insert("a", "3")
|
|
|
|
if !b || i != 3 {
|
|
|
|
t.Fatalf("error in insert %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Insert("a", "2")
|
|
|
|
if b || i != 3 {
|
|
|
|
t.Fatalf("error in insert %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Insert("a", "3")
|
|
|
|
if b || i != 3 {
|
|
|
|
t.Fatalf("error in insert %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Insert("a", "4")
|
|
|
|
if !b || i != 4 {
|
|
|
|
t.Fatalf("error in insert %t %d", b, i)
|
|
|
|
}
|
|
|
|
|
|
|
|
b, p := s.Contains("a", "1")
|
|
|
|
if !b || !p {
|
|
|
|
t.Fatalf("error in contains %t %t", b, p)
|
|
|
|
}
|
|
|
|
b, p = s.Contains("a", "2")
|
|
|
|
if !b || !p {
|
|
|
|
t.Fatalf("error in contains %t %t", b, p)
|
|
|
|
}
|
|
|
|
b, p = s.Contains("a", "3")
|
|
|
|
if !b || !p {
|
|
|
|
t.Fatalf("error in contains %t %t", b, p)
|
|
|
|
}
|
|
|
|
b, p = s.Contains("a", "4")
|
|
|
|
if !b || !p {
|
|
|
|
t.Fatalf("error in contains %t %t", b, p)
|
|
|
|
}
|
|
|
|
|
|
|
|
i, b = s.Cardinality("a")
|
|
|
|
if !b || i != 4 {
|
|
|
|
t.Fatalf("error in cardinality count %t %d", b, i)
|
|
|
|
}
|
2017-08-29 20:49:42 -04:00
|
|
|
keys := s.Keys()
|
|
|
|
if len(keys) != 1 {
|
|
|
|
t.Fatalf("error in keys %v", keys)
|
|
|
|
}
|
|
|
|
str, b := s.String("a")
|
|
|
|
if !b ||
|
|
|
|
!strings.Contains(str, "1") ||
|
|
|
|
!strings.Contains(str, "2") ||
|
|
|
|
!strings.Contains(str, "3") ||
|
|
|
|
!strings.Contains(str, "4") {
|
|
|
|
t.Fatalf("error in string %t %s", b, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, b = s.Get("a")
|
|
|
|
if !b {
|
|
|
|
t.Fatalf("error in get %t", b)
|
|
|
|
}
|
2017-06-07 16:09:50 -04:00
|
|
|
|
|
|
|
b, i = s.Remove("a", "1")
|
|
|
|
if !b || i != 3 {
|
|
|
|
t.Fatalf("error in remove %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Remove("a", "3")
|
|
|
|
if !b || i != 2 {
|
|
|
|
t.Fatalf("error in remove %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Remove("a", "1")
|
|
|
|
if b || i != 2 {
|
|
|
|
t.Fatalf("error in remove %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Remove("a", "4")
|
|
|
|
if !b || i != 1 {
|
|
|
|
t.Fatalf("error in remove %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Remove("a", "2")
|
|
|
|
if !b || i != 0 {
|
|
|
|
t.Fatalf("error in remove %t %d", b, i)
|
|
|
|
}
|
|
|
|
b, i = s.Remove("a", "2")
|
|
|
|
if b || i != 0 {
|
|
|
|
t.Fatalf("error in remove %t %d", b, i)
|
|
|
|
}
|
|
|
|
|
|
|
|
i, b = s.Cardinality("a")
|
|
|
|
if b || i != 0 {
|
|
|
|
t.Fatalf("error in cardinality count %t %d", b, i)
|
|
|
|
}
|
2017-08-29 20:49:42 -04:00
|
|
|
|
|
|
|
str, b = s.String("a")
|
|
|
|
if b || str != "" {
|
|
|
|
t.Fatalf("error in string %t %s", b, str)
|
|
|
|
}
|
|
|
|
|
|
|
|
keys = s.Keys()
|
|
|
|
if len(keys) > 0 {
|
|
|
|
t.Fatalf("error in keys %v", keys)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Negative tests
|
|
|
|
_, b = s.Get("not exists")
|
|
|
|
if b {
|
|
|
|
t.Fatalf("error should not happen %t", b)
|
|
|
|
}
|
|
|
|
|
|
|
|
b1, b := s.Contains("not exists", "a")
|
|
|
|
if b1 || b {
|
|
|
|
t.Fatalf("error should not happen %t %t", b1, b)
|
|
|
|
}
|
2017-06-07 16:09:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func insertDeleteRotuine(ctx context.Context, endCh chan int, s SetMatrix, key, value string) {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
endCh <- 0
|
|
|
|
return
|
|
|
|
default:
|
|
|
|
b, _ := s.Insert(key, value)
|
|
|
|
if !b {
|
|
|
|
endCh <- 1
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
b, _ = s.Remove(key, value)
|
|
|
|
if !b {
|
|
|
|
endCh <- 2
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetParallelInsertDelete(t *testing.T) {
|
|
|
|
s := NewSetMatrix()
|
|
|
|
parallelRoutines := 6
|
|
|
|
endCh := make(chan int)
|
|
|
|
// Let the routines running and competing for 10s
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
defer cancel()
|
|
|
|
for i := 0; i < parallelRoutines; i++ {
|
|
|
|
go insertDeleteRotuine(ctx, endCh, s, "key-"+strconv.Itoa(i%3), strconv.Itoa(i))
|
|
|
|
}
|
|
|
|
for parallelRoutines > 0 {
|
|
|
|
v := <-endCh
|
|
|
|
if v == 1 {
|
|
|
|
t.Fatalf("error one goroutine failed on the insert")
|
|
|
|
}
|
|
|
|
if v == 2 {
|
|
|
|
t.Fatalf("error one goroutine failed on the remove")
|
|
|
|
}
|
|
|
|
parallelRoutines--
|
|
|
|
}
|
|
|
|
if i, b := s.Cardinality("key"); b || i > 0 {
|
|
|
|
t.Fatalf("error the set should be empty %t %d", b, i)
|
|
|
|
}
|
|
|
|
}
|