github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/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/ncw/rclone/fs"
    13  	"github.com/pkg/errors"
    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  	SubDir     bool   // if it is possible to add -sub-dir to tests
    21  	FastList   bool   // if it is possible to add -fast-list to tests
    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  	SubDir   bool     // set to test with -sub-dir
    35  	FastList bool     // set to test with -fast-list
    36  	OneOnly  bool     // set to run only one backend test at once
    37  	Ignore   []string // test names to ignore the failure of
    38  	Tests    []string // paths of tests to run, blank for all
    39  }
    40  
    41  // includeTest returns true if this backend should be included in this
    42  // test
    43  func (b *Backend) includeTest(t *Test) bool {
    44  	if len(b.Tests) == 0 {
    45  		return true
    46  	}
    47  	for _, testPath := range b.Tests {
    48  		if testPath == t.Path {
    49  			return true
    50  		}
    51  	}
    52  	return false
    53  }
    54  
    55  // MakeRuns creates Run objects the Backend and Test
    56  //
    57  // There can be several created, one for each combination of SubDir
    58  // and FastList
    59  func (b *Backend) MakeRuns(t *Test) (runs []*Run) {
    60  	if !b.includeTest(t) {
    61  		return runs
    62  	}
    63  	subdirs := []bool{false}
    64  	if b.SubDir && t.SubDir {
    65  		subdirs = append(subdirs, true)
    66  	}
    67  	fastlists := []bool{false}
    68  	if b.FastList && t.FastList {
    69  		fastlists = append(fastlists, true)
    70  	}
    71  	ignore := make(map[string]struct{}, len(b.Ignore))
    72  	for _, item := range b.Ignore {
    73  		ignore[item] = struct{}{}
    74  	}
    75  	for _, subdir := range subdirs {
    76  		for _, fastlist := range fastlists {
    77  			if t.LocalOnly && b.Backend != "local" {
    78  				continue
    79  			}
    80  			run := &Run{
    81  				Remote:    b.Remote,
    82  				Backend:   b.Backend,
    83  				Path:      t.Path,
    84  				SubDir:    subdir,
    85  				FastList:  fastlist,
    86  				NoRetries: t.NoRetries,
    87  				OneOnly:   b.OneOnly,
    88  				NoBinary:  t.NoBinary,
    89  				Ignore:    ignore,
    90  			}
    91  			if t.AddBackend {
    92  				run.Path = path.Join(run.Path, b.Backend)
    93  			}
    94  			runs = append(runs, run)
    95  		}
    96  	}
    97  	return runs
    98  }
    99  
   100  // Config describes the config for this program
   101  type Config struct {
   102  	Tests    []Test
   103  	Backends []Backend
   104  }
   105  
   106  // NewConfig reads the config file
   107  func NewConfig(configFile string) (*Config, error) {
   108  	d, err := ioutil.ReadFile(configFile)
   109  	if err != nil {
   110  		return nil, errors.Wrap(err, "failed to read config file")
   111  	}
   112  	config := &Config{}
   113  	err = yaml.Unmarshal(d, &config)
   114  	if err != nil {
   115  		return nil, errors.Wrap(err, "failed to parse config file")
   116  	}
   117  	// d, err = yaml.Marshal(&config)
   118  	// if err != nil {
   119  	// 	log.Fatalf("error: %v", err)
   120  	// }
   121  	// fmt.Printf("--- m dump:\n%s\n\n", string(d))
   122  	return config, nil
   123  }
   124  
   125  // MakeRuns makes Run objects for each combination of Backend and Test
   126  // in the config
   127  func (c *Config) MakeRuns() (runs Runs) {
   128  	for _, backend := range c.Backends {
   129  		for _, test := range c.Tests {
   130  			runs = append(runs, backend.MakeRuns(&test)...)
   131  		}
   132  	}
   133  	return runs
   134  }
   135  
   136  // Filter the Backends with the remotes passed in.
   137  //
   138  // If no backend is found with a remote is found then synthesize one
   139  func (c *Config) filterBackendsByRemotes(remotes []string) {
   140  	var newBackends []Backend
   141  	for _, name := range remotes {
   142  		found := false
   143  		for i := range c.Backends {
   144  			if c.Backends[i].Remote == name {
   145  				newBackends = append(newBackends, c.Backends[i])
   146  				found = true
   147  			}
   148  		}
   149  		if !found {
   150  			log.Printf("Remote %q not found - inserting with default flags", name)
   151  			// Lookup which backend
   152  			fsInfo, _, _, _, err := fs.ConfigFs(name)
   153  			if err != nil {
   154  				log.Fatalf("couldn't find remote %q: %v", name, err)
   155  			}
   156  			newBackends = append(newBackends, Backend{Backend: fsInfo.FileName(), Remote: name})
   157  		}
   158  	}
   159  	c.Backends = newBackends
   160  }
   161  
   162  // Filter the Backends with the backendNames passed in
   163  func (c *Config) filterBackendsByBackends(backendNames []string) {
   164  	var newBackends []Backend
   165  	for _, name := range backendNames {
   166  		for i := range c.Backends {
   167  			if c.Backends[i].Backend == name {
   168  				newBackends = append(newBackends, c.Backends[i])
   169  			}
   170  		}
   171  	}
   172  	c.Backends = newBackends
   173  }
   174  
   175  // Filter the incoming tests into the backends selected
   176  func (c *Config) filterTests(paths []string) {
   177  	var newTests []Test
   178  	for _, path := range paths {
   179  		for i := range c.Tests {
   180  			if c.Tests[i].Path == path {
   181  				newTests = append(newTests, c.Tests[i])
   182  			}
   183  		}
   184  	}
   185  	c.Tests = newTests
   186  }
   187  
   188  // Remotes returns the unique remotes
   189  func (c *Config) Remotes() (remotes []string) {
   190  	found := map[string]struct{}{}
   191  	for _, backend := range c.Backends {
   192  		if _, ok := found[backend.Remote]; ok {
   193  			continue
   194  		}
   195  		remotes = append(remotes, backend.Remote)
   196  		found[backend.Remote] = struct{}{}
   197  	}
   198  	return remotes
   199  }