github.com/tencent/goom@v1.0.1/internal/proxy/func_fixins_test.go (about) 1 package proxy 2 3 import ( 4 "fmt" 5 "math/rand" 6 "runtime/debug" 7 "testing" 8 9 "github.com/tencent/goom/internal/logger" 10 ) 11 12 // Caller 测试函数 13 // 14 //go:noinline 15 func Caller(i int) int { 16 if i <= 0 { 17 return 1 18 } 19 return i * Caller(i-1) 20 } 21 22 // Caller1 测试函数 23 // 24 //go:noinline 25 func Caller1(i int) int { 26 if i <= 0 { 27 return 1 28 } 29 return i 30 } 31 32 // Caller2 测试函数 33 // 34 //go:noinline 35 func Caller2(i int) int { 36 for j := 0; j < 10; j++ { 37 i += j 38 } 39 return i 40 } 41 42 // Arg 测试参数 43 type Arg struct { 44 field1 string 45 field2 map[string]int 46 } 47 48 // Caller3 测试函数 49 // 50 //go:noinline 51 func Caller3(arg Arg) int { 52 //if len(arg.field2) > 0 { 53 // fmt.Println(len(arg.field2)) 54 //} 55 return 2 + len(arg.field1) + len(arg.field2) 56 } 57 58 // Caller4 测试函数 59 // 60 //go:noinline 61 func Caller4(arg *Arg) int { 62 return 0 63 } 64 65 // Caller5 测试函数 66 // 67 //go:noinline 68 func Caller5() int { 69 logger.Trace(string(debug.Stack())) 70 return 0 71 } 72 73 // Caller6 测试函数 74 // 75 //go:noinline 76 func Caller6(a int) func() int { 77 return func() int { 78 return a + 1 79 } 80 } 81 82 // Caller7 测试函数 83 // 84 //go:noinline 85 func Caller7(i int) { 86 } 87 88 // Caller8 测试函数 89 // nolint 90 // 91 //go:noinline 92 func Caller8(i int) int { 93 tag: 94 return i 95 tag1: 96 return -i 97 if i < 0 { 98 goto tag 99 } else { 100 goto tag1 101 } 102 } 103 104 var testCases1 = []struct { 105 funcName string 106 funcDef interface{} 107 eval func(t *testing.T) 108 trampoline func() interface{} 109 proxy func(interface{}) interface{} 110 wantError bool 111 }{ 112 { 113 funcName: "Caller", 114 funcDef: Caller, 115 eval: func(t *testing.T) { 116 if r := Caller(5); r != 120 { 117 t.Fatalf("want result: %d, real: %d", 120, r) 118 } 119 }, 120 trampoline: func() interface{} { 121 var result = func(i int) int { 122 fmt.Println("trampoline") 123 return i + 10 124 } 125 return &result 126 }, 127 proxy: func(origin interface{}) interface{} { 128 return func(i int) int { 129 logger.Trace("proxy Caller called, args", i) 130 originFunc, _ := origin.(*func(i int) int) 131 return (*originFunc)(i) 132 } 133 }, 134 }, 135 { 136 funcName: "Caller1", 137 funcDef: Caller1, 138 eval: func(t *testing.T) { 139 if r := Caller1(-1); r != 1 { 140 t.Fatalf("want result: %d, real: %d", 1, r) 141 } 142 }, 143 trampoline: func() interface{} { 144 var result = func(i int) int { 145 fmt.Println("trampoline") 146 return i + 20 147 } 148 return &result 149 }, 150 proxy: func(origin interface{}) interface{} { 151 var origin1 = origin 152 return func(i int) int { 153 logger.Trace("proxy Caller1 called, args", i) 154 originFunc, _ := origin1.(*func(i int) int) 155 return (*originFunc)(i) 156 } 157 }, 158 }, 159 { 160 funcName: "Caller2", 161 funcDef: Caller2, 162 wantError: true, 163 eval: func(t *testing.T) { 164 if r := Caller2(5); r != 50 { 165 t.Fatalf("want result: %d, real: %d", 50, r) 166 } 167 168 }, 169 trampoline: func() interface{} { 170 var result = func(i int) int { 171 fmt.Println("trampoline") 172 return i + 30 173 } 174 return &result 175 }, 176 proxy: func(origin interface{}) interface{} { 177 var origin1 = origin 178 return func(i int) int { 179 logger.Trace("proxy Caller2 called, args", i) 180 originFunc, _ := origin1.(*func(i int) int) 181 return (*originFunc)(i) 182 } 183 }, 184 }, 185 { 186 funcName: "Caller3", 187 funcDef: Caller3, 188 eval: func(t *testing.T) { 189 if r := Caller3(Arg{ 190 field1: "field1", 191 field2: nil, 192 }); r != 8 { 193 t.Fatalf("want result: %d, real: %d", 8, r) 194 } 195 }, 196 trampoline: func() interface{} { 197 var result = func(arg Arg) int { 198 fmt.Println("trampoline") 199 return 40 200 } 201 return &result 202 }, 203 proxy: func(origin interface{}) interface{} { 204 var origin1 = origin 205 return func(arg Arg) int { 206 fmt.Println("Caller3") 207 logger.Trace("proxy Caller3 called, args", arg) 208 originFunc, _ := origin1.(*func(arg Arg) int) 209 fmt.Println("Caller3-1") 210 result := (*originFunc)(arg) 211 fmt.Println("Caller3-2") 212 return result 213 } 214 }, 215 }, 216 { 217 funcName: "Caller4", 218 funcDef: Caller4, 219 eval: func(t *testing.T) { 220 if r := Caller4(&Arg{ 221 field1: "field1", 222 field2: make(map[string]int), 223 }); r != 0 { 224 t.Fatalf("want result: %d, real: %d", 0, r) 225 } 226 }, 227 trampoline: func() interface{} { 228 var result = func(arg *Arg) int { 229 fmt.Println("trampoline") 230 return 50 231 } 232 return &result 233 }, 234 proxy: func(origin interface{}) interface{} { 235 var origin1 = origin 236 return func(arg *Arg) int { 237 logger.Trace("proxy Caller4 called, args", arg) 238 originFunc, _ := origin1.(*func(arg *Arg) int) 239 return (*originFunc)(arg) 240 } 241 }, 242 }, 243 { 244 funcName: "Caller5", 245 funcDef: Caller5, 246 eval: func(t *testing.T) { 247 if r := Caller5(); r != 0 { 248 t.Fatalf("want result: %d, real: %d", 0, r) 249 } 250 }, 251 trampoline: func() interface{} { 252 var result = func() int { 253 return 60 + rand.Int() 254 } 255 return &result 256 }, 257 proxy: func(origin interface{}) interface{} { 258 var origin1 = origin 259 return func() int { 260 logger.Trace("proxy Caller5 called, no args") 261 originFunc, _ := origin1.(*func() int) 262 return (*originFunc)() 263 } 264 }, 265 }, 266 { 267 funcName: "Caller6", 268 funcDef: Caller6, 269 eval: func(t *testing.T) { 270 if r := Caller6(3)(); r != 4 { 271 t.Fatalf("want result: %d, real: %d", 4, r) 272 } 273 }, 274 trampoline: func() interface{} { 275 var result = func(a int) func() int { 276 return func() int { 277 return a + 70 278 } 279 } 280 return &result 281 }, 282 proxy: func(origin interface{}) interface{} { 283 var origin1 = origin 284 return func(a int) func() int { 285 logger.Trace("proxy Caller6 called, args", a) 286 originFunc, _ := origin1.(*func(a int) func() int) 287 return (*originFunc)(a) 288 } 289 }, 290 }, 291 { 292 funcName: "Caller7", 293 funcDef: Caller7, 294 eval: func(t *testing.T) { 295 Caller7(2) 296 }, 297 trampoline: func() interface{} { 298 var result = func(i int) { 299 fmt.Println("trampoline") 300 } 301 return &result 302 }, 303 proxy: func(origin interface{}) interface{} { 304 var origin1 = origin 305 return func(i int) { 306 logger.Trace("proxy Caller7 called, args", i) 307 originFunc, _ := origin1.(*func(i int)) 308 (*originFunc)(i) 309 } 310 }, 311 }, 312 { // TODO 排查不同环境结果不一致的原因 313 funcName: "Caller8", 314 funcDef: Caller8, 315 eval: func(t *testing.T) { 316 if r := Caller8(-1); r != -1 { 317 t.Fatalf("want result: %d, real: %d", -1, r) 318 } 319 }, 320 trampoline: func() interface{} { 321 var result = func(i int) int { 322 fmt.Println("trampoline") 323 return 99 324 } 325 return &result 326 }, 327 proxy: func(origin interface{}) interface{} { 328 var origin1 = origin 329 return func(i int) int { 330 logger.Trace("proxy Caller8 called, args", i) 331 originFunc, _ := origin1.(*func(int) int) 332 return (*originFunc)(i) 333 } 334 }, 335 }, 336 } 337 338 // main 测试静态代理 339 func TestProxy_fixIns(t *testing.T) { 340 logger.LogLevel = logger.TraceLevel 341 logger.SetLog2Console(true) 342 for _, tc := range testCases1 { 343 344 trampoline := tc.trampoline() 345 346 // 静态代理函数 347 patch, err := FuncName("github.com/tencent/goom/internal/proxy."+ 348 tc.funcName, tc.proxy(trampoline), trampoline) 349 if tc.wantError && err != nil { 350 continue 351 } 352 353 if err != nil { 354 t.Fatalf("mock func %s err: %v", tc.funcName, err) 355 } 356 357 patch.Apply() 358 359 tc.eval(t) 360 patch.Unpatch() 361 } 362 fmt.Println("all test is ok") 363 }