github.com/xhghs/rclone@v1.51.1-0.20200430155106-e186a28cced8/fstest/test_all/config.go (about)

     1  // Config handling
     2  
     3  // +build go1.11
     4  
     5  package main
     6  
     7  import (
     8  	"io/ioutil"
     9  	"log"
    10  	"path"
    11  
    12  	"github.com/pkg/errors"
    13  	"github.com/rclone/rclone/fs"
    14  	yaml "gopkg.in/yaml.v2"
    15  )
    16  
    17  // Test describes an integration test to run with `go test`
    18  type Test struct {
    19  	Path       string // path to the source directory
    20  	FastList   bool   // if it is possible to add -fast-list to tests
    21  	Short      bool   // if it is possible to run the test with -short
    22  	AddBackend bool   // set if Path needs the current backend appending
    23  	NoRetries  bool   // set if no retries should be performed
    24  	NoBinary   bool   // set to not build a binary in advance
    25  	LocalOnly  bool   // if set only run with the local backend
    26  }
    27  
    28  // Backend describes a backend test
    29  //
    30  // FIXME make bucket based remotes set sub-dir automatically???
    31  type Backend struct {
    32  	Backend  string   // name of the backend directory
    33  	Remote   string   // name of the test remote
    34  	FastList bool     // set to test with -fast-list
    35  	Short    bool     // set to test with -short
    36  	OneOnly  bool     // set to run only one backend test at once
    37  	MaxFile  string   // file size limit
    38  	Ignore   []string // test names to ignore the failure of
    39  	Tests    []string // paths of tests to run, blank for all
    40  }
    41  
    42  // includeTest returns true if this backend should be included in this
    43  // test
    44  func (b *Backend) includeTest(t *Test) bool {
    45  	if len(b.Tests) == 0 {
    46  		return true
    47  	}
    48  	for _, testPath := range b.Tests {
    49  		if testPath == t.Path {
    50  			return true
    51  		}
    52  	}
    53  	return false
    54  }
    55  
    56  // MakeRuns creates Run objects the Backend and Test
    57  //
    58  // There can be several created, one for each combination of optionl
    59  // flags (eg FastList)
    60  func (b *Backend) MakeRuns(t *Test) (runs []*Run) {
    61  	if !b.includeTest(t) {
    62  		return runs
    63  	}
    64  	maxSize := fs.SizeSuffix(0)
    65  	if b.MaxFile != "" {
    66  		if err := maxSize.Set(b.MaxFile); err != nil {
    67  			log.Printf("Invalid maxfile value %q: %v", b.MaxFile, err)
    68  		}
    69  	}
    70  	fastlists := []bool{false}
    71  	if b.FastList && t.FastList {
    72  		fastlists = append(fastlists, true)
    73  	}
    74  	ignore := make(map[string]struct{}, len(b.Ignore))
    75  	for _, item := range b.Ignore {
    76  		ignore[item] = struct{}{}
    77  	}
    78  	for _, fastlist := range fastlists {
    79  		if t.LocalOnly && b.Backend != "local" {
    80  			continue
    81  		}
    82  		run := &Run{
    83  			Remote:    b.Remote,
    84  			Backend:   b.Backend,
    85  			Path:      t.Path,
    86  			FastList:  fastlist,
    87  			Short:     (b.Short && t.Short),
    88  			NoRetries: t.NoRetries,
    89  			OneOnly:   b.OneOnly,
    90  			NoBinary:  t.NoBinary,
    91  			SizeLimit: int64(maxSize),
    92  			Ignore:    ignore,
    93  		}
    94  		if t.AddBackend {
    95  			run.Path = path.Join(run.Path, b.Backend)
    96  		}
    97  		runs = append(runs, run)
    98  	}
    99  	return runs
   100  }
   101  
   102  // Config describes the config for this program
   103  type Config struct {
   104  	Tests    []Test
   105  	Backends []Backend
   106  }
   107  
   108  // NewConfig reads the config file
   109  func NewConfig(configFile string) (*Config, error) {
   110  	d, err := ioutil.ReadFile(configFile)
   111  	if err != nil {
   112  		return nil, errors.Wrap(err, "failed to read config file")
   113  	}
   114  	config := &Config{}
   115  	err = yaml.Unmarshal(d, &config)
   116  	if err != nil {
   117  		return nil, errors.Wrap(err, "failed to parse config file")
   118  	}
   119  	// d, err = yaml.Marshal(&config)
   120  	// if err != nil {
   121  	// 	log.Fatalf("error: %v", err)
   122  	// }
   123  	// fmt.Printf("--- m dump:\n%s\n\n", string(d))
   124  	return config, nil
   125  }
   126  
   127  // MakeRuns makes Run objects for each combination of Backend and Test
   128  // in the config
   129  func (c *Config) MakeRuns() (runs Runs) {
   130  	for _, backend := range c.Backends {
   131  		for _, test := range c.Tests {
   132  			runs = append(runs, backend.MakeRuns(&test)...)
   133  		}
   134  	}
   135  	return runs
   136  }
   137  
   138  // Filter the Backends with the remotes passed in.
   139  //
   140  // If no backend is found with a remote is found then synthesize one
   141  func (c *Config) filterBackendsByRemotes(remotes []string) {
   142  	var newBackends []Backend
   143  	for _, name := range remotes {
   144  		found := false
   145  		for i := range c.Backends {
   146  			if c.Backends[i].Remote == name {
   147  				newBackends = append(newBackends, c.Backends[i])
   148  				found = true
   149  			}
   150  		}
   151  		if !found {
   152  			log.Printf("Remote %q not found - inserting with default flags", name)
   153  			// Lookup which backend
   154  			fsInfo, _, _, _, err := fs.ConfigFs(name)
   155  			if err != nil {
   156  				log.Fatalf("couldn't find remote %q: %v", name, err)
   157  			}
   158  			newBackends = append(newBackends, Backend{Backend: fsInfo.FileName(), Remote: name})
   159  		}
   160  	}
   161  	c.Backends = newBackends
   162  }
   163  
   164  // Filter the Backends with the backendNames passed in
   165  func (c *Config) filterBackendsByBackends(backendNames []string) {
   166  	var newBackends []Backend
   167  	for _, name := range backendNames {
   168  		for i := range c.Backends {
   169  			if c.Backends[i].Backend == name {
   170  				newBackends = append(newBackends, c.Backends[i])
   171  			}
   172  		}
   173  	}
   174  	c.Backends = newBackends
   175  }
   176  
   177  // Filter the incoming tests into the backends selected
   178  func (c *Config) filterTests(paths []string) {
   179  	var newTests []Test
   180  	for _, path := range paths {
   181  		for i := range c.Tests {
   182  			if c.Tests[i].Path == path {
   183  				newTests = append(newTests, c.Tests[i])
   184  			}
   185  		}
   186  	}
   187  	c.Tests = newTests
   188  }
   189  
   190  // Remotes returns the unique remotes
   191  func (c *Config) Remotes() (remotes []string) {
   192  	found := map[string]struct{}{}
   193  	for _, backend := range c.Backends {
   194  		if _, ok := found[backend.Remote]; ok {
   195  			continue
   196  		}
   197  		remotes = append(remotes, backend.Remote)
   198  		found[backend.Remote] = struct{}{}
   199  	}
   200  	return remotes
   201  }