apg-go/random_test.go
Winni Neessen 45b45919c1
Add TestGetCharRangeFromConfig function in random_test.go
A comprehensive unit test, TestGetCharRangeFromConfig, has been added to the random_test.go file. This test validates the GetCharRangeFromConfig function across various scenarios and configurations. It also improves code reliability and makes the application more robust against potential issues.
2024-03-12 12:14:36 +01:00

251 lines
6.1 KiB
Go

package apg
import (
"bytes"
"strings"
"testing"
)
func TestGenerator_CoinFlip(t *testing.T) {
g := New(NewConfig())
cf := g.CoinFlip()
if cf < 0 || cf > 1 {
t.Errorf("CoinFlip failed(), expected 0 or 1, got: %d", cf)
}
}
func TestGenerator_CoinFlipBool(t *testing.T) {
g := New(NewConfig())
gt := false
for i := 0; i < 500_000; i++ {
cf := g.CoinFlipBool()
if cf {
gt = true
break
}
}
if !gt {
t.Error("CoinFlipBool likely not working, expected at least one true value in 500k tries, got none")
}
}
func TestGenerator_RandNum(t *testing.T) {
tt := []struct {
name string
v int64
max int64
min int64
sf bool
}{
{"RandNum up to 1000", 1000, 1000, 0, false},
{"RandNum should be 1", 1, 1, 0, false},
{"RandNum should fail on 1", 0, 0, 0, true},
{"RandNum should fail on negative", -1, 0, 0, true},
}
g := New(NewConfig())
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
rn, err := g.RandNum(tc.v)
if err == nil && tc.sf {
t.Errorf("random number generation was supposed to fail, but didn't, got: %d", rn)
}
if err != nil && !tc.sf {
t.Errorf("random number generation failed: %s", err)
}
if rn > tc.max {
t.Errorf("random number generation returned too big number expected below: %d, got: %d",
tc.max, rn)
}
if rn < tc.min {
t.Errorf("random number generation returned too small number, expected min: %d, got: %d",
tc.min, rn)
}
})
}
}
func TestGenerator_RandomBytes(t *testing.T) {
tt := []struct {
name string
l int64
sf bool
}{
{"1 bytes of randomness", 1, false},
{"100 bytes of randomness", 100, false},
{"1024 bytes of randomness", 1024, false},
{"4096 bytes of randomness", 4096, false},
{"-1 bytes of randomness", -1, true},
}
g := New(NewConfig())
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
rb, err := g.RandomBytes(tc.l)
if err != nil && !tc.sf {
t.Errorf("random byte generation failed: %s", err)
return
}
if tc.sf {
return
}
bl := len(rb)
if int64(bl) != tc.l {
t.Errorf("lenght of provided bytes does not match requested length: got: %d, expected: %d",
bl, tc.l)
}
if bytes.Equal(rb, make([]byte, tc.l)) {
t.Errorf("random byte generation failed. returned slice is empty")
}
})
}
}
func TestGenerator_RandomString(t *testing.T) {
g := New(NewConfig())
var l int64 = 32 * 1024
tt := []struct {
name string
cr string
nr string
sf bool
}{
{
"CharRange:AlphaLower", CharRangeAlphaLower,
CharRangeAlphaUpper + CharRangeNumeric + CharRangeSpecial, false,
},
{
"CharRange:AlphaUpper", CharRangeAlphaUpper,
CharRangeAlphaLower + CharRangeNumeric + CharRangeSpecial, false,
},
{
"CharRange:Number", CharRangeNumeric,
CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeSpecial, false,
},
{
"CharRange:Special", CharRangeSpecial,
CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeNumeric, false,
},
{
"CharRange:Invalid", "",
CharRangeAlphaLower + CharRangeAlphaUpper + CharRangeNumeric + CharRangeSpecial, true,
},
}
for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
rs, err := g.RandomStringFromCharRange(l, tc.cr)
if err != nil && !tc.sf {
t.Errorf("RandomStringFromCharRange failed: %s", err)
}
if int64(len(rs)) != l && !tc.sf {
t.Errorf("RandomStringFromCharRange failed. Expected length: %d, got: %d", l, len(rs))
}
if strings.ContainsAny(rs, tc.nr) {
t.Errorf("RandomStringFromCharRange failed. Unexpected character found in returned string: %s", rs)
}
})
}
}
func TestGetCharRangeFromConfig(t *testing.T) {
// Arrange
config := NewConfig()
generator := New(config)
// Test cases
testCases := []struct {
Name string
ConfigMode ModeMask
ExpectedRange string
}{
{
Name: "LowerCaseHumanReadable",
ConfigMode: ModeLowerCase | ModeHumanReadable,
ExpectedRange: CharRangeAlphaLowerHuman,
},
{
Name: "LowerCaseNonHumanReadable",
ConfigMode: ModeLowerCase,
ExpectedRange: CharRangeAlphaLower,
},
{
Name: "NumericHumanReadable",
ConfigMode: ModeNumeric | ModeHumanReadable,
ExpectedRange: CharRangeNumericHuman,
},
{
Name: "NumericNonHumanReadable",
ConfigMode: ModeNumeric,
ExpectedRange: CharRangeNumeric,
},
{
Name: "SpecialHumanReadable",
ConfigMode: ModeSpecial | ModeHumanReadable,
ExpectedRange: CharRangeSpecialHuman,
},
{
Name: "SpecialNonHumanReadable",
ConfigMode: ModeSpecial,
ExpectedRange: CharRangeSpecial,
},
{
Name: "UpperCaseHumanReadable",
ConfigMode: ModeUpperCase | ModeHumanReadable,
ExpectedRange: CharRangeAlphaUpperHuman,
},
{
Name: "UpperCaseNonHumanReadable",
ConfigMode: ModeUpperCase,
ExpectedRange: CharRangeAlphaUpper,
},
{
Name: "MultipleModes",
ConfigMode: ModeLowerCase | ModeNumeric | ModeUpperCase | ModeHumanReadable,
ExpectedRange: CharRangeAlphaLowerHuman + CharRangeNumericHuman + CharRangeAlphaUpperHuman,
},
}
// Act and assert for each test case
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
generator.config.Mode = tc.ConfigMode
actualRange := generator.GetCharRangeFromConfig()
if actualRange != tc.ExpectedRange {
t.Errorf("Expected range %s, got %s", tc.ExpectedRange, actualRange)
}
})
}
}
func BenchmarkGenerator_CoinFlip(b *testing.B) {
b.ReportAllocs()
g := New(NewConfig())
for i := 0; i < b.N; i++ {
_ = g.CoinFlip()
}
}
func BenchmarkGenerator_RandomBytes(b *testing.B) {
b.ReportAllocs()
g := New(NewConfig())
var l int64 = 1024
for i := 0; i < b.N; i++ {
_, err := g.RandomBytes(l)
if err != nil {
b.Errorf("failed to generate random bytes: %s", err)
return
}
}
}
func BenchmarkGenerator_RandomString(b *testing.B) {
b.ReportAllocs()
g := New(NewConfig())
cr := CharRangeAlphaUpper + CharRangeAlphaLower + CharRangeNumeric + CharRangeSpecial
for i := 0; i < b.N; i++ {
_, err := g.RandomStringFromCharRange(32, cr)
if err != nil {
b.Errorf("RandomStringFromCharRange() failed: %s", err)
}
}
}