github.com/bazelbuild/rules_webtesting@v0.2.0/go/errors/errors.go (about) 1 // Copyright 2016 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package errors provides an Error interface that includes the component name with the underlying error. 16 package errors 17 18 import ( 19 "errors" 20 "fmt" 21 ) 22 23 // DefaultComp is the default component name used when no other component specified. 24 const DefaultComp = "web test launcher" 25 26 type wtlError struct { 27 error 28 component string 29 permanent bool 30 } 31 32 func (we *wtlError) Component() string { 33 return we.component 34 } 35 36 func (we *wtlError) Permanent() bool { 37 return we.permanent 38 } 39 40 // Component returns err.Component() if err implements it, otherwise it returns DefaultComp. 41 // Component is intended for grouping error messages by source. 42 func Component(err error) string { 43 type componentError interface { 44 Component() string 45 } 46 if ce, ok := err.(componentError); ok { 47 return ce.Component() 48 } 49 return DefaultComp 50 } 51 52 // IsPermanent returns err.Permanent() if err implements it, otherwise it returns false. 53 // IsPermanent is intended for preventing retries when errors occur that are unlikely to go away. 54 func IsPermanent(err error) bool { 55 type permanentError interface { 56 Permanent() bool 57 } 58 59 pe, ok := err.(permanentError) 60 return ok && pe.Permanent() 61 } 62 63 func (we *wtlError) Error() string { 64 p := "" 65 if we.permanent { 66 p = " (permanent)" 67 } 68 return fmt.Sprintf("[%s%s]: %v", we.component, p, we.error) 69 } 70 71 // New returns an error, e, such that: 72 // Permanent(e) is false 73 // If Component(err) is not DefaultComp, Component(e) is Component(err) 74 // Else If component is "", Component(e) is DefaultComp 75 // Else Component(e) is component. 76 func New(component string, err interface{}) error { 77 return createErr(component, err, false) 78 } 79 80 // NewPermanent returns an error, e, such that: 81 // Permanent(e) is true 82 // If Component(err) is not DefaultComp, Component(e) is Component(err) 83 // Else If component is "", Component(e) is DefaultComp 84 // Else Component(e) is component. 85 func NewPermanent(component string, err interface{}) error { 86 return createErr(component, err, true) 87 } 88 89 func createErr(component string, err interface{}, permanent bool) error { 90 e := func() error { 91 switch t := err.(type) { 92 case error: 93 return t 94 case string: 95 return errors.New(t) 96 default: 97 return fmt.Errorf("%v", err) 98 } 99 }() 100 101 ec := Component(e) 102 ep := IsPermanent(e) 103 104 if ec != DefaultComp { 105 component = ec 106 } 107 108 if component == "" { 109 component = DefaultComp 110 } 111 112 if ep == permanent && ec == component { 113 return e 114 } 115 116 if we, ok := e.(*wtlError); ok { 117 return createErr(component, we.error, permanent) 118 } 119 120 return &wtlError{ 121 error: e, 122 component: component, 123 permanent: permanent, 124 } 125 }