d0888edc0a
Fix spelling of: above, already, anonymous, associated, authentication, bandwidth, because, between, blocks, calculate, candidates, cautious, changelog, cleaner, clipboard, command, completely, concurrently, considered, constructs, corrupt, current, daemon, dependencies, deprecated, directory, dispatcher, download, eligible, ellipsis, encrypter, endpoint, entrieslist, essentially, existing writers, existing, expires, filesystem, flushing, frequently, hierarchy, however, implementation, implements, inaccurate, individually, insensitive, longer, maximum, metadata, modified, multipart, namedirfirst, nextcloud, obscured, opened, optional, owncloud, pacific, passphrase, password, permanently, persimmon, positive, potato, protocol, quota, receiving, recommends, referring, requires, revisited, satisfied, satisfies, satisfy, semver, serialized, session, storage, strategies, stringlist, successful, supported, surprise, temporarily, temporary, transactions, unneeded, update, uploads, wrapped Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
146 lines
3.8 KiB
Go
146 lines
3.8 KiB
Go
// +build ignore
|
|
|
|
// Build a directory structure with the required number of files in
|
|
//
|
|
// Run with go run make_test_files.go [flag] <directory>
|
|
package main
|
|
|
|
import (
|
|
cryptrand "crypto/rand"
|
|
"flag"
|
|
"io"
|
|
"log"
|
|
"math/rand"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
var (
|
|
// Flags
|
|
numberOfFiles = flag.Int("n", 1000, "Number of files to create")
|
|
averageFilesPerDirectory = flag.Int("files-per-directory", 10, "Average number of files per directory")
|
|
maxDepth = flag.Int("max-depth", 10, "Maximum depth of directory hierarchy")
|
|
minFileSize = flag.Int64("min-size", 0, "Minimum size of file to create")
|
|
maxFileSize = flag.Int64("max-size", 100, "Maximum size of files to create")
|
|
minFileNameLength = flag.Int("min-name-length", 4, "Minimum size of file to create")
|
|
maxFileNameLength = flag.Int("max-name-length", 12, "Maximum size of files to create")
|
|
|
|
directoriesToCreate int
|
|
totalDirectories int
|
|
fileNames = map[string]struct{}{} // keep a note of which file name we've used already
|
|
)
|
|
|
|
// randomString create a random string for test purposes
|
|
func randomString(n int) string {
|
|
const (
|
|
vowel = "aeiou"
|
|
consonant = "bcdfghjklmnpqrstvwxyz"
|
|
digit = "0123456789"
|
|
)
|
|
pattern := []string{consonant, vowel, consonant, vowel, consonant, vowel, consonant, digit}
|
|
out := make([]byte, n)
|
|
p := 0
|
|
for i := range out {
|
|
source := pattern[p]
|
|
p = (p + 1) % len(pattern)
|
|
out[i] = source[rand.Intn(len(source))]
|
|
}
|
|
return string(out)
|
|
}
|
|
|
|
// fileName creates a unique random file or directory name
|
|
func fileName() (name string) {
|
|
for {
|
|
length := rand.Intn(*maxFileNameLength-*minFileNameLength) + *minFileNameLength
|
|
name = randomString(length)
|
|
if _, found := fileNames[name]; !found {
|
|
break
|
|
}
|
|
}
|
|
fileNames[name] = struct{}{}
|
|
return name
|
|
}
|
|
|
|
// dir is a directory in the directory hierarchy being built up
|
|
type dir struct {
|
|
name string
|
|
depth int
|
|
children []*dir
|
|
parent *dir
|
|
}
|
|
|
|
// Create a random directory hierarchy under d
|
|
func (d *dir) createDirectories() {
|
|
for totalDirectories < directoriesToCreate {
|
|
newDir := &dir{
|
|
name: fileName(),
|
|
depth: d.depth + 1,
|
|
parent: d,
|
|
}
|
|
d.children = append(d.children, newDir)
|
|
totalDirectories++
|
|
switch rand.Intn(4) {
|
|
case 0:
|
|
if d.depth < *maxDepth {
|
|
newDir.createDirectories()
|
|
}
|
|
case 1:
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// list the directory hierarchy
|
|
func (d *dir) list(path string, output []string) []string {
|
|
dirPath := filepath.Join(path, d.name)
|
|
output = append(output, dirPath)
|
|
for _, subDir := range d.children {
|
|
output = subDir.list(dirPath, output)
|
|
}
|
|
return output
|
|
}
|
|
|
|
// writeFile writes a random file at dir/name
|
|
func writeFile(dir, name string) {
|
|
err := os.MkdirAll(dir, 0777)
|
|
if err != nil {
|
|
log.Fatalf("Failed to make directory %q: %v", dir, err)
|
|
}
|
|
path := filepath.Join(dir, name)
|
|
fd, err := os.Create(path)
|
|
if err != nil {
|
|
log.Fatalf("Failed to open file %q: %v", path, err)
|
|
}
|
|
size := rand.Int63n(*maxFileSize-*minFileSize) + *minFileSize
|
|
_, err = io.CopyN(fd, cryptrand.Reader, size)
|
|
if err != nil {
|
|
log.Fatalf("Failed to write %v bytes to file %q: %v", size, path, err)
|
|
}
|
|
err = fd.Close()
|
|
if err != nil {
|
|
log.Fatalf("Failed to close file %q: %v", path, err)
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
args := flag.Args()
|
|
if len(args) != 1 {
|
|
log.Fatalf("Require 1 directory argument")
|
|
}
|
|
outputDirectory := args[0]
|
|
log.Printf("Output dir %q", outputDirectory)
|
|
|
|
directoriesToCreate = *numberOfFiles / *averageFilesPerDirectory
|
|
log.Printf("directoriesToCreate %v", directoriesToCreate)
|
|
root := &dir{name: outputDirectory, depth: 1}
|
|
for totalDirectories < directoriesToCreate {
|
|
root.createDirectories()
|
|
}
|
|
dirs := root.list("", []string{})
|
|
for i := 0; i < *numberOfFiles; i++ {
|
|
dir := dirs[rand.Intn(len(dirs))]
|
|
writeFile(dir, fileName())
|
|
}
|
|
}
|