github.com/liangmanlin/routine@v1.1.0/goid_test.go (about) 1 package routine 2 3 import ( 4 "github.com/stretchr/testify/assert" 5 "reflect" 6 "runtime" 7 "testing" 8 "unsafe" 9 ) 10 11 // curGoroutineID parse the current g's goid from caller stack. 12 //go:linkname curGoroutineID net/http.http2curGoroutineID 13 func curGoroutineID() int64 14 15 // setPanicOnFault controls the runtime's behavior when a program faults at an unexpected (non-nil) address. 16 //go:linkname setPanicOnFault runtime/debug.setPanicOnFault 17 func setPanicOnFault(new bool) (old bool) 18 19 // getProfLabel get current g's labels which will be inherited by new goroutine. 20 //go:linkname getProfLabel runtime/pprof.runtime_getProfLabel 21 func getProfLabel() unsafe.Pointer 22 23 // setProfLabel set current g's labels which will be inherited by new goroutine. 24 //go:linkname setProfLabel runtime/pprof.runtime_setProfLabel 25 func setProfLabel(labels unsafe.Pointer) 26 27 func TestGoidNative(t *testing.T) { 28 runTest(t, func() { 29 gp := getg() 30 runtime.GC() 31 assert.Equal(t, curGoroutineID(), gp.goid) 32 }) 33 } 34 35 func TestPaniconfault(t *testing.T) { 36 runTest(t, func() { 37 gp := getg() 38 runtime.GC() 39 //read-1 40 assert.False(t, setPanicOnFault(false)) 41 assert.False(t, gp.getPanicOnFault()) 42 //read-2 43 setPanicOnFault(true) 44 assert.True(t, gp.getPanicOnFault()) 45 //write-1 46 gp.setPanicOnFault(false) 47 assert.False(t, setPanicOnFault(false)) 48 //write-2 49 gp.setPanicOnFault(true) 50 assert.True(t, setPanicOnFault(true)) 51 //write-read-1 52 gp.setPanicOnFault(false) 53 assert.False(t, gp.getPanicOnFault()) 54 //write-read-2 55 gp.setPanicOnFault(true) 56 assert.True(t, gp.getPanicOnFault()) 57 //restore 58 gp.setPanicOnFault(false) 59 }) 60 } 61 62 func TestProfLabel(t *testing.T) { 63 runTest(t, func() { 64 ptr := unsafe.Pointer(&struct{}{}) 65 null := unsafe.Pointer(nil) 66 assert.NotEqual(t, ptr, null) 67 // 68 gp := getg() 69 runtime.GC() 70 //read-1 71 assert.Equal(t, null, getProfLabel()) 72 assert.Equal(t, null, gp.getLabels()) 73 //read-2 74 setProfLabel(ptr) 75 assert.Equal(t, ptr, gp.getLabels()) 76 //write-1 77 gp.setLabels(nil) 78 assert.Equal(t, null, getProfLabel()) 79 //write-2 80 gp.setLabels(ptr) 81 assert.Equal(t, ptr, getProfLabel()) 82 //write-read-1 83 gp.setLabels(nil) 84 assert.Equal(t, null, gp.getLabels()) 85 //write-read-2 86 gp.setLabels(ptr) 87 assert.Equal(t, ptr, gp.getLabels()) 88 //restore 89 gp.setLabels(null) 90 }) 91 } 92 93 func TestOffset(t *testing.T) { 94 runTest(t, func() { 95 assert.Panics(t, func() { 96 gt := reflect.TypeOf(0) 97 offset(gt, "hello") 98 }) 99 assert.PanicsWithValue(t, "No such field 'hello' of struct 'runtime.g'.", func() { 100 gt := getgt() 101 offset(gt, "hello") 102 }) 103 }) 104 } 105 106 //=== 107 108 // BenchmarkGohack-8 186637413 5.734 ns/op 0 B/op 0 allocs/op 109 func BenchmarkGohack(b *testing.B) { 110 _ = getg() 111 b.ReportAllocs() 112 b.ResetTimer() 113 for i := 0; i < b.N; i++ { 114 gp := getg() 115 _ = gp.goid 116 _ = gp.getLabels() 117 _ = gp.getPanicOnFault() 118 gp.setLabels(nil) 119 gp.setPanicOnFault(false) 120 } 121 }