github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/eval/exception_test.go (about)

     1  package eval_test
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  	"runtime"
     7  	"testing"
     8  	"unsafe"
     9  
    10  	"github.com/markusbkk/elvish/pkg/diag"
    11  	. "github.com/markusbkk/elvish/pkg/eval"
    12  
    13  	. "github.com/markusbkk/elvish/pkg/eval/evaltest"
    14  	"github.com/markusbkk/elvish/pkg/eval/vals"
    15  	"github.com/markusbkk/elvish/pkg/persistent/hash"
    16  	"github.com/markusbkk/elvish/pkg/tt"
    17  )
    18  
    19  func TestReason(t *testing.T) {
    20  	err := errors.New("ordinary error")
    21  	tt.Test(t, tt.Fn("Reason", Reason), tt.Table{
    22  		tt.Args(err).Rets(err),
    23  		tt.Args(makeException(err)).Rets(err),
    24  	})
    25  }
    26  
    27  func TestException(t *testing.T) {
    28  	err := FailError{"error"}
    29  	exc := makeException(err)
    30  	vals.TestValue(t, exc).
    31  		Kind("exception").
    32  		Bool(false).
    33  		Hash(hash.Pointer(unsafe.Pointer(reflect.ValueOf(exc).Pointer()))).
    34  		Equal(exc).
    35  		NotEqual(makeException(errors.New("error"))).
    36  		AllKeys("reason").
    37  		Index("reason", err).
    38  		IndexError("stack", vals.NoSuchKey("stack")).
    39  		Repr("[&reason=[&content=error &type=fail]]")
    40  
    41  	vals.TestValue(t, OK).
    42  		Kind("exception").
    43  		Bool(true).
    44  		Repr("$ok")
    45  }
    46  
    47  func makeException(cause error, entries ...*diag.Context) Exception {
    48  	return NewException(cause, makeStackTrace(entries...))
    49  }
    50  
    51  // Creates a new StackTrace, using the first entry as the head.
    52  func makeStackTrace(entries ...*diag.Context) *StackTrace {
    53  	var s *StackTrace
    54  	for i := len(entries) - 1; i >= 0; i-- {
    55  		s = &StackTrace{Head: entries[i], Next: s}
    56  	}
    57  	return s
    58  }
    59  
    60  func TestFlow_Fields(t *testing.T) {
    61  	Test(t,
    62  		That("put ?(return)[reason][type name]").Puts("flow", "return"),
    63  	)
    64  }
    65  
    66  func TestExternalCmdExit_Fields(t *testing.T) {
    67  	badCmd := "false"
    68  	if runtime.GOOS == "windows" {
    69  		badCmd = "cmd /c exit 1"
    70  	}
    71  	Test(t,
    72  		That("put ?("+badCmd+")[reason][type exit-status]").
    73  			Puts("external-cmd/exited", "1"),
    74  		// TODO: Test killed and stopped commands
    75  	)
    76  }
    77  
    78  func TestPipelineError_Fields(t *testing.T) {
    79  	Test(t,
    80  		That("put ?(fail 1 | fail 2)[reason][type]").Puts("pipeline"),
    81  		That("count ?(fail 1 | fail 2)[reason][exceptions]").Puts(2),
    82  		That("put ?(fail 1 | fail 2)[reason][exceptions][0][reason][type]").
    83  			Puts("fail"),
    84  	)
    85  }
    86  
    87  func TestErrorMethods(t *testing.T) {
    88  	tt.Test(t, tt.Fn("Error", error.Error), tt.Table{
    89  		tt.Args(makeException(errors.New("err"))).Rets("err"),
    90  
    91  		tt.Args(MakePipelineError([]Exception{
    92  			makeException(errors.New("err1")),
    93  			makeException(errors.New("err2"))})).Rets("(err1 | err2)"),
    94  
    95  		tt.Args(Return).Rets("return"),
    96  		tt.Args(Break).Rets("break"),
    97  		tt.Args(Continue).Rets("continue"),
    98  		tt.Args(Flow(1000)).Rets("!(BAD FLOW: 1000)"),
    99  	})
   100  }