github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/fstest/test_all/test_all.go (about) 1 // Run tests for all the remotes. Run this with package names which 2 // need integration testing. 3 // 4 // See the `test` target in the Makefile. 5 // 6 package main 7 8 /* FIXME 9 10 Make TesTrun have a []string of flags to try - that then makes it generic 11 12 */ 13 14 import ( 15 "flag" 16 "log" 17 "math/rand" 18 "os" 19 "path" 20 "regexp" 21 "strings" 22 "time" 23 24 _ "github.com/rclone/rclone/backend/all" // import all fs 25 "github.com/rclone/rclone/lib/pacer" 26 ) 27 28 var ( 29 // Flags 30 maxTries = flag.Int("maxtries", 5, "Number of times to try each test") 31 maxN = flag.Int("n", 20, "Maximum number of tests to run at once") 32 testRemotes = flag.String("remotes", "", "Comma separated list of remotes to test, eg 'TestSwift:,TestS3'") 33 testBackends = flag.String("backends", "", "Comma separated list of backends to test, eg 's3,googlecloudstorage") 34 testTests = flag.String("tests", "", "Comma separated list of tests to test, eg 'fs/sync,fs/operations'") 35 clean = flag.Bool("clean", false, "Instead of testing, clean all left over test directories") 36 runOnly = flag.String("run", "", "Run only those tests matching the regexp supplied") 37 timeout = flag.Duration("timeout", 60*time.Minute, "Maximum time to run each test for before giving up") 38 configFile = flag.String("config", "fstest/test_all/config.yaml", "Path to config file") 39 outputDir = flag.String("output", path.Join(os.TempDir(), "rclone-integration-tests"), "Place to store results") 40 emailReport = flag.String("email", "", "Set to email the report to the address supplied") 41 dryRun = flag.Bool("dry-run", false, "Print commands which would be executed only") 42 urlBase = flag.String("url-base", "https://pub.rclone.org/integration-tests/", "Base for the online version") 43 uploadPath = flag.String("upload", "", "Set this to an rclone path to upload the results here") 44 verbose = flag.Bool("verbose", false, "Set to enable verbose logging in the tests") 45 listRetries = flag.Int("list-retries", -1, "Number or times to retry listing - set to override the default") 46 ) 47 48 // if matches then is definitely OK in the shell 49 var shellOK = regexp.MustCompile("^[A-Za-z0-9./_:-]+$") 50 51 // converts an argv style input into a shell command 52 func toShell(args []string) (result string) { 53 for _, arg := range args { 54 if result != "" { 55 result += " " 56 } 57 if shellOK.MatchString(arg) { 58 result += arg 59 } else { 60 result += "'" + arg + "'" 61 } 62 } 63 return result 64 } 65 66 func main() { 67 flag.Parse() 68 conf, err := NewConfig(*configFile) 69 if err != nil { 70 log.Println("test_all should be run from the root of the rclone source code") 71 log.Fatal(err) 72 } 73 74 // Seed the random number generator 75 rand.Seed(time.Now().UTC().UnixNano()) 76 77 // Filter selection 78 if *testRemotes != "" { 79 conf.filterBackendsByRemotes(strings.Split(*testRemotes, ",")) 80 } 81 if *testBackends != "" { 82 conf.filterBackendsByBackends(strings.Split(*testBackends, ",")) 83 } 84 if *testTests != "" { 85 conf.filterTests(strings.Split(*testTests, ",")) 86 } 87 88 // Just clean the directories if required 89 if *clean { 90 err := cleanRemotes(conf) 91 if err != nil { 92 log.Fatalf("Failed to clean: %v", err) 93 } 94 return 95 } 96 97 var names []string 98 for _, remote := range conf.Backends { 99 names = append(names, remote.Remote) 100 } 101 log.Printf("Testing remotes: %s", strings.Join(names, ", ")) 102 103 // Runs we will do for this test in random order 104 runs := conf.MakeRuns() 105 rand.Shuffle(len(runs), runs.Swap) 106 107 // Create Report 108 report := NewReport() 109 110 // Make the test binaries, one per Path found in the tests 111 done := map[string]struct{}{} 112 for _, run := range runs { 113 if _, found := done[run.Path]; !found { 114 done[run.Path] = struct{}{} 115 if !run.NoBinary { 116 run.MakeTestBinary() 117 defer run.RemoveTestBinary() 118 } 119 } 120 } 121 122 // workaround for cache backend as we run simultaneous tests 123 _ = os.Setenv("RCLONE_CACHE_DB_WAIT_TIME", "30m") 124 125 // start the tests 126 results := make(chan *Run, len(runs)) 127 awaiting := 0 128 tokens := pacer.NewTokenDispenser(*maxN) 129 for _, run := range runs { 130 tokens.Get() 131 go func(run *Run) { 132 defer tokens.Put() 133 run.Run(report.LogDir, results) 134 }(run) 135 awaiting++ 136 } 137 138 // Wait for the tests to finish 139 for ; awaiting > 0; awaiting-- { 140 t := <-results 141 report.RecordResult(t) 142 } 143 144 // Log and exit 145 report.End() 146 report.LogSummary() 147 report.LogJSON() 148 report.LogHTML() 149 report.EmailHTML() 150 report.Upload() 151 if !report.AllPassed() { 152 os.Exit(1) 153 } 154 }