github.com/nya3jp/tast@v0.0.0-20230601000426-85c8e4d83a9b/src/go.chromium.org/tast/core/internal/dep/dep.go (about) 1 // Copyright 2020 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 dep deals with dependencies of tests. 6 package dep 7 8 import ( 9 "fmt" 10 "regexp" 11 "strings" 12 13 "go.chromium.org/tast/core/errors" 14 "go.chromium.org/tast/core/internal/protocol" 15 16 frameworkprotocol "go.chromium.org/tast/core/framework/protocol" 17 ) 18 19 // Deps contains all information about dependencies tests have. 20 type Deps struct { 21 Test string 22 Var []string 23 Software map[string]SoftwareDeps 24 Hardware map[string]HardwareDeps 25 } 26 27 // Check performs dependency checks according to given features. 28 // On success, it returns a list of reasons for which a test should be skipped. 29 // If reasons is empty, a test should be run. 30 func (d *Deps) Check(f *protocol.Features) (reasons []string, err error) { 31 if reason, skip := f.GetForceSkips()[d.Test]; skip { 32 return []string{reason.Reason}, nil 33 } 34 35 if !f.GetCheckDeps() { 36 return nil, nil 37 } 38 39 for role, swDep := range d.Software { 40 var dut *frameworkprotocol.DUTFeatures 41 if role != "" { 42 var valid bool 43 if dut, valid = f.GetCompanionFeatures()[role]; !valid { 44 continue 45 } 46 } else { 47 dut = f.GetDut() 48 } 49 50 missing, unknown := missingSoftwareDeps(swDep, dut.GetSoftware()) 51 52 if len(unknown) > 0 { 53 return nil, errors.Errorf("unknown SoftwareDeps: %v", strings.Join(unknown, ", ")) 54 } 55 if len(missing) > 0 { 56 reasons = append(reasons, fmt.Sprintf("missing SoftwareDeps: %s", strings.Join(missing, ", "))) 57 } 58 } 59 60 for role, hwDep := range d.Hardware { 61 var dut *frameworkprotocol.DUTFeatures 62 if role != "" { 63 var valid bool 64 dut, valid = f.GetCompanionFeatures()[role] 65 if !valid { 66 continue 67 } 68 } else { 69 dut = f.GetDut() 70 } 71 72 sat, err := hwDep.Satisfied(dut.GetHardware()) 73 if err != nil { 74 return nil, err 75 } 76 for _, r := range sat { 77 reasons = append(reasons, r) 78 } 79 } 80 81 if len(reasons) != 0 { 82 return reasons, nil 83 } 84 85 // If f.MaybeMissingVars is empty, no variables are considered as missing. 86 maybeMissingVars, err := regexp.Compile("^" + f.GetInfra().GetMaybeMissingVars() + "$") 87 if err != nil { 88 return nil, errors.Errorf("regex %v is invalid: %v", f.GetInfra().GetMaybeMissingVars(), err) 89 } 90 91 vars := f.GetInfra().GetVars() 92 for _, v := range d.Var { 93 if _, ok := vars[v]; ok { 94 continue 95 } 96 if maybeMissingVars.MatchString(v) { 97 reasons = append(reasons, fmt.Sprintf("runtime variable %v is missing and matches with %v", v, maybeMissingVars)) 98 continue 99 } 100 if f.GetInfra().GetMaybeMissingVars() == "" { 101 return nil, errors.Errorf("runtime variable %v is missing", v) 102 } 103 return nil, errors.Errorf("runtime variable %v is missing and doesn't match with %v", v, maybeMissingVars) 104 } 105 106 return reasons, nil 107 }