test makefiles: add --seed flag and make data generated repeatable #5214

This commit is contained in:
Nick Craig-Wood 2021-04-10 13:42:17 +01:00
parent 813bf029d4
commit 60dcafe04d
2 changed files with 26 additions and 10 deletions

View file

@ -3,12 +3,12 @@
package makefiles package makefiles
import ( import (
cryptrand "crypto/rand"
"io" "io"
"log" "log"
"math/rand" "math/rand"
"os" "os"
"path/filepath" "path/filepath"
"time"
"github.com/rclone/rclone/cmd" "github.com/rclone/rclone/cmd"
"github.com/rclone/rclone/cmd/test" "github.com/rclone/rclone/cmd/test"
@ -27,8 +27,10 @@ var (
maxFileSize = fs.SizeSuffix(100) maxFileSize = fs.SizeSuffix(100)
minFileNameLength = 4 minFileNameLength = 4
maxFileNameLength = 12 maxFileNameLength = 12
seed = int64(1)
// Globals // Globals
randSource *rand.Rand
directoriesToCreate int directoriesToCreate int
totalDirectories int totalDirectories int
fileNames = map[string]struct{}{} // keep a note of which file name we've used already fileNames = map[string]struct{}{} // keep a note of which file name we've used already
@ -44,6 +46,7 @@ func init() {
flags.FVarP(cmdFlags, &maxFileSize, "max-file-size", "", "Maximum size of files to create") flags.FVarP(cmdFlags, &maxFileSize, "max-file-size", "", "Maximum size of files to create")
flags.IntVarP(cmdFlags, &minFileNameLength, "min-name-length", "", minFileNameLength, "Minimum size of file names") flags.IntVarP(cmdFlags, &minFileNameLength, "min-name-length", "", minFileNameLength, "Minimum size of file names")
flags.IntVarP(cmdFlags, &maxFileNameLength, "max-name-length", "", maxFileNameLength, "Maximum size of file names") flags.IntVarP(cmdFlags, &maxFileNameLength, "max-name-length", "", maxFileNameLength, "Maximum size of file names")
flags.Int64VarP(cmdFlags, &seed, "seed", "", seed, "Seed for the random number generator (0 for random)")
} }
var commandDefinition = &cobra.Command{ var commandDefinition = &cobra.Command{
@ -51,6 +54,11 @@ var commandDefinition = &cobra.Command{
Short: `Make a random file hierarchy in <dir>`, Short: `Make a random file hierarchy in <dir>`,
Run: func(command *cobra.Command, args []string) { Run: func(command *cobra.Command, args []string) {
cmd.CheckArgs(1, 1, command, args) cmd.CheckArgs(1, 1, command, args)
if seed == 0 {
seed = time.Now().UnixNano()
log.Printf("Using random seed = %d", seed)
}
randSource = rand.New(rand.NewSource(seed))
outputDirectory := args[0] outputDirectory := args[0]
directoriesToCreate = numberOfFiles / averageFilesPerDirectory directoriesToCreate = numberOfFiles / averageFilesPerDirectory
averageSize := (minFileSize + maxFileSize) / 2 averageSize := (minFileSize + maxFileSize) / 2
@ -61,7 +69,7 @@ var commandDefinition = &cobra.Command{
} }
dirs := root.list("", []string{}) dirs := root.list("", []string{})
for i := 0; i < numberOfFiles; i++ { for i := 0; i < numberOfFiles; i++ {
dir := dirs[rand.Intn(len(dirs))] dir := dirs[randSource.Intn(len(dirs))]
writeFile(dir, fileName()) writeFile(dir, fileName())
} }
log.Printf("Done.") log.Printf("Done.")
@ -71,8 +79,8 @@ var commandDefinition = &cobra.Command{
// fileName creates a unique random file or directory name // fileName creates a unique random file or directory name
func fileName() (name string) { func fileName() (name string) {
for { for {
length := rand.Intn(maxFileNameLength-minFileNameLength) + minFileNameLength length := randSource.Intn(maxFileNameLength-minFileNameLength) + minFileNameLength
name = random.String(length) name = random.StringFn(length, randSource.Intn)
if _, found := fileNames[name]; !found { if _, found := fileNames[name]; !found {
break break
} }
@ -99,7 +107,7 @@ func (d *dir) createDirectories() {
} }
d.children = append(d.children, newDir) d.children = append(d.children, newDir)
totalDirectories++ totalDirectories++
switch rand.Intn(4) { switch randSource.Intn(4) {
case 0: case 0:
if d.depth < maxDepth { if d.depth < maxDepth {
newDir.createDirectories() newDir.createDirectories()
@ -132,8 +140,8 @@ func writeFile(dir, name string) {
if err != nil { if err != nil {
log.Fatalf("Failed to open file %q: %v", path, err) log.Fatalf("Failed to open file %q: %v", path, err)
} }
size := rand.Int63n(int64(maxFileSize-minFileSize)) + int64(minFileSize) size := randSource.Int63n(int64(maxFileSize-minFileSize)) + int64(minFileSize)
_, err = io.CopyN(fd, cryptrand.Reader, size) _, err = io.CopyN(fd, randSource, size)
if err != nil { if err != nil {
log.Fatalf("Failed to write %v bytes to file %q: %v", size, path, err) log.Fatalf("Failed to write %v bytes to file %q: %v", size, path, err)
} }

View file

@ -10,10 +10,11 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// String create a random string for test purposes. // StringFn create a random string for test purposes using the random
// number generator function passed in.
// //
// Do not use these for passwords. // Do not use these for passwords.
func String(n int) string { func StringFn(n int, randIntn func(n int) int) string {
const ( const (
vowel = "aeiou" vowel = "aeiou"
consonant = "bcdfghjklmnpqrstvwxyz" consonant = "bcdfghjklmnpqrstvwxyz"
@ -25,11 +26,18 @@ func String(n int) string {
for i := range out { for i := range out {
source := pattern[p] source := pattern[p]
p = (p + 1) % len(pattern) p = (p + 1) % len(pattern)
out[i] = source[mathrand.Intn(len(source))] out[i] = source[randIntn(len(source))]
} }
return string(out) return string(out)
} }
// String create a random string for test purposes.
//
// Do not use these for passwords.
func String(n int) string {
return StringFn(n, mathrand.Intn)
}
// Password creates a crypto strong password which is just about // Password creates a crypto strong password which is just about
// memorable. The password is composed of printable ASCII characters // memorable. The password is composed of printable ASCII characters
// from the base64 alphabet. // from the base64 alphabet.