github.com/cloudwego/kitex@v0.9.0/pkg/kerrors/kerrors_test.go (about)

     1  /*
     2   * Copyright 2021 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package kerrors
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"os"
    24  	"runtime/debug"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/cloudwego/kitex/internal/test"
    29  )
    30  
    31  func TestIsKitexError(t *testing.T) {
    32  	errs := []error{
    33  		ErrInternalException,
    34  		ErrServiceDiscovery,
    35  		ErrGetConnection,
    36  		ErrLoadbalance,
    37  		ErrRPCTimeout,
    38  		ErrACL,
    39  		ErrCircuitBreak,
    40  		ErrRemoteOrNetwork,
    41  		ErrOverlimit,
    42  		ErrNotSupported,
    43  		ErrNoResolver,
    44  		ErrNoDestService,
    45  		ErrNoDestAddress,
    46  		ErrNoConnection,
    47  		ErrNoMoreInstance,
    48  		ErrConnOverLimit,
    49  		ErrQPSOverLimit,
    50  	}
    51  	for _, e := range errs {
    52  		test.Assert(t, IsKitexError(e))
    53  	}
    54  
    55  	e := errors.New("any error")
    56  	test.Assert(t, !IsKitexError(e))
    57  
    58  	e = ErrInternalException.WithCause(e)
    59  	test.Assert(t, IsKitexError(e))
    60  }
    61  
    62  func TestIs(t *testing.T) {
    63  	any := errors.New("any error")
    64  
    65  	test.Assert(t, !errors.Is(any, ErrACL))
    66  
    67  	var e error
    68  	e = ErrACL
    69  	test.Assert(t, errors.Is(e, ErrACL))
    70  
    71  	e = ErrACL.WithCause(any)
    72  	test.Assert(t, errors.Is(e, ErrACL))
    73  	test.Assert(t, errors.Is(e, any))
    74  }
    75  
    76  func TestError(t *testing.T) {
    77  	basic := "basic"
    78  	extra := "extra"
    79  	be := &basicError{basic}
    80  	test.Assert(t, be.Error() == basic)
    81  	detailedMsg := appendErrMsg(basic, extra)
    82  	test.Assert(t, (&DetailedError{basic: be, extraMsg: extra}).Error() == detailedMsg)
    83  }
    84  
    85  func TestWithCause(t *testing.T) {
    86  	ae := errors.New("any error")
    87  	be := &basicError{"basic"}
    88  	de := be.WithCause(ae)
    89  
    90  	test.Assert(t, be.Error() == "basic")
    91  	test.Assert(t, strings.HasPrefix(de.Error(), be.Error()))
    92  	test.Assert(t, strings.HasSuffix(de.Error(), ae.Error()))
    93  
    94  	xe, ok := de.(interface{ ErrorType() error })
    95  	test.Assert(t, ok)
    96  	test.Assert(t, xe.ErrorType() == be)
    97  
    98  	ye, ok := de.(interface{ Unwrap() error })
    99  	test.Assert(t, ok)
   100  	test.Assert(t, ye.Unwrap() == ae)
   101  }
   102  
   103  func TestWithCauseAndStack(t *testing.T) {
   104  	ae := errors.New("any error")
   105  	be := &basicError{"basic"}
   106  	stack := string(debug.Stack())
   107  	de := be.WithCauseAndStack(ae, stack)
   108  
   109  	test.Assert(t, be.Error() == "basic")
   110  	test.Assert(t, strings.HasPrefix(de.Error(), be.Error()))
   111  	test.Assert(t, strings.HasSuffix(de.Error(), ae.Error()))
   112  
   113  	xe, ok := de.(interface{ ErrorType() error })
   114  	test.Assert(t, ok)
   115  	test.Assert(t, xe.ErrorType() == be)
   116  
   117  	ye, ok := de.(interface{ Unwrap() error })
   118  	test.Assert(t, ok)
   119  	test.Assert(t, ye.Unwrap() == ae)
   120  
   121  	se, ok := de.(interface{ Stack() string })
   122  	test.Assert(t, ok)
   123  	test.Assert(t, se.Stack() == stack)
   124  }
   125  
   126  type timeoutError struct{}
   127  
   128  func (te *timeoutError) Error() string { return "timeout" }
   129  func (te *timeoutError) Timeout() bool { return true }
   130  
   131  func TestTimeout(t *testing.T) {
   132  	var ae, ke error
   133  	ae = errors.New("any error")
   134  	osCheck := func(err error) bool {
   135  		return os.IsTimeout(err)
   136  	}
   137  
   138  	ke = &basicError{"non-timeout"}
   139  	TimeoutCheckFunc = osCheck
   140  	test.Assert(t, !IsTimeoutError(ke))
   141  	TimeoutCheckFunc = nil
   142  	test.Assert(t, !IsTimeoutError(ke))
   143  
   144  	ke = ErrRPCTimeout
   145  	TimeoutCheckFunc = osCheck
   146  	test.Assert(t, IsTimeoutError(ke))
   147  	TimeoutCheckFunc = nil
   148  	test.Assert(t, IsTimeoutError(ke))
   149  
   150  	ke = ErrRPCTimeout.WithCause(ae)
   151  	TimeoutCheckFunc = osCheck
   152  	test.Assert(t, IsTimeoutError(ke))
   153  	TimeoutCheckFunc = nil
   154  	test.Assert(t, IsTimeoutError(ke))
   155  
   156  	ke = ErrOverlimit.WithCause(ae)
   157  	TimeoutCheckFunc = osCheck
   158  	test.Assert(t, !IsTimeoutError(ke))
   159  	TimeoutCheckFunc = nil
   160  	test.Assert(t, !IsTimeoutError(ke))
   161  
   162  	ae = &timeoutError{}
   163  	TimeoutCheckFunc = osCheck
   164  	test.Assert(t, IsTimeoutError(ae))
   165  	TimeoutCheckFunc = nil
   166  	test.Assert(t, !IsTimeoutError(ae))
   167  
   168  	ke = ErrOverlimit.WithCause(ae)
   169  	TimeoutCheckFunc = osCheck
   170  	test.Assert(t, IsTimeoutError(ke))
   171  	TimeoutCheckFunc = nil
   172  	test.Assert(t, !IsTimeoutError(ke))
   173  }
   174  
   175  func TestWithCause1(t *testing.T) {
   176  	ae := &basicError{"basic"}
   177  	be := ErrRPCTimeout.WithCause(ae)
   178  	if e2, ok := be.(*DetailedError); ok {
   179  		e2.WithExtraMsg("retry circuite break")
   180  	}
   181  	test.Assert(t, be.Error() == "rpc timeout[retry circuite break]: basic", be)
   182  }
   183  
   184  type _err struct {
   185  	error
   186  }
   187  
   188  // Format the error.
   189  func (de *_err) Format(s fmt.State, verb rune) {
   190  	switch verb {
   191  	case 'v':
   192  		if s.Flag('+') {
   193  			_, _ = io.WriteString(s, "some message only when v+")
   194  			return
   195  		}
   196  		fallthrough
   197  	case 's', 'q':
   198  		_, _ = io.WriteString(s, de.Error())
   199  	}
   200  }
   201  
   202  func TestFormat(t *testing.T) {
   203  	businessError := &_err{
   204  		error: errors.New("some_business_error"),
   205  	}
   206  	basicErr := &basicError{
   207  		message: "fake_msg",
   208  	}
   209  	err := basicErr.WithCause(businessError)
   210  	got := fmt.Sprintf("%+v", err)
   211  	test.Assert(t, got == "fake_msg: some message only when v+")
   212  
   213  	got = fmt.Sprintf("%v", err)
   214  	test.Assert(t, got == "fake_msg: some_business_error")
   215  }
   216  
   217  func BenchmarkWithCause3(b *testing.B) {
   218  	b.ReportAllocs()
   219  	b.ResetTimer()
   220  	for i := 0; i < b.N; i++ {
   221  		ae := &basicError{"basic"}
   222  		be := ErrRPCTimeout.WithCause(ae)
   223  		if e2, ok := be.(*DetailedError); ok {
   224  			e2.WithExtraMsg("测试")
   225  		}
   226  	}
   227  }