github.com/blend/go-sdk@v1.20240719.1/ex/is_test.go (about)

     1  /*
     2  
     3  Copyright (c) 2024 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package ex
     9  
    10  import (
    11  	"errors"
    12  	"fmt"
    13  	"testing"
    14  
    15  	"github.com/blend/go-sdk/assert"
    16  )
    17  
    18  func TestIs(t *testing.T) {
    19  	stdLibErr := errors.New("sentinel")
    20  	multi := Multi{New("not test class"), Class("test class")}
    21  	testCases := []struct {
    22  		Name     string
    23  		Err      error
    24  		Cause    error
    25  		Expected bool
    26  	}{
    27  		{
    28  			Name:     "True for equal classes",
    29  			Err:      Class("test class"),
    30  			Cause:    Class("test class"),
    31  			Expected: true,
    32  		},
    33  		{
    34  			Name:     "True for comparing ex against class",
    35  			Err:      New("test class"),
    36  			Cause:    Class("test class"),
    37  			Expected: true,
    38  		},
    39  		{
    40  			Name:     "True for comparing ex against ex with equal class",
    41  			Err:      New("test class"),
    42  			Cause:    New("test class"),
    43  			Expected: true,
    44  		},
    45  		{
    46  			Name:     "True for comparing ex against ex with equal sentinel errors",
    47  			Err:      New(stdLibErr),
    48  			Cause:    stdLibErr,
    49  			Expected: true,
    50  		},
    51  		{
    52  			Name:     "True for comparing ex with wrapped sentinel error against sentinel error",
    53  			Err:      New(fmt.Errorf("outer err: %w", stdLibErr)),
    54  			Cause:    stdLibErr,
    55  			Expected: true,
    56  		},
    57  		{
    58  			Name:     "True for comparing a ClassProvider against sentinel error",
    59  			Err:      classProvider{ErrClass: stdLibErr},
    60  			Cause:    stdLibErr,
    61  			Expected: true,
    62  		},
    63  		{
    64  			Name:     "True for comparing a ClassProvider that implements Unwrap() against sentinel error",
    65  			Err:      wrappingClassProvider{error: stdLibErr, ErrClass: New("another class")},
    66  			Cause:    stdLibErr,
    67  			Expected: true,
    68  		},
    69  		{
    70  			Name:     "False for comparing multi ex against multi (due to Go slice comparison limitation)",
    71  			Err:      Multi([]error{New("not test class"), Class("test class")}),
    72  			Cause:    Multi([]error{New("not test class"), Class("test class")}),
    73  			Expected: false,
    74  		},
    75  		{
    76  			Name:     "False for identity comparison of multi ex (due to Go slice comparison limitation)",
    77  			Err:      multi,
    78  			Cause:    multi,
    79  			Expected: false,
    80  		},
    81  		{
    82  			Name: "True for comparing multi ex against class",
    83  			Err: func() error {
    84  				var err error = Multi{Class("test class")}
    85  				for i := 0; i < 50; i++ {
    86  					err = Multi{New(err), New("not test class")}
    87  				}
    88  				return err
    89  			}(),
    90  			Cause:    Class("test class"),
    91  			Expected: true,
    92  		},
    93  		{
    94  			Name: "True for comparing multi ex (created via ex.Append()) against class",
    95  			Err: func() error {
    96  				var err error
    97  				for i := 0; i < 50; i++ {
    98  					err = Append(err, New("not test class"))
    99  				}
   100  				return Append(err, Class("test class"))
   101  			}(),
   102  			Cause:    Class("test class"),
   103  			Expected: true,
   104  		},
   105  		{
   106  			Name:     "False for comparing a ClassProvider without Unwrap() against sentinel error",
   107  			Err:      classProvider{error: stdLibErr, ErrClass: New("another class")},
   108  			Cause:    stdLibErr,
   109  			Expected: false,
   110  		},
   111  		{
   112  			Name:     "False for comparing multi ex against different multi #1",
   113  			Err:      Multi([]error{New("not test class"), Class("test class"), Class("?? class")}),
   114  			Cause:    Multi([]error{New("not test class"), Class("test class")}),
   115  			Expected: false,
   116  		},
   117  		{
   118  			Name:     "False for comparing multi ex against different multi #2",
   119  			Err:      Multi([]error{New("not test class"), Class("test class")}),
   120  			Cause:    Multi([]error{New("test class"), Class("not test class")}),
   121  			Expected: false,
   122  		},
   123  		{
   124  			Name: "False for comparing multi ex (created via ex.Append()) against class",
   125  			Err: func() error {
   126  				var err error
   127  				for i := 0; i < 50; i++ {
   128  					err = Append(err, New("not test class"))
   129  				}
   130  				return Append(err, Class("test class"))
   131  			}(),
   132  			Cause:    Class("neither"),
   133  			Expected: false,
   134  		},
   135  		{
   136  			Name:     "False for different classes",
   137  			Err:      Class("not test class"),
   138  			Cause:    New("test class"),
   139  			Expected: false,
   140  		},
   141  		{
   142  			Name:     "False for ex with different classes",
   143  			Err:      New("test class"),
   144  			Cause:    New("not test class"),
   145  			Expected: false,
   146  		},
   147  		{
   148  			Name:     "False for ex comparison against nil",
   149  			Err:      New("test class"),
   150  			Cause:    nil,
   151  			Expected: false,
   152  		},
   153  		{
   154  			Name:     "True for wrapped sentinel error",
   155  			Err:      fmt.Errorf("outer err: %w", stdLibErr),
   156  			Cause:    stdLibErr,
   157  			Expected: true,
   158  		},
   159  		{
   160  			Name:     "True for identity comparison of native error",
   161  			Err:      stdLibErr,
   162  			Cause:    stdLibErr,
   163  			Expected: true,
   164  		},
   165  		{
   166  			Name:     "False for comparison between two different instances of the same native error",
   167  			Err:      stdLibErr,
   168  			Cause:    errors.New("sentinel"),
   169  			Expected: false,
   170  		},
   171  		{
   172  			Name:     "False for nil comparisons",
   173  			Err:      nil,
   174  			Cause:    nil,
   175  			Expected: false,
   176  		},
   177  		{
   178  			Name:     "False for nil error against class",
   179  			Err:      nil,
   180  			Cause:    Class("test class"),
   181  			Expected: false,
   182  		},
   183  	}
   184  
   185  	for _, tc := range testCases {
   186  		tc := tc
   187  		t.Run(tc.Name, func(t *testing.T) {
   188  			t.Parallel()
   189  			its := assert.New(t)
   190  			its.Equal(tc.Expected, Is(tc.Err, tc.Cause))
   191  		})
   192  	}
   193  }
   194  
   195  type wrappingClassProvider classProvider // classProvider is declared in util_test.go
   196  
   197  // Unwrap implements the error interface.
   198  func (wcp wrappingClassProvider) Unwrap() error {
   199  	return wcp.error
   200  }