Automatically generate the tests files for each Fs

This commit is contained in:
Nick Craig-Wood 2014-07-26 17:18:29 +01:00
parent 17ffb0855f
commit 457ef2c190
11 changed files with 184 additions and 18 deletions

View File

@ -61,3 +61,6 @@ tag:
retag: retag:
git tag -f $(LAST_TAG) git tag -f $(LAST_TAG)
gen_tests:
cd fstest/fstests && go run gen_tests.go

View File

@ -1,4 +1,7 @@
// Test Drive filesystem interface // Test Drive filesystem interface
//
// Automatically generated - DO NOT EDIT
// Regenerate with: go run gen_tests.go or make gen_tests
package drive_test package drive_test
import ( import (

View File

@ -1,4 +1,7 @@
// Test Dropbox filesystem interface // Test Dropbox filesystem interface
//
// Automatically generated - DO NOT EDIT
// Regenerate with: go run gen_tests.go or make gen_tests
package dropbox_test package dropbox_test
import ( import (

View File

@ -17,6 +17,12 @@ import (
var Fatalf = log.Fatalf var Fatalf = log.Fatalf
// Seed the random number generator
func init() {
rand.Seed(time.Now().UnixNano())
}
// Represents an item for checking // Represents an item for checking
type Item struct { type Item struct {
Path string Path string
@ -25,6 +31,15 @@ type Item struct {
Size int64 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) { func (i *Item) Check(obj fs.Object) {
if obj == nil { if obj == nil {
Fatalf("Object is nil") Fatalf("Object is nil")
@ -40,13 +55,7 @@ func (i *Item) Check(obj fs.Object) {
if i.Size != obj.Size() { if i.Size != obj.Size() {
Fatalf("%s: Size incorrect - expecting %d got %d", obj.Remote(), 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 i.CheckModTime(obj, obj.ModTime())
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)
}
} }
// Represents all items for checking // Represents all items for checking

View File

@ -110,7 +110,7 @@ func TestFsNewFsObjectNotFound(t *testing.T) {
func findObject(t *testing.T, Name string) fs.Object { func findObject(t *testing.T, Name string) fs.Object {
obj := remote.NewFsObject(Name) obj := remote.NewFsObject(Name)
if obj == nil { if obj == nil {
t.Fatalf("nil object") t.Fatalf("Object not found: %q", Name)
} }
return obj return obj
} }
@ -235,9 +235,7 @@ func TestObjectMd5sum(t *testing.T) {
func TestObjectModTime(t *testing.T) { func TestObjectModTime(t *testing.T) {
skipIfNotOk(t) skipIfNotOk(t)
obj := findObject(t, file1.Path) obj := findObject(t, file1.Path)
if !obj.ModTime().Equal(file1.ModTime) { file1.CheckModTime(obj, obj.ModTime())
t.Errorf("ModTime is wrong %v != %v", obj.ModTime(), file1.ModTime)
}
} }
func TestObjectSetModTime(t *testing.T) { func TestObjectSetModTime(t *testing.T) {
@ -245,11 +243,8 @@ func TestObjectSetModTime(t *testing.T) {
newModTime := fstest.Time("2011-12-13T14:15:16.999999999Z") newModTime := fstest.Time("2011-12-13T14:15:16.999999999Z")
obj := findObject(t, file1.Path) obj := findObject(t, file1.Path)
obj.SetModTime(newModTime) 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.ModTime = newModTime
file1.CheckModTime(obj, newModTime)
// And make a new object and read it from there too // And make a new object and read it from there too
TestObjectModTime(t) TestObjectModTime(t)
} }

143
fstest/fstests/gen_tests.go Normal file
View File

@ -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")
}

View File

@ -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 package googlecloudstorage_test
import ( import (

View File

@ -1,4 +1,7 @@
// Test Local filesystem interface // Test Local filesystem interface
//
// Automatically generated - DO NOT EDIT
// Regenerate with: go run gen_tests.go or make gen_tests
package local_test package local_test
import ( import (

View File

@ -7,7 +7,6 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"math/rand"
"os" "os"
"path" "path"
"time" "time"
@ -251,7 +250,6 @@ func main() {
os.Exit(0) os.Exit(0)
} }
fs.LoadConfig() fs.LoadConfig()
rand.Seed(time.Now().UnixNano())
args := pflag.Args() args := pflag.Args()
if len(args) != 1 { if len(args) != 1 {

View File

@ -1,4 +1,7 @@
// Test S3 filesystem interface // Test S3 filesystem interface
//
// Automatically generated - DO NOT EDIT
// Regenerate with: go run gen_tests.go or make gen_tests
package s3_test package s3_test
import ( import (

View File

@ -1,4 +1,7 @@
// Test Swift filesystem interface // Test Swift filesystem interface
//
// Automatically generated - DO NOT EDIT
// Regenerate with: go run gen_tests.go or make gen_tests
package swift_test package swift_test
import ( import (