Add Byte Slice Intersection Utils (#3204)

* remove unused code

* table drive tests for byte slice intersections

* include all table driven tests

* gazelle imports

* imports
This commit is contained in:
Raul Jordan
2019-08-14 10:27:18 -05:00
committed by GitHub
parent 072bb4be27
commit d0bdbe5a33
15 changed files with 141 additions and 920 deletions

View File

@@ -3,13 +3,13 @@ package p2p
import (
"testing"
"github.com/libp2p/go-libp2p-pubsub"
pubsub "github.com/libp2p/go-libp2p-pubsub"
)
const (
// overlay parameters
gossipSubD = 6 // topic stable mesh target count
gossipSubDlo = 4 // topic stable mesh low watermark
gossipSubD = 6 // topic stable mesh target count
gossipSubDlo = 4 // topic stable mesh low watermark
gossipSubDhi = 12 // topic stable mesh high watermark
// gossip parameters

View File

@@ -5,12 +5,13 @@ package ethereum_beacon_p2p_v1
import (
fmt "fmt"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
v1alpha1 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -7,14 +7,15 @@ import (
context "context"
encoding_binary "encoding/binary"
fmt "fmt"
io "io"
math "math"
proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
_ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger/options"
v1alpha1 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -6,13 +6,14 @@ package ethereum_beacon_rpc_v1
import (
context "context"
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
empty "github.com/golang/protobuf/ptypes/empty"
_ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger/options"
v1alpha1 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,11 +5,12 @@ package eth
import (
fmt "fmt"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
github_com_prysmaticlabs_go_bitfield "github.com/prysmaticlabs/go-bitfield"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,10 +5,11 @@ package eth
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -7,13 +7,14 @@ import (
context "context"
encoding_binary "encoding/binary"
fmt "fmt"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -6,12 +6,13 @@ package eth
import (
context "context"
fmt "fmt"
io "io"
math "math"
proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -6,13 +6,14 @@ package eth
import (
context "context"
fmt "fmt"
io "io"
math "math"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
io "io"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,9 +5,10 @@ package ethereum_sharding_p2p_v1
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
proto "github.com/gogo/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.

View File

@@ -5,20 +5,14 @@ go_library(
srcs = [
"doc.go",
"slice.go",
"slice_generic.go",
],
importpath = "github.com/prysmaticlabs/prysm/shared/sliceutil",
visibility = ["//visibility:public"],
deps = ["@com_github_pkg_errors//:go_default_library"],
)
go_test(
name = "go_default_test",
size = "small",
srcs = [
"slice_generic_test.go",
"slice_test.go",
],
srcs = ["slice_test.go"],
embed = [":go_default_library"],
deps = ["@com_github_prysmaticlabs_go_ssz//:go_default_library"],
)

View File

@@ -174,64 +174,44 @@ func IsInInt64(a int64, b []int64) bool {
return false
}
// ByteIntersection returns a new set with elements that are common in
// both sets a and b.
func ByteIntersection(a []byte, b []byte) []byte {
set := make([]byte, 0)
m := make(map[byte]bool)
for i := 0; i < len(a); i++ {
m[a[i]] = true
// IntersectionByteSlices returns the common elements between two
// sets of byte slices.
func IntersectionByteSlices(s1, s2 [][]byte) [][]byte {
hash := make(map[string]bool)
for _, e := range s1 {
hash[string(e)] = true
}
for i := 0; i < len(b); i++ {
if _, found := m[b[i]]; found {
set = append(set, b[i])
inter := make([][]byte, 0)
for _, e := range s2 {
if hash[string(e)] {
inter = append(inter, e)
}
}
return set
}
// ByteUnion returns a new set with elements that are common in
// both sets a and b.
func ByteUnion(a []byte, b []byte) []byte {
set := make([]byte, 0)
m := make(map[byte]bool)
for i := 0; i < len(a); i++ {
m[a[i]] = true
set = append(set, a[i])
}
for i := 0; i < len(b); i++ {
if _, found := m[b[i]]; !found {
set = append(set, b[i])
// Remove duplicates from slice.
deduped := make([][]byte, 0)
encountered := make(map[string]bool)
for _, element := range inter {
if !encountered[string(element)] {
deduped = append(deduped, element)
encountered[string(element)] = true
}
}
return set
return deduped
}
// ByteNot returns a new set with elements that are common in
// both sets a and b.
func ByteNot(a []byte, b []byte) []byte {
set := make([]byte, 0)
m := make(map[byte]bool)
for i := 0; i < len(a); i++ {
m[a[i]] = true
// TotalIntersectionByteSlices takes in a set of byte slices
// and determines the intersection of common elements across all of them,
// returning a single slice of byte slices.
func TotalIntersectionByteSlices(sets [][][]byte) [][]byte {
if len(sets) == 0 {
return [][]byte{}
}
for i := 0; i < len(b); i++ {
if _, found := m[b[i]]; !found {
set = append(set, b[i])
}
if len(sets) == 1 {
return sets[0]
}
return set
}
// ByteIsIn returns true if a is in b and False otherwise.
func ByteIsIn(a byte, b []byte) bool {
for _, v := range b {
if a == v {
return true
}
}
return false
intersected := IntersectionByteSlices(sets[0], sets[1])
for i := 2; i < len(sets); i++ {
intersected = IntersectionByteSlices(intersected, sets[i])
}
return intersected
}

View File

@@ -1,155 +0,0 @@
package sliceutil
import (
"reflect"
"github.com/pkg/errors"
)
func interfaceToSlice(slice interface{}) ([]interface{}, error) {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
return nil, errors.New("slice error: not of type slice")
}
ret := make([]interface{}, s.Len())
for i := 0; i < s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret, nil
}
// GenericIntersection returns a new set with elements that are common in
// both sets a and b.
func GenericIntersection(a, b interface{}) (reflect.Value, error) {
set := reflect.MakeSlice(reflect.TypeOf(a), 0, 0)
set1, err := interfaceToSlice(a)
if err != nil {
return set, errors.Wrap(err, "slice type is invalid")
}
set2, err := interfaceToSlice(b)
if err != nil {
return set, errors.Wrap(err, "slice type is invalid")
}
if len(set1) == 0 || len(set2) == 0 {
return set, nil
}
m := reflect.MapOf(reflect.TypeOf(set1[0]), reflect.TypeOf(true))
m1 := reflect.MakeMapWithSize(m, 0)
for i := 0; i < len(set1); i++ {
m1.SetMapIndex(reflect.ValueOf(set1[i]), reflect.ValueOf(true))
}
for i := 0; i < len(set2); i++ {
x := m1.MapIndex(reflect.ValueOf(set2[i]))
if x.IsValid() {
if found := x; found.Bool() {
rv := reflect.ValueOf(set2[i])
set = reflect.Append(set, rv)
}
}
}
return set, nil
}
// GenericUnion returns a new set with elements from both
// the given sets a and b.
func GenericUnion(a, b interface{}) (reflect.Value, error) {
set := reflect.MakeSlice(reflect.TypeOf(a), 0, 0)
set1, err := interfaceToSlice(a)
if err != nil {
return set, errors.Wrap(err, "slice type is invalid")
}
set2, err := interfaceToSlice(b)
if err != nil {
return set, errors.Wrap(err, "slice type is invalid")
}
if len(set1) == 0 {
return reflect.ValueOf(set2), nil
}
if len(set2) == 0 {
return reflect.ValueOf(set1), nil
}
m := reflect.MapOf(reflect.TypeOf(set1[0]), reflect.TypeOf(true))
m1 := reflect.MakeMapWithSize(m, 0)
for i := 0; i < len(set1); i++ {
m1.SetMapIndex(reflect.ValueOf(set1[i]), reflect.ValueOf(true))
rv := reflect.ValueOf(set1[i])
set = reflect.Append(set, rv)
}
for i := 0; i < len(set2); i++ {
x := m1.MapIndex(reflect.ValueOf(set2[i]))
if x.IsValid() {
if found := x; !found.Bool() {
rv := reflect.ValueOf(set2[i])
set = reflect.Append(set, rv)
}
}
}
return set, nil
}
// GenericNot returns new set with elements which of a which are not in
// set b.
func GenericNot(a, b interface{}) (reflect.Value, error) {
set := reflect.MakeSlice(reflect.TypeOf(a), 0, 0)
set1, err := interfaceToSlice(a)
if err != nil {
return set, errors.Wrap(err, "slice type is invalid")
}
set2, err := interfaceToSlice(b)
if err != nil {
return set, errors.Wrap(err, "slice type is invalid")
}
if len(set1) == 0 {
return reflect.ValueOf(set2), nil
}
if len(set2) == 0 {
return reflect.ValueOf(set1), nil
}
m := reflect.MapOf(reflect.TypeOf(set1[0]), reflect.TypeOf(true))
m1 := reflect.MakeMapWithSize(m, 0)
for i := 0; i < len(set1); i++ {
m1.SetMapIndex(reflect.ValueOf(set1[i]), reflect.ValueOf(true))
}
for i := 0; i < len(set2); i++ {
x := m1.MapIndex(reflect.ValueOf(set2[i]))
if x.IsValid() {
if found := x; !found.Bool() {
rv := reflect.ValueOf(set2[i])
set = reflect.Append(set, rv)
}
}
}
return set, nil
}
// GenericIsIn returns true if a is in b and False otherwise.
func GenericIsIn(a, b interface{}) bool {
set1, err := interfaceToSlice(b)
if err == nil {
for _, v := range set1 {
if a == v {
return true
}
}
}
return false
}

View File

@@ -1,688 +0,0 @@
package sliceutil
import (
"reflect"
"testing"
"github.com/prysmaticlabs/go-ssz"
)
func TestGenericIntersection(t *testing.T) {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
result, err := GenericIntersection(tt.setA, tt.setB)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %d", result, tt.out)
}
}
}
}
func TestGenericIntersectionWithSSZ(t *testing.T) {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
b1, err := ssz.Marshal(tt.setA)
b2, err1 := ssz.Marshal(tt.setB)
if err1 == nil && err == nil {
result, err := GenericIntersection(b1, b2)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %d", result, tt.out)
}
}
}
}
}
func TestFloatGenericIntersection(t *testing.T) {
testCases := []struct {
setA []float32
setB []float32
out []float32
}{
{[]float32{2, 3, 5}, []float32{3}, []float32{3}},
{[]float32{2, 3, 5}, []float32{3, 5}, []float32{3, 5}},
{[]float32{2, 3, 5}, []float32{5, 3, 2}, []float32{5, 3, 2}},
{[]float32{2, 3, 5}, []float32{2, 3, 5}, []float32{2, 3, 5}},
{[]float32{2, 3, 5}, []float32{}, []float32{}},
{[]float32{}, []float32{2, 3, 5}, []float32{}},
{[]float32{}, []float32{}, []float32{}},
{[]float32{1}, []float32{1}, []float32{1}},
}
for _, tt := range testCases {
result, err := GenericIntersection(tt.setA, tt.setB)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %v", result, tt.out)
}
}
}
}
func TestStringGenericIntersection(t *testing.T) {
testCases := []struct {
setA []string
setB []string
out []string
}{
{[]string{"hello", "world"}, []string{"world"}, []string{"world"}},
{[]string{"hello"}, []string{"world"}, []string{}},
}
for _, tt := range testCases {
result, err := GenericIntersection(tt.setA, tt.setB)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %v", result, tt.out)
}
}
}
}
func TestIntGenericIntersection(t *testing.T) {
testCases := []struct {
setA []int32
setB []int32
out []int32
}{
{[]int32{2, 3, 5}, []int32{3}, []int32{3}},
{[]int32{2, 3, 5}, []int32{3, 5}, []int32{3, 5}},
{[]int32{2, 3, 5}, []int32{5, 3, 2}, []int32{5, 3, 2}},
{[]int32{2, 3, 5}, []int32{2, 3, 5}, []int32{2, 3, 5}},
{[]int32{2, 3, 5}, []int32{}, []int32{}},
{[]int32{}, []int32{2, 3, 5}, []int32{}},
{[]int32{}, []int32{}, []int32{}},
{[]int32{1}, []int32{1}, []int32{1}},
}
for _, tt := range testCases {
result, err := GenericIntersection(tt.setA, tt.setB)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %d", result, tt.out)
}
}
}
}
func TestGenericNot(t *testing.T) {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{4, 6}, []uint64{2, 3, 5, 4, 6}, []uint64{2, 3, 5}},
{[]uint64{3, 5}, []uint64{2, 3, 5}, []uint64{2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{2}, []uint64{2, 3, 5}, []uint64{3, 5}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{}},
}
for _, tt := range testCases {
result, err := GenericNot(tt.setA, tt.setB)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %d", result, tt.out)
}
}
}
}
func TestFloatGenericNot(t *testing.T) {
testCases := []struct {
setA []float32
setB []float32
out []float32
}{
{[]float32{4, 6}, []float32{2, 3, 5, 4, 6}, []float32{2, 3, 5}},
{[]float32{3, 5}, []float32{2, 3, 5}, []float32{2}},
{[]float32{2, 3, 5}, []float32{2, 3, 5}, []float32{}},
{[]float32{2}, []float32{2, 3, 5}, []float32{3, 5}},
{[]float32{}, []float32{2, 3, 5}, []float32{2, 3, 5}},
{[]float32{}, []float32{}, []float32{}},
{[]float32{1}, []float32{1}, []float32{}},
}
for _, tt := range testCases {
result, err := GenericNot(tt.setA, tt.setB)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %v", result, tt.out)
}
}
}
}
func TestStringGenericNot(t *testing.T) {
testCases := []struct {
setA []string
setB []string
out []string
}{
{[]string{"hello", "world"}, []string{"hello", "world", "its", "go"}, []string{"its", "go"}},
{[]string{}, []string{}, []string{}},
}
for _, tt := range testCases {
result, err := GenericNot(tt.setA, tt.setB)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %v", result, tt.out)
}
}
}
}
func TestIntGenericNot(t *testing.T) {
testCases := []struct {
setA []int32
setB []int32
out []int32
}{
{[]int32{4, 6}, []int32{2, 3, 5, 4, 6}, []int32{2, 3, 5}},
{[]int32{3, 5}, []int32{2, 3, 5}, []int32{2}},
{[]int32{2, 3, 5}, []int32{2, 3, 5}, []int32{}},
{[]int32{2}, []int32{2, 3, 5}, []int32{3, 5}},
{[]int32{}, []int32{2, 3, 5}, []int32{2, 3, 5}},
{[]int32{}, []int32{}, []int32{}},
{[]int32{1}, []int32{1}, []int32{}},
}
for _, tt := range testCases {
result, err := GenericNot(tt.setA, tt.setB)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %d", result, tt.out)
}
}
}
}
func TestGenericUnion(t *testing.T) {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{4, 6}, []uint64{2, 3, 5, 4, 6}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{2, 3, 5}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
result, err := GenericUnion(tt.setA, tt.setB)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %d", result, tt.out)
}
}
}
}
func TestFloatGenericUnion(t *testing.T) {
testCases := []struct {
setA []float32
setB []float32
out []float32
}{
{[]float32{2, 3, 5}, []float32{4, 6}, []float32{2, 3, 5, 4, 6}},
{[]float32{2, 3, 5}, []float32{4, 6}, []float32{2, 3, 5, 4, 6}},
{[]float32{2, 3, 5}, []float32{3, 5}, []float32{2, 3, 5}},
{[]float32{2, 3, 5}, []float32{2, 3, 5}, []float32{2, 3, 5}},
{[]float32{2, 3, 5}, []float32{}, []float32{2, 3, 5}},
{[]float32{}, []float32{2, 3, 5}, []float32{2, 3, 5}},
{[]float32{}, []float32{}, []float32{}},
{[]float32{1}, []float32{1}, []float32{1}},
}
for _, tt := range testCases {
result, err := GenericUnion(tt.setA, tt.setB)
if err != nil {
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("got %v, want %v", result, tt.out)
}
}
}
}
func TestGenericIsIn(t *testing.T) {
testCases := []struct {
a uint64
b []uint64
result bool
}{
{0, []uint64{}, false},
{0, []uint64{0}, true},
{4, []uint64{2, 3, 5, 4, 6}, true},
{100, []uint64{2, 3, 5, 4, 6}, false},
}
for _, tt := range testCases {
result := GenericIsIn(tt.a, tt.b)
if result != tt.result {
t.Errorf("IsIn(%d, %v)=%v, wanted: %v",
tt.a, tt.b, result, tt.result)
}
}
}
func BenchmarkGenericIntersection(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
res, err := GenericIntersection(tt.setA, tt.setB)
if err != nil {
b.Errorf("Benchmark error for %v", res)
}
}
}
}
func BenchmarkIntersection(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
IntersectionUint64(tt.setA, tt.setB)
}
}
}
func BenchmarkUnion(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
UnionUint64(tt.setA, tt.setB)
}
}
}
func BenchmarkGenericUnion(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
res, err := GenericUnion(tt.setA, tt.setB)
if err != nil {
b.Errorf("Benchmark error for %v", res)
}
}
}
}
func BenchmarkNot(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
NotUint64(tt.setA, tt.setB)
}
}
}
func BenchmarkGenericNot(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
res, err := GenericNot(tt.setA, tt.setB)
if err != nil {
b.Errorf("Benchmark error for %v", res)
}
}
}
}
func BenchmarkIsIn(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
a uint64
b []uint64
result bool
}{
{0, []uint64{}, false},
{0, []uint64{0}, true},
{4, []uint64{2, 3, 5, 4, 6}, true},
{100, []uint64{2, 3, 5, 4, 6}, false},
}
for _, tt := range testCases {
IsInUint64(tt.a, tt.b)
}
}
}
func BenchmarkGenericIsIn(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
a uint64
b []uint64
result bool
}{
{0, []uint64{}, false},
{0, []uint64{0}, true},
{4, []uint64{2, 3, 5, 4, 6}, true},
{100, []uint64{2, 3, 5, 4, 6}, false},
}
for _, tt := range testCases {
GenericIsIn(tt.a, tt.b)
}
}
}
func BenchmarkGenericIntersectionWithSSZ(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
b1, err := ssz.Marshal(tt.setA)
b2, err1 := ssz.Marshal(tt.setB)
if err1 == nil && err == nil {
res, err := GenericIntersection(b1, b2)
if err != nil {
b.Errorf("Benchmark error for %v", res)
}
}
}
}
}
func BenchmarkIntersectionWithSSZ(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
b1, err := ssz.Marshal(tt.setA)
b2, err1 := ssz.Marshal(tt.setB)
if err1 == nil && err == nil {
ByteIntersection(b1, b2)
}
}
}
}
func BenchmarkGenericUnionWithSSZ(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
b1, err := ssz.Marshal(tt.setA)
b2, err1 := ssz.Marshal(tt.setB)
if err1 == nil && err == nil {
res, err := GenericUnion(b1, b2)
if err != nil {
b.Errorf("Benchmark error for %v", res)
}
}
}
}
}
func BenchmarkUnionWithSSZ(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
b1, err := ssz.Marshal(tt.setA)
b2, err1 := ssz.Marshal(tt.setB)
if err1 == nil && err == nil {
ByteUnion(b1, b2)
}
}
}
}
func BenchmarkGenericNotWithSSZ(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
b1, err := ssz.Marshal(tt.setA)
b2, err1 := ssz.Marshal(tt.setB)
if err1 == nil && err == nil {
res, err := GenericNot(b1, b2)
if err != nil {
b.Errorf("Benchmark error for %v", res)
}
}
}
}
}
func BenchmarkNotWithSSZ(b *testing.B) {
for i := 0; i < b.N; i++ {
testCases := []struct {
setA []uint64
setB []uint64
out []uint64
}{
{[]uint64{2, 3, 5}, []uint64{3}, []uint64{3}},
{[]uint64{2, 3, 5}, []uint64{3, 5}, []uint64{3, 5}},
{[]uint64{2, 3, 5}, []uint64{5, 3, 2}, []uint64{5, 3, 2}},
{[]uint64{2, 3, 5}, []uint64{2, 3, 5}, []uint64{2, 3, 5}},
{[]uint64{2, 3, 5}, []uint64{}, []uint64{}},
{[]uint64{}, []uint64{2, 3, 5}, []uint64{}},
{[]uint64{}, []uint64{}, []uint64{}},
{[]uint64{1}, []uint64{1}, []uint64{1}},
}
for _, tt := range testCases {
b1, err := ssz.Marshal(tt.setA)
b2, err1 := ssz.Marshal(tt.setB)
if err1 == nil && err == nil {
ByteNot(b1, b2)
}
}
}
}

