func TestGetCharRange(t *testing.T) {
	lowerCaseBytes := []int{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
		's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
	lowerCaseHumanBytes := []int{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r',
		's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
	upperCaseBytes := []int{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
		'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
	upperCaseHumanBytes := []int{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q',
		'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
	numberBytes := []int{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
	numberHumanBytes := []int{'2', '3', '4', '5', '6', '7', '8', '9'}
	specialBytes := []int{'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':',
		';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~'}
	specialHumanBytes := []int{'"', '#', '%', '*', '+', '-', '/', ':', ';', '=', '\\', '_', '|', '~'}
	testTable := []struct {
		testName      string
		allowedBytes  []int
		useLowerCase  bool
		useUpperCase  bool
		useNumber     bool
		useSpecial    bool
		humanReadable bool
	}{
		{"lowercase_only", lowerCaseBytes, true, false, false, false, false},
		{"lowercase_only_human", lowerCaseHumanBytes, true, false, false, false, true},
		{"uppercase_only", upperCaseBytes, false, true, false, false, false},
		{"uppercase_only_human", upperCaseHumanBytes, false, true, false, false, true},
		{"number_only", numberBytes, false, false, true, false, false},
		{"number_only_human", numberHumanBytes, false, false, true, false, true},
		{"special_only", specialBytes, false, false, false, true, false},
		{"special_only_human", specialHumanBytes, false, false, false, true, true},
	}
	for _, testCase := range testTable {
		t.Run(testCase.testName, func(t *testing.T) {
			cfgObj.UseLowerCase = testCase.useLowerCase
			cfgObj.UseUpperCase = testCase.useUpperCase
			cfgObj.UseNumber = testCase.useNumber
			cfgObj.UseSpecial = testCase.useSpecial
			cfgObj.HumanReadable = testCase.humanReadable
			charRange := chars.GetRange(&cfgObj)
			for _, curChar := range charRange {
				searchAllowedBytes := containsByte(testCase.allowedBytes, int(curChar), t)
				if !searchAllowedBytes {
					t.Errorf("Character range returned invalid value: %v", string(curChar))
				}
			}
		})
	}
}
Test getCharRange() with different cfgObj settings
package main
import (
	"github.com/wneessen/apg-go/chars"
	"github.com/wneessen/apg-go/config"
	"github.com/wneessen/apg-go/random"
	"github.com/wneessen/apg-go/spelling"
	"testing"
)
var cfgObj config.Config
var _ = func() bool {
	testing.Init()
	cfgObj = config.New()
	return true
}()
func TestGetRandNum(t *testing.T) {
	testTable := []struct {
		testName   string
		givenVal   int
		maxRet     int
		minRet     int
		shouldFail bool
	}{
		{"randNum up to 1000", 1000, 1000, 0, false},
		{"randNum should be 1", 1, 1, 0, false},
		{"randNum should fail on 0", 0, 0, 0, true},
		{"randNum should fail on negative", -1, 0, 0, true},
	}
	for _, testCase := range testTable {
		t.Run(testCase.testName, func(t *testing.T) {
			randNum, err := random.GetNum(testCase.givenVal)
			if testCase.shouldFail {
				if err == nil {
					t.Errorf("Random number generation succeeded but was expected to fail. Given: %v, returned: %v",
						testCase.givenVal, randNum)
				}
			} else {
				if err != nil {
					t.Errorf("Random number generation failed: %v", err.Error())
				}
				if randNum > testCase.maxRet {
					t.Errorf("Random number generation returned too big value. Given %v, expected max: %v, got: %v",
						testCase.givenVal, testCase.maxRet, randNum)
				}
				if randNum < testCase.minRet {
					t.Errorf("Random number generation returned too small value. Given %v, expected max: %v, got: %v",
						testCase.givenVal, testCase.minRet, randNum)
				}
			}
		})
	}
}
func TestGenLength(t *testing.T) {
	testTable := []struct {
		testName  string
		minLength int
		maxLength int
	}{
		{"pwLength defaults", config.DefaultMinLength, config.DefaultMaxLength},
		{"pwLength 0 to 1", 0, 1},
		{"pwLength 1 to 10", 0, 10},
		{"pwLength 10 to 100", 10, 100},
	}
	charRange := chars.GetRange(&cfgObj)
	for _, testCase := range testTable {
		t.Run(testCase.testName, func(t *testing.T) {
			cfgObj.MinPassLen = testCase.minLength
			cfgObj.MaxPassLen = testCase.maxLength
			pwLength := config.GetPwLengthFromParams(&cfgObj)
			for i := 0; i < 1000; i++ {
				pwString, err := random.GetChar(charRange, pwLength)
				if err != nil {
					t.Errorf("getRandChar returned an error: %q", err)
				}
				retLen := len(pwString)
				if retLen > testCase.maxLength {
					t.Errorf("Generated password length too long. GivenMin %v, GivenMax: %v, Returned length %v",
						testCase.minLength, testCase.maxLength, retLen)
				}
				if retLen < testCase.minLength {
					t.Errorf("Generated password length too short. GivenMin %v, GivenMax: %v, Returned length %v",
						testCase.minLength, testCase.maxLength, retLen)
				}
			}
		})
	}
}
func TestGetRandChar(t *testing.T) {
	t.Run("return_value_is_A_B_or_C", func(t *testing.T) {
		charRange := "ABC"
		randChar, err := random.GetChar(charRange, 1)
		if err != nil {
			t.Fatalf("Random character generation failed => %v", err.Error())
		}
		if randChar != "A" && randChar != "B" && randChar != "C" {
			t.Fatalf("Random character generation failed. Expected A, B or C but got: %v", randChar)
		}
	})
	t.Run("return_value_has_specific_length", func(t *testing.T) {
		charRange := "ABC"
		randChar, err := random.GetChar(charRange, 1000)
		if err != nil {
			t.Fatalf("Random character generation failed => %v", err.Error())
		}
		if len(randChar) != 1000 {
			t.Fatalf("Generated random characters with 1000 chars returned wrong amount of chars: %v",
				len(randChar))
		}
	})
	t.Run("fail", func(t *testing.T) {
		charRange := "ABC"
		randChar, err := random.GetChar(charRange, -2000)
		if err == nil {
			t.Fatalf("Generated random characters expected to fail, but returned a value => %v",
				randChar)
		}
	})
}