Add IterateSocketMasks() function to socketmask abstraction

This commit is contained in:
Kevin Klues 2019-08-13 17:54:21 +02:00
parent e33af11add
commit 9a6788cb13
2 changed files with 71 additions and 0 deletions

View File

@ -185,3 +185,23 @@ func Or(first SocketMask, masks ...SocketMask) SocketMask {
s.Or(masks...)
return &s
}
// IterateSocketMasks iterates all possible masks from a list of sockets,
// issuing a callback on each mask.
func IterateSocketMasks(sockets []int, callback func(SocketMask)) {
var iterate func(sockets, accum []int, size int)
iterate = func(sockets, accum []int, size int) {
if len(accum) == size {
mask, _ := NewSocketMask(accum...)
callback(mask)
return
}
for i := range sockets {
iterate(sockets[i+1:], append(accum, sockets[i]), size)
}
}
for i := 1; i <= len(sockets); i++ {
iterate(sockets, []int{}, i)
}
}

View File

@ -342,3 +342,54 @@ func TestIsNarrowerThan(t *testing.T) {
}
}
}
func TestIterateSocketMasks(t *testing.T) {
tcases := []struct {
name string
numSockets int
}{
{
name: "1 Socket",
numSockets: 1,
},
{
name: "2 Sockets",
numSockets: 2,
},
{
name: "4 Sockets",
numSockets: 4,
},
{
name: "8 Sockets",
numSockets: 8,
},
{
name: "16 Sockets",
numSockets: 16,
},
}
for _, tc := range tcases {
// Generate a list of sockets from tc.numSockets.
var sockets []int
for i := 0; i < tc.numSockets; i++ {
sockets = append(sockets, i)
}
// Calculate the expected number of masks. Since we always have masks
// with sockets from 0..n, this is just (2^n - 1) since we want 1 mask
// represented by each integer between 1 and 2^n-1.
expectedNumMasks := (1 << uint(tc.numSockets)) - 1
// Iterate all masks and count them.
numMasks := 0
IterateSocketMasks(sockets, func(SocketMask) {
numMasks++
})
// Compare the number of masks generated to the expected amount.
if expectedNumMasks != numMasks {
t.Errorf("Expected to iterate %v masks, got %v", expectedNumMasks, numMasks)
}
}
}