github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/throw/stackcmp_test.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package throw
     7  
     8  import (
     9  	"fmt"
    10  	"runtime"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func tracesLines() []StackTrace {
    18  	return []StackTrace{
    19  		stackTrace{captureStackByDebug(0, false), false},
    20  		stackTrace{captureStackByDebug(0, true), true},
    21  		stackTrace{captureStackByCallers(0, false), false},
    22  		stackTrace{captureStackByCallers(0, true), true},
    23  	}
    24  }
    25  
    26  func tracesCodesAndLines() []StackTrace {
    27  	return []StackTrace{
    28  		// first 2 entries MUST BE on the same line
    29  		stackTrace{captureStackByDebug(0, false), false}, stackTrace{captureStackByDebug(0, false), false},
    30  		stackTrace{captureStackByDebug(0, false), false},
    31  		stackTrace{captureStackByDebug(0, false), false},
    32  		stackTrace{captureStackByDebug(1, false), false},
    33  	}
    34  }
    35  
    36  func TestCompareStackTraceExt(t *testing.T) {
    37  	others := tracesCodesAndLines()
    38  	shorter := others[len(others)-1]
    39  	others = others[:len(others)-1]
    40  
    41  	for i, o := range others {
    42  		for j := i + 1; j < len(others)-1; j++ {
    43  			assert.Equal(t, DifferentStack, CompareStackTraceExt(o, others[j], StrictMatch), i)
    44  			assert.Equal(t, DifferentStack, CompareStackTraceExt(others[j], o, StrictMatch), i)
    45  		}
    46  		assert.Equal(t, SubsetStack, CompareStackTraceExt(shorter, o, StrictMatch), i)
    47  		assert.Equal(t, SupersetStack, CompareStackTraceExt(o, shorter, StrictMatch), i)
    48  	}
    49  
    50  	for i, o := range others {
    51  		assert.Equal(t, SubsetStack, CompareStackTraceExt(shorter, o, SameLine), i)
    52  		assert.Equal(t, SupersetStack, CompareStackTraceExt(o, shorter, SameLine), i)
    53  	}
    54  
    55  	for i, o := range others {
    56  		assert.Equal(t, SubsetStack, CompareStackTraceExt(shorter, o, SameMethod), i)
    57  		assert.Equal(t, SupersetStack, CompareStackTraceExt(o, shorter, SameMethod), i)
    58  	}
    59  
    60  	assert.Equal(t, SupersetStack, CompareStackTraceExt(others[0], others[1], SameLine))
    61  	assert.Equal(t, SubsetStack, CompareStackTraceExt(others[1], others[0], SameLine))
    62  	assert.Equal(t, DifferentStack, CompareStackTraceExt(others[2], others[3], SameLine))
    63  	assert.Equal(t, DifferentStack, CompareStackTraceExt(others[3], others[2], SameLine))
    64  
    65  	assert.Equal(t, SupersetStack, CompareStackTraceExt(others[0], others[1], SameMethod))
    66  	assert.Equal(t, SubsetStack, CompareStackTraceExt(others[1], others[0], SameMethod))
    67  	assert.Equal(t, SupersetStack, CompareStackTraceExt(others[2], others[3], SameMethod))
    68  	assert.Equal(t, SubsetStack, CompareStackTraceExt(others[3], others[2], SameMethod))
    69  }
    70  
    71  func TestCompareStackTrace(t *testing.T) {
    72  	others := tracesLines()
    73  
    74  	for i, o := range others {
    75  		for j := i + 1; j < len(others); j++ {
    76  			assert.Equal(t, DifferentStack, CompareStackTrace(o, others[j]))
    77  			assert.Equal(t, DifferentStack, CompareStackTrace(others[j], o))
    78  		}
    79  	}
    80  
    81  	for n, tt := range []struct {
    82  		fn0, fn1 stackCaptureFunc
    83  	}{
    84  		{captureStackByDebug, captureStackByDebug},
    85  		{captureStackByCallers, captureStackByCallers},
    86  		{captureStackByCallers, captureStackByDebug},
    87  		// Not supported - { captureStackByDebug, captureStackByCallers },
    88  	} {
    89  		for i := 0; i <= 1; i++ {
    90  			var top, full StackTrace
    91  			getFn := getTraces
    92  			skipFrames := 1
    93  			if i != 0 {
    94  				getFn = getDeferTraces
    95  				skipFrames++ // to avoid catching different line of getFn calls
    96  			}
    97  			top, full = getFn(0, tt.fn0, tt.fn1)
    98  			_, full1 := getFn(skipFrames, tt.fn0, tt.fn1)
    99  
   100  			t.Run(fmt.Sprint(n, i), func(t *testing.T) {
   101  				{
   102  					require.Equal(t, SupersetStack, CompareStackTrace(full, full1))
   103  					require.Equal(t, SubsetStack, CompareStackTrace(full1, full))
   104  				}
   105  
   106  				assert.Equal(t, EqualStack, CompareStackTrace(top, top))
   107  				assert.Equal(t, EqualStack, CompareStackTrace(full, full))
   108  
   109  				assert.Equal(t, StackTop, CompareStackTrace(top, full))
   110  				assert.Equal(t, FullStack, CompareStackTrace(full, top))
   111  
   112  				for i, o := range others {
   113  					assert.Equal(t, DifferentStack, CompareStackTrace(o, top), i)
   114  					assert.Equal(t, DifferentStack, CompareStackTrace(top, o), i)
   115  					assert.Equal(t, DifferentStack, CompareStackTrace(o, full), i)
   116  					assert.Equal(t, DifferentStack, CompareStackTrace(full, o), i)
   117  				}
   118  			})
   119  		}
   120  	}
   121  }
   122  
   123  type stackCaptureFunc = func(skipFrames int, limitFrames bool) []byte
   124  
   125  func getTraces(skipFrames int, fn0, fn1 stackCaptureFunc) (StackTrace, StackTrace) {
   126  	skipFrames++
   127  	return stackTrace{fn0(skipFrames, true), true}, stackTrace{fn1(skipFrames, false), false}
   128  }
   129  
   130  func getDeferTraces(skipFrames int, fn0, fn1 stackCaptureFunc) (st0 StackTrace, st1 StackTrace) {
   131  	skipFrames++
   132  	defer func() {
   133  		st0, st1 = stackTrace{fn0(skipFrames, true), true}, stackTrace{fn1(skipFrames, false), false}
   134  	}()
   135  	runtime.Gosched() // just to do something
   136  	return
   137  }
   138  
   139  func TestExtractStackTop(t *testing.T) {
   140  	st := stackTrace{data: []byte(testStackDebug)}
   141  	require.Equal(t, testStackDebugCall, ExtractStackTop(st, 0).StackTraceAsText())
   142  	require.Equal(t, testStackValuableOnce, ExtractStackTop(st, 1).StackTraceAsText())
   143  	require.Equal(t, testCreatedBy, ExtractStackTop(st, 99).StackTraceAsText())
   144  
   145  	st.data = []byte(testStackValuableOnce)
   146  
   147  	require.Equal(t, testStackValuableOnce, ExtractStackTop(st, 0).StackTraceAsText())
   148  	require.Equal(t, testStackValuableOnce, ExtractStackTop(st, 1).StackTraceAsText())
   149  	require.Equal(t, testStackValuableOnce, ExtractStackTop(st, 99).StackTraceAsText())
   150  
   151  	st.limit = true
   152  
   153  	require.Equal(t, testStackValuableOnce, ExtractStackTop(st, 0).StackTraceAsText())
   154  	require.Equal(t, testStackValuableOnce, ExtractStackTop(st, 1).StackTraceAsText())
   155  	require.Equal(t, testStackValuableOnce, ExtractStackTop(st, 99).StackTraceAsText())
   156  }