github.com/timandy/routine@v1.1.4-0.20240507073150-e4a3e1fe2ba5/error_test.go (about)

     1  package routine
     2  
     3  import (
     4  	"errors"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func TestRuntimeError_Goid(t *testing.T) {
    12  	goid := Goid()
    13  	err := NewRuntimeError(nil)
    14  	assert.Equal(t, goid, err.Goid())
    15  	task := GoWait(func(token CancelToken) {
    16  		assert.Equal(t, goid, err.Goid())
    17  		assert.NotEqual(t, Goid(), err.Goid())
    18  	})
    19  	task.Get()
    20  }
    21  
    22  func TestRuntimeError_Gopc(t *testing.T) {
    23  	gopc := *getg().gopc
    24  	err := NewRuntimeError(nil)
    25  	assert.Equal(t, gopc, err.Gopc())
    26  	task := GoWait(func(token CancelToken) {
    27  		assert.Equal(t, gopc, err.Gopc())
    28  		assert.NotEqual(t, *getg().gopc, err.Gopc())
    29  	})
    30  	task.Get()
    31  }
    32  
    33  func TestRuntimeError_Message(t *testing.T) {
    34  	err := NewRuntimeError(nil)
    35  	assert.Equal(t, "", err.Message())
    36  
    37  	err2 := NewRuntimeError("Hello")
    38  	assert.Equal(t, "Hello", err2.Message())
    39  
    40  	err3 := NewRuntimeError(&person{Id: 1, Name: "Tim"})
    41  	assert.Equal(t, "&{1 Tim}", err3.Message())
    42  }
    43  
    44  func TestRuntimeError_StackTrace(t *testing.T) {
    45  	err := NewRuntimeError(nil)
    46  	stackTrace := err.StackTrace()
    47  	capturedStackTrace := captureStackTrace(0, 200)
    48  	for i := 1; i < len(stackTrace); i++ {
    49  		assert.Equal(t, capturedStackTrace[i], stackTrace[i])
    50  	}
    51  }
    52  
    53  func TestRuntimeError_Panic_Panic(t *testing.T) {
    54  	defer func() {
    55  		cause := recover()
    56  		assert.NotNil(t, cause)
    57  		err := NewRuntimeError(cause)
    58  		lines := strings.Split(err.Error(), newLine)
    59  		assert.Equal(t, 6, len(lines))
    60  		//
    61  		line := lines[0]
    62  		assert.Equal(t, "RuntimeError: 1", line)
    63  		//
    64  		line = lines[1]
    65  		assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestRuntimeError_Panic_Panic."))
    66  		assert.True(t, strings.HasSuffix(line, "error_test.go:74"))
    67  		//
    68  		line = lines[2]
    69  		assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestRuntimeError_Panic_Panic()"))
    70  		assert.True(t, strings.HasSuffix(line, "error_test.go:77"))
    71  	}()
    72  	defer func() {
    73  		if cause := recover(); cause != nil {
    74  			panic(cause)
    75  		}
    76  	}()
    77  	panic(1)
    78  }
    79  
    80  func TestRuntimeError_Cause(t *testing.T) {
    81  	err := NewRuntimeError(nil)
    82  	assert.Nil(t, err.Cause())
    83  
    84  	err2 := NewRuntimeError(errors.New("error"))
    85  	assert.Nil(t, err2.Cause())
    86  
    87  	err3 := NewRuntimeError(&person{Id: 1, Name: "Tim"})
    88  	assert.Nil(t, err3.Cause())
    89  
    90  	err4 := NewRuntimeError(err)
    91  	assert.Same(t, err, err4.Cause())
    92  }
    93  
    94  func TestRuntimeError_Error_EmptyMessage_NilError(t *testing.T) {
    95  	err := NewRuntimeErrorWithMessageCause("", nil)
    96  	lines := strings.Split(err.Error(), newLine)
    97  	assert.Equal(t, 5, len(lines))
    98  	//
    99  	line := lines[0]
   100  	assert.Equal(t, "RuntimeError", line)
   101  	//
   102  	line = lines[1]
   103  	assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestRuntimeError_Error_EmptyMessage_NilError() in "))
   104  	assert.True(t, strings.HasSuffix(line, "error_test.go:95"))
   105  	//
   106  	line = lines[2]
   107  	assert.True(t, strings.HasPrefix(line, "   at testing.tRunner() in "))
   108  	//
   109  	line = lines[3]
   110  	assert.Equal(t, "   --- End of error stack trace ---", line)
   111  	//
   112  	line = lines[4]
   113  	assert.True(t, strings.HasPrefix(line, "   created by testing.(*T).Run() in "))
   114  }
   115  
   116  func TestRuntimeError_Error_EmptyMessage_NormalError(t *testing.T) {
   117  	cause := NewRuntimeError("this is inner error")
   118  	err := NewRuntimeErrorWithMessageCause("", cause)
   119  	lines := strings.Split(err.Error(), newLine)
   120  	assert.Equal(t, 9, len(lines))
   121  	//
   122  	line := lines[0]
   123  	assert.Equal(t, "RuntimeError", line)
   124  	//
   125  	line = lines[1]
   126  	assert.Equal(t, " ---> RuntimeError: this is inner error", line)
   127  	//
   128  	line = lines[2]
   129  	assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestRuntimeError_Error_EmptyMessage_NormalError() in "))
   130  	assert.True(t, strings.HasSuffix(line, "error_test.go:117"))
   131  	//
   132  	line = lines[3]
   133  	assert.True(t, strings.HasPrefix(line, "   at testing.tRunner() in "))
   134  	//
   135  	line = lines[4]
   136  	assert.Equal(t, "   --- End of inner error stack trace ---", line)
   137  	//
   138  	line = lines[5]
   139  	assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestRuntimeError_Error_EmptyMessage_NormalError() in "))
   140  	assert.True(t, strings.HasSuffix(line, "error_test.go:118"))
   141  	//
   142  	line = lines[6]
   143  	assert.True(t, strings.HasPrefix(line, "   at testing.tRunner() in "))
   144  	//
   145  	line = lines[7]
   146  	assert.Equal(t, "   --- End of error stack trace ---", line)
   147  	//
   148  	line = lines[8]
   149  	assert.True(t, strings.HasPrefix(line, "   created by testing.(*T).Run() in "))
   150  }
   151  
   152  func TestRuntimeError_Error_NormalMessage_NilError(t *testing.T) {
   153  	err := NewRuntimeErrorWithMessageCause("this is error message", nil)
   154  	lines := strings.Split(err.Error(), newLine)
   155  	assert.Equal(t, 5, len(lines))
   156  	//
   157  	line := lines[0]
   158  	assert.Equal(t, "RuntimeError: this is error message", line)
   159  	//
   160  	line = lines[1]
   161  	assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestRuntimeError_Error_NormalMessage_NilError() in "))
   162  	assert.True(t, strings.HasSuffix(line, "error_test.go:153"))
   163  	//
   164  	line = lines[2]
   165  	assert.True(t, strings.HasPrefix(line, "   at testing.tRunner() in "))
   166  	//
   167  	line = lines[3]
   168  	assert.Equal(t, "   --- End of error stack trace ---", line)
   169  	//
   170  	line = lines[4]
   171  	assert.True(t, strings.HasPrefix(line, "   created by testing.(*T).Run() in "))
   172  }
   173  
   174  func TestRuntimeError_Error_NormalMessage_NormalError(t *testing.T) {
   175  	cause := NewRuntimeError("this is inner error")
   176  	err := NewRuntimeErrorWithMessageCause("this is error message", cause)
   177  	lines := strings.Split(err.Error(), newLine)
   178  	assert.Equal(t, 9, len(lines))
   179  	//
   180  	line := lines[0]
   181  	assert.Equal(t, "RuntimeError: this is error message", line)
   182  	//
   183  	line = lines[1]
   184  	assert.Equal(t, " ---> RuntimeError: this is inner error", line)
   185  	//
   186  	line = lines[2]
   187  	assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestRuntimeError_Error_NormalMessage_NormalError() in "))
   188  	assert.True(t, strings.HasSuffix(line, "error_test.go:175"))
   189  	//
   190  	line = lines[3]
   191  	assert.True(t, strings.HasPrefix(line, "   at testing.tRunner() in "))
   192  	//
   193  	line = lines[4]
   194  	assert.Equal(t, "   --- End of inner error stack trace ---", line)
   195  	//
   196  	line = lines[5]
   197  	assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestRuntimeError_Error_NormalMessage_NormalError() in "))
   198  	assert.True(t, strings.HasSuffix(line, "error_test.go:176"))
   199  	//
   200  	line = lines[6]
   201  	assert.True(t, strings.HasPrefix(line, "   at testing.tRunner() in "))
   202  	//
   203  	line = lines[7]
   204  	assert.Equal(t, "   --- End of error stack trace ---", line)
   205  	//
   206  	line = lines[8]
   207  	assert.True(t, strings.HasPrefix(line, "   created by testing.(*T).Run() in "))
   208  }
   209  
   210  func TestRuntimeError_Error_NilStackTrace(t *testing.T) {
   211  	cause := NewRuntimeError("this is inner error")
   212  	cause.(*runtimeError).stackTrace = nil
   213  	err := NewRuntimeErrorWithMessageCause("this is error message", cause)
   214  	err.(*runtimeError).stackTrace = nil
   215  	lines := strings.Split(err.Error(), newLine)
   216  	assert.Equal(t, 5, len(lines))
   217  	//
   218  	line := lines[0]
   219  	assert.Equal(t, "RuntimeError: this is error message", line)
   220  	//
   221  	line = lines[1]
   222  	assert.Equal(t, " ---> RuntimeError: this is inner error", line)
   223  	//
   224  	line = lines[2]
   225  	assert.Equal(t, "   --- End of inner error stack trace ---", line)
   226  	//
   227  	line = lines[3]
   228  	assert.Equal(t, "   --- End of error stack trace ---", line)
   229  	//
   230  	line = lines[4]
   231  	assert.True(t, strings.HasPrefix(line, "   created by testing.(*T).Run() in "))
   232  }
   233  
   234  func TestRuntimeError_Error_MainGoid(t *testing.T) {
   235  	err := NewRuntimeErrorWithMessageCause("this is error message", nil)
   236  	err.(*runtimeError).goid = 1
   237  	lines := strings.Split(err.Error(), newLine)
   238  	assert.Equal(t, 3, len(lines))
   239  	//
   240  	line := lines[0]
   241  	assert.Equal(t, "RuntimeError: this is error message", line)
   242  	//
   243  	line = lines[1]
   244  	assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestRuntimeError_Error_MainGoid() in "))
   245  	assert.True(t, strings.HasSuffix(line, "error_test.go:235"))
   246  	//
   247  	line = lines[2]
   248  	assert.True(t, strings.HasPrefix(line, "   at testing.tRunner() in "))
   249  }
   250  
   251  func TestRuntimeError_Error_ZeroGopc(t *testing.T) {
   252  	err := NewRuntimeErrorWithMessageCause("this is error message", nil)
   253  	err.(*runtimeError).gopc = 0
   254  	lines := strings.Split(err.Error(), newLine)
   255  	assert.Equal(t, 3, len(lines))
   256  	//
   257  	line := lines[0]
   258  	assert.Equal(t, "RuntimeError: this is error message", line)
   259  	//
   260  	line = lines[1]
   261  	assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestRuntimeError_Error_ZeroGopc() in "))
   262  	assert.True(t, strings.HasSuffix(line, "error_test.go:252"))
   263  	//
   264  	line = lines[2]
   265  	assert.True(t, strings.HasPrefix(line, "   at testing.tRunner() in "))
   266  }
   267  
   268  func TestArgumentNilError_Goid(t *testing.T) {
   269  	goid := Goid()
   270  	err := NewArgumentNilError("number", nil)
   271  	assert.Equal(t, goid, err.Goid())
   272  	task := GoWait(func(token CancelToken) {
   273  		assert.Equal(t, goid, err.Goid())
   274  		assert.NotEqual(t, Goid(), err.Goid())
   275  	})
   276  	task.Get()
   277  }
   278  
   279  func TestArgumentNilError_Gopc(t *testing.T) {
   280  	gopc := *getg().gopc
   281  	err := NewArgumentNilError("number", nil)
   282  	assert.Equal(t, gopc, err.Gopc())
   283  	task := GoWait(func(token CancelToken) {
   284  		assert.Equal(t, gopc, err.Gopc())
   285  		assert.NotEqual(t, *getg().gopc, err.Gopc())
   286  	})
   287  	task.Get()
   288  }
   289  
   290  func TestArgumentNilError_Message(t *testing.T) {
   291  	err := NewArgumentNilError("", nil)
   292  	assert.Equal(t, "Value cannot be null.", err.Message())
   293  
   294  	err2 := NewArgumentNilError("", "Hello")
   295  	assert.Equal(t, "Hello", err2.Message())
   296  
   297  	err3 := NewArgumentNilError("number", nil)
   298  	assert.Equal(t, "Value cannot be null."+newLine+"Parameter name: number.", err3.Message())
   299  
   300  	err4 := NewArgumentNilError("number", "Hello")
   301  	assert.Equal(t, "Hello"+newLine+"Parameter name: number.", err4.Message())
   302  }
   303  
   304  func TestArgumentNilError_StackTrace(t *testing.T) {
   305  	err := NewArgumentNilError("", nil)
   306  	stackTrace := err.StackTrace()
   307  	capturedStackTrace := captureStackTrace(0, 200)
   308  	for i := 1; i < len(stackTrace); i++ {
   309  		assert.Equal(t, capturedStackTrace[i], stackTrace[i])
   310  	}
   311  }
   312  
   313  func TestArgumentNilError_Panic_Panic(t *testing.T) {
   314  	defer func() {
   315  		cause := recover()
   316  		assert.NotNil(t, cause)
   317  		err := NewArgumentNilError("a", nil)
   318  		lines := strings.Split(err.Error(), newLine)
   319  		assert.Equal(t, 7, len(lines))
   320  		//
   321  		line := lines[0]
   322  		assert.Equal(t, "ArgumentNilError: Value cannot be null.", line)
   323  		//
   324  		line = lines[1]
   325  		assert.Equal(t, "Parameter name: a.", line)
   326  		//
   327  		line = lines[2]
   328  		assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestArgumentNilError_Panic_Panic."))
   329  		assert.True(t, strings.HasSuffix(line, "error_test.go:337"))
   330  		//
   331  		line = lines[3]
   332  		assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestArgumentNilError_Panic_Panic()"))
   333  		assert.True(t, strings.HasSuffix(line, "error_test.go:341"))
   334  	}()
   335  	defer func() {
   336  		if cause := recover(); cause != nil {
   337  			panic(cause)
   338  		}
   339  	}()
   340  	var a any
   341  	_ = a.(string)
   342  }
   343  
   344  func TestArgumentNilError_Cause(t *testing.T) {
   345  	err := NewArgumentNilError("", nil)
   346  	assert.Nil(t, err.Cause())
   347  
   348  	err2 := NewArgumentNilError("", errors.New("error"))
   349  	assert.Nil(t, err2.Cause())
   350  
   351  	err3 := NewArgumentNilError("", &person{Id: 1, Name: "Tim"})
   352  	assert.Nil(t, err3.Cause())
   353  
   354  	err4 := NewArgumentNilError("", err)
   355  	assert.Same(t, err, err4.Cause())
   356  }
   357  
   358  func TestArgumentNilError_Error(t *testing.T) {
   359  	cause := NewRuntimeError("this is inner error")
   360  	err := NewArgumentNilError("number", cause)
   361  	lines := strings.Split(err.Error(), newLine)
   362  	assert.Equal(t, 10, len(lines))
   363  	//
   364  	line := lines[0]
   365  	assert.Equal(t, "ArgumentNilError: Value cannot be null.", line)
   366  	//
   367  	line = lines[1]
   368  	assert.Equal(t, "Parameter name: number.", line)
   369  	//
   370  	line = lines[2]
   371  	assert.Equal(t, " ---> RuntimeError: this is inner error", line)
   372  	//
   373  	line = lines[3]
   374  	assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestArgumentNilError_Error() in "))
   375  	assert.True(t, strings.HasSuffix(line, "error_test.go:359"))
   376  	//
   377  	line = lines[4]
   378  	assert.True(t, strings.HasPrefix(line, "   at testing.tRunner() in "))
   379  	//
   380  	line = lines[5]
   381  	assert.Equal(t, "   --- End of inner error stack trace ---", line)
   382  	//
   383  	line = lines[6]
   384  	assert.True(t, strings.HasPrefix(line, "   at github.com/timandy/routine.TestArgumentNilError_Error() in "))
   385  	assert.True(t, strings.HasSuffix(line, "error_test.go:360"))
   386  	//
   387  	line = lines[7]
   388  	assert.True(t, strings.HasPrefix(line, "   at testing.tRunner() in "))
   389  	//
   390  	line = lines[8]
   391  	assert.Equal(t, "   --- End of error stack trace ---", line)
   392  	//
   393  	line = lines[9]
   394  	assert.True(t, strings.HasPrefix(line, "   created by testing.(*T).Run() in "))
   395  }
   396  
   397  func TestArgumentNilError_ParamName(t *testing.T) {
   398  	err := NewArgumentNilError("", nil)
   399  	assert.Equal(t, "", err.ParamName())
   400  
   401  	err2 := NewArgumentNilError("number", nil)
   402  	assert.Equal(t, "number", err2.ParamName())
   403  }
   404  
   405  type ArgumentNilError struct {
   406  	goid       int64
   407  	gopc       uintptr
   408  	message    string
   409  	stackTrace []uintptr
   410  	cause      RuntimeError
   411  	paramName  string
   412  }
   413  
   414  func (ae *ArgumentNilError) Goid() int64 {
   415  	return ae.goid
   416  }
   417  
   418  func (ae *ArgumentNilError) Gopc() uintptr {
   419  	return ae.gopc
   420  }
   421  
   422  func (ae *ArgumentNilError) Message() string {
   423  	builder := &strings.Builder{}
   424  	if len(ae.message) == 0 {
   425  		builder.WriteString("Value cannot be null.")
   426  	} else {
   427  		builder.WriteString(ae.message)
   428  	}
   429  	if len(ae.paramName) != 0 {
   430  		builder.WriteString(newLine)
   431  		builder.WriteString("Parameter name: ")
   432  		builder.WriteString(ae.paramName)
   433  		builder.WriteString(".")
   434  	}
   435  	return builder.String()
   436  }
   437  
   438  func (ae *ArgumentNilError) StackTrace() []uintptr {
   439  	return ae.stackTrace
   440  }
   441  
   442  func (ae *ArgumentNilError) Cause() RuntimeError {
   443  	return ae.cause
   444  }
   445  
   446  func (ae *ArgumentNilError) Error() string {
   447  	return runtimeErrorError(ae)
   448  }
   449  
   450  func (ae *ArgumentNilError) ParamName() string {
   451  	return ae.paramName
   452  }
   453  
   454  func NewArgumentNilError(paramName string, cause any) *ArgumentNilError {
   455  	goid, gopc, msg, stackTrace, innerErr := runtimeErrorNew(cause)
   456  	return &ArgumentNilError{goid: goid, gopc: gopc, message: msg, paramName: paramName, stackTrace: stackTrace, cause: innerErr}
   457  }