go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/errutil/multi_test.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package errutil
     9  
    10  import (
    11  	"errors"
    12  	"fmt"
    13  	"testing"
    14  )
    15  
    16  func TestError_Impl(t *testing.T) {
    17  	var _ error = (*Multi)(nil)
    18  }
    19  
    20  func TestErrorError_default(t *testing.T) {
    21  	expected := `2 errors occurred:
    22  	* foo
    23  	* bar
    24  
    25  `
    26  
    27  	errors := []error{
    28  		errors.New("foo"),
    29  		errors.New("bar"),
    30  	}
    31  
    32  	multi := Multi(errors)
    33  	if multi.Error() != expected {
    34  		t.Fatalf("bad: %s", multi.Error())
    35  	}
    36  }
    37  
    38  func Test_Multi_WrappedErrors(t *testing.T) {
    39  	errors := []error{
    40  		errors.New("foo"),
    41  		errors.New("bar"),
    42  	}
    43  
    44  	multi := Multi(errors)
    45  	wrapped := multi.WrappedErrors()
    46  	for x := 0; x < len(errors); x++ {
    47  		if wrapped[x].Error() != errors[x].Error() {
    48  			t.Fatalf("bad: %s vs. %s", wrapped[x], errors[x])
    49  		}
    50  	}
    51  
    52  	multi = nil
    53  	if err := multi.WrappedErrors(); err != nil {
    54  		t.Fatalf("bad: %#v", multi)
    55  	}
    56  }
    57  
    58  func TestErrorUnwrap(t *testing.T) {
    59  	t.Run("with errors", func(t *testing.T) {
    60  		err := Multi([]error{
    61  			errors.New("foo"),
    62  			errors.New("bar"),
    63  			errors.New("baz"),
    64  		})
    65  
    66  		var current error = err
    67  		for i := 0; i < len(err); i++ {
    68  			current = errors.Unwrap(current)
    69  			if !errors.Is(current, err[i]) {
    70  				t.Fatal("should be next value")
    71  			}
    72  		}
    73  
    74  		if errors.Unwrap(current) != nil {
    75  			t.Fatal("should be nil at the end")
    76  		}
    77  	})
    78  
    79  	t.Run("with no errors", func(t *testing.T) {
    80  		err := Multi{}
    81  		if errors.Unwrap(err) != nil {
    82  			t.Fatal("should be nil")
    83  		}
    84  	})
    85  
    86  	t.Run("with nil multierror", func(t *testing.T) {
    87  		var err Multi
    88  		if errors.Unwrap(err) != nil {
    89  			t.Fatal("should be nil")
    90  		}
    91  	})
    92  }
    93  
    94  func TestErrorIs(t *testing.T) {
    95  	errBar := errors.New("bar")
    96  
    97  	t.Run("with errBar", func(t *testing.T) {
    98  		err := Multi([]error{
    99  			errors.New("foo"),
   100  			errBar,
   101  			errors.New("baz"),
   102  		})
   103  
   104  		if !errors.Is(err, errBar) {
   105  			t.Fatal("should be true")
   106  		}
   107  	})
   108  
   109  	t.Run("with errBar wrapped by fmt.Errorf", func(t *testing.T) {
   110  		err := Multi([]error{
   111  			errors.New("foo"),
   112  			fmt.Errorf("errorf: %w", errBar),
   113  			errors.New("baz"),
   114  		})
   115  
   116  		if !errors.Is(err, errBar) {
   117  			t.Fatal("should be true")
   118  		}
   119  	})
   120  
   121  	t.Run("without errBar", func(t *testing.T) {
   122  		err := Multi([]error{
   123  			errors.New("foo"),
   124  			errors.New("baz"),
   125  		})
   126  
   127  		if errors.Is(err, errBar) {
   128  			t.Fatal("should be false")
   129  		}
   130  	})
   131  }
   132  
   133  func TestErrorAs(t *testing.T) {
   134  	match := &nestedError{}
   135  
   136  	t.Run("with the value", func(t *testing.T) {
   137  		err := Multi([]error{
   138  			errors.New("foo"),
   139  			match,
   140  			errors.New("baz"),
   141  		})
   142  
   143  		var target *nestedError
   144  		if !errors.As(err, &target) {
   145  			t.Fatal("should be true")
   146  		}
   147  		if target == nil {
   148  			t.Fatal("target should not be nil")
   149  		}
   150  	})
   151  
   152  	t.Run("with the value wrapped by fmt.Errorf", func(t *testing.T) {
   153  		err := Multi([]error{
   154  			errors.New("foo"),
   155  			fmt.Errorf("errorf: %w", match),
   156  			errors.New("baz"),
   157  		})
   158  
   159  		var target *nestedError
   160  		if !errors.As(err, &target) {
   161  			t.Fatal("should be true")
   162  		}
   163  		if target == nil {
   164  			t.Fatal("target should not be nil")
   165  		}
   166  	})
   167  
   168  	t.Run("without the value", func(t *testing.T) {
   169  		err := Multi([]error{
   170  			errors.New("foo"),
   171  			errors.New("baz"),
   172  		})
   173  
   174  		var target *nestedError
   175  		if errors.As(err, &target) {
   176  			t.Fatal("should be false")
   177  		}
   178  		if target != nil {
   179  			t.Fatal("target should be nil")
   180  		}
   181  	})
   182  }
   183  
   184  // nestedError implements error and is used for tests.
   185  type nestedError struct{}
   186  
   187  func (*nestedError) Error() string { return "" }