зеркало из https://github.com/golang/tools.git
container/intsets: fix bug in UnionWith 'changed' result
This change corrects the computation of the 'changed' result of the x.UnionWith(y) method in the case where a block of y is a subset of the corresponding block of x. It also adds a test. I audited for similar problems and found none. Fixes golang/go#50352 Change-Id: I5224211a3cab06ce8986cdaa7b75c3b0531b3a9e Reviewed-on: https://go-review.googlesource.com/c/tools/+/374455 Trust: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Родитель
2c49d4f1ee
Коммит
ee1ca4ffc4
|
@ -666,8 +666,9 @@ func (s *Sparse) UnionWith(x *Sparse) bool {
|
|||
for xb != &none {
|
||||
if sb != &none && sb.offset == xb.offset {
|
||||
for i := range xb.bits {
|
||||
if sb.bits[i] != xb.bits[i] {
|
||||
sb.bits[i] |= xb.bits[i]
|
||||
union := sb.bits[i] | xb.bits[i]
|
||||
if sb.bits[i] != union {
|
||||
sb.bits[i] = union
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -460,6 +460,41 @@ func TestSetOperations(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestUnionWithChanged checks the 'changed' result of UnionWith.
|
||||
func TestUnionWithChanged(t *testing.T) {
|
||||
setOf := func(elems ...int) *intsets.Sparse {
|
||||
s := new(intsets.Sparse)
|
||||
for _, elem := range elems {
|
||||
s.Insert(elem)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
checkUnionWith := func(x, y *intsets.Sparse) {
|
||||
xstr := x.String()
|
||||
prelen := x.Len()
|
||||
changed := x.UnionWith(y)
|
||||
if (x.Len() > prelen) != changed {
|
||||
t.Errorf("%s.UnionWith(%s) => %s, changed=%t", xstr, y, x, changed)
|
||||
}
|
||||
}
|
||||
|
||||
// The case marked "!" is a regression test for Issue 50352,
|
||||
// which spuriously returned true when y ⊂ x.
|
||||
|
||||
// same block
|
||||
checkUnionWith(setOf(1, 2), setOf(1, 2))
|
||||
checkUnionWith(setOf(1, 2, 3), setOf(1, 2)) // !
|
||||
checkUnionWith(setOf(1, 2), setOf(1, 2, 3))
|
||||
checkUnionWith(setOf(1, 2), setOf())
|
||||
|
||||
// different blocks
|
||||
checkUnionWith(setOf(1, 1000000), setOf(1, 1000000))
|
||||
checkUnionWith(setOf(1, 2, 1000000), setOf(1, 2))
|
||||
checkUnionWith(setOf(1, 2), setOf(1, 2, 1000000))
|
||||
checkUnionWith(setOf(1, 1000000), setOf())
|
||||
}
|
||||
|
||||
func TestIntersectionWith(t *testing.T) {
|
||||
// Edge cases: the pairs (1,1), (1000,2000), (8000,4000)
|
||||
// exercise the <, >, == cases in IntersectionWith that the
|
||||
|
|
Загрузка…
Ссылка в новой задаче