github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/stack/record_test.go (about) 1 package stack 2 3 import ( 4 "reflect" 5 "runtime" 6 "strings" 7 "testing" 8 9 "github.com/stretchr/testify/require" 10 ) 11 12 type testStruct struct { 13 depth int 14 opts []recordOption 15 } 16 17 func (s testStruct) TestFunc() string { 18 return func() string { 19 return Record(s.depth, s.opts...) 20 }() 21 } 22 23 func (s *testStruct) TestPointerFunc() string { 24 return func() string { 25 return Record(s.depth, s.opts...) 26 }() 27 } 28 29 func TestRecord(t *testing.T) { 30 for _, tt := range []struct { 31 act string 32 exp string 33 }{ 34 { 35 act: Record(0), 36 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack.TestRecord(record_test.go:35)", 37 }, 38 { 39 act: func() string { 40 return Record(1) 41 }(), 42 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack.TestRecord(record_test.go:41)", 43 }, 44 { 45 act: func() string { 46 return func() string { 47 return Record(2) 48 }() 49 }(), 50 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack.TestRecord(record_test.go:49)", 51 }, 52 { 53 act: testStruct{depth: 0, opts: []recordOption{ 54 PackagePath(false), 55 PackageName(false), 56 StructName(false), 57 FunctionName(false), 58 Lambda(false), 59 FileName(false), 60 Line(false), 61 }}.TestFunc(), 62 exp: "", 63 }, 64 { 65 act: testStruct{depth: 0, opts: []recordOption{ 66 // PackagePath(false), 67 PackageName(false), 68 StructName(false), 69 FunctionName(false), 70 Lambda(false), 71 FileName(false), 72 Line(false), 73 }}.TestFunc(), 74 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal", 75 }, 76 { 77 act: testStruct{depth: 0, opts: []recordOption{ 78 PackagePath(false), 79 // PackageName(false), 80 StructName(false), 81 FunctionName(false), 82 Lambda(false), 83 FileName(false), 84 Line(false), 85 }}.TestFunc(), 86 exp: "stack", 87 }, 88 { 89 act: testStruct{depth: 0, opts: []recordOption{ 90 PackagePath(false), 91 PackageName(false), 92 // StructName(false), 93 FunctionName(false), 94 Lambda(false), 95 FileName(false), 96 Line(false), 97 }}.TestFunc(), 98 exp: "testStruct", 99 }, 100 { 101 act: testStruct{depth: 0, opts: []recordOption{ 102 PackagePath(false), 103 PackageName(false), 104 StructName(false), 105 // FunctionName(false), 106 Lambda(false), 107 FileName(false), 108 Line(false), 109 }}.TestFunc(), 110 exp: "TestFunc", 111 }, 112 { 113 act: testStruct{depth: 0, opts: []recordOption{ 114 PackagePath(false), 115 PackageName(false), 116 StructName(false), 117 FunctionName(false), 118 // Lambda(false), 119 FileName(false), 120 Line(false), 121 }}.TestFunc(), 122 exp: "", 123 }, 124 { 125 act: testStruct{depth: 0, opts: []recordOption{ 126 PackagePath(false), 127 PackageName(false), 128 StructName(false), 129 // FunctionName(false), 130 // Lambda(false), 131 FileName(false), 132 Line(false), 133 }}.TestFunc(), 134 exp: "TestFunc.func1", 135 }, 136 { 137 act: testStruct{depth: 0, opts: []recordOption{ 138 PackagePath(false), 139 PackageName(false), 140 StructName(false), 141 FunctionName(false), 142 Lambda(false), 143 // FileName(false), 144 Line(false), 145 }}.TestFunc(), 146 exp: "record_test.go", 147 }, 148 { 149 act: testStruct{depth: 0, opts: []recordOption{ 150 PackagePath(false), 151 PackageName(false), 152 StructName(false), 153 FunctionName(false), 154 Lambda(false), 155 FileName(false), 156 // Line(false), 157 }}.TestFunc(), 158 exp: "", 159 }, 160 { 161 act: testStruct{depth: 0, opts: []recordOption{ 162 PackagePath(false), 163 PackageName(false), 164 StructName(false), 165 FunctionName(false), 166 Lambda(false), 167 // FileName(false), 168 // Line(false), 169 }}.TestFunc(), 170 exp: "record_test.go:19", 171 }, 172 { 173 act: testStruct{depth: 0, opts: []recordOption{ 174 // PackagePath(false), 175 // PackageName(false), 176 StructName(false), 177 FunctionName(false), 178 Lambda(false), 179 FileName(false), 180 Line(false), 181 }}.TestFunc(), 182 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack", 183 }, 184 { 185 act: testStruct{depth: 0, opts: []recordOption{ 186 // PackagePath(false), 187 // PackageName(false), 188 // StructName(false), 189 FunctionName(false), 190 Lambda(false), 191 FileName(false), 192 Line(false), 193 }}.TestFunc(), 194 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack.testStruct", 195 }, 196 { 197 act: testStruct{depth: 0, opts: []recordOption{ 198 // PackagePath(false), 199 // PackageName(false), 200 // StructName(false), 201 // FunctionName(false), 202 Lambda(false), 203 FileName(false), 204 Line(false), 205 }}.TestFunc(), 206 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack.testStruct.TestFunc", 207 }, 208 { 209 act: testStruct{depth: 0, opts: []recordOption{ 210 // PackagePath(false), 211 // PackageName(false), 212 // StructName(false), 213 // FunctionName(false), 214 // Lambda(false), 215 FileName(false), 216 Line(false), 217 }}.TestFunc(), 218 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack.testStruct.TestFunc.func1", 219 }, 220 { 221 act: testStruct{depth: 0, opts: []recordOption{ 222 // PackagePath(false), 223 // PackageName(false), 224 // StructName(false), 225 // FunctionName(false), 226 // Lambda(false), 227 // FileName(false), 228 Line(false), 229 }}.TestFunc(), 230 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack.testStruct.TestFunc.func1(record_test.go)", 231 }, 232 { 233 act: testStruct{depth: 0, opts: []recordOption{ 234 // PackagePath(false), 235 // PackageName(false), 236 // StructName(false), 237 // FunctionName(false), 238 // Lambda(false), 239 // FileName(false), 240 // Line(false), 241 }}.TestFunc(), 242 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack.testStruct.TestFunc.func1(record_test.go:19)", 243 }, 244 { 245 act: (&testStruct{depth: 0, opts: []recordOption{ 246 // PackagePath(false), 247 // PackageName(false), 248 // StructName(false), 249 // FunctionName(false), 250 // Lambda(false), 251 // FileName(false), 252 // Line(false), 253 }}).TestPointerFunc(), 254 exp: "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack.(*testStruct).TestPointerFunc.func1(record_test.go:25)", 255 }, 256 } { 257 t.Run("", func(t *testing.T) { 258 require.Equal(t, tt.exp, tt.act) 259 }) 260 } 261 } 262 263 func TestExtractNames(t *testing.T) { 264 testFunc := func() {} 265 funcPtr := reflect.ValueOf(testFunc).Pointer() 266 267 funcNameExpected := runtime.FuncForPC(funcPtr).Name() 268 269 _, file, _, ok := runtime.Caller(0) 270 require.True(t, ok, "runtime.Caller should return true indicating success") 271 272 fileParts := strings.Split(file, "/") 273 fileNameExpected := fileParts[len(fileParts)-1] 274 275 name, fileName := extractName(funcPtr, file) 276 277 require.Equal(t, funcNameExpected, name, "Function name should match expected value") 278 require.Equal(t, fileNameExpected, fileName, "File name should match expected value") 279 } 280 281 func TestParseFunctionName(t *testing.T) { 282 name := "github.com/ydb-platform/ydb-go-sdk/v3/internal/stack.TestParseFunctionName.func1" 283 fnDetails := parseFunctionName(name) 284 285 require.Equal(t, "github.com/ydb-platform/ydb-go-sdk/v3/internal", fnDetails.pkgPath) 286 require.Equal(t, "stack", fnDetails.pkgName) 287 require.Empty(t, fnDetails.structName, "Struct name should be empty for standalone functions") 288 require.Equal(t, "TestParseFunctionName", fnDetails.funcName) 289 require.Contains(t, fnDetails.lambdas, "func1", "Lambdas should include 'func1'") 290 } 291 292 func TestBuildRecordString(t *testing.T) { 293 optionsHolder := recordOptions{ 294 packagePath: true, 295 packageName: false, 296 structName: true, 297 functionName: true, 298 fileName: true, 299 line: true, 300 lambdas: true, 301 } 302 fnDetails := functionDetails{ 303 pkgPath: "github.com/ydb-platform/ydb-go-sdk/v3/internal", 304 pkgName: "", 305 structName: "testStruct", 306 funcName: "TestFunc", 307 308 lambdas: []string{"func1"}, 309 } 310 file := "record_test.go" 311 line := 319 312 313 result := buildRecordString(optionsHolder, &fnDetails, file, line) 314 expected := "github.com/ydb-platform/ydb-go-sdk/v3/internal.testStruct.TestFunc.func1(record_test.go:319)" 315 require.Equal(t, expected, result) 316 } 317 318 func BenchmarkCall(b *testing.B) { 319 b.ReportAllocs() 320 for i := 0; i < b.N; i++ { 321 _ = Call(0) 322 } 323 } 324 325 func BenchmarkRecord(b *testing.B) { 326 b.ReportAllocs() 327 for i := 0; i < b.N; i++ { 328 _ = Record(0) 329 } 330 } 331 332 func BenchmarkCallRecord(b *testing.B) { 333 b.ReportAllocs() 334 for i := 0; i < b.N; i++ { 335 _ = Call(0).Record() 336 } 337 } 338 339 func BenchmarkCallFuncionID(b *testing.B) { 340 b.ReportAllocs() 341 for i := 0; i < b.N; i++ { 342 _ = Call(0).FunctionID() 343 } 344 }