Commit e44998bc authored by Jure Ham's avatar Jure Ham Committed by Andrew Gerrand

sort: fix for nondeterministic less function in quicksort pivot

Fixes #14377

Change-Id: I130a6e1b8bc827db44efd0a74e759b894ecc4977
Reviewed-on: https://go-review.googlesource.com/19823Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/22039
parent 002cf282
......@@ -119,15 +119,15 @@ func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
pivot := lo
a, c := lo+1, hi-1
for ; a != c && data.Less(a, pivot); a++ {
for ; a < c && data.Less(a, pivot); a++ {
}
b := a
for {
for ; b != c && !data.Less(pivot, b); b++ { // data[b] <= pivot
for ; b < c && !data.Less(pivot, b); b++ { // data[b] <= pivot
}
for ; b != c && data.Less(pivot, c-1); c-- { // data[c-1] > pivot
for ; b < c && data.Less(pivot, c-1); c-- { // data[c-1] > pivot
}
if b == c {
if b >= c {
break
}
// data[b] > pivot; data[c-1] <= pivot
......@@ -167,11 +167,11 @@ func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
// data[a <= i < b] unexamined
// data[b <= i < c] = pivot
for {
for ; a != b && !data.Less(b-1, pivot); b-- { // data[b] == pivot
for ; a < b && !data.Less(b-1, pivot); b-- { // data[b] == pivot
}
for ; a != b && data.Less(a, pivot); a++ { // data[a] < pivot
for ; a < b && data.Less(a, pivot); a++ { // data[a] < pivot
}
if a == b {
if a >= b {
break
}
// data[a] == pivot; data[b-1] < pivot
......
......@@ -109,6 +109,43 @@ func TestReverseSortIntSlice(t *testing.T) {
}
}
type nonDeterministicTestingData struct {
r *rand.Rand
}
func (t *nonDeterministicTestingData) Len() int {
return 500
}
func (t *nonDeterministicTestingData) Less(i, j int) bool {
if i < 0 || j < 0 || i >= t.Len() || j >= t.Len() {
panic("nondeterministic comparison out of bounds")
}
return t.r.Float32() < 0.5
}
func (t *nonDeterministicTestingData) Swap(i, j int) {
if i < 0 || j < 0 || i >= t.Len() || j >= t.Len() {
panic("nondeterministic comparison out of bounds")
}
}
func TestNonDeterministicComparison(t *testing.T) {
// Ensure that sort.Sort does not panic when Less returns inconsistent results.
// See https://golang.org/issue/14377.
defer func() {
if r := recover(); r != nil {
t.Error(r)
}
}()
td := &nonDeterministicTestingData{
r: rand.New(rand.NewSource(0)),
}
for i := 0; i < 10; i++ {
Sort(td)
}
}
func BenchmarkSortString1K(b *testing.B) {
b.StopTimer()
for i := 0; i < b.N; i++ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment