github.com/nya3jp/tast@v0.0.0-20230601000426-85c8e4d83a9b/src/go.chromium.org/tast/core/internal/runner/args.go (about) 1 // Copyright 2018 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package runner 6 7 import ( 8 "context" 9 "flag" 10 "fmt" 11 "io" 12 "os" 13 "path/filepath" 14 15 "go.chromium.org/tast/core/internal/command" 16 "go.chromium.org/tast/core/internal/protocol" 17 18 frameworkprotocol "go.chromium.org/tast/core/framework/protocol" 19 ) 20 21 // RunnerType describes the type of test runner that is using this package. 22 type RunnerType int // NOLINT 23 24 const ( 25 // LocalRunner indicates that this package is being used by local_test_runner. 26 LocalRunner RunnerType = iota 27 // RemoteRunner indicates that this package is being used by remote_test_runner. 28 RemoteRunner 29 ) 30 31 // StaticConfig contains fixed parameters for the runner that are passed in from 32 // local_test_runner or remote_test_runner. 33 type StaticConfig struct { 34 // Type describes the type of runner being executed. 35 Type RunnerType 36 37 // KillStaleRunners dictates whether SIGTERM should be sent to any existing test runner processes 38 // when using RunnerRunTestsMode. This can help prevent confusing failures if multiple test jobs are 39 // incorrectly scheduled on the same DUT: https://crbug.com/941829 40 KillStaleRunners bool 41 // EnableSyslog specifies whether to copy logs to syslog. It should be 42 // always enabled on production, but can be disabled in unit tests to 43 // avoid spamming syslog. 44 EnableSyslog bool 45 46 // GetDUTInfo is a function to respond to GetDUTInfo RPC. 47 // If it is nil, an empty GetDUTInfoResponse is always returned. 48 GetDUTInfo func(ctx context.Context, req *protocol.GetDUTInfoRequest) (*protocol.GetDUTInfoResponse, error) 49 50 // GetSysInfoState is a function to respond to GetSysInfoState RPC. 51 // If it is nil, an empty GetSysInfoStateResponse is always returned. 52 GetSysInfoState func(ctx context.Context, req *protocol.GetSysInfoStateRequest) (*protocol.GetSysInfoStateResponse, error) 53 54 // CollectSysInfo is a function to respond to CollectSysInfo RPC. 55 // If it is nil, an empty CollectSysInfoResponse is always returned. 56 CollectSysInfo func(ctx context.Context, req *protocol.CollectSysInfoRequest) (*protocol.CollectSysInfoResponse, error) 57 58 // PrivateBundlesStampPath contains the path to a stamp file indicating private test bundles have been 59 // successfully downloaded and installed before. This prevents downloading private test bundles for 60 // every runner invocation. 61 PrivateBundlesStampPath string 62 63 // DeprecatedDirectRunDefaults is default configuration values used when 64 // the user executes a test runner directly to run tests. 65 // 66 // DEPRECATED: Direct test execution is deprecated. Tast tests should be 67 // always initiated with Tast CLI, in which case default values here are 68 // ignored. 69 DeprecatedDirectRunDefaults DeprecatedDirectRunConfig 70 } 71 72 // mode denotes the execution mode of the test runner. 73 type mode int 74 75 const ( 76 // modeRPC is the standard execution mode of the test runner to start 77 // a gRPC server on stdin/stdout. 78 modeRPC mode = iota 79 80 // modeDeprecatedDirectRun is the deprecated execution mode of the test 81 // runner to allow users to run local tests directly on the DUT without 82 // Tast CLI. 83 modeDeprecatedDirectRun 84 ) 85 86 // parsedArgs holds the results of command line parsing. 87 type parsedArgs struct { 88 Mode mode 89 90 // DeprecatedDirectRunConfig contains configuration values used when 91 // the user executes a test runner directly to run tests. 92 // 93 // DEPRECATED: Direct test execution is deprecated. Tast tests should be 94 // always initiated with Tast CLI. 95 DeprecatedDirectRunConfig DeprecatedDirectRunConfig 96 } 97 98 // DeprecatedDirectRunConfig contains configuration values used when the user 99 // executes a test runner directly to run tests. 100 // 101 // DEPRECATED: Direct test execution is deprecated. Tast tests should be always 102 // initiated with Tast CLI. 103 type DeprecatedDirectRunConfig struct { 104 // BundleGlob is a glob-style path matching test bundles to execute. 105 BundleGlob string 106 // DataDir is the path to the directory containing test data files. 107 DataDir string 108 // TempDir is the path to the directory under which temporary files for 109 // tests are written. 110 TempDir string 111 112 // Patterns contains patterns (either empty to run all tests, exactly one attribute expression, 113 // or one or more globs) describing which tests to run. 114 Patterns []string 115 // OutDir is the path to the base directory under which tests should write output files. 116 OutDir string 117 // Devservers contains URLs of devservers that can be used to download files. 118 Devservers []string 119 // WaitUntilReady indicates that the test bundle's "ready" function (see ReadyFunc) should 120 // be executed before any tests are executed. 121 WaitUntilReady bool 122 // ConnectionSpec is the DUT connection spec as [<user>@]host[:<port>]. 123 // It is only relevant for remote tests. 124 ConnectionSpec string 125 // KeyFile is the path to the SSH private key to use to connect to the DUT. 126 // It is only relevant for remote tests. 127 KeyFile string 128 // KeyDir is the directory containing SSH private keys (typically $HOME/.ssh). 129 // It is only relevant for remote tests. 130 KeyDir string 131 // CheckDeps indicates whether test runners should skip tests whose 132 // dependencies are not satisfied by available features. 133 CheckDeps bool 134 // AvailableSoftwareFeatures contains a list of software features supported by the DUT. 135 AvailableSoftwareFeatures []string 136 // UnavailableSoftwareFeatures contains a list of software features supported by the DUT. 137 UnavailableSoftwareFeatures []string 138 } 139 140 // RunConfig generates protocol.RunConfig. 141 // Tests should be a resolved list of test names according to a.Patterns. 142 // Todo: Use primary dut for now, will add companion features in the future 143 func (c *DeprecatedDirectRunConfig) RunConfig(tests []string) *protocol.RunConfig { 144 return &protocol.RunConfig{ 145 Tests: tests, 146 Dirs: &protocol.RunDirectories{ 147 DataDir: c.DataDir, 148 OutDir: c.OutDir, 149 TempDir: c.TempDir, 150 }, 151 Features: &protocol.Features{ 152 CheckDeps: c.CheckDeps, 153 Dut: &frameworkprotocol.DUTFeatures{ 154 Software: &frameworkprotocol.SoftwareFeatures{ 155 Available: c.AvailableSoftwareFeatures, 156 Unavailable: c.UnavailableSoftwareFeatures, 157 }, 158 }, 159 }, 160 ServiceConfig: &protocol.ServiceConfig{ 161 Devservers: c.Devservers, 162 }, 163 DataFileConfig: &protocol.DataFileConfig{}, 164 WaitUntilReady: c.WaitUntilReady, 165 } 166 } 167 168 // parseArgs parses runtime arguments. 169 // clArgs contains command-line arguments and is typically os.Args[1:]. 170 func parseArgs(clArgs []string, stderr io.Writer, scfg *StaticConfig) (*parsedArgs, error) { 171 args := &parsedArgs{ 172 Mode: modeDeprecatedDirectRun, 173 DeprecatedDirectRunConfig: scfg.DeprecatedDirectRunDefaults, 174 } 175 176 // Expose a limited amount of configurability via command-line flags to support running test runners manually. 177 var extraUSEFlags []string 178 flags := flag.NewFlagSet("", flag.ContinueOnError) 179 flags.SetOutput(stderr) 180 const usage = `Usage: %s [flag]... [pattern]... 181 182 Run Tast tests matched by zero or more patterns. 183 184 This executes test bundles to run Tast tests and is typically executed by the 185 "tast" command. It can be executed manually to e.g. perform stress testing. 186 187 Exits with 0 if all tests passed and with a non-zero exit code for all other 188 errors, including the failure of an individual test. 189 190 ` 191 flags.Usage = func() { 192 fmt.Fprintf(stderr, usage, filepath.Base(os.Args[0])) 193 flags.PrintDefaults() 194 } 195 rpc := flags.Bool("rpc", false, "run gRPC server") 196 flags.StringVar(&args.DeprecatedDirectRunConfig.BundleGlob, "bundles", 197 args.DeprecatedDirectRunConfig.BundleGlob, "glob matching test bundles") 198 flags.StringVar(&args.DeprecatedDirectRunConfig.DataDir, "datadir", 199 args.DeprecatedDirectRunConfig.DataDir, "directory containing data files") 200 flags.StringVar(&args.DeprecatedDirectRunConfig.OutDir, "outdir", 201 args.DeprecatedDirectRunConfig.OutDir, "base directory to write output files to") 202 flags.Var(command.NewListFlag(",", func(v []string) { args.DeprecatedDirectRunConfig.Devservers = v }, nil), 203 "devservers", "comma-separated list of devserver URLs") 204 flags.Var(command.NewListFlag(",", func(v []string) { extraUSEFlags = v }, nil), 205 "extrauseflags", "comma-separated list of additional USE flags to inject when checking test dependencies") 206 flags.BoolVar(&args.DeprecatedDirectRunConfig.WaitUntilReady, "waituntilready", 207 true, "wait until DUT is ready before running tests") 208 209 if scfg.Type == RemoteRunner { 210 flags.StringVar(&args.DeprecatedDirectRunConfig.ConnectionSpec, "target", 211 "", "DUT connection spec as \"[<user>@]host[:<port>]\"") 212 flags.StringVar(&args.DeprecatedDirectRunConfig.KeyFile, "keyfile", 213 "", "path to SSH private key to use for connecting to DUT") 214 flags.StringVar(&args.DeprecatedDirectRunConfig.KeyDir, "keydir", 215 "", "directory containing SSH private keys (typically $HOME/.ssh)") 216 } 217 218 if err := flags.Parse(clArgs); err != nil { 219 return nil, command.NewStatusErrorf(statusBadArgs, "%v", err) 220 } 221 222 if *rpc { 223 args.Mode = modeRPC 224 return args, nil 225 } 226 227 args.DeprecatedDirectRunConfig.Patterns = flags.Args() 228 229 // When the runner is executed by the "tast run" command, the list of software features (used to skip 230 // unsupported tests) is passed in after having been gathered by an earlier call to local_test_runner 231 // with RunnerGetDUTInfoMode. When the runner is executed directly, gather the list here instead. 232 if scfg.GetDUTInfo != nil { 233 req := &protocol.GetDUTInfoRequest{ExtraUseFlags: extraUSEFlags} 234 res, err := scfg.GetDUTInfo(context.Background(), req) 235 if err != nil { 236 return nil, err 237 } 238 239 fs := res.GetDutInfo().GetFeatures().GetSoftware() 240 args.DeprecatedDirectRunConfig.CheckDeps = true 241 args.DeprecatedDirectRunConfig.AvailableSoftwareFeatures = fs.GetAvailable() 242 args.DeprecatedDirectRunConfig.UnavailableSoftwareFeatures = fs.GetUnavailable() 243 // Historically we set software features only. Do not bother to 244 // improve hardware feature support in direct mode. 245 } 246 return args, nil 247 }