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  }