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 }