diff --git a/Makefile b/Makefile index afbfe31ab..715bf6344 100644 --- a/Makefile +++ b/Makefile @@ -61,3 +61,6 @@ tag: retag: git tag -f $(LAST_TAG) + +gen_tests: + cd fstest/fstests && go run gen_tests.go diff --git a/drive/drive_test.go b/drive/drive_test.go index 803c6cf4c..d8ee07f3b 100644 --- a/drive/drive_test.go +++ b/drive/drive_test.go @@ -1,4 +1,7 @@ // Test Drive filesystem interface +// +// Automatically generated - DO NOT EDIT +// Regenerate with: go run gen_tests.go or make gen_tests package drive_test import ( diff --git a/dropbox/dropbox_test.go b/dropbox/dropbox_test.go index 9ba2d08d7..99e816cfc 100644 --- a/dropbox/dropbox_test.go +++ b/dropbox/dropbox_test.go @@ -1,4 +1,7 @@ // Test Dropbox filesystem interface +// +// Automatically generated - DO NOT EDIT +// Regenerate with: go run gen_tests.go or make gen_tests package dropbox_test import ( diff --git a/fstest/fstest.go b/fstest/fstest.go index 7ffbcb4fd..e103b7648 100644 --- a/fstest/fstest.go +++ b/fstest/fstest.go @@ -17,6 +17,12 @@ import ( var Fatalf = log.Fatalf +// Seed the random number generator +func init() { + rand.Seed(time.Now().UnixNano()) + +} + // Represents an item for checking type Item struct { Path string @@ -25,6 +31,15 @@ type Item struct { Size int64 } +// check the mod time to the given precision +func (i *Item) CheckModTime(obj fs.Object, modTime time.Time) { + dt := modTime.Sub(i.ModTime) + precision := obj.Fs().Precision() + if dt >= precision || dt <= -precision { + Fatalf("%s: Modification time difference too big |%s| > %s (%s vs %s)", obj.Remote(), dt, precision, modTime, i.ModTime) + } +} + func (i *Item) Check(obj fs.Object) { if obj == nil { Fatalf("Object is nil") @@ -40,13 +55,7 @@ func (i *Item) Check(obj fs.Object) { if i.Size != obj.Size() { Fatalf("%s: Size incorrect - expecting %d got %d", obj.Remote(), i.Size, obj.Size()) } - // check the mod time to the given precision - modTime := obj.ModTime() - dt := modTime.Sub(i.ModTime) - if dt >= fs.Config.ModifyWindow || dt <= -fs.Config.ModifyWindow { - Fatalf("%s: Modification time difference too big |%s| > %s (%s vs %s)", obj.Remote(), dt, fs.Config.ModifyWindow, modTime, i.ModTime) - } - + i.CheckModTime(obj, obj.ModTime()) } // Represents all items for checking diff --git a/fstest/fstests/fstests.go b/fstest/fstests/fstests.go index ad7ba2282..99be49c6f 100644 --- a/fstest/fstests/fstests.go +++ b/fstest/fstests/fstests.go @@ -110,7 +110,7 @@ func TestFsNewFsObjectNotFound(t *testing.T) { func findObject(t *testing.T, Name string) fs.Object { obj := remote.NewFsObject(Name) if obj == nil { - t.Fatalf("nil object") + t.Fatalf("Object not found: %q", Name) } return obj } @@ -235,9 +235,7 @@ func TestObjectMd5sum(t *testing.T) { func TestObjectModTime(t *testing.T) { skipIfNotOk(t) obj := findObject(t, file1.Path) - if !obj.ModTime().Equal(file1.ModTime) { - t.Errorf("ModTime is wrong %v != %v", obj.ModTime(), file1.ModTime) - } + file1.CheckModTime(obj, obj.ModTime()) } func TestObjectSetModTime(t *testing.T) { @@ -245,11 +243,8 @@ func TestObjectSetModTime(t *testing.T) { newModTime := fstest.Time("2011-12-13T14:15:16.999999999Z") obj := findObject(t, file1.Path) obj.SetModTime(newModTime) - // Check in this object - if !obj.ModTime().Equal(newModTime) { - t.Errorf("newModTime is wrong %v != %v", obj.ModTime(), newModTime) - } file1.ModTime = newModTime + file1.CheckModTime(obj, newModTime) // And make a new object and read it from there too TestObjectModTime(t) } diff --git a/fstest/fstests/gen_tests.go b/fstest/fstests/gen_tests.go new file mode 100644 index 000000000..9c8e5a7f3 --- /dev/null +++ b/fstest/fstests/gen_tests.go @@ -0,0 +1,143 @@ +// +build ignore + +// Make the test files from fstests.go +package main + +import ( + "bufio" + "html/template" + "log" + "os" + "os/exec" + "regexp" + "strings" +) + +// Search fstests.go and return all the test function names +func findTestFunctions() []string { + fns := []string{} + matcher := regexp.MustCompile(`^func\s+(Test.*?)\(`) + + in, err := os.Open("fstests.go") + if err != nil { + log.Fatalf("Couldn't open fstests.go: %v", err) + } + defer in.Close() + + scanner := bufio.NewScanner(in) + for scanner.Scan() { + line := scanner.Text() + matches := matcher.FindStringSubmatch(line) + if len(matches) > 0 { + fns = append(fns, matches[1]) + } + } + + if err := scanner.Err(); err != nil { + log.Fatalf("Error scanning file: %v", err) + } + return fns +} + +// Data to substitute +type Data struct { + Regenerate string + FsName string + UpperFsName string + TestName string + ObjectName string + Fns []string +} + +var testProgram = ` +// Test {{ .UpperFsName }} filesystem interface +// +// Automatically generated - DO NOT EDIT +// Regenerate with: {{ .Regenerate }} +package {{ .FsName }}_test + +import ( + "testing" + + "github.com/ncw/rclone/fs" + "github.com/ncw/rclone/fstest/fstests" + "github.com/ncw/rclone/{{ .FsName }}" +) + +func init() { + fstests.NilObject = fs.Object((*{{ .FsName }}.FsObject{{ .ObjectName }})(nil)) + fstests.RemoteName = "{{ .TestName }}" +} + +// Generic tests for the Fs +{{ range $fn := .Fns }}func {{ $fn }}(t *testing.T){ fstests.{{ $fn }}(t) } +{{ end }} +` + +// Generate test file piping it through gofmt +func generateTestProgram(t *template.Template, fns []string, Fsname string) { + fsname := strings.ToLower(Fsname) + TestName := "Test" + Fsname + ":" + outfile := "../../" + fsname + "/" + fsname + "_test.go" + // Find last capitalised group to be object name + matcher := regexp.MustCompile(`([A-Z][a-z0-9]+)$`) + matches := matcher.FindStringSubmatch(Fsname) + if len(matches) == 0 { + log.Fatalf("Couldn't find object name in %q", Fsname) + } + ObjectName := matches[1] + + if fsname == "local" { + TestName = "" + } + + data := Data{ + Regenerate: "go run gen_tests.go or make gen_tests", + FsName: fsname, + UpperFsName: Fsname, + TestName: TestName, + ObjectName: ObjectName, + Fns: fns, + } + + cmd := exec.Command("gofmt") + + log.Printf("Writing %q", outfile) + out, err := os.Create(outfile) + if err != nil { + log.Fatal(err) + } + cmd.Stdout = out + + gofmt, err := cmd.StdinPipe() + if err != nil { + log.Fatal(err) + } + if err = cmd.Start(); err != nil { + log.Fatal(err) + } + if err = t.Execute(gofmt, data); err != nil { + log.Fatal(err) + } + if err = gofmt.Close(); err != nil { + log.Fatal(err) + } + if err = cmd.Wait(); err != nil { + log.Fatal(err) + } + if err = out.Close(); err != nil { + log.Fatal(err) + } +} + +func main() { + fns := findTestFunctions() + t := template.Must(template.New("main").Parse(testProgram)) + generateTestProgram(t, fns, "Local") + generateTestProgram(t, fns, "Swift") + generateTestProgram(t, fns, "S3") + generateTestProgram(t, fns, "Drive") + generateTestProgram(t, fns, "GoogleCloudStorage") + generateTestProgram(t, fns, "Dropbox") + log.Printf("Done") +} diff --git a/googlecloudstorage/googlecloudstorage_test.go b/googlecloudstorage/googlecloudstorage_test.go index b83a0b36e..31487840a 100644 --- a/googlecloudstorage/googlecloudstorage_test.go +++ b/googlecloudstorage/googlecloudstorage_test.go @@ -1,4 +1,7 @@ -// Test Google cloud storage filesystem interface +// Test GoogleCloudStorage filesystem interface +// +// Automatically generated - DO NOT EDIT +// Regenerate with: go run gen_tests.go or make gen_tests package googlecloudstorage_test import ( diff --git a/local/local_test.go b/local/local_test.go index 689be7fff..8f67161e5 100644 --- a/local/local_test.go +++ b/local/local_test.go @@ -1,4 +1,7 @@ // Test Local filesystem interface +// +// Automatically generated - DO NOT EDIT +// Regenerate with: go run gen_tests.go or make gen_tests package local_test import ( diff --git a/rclonetest/rclonetest.go b/rclonetest/rclonetest.go index 6c2827069..2a94f3eea 100644 --- a/rclonetest/rclonetest.go +++ b/rclonetest/rclonetest.go @@ -7,7 +7,6 @@ import ( "fmt" "io/ioutil" "log" - "math/rand" "os" "path" "time" @@ -251,7 +250,6 @@ func main() { os.Exit(0) } fs.LoadConfig() - rand.Seed(time.Now().UnixNano()) args := pflag.Args() if len(args) != 1 { diff --git a/s3/s3_test.go b/s3/s3_test.go index a2ef7054a..f63e794ff 100644 --- a/s3/s3_test.go +++ b/s3/s3_test.go @@ -1,4 +1,7 @@ // Test S3 filesystem interface +// +// Automatically generated - DO NOT EDIT +// Regenerate with: go run gen_tests.go or make gen_tests package s3_test import ( diff --git a/swift/swift_test.go b/swift/swift_test.go index 19f47d7d9..d09f0bf46 100644 --- a/swift/swift_test.go +++ b/swift/swift_test.go @@ -1,4 +1,7 @@ // Test Swift filesystem interface +// +// Automatically generated - DO NOT EDIT +// Regenerate with: go run gen_tests.go or make gen_tests package swift_test import (