View File

@@ -225,3 +225,84 @@ func TestIsInInt64(t *testing.T) {
}
}
}
func TestIntersectionByteSlices(t *testing.T) {
testCases := []struct {
a [][]byte
b [][]byte
result [][]byte
}{
{[][]byte{{1, 2, 3}, {4, 5}}, [][]byte{{1, 2}, {4, 5}}, [][]byte{{4, 5}}},
// Ensure duplicate elements are moved in the resulting set.
{[][]byte{{1, 2, 3}, {4, 5}, {4, 5}}, [][]byte{{1, 2}, {4, 5}, {4, 5}}, [][]byte{{4, 5}}},
// Ensure no intersection returns an empty set.
{[][]byte{{1, 2, 3}, {4, 5}}, [][]byte{{1, 2}}, [][]byte{}},
// Intersection between A and A should return A.
{[][]byte{{1, 2}}, [][]byte{{1, 2}}, [][]byte{{1, 2}}},
}
for _, tt := range testCases {
result := IntersectionByteSlices(tt.a, tt.b)
if !reflect.DeepEqual(result, tt.result) {
t.Errorf("IntersectionByteSlices(%v, %v)=%v, wanted: %v",
tt.a, tt.b, result, tt.result)
}
}
}
func TestTotalIntersectionByteSlices(t *testing.T) {
testCases := []struct {
a [][][]byte
result [][]byte
}{
{
[][][]byte{
{
{1, 2, 3},
{4, 5},
},
{
{4, 5},
},
{
{4, 5},
{6, 7, 8},
{9, 10, 11},
},
},
[][]byte{
{4, 5},
},
},
{
[][][]byte{
{
{1, 2, 3},
{4, 5},
},
},
[][]byte{
{1, 2, 3},
{4, 5},
},
},
{
[][][]byte{
{
{1, 2, 3},
{4, 5},
},
{
{6},
},
},
[][]byte{},
},
}
for _, tt := range testCases {
result := TotalIntersectionByteSlices(tt.a)
if !reflect.DeepEqual(result, tt.result) {
t.Errorf("TotalIntersectionByteSlices(%v)=%v, wanted: %v",
tt.a, result, tt.result)
}
}
}