coredns/plugin/pkg/rand/rand_test.go
Ville Vesilehto 19a6ae4983
lint: enable intrange linter (#7331)
Enable intrange linter to enforce modern Go range syntax over
traditional for loops, by converting:

for i := 0; i < n; i++

to:

for i := range n

Adding type conversions where needed for compatibility
with existing uint64 parameters.

Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-05-28 17:50:55 -07:00

207 lines
3.4 KiB
Go

package rand
import (
"sync"
"testing"
"time"
)
func TestNew(t *testing.T) {
tests := []struct {
name string
seed int64
}{
{
name: "positive seed",
seed: 12345,
},
{
name: "zero seed",
seed: 0,
},
{
name: "negative seed",
seed: -12345,
},
{
name: "current time seed",
seed: time.Now().UnixNano(),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
r := New(test.seed)
if r.r == nil {
t.Error("internal rand.Rand is nil")
}
})
}
}
func TestIntDeterministic(t *testing.T) {
seed := int64(42)
// Create two generators with the same seed
r1 := New(seed)
r2 := New(seed)
// They should produce the same sequence
for i := range 10 {
val1 := r1.Int()
val2 := r2.Int()
if val1 != val2 {
t.Errorf("generators with same seed produced different values at iteration %d: %d != %d", i, val1, val2)
}
}
}
func TestPerm(t *testing.T) {
r := New(12345)
tests := []struct {
name string
n int
}{
{
name: "empty permutation",
n: 0,
},
{
name: "single element",
n: 1,
},
{
name: "small permutation",
n: 5,
},
{
name: "larger permutation",
n: 20,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
perm := r.Perm(test.n)
if len(perm) != test.n {
t.Errorf("Perm(%d) returned slice of length %d", test.n, len(perm))
}
})
}
}
func TestPermDeterministic(t *testing.T) {
seed := int64(42)
n := 10
// Create two generators with the same seed
r1 := New(seed)
r2 := New(seed)
perm1 := r1.Perm(n)
perm2 := r2.Perm(n)
// They should produce the same permutation
if len(perm1) != len(perm2) {
t.Errorf("permutations have different lengths: %d != %d", len(perm1), len(perm2))
}
for i := 0; i < len(perm1) && i < len(perm2); i++ {
if perm1[i] != perm2[i] {
t.Errorf("permutations differ at index %d: %d != %d", i, perm1[i], perm2[i])
}
}
}
func TestConcurrentAccess(t *testing.T) {
r := New(12345)
numGoroutines := 10
numOperations := 100
var wg sync.WaitGroup
errors := make(chan error, numGoroutines*numOperations)
// Test concurrent Int() calls
for range numGoroutines {
wg.Add(1)
go func() {
defer wg.Done()
for range numOperations {
val := r.Int()
if val < 0 {
errors <- nil
}
}
}()
}
// Test concurrent Perm() calls
for range numGoroutines {
wg.Add(1)
go func() {
defer wg.Done()
for range numOperations {
perm := r.Perm(5)
if len(perm) != 5 {
errors <- nil
}
}
}()
}
wg.Wait()
close(errors)
errorCount := 0
for range errors {
errorCount++
}
if errorCount > 0 {
t.Errorf("concurrent access resulted in %d errors", errorCount)
}
}
func TestConcurrentMixedOperations(t *testing.T) {
r := New(time.Now().UnixNano())
numGoroutines := 5
numOperations := 50
var wg sync.WaitGroup
errors := make(chan error, numGoroutines*numOperations)
// Mix of Int() and Perm() operations running concurrently
for i := range numGoroutines {
wg.Add(1)
go func(id int) {
defer wg.Done()
for j := range numOperations {
if j%2 == 0 {
val := r.Int()
if val < 0 {
errors <- nil
}
} else {
perm := r.Perm(3)
if len(perm) != 3 {
errors <- nil
}
}
}
}(i)
}
wg.Wait()
close(errors)
errorCount := 0
for range errors {
errorCount++
}
if errorCount > 0 {
t.Errorf("concurrent mixed operations resulted in %d errors", errorCount)
}
}