lib/random: unify random string generation into random.String

This was factored from fstest as we were including the testing
enviroment into the main binary because of it.

This was causing opening the browser to fail because of 8243ff8bc8.
s3-about
Nick Craig-Wood 2019-08-06 12:44:08 +01:00
parent 72d5b11d1b
commit 5065c422b4
12 changed files with 63 additions and 65 deletions

View File

@ -33,6 +33,7 @@ import (
"github.com/rclone/rclone/fs/object"
"github.com/rclone/rclone/fs/rc"
"github.com/rclone/rclone/fstest"
"github.com/rclone/rclone/lib/random"
"github.com/rclone/rclone/vfs"
"github.com/rclone/rclone/vfs/vfsflags"
"github.com/stretchr/testify/assert"
@ -355,8 +356,8 @@ func TestInternalCachedUpdatedContentMatches(t *testing.T) {
testData2, err = base64.StdEncoding.DecodeString(cryptedText2Base64)
require.NoError(t, err)
} else {
testData1 = []byte(fstest.RandomString(100))
testData2 = []byte(fstest.RandomString(200))
testData1 = []byte(random.String(100))
testData2 = []byte(random.String(200))
}
// write the object

View File

@ -13,6 +13,7 @@ import (
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/hash"
"github.com/rclone/rclone/fstest"
"github.com/rclone/rclone/lib/random"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -55,7 +56,7 @@ func TestIntegration(t *testing.T) {
require.NoError(t, err)
t.Run("CreateAlbum", func(t *testing.T) {
albumName := "album/rclone-test-" + fstest.RandomString(24)
albumName := "album/rclone-test-" + random.String(24)
err = f.Mkdir(ctx, albumName)
require.NoError(t, err)
remote := albumName + "/" + fileNameAlbum

View File

@ -9,6 +9,7 @@ package cmd
import (
"fmt"
"log"
"math/rand"
"os"
"os/exec"
"path"
@ -492,6 +493,7 @@ func AddBackendFlags() {
// Main runs rclone interpreting flags and commands out of os.Args
func Main() {
rand.Seed(time.Now().Unix())
setupRootCommand(Root)
AddBackendFlags()
if err := Root.Execute(); err != nil {

View File

@ -18,7 +18,7 @@ import (
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/hash"
"github.com/rclone/rclone/fs/object"
"github.com/rclone/rclone/fstest"
"github.com/rclone/rclone/lib/random"
"github.com/spf13/cobra"
)
@ -118,7 +118,7 @@ func (r *results) Print() {
// writeFile writes a file with some random contents
func (r *results) writeFile(path string) (fs.Object, error) {
contents := fstest.RandomString(50)
contents := random.String(50)
src := object.NewStaticObjectInfo(path, time.Now(), int64(len(contents)), true, nil, r.f)
return r.f.Put(r.ctx, bytes.NewBufferString(contents), src)
}

View File

@ -6,6 +6,7 @@ import (
"testing"
"github.com/rclone/rclone/fs/accounting"
"github.com/rclone/rclone/lib/random"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fstest"
@ -52,7 +53,7 @@ func TestMultithreadCopy(t *testing.T) {
} {
t.Run(fmt.Sprintf("%+v", test), func(t *testing.T) {
var err error
contents := fstest.RandomString(test.size)
contents := random.String(test.size)
t1 := fstest.Time("2001-02-03T04:05:06.499999999Z")
file1 := r.WriteObject(context.Background(), "file1", contents, t1)
fstest.CheckItems(t, r.Fremote, file1)

View File

@ -8,7 +8,6 @@ import (
"fmt"
"io"
"io/ioutil"
"math/rand"
"path"
"path/filepath"
"sort"
@ -28,6 +27,7 @@ import (
"github.com/rclone/rclone/fs/march"
"github.com/rclone/rclone/fs/object"
"github.com/rclone/rclone/fs/walk"
"github.com/rclone/rclone/lib/random"
"github.com/rclone/rclone/lib/readers"
"golang.org/x/sync/errgroup"
)
@ -1666,7 +1666,7 @@ func moveOrCopyFile(ctx context.Context, fdst fs.Fs, fsrc fs.Fs, dstFileName str
// to avoid issues with certain remotes and avoid file deletion.
if !cp && fdst.Name() == fsrc.Name() && fdst.Features().CaseInsensitive && dstFileName != srcFileName && strings.ToLower(dstFilePath) == strings.ToLower(srcFilePath) {
// Create random name to temporarily move file to
tmpObjName := dstFileName + "-rclone-move-" + random(8)
tmpObjName := dstFileName + "-rclone-move-" + random.String(8)
_, err := fdst.NewObject(ctx, tmpObjName)
if err != fs.ErrorObjectNotFound {
if err == nil {
@ -1730,17 +1730,6 @@ func moveOrCopyFile(ctx context.Context, fdst fs.Fs, fsrc fs.Fs, dstFileName str
return err
}
// random generates a pseudorandom alphanumeric string
func random(length int) string {
randomOutput := make([]byte, length)
possibleCharacters := "123567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
rand.Seed(time.Now().Unix())
for i := range randomOutput {
randomOutput[i] = possibleCharacters[rand.Intn(len(possibleCharacters))]
}
return string(randomOutput)
}
// MoveFile moves a single file possibly to a new name
func MoveFile(ctx context.Context, fdst fs.Fs, fsrc fs.Fs, dstFileName string, srcFileName string) (err error) {
return moveOrCopyFile(ctx, fdst, fsrc, dstFileName, srcFileName, false)

View File

@ -95,6 +95,8 @@ func (s *Server) Serve() error {
// Don't open browser if serving in testing environment.
if flag.Lookup("test.v") == nil {
_ = open.Start(openURL.String())
} else {
fs.Errorf(nil, "Not opening browser in testing environment")
}
}
return nil

View File

@ -27,6 +27,7 @@ import (
"github.com/rclone/rclone/fs/config"
"github.com/rclone/rclone/fs/hash"
"github.com/rclone/rclone/fs/walk"
"github.com/rclone/rclone/lib/random"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/text/unicode/norm"
@ -357,24 +358,6 @@ func Time(timeString string) time.Time {
return t
}
// 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)
}
// LocalRemote creates a temporary directory name for local remotes
func LocalRemote() (path string, err error) {
path, err = ioutil.TempDir("", "rclone")
@ -403,7 +386,7 @@ func RandomRemoteName(remoteName string) (string, string, error) {
if !strings.HasSuffix(remoteName, ":") {
remoteName += "/"
}
leafName = "rclone-test-" + RandomString(24)
leafName = "rclone-test-" + random.String(24)
if !MatchTestRemote.MatchString(leafName) {
log.Fatalf("%q didn't match the test remote name regexp", leafName)
}
@ -432,7 +415,7 @@ func RandomRemote(remoteName string, subdir bool) (fs.Fs, string, func(), error)
if err != nil {
return nil, "", nil, err
}
remoteName += "/rclone-test-subdir-" + RandomString(8)
remoteName += "/rclone-test-subdir-" + random.String(8)
}
remote, err := fs.NewFs(remoteName)

View File

@ -31,6 +31,7 @@ import (
"github.com/rclone/rclone/fs/operations"
"github.com/rclone/rclone/fs/walk"
"github.com/rclone/rclone/fstest"
"github.com/rclone/rclone/lib/random"
"github.com/rclone/rclone/lib/readers"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -157,7 +158,7 @@ func testPut(t *testing.T, f fs.Fs, file *fstest.Item) (string, fs.Object) {
contents string
)
retry(t, "Put", func() error {
contents = fstest.RandomString(100)
contents = random.String(100)
buf := bytes.NewBufferString(contents)
uploadHash = hash.NewMultiHasher()
in := io.TeeReader(buf, uploadHash)
@ -557,7 +558,7 @@ func Run(t *testing.T, opt *Opt) {
const N = 5 * 1024
// Read N bytes then produce an error
contents := fstest.RandomString(N)
contents := random.String(N)
buf := bytes.NewBufferString(contents)
er := &errorReader{errors.New("potato")}
in := io.MultiReader(buf, er)
@ -1322,7 +1323,7 @@ func Run(t *testing.T, opt *Opt) {
// TestObjectUpdate tests that Update works
t.Run("ObjectUpdate", func(t *testing.T) {
skipIfNotOk(t)
contents := fstest.RandomString(200)
contents := random.String(200)
buf := bytes.NewBufferString(contents)
hash := hash.NewMultiHasher()
in := io.TeeReader(buf, hash)
@ -1507,7 +1508,7 @@ func Run(t *testing.T, opt *Opt) {
contentSize = 100
)
retry(t, "PutStream", func() error {
contents := fstest.RandomString(contentSize)
contents := random.String(contentSize)
buf := bytes.NewBufferString(contents)
uploadHash = hash.NewMultiHasher()
in := io.TeeReader(buf, uploadHash)
@ -1564,7 +1565,7 @@ func Run(t *testing.T, opt *Opt) {
assert.Nil(t, recover(), "Fs.Put() should not panic when src.Size() == -1")
}()
contents := fstest.RandomString(100)
contents := random.String(100)
in := bytes.NewBufferString(contents)
obji := object.NewStaticObjectInfo("unknown-size-put.txt", fstest.Time("2002-02-03T04:05:06.499999999Z"), -1, true, nil, nil)
@ -1587,7 +1588,7 @@ func Run(t *testing.T, opt *Opt) {
assert.Nil(t, recover(), "Object.Update() should not panic when src.Size() == -1")
}()
newContents := fstest.RandomString(200)
newContents := random.String(200)
in := bytes.NewBufferString(newContents)
obj := findObject(t, remote, unknownSizeUpdateFile.Path)

22
lib/random/random.go Normal file
View File

@ -0,0 +1,22 @@
// Package random holds a few functions for working with random numbers
package random
import "math/rand"
// String create a random string for test purposes
func String(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)
}

13
lib/random/random_test.go Normal file
View File

@ -0,0 +1,13 @@
package random
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestString(t *testing.T) {
for i := 0; i < 100; i++ {
assert.Equal(t, i, len(String(i)))
}
}

View File

@ -18,6 +18,7 @@ import (
"time"
"github.com/rclone/rclone/lib/file"
"github.com/rclone/rclone/lib/random"
)
var (
@ -35,24 +36,6 @@ func init() {
}
// 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)
}
// Test contains stats about the running test which work for files or
// directories
type Test struct {
@ -71,7 +54,7 @@ type Test struct {
func NewTest(Dir string) *Test {
t := &Test{
dir: Dir,
name: RandomString(*nameLength),
name: random.String(*nameLength),
isDir: rand.Intn(2) == 0,
number: atomic.AddInt32(&testNumber, 1),
timer: time.NewTimer(*timeout),
@ -168,7 +151,7 @@ func (t *Test) rename() {
return
}
t.logf("rename")
NewName := RandomString(*nameLength)
NewName := random.String(*nameLength)
newPath := path.Join(t.dir, NewName)
err := os.Rename(t.path(), newPath)
if err != nil {