gcs/gcs_test: match zero element

This commit is contained in:
Conner Fromknecht 2019-04-24 17:04:27 -07:00 committed by Olaoluwa Osuntokun
parent 3ac1210f4b
commit 6f51807c27

View file

@ -88,6 +88,85 @@ func TestGCSFilterBuild(t *testing.T) {
} }
} }
// TestGCSMatchZeroHash ensures that Match and MatchAny properly match an item
// if it's hash after the reduction is zero. This is accomplished by brute
// forcing a specific target whose hash is zero given a certain (P, M, key,
// len(elements)) combination. In this case, P and M are the default, key was
// chosen randomly, and len(elements) is 13. The target 4-byte value of 16060032
// is the first such 32-bit value, thus we use the number 0-11 as the other
// elements in the filter since we know they won't collide. We test both the
// positive and negative cases, when the zero hash item is in the filter and
// when it is excluded. In the negative case, the 32-bit value of 12 is added to
// the filter instead of the target.
func TestGCSMatchZeroHash(t *testing.T) {
t.Run("include zero", func(t *testing.T) {
testGCSMatchZeroHash(t, true)
})
t.Run("exclude zero", func(t *testing.T) {
testGCSMatchZeroHash(t, false)
})
}
func testGCSMatchZeroHash(t *testing.T, includeZeroHash bool) {
key := [gcs.KeySize]byte{
0x25, 0x28, 0x0d, 0x25, 0x26, 0xe1, 0xd3, 0xc7,
0xa5, 0x71, 0x85, 0x34, 0x92, 0xa5, 0x7e, 0x68,
}
// Construct the target data to match, whose hash is zero after applying
// the reduction with the parameters in the test.
target := make([]byte, 4)
binary.BigEndian.PutUint32(target, 16060032)
// Construct the set of 13 items including the target, using the 32-bit
// values of 0 through 11 as the first 12 items. We known none of these
// hash to zero since the brute force ended well beyond them.
elements := make([][]byte, 0, 13)
for i := 0; i < 12; i++ {
data := make([]byte, 4)
binary.BigEndian.PutUint32(data, uint32(i))
elements = append(elements, data)
}
// If the filter should include the zero hash element, add the target
// which we know hashes to zero. Otherwise add 32-bit value of 12 which
// we know does not hash to zero.
if includeZeroHash {
elements = append(elements, target)
} else {
data := make([]byte, 4)
binary.BigEndian.PutUint32(data, 12)
elements = append(elements, data)
}
filter, err := gcs.BuildGCSFilter(P, M, key, elements)
if err != nil {
t.Fatalf("unable to build filter: %v", err)
}
match, err := filter.Match(key, target)
if err != nil {
t.Fatalf("unable to match: %v", err)
}
// We should only get a match iff the target was included.
if match != includeZeroHash {
t.Fatalf("expected match from Match: %t, got %t",
includeZeroHash, match)
}
match, err = filter.MatchAny(key, [][]byte{target})
if err != nil {
t.Fatalf("unable to match any: %v", err)
}
// We should only get a match iff the target was included.
if match != includeZeroHash {
t.Fatalf("expected match from MatchAny: %t, got %t",
includeZeroHash, match)
}
}
// TestGCSFilterCopy deserializes and serializes a filter to create a copy. // TestGCSFilterCopy deserializes and serializes a filter to create a copy.
func TestGCSFilterCopy(t *testing.T) { func TestGCSFilterCopy(t *testing.T) {
serialized2, err := filter.Bytes() serialized2, err := filter.Bytes()