Skip to content

Commit

Permalink
Add test to ensure that database packing produces sorted values (ava-…
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenButtolph authored May 31, 2023
1 parent e17a6ca commit d6004f2
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 5 deletions.
52 changes: 52 additions & 0 deletions database/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package database

import (
"math/rand"
"testing"
"time"

"github.com/stretchr/testify/require"

"golang.org/x/exp/slices"

"github.com/ava-labs/avalanchego/utils"
)

func TestSortednessUint64(t *testing.T) {
seed := time.Now().UnixNano()
t.Log("Seed: ", seed)
rand := rand.New(rand.NewSource(seed)) //#nosec G404

ints := make([]uint64, 1024)
for i := range ints {
ints[i] = rand.Uint64()
}
slices.Sort(ints)

intBytes := make([][]byte, 1024)
for i, val := range ints {
intBytes[i] = PackUInt64(val)
}
require.True(t, utils.IsSortedBytes(intBytes))
}

func TestSortednessUint32(t *testing.T) {
seed := time.Now().UnixNano()
t.Log("Seed: ", seed)
rand := rand.New(rand.NewSource(seed)) //#nosec G404

ints := make([]uint32, 1024)
for i := range ints {
ints[i] = rand.Uint32()
}
slices.Sort(ints)

intBytes := make([][]byte, 1024)
for i, val := range ints {
intBytes[i] = PackUInt32(val)
}
require.True(t, utils.IsSortedBytes(intBytes))
}
20 changes: 15 additions & 5 deletions utils/sorting.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,22 @@ func SortByHash[T ~[]byte](s []T) {
// Sorts a 2D byte slice.
// Each byte slice is not sorted internally; the byte slices are sorted relative
// to one another.
func SortBytes[T ~[]byte](arr []T) {
slices.SortFunc(arr, func(i, j T) bool {
func SortBytes[T ~[]byte](s []T) {
slices.SortFunc(s, func(i, j T) bool {
return bytes.Compare(i, j) == -1
})
}

// Returns true iff the elements in [s] are sorted.
func IsSortedBytes[T ~[]byte](s []T) bool {
for i := 0; i < len(s)-1; i++ {
if bytes.Compare(s[i], s[i+1]) == 1 {
return false
}
}
return true
}

// Returns true iff the elements in [s] are unique and sorted.
func IsSortedAndUniqueSortable[T Sortable[T]](s []T) bool {
for i := 0; i < len(s)-1; i++ {
Expand Down Expand Up @@ -82,10 +92,10 @@ func IsSortedAndUniqueByHash[T ~[]byte](s []T) bool {
}

// Returns true iff the elements in [s] are unique.
func IsUnique[T comparable](elts []T) bool {
func IsUnique[T comparable](s []T) bool {
// Can't use set.Set because it'd be a circular import.
asMap := make(map[T]struct{}, len(elts))
for _, elt := range elts {
asMap := make(map[T]struct{}, len(s))
for _, elt := range s {
if _, ok := asMap[elt]; ok {
return false
}
Expand Down
19 changes: 19 additions & 0 deletions utils/sorting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
package utils

import (
"math/rand"
"testing"
"time"

"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -57,6 +59,23 @@ func TestSortSliceSortable(t *testing.T) {
require.Equal([]sortable{1, 2, 3}, s)
}

func TestSortBytesIsSortedBytes(t *testing.T) {
require := require.New(t)

seed := time.Now().UnixNano()
t.Log("Seed: ", seed)
rand := rand.New(rand.NewSource(seed)) //#nosec G404

slices := make([][]byte, 1024)
for j := 0; j < len(slices); j++ {
slices[j] = make([]byte, 32)
_, _ = rand.Read(slices[j])
}
require.False(IsSortedBytes(slices))
SortBytes(slices)
require.True(IsSortedBytes(slices))
}

func TestIsSortedAndUniqueSortable(t *testing.T) {
require := require.New(t)

Expand Down

0 comments on commit d6004f2

Please sign in to comment.